///////////////////////////////
// TomTom namespace
///////////////////////////////
var TT = {};

/////////////////////////////////////////
// TomTom Browser Object
////////////////////////////////////////
TT.Browser = {};
TT.Browser.UAEngine =
{ 
	trident : !!window.ActiveXObject, 		 
	presto  : !!window.opera,
	webkit  : navigator.userAgent.indexOf('AppleWebKit/') > -1,	
	gecko   : navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
};

//////////////////////////////////////////////////////////////////////////
// TomTom DomLoad Object
// Based on excellent work of : Dean Edwards, John Resig, Diego Perini
//////////////////////////////////////////////////////////////////////////
TT.DOMLoad = {};
// TT.DOMLoad.TT = TT;
// TT.DOMLoad.Browser = TT.Browser;

TT.DOMLoad.isFired = false;
TT.DOMLoad.isObserving = false;
TT.DOMLoad.observers = [];

///////////////////////////////////////////////////////////////////////////////////////////
// Method to be called on event initiation
///////////////////////////////////////////////////////////////////////////////////////////
TT.DOMLoad.fire = function ()
{
	///////////////////////////////////////////////////////////////////////////////////////////
	// only fire if we are observing and we have not been fired already
	///////////////////////////////////////////////////////////////////////////////////////////
	if ( TT.DOMLoad.isObserving == true && TT.DOMLoad.isFired == false )
	{
		TT.DOMLoad.isFired = true;
		TT.DOMLoad.isObserving = false;
	
		///////////////////////////////////////////////////////////////////////////////////////////
		// call every handler individually in the order they were added
		///////////////////////////////////////////////////////////////////////////////////////////
		for ( var index = 0, length = TT.DOMLoad.observers.length; index < length; index++ )
		{
			TT.DOMLoad.observers[index].callback.apply ( TT.DOMLoad.observers.scope, [ document, TT.DOMLoad.observers.data ] );
		}
	}
};

///////////////////////////////////////////////////////////////////////////////////////////
// Add methods to be called on dom.load
///////////////////////////////////////////////////////////////////////////////////////////
TT.DOMLoad.observe = function ( callback, data, scope )
{	
	///////////////////////////////////////////////////////////////////////////////////////////
	// only add callbacks if the event has not been fired yet
	///////////////////////////////////////////////////////////////////////////////////////////
	if ( TT.DOMLoad.isFired == false )
	{
		///////////////////////////////////////////////////////////////////////////////////////////
		// push the callback, it's data and the execution scope to the stack
		///////////////////////////////////////////////////////////////////////////////////////////
		TT.DOMLoad.observers.push 
		({
			callback : callback,
			data : data,
			scope : scope	
		});
		
		///////////////////////////////////////////////////////////////////////////////////////////
		// init the global dom.onload function if we didn't do that already
		///////////////////////////////////////////////////////////////////////////////////////////
		if (!TT.DOMLoad.isObserving) TT.DOMLoad.startObserving ();
	}
};

///////////////////////////////////////////////////////////////////////////////////////////
// Init the global dom.load function ( native || timed implementation )
///////////////////////////////////////////////////////////////////////////////////////////
TT.DOMLoad.startObserving = function ()
{
	///////////////////////////////////////////////////////////////////////////////////////////
	// only start observing if the event hasn't fired yet and we are not already observing
	///////////////////////////////////////////////////////////////////////////////////////////
	if ( TT.DOMLoad.isFired == false && TT.DOMLoad.isObserving == false )
	{
		TT.DOMLoad.isObserving = true;
		
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Mozilla and Opera
		///////////////////////////////////////////////////////////////////////////////////////////
		if(TT.Browser.UAEngine.gecko || TT.Browser.UAEngine.presto)
		{
			///////////////////////////////////////////////////////////////////////////////////////////
			// use the native domcontentloaded event
			///////////////////////////////////////////////////////////////////////////////////////////
			document.addEventListener ( 'DOMContentLoaded', TT.DOMLoad.fire, false );
		}
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Internet Explorer
		///////////////////////////////////////////////////////////////////////////////////////////
		else if (TT.Browser.UAEngine.trident)
		{
			(function(){
				
				///////////////////////////////////////////////////////////////////////////////////////////
				// check for doScroll method to stop throwing exceptions ( e.g. the dom is loaded )
				///////////////////////////////////////////////////////////////////////////////////////////
				try 
				{
					document.documentElement.doScroll("left");
					TT.DOMLoad.fire ();
				} 
				catch( e ) 
				{
					///////////////////////////////////////////////////////////////////////////////////////////
					// keep trying until we succeed
					///////////////////////////////////////////////////////////////////////////////////////////
					setTimeout( arguments.callee, 0 );
				}
				
			})();
		}
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Safari and khtml
		///////////////////////////////////////////////////////////////////////////////////////////
		else if(TT.Browser.UAEngine.webkit)
		{
			(function(){
				
				///////////////////////////////////////////////////////////////////////////////////////////
				// check for the document to be loaded or complete ( e.g. the dom is loaded )
				///////////////////////////////////////////////////////////////////////////////////////////
				if ( document.readyState != "loaded" && document.readyState != "complete" ) 
				{	
					///////////////////////////////////////////////////////////////////////////////////////////
					// keep trying until we succeed
					///////////////////////////////////////////////////////////////////////////////////////////
					setTimeout( arguments.callee, 0 );	
				}
				else
				{
					TT.DOMLoad.fire ();
				}
				
			})();
		}
		
		///////////////////////////////////////////////////////////////////////////////////////////
		// If all the above failed we force the callbacks to be invoked on window.onload
		///////////////////////////////////////////////////////////////////////////////////////////
		addWindowOnload ( TT.DOMLoad.fire );
	}
};

///////////////////////////////////////////////////////////////////////////////////////////
// TomTom Global methods to assign event handlers for DomDocument and Window load events
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////
// Map old dom.onload method to our new method to be backwards compatible
///////////////////////////////////////////////////////////////////////////////////////////
var addDomDocumentOnload = TT.DOMLoad.observe;

///////////////////////////////////////////////////////////////////////////////////////////
// Window onload implementation
///////////////////////////////////////////////////////////////////////////////////////////
var addWindowOnload = function ( callback ) 
{
	var prev = window.onload;
	window.onload = function()
	{ 
		if ( prev ) prev(); 
		callback (); 
	}
};
