// VARIABLE DECLARATIONS
var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var whitespace = " \t\n\r";
var decimalPointDelimiter = ".";
var phoneNumberDelimiters = "()-. ";
var validUSPhoneChars = digits + phoneNumberDelimiters;
var validWorldPhoneChars = digits + phoneNumberDelimiters + '+';
var SSNDelimiters = "- ";
var validSSNChars = digits + SSNDelimiters;
var digitsInSocialSecurityNumber = 9;
var digitsInUSPhoneNumber = 10;
var ZIPCodeDelimiters = "-";
var ZIPCodeDelimeter = "-";
var validZIPCodeChars = digits + ZIPCodeDelimiters;
var digitsInZIPCode1 = 5;
var digitsInZIPCode2 = 9;
var creditCardDelimiters = " ";
var mPrefix = "You did not enter a value into the ";
var mSuffix = " field. This is a required field. Please enter it now.";
var diffPrefix = "You cannot add this as a new record because the ";
var diffMiddle = " has not changed.  Please enter a new ";
var diffSuffix = " now.";

// s is an abbreviation for "string"
var sUSLastName = "Last Name";
var sUSFirstName = "First Name";
var sWorldLastName = "Family Name";
var sWorldFirstName = "Given Name";
var sTitle = "Title";
var sCompanyName = "Company Name";
var sUSAddress = "Street Address";
var sWorldAddress = "Address";
var sCity = "City";
var sStateCode = "State Code";
var sWorldState = "State, Province, or Prefecture";
var sCountry = "Country";
var sZIPCode = "ZIP Code";
var sWorldPostalCode = "Postal Code";
var sPhone = "Phone Number";
var sFax = "Fax Number";
var sDateOfBirth = "Date of Birth";
var sExpirationDate = "Expiration Date";
var sEmail = "Email";
var sSSN = "Social Security Number";
var sCreditCardNumber = "Credit Card Number";
var sOtherInfo = "Other Information";
var sURL = "Website URL";
var sUserID = "User ID";
var sPasswd = "Password";


// i is an abbreviation for "invalid"
var iStateCode = "This field must be a valid two character U.S. state abbreviation (like CA for California). Please reenter it now.";
var iZIPCode = "This field must be a 5 or 9 digit U.S. ZIP Code (like 94043). Please reenter it now.";
var iUSPhone = "This field must be a 10 digit U.S. phone number (like 415 555 1212). Please reenter it now.";
var iWorldPhone = "This field must be a valid international phone number. Please reenter it now.";
var iSSN = "This field must be a 9 digit U.S. social security number (like 123 45 6789). Please reenter it now.";
var iEmail = "This field must be a valid email address (like joe@example.com). Please reenter it now.";
var iCreditCardPrefix = "This is not a valid ";
var iCreditCardSuffix = " credit card number. Please reenter it now.";
var iDay = "This field must be a day number between 1 and 31.  Please reenter it now.";
var iMonth = "This field must be a month number between 1 and 12.  Please reenter it now.";
var iYear = "This field must be a 2 or 4 digit year number.  Please reenter it now.";
var iSqlDate = "This filed must be a valid date in the form YYYY-MM-DD.  Please reenter it now.";
var iExpDate = "This field must be a day number between 1 and 31 and the 2 digit year number separated by the '/' character.  Please reenter it now.";
var iDatePrefix = "The Day, Month, and Year for ";
var iDateSuffix = " do not form a valid date.  Please reenter them now.";
var iURL = "This field must be a properly formatted URL (like http://www.someplace.com/index.htm). Please reenter it now.";
var iUserID = "This field must be a valid User ID. Please reenter it now.";
var iNewUserID = "User ID";
var iNewEmail = "Email Address";
var iPasswd = "The password must be entered twice to assure accuracy. Please reenter the password in both fields now.";
var iSelectAny = " field requires a valid selection to be made. Please choose an option now.";
var iSelectParticular1 = " field requires that the value of ";
var iSelectParticular2 = " be selected. Please choose that option now.";
var iNewPass = "Password";
var iCompanyType = "Please choose a valid company type.";
var iOSPlatform = "Please choose a valid Operating System Platform.";
var iInternetBrowser = "Please choose a valid option for your internet browser.";
var iInternetSpeed = "Please choose a valid option for your internet connection speed.";


// p is an abbreviation for "prompt"
var pEntryPrompt = "Please enter a ";
var pStateCode = "2 character code (like CA).";
var pZIPCode = "5 or 9 digit U.S. ZIP Code (like 94043).";
var pUSPhone = "10 digit U.S. phone number (like 415 555 1212).";
var pWorldPhone = "international phone number.";
var pSSN = "9 digit U.S. social security number (like 123 45 6789).";
var pEmail = "valid email address (like foo@bar.com).";
var pCreditCard = "valid credit card number.";
var pDay = "day number between 1 and 31.";
var pMonth = "month number between 1 and 12.";
var pYear = "2 or 4 digit year number.";

var USStateCodeDelimiter = "|";
var USStateCodes = "AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AE|AE|AP";


var defaultEmptyOK = true;

function makeArray(n) {
   for (var i = 1; i <= n; i++) {
      this[i] = 0;
   }
   return this;
}

var daysInMonth = makeArray(12);
daysInMonth[1] = 31;
daysInMonth[2] = 29;   // must programmatically check this
daysInMonth[3] = 31;
daysInMonth[4] = 30;
daysInMonth[5] = 31;
daysInMonth[6] = 30;
daysInMonth[7] = 31;
daysInMonth[8] = 31;
daysInMonth[9] = 30;
daysInMonth[10] = 31;
daysInMonth[11] = 30;
daysInMonth[12] = 31;

// Check whether string s is empty.
function isEmpty(s){ return ((s == null) || (s.length == 0))}

// Returns true if string s is empty or
// whitespace characters only.
function isWhitespace (s) {
	var i;

    if (isEmpty(s)) { return true; }

    for (i = 0; i < s.length; i++) {
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (whitespace.indexOf(c) == -1) { return false; }
    }
    // All characters are whitespace.
    return true;
}

// Removes all characters which appear in string bag from string s.
function stripCharsInBag (s, bag) {
	var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++) {  
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) { returnString += c; }
    }
    return returnString;
}

// Removes all characters which do NOT appear in string bag
// from string s.
function stripCharsNotInBag (s, bag) {
	var i;
    var returnString = "";

    for (i = 0; i < s.length; i++) {  
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) != -1) { returnString += c; }
    }
    return returnString;
}


// Removes all whitespace characters from s.
function stripWhitespace (s) { return stripCharsInBag (s, whitespace); }


// Returns true if single character c (actually a string)
// is contained within string s.
function charInString (c, s) {
	for (i = 0; i < s.length; i++) {
		if (s.charAt(i) == c) { return true; }
    }
    return false;
}



// Removes initial (leading) whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.
function stripInitialWhitespace (s) {
	var i = 0;
    while ((i < s.length) && charInString (s.charAt(i), whitespace)){
       i++;}
    return s.substring (i, s.length);
}


// Returns true if character c is an English letter
// (A .. Z, a..z).
function isLetter (c) { return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) ); }

// Returns true if character c is a digit
// (0 .. 9).
function isDigit (c) { return ((c == "0") || (c == "1") || (c == "2") || (c == "3") || (c == "4") || (c == "5") || (c == "6") || (c == "7") || (c == "8") || (c == "9")); }

// Returns true if character c is a letter or digit.
function isLetterOrDigit (c) { return (isLetter(c) || isDigit(c)); }

// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters in string s are numbers.
function isInteger (s) { 
	var i;
    if (isEmpty(s)) {
       if (isInteger.arguments.length == 1) { return defaultEmptyOK; }
       else { return (isInteger.arguments[1] == true); } }

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.
    for (i = 0; i < s.length; i++) {  
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c)) { return false; }
    }
    // All characters are numbers.
    return true;
}


// isSignedInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters are numbers;
// first character is allowed to be + or - as well.
//
function isSignedInteger (s) {
	if (isEmpty(s)) {
       if (isSignedInteger.arguments.length == 1) { return defaultEmptyOK; }
       else { return (isSignedInteger.arguments[1] == true); }}

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedInteger.arguments.length > 1) {
            secondArg = isSignedInteger.arguments[1];
		}
        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == '+') ) {
           startPos = 1;   }
        return (isInteger(s.substring(startPos, s.length), secondArg));
    }
}


// isPositiveInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is an integer > 0.
function isPositiveInteger (s) {
	var secondArg = defaultEmptyOK;

    if (isPositiveInteger.arguments.length > 1){
        secondArg = isPositiveInteger.arguments[1];}

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a positive, not negative, number

    return (isSignedInteger(s, secondArg) && ( (isEmpty(s) && secondArg)  || (parseInt (s) > 0) ) );
}

// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is an integer >= 0.
function isNonnegativeInteger (s) {
	var secondArg = defaultEmptyOK;

    if (isNonnegativeInteger.arguments.length > 1){
        secondArg = isNonnegativeInteger.arguments[1];}

    return (isSignedInteger(s, secondArg)&& ( (isEmpty(s) && secondArg)  || (parseInt (s) >= 0) ) );
}



// isNegativeInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is an integer < 0.
function isNegativeInteger (s) {
	var secondArg = defaultEmptyOK;

    if (isNegativeInteger.arguments.length > 1){
        secondArg = isNegativeInteger.arguments[1];}
    return (isSignedInteger(s, secondArg) && ( (isEmpty(s) && secondArg)  || (parseInt (s) < 0) ) );
}


// isNonpositiveInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is an integer <= 0.
//
function isNonpositiveInteger (s) {
	var secondArg = defaultEmptyOK;

    if (isNonpositiveInteger.arguments.length > 1){
        secondArg = isNonpositiveInteger.arguments[1];}

    return (isSignedInteger(s, secondArg) && ( (isEmpty(s) && secondArg)  || (parseInt (s) <= 0) ) );
}


// isFloat (STRING s [, BOOLEAN emptyOK])
//
// True if string s is an unsigned floating point (real) number.
//
function isFloat (s) {
	var i;
    var seenDecimalPoint = false;

    if (isEmpty(s)){
       if (isFloat.arguments.length == 1){ return defaultEmptyOK; }
       else { return (isFloat.arguments[1] == true);} }

    if (s == decimalPointDelimiter){ return false; }

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)  {  
        // Check that current character is number.
        var c = s.charAt(i);

        if ((c == decimalPointDelimiter) && !(seenDecimalPoint)) { seenDecimalPoint = true; }
        else if (!isDigit(c)) { return false; }
    }

    // All characters are numbers.
    return true;
}


// isSignedFloat (STRING s [, BOOLEAN emptyOK])
//
// True if string s is a signed or unsigned floating point
// (real) number. First character is allowed to be + or -.
function isSignedFloat (s) {
	if (isEmpty(s)) {
       if (isSignedFloat.arguments.length == 1) { return defaultEmptyOK; }
       else { return (isSignedFloat.arguments[1] == true); } }
    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedFloat.arguments.length > 1){
            secondArg = isSignedFloat.arguments[1];}

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == '+') ){
           startPos = 1;   }
        return (isFloat(s.substring(startPos, s.length), secondArg));
    }
}


// isAlphabetic (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is English letters
// (A .. Z, a..z) only.
function isAlphabetic (s) {
	var i;

    if (isEmpty(s)){
       if (isAlphabetic.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isAlphabetic.arguments[1] == true);}}

    // Search through string's characters one by one
    // until we find a non-alphabetic character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++) {  
        // Check that current character is letter.
        var c = s.charAt(i);

        if (!isLetter(c)){
        return false;}
    }

    // All characters are letters.
    return true;
}


// isAlphanumeric (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is English letters
// (A .. Z, a..z) and numbers only.
//
function isAlphanumeric (s) {
	var i;

    if (isEmpty(s)){
       if (isAlphanumeric.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isAlphanumeric.arguments[1] == true);}}

    // Search through string's characters one by one
    // until we find a non-alphanumeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++) {  
        // Check that current character is number or letter.
        var c = s.charAt(i);

        if (! (isLetter(c) || isDigit(c) ) ){
        return false;}
    }

    // All characters are numbers or letters.
    return true;
}


// reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... )      
//
function reformat (s) {
	var arg;
    var sPos = 0;
    var resultString = "";

    for (var i = 1; i < reformat.arguments.length; i++) {
       arg = reformat.arguments[i];
       if (i % 2 == 1) {resultString += arg;}
       else {
           resultString += s.substring(sPos, sPos + arg);
           sPos += arg;
       }
    }
    return resultString;
}


// isSSN (STRING s [, BOOLEAN emptyOK])
//
// isSSN returns true if string s is a valid U.S. Social
// Security Number.  Must be 9 digits.
//
function isSSN (s) {
	if (isEmpty(s)){
       if (isSSN.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isSSN.arguments[1] == true);}}
    return (isInteger(s) && s.length == digitsInSocialSecurityNumber);
}


// isUSPhoneNumber (STRING s [, BOOLEAN emptyOK])
//
// isUSPhoneNumber returns true if string s is a valid U.S. Phone
// Number.  Must be 10 digits.
//
function isUSPhoneNumber (s) {
	if (isEmpty(s)){
       if (isUSPhoneNumber.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isUSPhoneNumber.arguments[1] == true);}}
    return (isInteger(s) && ((s.length == digitsInUSPhoneNumber && s.charAt(0) != '1' && s.charAt(0) != '0') || (s.length == digitsInUSPhoneNumber+1 && s.charAt(0) == '1')));
}


// isInternationalPhoneNumber (STRING s [, BOOLEAN emptyOK])
//
// isInternationalPhoneNumber returns true if string s is a valid
// international phone number.  Must be digits only; any length OK.
// May be prefixed by + character.
//
function isInternationalPhoneNumber (s) {
	if (isEmpty(s)){
       if (isInternationalPhoneNumber.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isInternationalPhoneNumber.arguments[1] == true);}}
    return (isPositiveInteger(s));
}


// isZIPCode (STRING s [, BOOLEAN emptyOK])
//
// isZIPCode returns true if string s is a valid
// U.S. ZIP code.  Must be 5 or 9 digits only.
//
function isZIPCode (s) {
	if (isEmpty(s)){
       if (isZIPCode.arguments.length == 1){ return defaultEmptyOK;}
       else {return (isZIPCode.arguments[1] == true);}}
   return (isInteger(s) &&
            ((s.length == digitsInZIPCode1) ||
             (s.length == digitsInZIPCode2)));
}


// isStateCode (STRING s [, BOOLEAN emptyOK])
//
// Return true if s is a valid U.S. Postal Code
// (abbreviation for state).
//
function isStateCode(s) {
	if (isEmpty(s)){
       if (isStateCode.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isStateCode.arguments[1] == true);}}
    return ( (USStateCodes.indexOf(s) != -1) &&
             (s.indexOf(USStateCodeDelimiter) == -1) );
}


// isEmail (STRING s [, BOOLEAN emptyOK])
//
function isEmail (s) {
	if (isEmpty(s)) {
       if (isEmail.arguments.length == 1) { return defaultEmptyOK; }
       else {return (isEmail.arguments[1] == true);}}
  
    // is s whitespace?
    if (isWhitespace(s)) {return false;}
   
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@")) { i++; }

    if ((i >= sLength) || (s.charAt(i) != "@")) {return false;}
    else {i += 2;}

    // look for .
    while ((i < sLength) && (s.charAt(i) != ".")) { i++; }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != ".")) { return false;}
    else {return true;}
}


// isYear (STRING s [, BOOLEAN emptyOK])
//
// isYear returns true if string s is a valid
// Year number.  Must be 2 or 4 digits only.
function isYear (s) {
	if (isEmpty(s)){
       if (isYear.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isYear.arguments[1] == true);}}
    if (!isNonnegativeInteger(s)) {return false;}
    return ((s.length == 2) || (s.length == 4));
}

function isYear4 (s) {
	if (isEmpty(s)){
       if (isYear4.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isYear4.arguments[1] == true);}}
    if (!isNonnegativeInteger(s)) {return false;}
    return (s.length == 4);
}

// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
//
// isIntegerInRange returns true if string s is an integer
// within the range of integer arguments a and b, inclusive.
function isIntegerInRange (s, a, b) {
	if (isEmpty(s)){
       if (isIntegerInRange.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isIntegerInRange.arguments[1] == true);}}

    // Catch non-integer strings to avoid creating a NaN below,
    // which isn't available on JavaScript 1.0 for Windows.
    if (!isInteger(s, false)) {return false;}

    var num = parseInt (s);
    return ((num >= a) && (num <= b));
}


// isMonth (STRING s [, BOOLEAN emptyOK])
//
// isMonth returns true if string s is a valid
// month number between 1 and 12.
function isMonth (s) {
	if (isEmpty(s)) {
       if (isMonth.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isMonth.arguments[1] == true);}}
    return isIntegerInRange (s, 1, 12);
}

function isSqlMonth (s) {
	if (isEmpty(s)) {
       if (isSqlMonth.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isSqlMonth.arguments[1] == true);}}
    return (s.length == 2 && isIntegerInRange(parseInt(s), 1, 12));
}


// isDay (STRING s [, BOOLEAN emptyOK])
//
// isDay returns true if string s is a valid
// day number between 1 and 31.
function isDay (s) {
	if (isEmpty(s)) {
       if (isDay.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isDay.arguments[1] == true);}}
    return isIntegerInRange (s, 1, 31);
}

function isSqlDay (s) {
	if (isEmpty(s)) {
       if (isSqlDay.arguments.length == 1) {return defaultEmptyOK;}
       else {return (isSqlDay.arguments[1] == true);}}
    return (s.length == 2 && isIntegerInRange (parseInt(s), 1, 31));
}


// daysInFebruary (INTEGER year)
//
// Given integer argument year,
// returns number of days in February of that year.
function daysInFebruary (year) {
	// February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}


// isDate (STRING year, STRING month, STRING day)
//
// isDate returns true if string arguments year, month, and day
// form a valid date.
//
function isDate (year, month, day) {
	// catch invalid years (not 2- or 4-digit) and invalid months and days.
    if (! (isYear(year, false) && isMonth(month, false) && isDay(day, false))){ return false;}

    // Explicitly change type to integer to make code work in both
    // JavaScript 1.1 and JavaScript 1.2.
    var intYear = parseInt(year);
    var intMonth = parseInt(month);
    var intDay = parseInt(day);

    // catch invalid days, except for February
    if (intDay > daysInMonth[intMonth]){ return false;}

    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) {return false;}

    return true;
}

function isSqlDate (year, month, day) {
	// catch invalid years (not 2- or 4-digit) and invalid months and days.
    if (! (isYear4(year, false) && isSqlMonth(month, false) && isSqlDay(day, false))){ return false;}

    // Explicitly change type to integer to make code work in both
    // JavaScript 1.1 and JavaScript 1.2.
    var intYear = parseInt(year);
    var intMonth = parseInt(month);
    var intDay = parseInt(day);

    // catch invalid days, except for February
    if (intDay > daysInMonth[intMonth]){ return false;}

    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) {return false;}

    return true;
}

/* FUNCTIONS TO NOTIFY USER OF INPUT REQUIREMENTS OR MISTAKES. */

// Display prompt string s in status bar.
function prompt (s) { window.status = s }

// Display data entry prompt string s in status bar.
function promptEntry (s) { window.status = pEntryPrompt + s }

// Notify user that required field theField is empty.
// String s describes expected contents of theField.value.
// Put focus in theField and return false.
function warnEmpty (theField, s) {
	theField.focus();
	theField.select();
    alert(mPrefix + s + mSuffix);
	theField.focus();
    return false;
}

function warnInvalid (theField, s) {
	alert(s);
	theField.focus();
	theField.blur();
	theField.select();
	return false;
}

function warnSelectInvalid (theField, s) {
	alert(s);
	theField.focus();
	return false;
}

/* FUNCTIONS TO INTERACTIVELY CHECK VARIOUS FIELDS. */

// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is not all whitespace.
function checkString (theField, s, emptyOK) {
    if (checkString.arguments.length == 2){ emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))){ return true;}
    if (isWhitespace(theField.value)){
       return warnEmpty (theField, s);}
    else {return true;}
}


// checkSameStrings (TEXTFIELD theField1, TEXTFIELD theField2, STRING s, [, BOOLEAN emptyOK==false])
//
// Check that string theField1.value is equal to string theField2.value and return true
function checkSameStrings (theField1, theField2, s, emptyOK) {
    if (checkSameStrings.arguments.length == 3) { emptyOK = defaultEmptyOK; }
    if ((emptyOK == true) && (isEmpty(theField1.value)) && (isEmpty(theField2.value))) { return true; }
    if (theField1.value != theField2.value) { return warnInvalid (theField1, s); }
	else if ((emptyOK != true) && (isEmpty(theField1.value) || isEmpty(theField2.value))) { return warnInvalid (theField1, s); }
    else { return true; }
}


// checkDiffStrings (TEXTFIELD theField1, TEXTFIELD theField2, STRING s, [, BOOLEAN emptyOK==false])
//
// Check that string theField1.value is NOT equal to string theField2.value and return true
function checkDiffStrings (theField1, theField2, s, emptyOK) {
    if (checkDiffStrings.arguments.length == 3) { emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField1.value) || isEmpty(theField2.value))) { return true; }
    if (theField1.value == theField2.value) { return warnInvalid (theField1, diffPrefix + s + diffMiddle + s + diffSuffix); }
    else { return true; }
}


// checkURL (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false]))
//
// Check that string theField.value is in proper url format
function checkURL(theField, emptyOK) {
    if (checkURL.arguments.length == 1) { emptyOK = defaultEmptyOK; }
    if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	var myRegExp=/(http:\/\/)/gi;
	var myArray = myRegExp.exec(theField.value);
	if (!(myArray) || (myRegExp.lastIndex != 7)) { theField.value = "http://" + theField.value; }
    else { return true; }
}



// checkSelect (SELECTFIELD theField, CHAR mode, STRING pattern, STRING s[, BOOLEAN emptyOK==false]))
function checkSelect (theField, mode, pattern, s, emptyOK) {
	if (checkSelect.arguments.length == 4) { emptyOK = defaultEmptyOK; }
    if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	else if ((emptyOK == true) && (theField.selectedIndex == -1)) { return true; }
	else if (((mode == "i") && (theField.selectedIndex == pattern)) ||
		((mode == "I") && (theField.selectedIndex != pattern)) ||
		((mode == "v") && (theField.value == pattern)) ||
		((mode == "V") && (theField.value != pattern))) { return true; }
   else { return warnSelectInvalid (theField, s); }
}


// checkStateCode (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid U.S. state code.
function checkStateCode (theField, emptyOK) {
	if (checkStateCode.arguments.length == 1) { emptyOK = defaultEmptyOK; }
    if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
    else {  theField.value = theField.value.toUpperCase();
       if (!isStateCode(theField.value, false)) { return warnSelectInvalid (theField, iStateCode); }
       else { return true; } }
}



// takes ZIPString, a string of 5 or 9 digits;
// if 9 digits, inserts separator hyphen
function reformatZIPCode (ZIPString) {
	if (ZIPString.length == 5) { return ZIPString; }
    else { return (reformat (ZIPString, "", 5, "-", 4)); }
}

// checkZIPCode (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid ZIP code.
function checkZIPCode (theField, emptyOK) {
	if (checkZIPCode.arguments.length == 1) { emptyOK = defaultEmptyOK; }
    if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
    else { var normalizedZIP = stripCharsInBag(theField.value,ZIPCodeDelimiters);
      if (!isZIPCode(normalizedZIP, false)) { return warnInvalid (theField, iZIPCode); }
      else {  // if you don't want to insert a hyphen, comment next line out
         theField.value = reformatZIPCode(normalizedZIP);
         return true; }
    }
}



// takes USPhone, a string of 10 digits
// and reformats as (123) 456-789
function reformatUSPhone (USPhone) { return (reformat (USPhone.substring(USPhone.length-10,USPhone.length), "", 3, "-", 3, "-", 4)); }


// checkUSPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid US Phone.
function checkUSPhone (theField, emptyOK) {
	if (checkUSPhone.arguments.length == 1){ emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))) {return true;}
    else {  var normalizedPhone = stripCharsInBag(theField.value,phoneNumberDelimiters);
       if (!isUSPhoneNumber(normalizedPhone, false)){
          return warnInvalid (theField, iUSPhone);}
       else {  // if you don't want to reformat as (123) 456-789, comment next line out
          theField.value = reformatUSPhone(normalizedPhone);
          return true;
       }
    }
}


// checkInternationalPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid International Phone.
function checkInternationalPhone (theField, emptyOK) {
	if (checkInternationalPhone.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))) {return true;}
    else {  if (!isInternationalPhoneNumber(theField.value, false)){
          return warnInvalid (theField, iWorldPhone);}
       else {return true;}
    }
}

// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid Email.
function checkEmail (theField, emptyOK) {
	if (checkEmail.arguments.length == 1){ emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))){ return true;}
    else if (!isEmail(theField.value, false)){
       return warnInvalid (theField, iEmail);}
    else { return true;}
}


// takes SSN, a string of 9 digits
// and reformats as 123-45-6789
function reformatSSN (SSN) { return (reformat (SSN, "", 3, "-", 2, "-", 4)); }

// Check that string theField.value is a valid SSN.
function checkSSN (theField, emptyOK) {
	if (checkSSN.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))){ return true;}
    else   {  var normalizedSSN = stripCharsInBag(theField.value, SSNDelimiters);
       if (!isSSN(normalizedSSN, false)){
          return warnInvalid (theField, iSSN);}
       else {  // if you don't want to reformats as 123-456-7890, comment next line out
          theField.value = reformatSSN(normalizedSSN);
          return true;
       }
    }
}


// Check that string theField.value is a valid Year.
function checkYear (theField, emptyOK) {
	if (checkYear.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))){ return true;}
    if (!isYear(theField.value, false)){
       return warnInvalid (theField, iYear);}
    else {return true;}
}

function checkYear4 (theField, emptyOK) {
	if (checkYear4.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))){ return true;}
    if (!isYear4(theField.value, false)){
       return warnInvalid (theField, iYear);}
    else {return true;}
}

// Check that string theField.value is a valid Month.
function checkMonth (theField, emptyOK) {
	if (checkMonth.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))) {return true;}
    if (!isMonth(theField.value, false)){
       return warnInvalid (theField, iMonth);}
    else{ return true;}
}


// Check that string theField.value is a valid Day.
function checkDay (theField, emptyOK) {
	if (checkDay.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(theField.value))) {return true;}
    if (!isDay(theField.value, false)){
       return warnInvalid (theField, iDay);}
    else {return true;}
}


// checkDate (yearField, monthField, dayField, STRING labelString [, OKtoOmitDay==false])
//
// Check that yearField.value, monthField.value, and dayField.value
// form a valid date.
function checkDate (yearField, monthField, dayField, labelString, OKtoOmitDay) {
	// Next line is needed on NN3 to avoid "undefined is not a number" error
    // in equality comparison below.
    if (checkDate.arguments.length == 4) {OKtoOmitDay = false;}
    if (!isYear(yearField.value)){ return warnInvalid (yearField, iYear);}
    if (!isMonth(monthField.value)) {return warnInvalid (monthField, iMonth);}
    if ( (OKtoOmitDay == true) && isEmpty(dayField.value) ) {return true;}
    else if (!isDay(dayField.value)){
       return warnInvalid (dayField, iDay);}
    if (isDate (yearField.value, monthField.value, dayField.value)){
       return true;}
    alert (iDatePrefix + labelString + iDateSuffix);
    return false;
}

function checkSqlDate (dateField, emptyOK) {
	return true;
    if (checkSqlDate.arguments.length == 1) {emptyOK = defaultEmptyOK;}
    if ((emptyOK == true) && (isEmpty(dateField))){ return true;}
	dateFields = dateField.value.split("-");
    if (!isYear4(dateFields[0])){ return warnInvalid (dateField, iSqlDate);}
    if (!isSqlMonth(dateFields[1])) {return warnInvalid (dateField, iSqlDate);}
	if (!isSqlDay(dateFields[2])){ return warnInvalid (dateField, iSqlDate);}
    if (isSqlDate (dateFields[0], dateFields[1], dateFields[2])){ return true;}
    alert (iSqlDate);
    return false;
}


// Get checked value from radio button.
function getRadioButtonValue (radio) {
	for (var i = 0; i < radio.length; i++) {   if (radio[i].checked) { break; } }
    return radio[i].value;
}



// Validate credit card info.
function checkCreditCard (radio, theField) {
	var cardType = getRadioButtonValue (radio);
    var normalizedCCN = stripCharsInBag(theField.value, creditCardDelimiters);
    if (!isCardMatch(cardType, normalizedCCN)){
       return warnInvalid (theField, iCreditCardPrefix + cardType + iCreditCardSuffix);}
    else {  theField.value = normalizedCCN;
       return true;
    }
}


// Validate credit card info without
// indicating the card type
function checkAnyCard (theField) {
    var normalizedCCN = stripCharsInBag(theField.value, creditCardDelimiters);
    if (!isAnyCard(normalizedCCN)) {
       return warnInvalid (theField, iCreditCardPrefix + iCreditCardSuffix);}
    else {  theField.value = normalizedCCN;
       return true;
    }
}


/*  ================================================================
    FUNCTION:  isCreditCard(st)

    INPUT:     st - a string representing a credit card number

    RETURNS:  true, if the credit card number passes the Luhn Mod-10
    test.
      false, otherwise
    ================================================================ */

function isCreditCard(st) {
  // Encoding only works on cards with less than 19 digits
  if (st.length > 19){
    return (false);}

  sum = 0; mul = 1; l = st.length;
  for (i = 0; i < l; i++) {
    digit = st.substring(l-i-1,l-i);
    tproduct = parseInt(digit ,10)*mul;
    if (tproduct >= 10){
      sum += (tproduct % 10) + 1;}
    else{
      sum += tproduct;}
    if (mul == 1){
      mul++;}
    else{
      mul--;}
  }

  if ((sum % 10) == 0){
    return (true);}
  else{
    return (false);}

} // END FUNCTION isCreditCard()



/*
    FUNCTION:  isVisa()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is a valid VISA number.
      false, otherwise
*/

function isVisa(cc) {
  if (((cc.length == 16) || (cc.length == 13)) && (cc.substring(0,1) == 4)) {
    return isCreditCard(cc); }
  return false;
}  // END FUNCTION isVisa()




/*
    FUNCTION:  isMasterCard()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is a valid MasterCard
    number.
      false, otherwise
*/

function isMasterCard(cc) {
  firstdig = cc.substring(0,1);
  seconddig = cc.substring(1,2);
  if ((cc.length == 16) && (firstdig == 5) && ((seconddig >= 1) && (seconddig <= 5))){
    return isCreditCard(cc); }
  return false;

} // END FUNCTION isMasterCard()





/*
    FUNCTION:  isAmericanExpress()

    INPUT:     cc - a string representing a credit card number

    RETURNS:  true, if the credit card number is a valid American
    Express number.
   
      false, otherwise
*/

function isAmericanExpress(cc) {
  firstdig = cc.substring(0,1);
  seconddig = cc.substring(1,2);
  if ((cc.length == 15) && (firstdig == 3) && ((seconddig == 4) || (seconddig == 7))) {
    return isCreditCard(cc); }
  return false;

} // END FUNCTION isAmericanExpress()




/* 
    FUNCTION:  isDinersClub()

    INPUT:     cc - a string representing a credit card number

    RETURNS:  true, if the credit card number is a valid Diner's
    Club number.
   
      false, otherwise
*/

function isDinersClub(cc) {
  firstdig = cc.substring(0,1);
  seconddig = cc.substring(1,2);
  if ((cc.length == 14) && (firstdig == 3) &&
      ((seconddig == 0) || (seconddig == 6) || (seconddig == 8))){
    return isCreditCard(cc);}
  return false;
}



/*
    FUNCTION:  isCarteBlanche()

    INPUT:     cc - a string representing a credit card number

    RETURNS:  true, if the credit card number is a valid Carte
    Blanche number.
   
      false, otherwise
*/

function isCarteBlanche(cc) {
  return isDinersClub(cc);
}




/*
    FUNCTION:  isDiscover()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is a valid Discover
    card number.
     false, otherwise
*/

function isDiscover(cc) {
  first4digs = cc.substring(0,4);
  if ((cc.length == 16) && (first4digs == "6011")){
    return isCreditCard(cc);}
  return false;

} // END FUNCTION isDiscover()





/*
    FUNCTION:  isEnRoute()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is a valid enRoute
    card number.
      false, otherwise
*/

function isEnRoute(cc) {
  first4digs = cc.substring(0,4);
  if ((cc.length == 15) &&
      ((first4digs == "2014") ||
       (first4digs == "2149"))){
    return isCreditCard(cc);}
  return false;
}



/*
    FUNCTION:  isJCB()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is a valid JCB
    card number.
      false, otherwise
*/

function isJCB(cc) {
  first4digs = cc.substring(0,4);
  if ((cc.length == 16) &&
      ((first4digs == "3088") ||
       (first4digs == "3096") ||
       (first4digs == "3112") ||
       (first4digs == "3158") ||
       (first4digs == "3337") ||
       (first4digs == "3528"))){
    return isCreditCard(cc);}
  return false;

} // END FUNCTION isJCB()



/*
    FUNCTION:  isAnyCard()
    INPUT:     cc - a string representing a credit card number
    RETURNS:  true, if the credit card number is any valid credit
    card number for any of the accepted card types.
      false, otherwise
*/

function isAnyCard(cc) {
  if (!isCreditCard(cc)){
    return false;}
  if (!isMasterCard(cc) && !isVisa(cc) && !isAmericanExpress(cc) && !isDinersClub(cc) &&
      !isDiscover(cc) && !isEnRoute(cc) && !isJCB(cc)) {
    return false;
  }
  return true;

} // END FUNCTION isAnyCard()



/*
    FUNCTION:  isCardMatch()
    INPUT:    cardType - a string representing the credit card type
      cardNumber - a string representing a credit card number
    RETURNS:  true, if the credit card number is valid for the particular
      credit card type given in "cardType".
       false, otherwise
*/

function isCardMatch (cardType, cardNumber) {

cardType = cardType.toUpperCase();
var doesMatch = true;

if ((cardType == "VISA") && (!isVisa(cardNumber))){
doesMatch = false;}
if ((cardType == "MASTERCARD") && (!isMasterCard(cardNumber))){
doesMatch = false;}
if ( ( (cardType == "AMERICANEXPRESS") || (cardType == "AMEX") ) && (!isAmericanExpress(cardNumber))) {doesMatch = false;}
if ((cardType == "DISCOVER") && (!isDiscover(cardNumber))){
doesMatch = false;}
if ((cardType == "JCB") && (!isJCB(cardNumber))){
doesMatch = false;}
if ((cardType == "DINERS") && (!isDinersClub(cardNumber))){
doesMatch = false;}
if ((cardType == "CARTEBLANCHE") && (!isCarteBlanche(cardNumber))){
doesMatch = false;}
if ((cardType == "ENROUTE") && (!isEnRoute(cardNumber))){
doesMatch = false;}
return doesMatch;

}