// ----------------------------------------------------------------------
// Javascript form validation routines.
// ORIGINAL Author: Stephen Poley
// HEAVY ADDITIONS AND MODS : Keith Savoie (Leopard Inc. www.leopard-inc.com)
// Simple routines to quickly pick up obvious typos.
// All validation routines return true if executed by an older browser:
// in this case validation must be left to the server.
// ----------------------------------------------------------------------

var nbsp = 160;    // non-breaking space char
var node_text = 3; // DOM text node-type
emptyString = /^\s*$/

// -----------------------------------------
//                  trim
// Trim leading/trailing whitespace off string
// -----------------------------------------
function trim(str)
{
	return str.replace(/^\s+|\s+$/g, '');
};

// -----------------------------------------
//                  msg
// Display warn/error message in HTML element
// commonCheck routine must have previously been called
// -----------------------------------------
function msg(fld,     // id of element to display message in
             msgtype, // class to give element ("warn" or "error")
             message) // string to display
{
  // setting an empty string can give problems if later set to a 
  // non-empty string, so ensure a space present. (For Mozilla and Opera one could 
  // simply use a space, but IE demands something more, like a non-breaking space.)
  var dispmessage;
  if (emptyString.test(message)) 
    dispmessage = String.fromCharCode(nbsp);    
  else  
    dispmessage = message;

  var elem = document.getElementById(fld);
  elem.firstChild.nodeValue = dispmessage;  
  
  elem.className = msgtype;
};

// -----------------------------------------
//            commonCheck
// Common code for all validation routines to:
// (a) check for older / less-equipped browsers
// (b) check if empty fields are required
// Returns true (validation passed), 
//         false (validation failed) or 
//         proceed (don't know yet)
// -----------------------------------------
var proceed = 2;  

function commonCheck(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         reqd)   // true if required
{
  if (!document.getElementById) 
    return true;  // not available on this browser - leave validation to the server
  var elem = document.getElementById(ifld);
  if (!elem.firstChild)
    return true;  // not available on this browser 
  if (elem.firstChild.nodeType != node_text)
    return true;  // ifld is wrong type of node  

  if (emptyString.test(vfld.value)) {
    if (reqd) {
      msg (ifld, "error", " :required");  
      vfld.focus();
      return false;
    }
    else {
      msg (ifld, "warn", "");   // OK
      return true;  
    }
  }
  return proceed;
};

// -----------------------------------------
//            validateDropDown
// Validates that current selection doesn't match passed index
// Returns true if so
// -----------------------------------------
function validateDropDown(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         notIdx)   // index # we do not want value to equal
{
	if (!document.getElementById)
		return true;  // not available on this browser - leave validation to the server
		
  	var elem = document.getElementById(ifld);
	if (!elem.firstChild)
		return true;  // not available on this browser
		
	if (elem.firstChild.nodeType != node_text)
		return true;  // ifld is wrong type of node  
		
	for (var i=0; i<vfld.length; i++) {
		if (vfld.options[i].selected) {
			if (vfld.options[i].value == notIdx) { // selected option = notIdx
				msg (ifld, "error", " :invalid selection");  
				vfld.focus();
				return false;
				}
			else {
				msg (ifld, "warn", "");   // everything OK
				return true;
				}
			}
		}
	return true;
};

// -----------------------------------------
//            displayMSGonchange
// Displays message if select is changed
// Returns true if so
// -----------------------------------------
function displayMSGonchange(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         notIdx, // index # we do not want the message to display on
						 elmMsg,  // message to be displayed if element ID doesn't match passed ID
						popMsg)  // message to be popped before execution 
{
	var popConfirm
	
	if (popMsg > '') {
		popConfirm = confirm(popMsg)
		}
	else {
		popConfirm = true
	}
	if (popConfirm == true) {
		if (!document.getElementById)
			return true;  // not available on this browser - leave validation to the server
			
		var elem = document.getElementById(ifld);
		if (!elem.firstChild)
			return true;  // not available on this browser
			
		if (elem.firstChild.nodeType != node_text)
			return true;  // ifld is wrong type of node  
			
		for (var i=0; i<vfld.length; i++) {
			if (vfld.options[i].selected) {
				if (vfld.options[i].value != notIdx) { // selected option = notIdx
					msg (ifld, "error", " :" && elmMsg);  
					vfld.focus();
					return false;
					}
				else {
					msg (ifld, "warn", "");   // everything OK
					return true;
					}
				}
			}
		return true;
		}
	else {
		
		for (var i=0; i<vfld.length; i++) {
			if (vfld.options[i].value == notIdx) { // selected option = notIdx
				vfld.options[i].selected = true;
				}
			}
		return false;
		}
};

// -----------------------------------------
//            validateDateBuild
// Builds the passed fields into a date string then Validates if it is a true date
// Returns true if so
// -----------------------------------------

/** DHTML date validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */
// Declaring valid date character, minimum year and maximum year
var dtCh= "/";
var minYear=1900;
var maxYear=2100;
	
function isInteger(s){
	var i;
	for (i = 0; i < s.length; i++){   
		// Check that current character is number.
		var c = s.charAt(i);
		if (((c < "0") || (c > "9"))) return false;
	}
	// All characters are numbers.
	return true;
};
	
function stripCharsInBag(s, bag){
	var i;
	var returnString = "";
	// Search through string's characters one by one.
	// If character is not in bag, append to returnString.
	for (i = 0; i < s.length; i++){   
		var c = s.charAt(i);
		if (bag.indexOf(c) == -1) returnString += c;
	}
	return returnString;
};
	
function daysInFebruary (year){
	// February has 29 days in any year evenly divisible by four,
	// EXCEPT for centurial years which are not also divisible by 400.
	return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
};
	
function DaysArray(n) {
	for (var i = 1; i <= n; i++) {
		this[i] = 31
		if (i==4 || i==6 || i==9 || i==11) {this[i] = 30}
		if (i==2) {this[i] = 29}
   } 
   return this
};

function validatePullDownDateBuild(Dfld, // day field
									Mfld, // month field
									Yfld,	// year field
						  			ifld) // id of element to receive info/error msg
{
	if (!document.getElementById)
		return true;  // not available on this browser - leave validation to the server
		
  	var elemD = document.getElementById(Dfld);
	if (!elemD.firstChild)
		return true;  // not available on this browser
	if (elemD.firstChild.nodeType != node_text)
		return true;  // ifld is wrong type of node 
	var elemM = document.getElementById(Mfld);
	if (!elemM.firstChild)
		return true;  // not available on this browser
	if (elemM.firstChild.nodeType != node_text)
		return true;  // ifld is wrong type of node 
	var elemY = document.getElementById(Yfld);
	if (!elemY.firstChild)
		return true;  // not available on this browser
	if (elemY.firstChild.nodeType != node_text)
		return true;  // ifld is wrong type of node 	

	var dtStr = (elemM.value + '/' + elemD.value + '/' + elemY.value)
	var daysInMonth = DaysArray(12)
	var pos1=dtStr.indexOf(dtCh)
	var pos2=dtStr.indexOf(dtCh,pos1+1)
	var strMonth=dtStr.substring(0,pos1)
	var strDay=dtStr.substring(pos1+1,pos2)
	var strYear=dtStr.substring(pos2+1)
	strYr=strYear
	if (strDay.charAt(0)=="0" && strDay.length>1) strDay=strDay.substring(1)
	if (strMonth.charAt(0)=="0" && strMonth.length>1) strMonth=strMonth.substring(1)
	for (var i = 1; i <= 3; i++) {
		if (strYr.charAt(0)=="0" && strYr.length>1) strYr=strYr.substring(1)
	}
	month=parseInt(strMonth)
	day=parseInt(strDay)
	year=parseInt(strYr)
	if (pos1==-1 || pos2==-1){
		msg (ifld, "error", " :invalid format, mm/dd/yyyy");  
		return false
	}
	if (strMonth.length<1 || month<1 || month>12){
		msg (ifld, "error", " :invalid month");  
		alert("")
		return false
	}
	if (strDay.length<1 || day<1 || day>31 || (month==2 && day>daysInFebruary(year)) || day > daysInMonth[month]){
		msg (ifld, "error", " :invalid day");  
		return false
	}
	if (strYear.length != 4 || year==0 || year<minYear || year>maxYear){
		msg (ifld, "error", " :invalid year, 4 digits-between "+minYear+"-"+maxYear);  
		return false
	}
	if (dtStr.indexOf(dtCh,pos2+1)!=-1 || isInteger(stripCharsInBag(dtStr, dtCh))==false){
		msg (ifld, "error", " :invalid date");  
		return false
	}
	msg (ifld, "warn", "");   // everything OK
	return true;
};

// -----------------------------------------
//            populateDaySelect
// Dynamically populates a select field with the appropriate 
// day values based on the supplied month and year
// -----------------------------------------
function populateDaySelect(Mfld, // field name of month select box
							 Dfld, // field name of day select box (this drop-down gets updated with new values based upon the month/year selections.
							 Yfld, // field name of year select box
							 selectDayValue) // current day value, this is the current selected value of the day select box that the script compares against, 
							 				// if the new month does not contain this day value it defaults the day to 1 
{
	var elemD = document.getElementById(Dfld);
	if (!elemD.firstChild)
		return true;  // not available on this browser
	var elemM = document.getElementById(Mfld);
	if (!elemM.firstChild)
		return true;  // not available on this browser
	var elemY = document.getElementById(Yfld);
	if (!elemY.firstChild)
		return true;  // not available on this browser
	
	timeA = new Date(elemY.options[elemY.selectedIndex].text, elemM.options[elemM.selectedIndex].value,1);
	timeDifference = timeA - 86400000;
	timeB = new Date(timeDifference);
	var daysInMonth = timeB.getDate();
	var dayValue = 0;
	for (var i = 0; i < elemD.length; i++) {
		elemD.options[0] = null;
		}
	for (var i = 0; i < daysInMonth; i++) {
		dayValue = (i + 1)
		if (dayValue < 10) {
			dayValue = "0" + (dayValue += '');
			}
		else {
			dayValue = (dayValue += '')
			}
		elemD.options[i] = new Option(i+1,dayValue);
		if (elemD.options[i].value == selectDayValue) {
			elemD.options[i].selected = true;
			}
		}
};

// -----------------------------------------
//            validatePresent
// Validate if something has been entered
// Returns true if so 
// -----------------------------------------
function validatePresent(vfld,   // element to be validated
                         ifld)  // id of element to receive info/error msg
{
  var stat = commonCheck (vfld, ifld, true);
  if (stat != proceed) return stat;

  msg (ifld, "warn", "");  
  return true;
};

// -----------------------------------------
//            popMessageOnCheck
// Validate if something has been entered
// Returns true if so 
// -----------------------------------------
function popMessageOnCheck(elem, // name of check box/radio to check 
						   elmMsg) // mesage to be displayed
{
	var confirmationStatus
	if (elem.checked == true) {
		confirmationStatus = confirm(elmMsg);
		if (confirmationStatus == false) { 
			elem.checked = false;
			} 
		}
};

// -----------------------------------------
//               clearAlertMsgs
// Clears out the contnet of the msg fields
// -----------------------------------------
function clearAlertMsgs(ifld // contains a tilde(~) dilimited string of msg_fields to be cleared
						)
{
	var arrifld = ifld.split("~");
	for (var i = 0; i <= (arrifld.length-1); i++) {
		msg(arrifld[i], "", "");
		}
};

// -----------------------------------------
//               validateEmail
// Validate if e-mail address
// Returns true if so (and also if could not be executed because of old browser)
// -----------------------------------------
function validateEmail(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         reqd)   // true if required
{
  var stat = commonCheck (vfld, ifld, reqd);
  if (stat != proceed) return stat;

  var tfld = trim(vfld.value);  // value of field with whitespace trimmed off
  var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/
  if (!email.test(tfld)) {
    msg (ifld, "error", " :verify format");
    vfld.focus();
    return false;
  }

  //var email2 = /^[A-Za-z][\w.-]+@\w[\w.-]+\.[\w.-]*[A-Za-z][A-Za-z]$/
  
  var email2 = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/
  
  if (!email2.test(tfld)) 
    msg (ifld, "warn", " :unusual format");
  else
    msg (ifld, "warn", "");
  return true;
};

// -----------------------------------------
//            clearDefaultValue
//   used with onclick to empty a field 
//   of a default value
// -----------------------------------------
function clearDefaultValue(formElement, // element to be validated
						   defaultValue) // the value of the original form element that will be cleared if in field
{ 
	if (formElement.value == defaultValue) {
		formElement.value = "";
	}
};

// -----------------------------------------
//           insertDefaultValue
//    used with onblur to reset an empty
//    field to a default value
// -----------------------------------------
function insertDefaultValue(formElement, // element to be validated
							defaultValue) // the value you want the field to equal if empty
{ 
	if (formElement.value == "") {
		formElement.value = defaultValue;
	}
};

// -----------------------------------------
//           verifyPosNumeric
//    used with onkeyup to verify
//    field is a positive numver
// -----------------------------------------
function verifyPosNumeric(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         reqd,	// true/false set number to 'defVal' if field is empty
						 defVal)  // the default value to use if reqd is true
{
	if (((reqd == true) && (vfld.value == ""))) {
		// set the field to a default value if left empty
		if (defVal > "") {
			vfld.value = defVal;
			}
		else {
			msg (ifld, "error", "required");
			}
		return false;
		}
		
	var stat = commonCheck (vfld, ifld, reqd);
	if (stat != proceed) return stat;

	var tfld = trim(vfld.value);  // value of field with whitespace trimmed off
		
	if 	(tfld > "") {
		if (isNaN(tfld)) {
			msg (ifld, "error", "not numeric");
			return false;
			}
		else if (tfld < 0) {
			msg (ifld, "error", "positive only");
			return false;
			}
		else if (parseInt(tfld) != parseFloat(tfld)) {
			msg (ifld, "error", "no decimals");
			return false;
			}
		else {
			msg (ifld, "warn", "");
			}
		}
	return true;
};

// -----------------------------------------
//            validateTelnr
// Validate telephone number
// Returns true if so (and also if could not be executed because of old browser)
// Permits spaces, hyphens, brackets and leading +
// -----------------------------------------
function validateTelnr(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         reqd, // true if required
						 defaultValue) // if field is populated with this default value skip validation   
{
	if (vfld.value != defaultValue) {
		var stat = commonCheck (vfld, ifld, reqd);
		if (stat != proceed) return stat;
	
		var tfld = trim(vfld.value);  // value of field with whitespace trimmed off
		var telnr = /^([\+]?\(?[\d]{3}\)?|[\d]{3}\-?)?[\d]{3}[\-]?[\d]{4}$/
		
		if (!telnr.test(tfld)) {
			msg (ifld, "error", " :verify format");
			vfld.focus();
			return false;
			}
		
		var numdigits = 0;
		for (var j=0; j<tfld.length; j++)
			if (tfld.charAt(j)>='0' && tfld.charAt(j)<='9') numdigits++;
			if (numdigits<6) {
				msg (ifld, "error", " :too short");
				vfld.focus();
				return false;
				}
	
			if (numdigits>14)
				msg (ifld, "warn", " :" + numdigits + " digits, verify");
			else { 
				if (numdigits<10)
					msg (ifld, "warn", " :" + numdigits + " digits, verify");
				else
					msg (ifld, "warn", "");
			}
		}
	else {
		msg (ifld, "warn", "");
	}
	return true;
};

// -----------------------------------------
//             validateAge
// Validate person's age
// Returns true if OK 
// -----------------------------------------
function validateAge(vfld,   // element to be validated
                         ifld,   // id of element to receive info/error msg
                         reqd)   // true if required
{
  var stat = commonCheck (vfld, ifld, reqd);
  if (stat != proceed) return stat;

  var tfld = trim(vfld.value);
  var ageRE = /^[0-9]{1,3}$/
  if (!ageRE.test(tfld)) {
    msg (ifld, "error", " :not a valid age");
    vfld.focus();
    return false;
  }

  if (tfld>=200) {
    msg (ifld, "error", " :not a valid age");
    vfld.focus();
    return false;
  }

  if (tfld>110) msg (ifld, "warn", "Older than 110: check correct");
  else {
    if (tfld<7) msg (ifld, "warn", "Bit young for this, aren't you?");
    else        msg (ifld, "warn", "");
  }
  return true;
};

// -----------------------------------------
//             limitTextArea
// limits the number of characters allowed in a text area
// -----------------------------------------
function limitTextArea(vfld, // textarea to be limited
					   fldCount, //  field indicating how many charcters left
					   limitNum) // maximum number of allowed characters
{
	if (vfld.value.length > limitNum) {
    	vfld.value = vfld.value.substring(0, limitNum);
        }
	else {
    	fldCount.value = limitNum - vfld.value.length;
	}
};

// -----------------------------------------
//             confirmCheckbox
// if checkbox is true confirms if user wants to check box
// -----------------------------------------
function confirmCheckbox(elm,message) {
	var onfirmationStatus
	if (elm.checked == true) {
		confirmationStatus = confirm(message);
		if (confirmationStatus == false) { 
			elm.checked = false;
			}
		else {
			elm.checked = true;
			}
		}
};