
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//  AUTHOR: Kristian Ranstrom
// 	FILE:	validate.js
//	PURP:	input validation routines
//	
//	FUNCTIONS:
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//
//	FORM VALIDATION
//  errorMsg			(err)
//	errorMsgColor		(input)
//	errorMsgColorDetail	(input)
//	clearErrorColor		()
//	focusElement		(form object)
//  showErrorColor		()
//	showErrorSingle		(frm, name, msg)
//	isValidColor		()
//	isValid				()
//	
//	getValue			(input)
//	getRadioIndex		(input)
//	getSelectMultIndex	(input)
//
//	stripToAlphaNumeric	(str)
//
//	isPattern			(input,pattern)
//	isNumeric			(input)
//	isAlpha				(input)
//	isEmpty				(input)
//
//	isValidMonthDay		(int)
//	isLeapYear			()
//	isDay				(input)
//	isMonth				(input)
//	isYear				(input)
//	
//	isPhone				(input)
//	isPhone3			(input)
//	isPhone4			(input)
//	isPhoneAreaCode		(input)
//  formatPhone			(input)
//	formatPhoneNumeric	(input)
//
//	isThereSpaces		(input)
//	isOnlyLetters		(input)
//	isUsername			(input)
//
//	isStateAbbrev		(input)
//	isZip4				(input)
//	isZip				(input)
//	isEmail				(input)
//
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//Declare the globals
var errmsg = "";
var firstErrorField = "";
var arrErrorFields = new Array();
var errColor = "#0000ff";

//Browser Detection
var IE4up = document.all;
var NS4 = document.layers;
var NS6 = navigator.userAgent.indexOf("Netscape6") > 0;


//||ErrorMsg
//=========================================================
// FUNC:	errorMsg
// PARM: 	err
//=========================================================
function errorMsg (err) {
	if(errmsg.indexOf("following fields") == -1) {
		errmsg = "The following fields have errors: \n\n";
	}
	errmsg += err + "\n";
}

//||ErrorMsg
//=========================================================
// FUNC:	errorMsgColor
// PARM: 	err
//=========================================================
function errorMsgColor (input) {
	if(errmsg.indexOf("following fields") == -1) {
		clearErrorColor();
		errmsg = "Some fields have errors\nPlease review the form.";
		firstErrorField = getName(input.name);
	}
	arrErrorFields[arrErrorFields.length] = getName(input);
}

//||
//=========================================================
// FUNC:	errorMsgColorDetail
// PARM: 	err - string of error message
// PARM:	input - ref to form element
// PARM:	errid - the id of the object to be colored
//=========================================================
function errorMsgColorDetail (err, input, errid) {
	if(errmsg.indexOf("following fields") == -1) {
		clearErrorColor();
		errmsg = "The following fields are missing values or have errors: \n\n";
		firstErrorField = getName(input);
	}
	errmsg += err + "\n";
	arrErrorFields[arrErrorFields.length] = errid;
}

//=========================================================
// FUNC:	clearErrorColor
// PARM: 	input
//=========================================================
function clearErrorColor () {
	//If not IE4up or NS6 leave
	if(NS4) return;
	
	for(i=0; i < arrErrorFields.length; i++) {
		if(document.getElementById(arrErrorFields[i])) {
			document.getElementById(arrErrorFields[i]).style.color = "";
		}
	}
	
	arrErrorFields.length = 0;
}

//=========================================================
// FUNC:	focusElement
// PARM: 	f - form object
//=========================================================
function focusElement (f) {
	field = eval("document." + f.name + "." + firstErrorField);
	if(field.name && field.type != 'hidden' && field.type != "file") field.focus();
}

//=========================================================
// FUNC:	showErrorColor
// PARM: 	input
//=========================================================
function showErrorColor () {
	//If not IE4up or NS6 leave
	if(NS4) return;

	for(i=0; i < arrErrorFields.length; i++) {
		if(document.getElementById(arrErrorFields[i])) {
			document.getElementById(arrErrorFields[i]).style.color = errColor;
		}
	}
}

//=========================================================
// FUNC:	showErrorSingle
// PARM: 	input
//=========================================================
function showErrorSingle (frm, name, msg) {
	alert(msg);

	eval("document." + frm.name + "." + name + ".value = ''");
	eval("document." + frm.name + "." + name + ".focus()");
}

//=========================================================
// FUNC:	isValidColor
// PARM: 	fields - ref to form object
//=========================================================
function isValidColor (fields) {
	if(errmsg != "") {
		showErrorColor();
		alert(errmsg);
		focusElement(fields)
		errmsg = "";
		return false;
	}
	return true;
}

//=========================================================
// FUNC:	isValid
// PARM: 	input
//=========================================================
function isValid () {
	if(errmsg != "") {
		alert(errmsg);
		errmsg = "";
		return false;
	}
	return true;
}


//_________________________________________________________________________________________________
//||[ GENERAL ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//=========================================================
// FUNC:	getName
// PARM:	input - ref to form radio input
//=========================================================
function getName(input) {
	if(input.name) return input.name;
	else return input[0].name;
}

//=========================================================
// FUNC:	getValue
// PARM:	input - ref to form radio input
//=========================================================
function getValue(input) {

	switch (input.type) {
		case "text"				: 
		case "textarea"			: 
		case "checkbox"			: 
		case "hidden"			: 
		case "password"			: 
		case "file"				: 
		case "submit"			: 
		case "button"			:
		case "reset"			: return input.value;
		case "radio"			: return input.checked;
		case "select-one"		: return input.options[input.selectedIndex].value;
		case "select-multiple"	: var value="";
								  for (var i=0; i < input.options.length; i++)
									if (input.options[i].selected)
										value += (value == "" ? "" : ",") + i;
								  return value;
		default					: alert("getValue input type not supported."); return null;
	}
}

//=========================================================
// FUNC:	getRadioIndex
// PARM:	input - ref to form radio input
//=========================================================
function getRadioIndex(input) {
	
	for (var i=0; i < input.length; i++)
		if (input[i].checked) return i;
		
	return -1;
}

//=========================================================
// FUNC:	getSelectMultIndex
// PARM:	input - ref to form select-multiple input
//  RES:	array containing selected indexes
//=========================================================
function getSelectMultIndex(input) {
	if (input.type != "select-multiple") {
		alert("getSelectMultIndex: invalid input element");
		return -1;
	}
	
	var aResult = new Array();
	
	for (var i=0; i < input.options.length; i++)
		if (input.options[i].selected) aResult[aResult.length] = i;
		
	return aResult;
}

//=========================================================
// FUNC:	stripToAlphaNumeric
// PARM:	input - ref to form input
//			str - string to strip
// NOTE:
//			"9": numeral
//			"a": alpha
//			any other must match
//=========================================================
function stripToAlphaNumeric(str) {
	
	var i
	var temp = "";
	
	str = str.toString();

	for (i=0; i <= str.length; i++)	{
		
		if ((str.charAt(i) >= "0") && (str.charAt(i) <= "9")) temp += str.charAt(i);

		if ((str.charAt(i) >= "A") && (str.charAt(i) <= "Z")) temp += str.charAt(i);

		if ((str.charAt(i) >= "a") && (str.charAt(i) <= "z")) temp += str.charAt(i);
	}
	return temp;

}

//=========================================================
// FUNC:	trim
// PARM:	str - string to be trimmed
// PURP:	trims leading and trailing whitespace from a
//			string
//=========================================================
function trim(str){
	var iStart 	= 0;
	var iEnd 	= str.length-1;
	var bLoop	= true;
	var sTrimmed;
	var cChar;

	cChar = str.charAt(iStart);
	while ((iStart < iEnd) && ((cChar == "\n") || (cChar == "\r") || (cChar == "\t") || (cChar == " "))){
		iStart ++;
		cChar = str.charAt(iStart);
	}

	cChar = str.charAt(iEnd);
	while ((iEnd >= 0) && ((cChar == "\n") || (cChar == "\r") || (cChar == "\t") || (cChar == " "))){
		iEnd --;
		cChar = str.charAt(iEnd);
	}
	
	if (iStart <= iEnd)
		sTrimmed = str.substring(iStart, iEnd + 1);
	else
		sTrimmed = "";
	
	return sTrimmed;
}

//=========================================================
// FUNC:	isPattern
// PARM:	input - ref to form input
//			pattern - matching mask
// NOTE:
//			"9": numeral
//			"a": alpha
//			any other must match
//=========================================================
function isPattern(input,pattern) {

	var value = getValue(input);
	
	if (value == null) {
		alert("isPattern: getValue failed.");
		return null;
	}

	return isPatternValue(value, pattern);
}

function isPatternValue(value,pattern) {

	var p,s,i,value;

	if (value.length != pattern.length) return false;
	
	for (i=1; i<=value.length; i++)	{
	
		p = pattern.charAt(i);
		s = value.charAt(i);
		
		if ((p == "9") && ((s < "0") || (s > "9"))) return false;
		else
		if ((p == "a") && ( ((s < "a") || (s > "z")) && ((s < "A") || (s > "Z")) ) ) return false;
		else
		if ((p != "9") && (p != "a") && (p != s)) return false;
	}
	return true;
}

//=========================================================
// FUNC:	isNumeric
// PARM:	input - ref to form input
//=========================================================
function isNumeric(input) {

	switch (input.type) {
		case "text"				: 
		case "textarea"			: 
		case "checkbox"			: 
		case "hidden"			: 
		case "password"			: 
		case "file"				: 
		case "submit"			: 
		case "reset"			: return (parseFloat(input.value) == input.value);
		
		case "radio"			: if ((ndx = getRadioIndex(input)) == -1) return false;
								  return (parseFloat(input[ndx].value) == input[ndx].value);
								  
		case "select-one"		: value = input.options[input.selectedIndex].value ? input.options[input.selectedIndex].value : input.options[input.selectedIndex].text;
								  return (parseFloat(value) == value);
									
		default					: alert("isNumeric: input type not supported."); return null;
	}
}

//=========================================================
// FUNC:	isAlpha
// PARM:	input - ref to form input
//=========================================================
function isAlpha(input) {
	var str = getValue(input);
	var i, temp;
	
	for (i=1; i <= str.length; i++)	{

		if ((str.charAt(i) >= "A") && (str.charAt(i) <= "Z")) temp += str.charAt(i);

		if ((str.charAt(i) >= "a") && (str.charAt(i) <= "z")) temp += str.charAt(i);
	}

	return temp == str;
}

//=========================================================
// FUNC:	isEmpty
// PARM:	input - ref to form input
//=========================================================
function isEmpty(input) {

	switch (input.type) {									// requires 4.0+ browsers
		case "text" 			: 
		case "textarea" 		: 
		case "hidden"			: 
		case "password" 		: 
		case "file"				: 
		case "submit"			: 
		case "reset"			: for(i=0;i<input.value.length;i++) { if(input.value.charAt(i) != " ") return false; } return true;
		case "checkbox" 		: return (input.checked);
		case "radio"			: return (getRadioIndex(input) == -1);
		case "select-one"		:
		case "select-multiple"	: return (input.selectedIndex == -1);
		default					: alert("isEmpty: input type not supported."); return null;	
	}
}


//=========================================================
// FUNC:	listFind
// PARM:	list, str {string to search for}, delim {opt}
//=========================================================
function listFind() {
	if(!listFind.arguments[0] || !listFind.arguments[1]) {
		alert("listFind: 2 or 3 parameters expected");
		return null;
	}
	
	list = listFind.arguments[0];
	str =  listFind.arguments[1];
	if(listFind.arguments[2]) delim = listFind.arguments[2];
	else delim = ","
	
	arrList = list.split(delim);
	
	for(i=0; i < arrList.length; i++) {
		if(str == arrList[i]) return true;
	}
	
	return false;
	
}


//_________________________________________________________________________________________________
//||[ DATE ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//=========================================================
// FUNC:	isValidMonthDay
// PARM:	month	- int - 1-based
//			day		- int
//=========================================================
function isValidMonthDay(month,day) {

	month = parseInt(month,10);
	day = parseInt(day,10);

	switch (month) {
	// 31
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12: return (day <= 31);
	// 30
		case 4:
		case 6:
		case 9:
		case 11: return (day <= 30);
	//29 
		case 2: return (isLeapYear())?(day <= 29):(day <=28);
		default: alert("isValidMonthDay: invalid month"); return null;
	}
}

//=========================================================
// FUNC:	isLeapYear
//=========================================================
function isLeapYear() {
	
	var today, year;
	
	if(isLeapYear.arguments[0]) {
		year = isLeapYear.arguments[0];
	}
	else {
		today = new Date();
		year = today.getYear()
	}
	
	
	return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
	
}

//=========================================================
// FUNC:	isDay
// PARM:	input - ref to form input
//=========================================================
function isDay(value) {
	
	return (isPatternValue(value,"99") || isPatternValue(value,"9")) && ((value >= 1) && (value <= 31));
}

//=========================================================
// FUNC:	isMonth
// PARM:	input - ref to form input
//=========================================================
function isMonth(value) {

	return (isPatternValue(value,"99") || isPatternValue(value,"9")) && ((value >= 1) && (value <= 12));
}

//=========================================================
// FUNC:	isYear
// PARM:	input - ref to form input
//=========================================================
function isYear(value) {

	return isPatternValue(value,"9999");
}

//=========================================================
// FUNC:	isDate
// PARM:	input - ref to form input
//=========================================================
function isValidDate(input) {

	while(input.value.indexOf("-") > 0) {
		input.value = input.value.replace("-","/");
	}
	
	var mySplit = input.value.split("/");
	
	if(mySplit.length != 3) return false; 
	
	return isMonth(mySplit[0]) && isDay(mySplit[1]) && isYear(mySplit[2]) && isValidMonthDay(mySplit[0],mySplit[1]);
}

//_________________________________________________________________________________________________
//||[ PHONE ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//=========================================================
// FUNC:	isPhone
// PARM:	input - ref to form input
//=========================================================
function isPhone(input){ 

	input.value = trim(getValue(input));

	var val = isPattern(input,"(999) 999-9999") || 
			isPattern(input,"(999) 999.9999") ||
			isPattern(input,"999 999 9999") ||
			isPattern(input,"999-999-9999") || 
			isPattern(input,"999.999.9999") || 
			isPattern(input,"9999999999") ||	
			isPattern(input,"999-9999") ||
			isPattern(input,"999.9999") ||
			isPattern(input,"999 9999") ||
			isPattern(input,"9999999");
	return val;
}

//=========================================================
// FUNC:	isPhone3
// PARM:	input - ref to form input
//=========================================================
function isPhone3(input) { 
	return isPattern(input,"999");
}

//=========================================================
// FUNC:	isPhone4
// PARM:	input - ref to form input
//=========================================================
function isPhone4(input) {
	return isPattern(input,"9999");
}

//=========================================================
// FUNC:	isPhoneAreaCode
// PARM:	input - ref to form input
//=========================================================
function isPhoneAreaCode(input) {
	return isPattern(input,"999") || isPattern(input,"(999)");
}

//=========================================================
// FUNC:	formatPhone
// PARM"	input - ref to form input
//=========================================================
function formatPhone(input) {
	switch (input.value.length) {
		case 7:  input.value = input.value.substring(0,3) + "-" + input.value.substring(3);
				 break;
		case 8:  input.value = input.value.substring(0,3) + "-" + input.value.substring(4);
				 break;
		case 10: input.value = "(" + input.value.substring(0,3) + ") " + input.value.substring(3,6) + "-" + input.value.substring(6);
				 break;
		case 12: input.value = "(" + input.value.substring(0,3) + ") " + input.value.substring(4,7) + "-" + input.value.substring(8);
				 break;
		default:
   	}
}

//=========================================================
// FUNC:	formatPhoneNumeric
// PARM"	input - ref to form input
//=========================================================
function formatPhoneNumeric(input) {
	input.value = stripToAlphaNumeric(getValue(input));
	return;
}

//__________________________________________________________________________________________________
//||[Username]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//=========================================================
// FUNC:	isThereSpaces
// PARM"	input - ref to form input
//=========================================================
function isThereSpaces(input) {
	if(input.value.indexOf(" ") != -1) return true;
	else return false;
}

//=========================================================
// FUNC:	isOnlyLetters
// PARM"	input - ref to form input
//=========================================================
function isOnlyLetters(input) {
	var boo = true;
	var value = getValue(input);
	
	if (window.RegExp) {
			for(i=0; i < value.length; i++) {
			
			var regValid = /\w/

			boo = regValid.test(value.charAt(i));
			
			if (!boo) {return boo;}
		}
	}
	return boo;
}

//=========================================================
// FUNC:	isUsername
// PARM"	input - ref to form input
//=========================================================
function isUsername(input) {
	return !isThereSpaces(input) && isOnlyLetters(input);
}

//_________________________________________________________________________________________________
//||[ ADDRESS ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//=========================================================
// FUNC:	isStateAbbrev
// PARM:	input - ref to form input
//=========================================================
function isStateAbbrev(input) {
	return isPattern(input,"aa");
}

//=========================================================
// FUNC:	isZip4
// PARM:	input - ref to form input
//=========================================================
function isZip4(input) {
	return isPattern(input,"9999");
}

//=========================================================
// FUNC:	isZip
// PARM:	input - ref to form input
//=========================================================
function isZip(input) {
	return isPattern(input,"99999") || 
			isPattern(input,"99999-9999") ||
			isPattern(input,"a9a9a9") ||
			isPattern(input,"a9a 9a9");
}

//=========================================================
// FUNC:	isEmail
// PARM:	input - ref to form input
//=========================================================
function isEmail(input) {
	value = getValue(input);
	
	if (window.RegExp) {
	
		var regValid = /^\w+((-\w+)|(\.\w+))*\@\w+((\.|-)\w+)*\.([a-zA-Z]){2,3}$/

		return regValid.test(value);
		
	}
	else {
	
		var ndxAt = value.indexOf("@");
		var ndxPeriod = value.lastIndexOf(".");
		
		return ((ndxAt > -1) && (ndxPeriod > -1) && (ndxAt < ndxPeriod));
	}
}

//=========================================================
// FUNC:	isTime
// PARM:	input - ref to form input
//=========================================================
function isTime(input) {
	input.value = trim(getValue(input));

	return  isPattern(input,"9:99") || 
			isPattern(input,"9:99aa") ||
			isPattern(input,"9:99 aa") ||
			isPattern(input,"9:99a") ||
			isPattern(input,"9:99aa") ||
			isPattern(input,"9:99 a") ||
			isPattern(input,"99:99") ||
			isPattern(input,"99:99aa") ||
			isPattern(input,"99:99 aa") ||
			isPattern(input,"99:99aa") ||
			isPattern(input,"99:99a") ||
			isPattern(input,"99:99 a") ||
			isPattern(input,"9a") ||
			isPattern(input,"9aa") ||
			isPattern(input,"9 a") ||
			isPattern(input,"9 aa") ||
			isPattern(input,"99a") ||
			isPattern(input,"99aa") ||
			isPattern(input,"99 a") ||
			isPattern(input,"99 aa");
}