/* ********************************************************
* ValForm.js                                              *
*                                                         *
* Generic form validation for the onSubmit() handler of   *
* the Form object.  This code is adapted from lesson 9    *
* (Validating Form Data) in the JavaScript Programming    *
* handout from the ASP Level 1 course, taught by David    *
* Little of SteeleTech (November 17-21, 2003).            * 
**********************************************************/


/* ********************************************************
* set some global variables that will be checked later    *
**********************************************************/
var msg = "";                 // an output message
var missing = "";             // for missing required fields
var invNum = "";              // for invalid numeric fields
var outOfRange = "";          // less than min or more than max
var invZip = "";              // for invalid zip codes
var invPhone = "";            // for invalid phone numbers
var invState = "";            // for invalid state fields
var invEmail = "";            // for invalid e-mail fields
var invFldLen = "";           // for fields exceeding field length
var invDate = "";             // for invalid date fields

/* ********************************************************
* Displays an error message using an alert box            *
******************************************************** */
function errMsg(str)
  {
  var msg = ""
  var uln = "\n________________________________________";
  msg += "You entered some incorrect values into the form.";
  msg += "\nPlease correct your entries and re-submit the form.";
  msg += uln + str + uln;
  alert(msg);
  }

/* ********************************************************
* Returns true if a field has an invalid date format      *
**********************************************************/
function invalidDate(field)
  {
  var val = field.value;
  var dt = new Date(val.replace(/\D/g,'/'));
  if(!dt.valueOf())
    {
    return true; // the date was unparseable 
    }
  field.value = (dt.getMonth()+1)+'/'+dt.getDate()+'/'+dt.getFullYear();
  return false;
  }


/* ********************************************************
* Returns true if a field has an invalid e-mail format    *
**********************************************************/
function invalidEmail(field)
  {
  var email = field.value
  // simple email check
  var emailfmt= /^\w+([.-]\w+)*@\w+([.-]\w+)*\.\w{2,8}$/;
  if(!emailfmt.test(email))
    {
    return true;
    }
  return false;
  }

/* ********************************************************
* Returns true if a field has an invalid telephone format *
**********************************************************/
function invalidPhone(field)
  {
  var newStr = stripNonDigits(field.value);
  if(isEmpty(field))
    {
    return false;
    }
  if(newStr.length == 10)
    {
    return false;
    }
  return true;  
  }
  
/* ********************************************************
* Returns true if a field has an invalid state code       *
**********************************************************/
function invalidState(field)
  {
  var STATES = "";
  // abbreviations for the 50 states plus 
  // the District of Columbia and Puerto Rico
  STATES += "AK/AL/AR/AZ/CA/CO/CT/DC/DE/FL/GA/HI/IA/ID/IL/IN/KS/KY/LA/MA/";
  STATES += "MD/ME/MI/MN/MO/MS/MT/NC/ND/NE/NH/NJ/NM/NV/NY/OH/OK/OR/PA/PR/";
  STATES += "RI/SC/SD/TN/TX/UT/VA/VT/WA/WI/WV/WY";
  
  var newStr = field.value.toUpperCase();
  if(STATES.indexOf(newStr) == -1 || newStr.indexOf("/") != -1 || newStr.length != 2)
    {
    return true;
    }
  return false;  
  }

/* ********************************************************
* Returns true if a field has an invalid zip code format  *
**********************************************************/
function invalidZip(field)
  {
  var zipcode = field.value;
  if(zipcode.length == 5 || zipcode.length == 9)
    {
    var subZip = stripNonDigits(zipcode);
    if(subZip.length == zipcode.length)
      {
      return false;
      }
    else
      {
      return true;
      }
    }                                
  else if(zipcode.length == 10 && 
          (zipcode.charAt(5) == "-" || zipcode.charAt(5) == " "))
    {
    subZip = zipcode.substr(0,5) + zipcode.substr(6,4);
    subZip = stripNonDigits(subZip);
    if(subZip.length == 9)
      {
      return false;
      }
    else
      {
      return true;
      }
    }
  return true;  
  }

/* ********************************************************
* Returns true if a field is blank or empty, else false   *
******************************************************** */
function isEmpty(field)
  {
  var str = field.value;
  if(str == "")
    {
    return true;
    }
  else
    {
    for(j=0; j<str.length; j++)
      {
      if(str.charAt(j) != " ")
        {
        return false;
        }
      }
    }
  return true;
  }                                                      

/* ********************************************************
* Returns true if a field contains a non-numeric value    *
**********************************************************/
function notNumeric(field)
  {
  var errCount = 0, numDecs = 0;
  for(j=0; j<field.value.length; j++)
    {
    c = field.value.charAt(j);
    if((c >= "0" && c <= "9") || (c == ".") || (j == 0 && c == "-"))
      {
      if(c == ".")
        {
        numDecs++; 
        }
      }
    else
      {
      errCount++;
      break;
      }  
    }
  if(errCount > 0 || numDecs > 1)
    {
    return true;
    }
  return false;           
  }

/* ********************************************************
* Returns true if a field contains a non-numeric, -, (, ), or space value *
**********************************************************/
function notPhoneNumeric(field)
  {
  var errCount = 0;
  for(j=0; j<field.value.length; j++)
    {
    c = field.value.charAt(j);
    if((c >= "0" && c <= "9") || (c == "-") || (c == "(") || (c == ")") || (c == " "))
      {
      }
    else
      {
      errCount++;
      break;
      }  
    }
  if(errCount > 0)
    {
    return true;
    }
  return false;           
  }
		
/* ********************************************************
* Returns a string containing only the digit characters   *
* ('0'-'9') from the input parameter                        *
**********************************************************/
function stripNonDigits(str)
  {
  var newStr = "";
  for(j=0; j<str.length; j++)
    {
    c = str.charAt(j);
    if(c >= "0" && c <= "9")
      {
      newStr += c;
      }
    }
  return newStr;         
  }

  
/* ********************************************************
* The main validation function, calls other sub-functions *
**********************************************************/
function validate(frm)
  {
  var elText="";
  
  for(i=0; i<frm.elements.length; i++) // loop through form elements
    {
    var el = frm.elements[i];
    if(el.text)
      {
      elText=el.text
      }
    else
      {
      elText=el.name
      }
    if(el.required)
      {
      if(isEmpty(el))
        {
        missing += "\n   - " + elText; // + " is a required field";
        }
      }
    if(el.numeric)
      {
      if(notNumeric(el))
        {
        invNum += "\n   - " + elText; // + " must be a number"; 
        }
      }
    if(el.minVal)
      {
      if(parseFloat(el.value) < el.minVal)
        {
        outOfRange += "\n   - " + elText + " cannot be less than ";
        outOfRange += el.minVal + ", you entered " + el.value;
        }
      }
    if(el.maxVal)
      {
      if(parseFloat(el.value) > el.maxVal)
        {
        outOfRange += "\n   - " + elText + " cannot be greater than ";
        outOfRange += el.maxVal + ", you entered " + el.value;
        }
      }
    if(el.zip && el.value.length > 0)      
      {
      if(invalidZip(el))
        {
        invZip += "\n   - " + elText; // + " is not a valid zip code"; 
        }
      }
    if(el.phone && el.value.length > 0)      
      {
      if(invalidPhone(el) || el.value.length > 14)
        {
        invPhone += "\n   - " + elText; // + " is not a valid phone number"; 
        }
      }
    if(el.phonenumeric)
      {
      if(notPhoneNumeric(el))
        {
        invNum += "\n   - " + elText; // + " must be a number"; 
        }
      }
    if(el.state && el.value.length > 0)
      {
      if(invalidState(el))
        {
        invState += "\n   - " + elText; // + " is not a valid two-letter "; 
        // invState += "state abbreviation"; 
        }
      }
    if(el.email && el.value.length > 0)
      {
      if(invalidEmail(el))
        {
        invEmail += "\n   - " + elText; // + " is not a valid e-mail address"; 
        }
      } 
    if(el.chklen)
      {
      if(el.value.length > el.fldlen)
        {
        invFldLen += "\n   - " + elText + "(" + el.fldlen + ")"; // + " exceeds field length";
        }
      }
    if(el.date && el.value.length > 0)
      {
      if(invalidDate(el))
        {
        invDate += "\n   - " + elText; // + " is not a valid date"; 
        }
      } 
    }
    
  // build output message
  if(missing.length > 0 || invNum.length > 0 || outOfRange.length > 0 
        || invZip.length > 0 || invPhone.length > 0 || invState.length > 0 
        || invEmail.length > 0 || invFldLen.length > 0 || invDate.length > 0)
    {
    if(missing.length > 0)
      {
      msg += "\n\nThe following required fields are missing:";
      msg += missing;
      }
    if(invNum.length > 0)
      {
      msg += "\n\nYou entered non-numeric data in these fields:";
      msg += invNum;
      }
    if(outOfRange.length > 0)
      {
      msg += "\n\nYou entered out-of-range data in these fields:";
      msg += outOfRange;
      }
    if(invZip.length > 0)
      {
      msg += "\n\nYou entered an invalid zip code in these fields:";
      msg += invZip;
      }
    if(invPhone.length > 0)
      {
      msg += "\n\nYou entered an invalid phone/fax number in these fields;"
      msg += "\n           must be numeric; USA must include area code:";
      msg += invPhone;
      }
    if(invState.length > 0)
      {
      msg += "\n\nYou entered an invalid state abbreviation in these fields:";
      msg += invState;
      }
    if(invEmail.length > 0)
      {
      msg += "\n\nYou entered an invalid e-mail address in these fields:";
      msg += invEmail;
      }
    if(invDate.length > 0)
      {
      msg += "\n\nYou entered invalid date values in these fields:";
      msg += invDate;
      }
    if(invFldLen.length > 0)
      {
      msg += "\n\nThe following fields exceed their field length:";
      msg += invFldLen;
      }
    errMsg(msg);
    msg = ""; missing = ""; invNum = ""; outOfRange = ""; invZip = ""; 
    invPhone = ""; invState = ""; invEmail = ""; invFldLen = ""; invDate = "";
    return false;
    }
  else
    {
    return true;
    }
  }
