/*
 *
 * ContentLoaded.js
 *
 * Author: Diego Perini (diego.perini at gmail.com)
 * Summary: Cross-browser wrapper for DOMContentLoaded
 * Updated: 17/05/2008
 * License: MIT
 * Version: 1.1
 *
 * URL:
 * http://javascript.nwbox.com/ContentLoaded/
 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
 *
 * Notes:
 * based on code by Dean Edwards and John Resig
 * http://dean.edwards.name/weblog/2006/06/again/
 *
 */

// @w	window reference
// @f	function reference
function ContentLoaded(w, f) {

	var	d = w.document,
		D = 'DOMContentLoaded',
		// user agent, version
		u = w.navigator.userAgent.toLowerCase(),
		v = parseFloat(u.match(/.+(?:rv|it|ml|ra|ie)[\/: ]([\d.]+)/)[1]),
		fired = false;

	function init(e) {		
		if (!fired) {				
			// don't set document.loaded so prototype's dom:load works
			// instead, use fired
			fired = true;
			// pass a fake event if needed
			f((e.type && e.type == D) ? e : {
				type: D,
				target: d,
				eventPhase: 0,
				currentTarget: d,
				timeStamp: +new Date,
				eventType: e.type || e
			});
		}		
	}

	// safari < 525.13
	if (/webkit\//.test(u) && v < 525.13) {

		(function () {
			if (/complete|loaded/.test(d.readyState)) {
				init('khtml-poll');
			} else {
				setTimeout(arguments.callee, 10);
			}
		})();

	// internet explorer all versions
	} else if (/msie/.test(u) && !w.opera) {

		d.attachEvent('onreadystatechange',
			function (e) {
				if (d.readyState == 'complete') {
					d.detachEvent('on'+e.type, arguments.callee);
					init(e);
				}
			}
		);
		if (w == top) {
			(function () {
				try {
					d.documentElement.doScroll('left');
				} catch (e) {
					setTimeout(arguments.callee, 10);
					return;
				}
				init('msie-poll');
			})();
		}

	// browsers having native DOMContentLoaded
	} else if (d.addEventListener &&
		(/opera\//.test(u) && v > 9) ||
		(/gecko\//.test(u) && v >= 1.8) ||
		(/khtml\//.test(u) && v >= 4.0) ||
		(/webkit\//.test(u) && v >= 525.13)) {

		d.addEventListener(D,
			function (e) {
				d.removeEventListener(D, arguments.callee, false);
				init(e);
			}, false
		);

	// fallback to last resort for older browsers
	} else {

		// from Simon Willison
		var oldonload = w.onload;
		w.onload = function (e) {
			init(e || w.event);
			if (typeof oldonload == 'function') {
				oldonload(e || w.event);
			}
		};

	}
}
/*
 * loader object for prioritised onload javascript execution
 * call like:
 * 	Loader.addOnload(myFunc1[, 0]); // for no specific priority
 *  Loader.addOnload(myFunc2, 1); // for highest priority (libs)
 *  Loader.addOnload(myFunc3, 5); // for some lower priority x 
 *  Loader.addOnDOMload(myFunc4, xPriority);
 */
Loader = (function(){	
	var lcallbacks = [[]];
	var dcallbacks = [[]];
	var loaded = false;
	var domLoaded = false;
	var loadedEvent = false;
	var domLoadedEvent = false;
	function addCb(cb, prio, list) {
		if(!prio) {
			list[0].push(cb);
		} else {
			if(!list[prio]) {
				list[prio] = [];
			}
			list[prio].push(cb);
		}
	}
	// map callbacks call
	function load(e, cbs) {
		
		//: set correct loaded variables
		if (e.type == 'load') {
			loaded = true;
			//: cache the event for later calls, when event has already been fired
			loadedEvent = e;
		} else {
			domLoaded = true;
			domLoadedEvent = e;
		}
		
		for(var i=1, cc=cbs.length; c=cbs[i], i<cc; i++) {
			if(!c) {
				continue;
			}
			for(var j=0, l=c.length; j<l; j++) {				
				if(typeof c[j] == "function") {
					c[j](e);
				}
			}
		}
		var c=cbs[0];
		for(var j=0, l=c.length; j<l; j++) {			
			if(typeof c[j] == "function") {
				c[j](e);
			}
		}
	}
	
	function loadHandler(g) {
		return function (e) {return load(e, g)}
	}
	var loadH = loadHandler(lcallbacks)
		,domLoadH = loadHandler(dcallbacks);
	
	// listen to load event
	if(window.attachEvent) {
		window.attachEvent("onload", loadH);
	} else if(window.addEventListener) {
		window.addEventListener("load", loadH, false);		
	} else {
		var temp = window.onload;
		window.onload = function(){
			temp();
			loadH();			
		};
	}
	
	ContentLoaded(window, domLoadH);
	
	return {
		addOnload: function addOnload(/*function*/ callback, priority) {
			if (!loaded) {
				addCb(callback, priority, lcallbacks);
			} else {
				callback(loadedEvent);
			}
		}
		,onLoadCBCount: function(priority) { return lcallbacks[priority].length; }
		,addOnDOMload: function addOnDOMload(callback, priority){
			if (!domLoaded) { 
				addCb(callback, priority, dcallbacks);
			} else {
				callback(domLoadedEvent);
			}
		}
	};
})();

