	/**************************************************************
	 ***************	Form Validation Function	***************
	 **************************************************************
		Created on: 2009-12-10
		Last Updated: 2009-12-10
		
		A validation function to highlight incorrect fields, 
		pop-up a message about said fields, and handle basic 
		form scripts such as automatically tabbing for phone 
		numbers...

		USE:
			Place this script tag in the head of the document and comment out or remove any lines which are not needed
			
			<script type="text/javascript">
				function validateForm(target){
					forms = {
								"first_name" : "fname",
								"last_name" : "lname",
								"email" : "email",
								"phone" : ["phone", "phn1", "phn2", "phn3"],
								"phone" : "phone",
								"dob" : ["dob", "year", "month", "day"],
								"dob" : "dob",
								"ca_zip" : "zipcode"
							};

					return validate(target, forms);
				}
			</script>
		
	*/

	window.onload = function() {	addFocusedProperty();	};
	
	/*******	Generic functions	*******/
	
	// Checks if the element is of the given class
	//
	//	Arguments: the target element, the target class
	function hasClass(ele,cls) {
		if(ele && cls){	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));	}
	}

	// Adds the given class to the list of classes an element has
	//
	//	Arguments: the target element, the target class
	function addClass(ele,cls) {
		if (!this.hasClass(ele,cls)) ele.className += " "+cls;
	}

	// Removes a given class from an element
	//
	//	Arguments: the target element, the target class
	function removeClass(ele,cls) {
		if (hasClass(ele,cls)) {
			var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
			ele.className=ele.className.replace(reg,' ');
		}
	}
	
	// Returns an array of all elements of a given class
	//
	//	Arguments: the parentNode of the elements, the class
	function getElementsByClassName(rootNode, className) {
		var children = rootNode.getElementsByTagName('*');
		var elements = [], child, pattern = new RegExp('(^|\\s)' + className + '(\\s|$)');
		for (var i = 0, length = children.length; i < length; i++) {
			child = children[i];
			var elementClassName = child.className;
			if (elementClassName.length == 0) continue;
			if (elementClassName == className || elementClassName.match(pattern))
				elements.push(child);
		}
		return elements;
	}

	// Returns an array of all elements of a given class
	//
	//	Arguments: the parentNode of the elements, the input type
	function getInputElements(rootNode, inputType) {
		var children = rootNode.getElementsByTagName('input');
		var elements = [], child, pattern = new RegExp('(^|\\s)'+inputType+'(\\s|$)');
		for (var i = 0, length = children.length; i < length; i++) {
			child = children[i];
			var elementType = child.type;
			if (elementType.length == 0) continue;
			if (elementType == inputType || elementType.match(pattern))
				elements.push(child);
		}
		return elements;
	}
	
	function getIndex(ele) {
		var index = -1, i = 0, found = false;
		
		while (i < ele.form.length && index == -1){
			if (ele.form[i] == ele){	index = i;	}
			else {	i++;	}
		}
		
		return index;
  }
	
	// Turns the first letter of ever word in a string to a capital letter
	//
	//	Arguments: the string to convert
	function toTitleCase(str){
		return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
	}

	
	/*******	Form-specific functions 	*******/
		
	// Returns a "Proper Name" version of the form types by replacing underscores 
	// 		with spaces, converting it to Title Case, adding "Code"	to the end of 
	//		zip code formats, and fixing up the country notation for zip codes
	//			Example: ca_zip becomes "Canadian Zip Code"
	//
	//	Arguments: the the form type
	function toName(str){
		str = str.replace(/_/g, " ")
		
		str = toTitleCase(str);
		
		//replace us w/ US and ca w/ Canadian and add code if it ends in 'zip'
		if(str.substr(3) == "Zip"){
			if(str.substr(0, 2) == "Us")
				str = str.replace(/Us /, "US ");
			if(str.substr(0, 2) == "Ca")			
				str = str.replace(/Ca Zip/, "Canadian Postal");
			
			str += " Code";
		} else if(str == "Dob"){
		//replace dob with "Date of Birth"
			str = "Date of Birth";
		}
		
		return str;
	}
	
	
	// Jumps to the next form field when the calling element is full
	//		Example: Jump between section of a phone number field 
	//				without having to Tab between them
	//
	//	Arguments: The element the user is currently entering text into
	function jump(ele, keys) {
		if (ele.value.length == ele.maxLength){
			next = getIndex(ele) + 1;
			
			if (next < document.forms[0].elements.length && keys != 'nav' && keys != 'backspace'){
				ele.form.elements[next].focus();
			}
		} else if (ele.value.length == 0){
			prev = getIndex(ele) - 1;
			
			if (prev > 0 && keys == 'backspace'){
				alert(prev);
				ele.form.elements[prev].focus();
			}
		}
	}
	
	function key(e){
		var keynum;
		var keychar;
		var numcheck;

		if(window.event){ // IE
			keynum = e.keyCode;
		} else if(e.which){ // Netscape/Firefox/Opera
			keynum = e.which;
		}
		
		//keychar = String.fromCharCode(keynum)
		
		//alert(keynum);
		
		if(keynum == 16 || keynum == 9 || (keynum >= 37 && keynum <= 40))
			return "nav";
		else
			return false;
	}
	
	function addFocusedProperty(){

		forms = document.forms;
		
		for (i = 0; i < forms.length; i++){
			for (j = 0; j < forms[i].elements.length; j++){
				elem = forms[i].elements[j];
				elem.focused = false;
				
				elem.hasFocus = function(){	return this.focused;	}

				elem.onfocus = function() {		this.focused = true;	addClass(this, 'highlighted');	};

				elem.onblur = function() {		this.focused = false;	removeClass(this, 'highlighted');		};
				
				//alert(elem.name + ": " + elem.focused + "\n");
			}
		}
	}

	/*******	Validation functions 	*******/
	
	
	// Checks to make sure all fields with the class name "required"
	//		have been filled in
	//
	//	Arguments: the form you're checking
	function requiredCheck(theForm){
		var pass = true;
		
		var requiredEles = getElementsByClassName(theForm, 'required');
		
		for ( var i in requiredEles ){
			if(!requiredEles[i].value){
				addClass(requiredEles[i], 'error');
				if(requiredEles[i].type != 'hidden'){
					pass = false;
				}
			} else if(requiredEles[i].value){
				removeClass(requiredEles[i], 'error');
			}
		}
		//alert(theForm);
		return pass;
	}
	
	
	// Combines multiple dropdowns into a dob value and puts it into 
	//		the hidden dob form field
	//
	//	Arguments: only the ids of the fields containing the year, month, and day
	function dob(dob){
		if(typeof dob == "string"){
			return false;
		} else if (typeof dob == "object" && dob.length == 4){
			
			var errorStr = '';
			
			ele = ["dob", "year", "month", "day"];
			
			for (i = 1; i <= 3; i++){		errorStr += checkValid(ele[i], dob[i]);	}
			
			if(errorStr == ''){
				var full_dob = "" + document.getElementById(dob[1]).value + "-" + 
									document.getElementById(dob[2]).value + "-" + 
									document.getElementById(dob[3]).value;
		
				document.getElementById(dob[0]).value = full_dob;
				
				return false;
			} else {	return errorStr;	}
		} else{	return "-Date of Birth error"}
	/*
		var dob = new Object();
		var pass = true;
		
		dob['year'] = document.getElementById(year);
		dob['month'] = document.getElementById(month);
		dob['day'] = document.getElementById(day);
				
		if(document.getElementById('dob').type == 'hidden'){
			if(hasClass(document.getElementById('dob'), 'required')){
				for(field in dob){
					if(!dob[field].value){
						addClass(dob[field], 'error');
						pass = false;
					} else if(hasClass(dob[field], 'error')){
						removeClass(dob[field], 'error');
					}
				}	
			}
		
			if(pass){
				document.getElementById('dob').value = '' + dob['year'].value + '-' + dob['month'].value + '-' + dob['day'].value + '';
				//alert(document.getElementById('dob').value);
			}
		}
		
		return pass;*/
	}
	
	function processPhone(phone){
		if(typeof phone == "string"){
			return phone;
		} else if (typeof phone == "object" && phone.length == 4){
			
			var errorStr = '';
			
			ele = ["phone", "area_code", "exchange_code", "phone_number"];
			
			for (i = 1; i <= 3; i++){		errorStr += checkValid(ele[i], phone[i]);	}
			
			if(errorStr == ''){
				var full_phone = "" + document.getElementById(phone[1]).value + 
									document.getElementById(phone[2]).value + 
									document.getElementById(phone[3]).value;
									
				document.getElementById(phone[0]).value = full_phone;
			}
				
			return [false, errorStr];
		} else{	return phone; }
	}
	
	/*******	List of regex strings for certain types of data 	*******/
	var filter_first_name = /^[a-zA-Z0-9'\- ]+$/;
	var filter_last_name = /^[a-zA-Z0-9'\- ]+$/;
	var filter_email = /^[a-zA-Z0-9._%+-]{2,}@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
	var filter_phone = /^[1-9][0-9]{9}$/;
	var filter_area_code = /^[1-9][0-9]{2}$/;
	var filter_exchange_code = /^[0-9]{3}$/;
	var filter_phone_number = /^[0-9]{4}$/;
	var filter_ca_zip = /^[ABCEGHJKLMNPRSTVXY]{1}[0-9]{1}[A-Z]{1} *[0-9]{1}[A-Z]{1}[0-9]{1}$/i;
	var filter_us_zip = /^[0-9]{5}$/;
	var filter_age = /^[0-9]{1,3}$/;
	var filter_dob = /[0-2][0-9][0-9][0-9]\/0|1?[0-9]\/[0-3]?[0-9]$/;
	/**********************************************************************/
	
	
	// The grunt function which loops through the passed array
	//		and validates the values by comparing them to their
	//		respective regex filters above
	//
	//	Arguments: the value type (zip, phone, etc), and its id in the form
	function checkValid(type, value){
		//alert(type + " : " + value);
		
		var name = toName(type);
		var errors = '';
		var ele;
		
		if(type == 'phone'){
			phoneOutput = processPhone(value);
			value = phoneOutput[0];
			errors += phoneOutput[1];
		} 
		
		/*
		if(type == 'area_code' || type == 'exchange_code'){
			if(document.getElementById(value).value == '555' || document.getElementById(value).value == '000'){	
				ele = document.getElementById(value);
				value = false;
				addClass(ele, 'error');
				errors += "-Phone is invalid\n";
			}
		} */
		
		if(typeof type == "string" && typeof value == "string" && value != "false"){
			ele = document.getElementById(value);
			//alert(value);
			
			type = 'filter_' + type;
			
			if((type == 'filter_area_code' || type == 'filter_exchange_code') && 
				(document.getElementById(value).value == '555' || document.getElementById(value).value == '000') || 
				(type == 'filter_area_code' || type == 'filter_exchange_code') && 
				(ele.value != '' && !eval(type).test(ele.value))){
			
				addClass(ele, 'error');
				errors += "-Phone " + name + " is invalid\n";
			} else if (ele.value != '' && !eval(type).test(ele.value)){
				addClass(ele, 'error');
				errors += "-" + name + " is invalid\n";
			} else if(ele.value != '' ){
				removeClass(ele, 'error');
			}
			
			//alert(errors);
		} else{		
			//addClass(ele, 'error');
			//errors += "-" + name + " is invalid\n";
		}
		
		return errors;
	}
	
	
	// The controller function which manages the functions above 
	//
	//	Arguments: the submitButton that was clicked, the array of form targets
	function validate(submitButton, forms){
		var pass = true;
		
		var theForm = submitButton.form;
		var errorStr = '';
		
		if(!requiredCheck(theForm)){	errorStr += "-Some required form fields were not filled out\n";	}
		/*
		if(forms['year'] && forms['month'] && forms['day']){
			if(!dob('year', 'month', 'day')){
				errorStr += "\n-Date Of Birth was not entered";
			}
		}
		*/
		//var phone = processPhone(forms['phone']);
		
		//if(phone){	errorStr += phone;	delete forms['phone'];	}
		//else{	forms['phone'] = forms['phone'][0];	}
		
		delete forms['dob'];
		
		for (params in forms){	for (ele in forms[params]){		errorStr += checkValid(ele, forms[params][ele]);	}	}
		
		if(errorStr != ''){ 
			//errorStr = "Error: \n" + errorStr;
			alert(errorStr);
			
			pass = false;
			
			getElementsByClassName(theForm, 'error')[0].focus();
		};
		
		return pass;
	}