﻿/*
*
* DomReady v1.0.0
*
* 2011-09-08
* Paul Porthouse 
*
* A class which allows us to schedule javascript and stuff
* to load after the DOM has completed loading which should
* make the page load quicker and appear more responsive.
* This is a merging of two seperate projects
*		- http://code.google.com/p/domready/
*		- http://stackoverflow.com/questions/5852767/possible-to-defer-loading-of-jquery
*
* Version History:
*
*		2011-09-08 Initial version
*
*/

// ensure the namespace exists
if (typeof (SouthTynesideCouncil) === 'undefined') { SouthTynesideCouncil = {}; }
if (typeof (SouthTynesideCouncil.ICT) === 'undefined') { SouthTynesideCouncil.ICT = {}; }
if (typeof (SouthTynesideCouncil.ICT.ApplicationDevelopment) === 'undefined') { SouthTynesideCouncil.ICT.ApplicationDevelopment = {}; }
if (typeof (SouthTynesideCouncil.ICT.ApplicationDevelopment.Utilities) === 'undefined') { SouthTynesideCouncil.ICT.ApplicationDevelopment.Utilities = {}; }

SouthTynesideCouncil.ICT.ApplicationDevelopment.Utilities.DomReady = function() {
    var DomReady = window.DomReady = {},
		stylesheets = [],
		timerHandle = null;

	// Everything that has to do with properly supporting our document ready event. Brought over from the most awesome jQuery. 

    var userAgent = navigator.userAgent.toLowerCase();

    // Figure out what browser is being used
    var browser = {
    	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
    	safari: /webkit/.test(userAgent),
    	opera: /opera/.test(userAgent),
    	msie: (/msie/.test(userAgent)) && (!/opera/.test( userAgent )),
    	mozilla: (/mozilla/.test(userAgent)) && (!/(compatible|webkit)/.test(userAgent))
    };    

	var readyBound = false;	
	var isReady = false;
	var readyList = [];

	// Handle when the DOM is ready
	function domReady() {
		// Make sure that the DOM is not already loaded
		if(!isReady) {
			// Remember that the DOM is ready
			isReady = true;
        
	        if(readyList) {
	            for(var fn = 0; fn < readyList.length; fn++) {
	                readyList[fn].call(window, []);
	            }
            
	            readyList = [];
	        }
		}
	};

	// From Simon Willison. A safe way to fire onload w/o screwing up everyone else.
	function addLoadEvent(func) {
	  var oldonload = window.onload;
	  if (typeof window.onload != 'function') {
	    window.onload = func;
	  } else {
	    window.onload = function() {
	      if (oldonload) {
	        oldonload();
	      }
	      func();
	    }
	  }
	};

	// does the heavy work of working through the browsers idiosyncracies (let's call them that) to hook onload.
	function bindReady() {
		if(readyBound) {
		    return;
	    }
	
		readyBound = true;

		// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
		if (document.addEventListener && !browser.opera) {
			// Use the handy event callback
			document.addEventListener("DOMContentLoaded", domReady, false);
		}

		// If IE is used and is not in a frame
		// Continually check to see if the document is ready
		if (browser.msie && window == top) (function(){
			if (isReady) return;
			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch(error) {
				setTimeout(arguments.callee, 0);
				return;
			}
			// and execute any waiting functions
		    domReady();
		})();

		if(browser.opera) {
			document.addEventListener( "DOMContentLoaded", function () {
				if (isReady) return;
				for (var i = 0; i < document.styleSheets.length; i++)
					if (document.styleSheets[i].disabled) {
						setTimeout( arguments.callee, 0 );
						return;
					}
				// and execute any waiting functions
	            domReady();
			}, false);
		}

		if(browser.safari) {
		    var numStyles;
			(function(){
				if (isReady) return;
				if (document.readyState != "loaded" && document.readyState != "complete") {
					setTimeout( arguments.callee, 0 );
					return;
				}
				if (numStyles === undefined) {
	                var links = document.getElementsByTagName("link");
	                for (var i=0; i < links.length; i++) {
	                	if(links[i].getAttribute('rel') == 'stylesheet') {
	                	    numStyles++;
	                	}
	                }
	                var styles = document.getElementsByTagName("style");
	                numStyles += styles.length;
				}
				if (document.styleSheets.length != numStyles) {
					setTimeout( arguments.callee, 0 );
					return;
				}
			
				// and execute any waiting functions
				domReady();
			})();
		}

		// A fallback to window.onload, that will always work
	    addLoadEvent(domReady);
	};

	// This is the public function that people can use to hook up ready.
	this.ready = function(fn, args) {
		// Attach the listeners
		bindReady();
    
		// If the DOM is already ready
		if (isReady) {
			// Execute the function immediately
			fn.call(window, []);
	    } else {
			// Add the function to the wait list
	        readyList.push( function() { return fn.call(window, []); } );
	    }
	};
	
	function startTimer(interval) {
		return window.setInterval(checkForStylesheets);
	}
	
	function stopTimer(timerHandle) {
		window.clearInterval(timerHandle);
		timerHandle = null;
	}
	
	function checkForStylesheets() {
		var notLoaded = 0,
			docStyles = document.styleSheets,
			stylesheetCount = stylesheets.length;
		
		for (var ss in stylesheets) {
			if (stylesheets[ss].complete) {
				continue;
			}
			
			for (var docss in docStyles) {
				var file = docStyles[docss];
				var owner = file.ownerNode ? file.ownerNode : file.owningElement;			
				if (owner && owner.id === stylesheets[ss].id) { // && undefined !== file.cssRules && null !== file.cssRules && file.cssRules.length > 0) {
					stylesheets[ss].complete = true;
					
					// because it was successfully loaded, execute the callback
					if ('function' === typeof(stylesheets[ss].success)) {
						stylesheets[ss].success.call();
					}
					break;
				}
			}
			
			if (!stylesheets[ss].complete) {
				notLoaded++;
				stylesheets[ss].checks--;

				if (stylesheets[ss].checks <= 0) {
					// the stylesheet hasn't been loaded in time, so call it a failure
					stylesheets[ss].complete = true;
				}
			}
		}
		
		// if all of the stylesheets are accounted for and no new ones have been added, stop the timer
		if (notLoaded === 0 && stylesheets.length === stylesheetCount) {
			stopTimer(timerHandle);
		}
	}
	
	// add the function to get a script after the DOM has loaded
	this.getScript = function(url, success) {
		var script = document.createElement('script'),
			head = document.getElementsByTagName('head')[0],
			complete = false;
			
		script.setAttribute('type', 'text/javascript');
		script.src = url;

		script.onload = script.onreadystatechange = function() {
			if (!complete && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
				complete = true;
				if ('function' === typeof(success)) {
					success.call(this);
				}
				script.onload = script.onreadystatechange = null;
				head.removeChild(script);
			}
		};
		
		head.appendChild(script);		
	};
	
	// add the function to get a stylesheet after the DOM has loaded
	this.getCss = function(url, success) {
		var css = document.createElement('link'),
			head = document.getElementsByTagName('head')[0],
			complete = false,
			stylesheet = {},
			id = 'domready_' + stylesheets.length.toString();
			
		css.setAttribute('type', 'text/css');
		css.setAttribute('rel', 'stylesheet');
		css.id = id;
		css.href = url;
		
		stylesheet = {
			id : id,
			css : css,
			complete : false,
			success : success,
			checks : 1000
		};
		
		stylesheets.push(stylesheet);
		
		head.appendChild(stylesheet.css);
		
		if (timerHandle === null) {
			timerHandle = startTimer(100);
		}
	};
    
	bindReady();	
};


