/*
File: flexi-background.js

Author:
   Michael Bester <http://kimili.com>

About: Version
   2.0

Description:
   Javascript to set up full-screen flexible backgrounds in all widely used browsers.

License:
   Copyright 2010, Michael Bester.
   Released under the MIT license <http://opensource.org/licenses/mit-license.php>
*/

(function(){
   
   /**
      CONFIGURATION:
      Define the size of our background image
   */
   var bgImageSize = {
      width : 300,
      height   : 200
   };
   
   /* END CONFIGURATION */
   
   /**
      Detect support for CSS background-size. No need for any more javascript if background-size is supported.
      Property detection adapted from the most excellent Modernizr <http://modernizr.com>
   */
   if ((function(){
      var el      = document.createElement('div'),
         bs       = 'backgroundSize',
         ubs      = bs.charAt(0).toUpperCase() + bs.substr(1),
         props = [bs, 'Webkit' + ubs, 'Moz' + ubs, 'O' + ubs];
         
      for ( var i in props ) {
         if ( el.style[props[i]] !== undefined ) {
            return true;
         }
      }
      return false;
   }())) {
      return;
   };
   
   /**
      We also want to leave IE6 and below out in the cold with this
   */
   if ( false /*@cc_on || @_jscript_version < 5.7 @*/ ) {
      return;
   }
   
   /**
      If we've gotten here, we don't have background-size support,
      so we'll have to mimic it with Javascript.
      Let's set up some variables
   */
   var elBody,
      imageID     = 'expando',
      tallClass   = 'tall',
      wideClass   = 'wide',
      elBgImage, elWrapper, img, url, imgAR,
   
      /**
         Since we're not relying on a library, we'll need some utility functions
         First, basic cross browser event adders
      */
      addEvent = function(el, evnt, func) {
         if (el.addEventListener) {
            el.addEventListener(evnt, func, false);
         } else if (el.attachEvent) {
            return el.attachEvent("on" + evnt, func);
         } else {
            el['on' + evnt] = func;
         }
      },
   
      domLoaded = function(callback) {
         /* Internet Explorer */
         /*@cc_on
         @if (@_win32 || @_win64)
         document.write('<script id="ieScriptLoad" defer src="//:"><\/script>');
         document.getElementById('ieScriptLoad').onreadystatechange = function() {
            if (this.readyState == 'complete') {
               callback();
            }
         };
         @end @*/
         /* Mozilla, Chrome, Opera */
         if (document.addEventListener) {
            document.addEventListener('DOMContentLoaded', callback, false);
         }
         /* Safari, iCab, Konqueror */
         if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
            var DOMLoadTimer = setInterval(function () {
               if (/loaded|complete/i.test(document.readyState)) {
                  callback();
                  clearInterval(DOMLoadTimer);
               }
            }, 10);
         }
      },
   
      /**
         Next, a way to properly get the computed style of an element
         Courtesy of Robert Nyman - http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/
      */
      getStyle = function(el, css){
         var strValue = "";
         if (document.defaultView && document.defaultView.getComputedStyle){
            strValue = document.defaultView.getComputedStyle(el, "").getPropertyValue(css);
         }
         else if (el.currentStyle){
            css = css.replace(/\-(\w)/g, function (strMatch, p1){
               return p1.toUpperCase();
            });
            strValue = el.currentStyle[css];
         }
         return strValue;
      },
   
      /**
         Finally, some element class manipulation functions
      */
      classRegex = function(cls) {
         return new RegExp('(\\s|^)'+cls+'(\\s|$)');
      },
   
      hasClass = function(el, cls) {
         return el.className.match(classRegex(cls));
      },
   
      addClass = function(el, cls) {
         if ( ! hasClass(el, cls)) {
            el.className += ' ' + cls;
         }
      },
   
      removeClass = function(el, cls) {
         if (hasClass(el, cls)) {
            el.className = el.className.replace(classRegex(cls), '');
         }
      },
   
      /*
         Now we can move on with the core functionality of Flexibackground
      */
      initialize = function() {
      
         // No need for any of this if the screen isn't bigger than the background image
         if (screen.availWidth <= bgImageSize.width && screen.availHeight <= bgImageSize.height) {
            return;
         }
      
         // Grab elements we'll reference throughout
         elBody      = document.getElementsByTagName('body')[0];
      
         // Parse out the URL of the background image and drop out if we don't have one
         url = getStyle(elBody, 'backgroundImage').replace(/^url\(("|')?|("|')?\);?$/g, '') || false;
         if (!url || url === "none" || url === "") {
            return;
         }
      
         // Get the aspect ratio of the image
         imgAR = bgImageSize.width / bgImageSize.height;

         // Create a new image element
         elBgImage      = document.createElement('img');
         elBgImage.src  = url;
         elBgImage.id   = imageID;
      
         // Create a wrapper and append the image to it.
         // The wrapper ensures we don't get scrollbars.
         elWrapper = document.createElement('div');
         elWrapper.style.overflow   = 'hidden';
         elWrapper.style.width   = '100%';
         elWrapper.style.height  = '100%';
         elWrapper.style.zIndex  = '-1';
      
         elWrapper.appendChild(elBgImage);
         elBody.appendChild(elWrapper);
      
         // Fix the wrapper into position
         elWrapper.style.position   = 'fixed';
         elWrapper.style.top     = 0;
         elWrapper.style.left    = 0;
      
         // Set up a resize listener to add/remove classes from the body 
         addEvent(window, 'resize', resizeAction);

         // Set it up by triggering a resize
         resizeAction();
      
      },
   
      /**
         Set up the action that happens on resize
      */
      resizeAction = function() {
         var win = {
            height   : window.innerHeight || document.documentElement.clientHeight,
            width : window.innerWidth || document.documentElement.clientWidth
         },

         // The current aspect ratio of the window
         winAR = win.width / win.height;

         // Determine if we need to show the image and whether it needs to stretch tall or wide
         if (win.width < bgImageSize.width && win.height < bgImageSize.height) {
            removeClass(elBody, wideClass);
            removeClass(elBody, tallClass);
         } else if (winAR < imgAR) {
            removeClass(elBody, wideClass);
            addClass(elBody, tallClass);
            // Center the image
            elBgImage.style.left = Math.min(((win.width - bgImageSize.width) / 2), 0);
         } else if (winAR > imgAR) {
            addClass(elBody, wideClass);
            removeClass(elBody, tallClass);
            elBgImage.style.left = 0;
         }
      };
   
   // When the document is ready, run this thing.
   domLoaded(initialize);
   
})();

