//Original Author: Unknown
//Modified by: Jerrod Clausen (jerrod.clausen@usap.gov)- 12/01/04
//Modified by: Jeff Schmunk (jeffrey.schmunk@usap.gov)- 1/10/04
//This js parses through form element attributes to determine required format/values

//*************************************************************************
//Usage:
//Any form that uses these validators must have a unique name.
//The validation must be called in the onSubmit event of the form [onSubmit="return validate(this);"]

//Form fields may have either of the 3 following attributes (case sensitive):
//VALIDATOR, VALIDATORCHRS, VALIDATORNAME

//------------------------------------------------------------------------------------------------------------------------------
//VALIDATOR: (string) the name of the pattern you wish to validate against.
//------------------------------------------------------------------------------------------------------------------------------
//    zipPat - validates proper numeric US zip code format (e.g. xxxxx-xxxx)
//    emailPat - validates input is a standardized email address (e.g. xxxx@xxxx.xxx)
//    notEmptyPat - validates that the input is not empty, matches at least one character
//    numberPat - ensures the input contains only numeric values
//    pwPat - validates password format, matches between 4 and 10 characters with non-digit leading
//    currencyPat - validates currency with commas
//    timePat - validates times
//    validRadioBoxPat - validates that at least one option is selected for radio and checkbox collections
//    validNonReqTextPat - for text fields that do not require input.  ensures valid formatting, if populated

//The following date patterns are contained in the datepicker custom tag.
//To create date form fields, use the custom tag instead of calling these patterns directly!
//    validDatePat - validates proper date format, if populated (e.g. mm/dd/yyyy)
//    validReqDatePat - verifies and validates proper date format (e.g. mm/dd/yyyy)

//------------------------------------------------------------------------------------------------------------------------------
//VALIDATORCHRS: (numeric) the maximum length allowed for the field to be validated
//------------------------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------------------------------
//VALIDATORNAME: (string) the name of the field displayed to the user, in the event of a validation error
//------------------------------------------------------------------------------------------------------------------------------

//Examples:

//email validation
//<input type="text" name="yourName" VALIDATOR="emailPat" VALIDATORCHRS="100" VALIDATORNAME="Your Title">

//non-required text
//<textarea name="yourName" VALIDATORCHRS="1500" VALIDATOR="validNonReqTextPat"></textarea>

//radio button collection (NOTE: the radio button/checkbox validator should only be placed in the first tag of the collection!)
//<input type="radio" name="yourName" value="1" VALIDATOR="validRadioBoxPat" VALIDATORNAME="Your Title">
//<input type="radio" name="yourName" value="2">
//<input type="radio" name="yourName" value="3">

//*************************************************************************

alertColor="EFF15C";

//------------------------------------------------------------------------------------------------------------------------------
function validate(objForm) {

	clearBG(objForm);
	var PatternsDict = new Object();
	PatternsDict.zipPat = /\d{5}(-\d{4})?/;
	PatternsDict.emailPat = /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/;
	PatternsDict.notEmptyPat = /.{1,}/;
	PatternsDict.numberPat = /\d/;
	PatternsDict.pwPat = /^\D{1}\S{5,11}$/;
	PatternsDict.currencyPat = /\$\d{1,3}(,\d{3})*\.\d{2}/;
	PatternsDict.timePat = /^([1-9]|1[0-2]):[0-5]\d$/;
	
	var errStr = '';
	var errChrLimitStr = '';
	var v, thePat, gotIt, vName, vLength, readName, readChrLimitName;
	var elArr = objForm.elements;

	//Trim any unecessary extra spaces
	for (var i=0;i<elArr.length;i++)
	with (elArr[i]) { 
		v = elArr[i].getAttribute("VALIDATOR");
		if (!v) continue;

		elArr[i].value = trimInput(elArr[i].value);
	}

	for (var i=0; i<elArr.length; i++)
	with (elArr[i]) { 
		v = elArr[i].getAttribute("VALIDATOR");
		if (!v) continue; 

		if ((String(v) == "validReqDatePat")) {
			//Check for valid dates -------------------------------------------------------------------------------------------------------------------
			gotIt = isDate(elArr[i].value, 'MM/dd/yyyy');
		} else if ((String(v) == "validDatePat")) {
			//Check for valid dates only if populated -------------------------------------------------------------------------------------------
			if (elArr[i].value.length > 0) {gotIt = isDate(elArr[i].value, 'MM/dd/yyyy');} else {gotIt = true;}
		} else if ((String(v) == "validRadioBoxPat")) {
			//Check if a radio or checkbox option is checked --------------------------------------------------------------------------------
			var groupString = String(elArr[i].getAttribute("name"));
			var groupName = eval("document."+String(objForm.name)+"."+groupString);
			var checkedItem = -1;

			if (!groupName.length) {
				if (groupName.checked) {checkedItem = 0;}
			} else {
				for (var x=0;x<groupName.length;x++) {if (groupName[x].checked) {checkedItem = x;}}
			}

			if (checkedItem > -1) {gotIt = true;} else {gotIt = false;}
		} else if ((String(v) == "validNonReqTextPat")) {
			//Validate text that is not required --------------------------------------------------------------------------------------------------
			gotIt = true;
		} else {
			//Check for required patterns ----------------------------------------------------------------------------------------------------------
			thePat = PatternsDict[v];
			gotIt = thePat.exec(value); 
		}

		if (!gotIt) {
			vName = elArr[i].getAttribute("VALIDATORNAME");
			setElementBG(elArr[i],alertColor);

			if (!vName)
				readName = replace(name, "_", " ");
			else
				readName = vName;
				errStr = errStr + "\n\t" + readName;
		}
	}
	
	//Check for character lengths
	for (var i=0; i<elArr.length; i++)
	with (elArr[i]) { 
		v = elArr[i].getAttribute("VALIDATORCHRS");
		if (!v) continue; 
		
		vLength = elArr[i].value.length;

		if (vLength > v) {
			vName = elArr[i].getAttribute("VALIDATORNAME");
			setElementBG(elArr[i],alertColor);

			if (!vName)
				readName = replace(name, "_", " ") + " - Maximum characters: " + v + "; Current character count: " + vLength;
			else
				readName = vName + " - Maximum characters: " + v + "; Current character count: " + vLength;
				errStr = errStr + "\n\t" + readName;
				//alert(v + "\n" + errStr + "\n" + vLength);
		}
	}

	if (errStr) {
		var returnStr = "The form cannot be submitted.  The following fields are not valid:\n" + errStr + "\n\nPlease update the above field(s) and try again.";
		alert(returnStr);
		elArr[1].focus();
		return false;
	} else {
		return true;		
	}
}

//------------------------------------------------------------------------------------------------------------------------------
function replace(haystack, oldNeedle, newNeedle) {
	i = haystack.indexOf(oldNeedle);
	r = "";
	if (i == -1) return haystack;
	r += haystack.substring(0,i) + newNeedle;
	if (i + oldNeedle.length < haystack.length)
		r += replace(haystack.substring(i + oldNeedle.length, haystack.length), oldNeedle, newNeedle);
	return r;
}

//------------------------------------------------------------------------------------------------------------------------------
function clearBG(theForm) {
	for (i=0; i<theForm.elements.length; i++) {
		if ((theForm.elements[i].type == "text") || 
			(theForm.elements[i].type == "textarea") ||
			(theForm.elements[i].type == "select-one")) {
			theForm.elements[i].style.background = '#FFFFFF';
		}
	}
}

//------------------------------------------------------------------------------------------------------------------------------
function setElementBG(formElement,theColor) {
	if (String(formElement.type) != "radio" && String(formElement.type) != "checkbox") {formElement.style.background = "#"+theColor;}
}

//------------------------------------------------------------------------------------------------------------------------------
function trimInput(theString) {
	if (typeof theString != "string") {return theString;}
	
	var retValue = theString;
	var ch = retValue.substring(0, 1);
	
	while (ch == " ") { // check for spaces at the beginning of the string
		retValue = retValue.substring(1, retValue.length);
		ch = retValue.substring(0, 1);
	}
	
	ch = retValue.substring(retValue.length-1, retValue.length);
	
	while (ch == " ") { // check for spaces at the end of the string
		retValue = retValue.substring(0, retValue.length-1);
		ch = retValue.substring(retValue.length-1, retValue.length);
	}
	
	while (retValue.indexOf("  ") != -1) { // look for amd trim multiple spaces within the string
		retValue = retValue.substring(0, retValue.indexOf("  ")) + retValue.substring(retValue.indexOf("  ")+1, retValue.length);
	}
	
	//----------------------------------------------  check for returns at the beginning of the string and remove (IE)
	while (retValue.indexOf("\r") == 0) {
		retValue = escape(retValue);
		retValue = retValue.replace("%0D%0A", "");
		retValue = unescape(retValue);
	}
	
	//----------------------------------------------  check for returns at the beginning of the string and remove (Mozilla)
	retValue = escape(retValue);
	
	while (String(retValue.substring(0,3)) == "%0A") { 
		retValue = retValue.replace("%0A", "");
	}
	
	retValue = unescape(retValue);
	return retValue;
}



