// ----------------------------------------------------------------------
// Javascript form validation routines.
// Author: Stephen Poley
//
// 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.
//
// Update Jun 2005: discovered that reason IE wasn't setting focus was
// due to an IE timing bug. Added 0.1 sec delay to fix.
//
// Update Oct 2005: minor tidy-up: unused parameter removed
//
// Update Jun 2006: minor improvements to variable names and layout
// ----------------------------------------------------------------------

var nbsp = 160;		// non-breaking space char
var node_text = 3;	// DOM text node-type
var emptyString = /^\s*$/ ;
var global_valfield;	// retain valfield for timer thread

// --------------------------------------------
//                  trim
// Trim leading/trailing whitespace off string
// --------------------------------------------

function trim(str)
{
  return str.replace(/^\s+|\s+$/g, '');
}


// --------------------------------------------
//                  setfocus
// Delayed focus setting to get around IE bug
// --------------------------------------------

function setFocusDelayed()
{
  	try
  	{
  		global_valfield.focus();
	}
	catch(e)
	{}//do nothing
 	
}

function setfocus(valfield)
{
  // save valfield in global variable so value retained when routine exits
  global_valfield = valfield;
 
  setTimeout( 'setFocusDelayed()', 100 );
}


// --------------------------------------------
//                  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);
  try {
  elem.firstChild.nodeValue = dispmessage;  
  
  elem.className = msgtype;   // set the CSS class to adjust appearance of message
  }
  catch(e){}
}

// --------------------------------------------
//            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    (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  if (!document.getElementById) 
    return true;  // not available on this browser - leave validation to the server
  var elem = document.getElementById(infofield);
 
  if (!elem.firstChild) return true;  // not available on this browser 
  if (elem.firstChild.nodeType != node_text) return true;  // infofield is wrong type of node  

  if (emptyString.test(valfield.value)) {
    if (required) {
      msg (infofield, "error", "*");  
      setfocus(valfield);
      return false;
    }
    else {
      msg (infofield, "warn", "");   // OK
      return true;  
    }
  }
  return proceed;
}

// --------------------------------------------
//            validatePresent
// Validate if something has been entered
// Returns true if so 
// --------------------------------------------

function validatePresent(valfield,   // element to be validated
                         infofield ) // id of element to receive info/error msg
{
  var stat = commonCheck (valfield, infofield, true);
  if (stat != proceed) return stat;

  //msg (infofield, "warn", ""); 
  msg (infofield, "valid", "");  
  return true;
}

// --------------------------------------------
//               validateEmail
// Validate if e-mail address
// Returns true if so (and also if could not be executed because of old browser)
// --------------------------------------------

function validateEmail  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;
 

  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/  ;
  if (!email.test(tfld)) {
    msg (infofield, "error", "*");
    setfocus(valfield);
    return false;
  }

  var email2 = /^[A-Za-z][\w.-]+@\w[\w.-]+\.[\w.-]*[A-Za-z][A-Za-z]$/  ;
  if (!email2.test(tfld)) 
    msg (infofield, "warn", "*");
  else
    //msg (infofield, "warn", "");
	msg (infofield, "valid", "");
  return true;
}

function validEmail(emailStr)
{
	var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/  ;
	return email.test(emailStr);
}


// --------------------------------------------
//            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  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;

  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  var telnr = /^\+?[0-9 ()-]+[0-9]$/  ;
  if (!telnr.test(tfld)) {
    msg (infofield, "error", "ERROR: not a valid telephone number. Characters permitted are digits, space ()- and leading +");
    setfocus(valfield);
    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 (infofield, "error", "ERROR: " + numdigits + " digits - too short");
    setfocus(valfield);
    return false;
  }

  if (numdigits>14)
    msg (infofield, "warn", numdigits + " digits - check if correct");
  else { 
    if (numdigits<10)
      msg (infofield, "warn", "Only " + numdigits + " digits - check if correct");
    else
      msg (infofield, "warn", "");
  }
  return true;
}

// --------------------------------------------
//             validateAge
// Validate person's age
// Returns true if OK 
// --------------------------------------------

function validateAge    (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;

  var tfld = trim(valfield.value);
  var ageRE = /^[0-9]{1,3}$/
  if (!ageRE.test(tfld)) {
    msg (infofield, "error", "ERROR: not a valid age");
    setfocus(valfield);
    return false;
  }

  if (tfld>=200) {
    msg (infofield, "error", "ERROR: not a valid age");
    setfocus(valfield);
    return false;
  }

  if (tfld>110) msg (infofield, "warn", "Older than 110: check correct");
  else {
    if (tfld<7) msg (infofield, "warn", "Bit young for this, aren't you?");
    else        msg (infofield, "warn", "");
  }
  return true;
}

// --------------------------------------------
//               validateFloat
// Validate if is float
// Returns true if so (and also if could not be executed because of old browser)
// --------------------------------------------

function validateFloat  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required, 	 // true if required
						 isPositive)   // true if float must be a positive float
{
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;

  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  
  if(tfld.substring(0,1) == ".") //add 0 to begining if user just typed in the decimal
  	tfld = "0" + tfld;
	
  if(isPositive) { 
	if (!(tfld > 0)) {//must be greater than zero
		msg (infofield, "error", "*");
	    setfocus(valfield);	
		return false;  
	}
  }
	
  var float = /^[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?$/ ;
  if (!float.test(tfld)) {
    msg (infofield, "error", "*");
    setfocus(valfield);
    return false;
  }

  var float2 = /^[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?$/  ;
  if (!float2.test(tfld)) 
    msg (infofield, "warn", "*");
  else
    msg (infofield, "valid", "");
  return true;
}

// --------------------------------------------
//               validateInteger
// Validate if is Integer
// Returns true if so (and also if could not be executed because of old browser)
// --------------------------------------------

function validateInteger  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)	// true if required
						
{
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;
	
  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  var integer = /^[0-9]+[0-9]*$/ ;
  if (!integer.test(tfld)) {
    msg (infofield, "error", "*");
    setfocus(valfield);
    return false;
  }

  var integer2 = /^[0-9]+[0-9]*$/  ;
  if (!integer2.test(tfld)) 
    msg (infofield, "warn", "*");
  else
    msg (infofield, "valid", "");
  return true;
}

// --------------------------------------------
//               validateDate
// Validate if is Date
// Returns true if so (and also if could not be executed because of old browser)
// --------------------------------------------

function validateDate  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  	var stat = commonCheck (valfield, infofield, required);
  	if (stat != proceed) return stat;
	
	if(!IsValidDate(valfield.value))
	{
		msg (infofield, "error", "*");
		valfield.select();
    	setfocus(valfield);
    	return false;
	}
	else
	{
		msg (infofield, "valid", "");	//251
	}
	return true;					
  /*
  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  var valDate = /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/ ;
  if (!valDate.test(tfld)) {
    msg (infofield, "error", "*");
    setfocus(valfield);
    return false;
  }

  var valDate2 = /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/  ;
  if (!valDate2.test(tfld)) 
    msg (infofield, "warn", "*");
  else
    msg (infofield, "warn", "");
  return true;
  */
}

// --------------------------------------------
//               validateWebSite
// Validate if is Web site
// Returns true if so (and also if could not be executed because of old browser)
// --------------------------------------------

function validateWebSite  (valfield,   // element to be validated
                         infofield,  // id of element to receive info/error msg
                         required)   // true if required
{
  var stat = commonCheck (valfield, infofield, required);
  if (stat != proceed) return stat;

  var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
  var website = /^[a-zA-Z0-9\-\.]+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU)$/;
  if (!website.test(tfld)) {
    msg (infofield, "error", "*");
    setfocus(valfield);
    return false;
  }

  var website2 = /^[a-zA-Z0-9\-\.]+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU)$/;
  if (!website2.test(tfld)) 
    msg (infofield, "warn", "*");
  else
    //msg (infofield, "warn", "");
	msg (infofield, "valid", "");
  return true;
}

// --------------------------------------------
//               validateSelectBox
// Validate if value selected does not equal equal default value
// Returns true if so 
// --------------------------------------------

function validateSelectBox  (valfield,   // element to be validated
                         defaultVal, //default value to validate against
						 infofield)  // id of element to receive info/error msg
                           
{
	if(valfield.value == defaultVal)
	{
		msg (infofield, "error", "*");
		setfocus(valfield);
		return false;
  	}
	else
		msg (infofield, "valid", "");
	return true;
}

/////////////////////////////////////////////////DATE FUNCTIONS///////////////////////////////////////////////////
	 	
	//check for a valid date				
	function IsValidDate(date) //date = date string
	{
		if(date.length != 10) return false; //date string must be at least 10 chars
		
		//make sure month, day and year are numeric
		if(date.substring(0, 2) == 'NaN' || date.substring(3, 5) == 'NaN' || date.substring(6, 10) == 'NaN')
			return false;
			
		var regEx = "";
		var mnth = date.substring(0, 2);
		var retVal;
		
		//Figure out what length (number of days allowed) the month must be
		if(mnth == 02)
		{
			if(IsLeapYear(date.substring(6, 10))){ 
				regEx = "([0][1-9]|[1][0-2])\/([0][1-9]|[1][0-9]|[2][0-9])\/[1-9][0-9][0-9][0-9]$"; }
			else{
				regEx = "([0][1-9]|[1][0-2])\/([0][1-9]|[1][0-9]|[2][0-8])\/[1-9][0-9][0-9][0-9]$"; }
			
		}
		else if(mnth == 01 || mnth == 03 ||  mnth == 05 ||  mnth == 07 ||  mnth == 08 ||  mnth == 10 ||  mnth == 12)
		{
			regEx = "([0][1-9]|[1][0-2])\/([0][1-9]|[1][0-9]|[2][0-9]|[3][0-1])\/[1-9][0-9][0-9][0-9]$";		
		}
		else
		{
			regEx = "([0][1-9]|[1][0-2])\/([0][1-9]|[1][0-9]|[2][0-9]|[3][0])\/[1-9][0-9][0-9][0-9]$";	
		}
		
		retVal = date.match(regEx);
		
		if(retVal == null)
			return false;
		else
			return true;
	}
	
	//check if string is leap year
	function IsLeapYear(year)
	{
		if(parseInt(year) == 'NaN') return false;
		
		var myDay = new Date( year, 1, 29);
		return myDay.getDate()==29 ? true : false;
	}
	
	/////////////////////////////////////////////////END DATE FUNCTIONS///////////////////////////////////////////////////
