/* -*-C++-*-
 *  File:        ValidateForm.js
 *  RCS:         none
 *  Description: Defines form validation functions for Javascript
 *  Author:      Scott Lundberg, StarFire Enterprises, Inc.
 *  Created:     Tue Aug  16 10:54:38 2002
 *  Modified:    
 *  Language:    Javascript
 *  Package:     N/A
 *  Status:      Experimental (Do Not Distribute)
 *
 *  (C) Copyright 2002, StarFire Enterprises, Inc., all rights reserved.
 */
 
<!--#include virtual="ArrayUtils.js"-->
<!--#include virtual="/JSLib/ArrayUtils.js"-->
<!--#include virtual="/JSLib/Dates.js"-->
<!--#include virtual="/JSLib/Debug.js"-->
 
/******************************** -- EXAMPLE -- ********************************
<html>
  <head>
    <title>Example</title>
    <script language="javascript" src="/JSLib/ValidateForm.js">
    </script>
    <script language="javascript">
      function checkForm() {
        var clean = true;
        var f = document.exampleForm;
        var msg = " you have entered is incorrect.";
        
        clean = clean || _checkZip(f.zip, "The zip code" + msg);
        clean = clean || _checkPhone(f.phone, "The phone number" + msg);
        clean = clean || _checkPhoneLocal(f.lPhone, "The phone number" + msg);
        clean = clean || _checkPosFloat(f.posFloat, "The positive float" + msg);
      }
    </script>
  </head>
  <body>
    <form name="exampleForm">
      Zip: <input type="text" size="30" name="zip"><br>
      Phone: <input type="text" size="30" name="phone"><br>
      Local Phone: <input type="text" size="30" name="lPhone"><br>
      Positive Float: <input type="text" size="30" name="posFloat"><br>
      <br>
      <input type="button" value="Check Values" onclick="checkForm()">
    </form>
  </body>
</html>
  
******************************************************************************/

var undefined; // In case it is not defined by the host object
var error = 0; // Used by _checkForm
 

//#############################################################################
function _checkForm(form) {
   /*--------------------------------------------------------------------------
    * Uses the id values of form elements to validate the form values.
    *
    * Inputs: form - The form to check.
    *            
    * Returns: Wether the form is valid.
    *------------------------------------------------------------------------*/
    error = 0;
    
    // Default error messages
    var            emailMsg = "The e-mail address is not valid.";
    var        req_emailMsg = "Please enter a valid e-mail address.";
    var            phoneMsg = "The phone number is not valid, make sure you " +
                              "have entered an area code.";
    var        req_phoneMsg = "Please enter a valid phone number; make sure " +
	                      "you enter an area code.";
    var      local_phoneMsg = "The phone number is not valid.";
    var  req_local_phoneMsg = "Please enter a valid phone number.";
    var              zipMsg = "The zip code is not valid.";
    var          req_zipMsg = "Please enter a valid zip code.";
    var              urlMsg = "The web address is not valid. Make sure you " +
	                       "include the 'http://'";
    var          req_urlMsg = "Please enter a valid web address. Make sure " +
	                      "you include the 'http://'";
    var        pos_floatMsg; // Defined in the function
    var    req_pos_floatMsg; // Defined in the function
    var          pos_intMsg; // Defined in the function
    var      req_pos_intMsg; // Defined in the function
    var      credit_card_16 = "Your credit card number must have 16 digits.";
    var  req_credit_card_16 = "Please enter a credit card number with " + 
	                      "16 digits.";
    var       state_abbrMsg = "The state must be a two letter " +
	                      "abbreviation.";
    var   req_state_abbrMsg = "Please enter the state as a two letter " +
	                      "abbreviation.";
    var     country_abbrMsg = "The country must be a two letter " +
	                      "abbreviation.";
    var req_country_abbrMsg = "Please enter the country as a two letter " +
	                      "abbreviation.";
    var             dateMsg = "You entered an invalid date.";
    var         req_dateMsg = "Please enter a valid date.";
    var              reqMsg; // Defined in the function
    
    
    // Loop through each element in the form validating their values
    for (var i = 0; i < form.length; i++) {
	element = form[i];
	if (element.id == "") continue;
	//alert("Checking: " + element.id);
	
	// E-mail Addresses
	if (element.id == "email") {
	    if (!element.value.match(/^\W*$/))
		_checkEmail(element, emailMsg);
	} else if (element.id == "req-email") {
	    _checkEmail(element, req_emailMsg);
	}
	
	// Phone Numbers (Area code required)
	else if (element.id == "phone") {
	    if (!element.value.match(/^\W*$/))
		_checkPhone(element, phoneMsg);
	} else if (element.id == "req-phone") {
	    _checkPhone(element, req_phoneMsg);
	}
	
	// Phone Numbers (Area code not required)
	else if (element.id == "local-phone") {
	    if (!element.value.match(/^\W*$/))
		_checkPhoneLocal(element, local_phoneMsg);
	} else if (element.id == "req-local-phone") {
	    _checkPhoneLocal(element, req_local_phoneMsg);
	}

	// Zip Codes
	else if (element.id == "zip") {
	    if (!element.value.match(/^\W*$/))
		_checkZip(element, zipMsg);
	} else if (element.id == "req-zip") {
	    _checkZip(element, req_zipMsg);
	}

	// http URL's
	else if (element.id == "url") {
	    if (!element.value.match(/^\W*$/))
		_checkURL(element, urlMsg);
	} else if (element.id == "req-url") {
	    _checkURL(element, req_urlMsg);
	}
	
	// Positive Floats
	else if (element.id == "pos-float") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    pos_floatMsg = document["MSG"+element.name];
		else
		    pos_floatMsg = "The " + element.name + 
			" must be a positive number.";
		
		_checkPosFloat(element, pos_floatMsg);
	    }
	} else if (element.id == "req-pos-float") {
	    if (document["MSG"+element.name] != undefined)
	    	req_pos_floatMsg = document["MSG"+element.name];
	    else
		req_pos_floatMsg = "The " + element.name + 
		    " must be a positive number.";

	    _checkPosFloat(element, req_pos_floatMsg);
	}
	
	// Positive Integers
	else if (element.id == "pos-int") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    pos_intMsg = document["MSG"+element.name];
		else
		    pos_intMsg = "The " + element.name + 
			         " must be a positive integer.";

		_checkPosInt(element, pos_intMsg);
	    }
	} else if (element.id == "req-pos-int") {
	    if (document["MSG"+element.name] != undefined)
	    	req_pos_intMsg = document["MSG"+element.name];
	    else
		req_pos_intMsg = "The " + element.name + 
		    " must be a positive integer.";

	    _checkPosInt(element, req_pos_intMsg);
	}

	// Credit Cards
	else if (element.id == "credit-card") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    credit_card = document["MSG"+element.name];
		this.checkCreditCard(element, credit_card);
	    }
	} else if (element.id == "req-credit-card") {
	    if (document["MSG"+element.name] != undefined)
	    	req_credit_card = document["MSG"+element.name];
	    this.checkCreditCard(element, req_credit_card);
	}

	// State Abbreviations
	else if (element.id == "state-abbr") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    state_abbrMsg = document["MSG"+element.name];
		_checkStateAbbr(element, state_abbrMsg);
	    }
	} else if (element.id == "req-state-abbr") {
	    if (document["MSG"+element.name] != undefined)
	    	req_state_abbrMsg = document["MSG"+element.name];
	    _checkStateAbbr(element, req_state_abbrMsg);
	}
	
	// Country Abbreviations
	else if (element.id == "country-abbr") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    req_country_abbrMsg = document["MSG"+element.name];
		_checkCountryAbbr(element, country_abbrMsg);
	    }
	} else if (element.id == "req-country-abbr") {
	    if (document["MSG"+element.name] != undefined)
	    	req_country_abbrMsg = document["MSG"+element.name];
	    _checkCountry(element, req_country_abbrMsg);
	}

	// Dates
	else if (element.id == "date") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    dateMsg = document["MSG"+element.name];
		_checkDate(element, dateMsg);
	    }
	} else if (element.id == "req-date") {
	    if (document["MSG"+element.name] != undefined)
	    	req_dateMsg = document["MSG"+element.name];
	    
	    _checkDate(element, req_dateMsg);
	}

	// Dates - mysql
	else if (element.id == "mysql-date") {
	    if (!element.value.match(/^\W*$/)) {
		if (document["MSG"+element.name] != undefined)
		    dateMsg = document["MSG"+element.name];
		_checkDate(element, dateMsg, "mysql");
	    }
	} else if (element.id == "req-mysql-date") {
	    if (document["MSG"+element.name] != undefined)
	    	req_dateMsg = document["MSG"+element.name];
	    
	    _checkDate(element, req_dateMsg, "mysql");
	}

	// Non Blank
	else if (element.id == "req") {
	    if (document["MSG"+element.name] != undefined)
	    	reqMsg = document["MSG"+element.name];
	    else
		reqMsg = "You left the " + element.name + " field blank.";

	    _checkNonBlank(element, reqMsg);
	}
    
	if (error) break;
    }
    
    return !error; // The browser will only submit the form if we return true
}


//#############################################################################
function _checkZip(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid zip code for the form element, and formats the number.
    *
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    * 
    * Returns: Wether the zip code is valid.
    *------------------------------------------------------------------------*/
    var zip = formEl.value;
    
    // Canadian
    if (zip.match(/^[A-Z]\d[A-Z] *\d[A-Z]\d$/))
        return true;
    
    // US
    zip = zip.replace(/[ ,\-,\t]*/g, "");
    if (zip.length == 5) {
        formEl.value = zip;
        return true;
    }
    if (zip.length == 9) {
        formEl.value = zip.replace(/(.....)(....)/, "$1-$2");
        return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkURL(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid http URL in the form element.
    *
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    * 
    * Returns: Wether the http URL is valid.
    *------------------------------------------------------------------------*/
    var url = formEl.value;
    
    url = url.replace(/^\W+/, "");
    url = url.replace(/\W+$/, "");
    
    // Good
    if (url.match(/^http:\/\//i))
        return true;

    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkPhone(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid phone number, and formats the phone number, the area
    * code is not required.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the phone number is valid.
    *------------------------------------------------------------------------*/
    var phone = formEl.value;

    phone = phone.replace(/^\W+/, "");
    phone = phone.replace(/\W+$/, "");
    
    // Bad
    if (phone.match(/[A-z]/)) {
        alert(msg);
	error = 1;
        return false;
    }
    
    // Good
    phone = phone.replace(/[ ,\-,\t,(,)]*/g, "");
    if (phone.length == 10) {
        formEl.value = phone.replace(/(...)(...)(....)/, "$1-$2-$3");
        return true;
    }
    if (phone.length == 11) {
        formEl.value = phone.replace(/(.)(...)(...)(....)/, "$1-$2-$3-$4");
        return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkPhoneLocal(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid phone number, and formats the phone number, the area
    * code is not required.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the phone number is valid.
    *------------------------------------------------------------------------*/
    var phone = formEl.value;

    phone = phone.replace(/^\W+/, "");
    phone = phone.replace(/\W+$/, "");
    
    // Bad
    if (phone.match(/[A-z]/)) {
        alert(msg);
        return false;
    }
    
    // Good
    phone = phone.replace(/[ ,\-,\t,(,)]*/g, "");
    if (phone.length == 7) { // Local
        formEl.value = phone.replace(/(...)(....)/, "$1-$2");
        return true;
    }
    if (phone.length == 10) { // Area Code + Local
        formEl.value = phone.replace(/(...)(...)(....)/, "$1-$2-$3");
        return true;
    }
    if (phone.length == 11) { // County Code + Area Code + Local
        formEl.value = phone.replace(/(.)(...)(...)(....)/, "$1-$2-$3-$4");
        return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkPosFloat(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a positive floating point number.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is a positive floating point number.
    *------------------------------------------------------------------------*/
    var num = formEl.value;
    
    // Good
    if (num.match(/^\d+\.?\d*$/))
        return true;
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkPosInt(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a positive integer number.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is a positive integer number.
    *------------------------------------------------------------------------*/
    var num = formEl.value;
    
    // Good
    if (num.match(/^\d+$/))
        return true;
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkEmail(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid email address format.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is in a valid email address format.
    *------------------------------------------------------------------------*/
    var email = formEl.value;

    email = email.replace(/^\W+/, "");
    email = email.replace(/\W+$/, "");
    
    // Good
    if (email.match(/^[^\@]+@[^\.,\@]+\.[^\@]+$/)) {
	formEl.value = email;
        return true;
    }

    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function __checkCreditCard(formEl, allowTest) {
   /*--------------------------------------------------------------------------
    * Checks for a valid credit card number.
    *
    * Checks the VALIDITY!! of Visa, Amex, MC and Discover cards
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is a valid credit card number.
    *------------------------------------------------------------------------*/
    var cardNumber = formEl.value;
    var cardType = "unknown";
    
    var isValid = false;
    var ccCheckRegExp = /[^\d -]/;

    // alert("Checking Credit Cards - allowTest = " +
    //  (allowTest ? "true" : "false"));
    isValid = !ccCheckRegExp.test(cardNumber);

    if (!isValid) return isValid;

    var cardNumbersOnly = cardNumber.replace(/ |-/g,"");
    var cardNumberLength = cardNumbersOnly.length;
    var lengthIsValid = false;
    var prefixIsValid = false;
    var prefixRegExp;

    prefixRE = /^5[1-5]/;
    if (prefixRE.test(cardNumbersOnly))
	cardType = "mastercard";

    prefixRE = /^4/;
    if (prefixRE.test(cardNumbersOnly))
	cardType = "visa";

    prefixRE = /^3(4|7)/;
    if (prefixRE.test(cardNumbersOnly))
	cardType = "amex";

    prefixRE = /^6011/;
    if (prefixRE.test(cardNumbersOnly))
	cardType = "discover";

    switch(cardType) {
    case "mastercard":
        lengthIsValid = (cardNumberLength == 16);
        prefixRegExp = /^5[1-5]/;
        break;

    case "visa":
        lengthIsValid = (cardNumberLength == 16 || cardNumberLength == 13);
        prefixRegExp = /^4/;
        break;

    case "amex":
        lengthIsValid = (cardNumberLength == 15);
        prefixRegExp = /^3(4|7)/;
        break;

    case "discover":
        lengthIsValid = (cardNumberLength == 16);
        prefixRegExp = /^6011/;
        break;

    default:
        prefixRegExp = /^$/;
	lengthIsValid = false;
        //alert("Card type not found");
    }

    prefixIsValid = prefixRegExp.test(cardNumbersOnly);
    isValid = prefixIsValid && lengthIsValid;

    if (!isValid) {
	if (!formEl.className.match(/_err$/))
	    formEl.className += "_err";
    }
    if (!isValid) return isValid;

    //
    //  Handle our "test" Credit Card (only if we want them to)
    //
    if (allowTest) {
	if (cardNumbersOnly == "4999987654321098") {  // Visa
	    formEl.value = cardNumbersOnly;
	    return true;
	}

	if (cardNumbersOnly == "5199987654321098") {  // Master Card
	    formEl.value = cardNumbersOnly;
	    return true;
	}

	if (cardNumbersOnly == "349998765432109") {  // Am Ex
	    formEl.value = cardNumbersOnly;
	    return true;
	}

	if (cardNumbersOnly == "6011987654321098") {  // Discover
	    formEl.value = cardNumbersOnly;
	    return true;
	}
    }

    var numberProduct;
    var numberProductDigitIndex;
    var checkSumTotal = 0;

    for (digitCounter = cardNumberLength - 1; 
	 digitCounter >= 0; 
	 digitCounter--) {

	checkSumTotal += parseInt (cardNumbersOnly.charAt(digitCounter));
	digitCounter--;
	numberProduct = String((cardNumbersOnly.charAt(digitCounter) * 2));
	for (var productDigitCounter = 0;
	     productDigitCounter < numberProduct.length; 
	     productDigitCounter++) {

	    checkSumTotal += 
		parseInt(numberProduct.charAt(productDigitCounter));
	}
    }

    isValid = (checkSumTotal % 10 == 0);

    if (!isValid) {
	if (!formEl.className.match(/_err$/))
	    formEl.className += "_err";
    }
    //formEl.value = cardNumbersOnly;
    return isValid;
}

//#############################################################################
function _checkCountryAbbr(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid country abbreviation.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is a valid country abbreviation.
    *------------------------------------------------------------------------*/
    var country = formEl.value.toUpperCase();
    
    // Good
    if (country.match(/^[A-Z][A-Z]$/)) {
      formEl.value = country;
      return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkStateAbbr(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid state abbreviation.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is a valid state abbreviation.
    *------------------------------------------------------------------------*/
    var state = formEl.value.toUpperCase();
    
    // Good
    if ((state == "AL") || (state == "AK") || (state == "AS") ||
	(state == "AZ") || (state == "AR") || (state == "CA") ||
	(state == "CO") || (state == "CT") || (state == "DE") ||
	(state == "DC") || (state == "FM") || (state == "FL") ||
	(state == "GA") || (state == "GU") || (state == "HI") ||
	(state == "ID") || (state == "IL") || (state == "IN") ||
	(state == "IA") || (state == "KS") || (state == "KY") ||
	(state == "LA") || (state == "ME") || (state == "MH") ||
	(state == "MD") || (state == "MA") || (state == "MI") ||
	(state == "MN") || (state == "MS") || (state == "MO") ||
	(state == "MT") || (state == "NE") || (state == "NV") ||
	(state == "NH") || (state == "NJ") || (state == "NM") ||
	(state == "NY") || (state == "NC") || (state == "ND") ||
	(state == "MP") || (state == "OH") || (state == "OK") ||
	(state == "OR") || (state == "PW") || (state == "PA") ||
	(state == "PR") || (state == "RI") || (state == "SC") ||
	(state == "SD") || (state == "TN") || (state == "TX") ||
	(state == "UT") || (state == "VT") || (state == "VI") ||
	(state == "VA") || (state == "WA") || (state == "WV") ||
	(state == "WI") || (state == "WY")) {
      formEl.value = state;
      return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkRange(formEl, msg, lim1, lim2) {
   /*--------------------------------------------------------------------------
    * Checks that the value is between lim1 and lim2 inclusive.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *          lim1 - The upper or lower boundary of the range we are checking.
    *          lim2 - The upper or lower boundary of the range we are checking.
    *  
    * Returns: Wether the value is between lim1 and lim2 inclusive.
    *------------------------------------------------------------------------*/
    var value = formEl.value;
    
    // Good
    if (lim2 > lim1) {
        if ((value >= lim1) && (value <= lim2))
            return true;
    } else {
        if ((value >= lim2) && (value <= lim1))
            return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkLength(formEl, msg, lim1, lim2) {
   /*--------------------------------------------------------------------------
    * Checks that the value's length is between lim1 and lim2 inclusive.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *           lim1 - The upper or lower boundary of the range we are checking
    *           lim2 - The upper or lower boundary of the range we are checking
    *  
    * Returns: Wether the value's length is between lim1 and lim2 inclusive.
    *------------------------------------------------------------------------*/
    var length = formEl.value.length;
    
    // Good
    if (lim2 > lim1) {
        if ((length >= lim1) && (length <= lim2))
            return true;
    } else {
        if ((length >= lim2) && (length <= lim1))
            return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkNonBlank(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks that the value is not blank.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *  
    * Returns: Wether the value is not blank.
    *------------------------------------------------------------------------*/
    var value = formEl.value;
    var obj, i;

    // Radio buttons
    if (formEl.type == "radio") {
	obj = formEl.form[formEl.name];
	for (i = 0; i < obj.length; i++) {
	    if (obj[i].checked) return true;
	}

	error = 1;
	alert(msg);
	return false;
    }
    
    // Good
    if (value.match(/[^ ,\t,\r,\n]/))
        return true;
    
    // Bad
    error = 1;
    alert(msg);
    return false;
}

//#############################################################################
function _checkDate(formEl, msg, format) {
   /*--------------------------------------------------------------------------
    * Checks that the value seems is a valid date, and formats the date.
    * 
    * Inputs: formEl - The form element to check.
    *            msg - The msg to print if the value is not valid.
    *         format - The format type. (blank, mysql)
    *  
    * Returns: Wether the value is a valid date.
    *------------------------------------------------------------------------*/
    var value = formEl.value;
    var parts, len;
    var month, day, year;
    var error1 = false;
    var foundYear = false;
    var tmp;
    var months = [
        "january", "february", "march", "april", "may", "june", "july",
        "august", "september", "october", "november", "december"
    ];
    var days = [
        "sunday", "monday", "tuesday", "wednesday", "thursday", "friday",
        "saturday"
    ];
    var daysInMonth = [-1, 31, 28, 31, 30, 31, 31, 31, 31, 30, 31, 30, 31];

    // Change aliases
    value = value.replace(/(1)st/, "$1");
    value = value.replace(/(2)nd/, "$1");
    value = value.replace(/(3)rd/, "$1");
    value = value.replace(/([0,4,5,6,7,8,9])th/, "$1");
    value = value.replace(/of\W/ig, "");
    value = value.replace(/on\W/ig, "");
    value = value.replace(/in\W/ig, "");
    value = value.replace(/the\W/ig, "");
    value = value.replace(/day\W/ig, "");
    value = value.replace(/month\W/ig, "");
    
    // We remove all leading zeros so the numbers are not interpreted as octal
    value = value.replace(/([^0-9])[0]+/i, "$1");
    value = value.replace(/([^0-9])[0]+/i, "$1");
    
    // Alias numbers
    value = value.replace(/(first|one)/ig, "1");
    value = value.replace(/(second|two)/ig, "2");
    value = value.replace(/(third|three)/ig, "3");
    value = value.replace(/(fourth|four)/ig, "4");
    value = value.replace(/(fifth|five)/ig, "5");
    value = value.replace(/(sixth|six)/ig, "6");
    value = value.replace(/(seventh|seven)/ig, "7");
    value = value.replace(/(eighth|eight)/ig, "8");
    value = value.replace(/(nineth|nine)/ig, "9");
    value = value.replace(/(tenth|ten)/ig, "10");
    value = value.replace(/(eleventh|eleven)/ig, "11");
    value = value.replace(/(twelfth|twelve)/ig, "12");
    value = value.replace(/(thirteenth|thirteen)/ig, "13");
    value = value.replace(/(fourteenth|fourteen)/ig, "14");
    value = value.replace(/(fifteenth|fifteen)/ig, "15");
    value = value.replace(/(sixteenth|sixteen)/ig, "16");
    value = value.replace(/(seventeenth|seventeen)/ig, "17");
    value = value.replace(/(eighteenth|eighteen)/ig, "18");
    value = value.replace(/(nineteenth|nineteen)/ig, "19");
    value = value.replace(/(twentyth|twenty)/ig, "20");
    value = value.replace(/(twenty one|twenty first)/ig, "21");
    value = value.replace(/(twenty two|twenty second)/ig, "22");
    value = value.replace(/(twenty three|twenty third)/ig, "23");
    value = value.replace(/(twenty four|twenty fourth)/ig, "24");
    value = value.replace(/(twenty five|twenty fifth)/ig, "25");
    value = value.replace(/(twenty six|twenty sixth)/ig, "26");
    value = value.replace(/(twenty seven|twenty seventh)/ig, "27");
    value = value.replace(/(twenty eight|twenty eighth)/ig, "28");
    value = value.replace(/(twenty nine|twenty ninth)/ig, "29");
    value = value.replace(/(thirty|thirtieth)/ig, "30");
    value = value.replace(/(thirty one|thirty first)/ig, "31");
    
    // Combine all seperators into single spaces
    value = value.replace(/\W+/g, " ");
    
    parts = value.split(/ /);
    len = parts.length;

    // Check the names
    for (var i = 0; i < len; i++) {
        
        tmp = months.grepAll(parts[i].toLowerCase());
        if ((tmp.length == 1) && (month == undefined)) { 
            month = (months.grep(tmp[0]) % 12) + 1;
            parts.splice(i, 1); // Remove the entry
            len--;
            i--;
            continue;
        }
        tmp = days.grepAll(parts[i].toLowerCase());
        if ((tmp.length == 1) && (day == undefined)) {
            day = (days.grep(tmp[0]) % 7) + 1;
            parts.splice(i, 1); // Remove the entry
            len--;
            i--;
        }
    }
    //alert(parts[0] + " " + parts[1] + " " parts[2]);
    // Check the numbers
    for (var i = 0; i < len; i++) {
        if (parts[i].match(/[A-z]/)) {;
            error1 = true;
            break;
        } else {
            if ((month == undefined) && parseInt(parts[i]) <= 12)
                month = parseInt(parts[i]);
            else if ((day == undefined) && parseInt(parts[i]) <= 31)
                day = parseInt(parts[i]);
            else if (year == undefined)
                year = parseInt(parts[i]);
            else
                error1 = true;
        }
    }
   
        
    
    // Update february if we are in a leap year
    if (_isLeapYear(year))
        daysInMonth[2] = 29;
    
    // Format year
    if ((year > 1950) && (year < 2050)) {
        year %= 100;
        foundYear = true;
    }
    
    if (year < 10) year = "0" + year;
        
    // Check to see if the year is ambiguios
    if ((len < 3) && (year < 32) && !foundYear) {
        if (!confirm(month + "/" + day + "/" + year +
            "\nIs this the date you mean to enter?")) {
            error1 = true;
        }
    }
    
    // Bad
    if ((error1) || (month < 1 || month > 12) || 
        (day < 1 || day > daysInMonth[month]) ||
        (day == undefined) ||
        (month == undefined) ||
        (year == undefined) ||
        (year >= 3000)) {
        alert(msg);
	error = 1;
        return false;
    }
    
    // Good
    if (format == "mysql") {
	if (month < 10) month = "0" + month;
	if (day < 10) day = "0" + day;
	if (year < 50) year = "20" + year;
	if ((year > 50) && (year < 100)) year = "19" + year;
	formEl.value = year + "-" + month + "-" + day;
    } else {
	formEl.value = month + "/" + day + "/" + year;
    }
    return true;
}
