// VARIABLE DECLARATIONS
var whitespace = " \t\n\r"; // whitespace characters
var dateDelimiter = "/"; // Date Delimiter

// CONSTANT STRING DECLARATIONS
// (grouped for ease of translation and localization)

// m is an abbreviation for "missing"
var mPrefix = "You did not enter a value into the "
var mSuffix = " field. This is a required field. Please enter it now."

// s is an abbreviation for "string"
var sFirstName = "First Name"
var sLastName = "Last Name"
var sAcctNum = "Account Number"

// i is an abbreviation for "invalid"
var iEmail = "This field must be a valid email address. Please reenter it now."
var iDate = "We are unable to complete your request.\nPlease enter a valid date (mm/dd/yyyy)."

var defaultEmptyOK = false

var daysInMonth = new Array(13);
daysInMonth = [0,31,29,31,30,31,30,31,31,30,31,30,31];

// BASIC DATA VALIDATION FUNCTIONS:

// Check whether string s is empty.
function isEmpty(s) { return ((s == null) || (s.length == 0)) }

// Returns true if character c is a digit 
function isDigit (c) { return ((c >= "0") && (c <= "9")) }

// Returns true if character c is an English letter 
function isLetter (c) { return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) ) }

// 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;
}

// Returns true if string s is English letters (A .. Z, a..z) only.
function isAlphabetic (s) 
{
    var i;
    if (isEmpty(s)) return false;
    for (i = 0; i < s.length; i++)
    {   
        var c = s.charAt(i);
        if (!isLetter(c))
        return false;
    }
    return true;
}

// Returns true if all characters in string s are numbers.
// Accepts non-signed integers only. Does not accept floating 
// point, exponential notation, etc.
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
function isInteger (s)
{
    var i;
    if (isEmpty(s)) return false;
    var c;
    for (i = 0; i < s.length; i++)
    {   
        c = s.charAt(i);
        if (!isDigit(c)) return false;
    }
    return true;
}

// 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)) return false;
    // Catch non-integer strings to avoid creating a NaN below,
    // which isn't available on JavaScript 1.0 for Windows.
    if (!isInteger(s)) return false;
    // Now, explicitly change the type to integer via parseInt
    // so that the comparison code below will work both on 
    // JavaScript 1.2 (which typechecks in equality comparisons)
    // and JavaScript 1.1 and before (which doesn't).
    var num = parseInt (s,10);
    return ((num >= a) && (num <= b));
}

function LeadingZero(num, len)
{
    var s = eval('"' + num + '"');
    while (s.length < len) { s = "0" + s; }
    return s;
}

// Returns true if the checkbox object is checked
function isChecked (theField)
{
    return ((theField.checked==true) && true);
}

function warnInvalid (s, theField)
{
    if (warnInvalid.arguments.length == 2) {
        theField.focus();
        theField.select();
    }
    alert(s);
    return false
}

// 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);
    return false;
}

// 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;
}

// 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);
   
    // is s whitespace?
    if (isWhitespace(s)) return false;
    
    // there must be >= 1 character before @, so we
    // start looking at character position 1 
    // (i.e. second character)
    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;
}

// 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 (iEmail, theField);
    else return true;
}

// DATE VALIDATION FUNCTIONS

// isYear (STRING s)
// isYear returns true if string s is a valid Year number.  Must be 4 digits only.
function isYear (s)
{
    if (isEmpty(s)) return false;
    if (!isInteger(s)) return false;
    return (s.length == 4);
}

// isMonth (STRING s)
// isMonth returns true if string s is a valid month number between 1 and 12.
function isMonth (s)
{
    if (isEmpty(s)) return false;
    return isIntegerInRange (s, 1, 12);
}

// isDay (STRING s)
// isDay returns true if string s is a valid day number between 1 and 31.
function isDay (s)
{
    if (isEmpty(s)) return false;
    return isIntegerInRange (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 4-digit) and invalid months and days.
    if (! (isYear(year) && isMonth(month) && isDay(day))) return false;
    // Explicitly change type to integer to make code work in both
    // JavaScript 1.1 and JavaScript 1.2.
    var intYear = parseInt(year,10);
    var intMonth = parseInt(month,10);
    var intDay = parseInt(day,10);
    // catch invalid days, except for February
    if (intDay > daysInMonth[intMonth]) return false; 
    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) return false;
    return true;
}

// checkDate (dateString, emptyOK)
// Check that dateString is a valid date.
function checkDate (dateField, emptyOK)
{
    var dateStr = stripCharsInBag(dateField.value, dateDelimiter);
    if (isEmpty(dateStr) && (emptyOK==true)) return true;
    if (dateStr.length != 8) return warnInvalid(iDate,dateField);
    
    var yearStr, monthStr, dayStr;
    
    monthStr = dateStr.substring(0,2);
    dayStr = dateStr.substring(2,4);
    yearStr = dateStr.substring(4,8);    
    
    if (!isDate (yearStr, monthStr, dayStr)) return warnInvalid(iDate,dateField);
    return true;
}

//******* END OF VALIDATION FUNCTIONS ********