//==========================================================================================================================================
// form validation functions Ver 1.0
// Written by Silas Landricombe 2008
// Javascript 1.1
//==========================================================================================================================================
// Supports validation of the following fields:
// text - is the field empty?
// email - check for a vaild email address
// dropdown - ensures an option with a value has been selected also supports 'other' option - requires an additional input field on the form and it's ID passed as a 4th variable
// contactNo - e.g. phone, fax numbers - set VALID characters below
// numeric - checks for a valid numeric value
// antiSpam - can be used to match two fields - requires an additional, usually hidden, input field on the form and it's ID passed as a 4th variable
// userName - check if username is valid - set INVALID characters and maximum and minimum length below
// password - check if password is valid - set VALID characters and maximum and minimum length below - requires an additional input field on the form and it's ID passed as a 4th variable 
// date - check for a valid date - checks for three numerical values seperated by a character specified below
// fileType - check the extension of the file you are trying to upload against the editable list below
// radioButton - checks if anything from the specified group has been checked
//==========================================================================================================================================
// Validation settings - feel free to adjust these to suit your needs
var validFieldColour = "#ffffff"; // standard background colour of input fields
var invalidFieldColour = "#ffcc66"; // 'alert' background colour of input fields
var contactNoCharacters = "0123456789+()- "; // VALID characters for contact numbers
var userNameCharacters = " !*£$%^&()+=¬`\\<>/?|,;"; // INVALID characters for usernames
var userNameMaxLength = 10; // maximum characters for username validation
var userNameMinLength = 5; // minimum characters for username validation
var passwordCharacters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // VALID characters for passwords
var passwordMaxLength = 10; // maximum characters for password validation
var passwordMinLength = 5; // minimum characters for password validation
var dateFormat = "dd/mm/yyyy"; // date format, validation will check for 2 - 3 numerical values in the format specified here e.g. may be dd/mm/yyyy, dd.mm.yy, yyyy-dd-mm, mm/yy etc
var fileTypes = "jpg,gif,jpeg"; // VALID file types, seperate with a comma - NOT case sensitive
//==========================================================================================================================================
 
//==========================================================================================================================================
// show alternative field - this can be used in conjunction with the 'dropdown' validation when and alternative option is offered
function showAlt(altField,thisSelect){
 var theContainer = document.getElementById(altField);
 var theList = document.getElementById(thisSelect);
 if (theList.options.selectedIndex==(theList.options.length-1)){
  theContainer.style.display = 'block';
 } else {
  theContainer.style.display = 'none';
 }
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// ammend validated field
// This will change the validated fields background colour and focus on the field if it has been rejected
 
function reject(thisField){
 thisField.style.backgroundColor = invalidFieldColour;
 thisField.focus();
 if (thisField.tagName != 'SELECT'){thisField.select();}
 return false;
}
 
function accept(thisField){
 thisField.style.backgroundColor = validFieldColour;
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate an email address
 
function validateEmail(theEmail) {
 var str = theEmail;
 var reg1 = /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/;
 var reg2 = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/;
 if (!reg1.test(str) && reg2.test(str)) {
  return true;
 }
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// check against list of valid characters
 
function checkStringValid(string,validchars) {
 var charstovalidate = string.split('');
 for( var i=0; i < charstovalidate.length; i++){
  if (validchars.indexOf(charstovalidate[i]) == -1){ 
   return false;
  }
 }
 return true;
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// check against list of invalid characters
 
function checkStringInvalid(string,invalidchars) {
 var charstovalidate = string.split('');
 for( var i=0; i < charstovalidate.length; i++){
  if (invalidchars.indexOf(charstovalidate[i]) != -1){ 
   return false;
  }
 }
 return true;
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate a numerical value
 
function checkNumeric(string) {
 var goodNumeric=/(^-*\d+$)|(^-*\d+\.\d+$)/
 if (goodNumeric.test(string)) {
  return true;
 }
}
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate date
 
function AdvancedCheckDateValid(string) {
 var seperatorOK = 0;
 var retrieveSeperator = dateFormat.replace(/[a-zA-Z0-9]/g, "") // returns //
 var checkSeperator = retrieveSeperator.split('');// returns [/][/]
 var seperator = checkSeperator[0];// returns /
 var checkReqDigits = dateFormat.split(seperator); //[dd][mm][yyyy]
 var noSeg = checkReqDigits.length;// returns 3
 
 var stringElements = string.split('');
 for( var e=0; e < stringElements.length; e++ ){
  if (stringElements[e] == seperator){ var seperatorOK = 1; }
 }
 
 if (seperatorOK == 1){
  var checkActDigits = string.split(seperator); //[0][0][0]
  for( var d=0; d < noSeg; d++ ){
   var whatSegment = d+1;
   var count = checkReqDigits[d].length; // returns 2,2,4
   var goodSegment=new RegExp("^\\d{"+count+"}$");
   if (!goodSegment.test(checkActDigits[d])) {
    return false;
   }
  }
  return true;
 } else { return false; }
 
}
 
//==========================================================================================================================================
 

function validateform(f) {
 var tempobj;
 var tempobj2;
 var teststring1;
 var teststring2;
  
 for (var i = 0; i < fieldstovalidate.length; i++) {
  
  tempobj=eval("f."+fieldstovalidate[i][0]);
 

//==========================================================================================================================================
// validate text fields
 
  if (fieldstovalidate[i][1] == 'text') {
   
   if (tempobj.value == '') {
    alert("Please fill out all required fields.\n The field '"+fieldstovalidate[i][2]+"' must be completed.");
    return reject(tempobj);
   } else { accept(tempobj); }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate email fields
 
  if (fieldstovalidate[i][1] == 'email') {
   
   if(tempobj.value.length>0)
   {
    if(!validateEmail(tempobj.value))
    {
      alert("The email you have supplied appears not to be valid.\n Please ensure you supply a valid email for '"+fieldstovalidate[i][2]+"'.");
     return reject(tempobj);
     } else { accept(tempobj); }
   } else {
    alert("Please enter a valid email for '"+fieldstovalidate[i][2]+"'.");
    return reject(tempobj);
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate dropdown menus
 
  if (fieldstovalidate[i][1] == 'dropdown') {
   
   if (tempobj.options.selectedIndex==0) {
    alert("Please make a selection from the '"+fieldstovalidate[i][2]+"' dropdown menu.");
    return reject(tempobj);
   } else { accept(tempobj); }
   
   if(fieldstovalidate[i][3])
   {
    tempobj2=eval("f."+fieldstovalidate[i][3]);
    if(tempobj.options.selectedIndex==(tempobj.options.length-1))
    {
     if(tempobj2.value=="")
     {
      alert("You have chosen an option not listed in the '"+fieldstovalidate[i][2]+"' dropdown menu.\n Please fill in the extra provided text field.");
      tempobj2.style.backgroundColor = '#ffcc66';
      tempobj2.focus();
      return false;
     }
    }
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate number fields e.g. telephone numbers
 
  if (fieldstovalidate[i][1] == 'contactNo') {
   
   if (tempobj.value == ''){
    alert("Please fill out all required fields.\n The field '"+fieldstovalidate[i][2]+"' must be completed.");
    return reject(tempobj);
   } else {
    if(!checkStringValid(tempobj.value,contactNoCharacters)) {
     alert("Please enter a valid '"+fieldstovalidate[i][2]+"' number.");
     return reject(tempobj);
    } else { accept(tempobj); }
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate numerical fields
 
  if (fieldstovalidate[i][1] == 'numeric') {
   if (tempobj.value == ''){
    alert("Please fill out all required fields.\n The field '"+fieldstovalidate[i][2]+"' must be completed.");
    return reject(tempobj);
   } else {
    if(!checkNumeric(tempobj.value)) {
     alert("Please enter a valid number for "+fieldstovalidate[i][2]+".");
     return reject(tempobj);
    } else { accept(tempobj); }
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate anti spam code
 
  if (fieldstovalidate[i][1] == 'antiSpam') {
   tempobj2=eval("f."+fieldstovalidate[i][3]);
   if (tempobj.value == ''){
    alert("Please fill out all required fields.\n The field '"+fieldstovalidate[i][2]+"' must be completed.");
    return reject(tempobj);
   } else {
    if(tempobj.value != tempobj2.value) {
     alert("The '"+fieldstovalidate[i][2]+"' code you have entered does not appear to match.\n Please try again.");
     return reject(tempobj);
    } else { accept(tempobj); }
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate username
 
  if (fieldstovalidate[i][1] == 'userName') {
   
   if (tempobj.value.length < userNameMinLength){
    alert("The "+fieldstovalidate[i][2]+" you have entered is too short. Your "+fieldstovalidate[i][2]+" should be at least "+userNameMinLength+" characters.\n Please try again.");
    return reject(tempobj);
   } else if (tempobj.value.length > userNameMaxLength) {
    alert("The "+fieldstovalidate[i][2]+" you have entered is too long. Your "+fieldstovalidate[i][2]+" should be no more than "+userNameMaxLength+" characters.\n Please try again.");
    return reject(tempobj);
   } else {
    
    if(!checkStringInvalid(tempobj.value,userNameCharacters)) {
     alert("The "+fieldstovalidate[i][2]+" you have entered is invalid. Your "+fieldstovalidate[i][2]+" should NOT contain any of the following characters: "+userNameCharacters+".");
    return reject(tempobj);
    } else { accept(tempobj); }
    
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate password
 
  if (fieldstovalidate[i][1] == 'password') {
   tempobj2=eval("f."+fieldstovalidate[i][3]);
   if (tempobj.value.length == ""){
    
    alert("Please enter a valid "+fieldstovalidate[i][2]+".");
    return reject(tempobj);
    
   } else if (tempobj2.value.length == "") {
    
    accept(tempobj);
    alert("You must repeat your "+fieldstovalidate[i][2]+".");
    return reject(tempobj2);
    
   } else if (tempobj.value == tempobj2.value){
    
    if (tempobj.value.length < passwordMinLength){
    alert("The "+fieldstovalidate[i][2]+" you have entered is too short. Your "+fieldstovalidate[i][2]+" should be at least "+passwordMinLength+" characters.\n Please try again.");
    return reject(tempobj);
    } else if (tempobj.value.length > passwordMaxLength) {
     alert("The "+fieldstovalidate[i][2]+" you have entered is too long. Your "+fieldstovalidate[i][2]+" should be no more than "+passwordMaxLength+" characters.\n Please try again.");
     return reject(tempobj);
    } else {
     
     if(!checkStringValid(tempobj.value,passwordCharacters)) {
      alert("The "+fieldstovalidate[i][2]+" you have entered is invalid. Your "+fieldstovalidate[i][2]+" must consist of only numbers and letters of the alphabet.");
      return reject(tempobj);
     } else { accept(tempobj); accept(tempobj2); }
     
    }
    
   } else {
    
    alert("The "+fieldstovalidate[i][2]+"s you have entered do no match.\n Please try again.");
    return reject(tempobj2);
    
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate date fields
 
  if (fieldstovalidate[i][1] == 'date') {
   
   if (tempobj.value == '') {
    alert("Please enter a valid "+fieldstovalidate[i][2]+".");
    return reject(tempobj);
   } else { 
   
    if(!AdvancedCheckDateValid(tempobj.value)) {
     alert("Please enter a valid "+fieldstovalidate[i][2]+".\n You must use the following format: "+dateFormat+".");
     return reject(tempobj);
    } else { accept(tempobj); }
   
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate file types
 
  if (fieldstovalidate[i][1] == 'fileType') {
   
   if(tempobj.value=="") {
    alert("Please select a file to upload. The field '"+fieldstovalidate[i][2]+"' must be completed");
    return reject(tempobj);
   } else {
    
    teststring1 = fileTypes.split(",");
    getExt = tempobj.value.split(".");
    teststring2 = getExt[getExt.length-1];
    
    var exfound=false;
    if(teststring2!="") {
     for(var p=0; p < teststring1.length; p++) {
      if(teststring1[p].toUpperCase()==teststring2.toUpperCase()) { exfound=true; }
     }
    }
    if(!exfound) {
     alert("The type of file you have selected to upload in the '"+fieldstovalidate[i][2]+"' field is not allowed by this server.\n\n The following types are supported: "+fileTypes+"");
     return reject(tempobj);
    } else { accept(tempobj); }
    
   }
   
  }
 
//==========================================================================================================================================
 
//==========================================================================================================================================
// validate radio buttons
 
  if (fieldstovalidate[i][1] == 'radioButton') {
   tempobj2 = tempobj.length;
   var theRadio = false;
   for (r = 0; r < tempobj2; r++) {
    if (tempobj[r].checked) { theRadio = tempobj[r].value; }
   }
   
   if (!theRadio){
    alert("Please select an option for '"+fieldstovalidate[i][2]+"'.");
    for (bc = 0; bc < tempobj.length; bc++) {
     tempobj[bc].style.backgroundColor = invalidFieldColour;
    }
    tempobj[0].focus();
    return false;
   } else {
    for (bc = 0; bc < tempobj.length; bc++) {
     tempobj[bc].style.backgroundColor = validFieldColour;
    }
   }
  } 
 
//==========================================================================================================================================
 }
 
 return true;
 
}
