// JavaScript Document

//#	queryStringToArray( sURL, returnType, onMatch, debug )
//# mergeArray( keyArray, valueArray, doPadding )
//# joinArray( array1, array2 )
//#	arrayToList( array, delimiter, allowNull )
//# getObject( sID )
//# getCollection( sID, sTagName )
//# getCollectionByObject( oObj, sTagName )
//#	trim( sString )
//#	leftTrim( sString )
//#	rightTrim( sString )
//#	encode( sValue )
//#	decode( sValue )
//# htmlentities( sValue );
//# removeHTMLFormatting( sValue );
//#	getCharArray( value )
//#	substrCount( value , thing )
//#	inArray( value, array )
//# display( array, keys, name ) 
//#	throwException( file_name, line_num, ex, msg )

//# 08-18-07 : getSelectedValues( oSelect ); returns a comma-delimited list of selected values
//# 08-18-07 : replaceOptions( value_array, text_array, id, keep_first ); replaces options of id with arrays
//# 08-18-07 : getValues( oSelect ); returns selected OPTIONS as a comma-delimited list
//# 08-18-07 : getTableCellWidths( oTable ); returns the cell widths of a table object. 

//# 08-26-07 : createChildObject( c_id, p_id, tag_name ); creates and appends a new object (c_id) to a parent (p_id)

//# 09-01-07 : getScrollOffsetTop(); returns the measure from the top of the client window to the topmost of the document
//# 09-01-07 : getScrollOffsetLeft(); returns the measure from the left of the client window to the leftmost of the document

//# 10-16-07 : ucwords(); destroys planets.

/*== queryStringToArray( sURL, returnType, onMatch, debug ) =========================================
==	converts a query string into several outputs : used to clean up query strings
==	sURL		The query string
==	returnType			how the string is to be returned
==	onMatch				what to do with matching variables
*/
function queryStringToArray( sURL, returnType, onMatch, debug ){
	
	if(debug){
		var debug_msg = "queryStringToArray( sURL = "+sURL+", returnType = "+returnType+", onMatch = "+onMatch+" )\n\n";
	}
	
	if( sURL.indexOf('?') == -1 ){
		return;
	}
	else{
		sURL.substring( location.href.indexOf('?') )
	}

	sURL = sURL.replace( /\?/g, '' );
	sURL = sURL.replace( /\#/g, '' );
	
	var querySplit = sURL.split('&');
	var keyArray = new Array();
	var assocArray = new Array();
	var numArray = new Array();
	var key = "key";
	var value = "value";
	var assoc_string = "";
	var num_string = "";
		var test_string = "";
		var key_list = "";
		var key_string = "";
	var returnQuery = "";
	var a = 0;
	var key_match = false;
	
	for( i = 0; i < querySplit.length; i++ ){
		
		key = querySplit[i].substring( 0, querySplit[i].indexOf('=') );
		
		if( querySplit[i].indexOf('=') == querySplit[i].length ){
			value = "";
		}else{
			value = querySplit[i].substring( querySplit[i].indexOf('=')+1, querySplit[i].length );
		}
		
		if(keyArray.length == 0){ //automatically assign the firstkey value to the list
			
			assocArray[key] = value;
			numArray[a] = value;
			keyArray[a] = key;
			
			key_string += key+"\n";
			
			key_list += key+",";
			a++;
			
		}else{
			
			for( j = 0; j < keyArray.length; j++ ){ //test if the current key exists in the array

				if( key == keyArray[j] ){
					key_match = true;
					if( onMatch == "replace" ){ // if onMatch is set to replace like keys, overwrite array item value
						assocArray[key] = value;
						numArray[j] = value;
					}
					continue;	
				}
		
			}
			
			if( !key_match ){ // if key is new, add to everything

				assocArray[key] = value;
				numArray[a] = value;
				keyArray[a] = key;
			
				key_string += key+"\n";
				
				key_list += key+",";
				a++;

			}
			
			key_match = false;
		}
		
	}
	
	for( i = 0; i < keyArray.length; i++ ){ // build accurate item checklists and returnQuery
		assoc_string += "assocArray["+keyArray[i]+"] = " +assocArray[keyArray[i]]+ "\n";
		num_string += "numArray["+i+"] = " +numArray[i]+ "\n";
		returnQuery += "&"+keyArray[i]+"="+assocArray[keyArray[i]];
	}
	
	key_list = key_list.substring( 0, key_list.length-1 );

	key_string = key_string.substring( 0, key_string.length-1 );
	returnQuery = returnQuery.substring( 1, returnQuery.length );
	test_string = ( returnType == "array_assoc" )? assoc_string : num_string ;
	var length = a;
	
	switch( returnType.toLowerCase() ){
		case "array_assoc": return_value = assocArray;
			break;
		case "array_num": return_value = numArray;
			break;
		case "array_key": return_value = keyArray;
			break;
		case "key_list" : return_value = key_list;
			break;
		case "query": return_value = returnQuery;
			break;
		default: var default_type = "\narray_num\narray_assoc\nkey_list\nquery\n"
			alert( "queryStringToArray() only takes the following returnType values,\n"+default_type  );
	}
	
	if(debug){
		debug_msg += "Return Type: "+returnType+"\n\n";
		debug_msg += "Array Length: "+length+"\n\n";
		debug_msg += "Array Values:\n"+test_string+"\n\n";
		debug_msg += "Key List: "+key_list+"\n\n";
		debug_msg += "Key Array Values:\n"+key_string+"\n\n";
		debug_msg += "Return Query: "+returnQuery+"\n\n";
		alert(debug_msg);
	}

	return return_value;
	
}

/*== mergeArray( keyArray, valueArray, debug ) ====================================================================
==	takes two arrays and makes an associative array using keyArray as KEYS and  valueArray as VALUES
==	
==	
*/
function mergeArray( keyArray, valueArray, doPadding ){

	var returnArray = new Array();

	if(doPadding){
		if( valueArray.length > keyArray.length ){
			var diff = valueArray.length - keyArray.length;
			for( i = 0; i < diff; i++ ){
				keyArray[i] = "";
			}
			
		}
	}
	
	for( i = 0; i < keyArray.length; i++ ){
		returnArray[keyArray[i]] = valueArray[i];
	}
	
	return returnArray;
	
}

//### arrayToList( array, delimiter, allowNull )
//##
//#
function arrayToList( array, delimiter, allowNull ){

	var return_value = '';
	
	for( i = 0; i < array.length; i++ ){
	
		if( allowNull ){
			return_value += array[i]+delimiter;
		}else{
			return_value += ( array[i] != '' )? array[i]+delimiter : array[i] ;
		}
	}
	
	return return_value.substring( 0, return_value.length-1 );
}


//### joinArray( array, delimiter, allowNull )
//##
//#
function joinArray( array1, array2 ){

	var new_array = array1;
	
	var a = 0;
	for( i = array1.length; i < (array1.length+array2.length); i++ ){
	
		
		new_array[i] = array2[a];
		
		a++;

	}
	
	//alert(new_array[5].id)
	
	return new_array;
	
}



function getObject( sID ){
	
	try{
			
		return document.getElementById( sID );
			
	}catch(e){ throwException( 'process_scripts.js : getObject()', e.lineNumber, e, e.message ); }
		
}

function getCollectionById( sID, sTagName ){
	
	try{
			
		return document.getElementById( sID  ).getElementsByTagName( sTagName );
			
	}catch(e){ throwException( 'process_scripts.js : getCollection()', e.lineNumber, e, e.message ); }
		
}

function getCollectionByObject( oObj, sTagName ){
	
	try{
			
		return oObj.getElementsByTagName( sTagName );
			
	}catch(e){ throwException( 'process_scripts.js : getCollectionByObject()', e.lineNumber, e, e.message ); }
		
}



function trim( sString ){
	
	try{
			
		if( sString.length > 0 ){

			sString = leftTrim( sString );
			sString = rightTrim( sString );
		
		}
		
		return sString;
			
	}catch(e){ return sString; }
	
}

//trim spaces: Front
function leftTrim( sString ){
	
	try{
			
		if( sString.length > 0 ){
			
			var i = 0;
			var charHere = sString.charAt(0);

			while ( charHere == ' ' || charHere == "\t" ){ //first, strip any SPACES
				i++;	
				charHere = sString.charAt(i);
			}
			
			sString = sString.substring( i, sString.length );
		}
		
		return sString;
			
	}catch(e){ return sString; }
	
}

//trim spaces: BACK
function rightTrim( sString ){
	
	try{
		
		if( sString.length > 0 ){
			
			var i = 0;
			var charHere = sString.charAt( sString.length + i -1);

			while ( charHere == ' ' || charHere == "\t" ){ //first, strip any SPACES
				i--;	
				charHere = sString.charAt( sString.length + i -1 );
			}
			
			sString = sString.substring( 0, sString.length + i );
			
		}
	
		return sString;
		
	}catch(e){ return sString; }
	
}


//### encode( sValue )
//##
//#	  encodes special characters to a given their HTML or URL code
function encodeQuotes( sValue ){
	try{
		
		sValue = sValue.replace( /'/g, '&#039;' );
		sValue = sValue.replace( /"/g, '&quot;' );
		return sValue;
		
	}catch(e){ return sValue; }
}
function decodeQuotes( sValue ){
	try{
		
		sValue = sValue.replace( /&#039;/g, "'" );
		sValue = sValue.replace( /&quot;/g, '"' );
		return sValue;
		
	}catch(e){ return sValue; }
}

function encode( sValue ){
	
	try{
		
		sValue = sValue.replace( /'/g, '&#039;' );
		sValue = sValue.replace( /"/g, '&quot;' );
		sValue = sValue.replace( /:/g, "&#58;" );
		sValue = sValue.replace( /,/g, "&#44;" );
		sValue = sValue.replace( /'/g, "&#039;" );
		sValue = sValue.replace( /"/g, '&quot;' );
		sValue = sValue.replace( /</g, "&lt;" );
		sValue = sValue.replace( />/g, '&gt;' );
		sValue = sValue.replace( /<script/g, '...' );
		sValue = sValue.replace( /<style/g, '...' );

		return sValue;
		
	}catch(e){ return sValue; }
	
}

function urlEncode( sValue ){

	try{
		
		sValue = sValue.replace( / /g, "%20" );
		sValue = sValue.replace( /&/g, "%26" );
		//sValue = sValue.replace( /'/g, '%27' );
		sValue = sValue.replace( /"/g, '%22' );
		sValue = sValue.replace( /#/g, "%23" );
		sValue = sValue.replace( /\//g, "%2F" );
		
		return sValue;
		
	}catch(e){ return sValue; }
	
}

//### decode( sValue )
//##
//#	  decodes special characters from their HTML or URL code
function decode( sValue ){
	
	try{

		sValue = sValue.replace( /%20/g, " " );
		sValue = sValue.replace( /%26/g, "&" );
		sValue = sValue.replace( /%27/g, "'" );
		sValue = sValue.replace( /%22/g, '"' );
		sValue = sValue.replace( /%23/g, "#" );
		sValue = sValue.replace( /%2F/g, "/" );
		
		sValue = sValue.replace( /&#58;/g, ":" );
		sValue = sValue.replace( /&#44;/g, "," );
		sValue = sValue.replace( /&amp;/g, "&" );
		sValue = sValue.replace( /&#039;/g, "'" );
		sValue = sValue.replace( /&quot;/g, '"' );
		sValue = sValue.replace( /&lt;/g, "<" );
		sValue = sValue.replace( /&gt;/g, '>' );
		
		return sValue;
		
	}catch(e){ return sValue; }
	
}

function htmlentities(sValue){
	
	try{
		sValue = sValue.replace( /</g, "&lt;" );
		sValue = sValue.replace( />/g, "&gt;" );
			
		return sValue;
		
	}catch(e){ return sValue; }
	
}

function removeHTMLFormatting(sValue){
	
	try{
		sValue = sValue.replace( /<b>/g, "" );
		sValue = sValue.replace( /<i>/g, "" );
		sValue = sValue.replace( /<strong>/g, "" );
		sValue = sValue.replace( /<em>/g, "" );
		sValue = sValue.replace( /<\/b>/g, "" );
		sValue = sValue.replace( /<\/i>/g, "" );
		sValue = sValue.replace( /<\/strong>/g, "" );
		sValue = sValue.replace( /<\/em>/g, "" );
			
		return sValue;
		
	}catch(e){ return sValue; }
	
}


function addSlashes( sValue ){
	
	try{
		
		return sValue.replace( /'/g, "\\'" );
		
	}catch(e){ return sValue; }
	
}
function removeSlashes( sValue ){
	
	try{
		
		return sValue.replace( /\\'/g, "'" );
			
	}catch(e){ return sValue; }
	
}


//### getCharArray( value )
//##
//#
function getCharArray( value ){
	
	try{
		
		var char_array = new Array();
		for( i = 0; i < value.length; i++ ){
			char_array[i] = value.charAt(i);
		}
		return char_array;
		
	}catch(e){ return value; }
	
}
	

function substrCount( value , thing ){
	
	try{
		
		var count = 0;
		
		for( i = 0; i < value.length; i++ ){
		
			if( value.charAt(i) == thing ){ count++; }
			
		}
		
		return count;
		
	}catch(e){ return 0; }
			
}


function inArray( value, array ){
	
	try{
		
		for( zzzzz = 0; zzzzz < array.length; zzzzz++ ){
			
			if( array[zzzzz] == value ){
				return true;
			}
			
		}
		
		return false;

	}catch(e){ throwException( 'process_scripts.js : inArray()', e.lineNumber, e, e.message ); }

}


function display( array, keys, name ){
	
	try{
		
		var str = "";
		var key = 0;
		
		var count = 0;
		switch( name ){
			
			case "facilities_array":
				count = 5;
			break;
			
		}
		
		if( typeof array == "string" ){
			str += array;
		}else if( typeof array == "object" ){
			
			str += "Array(){\n";
			
			for( i = 0; i < array.length; i++ ){
				
				if( typeof array[i] == "string" ){
					
					key = ( keys == "" )? i : ( typeof keys[0] == "string" )? keys[i] : i ;
					
					str += "\t"+name+"["+key+"] = "+htmlentities(array[key])+"\r\n";
					
				}else if( typeof array[i] == "object" ){
					
					str += "\tArray(){\n";
					
					this_count = ( count > 0 )? count : array[i].length ;
					for( j = 0; j < this_count; j++ ){
						
						key = ( keys == "" )? j : ( typeof keys[0][0] == "string" )? keys[0][j] : j ;
						
						str += "\t\t"+name+"["+i+"]["+key+"] = "+htmlentities(array[i][key])+"\r\n";
						
					}
					
					str += "\t}\n";
					
				}
				
			}
			
			str += "}\n";
		}
		
		return "<pre>"+str+"</pre>";
			
	}catch(e){ throwException( 'main_library.js : display()', e.lineNumber, e, e.message ); }
		
}

function displaySelect( oSelect ){
	
	var str = "Array(){\n";
	for( zzz = 0; zzz < oSelect.length; zzz++ ){
		str += "\t"+oSelect.id+"[value] = "+oSelect[zzz].value+"\r\n";
		str += "\t"+oSelect.id+"[text] = "+oSelect[zzz].text+"\r\n";
	}
	str += "}\n";
	
	return "<pre>"+str+"</pre>";
}



//### throwException( file_name, line_num, ex, msg )
//##
//#	  function that gives file LINE NUMBER when a JS Exception is thrown
function throwException( file_name, line_num, ex, msg ){
	
	var msg = "Error in FILE: " +file_name+ " LINE: " +line_num+ "\n\nTYPE: " +ex+ "\n\n" +msg+ "\n\n" +ex.stack;
	
	if( getObject('error_div') ){
		getObject('error_div').innerHTML = "<pre class=\"error\">"+msg+"</pre>";
	}else{
		alert( msg );
	}

}


function getSelectedValues( oSelect ){
	
	var list = "";
	for( zzz = 0; zzz < oSelect.length; zzz++ ){
		if( oSelect[zzz].selected ){
			list += ( list != "" )? "," : "" ;
			list += oSelect[zzz].value;
		}
	}
	
	return list;
	
}

function getValues( oSelect, del ){
	
	var list = "";
	for( zzz = 0; zzz < oSelect.length; zzz++ ){
		list += ( list != "" )? del : "" ;
		list += oSelect[zzz].value;
	}
	
	return trim( list );

}

function replaceOptions( value_array, text_array, id, keep_first, selected_index ){
	
	try{
		
		var oSelect = getObject(id);
		
		oSelect.length = (keep_first)? 1 : 0 ;
		var first = oSelect.length;
		
		for( i = first; i < (value_array.length + first); i++ ){
			
			var no = new Option();
				no.value = value_array[i - first];
				no.text = text_array[i - first];
		
			//alert( typeof no.value );
			
			oSelect[i] = no;
			oSelect[i].selected = ( i == selected_index )? true : false ;
		
		}
		
		//###firefox bug? When messing with select options, an extra "undefined" option is tacked on.
		if( oSelect[oSelect.length-1].value == "undefined" ){
			oSelect.length = oSelect.length - 1;
		}
		
		
	}catch(e){ throwException( 'main_librasry.js : replaceOptions()', e.lineNumber, e, e.message ); }

}

function replaceOptions2D( value_array, id, keep_first, selected_index ){
	
	try{
		
		var oSelect = getObject(id);
		
		oSelect.length = (keep_first)? 1 : 0 ;
		var first = oSelect.length;
		
		if( value_array.length > 0 )
		{
			for( i = first; i < (value_array.length + first); i++ ){
				
				var no = new Option();
					no.value = value_array[i - first][0];
					no.text = value_array[i - first][1];
			
				//alert( typeof no.value );
				
				oSelect[i] = no;
				oSelect[i].selected = ( i == selected_index )? true : false ;
			
			}
			
			//###firefox bug? When messing with select options, an extra "undefined" option is tacked on.
			if( oSelect[oSelect.length-1].value == "undefined" ){
				oSelect.length = oSelect.length - 1;
			}
		}
		
	}catch(e){ throwException( 'main_librasry.js : replaceOptions()', e.lineNumber, e, e.message ); }

}


function getTableCellWidths( oTable ){
	
	var tr = getCollectionByObject( oTable, "TR" )[0];
	var td = getCollectionByObject( tr, "TD" );
	
	var w = "";
	var total = 0 ;
	for( bb = 0; bb < td.length; bb++ ){
		
		w += ( w == "" )? "" : "," ;
		w += td[bb].clientWidth;
		
		total += td[bb].clientWidth;
		
	}
	
	return w+":"+total;
	
}


function createChildObject( tag_name, c_id, p_id, isParent ){

	var child = document.createElement( tag_name.toUpperCase() );
	
	child.setAttribute( 'id', c_id );
	
	if( isParent ){
		if( typeof p_id == "string" ){
			getObject(p_id).appendChild( child );
		}else{
			p_id.appendChild( child );
		}
	}else{
		if( typeof p_id == "string" ){
			( getObject(p_id).parentNode ).insertBefore( child, getObject(p_id) );
		}else{
			( p_id.parentNode ).insertBefore( child, p_id );
		}
	}
	
	return child;
	
	//# REFERENCE:
	//# document.createElement('div'); creates an element by tag name
	//# parent.appendChild( child ); places child at the end of parent
	//# parent.insertBefore( child, parent.childNode[x] ); inserts child into a particular location within parent
	//# parent.removeChild( child ); removes a child element from parent
	//# obj.setAttribute('id', 'value'); used to set all attributes, including read-only types like ID
	//# obj.attributes[x]; array of attributes of obj
	//# document.createTextNode(); used to create text inside an object; equiv of obj.innerHTML(?)
	
	//# parent.replaceChild(); overwrites a particular node?
	//# obj.cloneNode(true); makes a copy of obj?
	
}

var body_tag = new Object();
var error_div = new Object();
function createWorkingObjects(){

	body_tag = document.getElementsByTagName("BODY")[0];
	body_tag.setAttribute('id', 'body_tag');
	if( typeof w_height != "undefined" ){ w_height = body_tag.clientHeight; }
	if( typeof w_width != "undefined" ){ w_width = body_tag.clientWidth; }
	
	error_div = createChildObject( "div", "error_div", "body_tag", true );
	
}

addEvent( window, "load", createWorkingObjects );
addEvent( window, "unload", function(){ removeEvent( window, "load", createWorkingObjects ); } );


function error( value ){
	
//	var ele = ( typeof(error_div.tagName == 'undefined' ) )
//		? createChildObject( "div", "error_div", "body_tag", true )
//		: getObject('error_div')
//	;
	
	getObject('error_div').innerHTML = "<pre>"+value+"</pre>";	
	
}


function getScrollOffsetTop(){
	try{
		
		var pos = 0;
		
		if (window.innerHeight){ pos = window.pageYOffset; }
		else if (document.documentElement && document.documentElement.scrollTop){ pos = document.documentElement.scrollTop; }
		else if (document.body){ pos = document.body.scrollTop ; }
		
		return pos;
		
	}catch(e){ throwException( 'main_librasry.js : getScrollOffsetHeight()', e.lineNumber, e, e.message ); }
}

function getScrollOffsetLeft(){
	try{
		
		var pos = 0;
		
		if (window.innerWidth){ pos = window.pageXOffset; }
		else if (document.documentElement && document.documentElement.scrollLeft){ pos = document.documentElement.scrollLeft; }
		else if (document.body){ pos = document.body.scrollLeft ; }
		
		return pos;
		
	}catch(e){ throwException( 'main_librasry.js : getScrollOffsetHeight()', e.lineNumber, e, e.message ); }
}


function getObjScrollOffsetTop( oObj ){
	try{
		
		var pos = oObj.scrollHeight;
		
//		if (window.innerHeight){ pos = oObj.YOffset; }
//		else if (document.documentElement && document.documentElement.scrollTop){ pos = oObj.documentElement.scrollTop; }
//		else if (document.body){ pos = oObj.scrollTop ; }
		
		return pos;
		
	}catch(e){ throwException( 'main_librasry.js : getScrollOffsetHeight()', e.lineNumber, e, e.message ); }
}

function getObjScrollOffsetLeft( oObj ){
	try{
		
		var pos = 0;
		
		if (window.innerWidth){ pos = window.pageXOffset; }
		else if (document.documentElement && document.documentElement.scrollLeft){ pos = document.documentElement.scrollLeft; }
		else if (document.body){ pos = document.body.scrollLeft ; }
		
		return pos;
		
	}catch(e){ throwException( 'main_librasry.js : getScrollOffsetHeight()', e.lineNumber, e, e.message ); }
}



function ucwords( sValue ){
	try{
		
		sValue = trim(sValue);
		
		if( sValue.indexOf(" ") != -1 ){
			var word_array = sValue.split(" ");
			
			for( var i = 0; i < word_array.length; i++ ){
				
				if( word_array[i] != "" ){
					word_array[i] = ucChar( word_array[i] );
				}
				
			}
			
			sValue = word_array.join(" ");
			
		}else{
			
			sValue = ucChar( sValue );	
			
		}
		
		return sValue;
		
	}catch(e){ return sValue; }
}

function ucChar( sValue ){
	try{
		
		var uc_char = sValue.charAt(0).toUpperCase();
		
		sValue = uc_char + sValue.substring( 1 );
		
		return sValue;
		
	}catch(e){ return sValue; }
}


function addslashes( value ){
	try{
		
		value = value.replace( /'/g, "\\'" );
		return value;
		
	}catch(e){ return value; }
}

function stripslashes( value ){
	try{
		
		value = value.replace( /\\/g, "" );
		return value;
		
	}catch(e){ return value; }
}


function isArray( oObj ){
	try{
		return ( oObj.length > -1 );
	}
	catch(e)
	{
		return false;
	}
}










function DelayFunctionCall( oFunction, iDelay )
{//# a quaint little function to delay calls via setTimeout(); 
 //# oFunction is passed as funtion(){ FuncitonToBeDelayed(parameters) }
	setTimeout( oFunction, iDelay );
}







/* ### BETA FUNCTIONS AND METHODS ... ### */

function ListProperties(obj) { //dumpProps()
	var obj_props = "";
	// Go through all the properties of the passed-in object
	for (var i in obj) {
		
		// if a parent (2nd parameter) was passed in, then use that to
		// build the message. Message includes i (the object's property name)
		// then the object's property value on a new line
		if (arguments[1]) { var msg = arguments[1] + "." + i + " : " + obj[i]; } else { var msg = i + " : " + obj[i]; }
		obj_props += msg + "\n";
		
		// Display the message. If the user clicks "OK", then continue. If they
		// click "CANCEL" then quit this level of recursion
		//if (!confirm(msg)) { return; }
		
		// If this property (i) is an object, then recursively process the object
		if (typeof obj[i] == "object") {
			if (arguments[1]) { ListProperties(obj[i], parent + "." + i); } else { ListProperties(obj[i], i); }
		}
	}
	
	return obj_props;
	//return obj.getAttribute('al-filepath');
	
}




// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini

// http://dean.edwards.name/weblog/2005/10/add-event/
// element	= the OBJECT to attach the event to
// type		= the type of EVENT; i.e. load, click
// handler	= the FUNCTION to call
function addEvent(element, type, handler) {
	if (element.addEventListener) {
		element.addEventListener(type, handler, false);
	} else {
		// assign each event handler a unique ID
		if (!handler.$$guid) handler.$$guid = addEvent.guid++;
		// create a hash table of event types for the element
		if (!element.events) element.events = {};
		// create a hash table of event handlers for each element/event pair
		var handlers = element.events[type];
		if (!handlers) {
			handlers = element.events[type] = {};
			// store the existing event handler (if there is one)
			if (element["on" + type]) {
				handlers[0] = element["on" + type];
			}
		}
		// store the event handler in the hash table
		handlers[handler.$$guid] = handler;
		// assign a global event handler to do all the work
		element["on" + type] = handleEvent;
	}
};
// a counter used to create unique IDs
addEvent.guid = 1;

function removeEvent(element, type, handler) {
	if (element.removeEventListener) {
		element.removeEventListener(type, handler, false);
	} else {
		// delete the event handler from the hash table
		if (element.events && element.events[type]) {
			delete element.events[type][handler.$$guid];
		}
	}
};

function handleEvent(event) {
	var returnValue = true;
	// grab the event object (IE uses a global event object)
	event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
	// get a reference to the hash table of event handlers
	var handlers = this.events[event.type];
	// execute each event handler
	for (var i in handlers) {
		this.$$handleEvent = handlers[i];
		if (this.$$handleEvent(event) === false) {
			returnValue = false;
		}
	}
	return returnValue;
};

function fixEvent(event) {
	// add W3C standard event methods
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
};
fixEvent.preventDefault = function() {
	this.returnValue = false;
};
fixEvent.stopPropagation = function() {
	this.cancelBubble = true;
};

// This little snippet fixes the problem that the onload attribute on the body-element will overwrite
// previous attached events on the window object for the onload event
if (!window.addEventListener)
{
	document.onreadystatechange = function()
	{
		if (window.onload && window.onload != handleEvent)
		{
			addEvent(window, 'load', window.onload);
			window.onload = handleEvent;
		}
	}
}


