
function updateState(country_select_obj){

	var current_country = country_select_obj.options[country_select_obj.selectedIndex].value;
	

	if(current_country=='USA'||current_country=='CA'){
		// hide the manual state
		document.getElementById('manual_state').style.display = 'none';
		// show the state selector
		document.getElementById('select_state').style.display = 'block';
	} else {
		// show the manual state
		document.getElementById('manual_state').style.display = 'block';
		// hide the state selector
		document.getElementById('select_state').style.display = 'none';
	}
	
}



function processReqChange()
{
	
	//alert('changed status');
	s.active = false;
	
	// only if req shows "complete"
	if (s.req.readyState == 4) {
		// only if "OK"
		if (s.req.status == 200) {
			var myObject = eval( '(' + s.req.responseText + ')' );
			
			//alert('result:' + s.req.responseText);
			
			//active = 
			//processResults(myObject);
		}
	}
}

var s = false;
var active = false;
var debug= false;

function validate(form, required){

	//var required = document.getElementById(this.id + '_requiredfields');
	//form = this;

	this.label_feedback = false;
	if(debug) alert('validating: ' + form + ' with ' + required.length + ' required elements');
	
	//return false;

	var status = true;
	
	for(i=0; i<required.length; i++){
		
		var item = required[i].split(":");
		
		if(debug) alert(item[0] + '-|-' + item[1]);
		
		switch(item[1]){
			case('-username'):
			
				s = new XMLHTTP("/api.php?");  
				s.call('username='+form[item[0]].value, processReqChange); 
				
				s.active = true;
				
				while(s.active){
						
					// do something
					
				}
				//alert('done');
				//alert('validate username');
				
			
			
			break;
			case("credit_card"):
			
				//alert('card');
				
				//alert(form[item[3]].type);
				
				//alert('type field: ' + item[2] + ' value=' + form[item[2]]);
				//alert('number field: ' + item[3] + ' value=' + form[item[3]]);
				//alert('month field: ' + item[4] + ' value=' + form[item[4]]);
				//alert('year field: ' + item[5] + ' value=' + form[item[5]]);
			
				var num = form[item[3]].value;
			
				switch(item[2].type){
					default:
					case("text"):		var type = form[item[2]].value;
					break;
					case("select-one"):	var type = form[item[2]].options[form[item[2]].selectedIndex].value;
					break;
				}
				
				switch(item[4].type){
					default:
					case("text"):		var mo = form[item[4]].value;
					break;
					case("select-one"):	var mo = form[item[4]].options[form[item[4]].selectedIndex].value;
					break;
				}
				
				switch(item[5].type){
					default:
					case("text"):		var ye = form[item[5]].value;
					break;
					case("select-one"):	var ye = form[item[5]].options[form[item[5]].selectedIndex].value;
					break;
				}
				
				type = type.toUpperCase();
				
				//alert(num + ' ' + type + ' ' + mo + '/' + ye);
				
				if(	!checkCard(type, num) ){
					status = false;
					form[item[2]].className = 'required';
					form[item[3]].className = 'required';
					if(document.getElementById(form[item[3]].name + '_msg')){
						var obj = document.getElementById(form[item[3]].name + '_msg');
						obj.innerHTML = 'Invalid';
					}
					if(this.label_feedback){
						if(document.getElementById(form[item[2]].name + '_label')){
							document.getElementById(form[item[2]].name + '_label').className = 'input-label-invalid';								
						}
						if(document.getElementById(form[item[3]].name + '_label')){
							document.getElementById(form[item[3]].name + '_label').className = 'input-label-invalid';								
						}
					}
					
				} else {
					
					form[item[2]].className = 'field';
					form[item[3]].className = 'field';
					if(document.getElementById(form[item[3]].name + '_msg')){
						var obj = document.getElementById(form[item[3]].name + '_msg');
						obj.innerHTML = '';
					}
					if(this.label_feedback){
						if(document.getElementById(form[item[2]].name + '_label')){
							document.getElementById(form[item[2]].name + '_label').className = 'input-label';								
						}
						if(document.getElementById(form[item[3]].name + '_label')){
							document.getElementById(form[item[3]].name + '_label').className = 'input-label';								
						}
					}
				}
				
				if(cardExpired(mo, ye)){
					
					form[item[4]].className = 'required';
					form[item[5]].className = 'required';
					status = false;
					if(document.getElementById(form[item[5]].name + '_msg')){
						var obj = document.getElementById(form[item[5]].name + '_msg');
						obj.innerHTML = 'Expired';
						
					}
					if(this.label_feedback){
						if(document.getElementById(form[item[4]].name + '_label')){
							document.getElementById(form[item[4]].name + '_label').className = 'input-label-invalid';								
						}
						if(document.getElementById(form[item[5]].name + '_label')){
							document.getElementById(form[item[5]].name + '_label').className = 'input-label-invalid';								
						}
					}
									
				} else {
					
					form[item[4]].className = 'field';
					form[item[5]].className = 'field';
					if(document.getElementById(form[item[5]].name + '_msg')){
						var obj = document.getElementById(form[item[5]].name + '_msg');
						obj.innerHTML = '';
						
					}
					if(this.label_feedback){
						
						if(document.getElementById(form[item[4]].name + '_label')){
							document.getElementById(form[item[4]].name + '_label').className = 'input-label';								
						}
						if(document.getElementById(form[item[5]].name + '_label')){
							document.getElementById(form[item[5]].name + '_label').className = 'input-label';								
						}
					}
				}
				
				if(document.getElementById('credit_card_error_msg')){
				
					if(status) document.getElementById('credit_card_error_msg').style.display = 'none';
					else document.getElementById('credit_card_error_msg').style.display = 'block';
				}
				   
				
				
				
				/*alert('credit card checking...
					  
					  cardnumber: ' + form[item[0]].value + '
					  cardtype: ' + form[item[1]].value + '
					  card_month: ' + form[item[2]].value + '
					  card_year: ' + form[item[3]].value);
				*/
			
			break;
			case('email'):		var res = validateEmail(form[item[0]].value);
			
								// FEEDBACK
								if(document.getElementById(form[item[0]].name + '_msg')){
										
									var obj = document.getElementById(form[item[0]].name + '_msg');
									// provide feedback
									switch(res){
										case(1):	//alert('no input');
													obj.innerHTML = '';
										break;
										case(-1):	//alert('too short');
													obj.innerHTML = 'No Input';
										break;
										case(-2):	//alert('too short');
													obj.innerHTML = 'Invalid Adress';
										break;
										default:
									}
								}

			
								if(res<=0){
									status = false;
									
									if(form[item[0]].value.length==0) form[item[0]].value = 'REQUIRED';
									form[item[0]].className = 'required';
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label-invalid';								
										}
									}
									form[item[0]].onfocus = function(){
										focused(this);
									}
								} else {
									form[item[0]].className = 'text-input';
								}
			break;
			case('zip'):		var res = validateZIP(form[item[0]].value);
								
								// FEEDBACK
								if(document.getElementById(form[item[0]].name + '_msg')){
										
									var obj = document.getElementById(form[item[0]].name + '_msg');
									// provide feedback
									switch(res){
										case(1):	// all good
													obj.innerHTML = '';
										break;
										case(-1):	//alert('too short');
													obj.innerHTML = 'Invalid';
										break;
										default:
									}
								}
								
								if(res<=0){
									status = false;
									//if(form[item[0]].value.length==0) form[item[0]].value = 'REQUIRED';
									form[item[0]].className = 'required';
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label-invalid';								
										}
									}
									
									form[item[0]].onfocus = function(){
										focused(this);
									}
								} else {
									form[item[0]].className = 'text-input';
								}
			break;
			case('select'):		var res = validateSelect(form[item[0]], form);
								// FEEDBACK
								if(document.getElementById(form[item[0]].name + '_msg')){
										
									var obj = document.getElementById(form[item[0]].name + '_msg');
									// provide feedback
									switch(res){
										case(1):	// all good
													obj.innerHTML = '';
										break;
										case(-1):	//alert('too short');
													obj.innerHTML = 'Select a State';
										break;
										default:
									}
								}
			
								if(res<=0){
									status = false;
									form[item[0]].className = 'required';
									form[item[0]].onfocus = function(){
										
										selectChanged(this, form);
									}
									form[item[0]].onchange = function(){
										
										selectChanged(this, form);
									}
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label-invalid';								
										}
									}
								} else {
									form[item[0]].className = 'text-input';
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label';								
										}
									}
								}
			break;
			case("state"):		// validateState(select_name, manual_name, country_select_name)
								var res = validateState(item[0], item[1], item[2]);
			
								//alert(item[0] + '_msg');
								/*
								if(res>0) alert('good: ' + res);
								else alert('state no good: ' + res);
								*/
								//alert('state!! name=' + item[0] + item[1] + item[2] + ', country_select=');
								if(document.getElementById(item[0] + '_msg')){
									//alert('fedback');	
									var obj = document.getElementById(item[0] + '_msg');
									// provide feedback
									
									
									
									/*
									validateState(select_state_id, manual_state_id, country_select_id){
	
									select_state_id 	= 'select_state';
									manual_state_id 	= 'manual_state';
									country_select_id 	= 'country';
									*/
									//alert(document.getElementByid(manual_state_id).className);
									
									switch(res){
										case(-4):	//alert('no input');
													obj.innerHTML = 'Enter State';
													//document.getElementById(item[1]).className = 'text-input';
										break;
										case(5):	// ok
													obj.innerHTML = '';
													//document.getElementById(item[1]).className = 'text-input';
										
										break;
										case(1):	obj.innerHTML = '';
													//document.getElementById(item[1]).className = 'text-input';
										break;
										case(-3):	//alert('too long');
													obj.innerHTML = 'Select State';
													//document.getElementById(item[1]).className = 'text-input';
										break;
										default:
									}
								}
								
								
								
			break;	
			default:
			case('text'):		
								var res = validateText(form[item[0]].value, item[2], item[3]);
								
								
								// FEEDBACK
								if(document.getElementById(form[item[0]].name + '_msg')){
										
									var obj = document.getElementById(form[item[0]].name + '_msg');
									// provide feedback
									switch(res){
										case(-1):	//alert('no input');
													obj.innerHTML = 'No Input';
										break;
										case(-2):	//alert('too short');
													obj.innerHTML = 'Too Short';
										break;
										case(-3):	//alert('too long');
													obj.innerHTML = 'Too Long';
										break;
										case(1):	obj.innerHTML = '';
										break;
										default:
									}
								}
								
								
								
								form[item[0]].onfocus = function(){
									
									//alert(form[item[0]].name);
									focused(this);
									
								}
								
								
								
								if(res<0){
									status = false;
									if(form[item[0]].value.length==0) {
									
										if(form[item[0]].type!='password'){
										
											if(item[4]!='0') form[item[0]].value = 'REQUIRED';
										}
									
									}
									form[item[0]].className = 'required';
								
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label-invalid';								
										}
									}
									
									form[item[0]].onfocus = function(){
										
										//alert(form[item[0]].name);
										focused(this);
										
									}
								} else {
									form[item[0]].className = 'text-input';
									
									if(this.label_feedback){
										if(document.getElementById(form[item[0]].name + '_label')){
											document.getElementById(form[item[0]].name + '_label').className = 'input-label';								
										}
									}
								
								}
		}
	}
	
	//if(!status) alert('Please Fill In All Required Fields.');
	return status;
}


function selectChanged(item, form){

	
	if(validateSelect(item)){
	
		item.className = 'text-input';
		
		if(this.label_feedback){
			if(document.getElementById(form[item.name].name + '_label')){
				document.getElementById(form[item.name].name + '_label').className = 'input-label';								
			}
		}
	
	
	}
	
	
}

function focused(item){

	if(item.value=='REQUIRED'){
	
		item.value = '';
		item.className = 'text-input';
	}
	
	if(item.className=='required'){
	
		item.className = 'text-input';
		
	}
	
}
function validateState(select_state_id, manual_state_id, country_select_id){
	
	
	select_state_id 	= 'select_state';
	manual_state_id 	= 'manual_state';
	country_select_id 	= 'country';
	
	
	
	if(debug) alert('VALIDATING THE STATE ENTRY: manual_state_id=' + manual_state_id + ', select_state_id=' + select_state_id + ', country_select_id=' + country_select_id);
	/**
	 *	default DOM id's:
	 *
	 *	country			|	country Selector
	 *	select_state	|	State Selector
	 *	manual_state	|	Manual State Entry Field
	 *
	 **/
	 

	 //return falase;
	 
	
	var manual_state = document.getElementById(manual_state_id);
	var select_state = document.getElementById(select_state_id);
	var country_select = document.getElementById(country_select_id);
	
	//var debug = true;
	//alert(country_select.options[country_select.selectedIndex].value);
	
	if(manual_state&&select_state&&country_select){
	
		switch(country_select.options[country_select.selectedIndex].value){
			case("CA"):
			case("USA"):	//alert('Fr');
							// we should check the states select for a value				
							
							if(select_state.selectedIndex>0){
								if(debug) alert('STATE SELECTOR IS SELECTED');
								select_state.className = 'text-input';
								
								return 1;	// STAET SELECTOR IS SELECTED
							} else {
								if(debug) alert('STATE SELETOR NOT SELECTED');
								select_state.className = 'required';
								return -3;	// STATE SELETOR NOT SELECTED
							}
							
			break;
			default:
							// we should use teh manual entry textbox
							
							if(manual_state.value.length>=2){
								if(debug) alert('the manual state is filled in');
								
								manual_state.className = 'text-input';
								return 5;	// the manual state is filled in
							} else {
								if(debug) alert('MANUAL STATE NOT FILLED IN');
								
								manual_state.className = 'required';
								return -4;	// MANUAL STATE NOT FILLED IN
							}
							
		}	
	
	}
	return -1;	// default failure
	
}
function validateSelect(obj, form){

	//alert('validateSelect()');
	//alert(obj.type);

	switch(obj.type){
		case("text"):		//alert('snagged text type');
							return validateText(obj.value, 2, 255);
		break;
		default:
	}

	if(obj.selectedIndex==-1) return -1;

	if(obj.options[obj.selectedIndex].value==-1) return -1;
	else return 1;


}

function validateText(str, minimum, maximum){
	
	//alert('validateText(' + str + ',' + minimum + ',' + maximum + ')');

	if(str=='REQUIRED') return -1;	// no input
	if(str.length<minimum) return -2;	// too short
	if(str.length>maximum) return -3;	// too long
	return 1;
}


/****
/**
 * DHTML email validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */

function validateEmail(str) {
	
		if(str.length==0) return -1;	// no input

		if(str=="REQUIRED") return -1;	// no input

		var at="@"
		var dot="."
		var lat=str.indexOf(at)
		var lstr=str.length
		var ldot=str.indexOf(dot)
		if (str.indexOf(at)==-1){
		   //alert("Invalid E-mail ID")
		   return false
		}

		if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
		   //alert("Invalid E-mail ID")
		   return -2;
		}

		if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
		   // alert("Invalid E-mail ID")
		    return -2;
		}

		 if (str.indexOf(at,(lat+1))!=-1){
		   // alert("Invalid E-mail ID")
		    return -2;
		 }

		 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
		   // alert("Invalid E-mail ID")
		    return -2;
		 }

		 if (str.indexOf(dot,(lat+2))==-1){
		    //alert("Invalid E-mail ID")
		    return -2;
		 }
		
		 if (str.indexOf(" ")!=-1){
		    //alert("Invalid E-mail ID")
		    return -2;
		 }

 		 return 1;					
	}

function validateZIP(field) {

	var valid = "0123456789-";
	var hyphencount = 0;
	
	if (field.length!=5 && field.length!=10) {
		//alert("Please enter your 5 digit or 5 digit+4 zip code.");
		return -1;
	}
	for (var i=0; i < field.length; i++) {
	temp = "" + field.substring(i, i+1);
	if (temp == "-") hyphencount++;
	if (valid.indexOf(temp) == "-1") {
	//alert("Invalid characters in your zip code.  Please try again.");
	return -1;
	}
	if ((hyphencount > 1) || ((field.length==10) && ""+field.charAt(5)!="-")) {
	//alert("The hyphen character should be used with a properly formatted 5 digit+four zip code, like '12345-6789'.   Please try again.");
	return -1;
	   }
	}
	return 1;
}

function cardExpired(month, year){
	
	return checkDate(month, 31, year);
	
}



function checkDate(month, day, year)
{
	
if (year.length == 2) year += 2000;
var now = new Date();
var nowMonth = now.getMonth() + 1;
var nowYear = now.getFullYear();
expired = (nowYear > year) || ((nowYear == year ) && (nowMonth > month));
return expired;

} 

var monthLength = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

function checkCardNumWithMod10(cardNum) {
	var i;
	var cc = new Array(16);
	var checksum = 0;
	var validcc;

	// assign each digit of the card number to a space in the array	
	for (i = 0; i < cardNum.length; i++) {
		cc[i] = Math.floor(cardNum.substring(i, i+1));
	}

	// walk through every other digit doing our magic
	// if the card number is sixteen digits then start at the
	// first digit (position 0), otherwise start from the
	// second (position 1)
	for (i = (cardNum.length % 2); i < cardNum.length; i+=2) {
		var a = cc[i] * 2;
		if (a >= 10) {
			var aStr = a.toString();
			var b = aStr.substring(0,1);
			var c = aStr.substring(1,2);
			cc[i] = Math.floor(b) + Math.floor(c);
		} else {
			cc[i] = a;
		}
	}

	// add up all of the digits in the array
	for (i = 0; i < cardNum.length; i++) {
		checksum += Math.floor(cc[i]);
	}

	// if the checksum is evenly divisble by 10
	// then this is a valid card number
	validcc = ((checksum % 10) == 0);

	return validcc;
}

function cleanCardNum(cardNum) {
	var i;
	var ch;
	var newCard = "";

	// walk through the string character by character to build
	// a new string with numbers only
	i = 0;
	while (i < cardNum.length) {
		// get the current character
		ch = cardNum.substring(i, i+1);
		if ((ch >= "0") && (ch <= "9")) {
			// if the current character is a digit then add it
			// to the numbers-only string we're building
			newCard += ch;
		} else {
			// not a digit, so check if its a dash or a space
			if ((ch != " ") && (ch != "-")) {
				// not a dash or a space so fail
				return false;
			}
		}
		i++;
	}

	// we got here if we didn't fail, so return what we built
	return newCard;
}

function checkCard(cardType, cardNum) {
	var validCard;
	var cardLength;
	var cardLengthOK;
	var cardStart;
	var cardStartOK;
	
	// check if the card type is valid
	if ((cardType != "VISA") && (cardType != "MC") && (cardType != "AMEX") && (cardType != "DISC")) {
		
		return false;
	}

	// clean up any spaces or dashes in the card number
	validCard = cleanCardNum(cardNum);
	if (validCard != "") {
		// check the first digit to see if it matches the card type
		cardStart = validCard.substring(0,1);
		cardStartOK = ( ((cardType == "VISA") && (cardStart == "4")) ||
				((cardType == "MC") && (cardStart == "5")) ||
				((cardType == "AMEX") && (cardStart == "3")) ||
				((cardType == "DISC") && (cardStart == "6")) );
		if (!(cardStartOK)) {
			// card number's first digit doesn't match card type
			
			//alert("Please make sure the card number you've entered matched the card type you selected.");
			return false;
		}

		// the card number is good now, so check to make sure
		// it's a the right length
		cardLength = validCard.length;		
		cardLengthOK = ( ((cardType == "VISA") && ((cardLength == 13) || (cardLength == 16))) ||
				 ((cardType == "MC") && (cardLength == 16)) ||
				 ((cardType == "AMEX") && (cardLength == 15)) ||
				 ((cardType == "DISC") && (cardLength == 16)) );
		if (!(cardLengthOK)) {
			// not the right length
			return false;
		}

		// card number seems OK so do the Mod10
		if (checkCardNumWithMod10(validCard)) {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}



/**
  * Crossbrowser event handling functions.
  *
  * A set of functions to easily attach and detach event handlers to HTML elements.
  * These functions work around the shortcomings of the traditional method ( element.onevent = function; )
  * where only 1 handler could be attached for a certain event on the object, and mimic the DOM level 2
  * event methods addEventListener and removeEventListener for browsers that do not support these
  * methods (e.g. Internet Explorer) without resorting to propriety methods such as attachEvent and detachEvent
  * that have a whole set of their own shortcomings.
  * Created as an entry for the 'contest' at quirksmode.org: http://www.quirksmode.org/blog/archives/2005/09/addevent_recodi.html
  *
  * @author Tino Zijdel ( crisp@xs4all.nl )
  * @version 1.2
  * @date 2005-10-21
  */


/**
  * addEvent
  *
  * Generic function to attach event listeners to HTML elements.
  * This function does NOT use attachEvent but creates an own stack of function references
  * in the DOM space of the element. This prevents closures and therefor possible memory leaks.
  * Also because of the way the function references are stored they will get executed in the
  * same order as they where attached - matching the behavior of addEventListener.
  *
  * @param obj The object to which the event should be attached.
  * @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
  * @param fn The function to be executed when the event fires.
  * @param useCapture (optional) Whether to use event capturing, or event bubbling (default).
  */
function addEvent(obj, evType, fn, useCapture)
{
	//-- Default to event bubbling
	if (!useCapture) useCapture = false;

	//-- DOM level 2 method
	if (obj.addEventListener)
	{
		obj.addEventListener(evType, fn, useCapture);
	}
	else
	{
		//-- event capturing not supported
		if (useCapture)
		{
			alert('This browser does not support event capturing!');
		}
		else
		{
			var evTypeRef = '__' + evType;

			//-- create function stack in the DOM space of the element; seperate stacks for each event type
			if (obj[evTypeRef])
			{
				//-- check if handler is not already attached, don't attach the same function twice to match behavior of addEventListener
				if (array_search(fn, obj[evTypeRef]) > -1) return;
			}
			else
			{
				//-- create the stack if it doesn't exist yet
				obj[evTypeRef] = [];

				//-- if there is an inline event defined store it in the stack
				if (obj['on'+evType]) obj[evTypeRef][0] = obj['on'+evType];

				//-- attach helper function using the DOM level 0 method
				obj['on'+evType] = IEEventHandler;
			}

			//-- add reference to the function to the stack
			obj[evTypeRef][obj[evTypeRef].length] = fn;
		}
	}
}

/**
  * removeEvent
  *
  * Generic function to remove previously attached event listeners.
  *
  * @param obj The object to which the event listener was attached.
  * @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
  * @param fn The listener function.
  * @param useCapture (optional) Whether event capturing, or event bubbling (default) was used.
  */
function removeEvent(obj, evType, fn, useCapture)
{
	//-- Default to event bubbling
	if (!useCapture) useCapture = false;

	//-- DOM level 2 method
	if (obj.removeEventListener)
	{
		obj.removeEventListener(evType, fn, useCapture);
	}
	else
	{
		var evTypeRef = '__' + evType;

		//-- Check if there is a stack of function references for this event type on the object
		if (obj[evTypeRef])
		{
			//-- check if function is present in the stack
			var i = array_search(fn, obj[evTypeRef]);
			if (i > -1)
			{
				try
				{
					delete obj[evTypeRef][i];
				}
				catch(e)
				{
					obj[evTypeRef][i] = null;
				}
			}
		}
	}
}

/**
  * IEEventHandler
  * 
  * IE helper function to execute the attached handlers for events.
  * Because of the way this helperfunction is attached to the object (using the DOM level 0 method)
  * the 'this' keyword will correctely point to the element that the handler was defined on.
  *
  * @param e (optional) Event object, defaults to window.event object when not passed as argument (IE).
  */
function IEEventHandler(e)
{
	e = e || window.event;
	var evTypeRef = '__' + e.type, retValue = true;

	//-- iterate through the stack and execute each function in the scope of the object by using function.call
	for (var i = 0, j = this[evTypeRef].length; i < j; i++)
	{
		if (this[evTypeRef][i])
		{
			if (Function.call)
			{
				retValue = this[evTypeRef][i].call(this, e) && retValue;
			}
			else
			{
				//-- IE 5.0 doesn't support call or apply, so use this
				this.__fn = this[evTypeRef][i];
				retValue = this.__fn(e) && retValue;
			}
		}
	}

	if (this.__fn) try { delete this.__fn; } catch(e) { this.__fn = null; }

	return retValue;
}

/**
  * array_search
  * 
  * Searches the array for a given value and returns the (highest) corresponding key if successful, -1 if not found.
  *
  * @param val The value to search for.
  * @param arr The array to search in.
  */
function array_search(val, arr)
{
	var i = arr.length;

	while (i--)
		if (arr[i] && arr[i] === val) break;

	return i;
}