/**********************************************************************************
***********************************************************************************
** FormCheck.js                                                                    **
**                                                                               **
** This JavaScript library file is written to used for all Music Choice web      **
** forms to check for user input values before submit to server.                 **
**                                                                               **
** This file was gracefully stolen from Netscape Communications Corporation      **
** created by Eric Krock. Some functions are modified to fit with Music Choice   **
** needs. Some other functions are added to handle the specific form needs. It   **
** includes some functions that are not used for now. But those functions may be **
** needed for future, so it is good to keep them.                                **
**                                                                               **
** Author: Qingrui Liu <mailto:qliu@musicchoice.com>                             **
** Copyright (C) Music Choice 2000 - 2001                                        **
***********************************************************************************
***********************************************************************************/

/*
 * Global variables
 */
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 mPrefix1 = "You did not select an item in the "
var mPrefix2 = "You did not check any item in the "
var mSuffix = " field. This is a required field. Please enter it now."
var mSuffix1 = " field. This is a required field. Please select now."
var mSuffix2 = " field. This is a required field. Please check now."

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 foo@bar.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 4 digit year number.  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 iPassword = "Your passwords do not match, please re-type your password."

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 = "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 = false


/*
 * Make array - used for Navigator 2.0, Explorer 2.0 or before
 */
function makeArray(n) 
{
   for (var i = 1; i <= n; i++) {
      this[i] = 0
   } 
   return this
}

/*
 * Initial days in month array
 */
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;

/*
 * IsEmpty(s) - check empty string s
 */
function isEmpty (s)
{
   return ((s == null) || (s.length == 0))
}

/*
 * IsWhitespace(s) - check if character s is white space
 */
function isWhitespace (s)
{
    var i;
    if (isEmpty(s)) return true;
    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);
        if (whitespace.indexOf(c) == -1) return false;
    }

    return true;
}

/*
 * stripCharsInBag(s, bag) - strip all characters in bag from s
 */
function stripCharsInBag (s, bag)
{
    var i;
    var returnString = "";
    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }

    return returnString;
}

/*
 * stripCharsNotInBag(s, bag) - strip all characters not in bag from s
 */
function stripCharsNotInBag (s, bag)
{
    var i;
    var returnString = "";
    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);
        if (bag.indexOf(c) != -1) returnString += c;
    }

    return returnString;
}

/*
 * stripWhitespace(s) - strip all white spaces from s
 */
function stripWhitespace (s)
{
    return stripCharsInBag (s, whitespace)
}

/*
 * charInString(c, s) - return ture if string s contains char c
 */
function charInString (c, s)
{
    for (i = 0; i < s.length; i++)
    {
        if (s.charAt(i) == c) return true;
    }
    return false
}

/*
 * stripInitialWhitespace(s) - chop out all leading white spaces
 */
function stripInitialWhitespace (s)
{
    var i = 0;
    while ((i < s.length) && charInString (s.charAt(i), whitespace))
       i++;
    
    return s.substring (i, s.length);
}

/*
 * isLetter(c) - True if c is an English letter (lower or upper case)
 */
function isLetter (c)
{
    return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) )
}

/*
 * isDigit(c) - true if c is a digit
 */
function isDigit (c)
{
    return ((c >= "0") && (c <= "9"))
}

/*
 * isLetterOrDigit(c) - true if c is digit or letter
 */
function isLetterOrDigit (c)
{
    return (isLetter(c) || isDigit(c))
}

/*
 * isInteger (STRING s [, BOOLEAN emptyOK])
 * Return 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);

    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);
        if (!isDigit(c)) return false;
    }

    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];

        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];

    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) numbe
 */
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;

    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);

        if ((c == decimalPointDelimiter) && !seenDecimalPoint) seenDecimalPoint = true;
        else if (!isDigit(c)) return false;
    }

    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];

        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);

    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);

        if (!isLetter(c))
        return false;
    }

    return true;
}

/*
 * isAlphanumeric (STRING s [, BOOLEAN emptyOK])
 * Returns true if string s is English letters (A .. Z, a..z) and numbers (0 .. 9) only
 */
function isAlphanumeric (s)
{
    var i;

    if (isEmpty(s)) 
       if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphanumeric.arguments[1] == true);

    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);

        if (! (isLetter(c) || isDigit(c) ) )
        return false;
    }

    return true;
}

/*
 * reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... )
 * Handy function for arbitrarily inserting formatting characters
 * or delimiters of various kinds within TARGETSTRING
 */
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])
 * 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])
 * 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)
}

/*
 * isInternationalPhoneNumber (STRING s [, BOOLEAN emptyOK])
 * 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])
 * 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])
 * Email address must be of form a@b.c -- in other words:
 * there must be at least one character before the @
 * there must be at least one character before and after the .
 * the characters @ and . are both required
 */
function isEmail (s)
{
    if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
   
    if (isWhitespace(s)) return false;
    
    var i = 1;
    var sLength = s.length;

    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@")) return false;
    else i += 2;

    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false;
    else return true;
}

/*
 * isYear (STRING s [, BOOLEAN emptyOK])
 * returns true if string s is a valid Year number.  Must be 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 == 4);
}

/*
 * isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
 * 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);

    if (!isInteger(s, false)) return false;

    var num = parseInt (s);
    return ((num >= a) && (num <= b));
}

/*
 * isMonth (STRING s [, BOOLEAN emptyOK])
 * 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);
}

/*
 * isDay (STRING s [, BOOLEAN emptyOK])
 * 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);
}

/*
 * daysInFebruary (INTEGER year)
 * Given integer argument year, returns number of days in February of that year
 */
function daysInFebruary (year)
{
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}

/*
 * isDate (STRING year, STRING month, STRING day)
 * returns true if string arguments year, month, and day form a valid date
 */
function isDate (year, month, day)
{
    if (! (isYear(year, false) && isMonth(month, false) && isDay(day, false))) return false;

    var intYear = parseInt(year);
    var intMonth = parseInt(month);
    var intDay = parseInt(day);

    if (intDay > daysInMonth[intMonth]) return false; 

    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) return false;

    return true;
}

/*
 * prompt(s) - Display prompt string s in status bar
 */
function prompt (s)
{
   window.status = s
}

/*
 * promptEntry(s) - Display data entry prompt string s in status bar
 */
function promptEntry (s)
{
    window.status = pEntryPrompt + s
}

/*
 * warnEmpty(theField, s) - Notify user that required field theField is empty
 */
function warnEmpty (theField, s)
{
    theField.focus()
    alert(mPrefix + s + mSuffix)
    return false
}

/*
 * warnEmptyDropDownBox(theField, s) - Notify user that required dropdown theField is empty
 */
function warnEmptyDropDownBox (theField, s)
{	theField.focus()
    alert(mPrefix1 + s + mSuffix1)
    return false
}

/*
 * warnEmptyRadio(theField, s) - Notify user that required radio button theField is empty
 */
function warnEmptyRadio (theField, s)
{  
    alert(mPrefix2 + s + mSuffix2)
    return false
}

/*
 * warnInvalid(theField, s) - Notify user that contents of field theField are invalid
 */
function warnInvalid (theField, s)
{
    theField.focus()
	theField.select()
    alert(s)
    return false
}

/*
 * checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
 * Check that string theField.value is not all whitespace
 * s should be the label name of theField
 */
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;
}

/*
 * checkPasswdMatch (TEXTFIELD theField1, TEXTFIELD theField2 [, BOOLEAN emptyOK==false])
 * Check that theField2.value equals theField1.value 
 */
function checkPasswdMatch (theField1, theField2, emptyOK)
{
	if (checkPasswdMatch.arguments.length == 2) emptyOK = defaultEmptyOK;
	if (theField1.value != theField2.value)	
		return warnInvalid (theField2, iPassword);
	else return true;
}

/*
 * 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 warnInvalid (theField, iStateCode);
       else return true;
    }
}

/*
 * reformatZIPCode(ZIPString - 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 
      {
         theField.value = reformatZIPCode(normalizedZIP)
         return true;
      }
    }
}

/*
 * reformatUSPhone(USPhone) - takes USPhone, a string of 10 digits
 * and reformats as (123) 456-789
 */
function reformatUSPhone (USPhone)
{
    return (reformat (USPhone, "(", 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 
       {
          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;
}

/*
 * reformatSSN(SSN) - takes SSN, a string of 9 digits and reformats as 123-45-6789
 */
function reformatSSN (SSN)
{
    return (reformat (SSN, "", 3, "-", 2, "-", 4))
}

/*
 * checkSSN (TEXTFIELD theField [, BOOLEAN emptyOK==false])
 * 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 
       {
          theField.value = reformatSSN(normalizedSSN)
          return true;
       }
    }
}

/*
 * checkYear (TEXTFIELD theField [, BOOLEAN emptyOK==false])
 * 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;
}

/*
 * stripInitialZero(s) - Strip leading zero for the day and month in s
 */
function stripInitialZero (s)
{	
	if (s.charAt(0) == '0') return s.substring(1, s.length);
	return s;
	
}

/*
 * reformatTwoDigits(s) - Reformat two digits. used for month and day (two digits)
 */
function reformatTwoDigits (s)
{
	if (s.length == 2) return s;
	return reformat (s, "0", 1);
}

/*
 * checkMonth (TEXTFIELD theField [, BOOLEAN emptyOK==false])
 * 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;
    var monthValue = stripInitialZero (theField.value);
    if (!isMonth(monthValue, false)) 
       return warnInvalid (theField, iMonth);
    else {
		theField.value = reformatTwoDigits (theField.value);
		return true;
	}
}

/*
 * checkDay (TEXTFIELD theField [, BOOLEAN emptyOK==false])
 * 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;
    var dayValue = stripInitialZero (theField.value);
    if (!isDay(dayValue, false)) 
       return warnInvalid (theField, iDay);
    else {
		theField.value = reformatTwoDigits (theField.value);
		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 (monthField, dayField, yearField, labelString, OKtoOmitDay)
{
    if (checkDate.arguments.length == 4) OKtoOmitDay = false;
    var monthValue = stripInitialZero (monthField.value);
    var dayValue = stripInitialZero (dayField.value);
    if (!isMonth(monthValue)) return warnInvalid (monthField, iMonth);
    if ( (OKtoOmitDay == true) && isEmpty(dayField.value) ) return true;
    else if (!isDay(dayValue)) 
       return warnInvalid (dayField, iDay);
    if (!isYear(yearField.value)) return warnInvalid (yearField, iYear);
    if (isDate (yearField.value, monthValue, dayValue)) {
		monthField.value = reformatTwoDigits (monthField.value);
		dayField.value = reformatTwoDigits (dayField.value);
        return true;
    }
    alert (iDatePrefix + labelString + iDateSuffix)
    monthField.focus();
    return false
}

/*
 * checkDropDownBox (TEXTFIELD theField, STRING theName [, BOOLEAN emptyOK==false])
 * Check if a item is selected from the dropdown 
 */ 
function checkDropDownBox (theField, theName, emptyOK)
{
    if (checkDropDownBox.arguments.length == 2) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.options[theField.selectedIndex].value))) return true;
    else
    {  
       if (isEmpty(theField.options[theField.selectedIndex].value)) 
          return warnEmptyDropDownBox (theField, theName);
       else return true;
    }
}

/*
 * getDropDownBoxValue(theBox) - Get checked value from dropdown box
 */
function getDropDownBoxValue(theBox)
{
	return theBox.options[theBox.selectedIndex].value;
}

/*
 * getRadioButtonValue(radio) - 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
}

/*
 * isRadioChecked(radio) - Is any radio or checkbox checked
 */
function isRadioChecked (radio)
{
    for (var i = 0; i < radio.length; i++)
    {
        if (radio[i].checked) { return true; }
    }
    return false;
}

/*
 * checkRadioButton (TEXTFIELD theField, STRING theName [, BOOLEAN emptyOK==false])
 * Check if radio button is checked
 */
function checkRadioButton (theField, theName, emptyOK)
{
    if (checkRadioButton.arguments.length == 2) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (!isRadioChecked(theField))) return true;
    if (!isRadioChecked(theField)) 
       return warnEmptyRadio (theField, theName);
    else return true;
}

/*
 * checkRadioOther (RADIO Radio, TEXTFIELD theField, STRING theName [, BOOLEAN emptyOK==false])
 * Check a combined radio and textfield
 */
function checkRadioOther (radio, textField, theName, emptyOK)
{
 	if (checkRadioOther.arguments.length == 3) emptyOK = defaultEmptyOK;
	if (getRadioButtonValue(radio) == theName) 
		return checkString(textField, theName);
	else return true;
}

/*
 * checkCreditCard (STRING indicator, TypeField cardTypeField, TEXTFIELD theField)
 * Validate credit card info.
 */
function checkCreditCard (indicator, cardTypeField, theField)
{	
	var cardType;
	if (indicator == "RADIO")
        cardType = getRadioButtonValue (cardTypeField);
    else
		cardType = getDropDownBoxValue (cardTypeField);
		
    var normalizedCCN = stripCharsInBag(theField.value, creditCardDelimiters)
    if (!isCardMatch(cardType, normalizedCCN)) 
       return warnInvalid (theField, iCreditCardPrefix + cardType + iCreditCardSuffix);
    else 
    {
       theField.value = normalizedCCN
       return true
    }
}

/*
 * isCreditCard(st) - true if the credit card number passes the Luhn Mod-10 test.
 */
function isCreditCard(st) 
{
  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);

}

/*
 * isVisa(cc) - true, if the credit card number is a valid VISA number
 */
function isVisa(cc)
{
  if (((cc.length == 16) || (cc.length == 13)) &&
      (cc.substring(0,1) == 4))
    return isCreditCard(cc);
  return false;
}

/*
 * isMasterCard(cc) - true, if the credit card number is a valid MasterCard number
 */
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;

}

/*
 * isAmericanExpress(cc) - true, if the credit card number is a valid American Express number
 */
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;

} 

/*
 * isDinersClub(cc) - true, if the credit card number is a valid Diner's Club number.
 */
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;
}

/*
 * isCarteBlanche(cc) - true, if the credit card number is a valid Carte Blanche number.
 */
function isCarteBlanche(cc)
{
  return isDinersClub(cc);
}

/*
 * isDiscover(cc) - true, if the credit card number is a valid Discover number
 */
function isDiscover(cc)
{
  first4digs = cc.substring(0,4);
  if ((cc.length == 16) && (first4digs == "6011"))
    return isCreditCard(cc);
  return false;

}

/*
 * isEnRoute(cc) - true, if the credit card number is a valid enRoute card number
 */
function isEnRoute(cc)
{
  first4digs = cc.substring(0,4);
  if ((cc.length == 15) &&
      ((first4digs == "2014") ||
       (first4digs == "2149")))
    return isCreditCard(cc);
  return false;
}

/*
 * isJCB(cc) - true, if the credit card number is a valid JCB card number
 */
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;

}

/*
 * isAnyCard(cc) - true, if the credit card number is any valid credit
 *      		    card number for any of the accepted card types
 */
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;

}

/*
 * isCardMatch(cardType, cardNumber) - true, if the credit card number is valid for the 
 *                                   particular credit card type given in "cardType"
 */
function isCardMatch (cardType, cardNumber)
{

	cardType = cardType.toUpperCase();
	var doesMatch = true;

	if ((cardType == "VISA") && (!isVisa(cardNumber)))
		doesMatch = false;
	if (((cardType == "MASTERCARD") || (cardType == "MC"))
				&& (!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;

}
