//===========================================//
// Standard Library
//              Coded by Vichraje @ Sep.2007
//____________vicrry@yahoo.com.hk____________
//===========================================//

//========================================================================
//.. Miscellaneous functions -:
//------------------------------------------------------------------------
	
	if(!Array.prototype.push)
		Array.prototype.push = function(obj) {
			return this[this.length] = obj;
		};
	if(!Array.prototype.unshift)
		Array.prototype.unshift = function(obj){
			for(var i=this.length-1;i>=0;i--)
				this[i+1]=this[i];
			
			return this[0] = obj;
		};
	if(!Array.prototype.shift)
		Array.prototype.shift = function() {
			return this.remove(this[0]);
		};
	if(!Array.prototype.pop)
		Array.prototype.pop = function() {
			return this.remove(this[this.length-1]);
		};
	if(!Array.prototype.indexOf)
		Array.prototype.indexOf = function(obj, idx) {
			for(var i=idx||0;i<this.length;i++) 
				if(this[i]===obj)return i;
			
			return -1;
		};
	
	Array.prototype.remove = function(obj, idx) {
		if(!this.length) return;
		
		for(var i = this.indexOf(obj, idx);i<this.length;i++)
			this[i]=this[i+1];
		
		this.length--;
		
		return obj;
	};
	Array.prototype.totop = function(obj, idx) {
		this[this.length-1] = this.remove(obj, idx);
	};
	Array.prototype.tobottom = function(obj, idx) {
		this.unshift(this.remove(obj, idx));
	};
	
	function $get(id) {
		return document.getElementById(id);
	}
	function $$(name) {
		return document.getElementsByTagName(name);
	}
	
//========================================================================
	
/**********************************************
 * Table():
 *
 * Creates a DOM table.
 **********************************************/	
	
	function Table(rows, columns, attributes, styles)
	{
		//-------------------------------------------------
		//.. Initialize the table -:
		//-------------------------------------------------
			if(!attributes['cellPadding'])
				attributes['cellPadding'] = 0;
			if(!attributes['cellSpacing'])
				attributes['cellSpacing'] = 0;
			
			var _tbl = Element('table', attributes, styles);
		//=================================================
		//Weird IE recognization. setAttribute() should set
		//the attributes spelling just like it in HTML tags,
		//but IE could only recognize "cellSpacing" and
		//"cellPadding" with the capital S and P, instead of
		//cellspacing and cellpadding.
		//Microsoft developers have been sick on separating
		//JavaScript and HTML syntaxis.
		//-------------------------------------------------
		//.. Create the body -:
			for(var r=0;r<rows;r++) {
				_tbl.insertRow(r);
				for(var c=0;c<columns;c++)
					_tbl.rows[r].insertCell(c);
			}
		//=================================================
		//.. Cell reference function -:
		//-------------------------------------------------
			_tbl.cellAt = function(row, cell) { 
				return this.rows[row].cells[cell];
			}
		//=================================================
		
		return _tbl;
	}
	
/**********************************************
 * Element():
 *
 * Create a DOM element with attributes.
 **********************************************/
	
	function Element(name, atts, styles)
	{
		var _el = document.createElement(name);
		
		for(var i in atts)
			if(typeof atts[i]=='function')
				_el[i] = atts[i];
			else
				_el.setAttribute(i, _el[i] = atts[i]);
		
		for(var i in styles) _el.style[i] = styles[i];
		
		return _el;
	}
	
/**********************************************
 * Text():
 *
 * Create a DOM text element.
 **********************************************/
	
	function Text(text)
	{
		return document.createTextNode(text);
	}
	
/**********************************************
 * parseQuery():
 *
 * parse the query into a collection, key referenced.
 **********************************************/
	
	function parseQuery()
	{
		if(!location.search) return {};
		
		var queryStr = location.search.substr(1).split('&'),
			queryArr = {};
		for(var i = 0; i < queryStr.length; i++)
		{
			queryStr[i] = queryStr[i].split('=');
			queryArr[queryStr[i][0]] = queryStr[i][1] || '';
		}
		
		return queryArr;
	}
	
/**********************************************
 * parseCookie():
 *
 * parse the cookies into a collection, key referenced.
 **********************************************/
	
	function parseCookie()
	{
		var cookieArr = {};
		
		if(document.cookie.length)
		{
		    var cookieStr = document.cookie.split(/;\s*/);
    		
		    for(var i = 0; i < cookieStr.length; i++)
		    {
			    cookieStr[i] = cookieStr[i].split('=');
			    cookieArr[cookieStr[i][0]] = cookieStr[i][1] || '';
		    }
		}
		
		cookieArr.__setValue = function(key, val, exp) {
			cookieArr[key] = val;
			document.cookie = 
				key + '=' + val + '; expires=' + 
				new Date(new Date().getTime()+(exp || 1800000)).toUTCString()
				+ '; path=/';
		};
		
		return cookieArr;
	}
	
/**********************************************
 * truncateHandlers():
 *
 * Truncate all handlers in the node tree.
 **********************************************/
	
	function truncateHandlers(node)
	{
		//====================================================
		// In IE, even the garbage collector itself is a junk,
		// it didn't collect event handlers of trashed nodes.
		//====================================================
		for(var evtName in node)
			if(/on.*/i.exec(evtName) && typeof node.evtName == 'function')
				node.evtName = null;
		
		for(var i=0;i<node.childNodes.length;i++)
			truncateHandlers(node.childNodes[i]);
	}
	
/**********************************************
 * truncateChildren():
 *
 * Truncate all child nodes in the node tree.
 **********************************************/
	
	function truncateChildren(node)
	{
		for(var i=node.childNodes.length;i>0;i--)
			node.removeChild( node.childNodes[0] );
	}

/**********************************************
 * toggle():
 *
 * Toggle visibility of element(s).
 **********************************************/
	
	function toggle(element) {
		if( element.length ) {
			for(var i=0; i<element.length; i++)
				toggle( element[i] );
			return;
		}
		
		if( typeof element == 'string' )
			element = $(elements[i]);
		
		with( element.style ) display = 
			( System.GetStyle(element, 'display') == 'block'? 'none' : 'block' );
	}
	
/**********************************************
 * hide():
 *
 * Hide element(s).
 **********************************************/
	
	function hide(element) {
		if( element.length ) {
			for(var i=0; i<element.length; i++)
				hide( element[i] );
			return;
		}
		
		if( typeof element == 'string' )
			element = $(elements[i]);
		
		with( element.style ) display = 'none';
	}
	
/**********************************************
 * show():
 *
 * Show element(s).
 **********************************************/
	
	function show(element) {
		if( element.length ) {
			for(var i=0; i<element.length; i++)
				show( element[i] );
			return;
		}
		
		if( typeof element == 'string' )
			element = $(elements[i]);
		
		with( element.style ) display = 'block';
	}

//========================================================================
//.. Pre-define constants -:
//------------------------------------------------------------------------
	
	/* Query String & Cookies */
	var $_GET		= parseQuery();
	var $_COOKIE	= parseCookie();
	
//========================================================================
//.. Main System Object -:
//------------------------------------------------------------------------
	
var System = {
	
	//===========================================
	//.. Public members -:
	//-------------------------------------------
		
		GetBounds : function(node)
		{
			with( this )
			{
				var _t = node.offsetTop, 
					_l = node.offsetLeft, // parseInt( GetStyles(node, {'left' : 0})['left'] ) || 0
					_w = GetStyles(node, {'paddingLeft' : 0, 'paddingRight' : 0, 'borderLeftWidth' : 0, 'borderRightWidth' : 0}), 
					_h = GetStyles(node, {'paddingTop' : 0, 'paddingBottom' : 0, 'borderTopWidth' : 0, 'borderBottomWidth' : 0});
				
				_w = node.offsetWidth  - 
					(parseInt(_w['paddingLeft']) || 0) - 
					(parseInt(_w['paddingRight']) || 0) - 
					(parseInt(_w['borderLeftWidth']) || 0) - 
					(parseInt(_w['borderRightWidth']) || 0);
				
				_h = node.offsetHeight - 
					(parseInt(_h['paddingTop']) || 0) - 
					(parseInt(_h['paddingBottom']) || 0) - 
					(parseInt(_h['borderTopWidth']) || 0) - 
					(parseInt(_h['borderBottomWidth']) || 0);
				
				while( node.offsetParent )
					with(node = node.offsetParent)
					{ _t += offsetTop; _l += offsetLeft; }
				
				return { t: _t, l: _l, w: _w, h: _h };
			}
		}, 
		
		GetStyle : function(node, style)
		{
			var win = document.defaultView || window;
			
			return ( win.getComputedStyle && win.getComputedStyle(node, null).getPropertyValue
				(style.replace(/[A-Z]/g, function(match) { return '-' + match.toLowerCase() })) ) || 
				( node.currentStyle || node.style )[style];
		}, 
		
		GetStyles : function(node, styles)
		{
			for(var style in styles)
				styles[style] = this.GetStyle(node, style);
			
			return styles;
		}, 
		
		HasClassName : function(node, className)
		{
		    if(typeof node.className != 'string') return;
		    
		    var tmp = node.className.split(' ');
		    
		    return tmp.indexOf(className) >= 0;
		},
		
		AddClassName : function(node, className)
		{
		    if(typeof node.className != 'string') return;
		    
		    var tmp = node.className.split(' ');
		    
		    if(tmp.indexOf(className) < 0)
		        tmp.push(className);
		    
		    node.className = tmp.join(' ');
		},
		
		RemoveClassName : function(node, className)
		{
		    if(typeof node.className != 'string') return;
		    
		    var tmp = node.className.split(' ');
		    
		    tmp.remove(className);
		    
		    node.className = tmp.join(' ');
		},
		
		AddEventHandler : function(eventType, func, runOnce)
		{
			with(this) {
				eventType = eventType.toLowerCase();
				
				if(typeof evtHandlers[eventType] != 'object')
					evtHandlers[eventType] = [];
				
				if(runOnce) {
					var ofunc = func;
					
					func = function(e) {
						ofunc(e); 
						
						System.RemoveEventHandler(eventType, func);
						
						ofunc = undefined;
					};
					
				}
				
				evtHandlers[eventType].push(func);
			}
		}, 
		
		RemoveEventHandler : function(eventType, func)
		{
			this.evtHandlers[String(eventType).toLowerCase()].remove(func);
		}, 
		
	//===========================================
	//.. internal functions -:
	//-------------------------------------------
	/* You don't need to read the following lines in most cases. */
		
		evtHandlers : {}, 
		
		initStack : [],
		
		initialize : function()
		{
			if(arguments[0] && typeof arguments[0]._initialize == 'function')
				return this.initStack.push( arguments[0] );
			
			for(var i=0; i<this.initStack.length; i++)
				this.initStack[i]._initialize();
			
			document.onkeydown = 
			document.onmousedown = 
				System._dDispatchEvent;
			
			// document.oncontextmenu =  function() { return ( window.event || arguments[0] ).returnValue = false; };
		},
		
		_dDispatchEvent : function() {
			var e = 
				window.event || arguments[0];
			
			var type = 
				e.type.toLowerCase();
			
			if(e.srcElement)
				e.target = e.srcElement;
			
			//====================================
			//.. Some Codings to dispatch -:
			// e.g. e.target ... blah
			//------------------------------------
				with(System)
					if( evtHandlers[type] )
						for(var i=0;i<evtHandlers[type].length;i++)
							try { evtHandlers[type][i](e); } catch(e) {}
			//====================================
		}, 
		
		_dReleaseEvent  : function() {
			document.onmousemove = document.onmouseup = undefined;
		}
		
	//===========================================
};
window.onload = function() { System.initialize(); };