/*
FORM VALIDATION SCRIPT
RELEASE / USAGE NOTES
author: john mcgaraghan

version 1.0 released 7.31.02 (alpha)
version 1.1 released 8.04.02 (beta)
version 1.2 released 8.13.02 (stable)
version 2.0 released 3.29.04 (alpha)

Version 2.0 introduces a new "is-ies" based validation method.
basic setup remains the same with additional features described below.
passing of 2nd arg to formVal for email address validation is deprecated 
but still supported.  it may be removed from future releases.

v2.0:
document's <form> declaration tag should have an onSubmit parameter formatted as follows:
    onSubmit="return formVal(this);
if email type validation is desired on a field (e.g. emlField), then the proper "is-ie" 
should be declared in the reqFields array as follows:
var ReqFields=new Array(
  Array("emlField","Email Address","isEmail")
);

v1.2 back support:
document's <form> declaration tag should have an onSubmit parameter formatted as follows:
    onSubmit="return formVal(this, this.emailfield.value);
where "emailfield" is the name of the form input field for an email address
if the second argument is not passed, no validation will be done on email.

Select boxes should have a default "Select One" options at index 0 (with value="").
support for textarea field types is not present at this time.

support for simple/verbose error reporting added 8.13.02
support for checkboxes and radio buttons added 8.13.02
  --checks to see if one of a group of like named radio buttons is selected
  --checks to see if the designated check box is actually checked 

methodology for validating elements overhauled (including variable type validation) 3.29.04 
support for use of typed error labels reporting added 3.29.04 
errOverRide implementation updated (full override allowed) 3.29.04 
*/

// set to true (or override explicitly in pages) for verbose error reporting
verbose=true;

// set to true (or override explicitly in pages) for addition of type-dependent error messages
typelabels=true;

/*
populate an array like this with arrays of 'FieldName','ErrorLabel' pairs in the html 
file that calls this script in this way, you may use this single file to validate 
forms on different pages.  the 'FieldName','ErrorLabel' pairs can be followed by a
list of optional "is-ies" for specific data validation.  in the absence of an optional
"is-ie", only notBlank will be run on the value of the indicated field 

var reqFields=new Array(
  Array ('EmailAddress','Email Address'[,isEmail[,notBlank]]),
  Array ('PostalCode','Zip Code')
);

*/
var errOverRide; // set a value in your html page (after the inclusion of this file) to override the default error messaging
function formVal(f, eml)  {
var err=new Array();
  // loop over required fields
  for(i=0;i<reqFields.length;i++)  {
    // load value from selected form element -- checkboxes and radios return return 'checked' or empty
    var fieldVal=getValue(f,reqFields[i][0]);
    // if the current field has no custom validation requirements declared, add notBlank 
    reqFields[i][2] = (reqFields[i].length<3 ? "notBlank" : reqFields[i][2]);
    // run each designated custom validation requirement against the current form field value
    for(j=2;j<reqFields[i].length;j++) {
      if(eval("!"+reqFields[i][j]+"('"+fieldVal+"');")) {
        err.push(reqFields[i][1]+(typelabels?" "+errorLabels[reqFields[i][j]]:""));
      }
    }
  }
  // prepare and report errors
  if(err.length>0)  {
    var errBase="There were problems with your form submission.";
    var errText="";
    if(verbose) {
      if(!errOverRide) {
        errBase+="\nPlease review your entries for the following fields:";
      } else {
        errBase=errOverRide;
      }
      errText=errBase + "\n  -" + err.join(",\n  -");
    } else {
      errText=errBase + "\nPlease check your information and try again";
    }
    alert(errText);
    return false;
  }
  return (eml?emailVal(eml):true);
}

function getValue(f,fn) {
  // return value of selected option if field type is select
  if(eval("f."+fn+".type") && eval("f."+fn+".type.indexOf('elect')>0")) {
    return eval("f."+fn+".options[f."+fn+".options.selectedIndex].value");

  // return 'checked' or '' if field type is checkbox
  } else if(eval("f."+fn+".type") && eval("f."+fn+".type.indexOf('heckbox')>0")) {
    return (eval("!f."+fn+".checked")?"checked":"");

  // return 'checked' or '' if field type is radio
  } else if(eval("f."+fn+"[0]") && eval("f."+fn+"[0].type.indexOf('adio')>0")) {
    var radioElements=eval("f."+fn+".length");
    var radioChecked=false;
    for(n=0;n<radioElements;n++)   {
      if(eval("f."+fn+"["+n+"].checked==true")) {
        return "checked";
        break;
      }
    }
    if(!radioChecked) {
      return "";
    }
    radioChecked=false;

  // return value in input fields
  } else {
    return eval("f."+fn+".value");
  }
}

//email validation for v1.2 support
//reEML = /\S*@.\S*\..\S*/
// TOM MALAHER's Email Validation RegEx
reEML = /^[_A-Za-z0-9-]+[._A-Za-z0-9-]*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,5})$/
function emailVal(val) {
  OK = reEML.test(val);
  if (OK != true) {
    alert("Please make sure your email address is in the format yourname@company.com.");
    return false;
  } else {
    return true;
  }
}

// the is-ies
function isEmail(val) {
  return reEML.test(val);
}

function isNum(val) {
  return !isNaN(val);
}

function isInt(val) {
  return parseInt(val) == val;
}

function notBlank(val) {
  return val!="";
}

// error reporting labels specific to the is-ies
var errorLabels = new Array();
errorLabels["isEmail"]="must be an email address";
errorLabels["isNum"]="must be a number";
errorLabels["isInt"]="must be an integer";
errorLabels["notBlank"]="is a required field";
errorLabels["isDate"]="must be a valid date in MM/DD/YYYY format";


function isDate(val)
{
    var bError = false;
    var aChar = null;
    var holder = null;
    var Short =0;
    var FebCheck = null;
    var NovCheck = 0;
    var MonthCheck = null;
    var i = 0;

    // blank dates are valid, required fields are checked elsewhere
    if (val.length == 0) {
        return true;
    }

    if ((val.charAt(1)=="/" || val.charAt(1)=="-") && (val.charAt(3)=="/" || val.charAt(3)=="-")) {
        val = "0" + val.substring(0,1) + "/0" + val.substring(2,9);
    } else if ((val.charAt(1)=="/" || val.charAt(1)=="-")) {
        val = "0" + val;
    } else if (val.charAt(4)=="/" || val.charAt(4)=="-") {
        val = val.substring(0,2) + "/0" + val.substring(3,9);
    }

        for (i = 0; i < 10; i++)
            {
                aChar = val.charAt(i)
                if (i == 0 && aChar > 1) bError = true;
                if (i == 0 && aChar < "0") bError = true;
                if (i == 0 && aChar == 1) MonthCheck =1;
                if (i == 0 && aChar ==1) NovCheck=1;
                if (i == 1 && aChar < "0" || aChar > "9") bError = true;
                if (i == 1 && aChar == 2) FebCheck=1;
                if (i == 1 && MonthCheck == 1 && aChar >2) bError = true;
                if (i == 1 && aChar == 4 || aChar ==6 || aChar ==9) Short=1;
                if (i == 1 && NovCheck == 1 && aChar == 1) Short=1;
                if (i == 2 && aChar != '-' && aChar != '/')  bError = true;
                if (FebCheck == 1 && NovCheck != 1)
                {
                    if (i==3 && aChar > 2) bError = true;
                } 
                if (i == 3 && aChar > 3) bError = true;        
                if (i == 3 && aChar ==3) holder=1;
                if (i == 4 && aChar >0 && Short==1 && holder==1) bError = true;
                if (i == 4 && aChar >1 && holder==1) bError = true;
                if (i == 4 && aChar < "0" || aChar > "9") bError = true;
                if (i == 5 && aChar != '-' && aChar != '/')  bError = true;
                if (i == 8 && aChar < "0" || aChar > "9") bError = true;
                if (i == 9 && aChar < "0" || aChar > "9") bError = true;
            }
    
    if ((val.substring(0,5) =="02/29" || val.substring(0,5) =="02-29") && val.substring(6,10) %4 !=0) {
        bError = true;
    }

    return !bError;
}

