if ( typeof ( TT ) == 'undefined' ) 
{
	window.TT = {};
}

///////////////////////////////////////////
// unique id object counter
///////////////////////////////////////////	
TT.UID = 0;

TT.getId = function ( object )
{
	return object [ '#uid' ] ? object [ '#uid' ] : object [ '#uid' ] = ++ TT.UID;
};

if ( typeof ( TT.Browser ) == 'undefined' )
{
	TT.Browser = {};	
}

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

if ( typeof ( TT.DOM ) == 'undefined' )
{
	TT.DOM = {};	
}

if ( typeof ( TT.DOM.Load ) == 'undefined' )
{
	TT.DOM.Load = {};	
}

TT.DOM.Load.isFired = false;
TT.DOM.Load.isObserving = false;
TT.DOM.Load.observers = [];

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

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

///////////////////////////////////////////////////////////////////////////////////////////
// Init the global dom.load function ( native || timed implementation )
///////////////////////////////////////////////////////////////////////////////////////////
TT.DOM.Load.startObserving = function ()
{
	///////////////////////////////////////////////////////////////////////////////////////////
	// only start observing if the event hasn't fired yet and we are not already observing
	///////////////////////////////////////////////////////////////////////////////////////////
	if ( TT.DOM.Load.isFired == false && TT.DOM.Load.isObserving == false )
	{
		TT.DOM.Load.isObserving = true;
		
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Mozilla and Opera
		///////////////////////////////////////////////////////////////////////////////////////////
		if(TT.Browser.Engine.gecko || TT.Browser.Engine.presto)
		{
			///////////////////////////////////////////////////////////////////////////////////////////
			// use the native domcontentloaded event
			///////////////////////////////////////////////////////////////////////////////////////////
			document.addEventListener ( 'DOMContentLoaded', TT.DOM.Load.fire, false );
		}
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Internet Explorer
		///////////////////////////////////////////////////////////////////////////////////////////
		else if (TT.Browser.Engine.trident)
		{
			(function(){
				
				///////////////////////////////////////////////////////////////////////////////////////////
				// check for doScroll method to stop throwing exceptions ( e.g. the dom is loaded )
				///////////////////////////////////////////////////////////////////////////////////////////
				try 
				{
					document.documentElement.doScroll("left");
					TT.DOM.Load.fire ();
				} 
				catch( e ) 
				{
					///////////////////////////////////////////////////////////////////////////////////////////
					// keep trying until we succeed
					///////////////////////////////////////////////////////////////////////////////////////////
					setTimeout( arguments.callee, 0 );
				}
				
			})();
		}
		///////////////////////////////////////////////////////////////////////////////////////////
		// For Safari and khtml
		///////////////////////////////////////////////////////////////////////////////////////////
		else if(TT.Browser.Engine.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.DOM.Load.fire ();
				}
				
			})();
		}
	}
};

if ( typeof ( TT.DOM.Unload ) == 'undefined' )
{
	TT.DOM.Unload = {};	
}

TT.DOM.Unload.observers = [];
TT.DOM.Unload.isFired = false;
TT.DOM.Unload.isObserving = false;

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

///////////////////////////////////////////////////////////////////////////////////////////
// Init the global dom.unload function ( native || timed implementation )
///////////////////////////////////////////////////////////////////////////////////////////
TT.DOM.Unload.startObserving = function ()
{
	///////////////////////////////////////////////////////////////////////////////////////////
	// only start observing if the event hasn't fired yet and we are not already observing
	///////////////////////////////////////////////////////////////////////////////////////////
	if ( TT.DOM.Unload.isFired == false && TT.DOM.Unload.isObserving == false )
	{
		TT.DOM.Unload.isObserving = true;
		
		TT.Event.observe ( window , 'unload' , TT.DOM.Unload.fire );
	}
};

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

///////////////////////////////////////////
// check if node is an element
///////////////////////////////////////////
TT.DOM.isElement = function ( object )
{
	return  object && object.nodeType && object.nodeType == 1;
};

///////////////////////////////////////////
// check if node is an document
///////////////////////////////////////////
TT.DOM.isDocument = function ( object )
{
	return object && object.nodeType && object.nodeType == 9;
};

///////////////////////////////////////////
// translate attribute property names
///////////////////////////////////////////	
TT.DOM.toAttr = function ( key )
{
	switch ( key )
	{
		case 'class' : return TT.Browser.Engine.trident ? 'className' : key;
		default : return key;
	}
};

///////////////////////////////////////////
// translate css property names
///////////////////////////////////////////
TT.DOM.toCss = function ( key )
{
	switch( key )
	{
		case 'float' : return TT.DOM.Browser.ie ? 'styleFloat' : 'cssFloat';
		default: return key;
	}
};

///////////////////////////////////////////
// get the style property value
///////////////////////////////////////////
TT.DOM.getStyle = function ( element , key )
{
	key = TT.DOM.toCss ( key );
	
	var value = null;
	
	if ( element.currentStyle )
	{
		 value = element.currentStyle [ key ];
	}
	else if ( window.getComputedStyle )
	{
		value = document.defaultView.getComputedStyle( element , null ).getPropertyValue( key );
	}
	
	return value;	
};

///////////////////////////////////////////
// set the style property value
///////////////////////////////////////////
TT.DOM.setStyle = function ( element , key , value )
{
	element.style [ TT.DOM.toCss ( key ) ] = value;
};

///////////////////////////////////////////
// check if class exists
///////////////////////////////////////////
TT.DOM.hasClass = function ( element , value )
{
	return ( ' ' + element.className + ' ' ).indexOf ( ' ' + value + ' ' ) > -1;
};

///////////////////////////////////////////
// get class
///////////////////////////////////////////
TT.DOM.getClass = function ( element  )
{
	return element.className;
};

///////////////////////////////////////////
// set class
///////////////////////////////////////////
TT.DOM.setClass = function ( element , value )
{
	element.className = value;
};

///////////////////////////////////////////
// add class
///////////////////////////////////////////
TT.DOM.addClass = function ( element, value )
{
	if( ! TT.DOM.hasClass ( element , value ) ) element.className += ' ' + value; 
};

///////////////////////////////////////////
// remove class
///////////////////////////////////////////
TT.DOM.removeClass = function ( element , value )
{
	element.className = element.className.replace ( new RegExp( '(^|\\s)' + value + '(\\s|$)' ) , ' ' );
};

///////////////////////////////////////////
// toggle class
///////////////////////////////////////////
TT.DOM.toggleClass = function ( element , value )
{
	TT.DOM [  TT.DOM.hasClass ( element , value ) ? 'removeClass' : 'addClass' ] ( element , value );
};

///////////////////////////////////////////
// get attribute value
///////////////////////////////////////////
TT.DOM.getAttr = function ( element , key )
{
	return element.getAttribute ( TT.DOM.toAttr ( key ) , 2 );
};

///////////////////////////////////////////
// has attribute value
///////////////////////////////////////////
TT.DOM.hasAttr = function ( element , key )
{
	return !! element [ element.hasAttribute ? 'hasAttribute' : 'getAttribute' ] ( TT.DOM.toAttr ( key ) );
};

///////////////////////////////////////////
// next element
///////////////////////////////////////////
TT.DOM.next = function ( node )
{
	for ( var current = node.nextSibling; current; current = current.nextSibling )
	{
		if ( TT.DOM.isElement ( current ) ) return current;
	}
	
	return null;
};

///////////////////////////////////////////
// previous element
///////////////////////////////////////////
TT.DOM.prev = function ( node )
{
	for( var current = node.previousSibling; current; current = current.previousSibling )
	{
		if ( TT.DOM.isElement ( current ) ) return current;
	}
	
	return null;
};

///////////////////////////////////////////
// first element
///////////////////////////////////////////
TT.DOM.first = function ( node )
{
	for( var current = node.firstChild; current; current = current.nextSibling )
	{
		if ( TT.DOM.isElement ( current ) ) return current;
	}
	
	return null;
};


///////////////////////////////////////////
// first element
///////////////////////////////////////////
TT.DOM.parent = function ( node )
{
	return node.parentNode || null;
};
///////////////////////////////////////////
// last element
///////////////////////////////////////////
TT.DOM.last = function ( node )
{
	for( var current = node.lastChild; current; current = current.previousSibling )
	{
		if ( TT.DOM.isElement ( current ) ) return current;
	}
	
	return null;
};

if ( typeof ( TT.Event ) == 'undefined' )
{
	TT.Event = {};	
}

///////////////////////////////////////////
// observe event
///////////////////////////////////////////
TT.Event.observe = function ( object , type , handler , scope , data )
{
	var observer = TT.Event.observer ( handler , object , scope , data );
	
	if ( object.addEventListener )
	{
		object.addEventListener ( type, observer, false);
	}
	else if ( object.attachEvent )
	{
		object.attachEvent (  'on' + type , observer );
	}
	
	TT.DOM.Unload.observe ( object , type , observer );
	
	return observer;
};

///////////////////////////////////////////
// unobserve event
///////////////////////////////////////////
TT.Event.unobserve = function ( object , type , observer )
{
	if (object.removeListener)
	{
		object.removeListener ( type , observer , false );
	}
	else if (object.detachEvent)
	{
		object.detachEvent ( 'on' + type , observer );
	}
};

///////////////////////////////////////////
// get observer
///////////////////////////////////////////
TT.Event.observer = function ( handler , object , scope , data )
{
	return function ( event )
	{
		return handler.apply ( scope || window , [ object , TT.Event.w3c ( event || window.event ) , data ] );
	};
};

///////////////////////////////////////////
// wrap browser event object for consistency
///////////////////////////////////////////
TT.Event.w3c = function ( event )
{
	if ( this instanceof TT.Event.w3c === false )
	{
		return new TT.Event.w3c ( event );
	}
	else
	{
		this.stop = function ( )
		{
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();	
		};
		
		this.kill = function ( )
		{
			this.stop();
			this.cancel();
		};
		
		this.cancel = function ( event )
		{
			event.returnValue = false;
			if ( event.preventDefault ) event.preventDefault ( );	
		};
		
		this.get = function ( )
		{
			return event;
		};
	}
};

if ( typeof ( TT.Storage ) == 'undefined' )
{
	TT.Storage = {};	
}

TT.Storage.data = { };

TT.Storage.set = function ( object , key , value )
{
	var id = TT.getId ( object );
	
	if ( typeof ( TT.Storage.data [ id ] ) == 'undefined' )
	{
		TT.Storage.data [ id ] = { };
	}
	
	if ( typeof ( value ) == 'undefined' || typeof ( value ) == 'null' )
	{
		TT.Storage.data [ id ] = key;
	}
	else
	{
		TT.Storage.data [ id ] [ key ] = value;
	}
};

TT.Storage.get = function ( object , key )
{
	var id = TT.getId ( object );
	
	if ( typeof ( TT.Storage.data [ id ] ) == 'undefined' )
	{
		return null;
	}
	else if ( typeof ( key ) == 'undefined' || typeof ( key ) == 'null' )
	{
		return TT.Storage.data [ id ];
	}
	else
	{
		return TT.Storage.data [ id ] [ key ] || null;
	}	
};

TT.Storage.unset = function ( object , key )
{
	var id = TT.getId ( object );
	
	if ( typeof ( TT.Storage.data [ id ] ) != 'undefined' )
	{
		if ( typeof ( key ) == 'undefined' || typeof ( key ) == 'null' )
		{
			delete TT.Storage.data [ id ];
		}
		else
		{
			delete TT.Storage.data [ id ] [ key ];
		}
	}
};

if ( typeof ( TT.Select ) == 'undefined' )
{
	TT.Select = {};	
}



///////////////////////////////////////////
// get elements by attribute
///////////////////////////////////////////
TT.Select.byAttr = function ( key , value , tag , from )
{
	from = from || document;
	tag = tag || '*';
	
	var raw_elements = from.getElementsByTagName ( tag );
	var filtered_elements = [];
	
	for( var index = 0 , length = raw_elements.length; index < length; index++ )
	{
		if ( key == 'class' )
		{		
			if( TT.DOM.hasClass ( raw_elements [ index ] , value ) )
			{
				filtered_elements.push ( raw_elements [ index ] );
			}
		}
		else
		{
			if( raw_elements [ index ].getAttribute( TT.DOM.toAttr ( key ) , 2 ) == value )
			{
				filtered_elements.push ( raw_elements [ index ] );
			}
		}
	}

	return filtered_elements;	
};

if ( typeof ( TT.Ajax ) == 'undefined' )
{
	TT.Ajax = {};	
}

TT.Ajax.Request = function ( )
{
	if ( this instanceof TT.Ajax.Request  == false )
	{
		return new TT.Ajax.Request ( );
	}
	
	var activex = [ 'Msxml2.XMLHTTP.6.0' , 'Msxml2.XMLHTTP' ];
	
	var options = 
	{ 
		type : 'get',
		url : document.location.protocol + '//' + document.location.host,
		params : {},
		callbacks : {}
	};
	
	this.post = function ( url , params , callbacks )
	{
		options.type = 'post';
		request ( url , params , callbacks );
	};
	
	this.get = function ( url , params , callbacks )
	{
		options.type = 'get';
		request ( url , params , callbacks );
	};
	
	var query = 
	{
		'get' : function ( )
		{
			var query = '';
			
			for ( var key in options.params )
			{
				if ( query != '' ) query += '&';
				query += key + '=' + options.params [ key ];
			}
			
			return query == '' ? query : ( options.url.indexOf ( '?' ) > -1 ? '' : '?' ) + query; 
		},
		
		'post' : function ( )
		{
			var query ='';
			
			for ( var key in options.params )
			{
				if ( query != '' ) query += ';';
				query += key + '=' + options.params [ key ];
			}
			
			return query;
		}
	};
	
	var request = function ( url , params , callbacks )
	{
		options.params = params;
		options.url += url;
		
		if ( typeof ( callbacks ) == 'function' )
		{
			options.callbacks.onsuccess = callbacks;
		}
		else
		{
			options.callbacks = callbacks;
		}
		
		var http = factory ( );
		
		var onreadystatechange = function ( )
		{
			if ( http.readyState == 4 )
			{				
				if ( http.status == 200 ) 
				{
					if ( typeof ( options.callbacks [ 'onsuccess' ] ) == 'function' ) options.callbacks [ 'onsuccess' ] ( TT.Ajax.Response ( http ) );	
				}
				else
				{
					if ( typeof ( options.callbacks [ 'onfailure' ] ) == 'function' ) options.callbacks [ 'onfailure' ] ( TT.Ajax.Response ( http ) );	
				}				
			}
		};
		
		if ( options.type == 'post' )
		{
			http.open ( options.type , encodeURI ( options.url ) , true );
			http.setRequestHeader( 'Content-Type' , 'application/x-www-form-urlencoded' );
			http.onreadystatechange = onreadystatechange;
			http.send ( query [ 'post' ] ( )  );
		}
		else
		{
			http.open ( options.type , encodeURI ( options.url + query [ 'get' ] (  ) ) , true );
			http.onreadystatechange = onreadystatechange;
			http.send ( null );
		}
	};
	
	var factory = function ( )
	{
		if ( window.ActiveXObject )
		{
			for ( var index = 0 , length = activex.length; index < length; index ++ )
			{
				try
				{
					return new ActiveXObject ( activex [ index ] );
				}
				catch ( e )
				{
					
				}
			}
		}
		else if ( XMLHttpRequest  )
		{
			return new XMLHttpRequest  ( );
		}
	};
};

TT.Ajax.Response = function ( http )
{
	if ( this instanceof TT.Ajax.Response  == false )
	{
		return new TT.Ajax.Response ( http );
	}
	
	this.text = function ( )
	{
		return http.responseText;
	};
	
	this.xml = function ( )
	{
		return http.responseXML;
	};
};

Object.merge = function ( source , target )
{
	var object = { };
	
	for ( var key in source )
	{		
		object [ key ] = source [ key ];
	}
	
	for ( var key in target )
	{
		if ( typeof ( source [ key ] ) == 'object' && typeof ( target [ key ] ) == 'object' )
		{
			object [ key ] = Object.merge ( source [ key ] , target [ key ] );			
		}
		else
		{
			if ( typeof ( target [ key ] ) != 'undefined' || target [ key ] != null ) object [ key ] = target [ key ];
		}
	}
	
	return object;
};

Object.toArray = function ( object )
{
	var array = [];
	
	if ( object.constructor == Array )
	{
		return object;
	}
	else if ( object.length && object !== window && typeof ( object ) != 'function' && typeof ( object ) != 'string' )
	{
		for ( var index = 0 , length = object.length; index < length; index ++ )
		{
			array.push ( object [ index ] );
		}
	}
	else if ( typeof ( object ) == 'object' && object !== window && typeof ( object.nodeType ) == 'undefined' )
	{
		for ( var key in object )
		{
			array.push ( object [ key ] );
		}
	}
	else
	{
		return [ object ];
	}
	
	return array;
};

if ( ! Array.prototype.pop )
{
	Array.prototype.pop = function ( )
	{
		var item = this [ this.length - 1 ];
		delete this [ this.length - 1 ];
		return item;
	};
}

if( ! Array.prototype.push )
{	
	Array.prototype.push = function ( item )
	{
		this [ this.length ] = item;
	};
}