/***********************************
* FILE:    FormValidation.js       *
* AUTHOR:  Lance E. Leonard        *
* DATE:    01/03/2001              *
* EMAIL:   solarfrog@earthlink.net *
***********************************/

/*
DESCRIPTION:
This file contains a library of functions used for form validation utilizing
Javascript Regular Expressions.


USAGE:
 


FUNCTIONS:
validateUSDate - checks for valid date in US format
validateTime - checks for valid 12 hour time
validateUSPhone - checks for a valid US phone number
validateEmail - checks for a valid email address
validateSSN - checks for a valid social security number
validateNumeric - checks for a numeric value
validateUSZip - checks for valid US postal code
validateNotEmpty - checks for an empty form field

trimAll - trim all white space

formatUSPhone - formats Phone Number to (###) ###-####

*/

/***********************************
* FILE:    FormValidation.js       *
* AUTHOR:  Eric Black              *
* APPEND DATE:    01/27/2003       *
* EMAIL:   eric.black@aecio.com    *
***********************************/

/*
DESCRIPTION:
Added prototype to String objects, allowing use of trim method.
Added use of trim method for valid email checking.
Added checkRequired function.

USAGE:
trim() method: Trim leading and trailing spaces only from string values as a method
of the string object. 
	Example: 
			var str = "   test   "
			str = str.trim()
			[yields: str = "test"]

checkRequired function: cycles through all of the controls on the form passed 
to it as a variable, looking for name starting with "req_". With textboxes and 
textareas, the function trims the value and verifies that the value is not an
empty string. With select controls, the function verifies that the selected 
value does not equal "0".
MODIFIED (EB 4/14/2003): 
With select controls, the function verifies that the selected value does not equal "-1".
Now does not use the control.name == "req_...". Since we are writing all of the names
 of required controls to a client-side array, simply check to see if the control name
 exists within the array list.
*/


/***********************************
* FILE:    FormValidation.js       *
* AUTHOR:  Eric Black              *
* APPEND DATE:    02/10/2003       *
* EMAIL:   eric.black@aecio.com    *
***********************************/

/*
DESCRIPTION:
Added page-level variable to flag individual form validation errors caused on the 
control onBlur events. The form-level checkRequired will check this value before 
attempting to submit.

USAGE:
Each of the individual controls fires a data validation check based on its expected
input. If it fails, it will set a page-level flag. Prior to submitting the form, all
required fields are checked for a value. Even if that value is invalid, the page could 
submit. By checking the value of the page-level flag, these errors can be avoided. 
*/


/***********************************
* FILE:    FormValidation.js       *
* AUTHOR:  Eric Black              *
* APPEND DATE:    04/11/2003       *
* EMAIL:   eric.black@aecio.com    *
***********************************/

/*
DESCRIPTION:
Added TrimForm function.
TrimForm receives an HTML form as an input parameter. The function loops through all of the
controls on the form and trims leading and trailing spaces off of the values entered in 
every textbox, textarea, and hidden control.
USAGE:
Any data entry form that has text-based controls and you do not want leading or trailing
spaces on the values being entered.


DESCRIPTION:
Added ClearForm function.
ClearForm receives an HTML form as an input parameter. The function loops through all of the
controls on the form and nulls the values entered in every textbox, textarea, and hidden 
control.
USAGE:
Any data entry form that has text-based controls and you want to empty the form, not just 
reset it to its default state.


DESCRIPTION:
Added IsEmpty function. IsEmpty received an HTML form as an input parameter. The function 
loops through all of the controls on the form and checks for a value length > 0 for any 
control of type text or textarea. Returns true if no controls have a value. 
USAGE:
Should be used in conjuction with TrimForm. Intended use for Search Forms when an empty 
search could return excessive amounts of data. Also for small forms where every field is 
text-based and required (login forms) for empty content validation. 
*/


function trim() {
  // Remove leading spaces
  var s = this.replace(/^\s+/g, "")
 
  // Remove trailing spaces
  s = s.replace(/\s+$/g, "")
  return s
}
 
// Assign this function to all strings
String.prototype.trim = trim



function validateUSDate(value) {
   var objRegExp = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/
 
   //check to see if in correct format
   if(!objRegExp.test(value)) {
      return false; //doesn't match pattern, bad date
   } else {
      var arrayDate = value.split(RegExp.$1); //split date into month, day, year
      var intDay = parseInt(arrayDate[1],10); 
      var intYear = parseInt(arrayDate[2],10);
      var intMonth = parseInt(arrayDate[0],10);
	
      //check for valid month
      if(intMonth > 12 || intMonth < 1) {
         return false;
      }
	
      //create a lookup for months not equal to Feb.
      var arrayLookup = { '01' : 31,'03' : 31, '04' : 30,'05' : 31,'06' : 30,'07' : 31,
                          '08' : 31,'09' : 30,'10' : 31,'11' : 30,'12' : 31}
  
      //check if month value and day value agree
      if(arrayLookup[arrayDate[0]] != null) {
         if(intDay <= arrayLookup[arrayDate[0]] && intDay != 0) {
            return true; //found in lookup table, good date
         }
      }
		
      //check for February
      var booLeapYear = (intYear % 4 == 0 && (intYear % 100 != 0 || intYear % 400 == 0));

      if( ((booLeapYear && intDay <= 29) || (!booLeapYear && intDay <=28)) && intDay !=0) {
         return true; //Feb. had valid number of days
      }
   }

   return false; //any other values, bad date
}

function validateTime(value) {
   var objRegExp = /^([1-9]|1[0-2]):[0-5]\d(:[0-5]\d(\.\d{1,3})?)?$/;

   return objRegExp.test(value );
}

function validateUSPhone(value) {
   var objRegExp  = /^\([1-9]\d{2}\)\s?(\d{3})\-(\d{4})$/;
   
   return objRegExp.test(value); 
}

function validateUSZip(value) {
   var objRegExp  = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
 
   return objRegExp.test(value);
}

function validateEmail(value) {
   var objRegExp  = /^[a-z0-9]([a-z0-9_\-\.\']*)@([a-z0-9_\-\.]*)(\.[a-z]{2,4}(\.[a-z]{2}){0,2})$/i;

   return objRegExp.test(value);
}

function validateSSN(value) {
   var objRegExp  = /^\d{3}\-\d{2}\-\d{4}$/;
 
   return objRegExp.test(value);
}

function validateNumeric(value) {
   var objRegExp  =  /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/; 
 
   return objRegExp.test(value);
}

function validateInteger(value) {
   var objRegExp  = /(^-?\d\d*$)/;
 
   return objRegExp.test(value);
}

function validateNotEmpty(value) {
   var strTemp = value;
   strTemp = trimAll(strTemp);

   if(strTemp.length > 0){
      return true;
   }  

   return false;
}

function checkUSDate(objDate){
  var strDate = objDate.value; 

  if (validateNotEmpty(strDate)) {
    if (!validateUSDate(strDate)) {
      alert('Please enter a valid date in the format MM/DD/YYYY.');
      objDate.focus();
    }
  }
}

function checkEmail(objEmail) {
  objEmail.value = objEmail.value.trim();
  var strEmail = objEmail.value;

  if (validateNotEmpty(strEmail)) {
    if (!validateEmail(strEmail)) {
      alert('Please enter a valid email address.');
      objEmail.focus();
    }
  }
}

function checkNumeric(objField) {

  var strValue = objField.value;
  
  if (validateNotEmpty(strValue)) {
    if (!validateNumeric(strValue)) {
      alert('Please enter a valid numeric value.');
      objField.focus();
    }
  }
}

//-------------------------------------//
var arrReqLabels = new Array();
var arrReqFields = new Array();
var intCountReqFields = 0;

function addRequired(strLabel,strName) {
	arrReqLabels[intCountReqFields] = strLabel;
	arrReqFields[intCountReqFields] = strName;
	intCountReqFields = intCountReqFields + 1;
}
//-------------------------------------//

function checkRequired(form) {
	var objCtl;
	var reqErr = "";
	for (var i=0; i<form.elements.length; i++) {

		if ( (!(form.elements[i].readonly)) && (!(form.elements[i].disabled)) && (!(form.elements[i].type=="hidden")) ) {

			if ((form.elements[i].type=="text")||(form.elements[i].type=="hidden")||(form.elements[i].type=="password")||(form.elements[i].type=="textarea")) {
				form.elements[i].value = form.elements[i].value.trim();
				if (form.elements[i].value == "") {
					for(var j=0; j<intCountReqFields; j++) {
						if(form.elements[i].name==arrReqFields[j]) {
							if ((reqErr=="") || (objCtl==null)) {
								if ( (!(form.elements[i].readonly)) && (!(form.elements[i].disabled)) && (!(form.elements[i].type=="hidden")) ) {
									objCtl = form.elements[i];
								} else {
									//loop starting with current element (var j=i)
									//check for ability to set focus
									//first time we can, set focus to that element
									objCtl = form.elements[i+1];
								}
							}
							reqErr = reqErr + "\n" + arrReqLabels[j];
							break;
						}
					}
				}
			}
			if ((form.elements[i].type.substr(0,6)=="select")&&(!(form.elements[i].multiple))) {
				if (form.elements[i].options[form.elements[i].selectedIndex].value=="-1") {
					for(var j=0; j<intCountReqFields;j++) {
						if(form.elements[i].name==arrReqFields[j]) {
							if ((reqErr=="") || (objCtl==null)) {
								if ( (!(form.elements[i].readonly)) && (!(form.elements[i].disabled)) && (!(form.elements[i].type=="hidden")) ) {
									objCtl = form.elements[i];
								} else {
									objCtl = form.elements[i+1];
								}
							}
							reqErr = reqErr + "\n" + arrReqLabels[j];
						}
					}
				}
			}
		}
	}
	if (reqErr!="") {
		reqErr = "The following required fields have been left blank.\nPlease enter appropriate values in each of these fields:\n" + reqErr
		alert(reqErr);
		if(objCtl!=null) {
			objCtl.focus();
		}
		return false;
	} else {
		//alert("all clear");
		return true;
	}
}


function trimAll( strValue ) {
   var objRegExp = /^(\s*)$/;

   //check for all spaces
   if(objRegExp.test(strValue)) {
      strValue = strValue.replace(objRegExp, '');
      if( strValue.length == 0) {
         return strValue;
       }
   }
    
   //check for leading & trailing spaces
   objRegExp = /^(\s*)([\W\w]*)(\b\s*$)/;
   if(objRegExp.test(strValue)) {
      //remove leading and trailing whitespace characters
      strValue = strValue.replace(objRegExp, '$2');
   }
   return strValue;
}

function formatUSPhone(el,required) {
   var phNumber = el.value;
   var pre = "";
   var area = "";
   var trunk = "";
   var post = "";
   var error = 0;
   var specialChars = "() -.";

   if (required == 1) {
	  if (phNumber.length == 0) {
	     error = 1;
	  }
   }
  
   
   //remove formatting characters
   for (i=0; i < phNumber.length; i++) {
      var phChar = phNumber.charAt(i);
      for (j=0; j < specialChars.length; j++) {
         if (phChar == specialChars.charAt(j)) {
            before = phNumber.substring(0,i);
            after = phNumber.substring(i+1);
            phNumber = before + after;
            i--;
         }
      }
   }

   //make sure number is numeric
   for (i=0; i < phNumber.length; i++) {
      if (parseInt(phNumber.charAt(i)) + "" == Number.NaN + "") {
         error = 1;
      }
   }
   
   //format phone number to standard US Phone
   if (phNumber.length == 11) {
      pre = phNumber.substring(0,1);
      area = phNumber.substring(1,4);
      trunk = phNumber.substring(4,7);
      post = phNumber.substring(7);
   } else if (phNumber.length == 10) {
      area = phNumber.substring(0,3);
      trunk = phNumber.substring(3,6);
      post = phNumber.substring(6);
   } else if (phNumber.length == 7) {
      trunk = phNumber.substring(0,3);
      post = phNumber.substring(3);
   } else if (phNumber.length == 0) {
   } else {
      error = 1;
   }
    
   if (error == 1) {
      alert('Please enter a valid phone number.');
      el.focus();
      return false;
   }
    
   if (pre != "") {
      formattedNumber = pre + " (" + area + ") " + trunk + "-" + post;
   } else if (area != "") { 
      formattedNumber = "(" + area + ") " + trunk + "-" + post;
   } else if (trunk != "") {
      formattedNumber = trunk + "-" + post;
   } else {
      formattedNumber = "";
   }
   
   el.value = formattedNumber;
   return true;
}


function trimForm(form) {
	for (var i=0; i<form.elements.length; i++) {
		if ((form.elements[i].type=="text")||(form.elements[i].type=="hidden")||(form.elements[i].type=="textarea")) {
			form.elements[i].value = form.elements[i].value.trim();
		}
	}
}

function ClearForm(frm) {
	for (var i=0; i<frm.elements.length; i++) {
		if ( (frm.elements[i].type=="text") || (frm.elements[i].type=="textarea") || (frm.elements[i].type=="hidden") ) {
			frm.elements[i].value = "";
		}
	}
}

function ZeroCombos(frm) {
	for (var i=0; i<frm.elements.length; i++) {
		if (frm.elements[i].type.substr(0,6)=="select") {
			frm.elements[i].selectedIndex = 0;
		}
	}
}

function IsEmpty(form) {
	var empty = true;
	for (var i=0; i<form.elements.length; i++) {
		if ((form.elements[i].type=="text")||(form.elements[i].type=="textarea")) {
			form.elements[i].value = form.elements[i].value.trim();
			if (form.elements[i].value.length>0) {
				empty = false;
			}
		}
	}
	return empty;
}


function GotoPage(PageId, SortBy, MaxVal) {
	if (PageId=="") {
		alert("You must specify a page number.");
		return false;
	}
	if (isNaN(PageId)) {
		alert("The requested page number must be numeric.");
		return false;
	} else {
		if ((parseInt(PageId,10)>MaxVal)||(parseInt(PageId,10)<1)) {
			alert("The requested page number does not exist.");
			return false;
		} else {
			PageId = PageId.toString(10);
			return true;
		}
	}
}


function CloseChildWin(reloadParent) {
//If a window has been opened as a child window, can use this function to close it
//and set focus to the parent. Optionally, can reload parent.
	window.close();
	window.opener.focus();
	if (reloadParent==true) {
		window.opener.location.href = window.opener.location.href;
	}
}

function EnterPage(event,search) {
//Trap Enter Key on pages with forms to process as needed.
//This function is specifically designed for pages with multiple needs for the Enter
//key. In particular, a page with a search form (search=true) and a simple method
//to navigate multiple pages of search results (search=false).
	if (event.srcElement.tagName=="A") {
		return 0;
	}
	var code = 0;
	if (document.layers) {
		code = event.which;
	} else {
		code = event.keyCode;
	}
	if (code==13) {
		if (search) {
			return 1;
		} else {
			return 2;
		}
	} else {
		return 0;
	}
}

function checkEnter(event) {
//Trap Enter Key on pages with forms to process as needed.
//Calling page requires call to this function in the page's BODY tag, OnKeyPress event.
//Calling page required a doEnter() function which performs the requested function.
	if (event.srcElement.tagName=="A") {
		return;
	}
	var code = 0;
	if (document.layers) {
		code = event.which;
	} else {
		code = event.keyCode;
	}
	if (code==13) doEnter();
}


function compareDates(startDate, endDate){
	var startDateUTC, startDateUTC
	
	startDateUTC = new Date()
	
	startDateUTC.setUTCFullYear(startDate.substring(6, 10))
	startDateUTC.setUTCMonth(startDate.substring(0, 2)-1)
	startDateUTC.setUTCDate(startDate.substring(3, 5))
	
	endDateUTC = new Date()
	
	endDateUTC.setUTCFullYear(endDate.substring(6, 10))
	endDateUTC.setUTCMonth(endDate.substring(0, 2)-1)
	endDateUTC.setUTCDate(endDate.substring(3, 5))
	
	if (endDateUTC < startDateUTC)
		return false
	else
		return true
}


function checkDecimals(objNumber) {
	decallowed = 2;  // how many decimals are allowed?
	if (isNaN(objNumber.value) || objNumber.value == "") {
		alert("That does not appear to be a valid number. Please try again.");
		objNumber.select();
		objNumber.focus();
	} else {
		if (objNumber.value.indexOf('.') == -1) objNumber.value += ".";
		dectext = objNumber.value.substring(objNumber.value.indexOf('.')+1, objNumber.value.length);
		if (dectext.length > decallowed)
		{
			alert ("Please enter a valid number with up to " + decallowed + " decimal places.  Please try again.");
			objNumber.select();
			objNumber.focus();
		}
	}
}
