// ----------------------------------------------------------------------
// 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()
{
  global_valfield.focus();
}

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

// --------------------------------------------
//            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", "Please don't leave this field blank.");  
      //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", "");  
  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 useCampaignCommanderChecks = true;
	var stat = commonCheck (valfield, infofield, required);
	if (stat != proceed) return stat;

	if (useCampaignCommanderChecks) {
		// additional checks as used in CampaignCommander webform 
		// added JJW 2009 Oct for NAC.
		emailAddress=valfield;
		emailAddressValue=valfield.value.toLowerCase();
		var countryTLDs=/^(ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)$/;
		var gTLDs=/^(aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)$/;
		var basicAddress=/^(.+)@(.+)$/;
		var specialChars='\\(\\)><@,;:\\\\\\\"\\.\\[\\]';
		var validChars='\[^\\s'+specialChars+'\]';
		var validCharset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\'-_.';
		var quotedUser='(\"[^\"]*\")';
		var atom=validChars+'+';
		var word='('+atom+'|'+quotedUser+')';
		var validUser=new RegExp('^'+word+'(\.'+word+')*$');
		var symDomain=new RegExp('^'+atom+'(\.'+atom+')*$');
		var matchArray=emailAddressValue.match(basicAddress);
		if(emailAddress.value==''||emailAddress==null){
			return true;
		}
		if(matchArray==null){
			msg (infofield, "error", "The email address doesn\'t seem to be correct - please check syntax.");
			setfocus(valfield);		
			return false;
		}else{
			var user=matchArray[1];
			var domain=matchArray[2];
			for(i=0;i<user.length;i++){
				if(validCharset.indexOf(user.charAt(i))==-1){
					msg (infofield, "error", 'The email address contains invalid characters (before the @) ');
					setfocus(valfield);		
					return false;
				}
			}
			for(i=0;i<domain.length;i++){
				if(validCharset.indexOf(domain.charAt(i))==-1){
					//alert('The Email address contains invalid characters,\nplease check the domain.');
					msg (infofield, "error", 'The Email address contains invalid characters (afer the @)');
					setfocus(valfield);		
					return false;
				}
			}
			if(user.match(validUser)==null){
				msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check the username.');
				setfocus(valfield);		
				return false;
			}
			var atomPat=new RegExp('^'+atom+'$');
			var domArr=domain.split('.');
			var len=domArr.length;
			for(i=0;i<len;i++){
				if(domArr[i].search(atomPat)==-1){
					msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check the domain name.');
					setfocus(valfield);		
					return false;
				}
			}
			if((domArr[domArr.length-1].length==2)&&(domArr[domArr.length-1].search(countryTLDs)==-1)){
				msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check domain suffix.');
				setfocus(valfield);
				return false;
			}
			if((domArr[domArr.length-1].length>2)&&(domArr[domArr.length-1].search(gTLDs)==-1)){
				msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check domain suffix.');
				setfocus(valfield);
				return false;
			}
			if((domArr[domArr.length-1].length<2)||(domArr[domArr.length-1].length>6)){
				msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check domain suffix. ');
				setfocus(valfield);
				return false;
			}
			if(len<2){
				// length of hostname (between @ and domain) < 2
				msg (infofield, "error", 'The Email address doesn\'t seem to be correct - please check after the @');
				setfocus(valfield);
				return false;
			}
			else
				msg (infofield, "warn", "");
		}  
		// end additional checks from CampaignCommander functionality
	} else {
		// standard email checks from Stephen Poley's formval code
		// This version will warn on illegal characters (e.g. ben@fuß.de) but won't stop them.
		var tfld = trim(valfield.value);  // value of field with whitespace trimmed off
		var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/  ;
		if (!email.test(tfld)) {
			msg (infofield, "error", "Please enter a valid e-mail address.");
			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", "Unusual e-mail address - please check if it is correct");
		else
			msg (infofield, "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  (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", "Please enter a valid telephone number (with country code)");
    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<4) {
    msg (infofield, "error", "Very short number: please check it is correct.");
    setfocus(valfield);
    return false;
  }

  if (numdigits>18)
    msg (infofield, "warn", numdigits + " digits - check if correct");
  else { 
    if (numdigits<8)
      msg (infofield, "warn", "Short number: please check it is 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", "Please enter your age (in years).");
    setfocus(valfield);
    return false;
  }

  if (tfld>=200) {
    msg (infofield, "error", "Please enter your correct age.");
    setfocus(valfield);
    return false;
  }

  if (tfld>160) msg (infofield, "warn", "Please enter your correct age.");
  else {
    if (tfld<2) msg (infofield, "warn", "Please enter your correct age.");
    else        msg (infofield, "warn", "");
  }
  return true;
}

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

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

  var statM = valfieldM.checked;
  var statF = valfieldF.checked;

  if ( statM == false && statF == false) {
	msg (infofield, "error", "Please select gender (male or female)");  
    setfocus(valfieldM);
	return false;
  }
  
   msg (infofield, "warn", "");
  return true;
}

