/* -*-C++-*-
 *  File:        ValidateForm.js
 *  RCS:         none
 *  Description: Defines form validation functions for Javascript
 *  Author:      Scott Lundberg, 
 *  Created:     Tue Aug  16 10:54:38 2002
 *  Modified:    
 *  Language:    Javascript
 *  Package:     N/A
 *  Status:      Experimental (Do Not Distribute)
 *
 *  (C) Copyright 2002, Scott Lundberg, all rights reserved.
 */
 
<!--#include virtual="/Shared/Javascript/ArrayUtils.js"-->
<!--#include virtual="/Shared/Javascript/Dates.js"-->
<!--#include virtual="/Shared/Javascript/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 you entered is not valid.";
    var        req_emailMsg = "Please enter a valid e-mail address.";
    var           emailsMsg = "The e-mail addresses you entered are not valid.";
    var       req_emailsMsg = "Please enter one or more valid e-mail addresses.";
    var            phoneMsg = "The phone number you entered 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        numMsg; // Defined in the function
    var    req_numMsg; // 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        hex_colorMsg = "You must enter the colors as a six digit " +
	                      "hexidecimal numbers.";
    var    req_hex_colorMsg = "You must enter the color as a six digit " +
	                      "hexidecimal number.";
    var            colorMsg = "You must enter colors as a six digit " +
	                      "hexidecimal numbers or common names.";
    var        req_colorMsg = "You must enter a color as a six digit " +
	                      "hexidecimal number or common name.";
    var             dateMsg = "You entered an invalid date.";
    var         req_dateMsg = "Please enter a valid date.";
    var         alphaNumMsg = "You entered an invalid alpha-numeric string.";
    var     req_alphaNumMsg = "Please enter a valid alpha-numeric string.";
    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];

	// Erase and skip diabled elements
	if (element.disabled) {
	    element.value = "";
	    continue;
	}
	
	// E-mail Addresses
	if (element.id.match(/^email_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    msg = document["MSG"+element.name];
		else
		    msg = emailMsg;
		_checkEmail(element, msg);
	    }
	} else if (element.id.match(/^req-email_/)) {
	    if (document["MSG"+element.name] != undefined)
		    msg = document["MSG"+element.name];
		else
		    msg = req_emailMsg;
		req_emailMsg = document["MSG"+element.name];
	    _checkEmail(element, msg);
	}
	
	// Multiple E-mail Addresses
	if (element.id.match(/^emails_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    msg = document["MSG"+element.name];
		else
		    msg = emailsMsg;
		_checkEmails(element, msg);
	    }
	} else if (element.id.match(/^req-emails_/)) {
	    if (document["MSG"+element.name] != undefined)
		    msg = document["MSG"+element.name];
		else
		    msg = req_emailsMsg;
		req_emailsMsg = document["MSG"+element.name];
	    _checkEmails(element, msg);
	}
	
	// Phone Numbers (Area code required)
	else if (element.id.match(/^phone_/)) {
	    if (!element.value == "")
		_checkPhone(element, phoneMsg);
	} else if (element.id.match(/^req-phone_/)) {
	    _checkPhone(element, req_phoneMsg);
	}
	
	// Phone Numbers (Area code not required)
	else if (element.id.match(/^local-phone_/)) {
	    if (!element.value == "")
		_checkPhoneLocal(element, local_phoneMsg);
	} else if (element.id.match(/^req-local-phone_/)) {
	    _checkPhoneLocal(element, req_local_phoneMsg);
	}

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

	// http URL's
	else if (element.id.match(/^url_/)) {
	    if (!element.value == "")
		_checkURL(element, urlMsg);
	} else if (element.id.match(/^req-url_/)) {
	    _checkURL(element, req_urlMsg);
	}
	
	// Positive Floats
	else if (element.id.match(/^pos-float_/)) {
	    if (!element.value == "") {
		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.match(/^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);
	}

	// Numbers
	else if (element.id.match(/^num_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    numMsg = document["MSG"+element.name];
		else
		    numMsg = "The " + element.name + 
			" must be a number.";
		
		_checkNum(element, numMsg);
	    }
	} else if (element.id.match(/^req-num_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_numMsg = document["MSG"+element.name];
	    else
		req_numMsg = "The " + element.name + 
		    " must be a number.";

	    _checkNum(element, req_numMsg);
	}
	
	// Positive Integers
	else if (element.id.match(/^pos-int_/)) {
	    if (!element.value == "") {
		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.match(/^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 with 16 digits
	else if (element.id.match(/^credit-card-16_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    credit_card_16 = document["MSG"+element.name];
		_checkCreditCard16(element, credit_card_16);
	    }
	} else if (element.id.match(/^req-credit-card-16_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_credit_card_16 = document["MSG"+element.name];
	    _checkCreditCard16(element, req_credit_card_16);
	}
	
	// State Abbreviations
	else if (element.id.match(/^state-abbr_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    state_abbrMsg = document["MSG"+element.name];
		_checkStateAbbr(element, state_abbrMsg);
	    }
	} else if (element.id.match(/^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.match(/^country-abbr_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    req_country_abbrMsg = document["MSG"+element.name];
		_checkCountryAbbr(element, country_abbrMsg);
	    }
	} else if (element.id.match(/^req-country-abbr_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_country_abbrMsg = document["MSG"+element.name];
	    _checkCountryAbbr(element, req_country_abbrMsg);
	}

	// Hex Colors
	else if (element.id.match(/^hex-color_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    hex_colorMsg = document["MSG"+element.name];
		_checkHexColor(element, hex_colorMsg);
	    }
	} else if (element.id.match(/^req-hex-color_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_hex_colorMsg = document["MSG"+element.name];
	    _checkHexColor(element, req_hex_colorMsg);
	}

	// HTML Colors
	else if (element.id.match(/^color_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    colorMsg = document["MSG"+element.name];
		_checkHTMLColor(element, colorMsg);
	    }
	} else if (element.id.match(/^req-color_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_colorMsg = document["MSG"+element.name];
	    _checkHTMLColor(element, req_colorMsg);
	}

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

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

	// Alpha Numeric
	else if (element.id.match(/^alpha-num_/)) {
	    if (!element.value == "") {
		if (document["MSG"+element.name] != undefined)
		    alphaNumMsg = document["MSG"+element.name];
		_checkAlphaNum(element, alphaNumMsg, "mysql");
	    }
	} else if (element.id.match(/^req-alpha-num_/)) {
	    if (document["MSG"+element.name] != undefined)
	    	req_alphaNumMsg = document["MSG"+element.name];
	    
	    _checkAlphaNum(element, req_alphaNumMsg, "mysql");
	}
        
	// Non Blank
        else if (element.id.match(/^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;
    
    // Good
    if (url.match(/^ftp:\/\//i))
        return true;

    // Good
    if (url.match(/^mailto:/i))
        return true;
    
    // Good
    if (url.match(/^mailto:/i))
        return true;

    // Good
    if (url.match(/^https:\/\//i))
        return true;

    // Good
    if (url.match(/^rtsp:\/\//i))
        return true;

    // Good
    if (url.match(/^gopher:\/\//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);
	error = 1;
        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 _checkNum(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a 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 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(/^([0-9A-z_\.-]+@[0-9A-z_\.-]+,?)+$/)) {
	formEl.value = email;
        return true;
    }

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

//#############################################################################
function _checkEmails(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid email address list.
    * 
    * 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+$/, "");
    
    // Bad
    if (email.match(/[^0-9A-z_\., @-]/)) {
        alert(msg);
        error = 1;
    }
    
    // Good
    if (email.match(/[0-9A-z_\.-]+@[0-9A-z_\.-]+\.[0-9A-z_\.-]+/)) {
	formEl.value = email;
        return true;
    }

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

//#############################################################################
function _checkCreditCard16(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid 16 digit credit card 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 valid 16 digit credit card number.
    *------------------------------------------------------------------------*/
    var number = formEl.value;
    
    // Good
    number = number.replace(/[^0-9]*/g, "");
    if (number.length == 16) {
        formEl.value = number.replace(/(....)(....)(....)(....)/,
				      "$1 $2 $3 $4");
        return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkAlphaNum(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for only alpha numeric characters and underscore.
    * 
    * 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 alpha numeric character string.
    *------------------------------------------------------------------------*/
    var str = formEl.value;
    
    // Good
    if (str.match(/^[A-z0-9_]+$/))
        return true;
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
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 _checkHexColor(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid Hex color code.
    * 
    * 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 Hex color code.
    *------------------------------------------------------------------------*/
    var color = formEl.value.toUpperCase();

    // Good
    if (color.match(/^#?[A-Z0-9]{6}$/)) {
	formEl.value = color;
	return true;
    }
    
    // Bad
    alert(msg);
    error = 1;
    return false;
}

//#############################################################################
function _checkHTMLColor(formEl, msg) {
   /*--------------------------------------------------------------------------
    * Checks for a valid HTML color.
    * 
    * 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 HTML color.
    *------------------------------------------------------------------------*/
    var color = formEl.value.toLowerCase();
    
    // Good
    if (color.match(/^red$/) || color.match(/^green$/) ||
	color.match(/^blue$/) || color.match(/^orange$/) || 
	color.match(/^teal$/) || color.match(/^brown$/) || 
	color.match(/^yellow$/) || color.match(/^gray$/) ||
	color.match(/^black$/) || color.match(/^white$/) || 
	color.match(/^purple$/) || color.match(/^maroon$/) ||
	color.match(/^violet$/) || color.match(/^tan$/) ||
	color.match(/^snow$/) || color.match(/^silver$/) ||
	color.match(/^pink$/) || color.match(/^Salmon$/) || 
	color.match(/^olive$/) || color.match(/^navy$/) ||
	color.match(/^magenta$/) || color.match(/^lime$/) ||
	color.match(/^indigo$/) || color.match(/^gold$/) || 
	color.match(/^cyan$/) || color.match(/^azure$/) || 
	color.match(/^beige$/)) {

	formEl.value = color;
	return true;
    }

    // Good
    if (color.match(/^#?[a-z0-9]{6}$/)) {
	formEl.value = color.toUpperCase();
	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;
    
    if (value == "") {
	 error = 1;
	 alert(msg);
	 return false;
    }

    // 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, "");

    // Remove days of the week
    value = value.replace(/sunday[^0-9a-z]*/ig, "");
    value = value.replace(/monday[^0-9a-z]*/ig, "");
    value = value.replace(/tuesday[^0-9a-z]*/ig, "");
    value = value.replace(/wednesday[^0-9a-z]*/ig, "");
    value = value.replace(/thursday[^0-9a-z]*/ig, "");
    value = value.replace(/friday[^0-9a-z]*/ig, "");
    value = value.replace(/saturday[^0-9a-z]*/ig, "");
    value = value.replace(/sun[^0-9a-z]*/ig, "");
    value = value.replace(/mon[^0-9a-z]*/ig, "");
    value = value.replace(/tue[^0-9a-z]*/ig, "");
    value = value.replace(/wed[^0-9a-z]*/ig, "");
    value = value.replace(/thu[^0-9a-z]*/ig, "");
    value = value.replace(/fri[^0-9a-z]*/ig, "");
    value = value.replace(/sat[^0-9a-z]*/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 && (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--;
        }
    }

    // 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;
}
