/*
Functions available: (PLEASE UNDERSTAND THE CODES BEFORE USING)
1. function getFormErrors(form) 
2. function isValidLength(string, min, max) 
3. function isValidCreditCard(number) 
4. function isValidEmail(address) 
5. function isValidEmailStrict(address) 
6. function isValidZipcode(zipcode) 
7. function isValidPostalcode(postalcode) 
8. function isValidUSPhoneNumber(areaCode, prefixNumber, suffixNumber) 
9. function isAlphanumeric(string, ignoreWhiteSpace) 
10. function isAlphabetic(string, ignoreWhiteSpace) 
11. function removeBadCharacters(string) 
12. function removeSpaces(string) 
13. function trimWhitespace(string) 
14. function getMod10(number) 
15. function isEmaila(emailField) - another version of email validation - takes the field of the form and returns error message if false and hilite the field
16. function isValidName(nameField) - check individual name field (last name, first name, city, etc) only alphabets - no symbols - no numbers returns error message
17. function isValidPhoneFax(areaField, prefixField, suffixField) - returns error message, focus and select area code field
18. function autoTab(input,len, e) - phone or fax number has 3 separate boxes for areacode, prefix & suffix - this functions will move automatically to the next box
19. function isValidAlphaNumericBox(itemField) - generic validation for alphanumeric box with error message, focus & select field
20. function isValidZipCodeWithErrMsg(zipField) - validate zipcode (5 or 10 characters) with error message
21. function isValidUsernamePassword(itemField) - validate username and password (read comment first)
22. function isVerifiedPassword(pswdField1, pswdField2) - verifies password entries - compares 2 passwords - error message
23. function isValidUSPhoneFaxSimple(string)
*/

//phone or fax number has 3 separate boxes for areacode, prefix & suffix - this functions will move automatically to the next box
var isNN = (navigator.appName.indexOf("Netscape")!=-1);
function autoTab(input,len, e) 
{
 var keyCode = (isNN) ? e.which : e.keyCode; 
 var filter = (isNN) ? [0,8,9] : [0,8,9,16,17,18,37,38,39,40,46];
 if(input.value.length >= len && !containsElement(filter,keyCode)) 
 {
	input.value = input.value.slice(0, len);
	input.form[(getIndex(input)+1) % input.form.length].focus();
 }

	function containsElement(arr, ele) 
	{
 	var found = false, index = 0;
 	while(!found && index < arr.length)
 	if(arr[index] == ele)
 		found = true;
 	else
		index++;
 	return found;
	}

	function getIndex(input) 
	{
 	var index = -1, i = 0, found = false;
 	while (i < input.form.length && index == -1)
 	if (input.form[i] == input)
 		index = i;
 	else 
 		i++;
 	return index;
	}

 return true;
}



function getFormErrors(form) 
{
   var errors = new Array();
   
   // loop thru all form elements
   for (var elementIndex = 0; elementIndex < form.elements.length; elementIndex++) 
   {
      var element = form.elements[elementIndex];
     
      // text and textarea types
      if (element.type == "text" || element.type == "textarea") 
      {
         element.value = trimWhitespace(element.value)
         
         // required element
         if (element.required  && element.value == '') 
         {
            errors[errors.length] = element.requiredError;
         }
         
         // maximum length
         else if (element.maxlength && isValidLength(element.value, 0, element.maxlength) == false) 
         {
            errors[errors.length] = element.maxlengthError;
         }

         // minimum length
         else if (element.minlength && isValidLength(element.value, element.minlength, Number.MAX_VALUE) == false) 
         {
            errors[errors.length] = element.minlengthError;
         }
         
         // pattern (credit card number, email address, zip or postal code, alphanumeric, numeric)
         else if (element.pattern) 
         {
            if ( ( (element.pattern.toLowerCase() == 'visa' || element.pattern.toLowerCase() == 'mastercard' || element.pattern.toLowerCase() == 'american express' || element.pattern.toLowerCase() == 'diners club' || element.pattern.toLowerCase() == 'discover' || element.pattern.toLowerCase() == 'enroute' || element.pattern.toLowerCase() == 'jcb' || element.pattern.toLowerCase() == 'credit card') && isValidCreditCard(element.value, element.pattern) == false) ||
                  (element.pattern.toLowerCase() == 'email' && isValidEmailStrict(element.value) == false) ||
                  (element.pattern.toLowerCase() == 'zip or postal code' && isValidZipcode(element.value) == false && isValidPostalcode(element.value) == false) ||
                  (element.pattern.toLowerCase() == 'zipcode' && isValidZipcode(element.value) == false) ||
                  (element.pattern.toLowerCase() == 'postal code' && isValidPostalcode(element.value) == false) ||
                  (element.pattern.toLowerCase() == 'us phone number' && 
                     ( (element.prefix && element.suffix && isValidUSPhoneNumber(element.value, form[element.prefix].value, form[element.suffix].value) == false) || 
                        (!element.prefix && !element.suffix && isValidUSPhoneNumber(element.value) == false) ) ) ||
                  (element.pattern.toLowerCase() == 'alphanumeric' && isAlphanumeric(element.value, true) == false) ||
                  (element.pattern.toLowerCase() == 'numeric' && isNumeric(element.value, true) == false) ||
                  (element.pattern.toLowerCase() == 'alphabetic' && isAlphabetic(element.value, true) == false) ) {
               errors[errors.length] = element.patternError;
            }
         }
      }
      
      // password 
      else if (element.type == "password") 
      {
         
         // required element
         if (element.required  && element.value == '') 
         {
            errors[errors.length] = element.requiredError;
         }
         
         // maximum length
         else if (element.maxlength && isValidLength(element.value, 0, element.maxlength) == false) 
         {
            errors[errors.length] = element.maxLengthError;
         }

         // minimum length
         else if (element.minlength && isValidLength(element.value, element.minlength, Number.MAX_VALUE) == false) 
         {
            errors[errors.length] = element.minLengthError;
         }
      }
      
      // file upload
      if (element.type == "file") 
      {
         
         // required element
         if (element.required  && element.value == '') 
         {
            errors[errors.length] = element.requiredError;
         }
      }
      
      // select
      else if (element.type == "select-one" || element.type == "select-multiple" || element.type == "select") 
      {

         // required element
         if (element.required && element.selectedIndex == -1) 
         {
            errors[errors.length] = element.requiredError;
         }
         
		 // disallow empty value selection
         else if (element.disallowEmptyValue && element.options[element.selectedIndex].value == '') 
         {
            errors[errors.length] = element.disallowEmptyValueError;
         }

      }
      
      // radio buttons
      else if (element.type == "radio") 
      {
         var radiogroup = form.elements[element.name];
         
         // required element
         if (radiogroup.required && radiogroup.length) 
         {
            var checkedRadioButton = -1;
            for (var radioIndex = 0; radioIndex < radiogroup.length; radioIndex++) 
            {
               if (radiogroup[radioIndex].checked == true) 
               {
                  checkedRadioButton = radioIndex;
                  break;
               }
            }
            if (checkedRadioButton == -1 && !radiogroup.tested) 
            {
               errors[errors.length] = radiogroup.requiredError;
               radiogroup.tested = true;
            }
         }
         
         radiogroup = null;
      }
   }
   
	return errors;
}

// Check that the number of characters in a string is between a max and a min
function isValidLength(string, min, max) 
{
	if (string.length < min || string.length > max) return false;
	else return true;
}

// Check that a credit card number is valid based using the LUHN formula (mod10 is 0)
function isValidCreditCard(number) 
{
	number = '' + number;
	
	if (number.length > 16 || number.length < 13 ) return false;
	else if (getMod10(number) != 0) return false;
	else if (arguments[1]) 
	{
		var type = arguments[1];
		var first2digits = number.substring(0, 2);
		var first4digits = number.substring(0, 4);
		
		if (type.toLowerCase() == 'visa' && number.substring(0, 1) == 4 &&
			(number.length == 16 || number.length == 13 )) return true;
		else if (type.toLowerCase() == 'mastercard' && number.length == 16 &&
			(first2digits == '51' || first2digits == '52' || first2digits == '53' || first2digits == '54' || first2digits == '55')) return true;
		else if (type.toLowerCase() == 'american express' && number.length == 15 && 
			(first2digits == '34' || first2digits == '37')) return true;
		else if (type.toLowerCase() == 'diners club' && number.length == 14 && 
			(first2digits == '30' || first2digits == '36' || first2digits == '38')) return true;
		else if (type.toLowerCase() == 'discover' && number.length == 16 && first4digits == '6011') return true;
		else if (type.toLowerCase() == 'enroute' && number.length == 15 && 
			(first4digits == '2014' || first4digits == '2149')) return true;
		else if (type.toLowerCase() == 'jcb' && number.length == 16 &&
			(first4digits == '3088' || first4digits == '3096' || first4digits == '3112' || first4digits == '3158' || first4digits == '3337' || first4digits == '3528')) return true;
		
    // if the above card types are all the ones that the site accepts, change the line below to 'else return false'
    else return true;
	}
	else return true;
}

// Check that an email address is valid based on RFC 821 (?)
function isValidEmail(address) 
{
	if (address != '' && address.search) 
	{
      if (address.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1) return true;
      else return false;
	}
	
   // allow empty strings to return true - screen these with either a 'required' test or a 'length' test
   else return true;
}

// Check that an email address has the form something@something.something
// This is a stricter standard than RFC 821 (?) which allows addresses like postmaster@localhost
function isValidEmailStrict(address) 
{
	if (isValidEmail(address) == false) return false;
	var domain = address.substring(address.indexOf('@') + 1);
	if (domain.indexOf('.') == -1) return false;
	if (domain.indexOf('.') == 0 || domain.indexOf('.') == domain.length - 1) return false;
	return true;
}

// Check that a US zip code is valid
function isValidZipcode(zipcode) 
{
	zipcode = removeSpaces(zipcode);
	if (!(zipcode.length == 5 || zipcode.length == 9 || zipcode.length == 10)) return false;
   if ((zipcode.length == 5 || zipcode.length == 9) && !isNumeric(zipcode)) return false;
   if (zipcode.length == 10 && zipcode.search && zipcode.search(/^\d{5}-\d{4}$/) == -1) return false;
   return true;
}

// Check that a Canadian postal code is valid
function isValidPostalcode(postalcode) 
{
	if (postalcode.search) 
	{
		postalcode = removeSpaces(postalcode);
		if (postalcode.length == 6 && postalcode.search(/^[a-zA-Z]\d[a-zA-Z]\d[a-zA-Z]\d$/) != -1) return true;
		else if (postalcode.length == 7 && postalcode.search(/^[a-zA-Z]\d[a-zA-Z]-\d[a-zA-Z]\d$/) != -1) return true;
		else return false;
	}
	return true;
}

// Check that a US or Canadian phone number is valid
function isValidUSPhoneNumber(areaCode, prefixNumber, suffixNumber) 
{
   if (arguments.length == 1) 
   {
      var phoneNumber = arguments[0];
      phoneNumber = phoneNumber.replace(/\D+/g, '');
      var length = phoneNumber.length;
      if (phoneNumber.length >= 7) 
      {
         var areaCode = phoneNumber.substring(0, length-7);
         var prefixNumber = phoneNumber.substring(length-7, length-4);
         var suffixNumber = phoneNumber.substring(length-4);
      }
      else return false;
   }
   else if (arguments.length == 3) 
   {
      var areaCode = arguments[0];
      var prefixNumber = arguments[1];
      var suffixNumber = arguments[2];
   }
   else return true;

   if (areaCode.length != 3 || !isNumeric(areaCode) || prefixNumber.length != 3 || !isNumeric(prefixNumber) || suffixNumber.length != 4 || !isNumeric(suffixNumber)) return false;
   return true;
}

// Check that a string contains only letters and numbers
function isAlphanumeric(string, ignoreWhiteSpace) 
{
	if (string.search) 
	{
		if ((ignoreWhiteSpace && string.search(/[^\w\s]/) != -1) || (!ignoreWhiteSpace && string.search(/\W/) != -1)) return false;
	}
	return true;
}

// Check that a string contains only letters
function isAlphabetic(string, ignoreWhiteSpace) 
{
	if (string.search) 
	{
		if ((ignoreWhiteSpace && string.search(/[^a-zA-Z\s]/) != -1) || (!ignoreWhiteSpace && string.search(/[^a-zA-Z]/) != -1)) return false;
	}
	return true;
}

// Check that a string contains only numbers
function isNumeric(string, ignoreWhiteSpace) 
{
	if (string.search) 
	{
		if ((ignoreWhiteSpace && string.search(/[^\d\s]/) != -1) || (!ignoreWhiteSpace && string.search(/\D/) != -1)) return false;
	}
	return true;
}

// Remove characters that might cause security problems from a string 
function removeBadCharacters(string) 
{
	if (string.replace) 
	{
		string.replace(/[<>\"\'%;\)\(&\+]/, '');
	}
	return string;
}

// Remove all spaces from a string
function removeSpaces(string) 
{
	var newString = '';
	for (var i = 0; i < string.length; i++) 
	{
		if (string.charAt(i) != ' ') newString += string.charAt(i);
	}
	return newString;
}

// Remove leading and trailing whitespace from a string
function trimWhitespace(string) 
{
	var newString  = '';
	var substring  = '';
	beginningFound = false;
	
	// copy characters over to a new string
	// retain whitespace characters if they are between other characters
	for (var i = 0; i < string.length; i++) 
	{
		
		// copy non-whitespace characters
		if (string.charAt(i) != ' ' && string.charCodeAt(i) != 9) 
		{
			
			// if the temporary string contains some whitespace characters, copy them first
			if (substring != '') 
			{
				newString += substring;
				substring = '';
			}
			newString += string.charAt(i);
			if (beginningFound == false) beginningFound = true;
		}
		
		// hold whitespace characters in a temporary string if they follow a non-whitespace character
		else if (beginningFound == true) substring += string.charAt(i);
	}
	return newString;
}

// Returns a checksum digit for a number using mod 10
function getMod10(number) 
{
	
	// convert number to a string and check that it contains only digits
	// return -1 for illegal input
	number = '' + number;
	number = removeSpaces(number);
	if (!isNumeric(number)) return -1;
	
	// calculate checksum using mod10
	var checksum = 0;
	for (var i = number.length - 1; i >= 0; i--) 
	{
		var isOdd = ((number.length - i) % 2 != 0) ? true : false;
		digit = number.charAt(i);
		
		if (isOdd) checksum += parseInt(digit);
		else 
		{
			var evenDigit = parseInt(digit) * 2;
			if (evenDigit >= 10) checksum += 1 + (evenDigit - 10);
			else checksum += evenDigit;
		}
	}
	return (checksum % 10);
}

//another version of email validation - takes the field of the form and returns error message if false and hilite the field
function isEmaila(emailField) 
{
  var field = emailField;
  var str = field.value;
  if (window.RegExp) 
  {
    var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
    var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$";
    var reg1 = new RegExp(reg1str);
    var reg2 = new RegExp(reg2str);
    if (!reg1.test(str) && reg2.test(str)) 
    {
      return true;
    }
    alert("Please Enter a Valid E-mail Address.");
    field.focus();
    field.select();
    
    return false;
  } 
  else 
  {
    if(str.indexOf("@") >= 0)
      return true;
    alert("Please Enter a Valid E-mail Address.");
    field.focus();
    field.select();
    
    return false;
  }
}

// check individual name field (last name or first name) only alphabets - no symbols - no numbers
// function can be used to validate any alphabetical field - *** filed name must include the name you want to appeear oon the error message
// replace spaces with underscores
function isValidName(nameField) 
{
  var field = nameField;
  var str = field.value;
  var ignoreWhiteSpace=true;
  	
  if (str!="")
  {
  	if (!isAlphabetic(str, ignoreWhiteSpace))
  	{
     		alert(field.title+" must only contain alphabets");
     		field.focus();
     		field.select();
     		return (false);	
  	} 
  }
  else 
  {
  	alert(field.title+" is invalid.");
        field.focus();
     	field.select();
     	return (false);
  }
  return (true);
  	
}

// to use this all field names must include the name that represent the field
// example: "fax_prefix" will appear as "Enter you fax number"  - function will search filed name for "fax" or "phone" word
function isValidPhoneFax(areaField, prefixField, suffixField)
{
  var afield = areaField;
  var pfield = prefixField;
  var sfield = suffixField;
  var astr = afield.value;
  var pstr = pfield.value;
  var sstr = sfield.value;
  var phonestr = /phone/i;  //if you have other telephony device eg. modem add - var modemstr = /modem/i  - (field name must include the word "modem")
  var faxstr = /fax/i;      //then adjust the codes appropriately & where necessary
  var fieldname = "";
  
  if (afield.name.search(phonestr)!=-1) fieldname = "phone";
  if (afield.name.search(faxstr)!=-1) fieldname = "fax";
  
  if (!isValidUSPhoneNumber(astr, pstr, sstr))
  {
     alert("Please enter valid " + fieldname + " number");
     afield.focus();
     afield.select();
     return (false);
  }
  else return (true);
}

// to use this itemField must be named exactly waht you wanna it to appear on the error message (under score is allowed in place of space)
// example: "job_title" will appear as "Enter job title" with underscore removed
function isValidAlphaNumericBox(itemField, ignoreGoodChars)
{
  var field = itemField;
  var str = field.value;
  var ignoreWhiteSpace=true;
  var goodchars = [",", "!", "@", "&", "#", "/", "-", "'", "%", ":", "=", "_"];  //****DO NOT INCLUDE "." IN HERE - INFINITE LOOP

  
  //alert(str.search(goodchars[i]) + " = " + goodchars[i] + " found");
  /*if (ignoreGoodChars) //ignore commonly found character in company name or address like ,.-!@&#
  {
  	str = str.replace(".", " ");
  	str = str.replace(",", " ");
  	str = str.replace("!", " ");
  	str = str.replace("@", " ");
  	str = str.replace("&", " ");
  	str = str.replace("/", " ");
  	str = str.replace("#", " ");
  	str = str.replace("-", " ");
  	str = str.replace("'", " ");
  }*/
  if (str!="")
  {
  	if (ignoreGoodChars)
  	{
  		str = str.replace(/./gi, " "); //replace all dots with space (refer p.174 O'reilly Javascript: The definitive Guide book)
  		for (var i=0;i<goodchars.length;i++)
  		{
			while (str.search(goodchars[i])!=-1 && str.search(goodchars[i])<str.length) 
			{
				str=str.replace(goodchars[i], " ");
			}
  		}
  	}
  	if (!isAlphanumeric(str, ignoreWhiteSpace))
  	{
     		alert(field.title + " has invalid characters.\nPlease re-enter value.");
     		field.focus();
     		field.select();
     		return (false);	
  	} 
  }
  else 
  {
  	    alert(field.title+" is invalid");
        field.focus();
     	field.select();
     	return (false);
  }
  return (true);
}

// no selection made or first selection will return false - good for drop down menu with the first selection of "Select one" type
function isValidNotFirstOneSelection(selectField)
{
  if (selectField.selectedIndex==-1 || selectField.selectedIndex==0)
  {
  	alert(selectField.title+" is invalid.");	
  	selectField.focus();
  	//selectField.select();  //select object does not support this method
  	return (false);
  }
  return (true);
}

function isValidZipCodeWithErrMsg(zipField)
{
  var field = zipField;
  var str = field.value;
  
  if (str!="")
  {
  	if (!isValidZipcode(str))
  	{
     		alert("Please enter a valid zipcode");
     		field.focus();
     		field.select();
     		return (false);	
  	} 
  }
  else 
  {
  	alert("Please enter your zipcode");
        field.focus();
     	field.select();
     	return (false);
  }
  return (true);

}

// requirement: at least 6 characters (alpha,numbers,underscore), first character must be alpha, force lowercase
// the word username or password must be in the field name
function isValidUsernamePassword(itemField)
{
 var field = itemField;
 var str = field.value;
 //var re = /^[A-Za-z]\w{6,}[A-Za-z]$/; 
 var re = /^[A-Za-z]\w{5,}/;
 
 var usernamestr = /username/i;  
 var passwordstr = /password/i;      
 var fieldname = "";
 
 if (field.name.search(usernamestr)!=-1) fieldname = "user name";
 if (field.name.search(passwordstr)!=-1) fieldname = "password";
  
 field.value = str.toLowerCase();
 
 if (!re.test(str.toLowerCase())) 
 { 
 	alert("Please enter a valid " + fieldname + "!\n(6 alphanumeric & underscore characters minimum, begin with a letter"); 
 	field.focus();
 	field.select();
 	return (false);
 }
 return (true);
}

// verifies password entries - compares 2 passwords - error message
function isVerifiedPassword(pswdField1, pswdField2)
{
 var field1 = pswdField1;
 var field2 = pswdField2;
 var str1 = field1.value;
 var str2 = field2.value;
 
 if (isValidUsernamePassword(field1) && isValidUsernamePassword(field2))
 {
 	if (str1 != str2)
 	{
 		alert("Passwords are not the same");
 		field2.focus();
 		field2.select();
 		return (false);	
 	}
 }
 return (true);
}

/***************************************************/

function isValidUSPhoneFaxSimple(itemField)
{
 var field = itemField;
 //var str = (str!="")? removeSpaces(field.value):field.value;
 var str = field.value;
 
 var re = /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;

     if (str=="") {
            alert(itemField.title+" is invalid.");
            field.focus();
            field.select();
            return false;
     }
    if (!re.test(str))
    {
        alert(itemField.title+" is invalid.");
        field.focus();
        field.select();
        return false;
    }
    return true;
}























