/***************************************************************************************************
*
*-- Form validation script by Peter Bailey (me@peterbailey.net) Copyright 2001-2002
*
*-- Rewritten by Jonathan Mendelson for compliance with Netscape 4.7+
*	Updated on August 27, 2002
*       Revision 3.0
*
*-- Table of Contents (More like an order of appearance for this document)
*	-- How to use it
*	-- Options
*	-- How it works
*	-- Validation Type List
*	-- Using bok
*	-- Additional Notes
*	-- Future Additions
*	-- Globals and Constants (for all functions expect Credit Card functions)
*	-- *** Source code for all functions except Credit Card functions ***
*	-- Documentation plus Globals and Constants for Credit Card functions
*	-- *** Source code for all Credit Card functions ***
*	-- EOD
*
*--	How to use it:
*
*	This function set will allow you to validate form input onSubmit very easily and efficiently.
*	Here is the process
*	
*		1)  Include the validate.js file to the page
*			Example: <script language="javascript" src="js/validate.js"></script>
*		2) 	add this event to any form you want validated:
*			[CODE]  onSubmit="return validateForm(this)  [/CODE]
*			Example: <form name="form1" action="" method="post" onSubmit="return validateForm(this)">
*		3)	Add validation attributes to the name parameter using proper syntax
*                       Example: <INPUT TYPE="text" NAME="Field1_alpha|bok">
*
*--	Options
*
*		1)	Add three parameters to the function validateForm.  
*                       The three optional parameters are bConfirm, bDisable and bDisableR.
*
*			bConfirm
*                         If set to 1, will prompt the user with a confirm just before submission.  
*                         The globla variable 'confirmMsg' will be the text for the CONFIRM popup.
*
*			bDisable
*                         If set to 1, will disable the submit button after a successful validation, 
*                         thus preventing multiple submissions of the same data.  Be sure to check the
*                         Constants and Globals section if you plan on bDisable
*
*			bDisableR
*                         If set to 1, will disable the reset button after a successful validation.  
*                         Be sure to check the Constants and Globals section if you plan on bDisableR
*
*			Syntax:		validateForm(this[,bConfirm[,bDisable[,bDisableR]]]);
*						this		- object.  required.
*						bConfirm	- boolean.  optional.
*						bDisable	- boolean.  optional.
*						bDisableR	- boolean.  optional.
*			Example: 	<form name="form1" action="" method="post" 
                                         onSubmit="return validateForm(this,1,1,1)">
*
*		2)  To enable 'error coloring', that is, where the form object that generates an error 
*                   receives new style properties via CSS, create a class in your CSS, enter it's name 
*                   into the 'errorClass' constant and add the onFocusOut event to the form calling the
*                   function clearStyle()
*
*			Example:	<style>
*					   .errHilite {background-color: #FFCCCC;}
*					</style>
*				 <form name="form1" action="" method="post" 
*                                 onSubmit="return validateForm(this)" 
*                                 onFocusOut="clearStyle(event.srcElement)">
*
*		3)	Sometimes more often than not, we want to validate user input format without requiring
*			the field entirely.  We just want to check its format ONLY if the user actually entered
*			data in.  By adding the optional parameter 'bok' to any validation type, you tell this 
*			script to validate the data, only if data has been entered.
*	
*
*-- How it works:
*
*	This function loops through each element in the form and checks for the existence of the alt
*	attribute.  If it exists, the data within the attribute is used the validate the associated
*	form object.  If you don't want an object validated, simply do not add any alt attribute!  
*	So, you can validate and entire form (like a credit app) in seconds! No hard-coding of form
*	names or any silly nonsense like that. Easy to add your own validation types (like checking
*	a promotional code format)
*
*	This system utilizes the pipe character '|' to separate parameters for the validation type.
*	All the required parameters are listed with each validation type below, but there is one 
*	optional parameter, 'bok'.  Please read the section at the bottom of the list titled "Using bok"
*
*	One of the optional functions you can use is clearStyle().  This script by default adds the 
*	className contained in the constant 'errorClass' to any object that requires input changes from 
*	the user.  So, by changing the value of 'errorClass' to the name of and CSS class you want to
*	use for error display, any of the rules you set in that class will be applied to the object.
*	The clearStyle() function, when properly assigned to the FORM object, will clear or reset the 
*       style only if it currently has the style set by 'errorClass'.
*
*	NOTE: The style clearing will NOT work in all broswers, but only those that fully support the
*	EVENT object.
*
*-- Validation type list
*
*  ------------------------------------------------------------------------------------------------	
*	noblank
*	
*			Errors if:	Field is left blank -OR- only whitespace characters are present
*			Syntax: 	<input type="text" name="First-Name_noblank" />
*			Notes:		Whitespace charactrs include Space, Tag, Carriage Return, Newline, Formfeed
*			Use with: 	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------	
*	alpha
*	
*			Errors if:	Field contains characters other than spacees, a-z, A-Z, 0-9, and
*					certain punctuation (period, comma, apostrophe, hyphen, ampersand)
*			Syntax: 	<input type="text" name="First-Name_noblank" />
*			Notes:		Whitespace charactrs include Space, Tag, Carriage Return, Newline, Formfeed
*			Use with: 	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------	
*	equalto|objectName
*	
*			Errors if:	Field's data does not exactly match spedfied field's data
*			Syntax: 	<input type="password" name="Password2_equalto|Password" />
*			Notes:		The value for 'objectName' must be IDENTICAL to the object's actual DOM 
*						name, or this script will NOT work (e.g. It's case sensitive)
*			Use with: 	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------			
*	length|min
*	
*			Errors if:	Field does not meet minimum length set
*			Syntax: 	<input type="password" name="Password_length|6" />
* 			Notes:		The number following the 'length' in the alt will be the
*		 				minimum required length. Do not add spaces or underscores.
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------	
*	number
*	
*			Errors if:	Field contains any character that are non-numeric (not 0-9)
*			Syntax: 	<input type="text" name="Age_number" />
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*------------------------------------------------------------------------------------------------	
*	numberl|min
*	
*			Errors if:	Field contains any character that are non-numeric (not 0-9)
*						-AND- does not meet minimum length requirement
*			Syntax: 	<input type="text" name="ID-Number_numberl|4" />
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	decimal|leftQuantity|rightQuantity
*	
*			Errors if:	Field data does not match decimal format specified
*			Syntax: 	<input type="text" name="Batting-Average_decimal|0|3" />
*			Notes:		Wildcards (*) can be used for either value
*			Examples:	decimal|*|2  matches '1234.12' -OR- '.34' -OR- '1234567890.00'
*						decimal|3|* matches '100.1' -OR- 123.987 -OR- '987.12345678'
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	decimalr|leftMinimum|leftMaximum|rightMimimum|rightMaximum
*	
*			Errors if:	Field data does not match decimal format specified
*			Syntax: 	<input type="text" name="Radio-Station_decimalr|2|3|1\1" />
*			Notes:		Wildcards (*) can be used for any value
*			Examples:	decimalr3|*|2|3 matches '123.12' -OR- '12345678.12' -OR- '9876.123'
*						decimalr0|2|1|* matches '.1' -OR- '23.123456789' -OR- '1.98'
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	money|flags
*			Errors if:	Field does not match money format specified
*			Syntax: 	<input type="text" name="Salary_money|&,." />
* 			Flags:		$ = Dollar sign required beginning of the string
*						, = Digit grouping must be applied (a comma between every 3rd digit)
*						. = The decimal plus 2 following digits is required at end of string
*			Notes:		The above flags can be used in any order and any combination.  If no flags
*						are set, then all rules become optional in the string.
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------	
*	zip	
*
*			Errors if:	Field does not match Zip or Zip+4 format
*			Syntax: 	<input type="text" name="Zip-Code_zip" />
*			Formats:	12345
*						123451234
*						12345 1234
*						12345-1234
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	phone
*
*			Errors if:	Field does not match phone format
*			Syntax: 	<input type="text" name="Phone_phone" />
*			Formats:	Many different formats
*			Notes:		Knowledge of regular expression will let you modify the
*						validation scope to suit your needs
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	email
*	
*			Errors if:	Field does not match email format
*			Syntax: 	<input type="text" name="Salary_email" />
*			Formats:	user@domain.suffix				( john@internet.com )
*						user.sub@domain.suffix			( john.doe@internet.com )
*						user.sub@domain.subd.suffix		( john.doe@email.internet.com )
*						user@ip							( john@[192.168.1.1] )
*						And several combinations of the above formats
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*  ------------------------------------------------------------------------------------------------
*	select
*
*			Errors if:	Select object is selected at 0 index, indicating no selection made
*			Syntax: 	<select name="state_select">[...options...]</select>
*			Use with:	SELECT (NOT for use with multiple select objects)
*  ------------------------------------------------------------------------------------------------
*	selecti|indexes
*
*			Errors if:	Select object is selected at any of the specified indexes
*			Syntax: 	<select name="Credit-Card-Type_selecti|0,1,6">[...options...]</select>
*			Notes:		indexes must be a comma separated string with no spaces
*			Use with:	SELECT (NOT for use with multiple select objects)
*  ------------------------------------------------------------------------------------------------
*	selectm|min|max
*
*			Errors if:	Number of selections does not meet minimum/maximum bounds set
*			Syntax: 	<select name="Sandwich-Preferences_selectm|1|3" multiple>
*						[...options...]
*						</select>
*			Notes:		For no minimum, enter 0.  For no maximum, enter 999
*						Example: alt="selectm|0|999"
*			Use with:	SELECT (for use with multiple select objects)
*  ------------------------------------------------------------------------------------------------
*	checkbox|min|max
*
*			Errors if:	Number of checked boxes does not meet minimum/maximum bounds set
*			Syntax: 	<input type="checkbox" name="Subscribe-to_checkbox|2|4" />
*						<input type="checkbox" name="Subscribe-to" />
*						<input type="checkbox" name="Subscribe-to" />
*						<input type="checkbox" name="Subscribe-to" />
*						<input type="checkbox" name="Subscribe-to" />
*			Notes:		All the names of the checkboxes to be included in the count must
*						be the same. Only add the 'alt' attribute to the first checkbox
*						in the array. For no minimum, enter 0.  For no maximum, enter 999
*						Example: alt="checkbox|0|999"
*			Use with:	INPUT type=checkbox
*  ------------------------------------------------------------------------------------------------
*	radio
*
*			Errors if:	None of the radio boxes in the group are checked
*			Syntax: 	<input type="radio" name="Inline-Skating_radio" value="Yes" />
*						<input type="radio" name="Inline-Skating" value="No" />
*			Notes:		All the names of the radio buttons to be included in the count must
*						be the same. Only add the 'alt' attribute to the first radio button
*						in the array. 
*			Use with:	INPUT type=radio
*  ------------------------------------------------------------------------------------------------
*	cc
*
*			Errors if:	Input does not validate against card rules spedified by the card type
*						-AND- does not satisfy the LUHN Checksum
*			Syntax: 	<input type="text" name="Credit-Card-Number_cc" alt="cc" onBlur="this.value=cleanupCCNum(this.value)" />
*			Notes:		See documentation at bottom of this file for more information about
*						the credit card validation capabilities of this script
*			Use with:	INPUT type=text, INPUT type=password, TEXTAREA
*
*******************************************************************************************************
*-- Using bok
*
*		The optional parameter 'bok' can be added to ANY validation type that checks data on a text-
*		based input (INPUT type=text, INPUT type=password, TEXTAREA).  'bok' will allow the field to
*		be submitted blank, but validates it against it's normal rules if any data is entered.  For 
*		example, if you do not want to require the email address, but do want to receive valid email
*		address if the user choses to enter them, then add the 'bok' parameter with the pipe character
*
*			<input type="text" name="Email_email|bok" />
*
*		The 'bok' parameter MUST ALWAYS be the last parameter.  If validating a decimal the syntax
*		would be as follows
*			
*			<input type="text" name="Batting-Average_decimal|0|3|bok" />
*
*		'bok' should NOT be used with the 'blank' validation type
*
*--	Additional notes:
*
*		The function formatName at the bottom of this include strips form object names of their 
*		underscores and hyphens. This is so that when the alert(s) are used, the user will not see 
*               the underscores.  
*		So, it is recommended that you name your fields accordingly for ease of reading to the user.
*		Example: 'First-Name' instead of 'fname' or 'Home-Phone' instead of 'HPhone'
*
*--	Future Additions
*
*		• Date validation
*		• Zip validation versus chosen State for geographical accuracy
*		• More specific control over validation format of Phone numbers and Postal codes
*
*********** WARNING: DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING! ******************
*
*--	Constants and Globals
*		Global used for flagging the validateBlank() function within most other validation functions
*/		var debug = false;
/*		Global used for skipping blank fields.
*/		var blankOK = false;
/*		Global used for class switching.  Do not modify
*/		var revertClass = '';
/*		Change this to the classname you want for the error highlighting
*/		var errorClass = 'errHilite';
/*		If the bConfirm flag is set to true, the users will be prompted with CONFIRM box with this message
*/		var confirmMsg = 'Your Data is about to be sent.\nPlease click \'Ok\' to proceed or \'Cancel\' to abort.';
/*		If user cancels CONFIRM, then this message will be alerted.  If you don't want this alert to show, then
*		empty the variable (  var confirmAbortMsg = '';  )
*/		var confirmAbortMsg = 'Submission cancelled.  Data has not been sent.';
/*		Enter the name/id of your form's submit button here (works with type=image too)
*/		var submitButton = 'SendNews';
/*		Enter the name/id of your form's reset button here (works with type=image too)
*/		var resetButton = 'Reset';
/*
*******************************************************************************************************/


function validateForm(Frm, bConfirm, bDisable, bDisableR) {
  var testOk;
  var testHack = 1;
  if (debug)
    alert('Function called, Frm.elements.length= '+Frm.elements.length);
  for (var i=0; i<Frm.elements.length; i++) {   // Loops through all the form's elements
    blankOK=false;
    if (debug)
      alert('Cycling on ['+i+']= '+Frm.elements[i].name);
    var nameField = new Array();
    nameField = Frm.elements[i].name.split(/[_]/);
    
    if (nameField[1]) {
      var validateType = nameField[1];		
      var validateObj = Frm.elements[i];
      testOk = false;			
      var params = new Array();
      params = validateType.split(/[|]/);	// Separates validation string into parameters
      if (debug) {
	for (var q=0; q<params.length; q++) {			
	  alert('params[' +q+ '] is ' + params[q]);
	}
	alert('validateObj.name is ' +validateObj.name+ ' and validateObj.value is "' + validateObj.value + '"');
      }
      if (params[0] == 'money')	{							// Sets flags for money syntax
	var dollarsign	= (params[1].indexOf('$') != -1);
	var grouping	= (params[1].indexOf(',') != -1);
	var decimal		= (params[1].indexOf('.') != -1);
      }
      if (params[params.length-1] == 'bok') {	// Sets flag if field is allowed to be blank
	blankOK = true;
      }
      
      if (debug) {
	alert('blankOK is ' + blankOK);
      }

      switch (params[0]) { // Calls appropriate validation function based on type
      case 'noblank'	: if (validateBlank(validateObj)) testOk = true; break;
      case 'alpha'	: if (validateAlpha(validateObj)) testOk = true; break;
      case 'equalto'	: if (validateEqualTo(validateObj, params[1], Frm)) testOk = true; break;
      case 'length'	: if (validateLength(validateObj, params[1])) testOk = true; break;
      case 'number'	: if (validateNumber(validateObj)) testOk = true; break;
      case 'numberl'	: if (validateNumberL(validateObj, params[1])) testOk = true; break;
      case 'decimal'	: if (validateDecimal(validateObj, params[1], params[2] )) testOk = true; break;
      case 'decimalr'	: if (validateDecimalR(validateObj, params[1], params[2], params[3], params[4] )) testOk = true; break;				
      case 'money'	: if (validateMoney(validateObj, dollarsign, grouping, decimal)) testOk = true; break;
      case 'zip'	: if (validateZip(validateObj)) testOk = true ;break;
      case 'phone'	: if (validatePhone(validateObj)) testOk = true; break;
      case 'email'	: if (validateEmail(validateObj)) testOk = true; break;
      case 'cc'	: if (validateCC(validateObj)) testOk = true; break;
      case 'select'	: if (validateSelect(validateObj)) testOk = true; break;
      case 'selectm'	: if (validateSelectM(validateObj, params[1], params[2])) testOk = true; break;
      case 'selecti'	: if (validateSelectI(validateObj, params[1])) testOk = true; break;
      case 'checkbox'	: if (validateCheckbox(validateObj, Frm.name, validateObj.name, params[1], params[2])) testOk = true; break;
      case 'radio'	: if (validateRadio(validateObj, Frm.name, validateObj.name)) testOk = true; break;
				// Add additional cases here
      default			: alert('Validation Type \'' + params[0] + '\' Not Found');
      }
      if (!testOk) 
	return false;
    }		
  }
/*******************************************************
*	Any special conditions you have can be added here
********************************************************/		
		
  if (typeof bConfirm == 'undefined') bConfirm = 0;				// Checks for submission flags
  if (typeof bDisable == 'undefined') bDisable = 0;	
  if (typeof bDisableR == 'undefined') bDisableR = 0;	
  if (bConfirm) {
    if(!confirm(confirmMsg)) {
      if (confirmAbortMsg != '') alert(confirmAbortMsg);		// Displays confim if requested
      return false;
    }
  }
  if (bDisable) Frm.elements[submitButton].disabled=true;			// Disables submit if requested
  if (bDisableR) Frm.elements[resetButton].disabled=true;			// Disables reset if requested
  return true;									// Form has been validated
}

/***************************************************************************/
function validateBlank(formObj) {
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }
  return true;
}

/***************************************************************************/
function validateAlpha(formObj) {
  var objName = formatName(formObj.name);
  var alphaCheck = /[^a-zA-Z0-9\.,\s\'\-\&]/; // Invalid case
  
  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  if (alphaCheck.test(formObj.value)) {     // Error triggered if invalid case true
    alert('Sorry, the '+objName+' field may only contain alphanumeric characters.');
    errorProcess(formObj,1,1);
    return false;			
  }
  return true;
}

/***************************************************************************/
// Special function used for bok
function checkBlank(formObj) {
  //  alert('Entered checkBlank');
  if (formObj.value == "")
    return true;

  var regex = /\S/;               // Matches non-whitespace character
  if (!regex.test(formObj.value)) // If regexp false, string does not contain whitespace characeters
    return true;		  // Return true to show field is blank
  return false;
}
		
/***************************************************************************/
function validateEqualTo(formObj, otherObjName, Frm)
	{
	var objName = formatName(formObj.name);
	var equalToValue = Frm.elements[otherObjName].value;

	if (formObj.value != equalToValue)
		{
		alert(otherObjName+' must be the same as '+objName+'.\nPlease make sure the data you entered matches.');
		errorProcess(formObj,1,1);
		return false;
		}
	return true;
	}
	
/***************************************************************************/
function validateLength(formObj,len) {
  var objName = formatName(formObj.name);	

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  if (formObj.value.length < parseInt(len)) {
    alert('The '+objName+' must be at least '+len+' characters long');
    errorProcess(formObj,1,1);
    return false;
  }		
	
  return true;
}
	
/***************************************************************************/
function validateNumber(formObj) {
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }
	
  //	numReg = "^[0-9]*$";
  //	new RegExp(numReg);
  var regex = /^[0-9]*$/;
  if (!regex.test(formObj.value)) {
    window.alert('Only numeric values are valid for the '+objName);
    errorProcess(formObj,1,1);
    return false;
  }

  return true;
}

/***************************************************************************/
function validateNumberL(formObj, len) {
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  //	numReg = "^[0-9]{"+parseInt(len)+",}$"
  var regex = '/^[0-9]{'+parseInt(len)+',}$/';
  if (!regex.test(formObj.value)) {
    window.alert('A minimum of '+len+' numeric values are required for the '+objName);
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}
/***************************************************************************/
function validateDecimal(formObj, lval, rval) {
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  (lval == '*')? lval = '*': lval = parseInt(lval);
  (rval == '*')? rval = '*': rval = parseInt(rval);
  //	var decReg = "";
  var regex = "";
  if (lval == 0)
    regex = '/^\\.[0-9]{'+rval+'}$/';	
  else if (lval == '*')
    regex = '/^[0-9]'+lval+'\\.[0-9]{'+rval+'}$/';
  else if (rval == '*')
    regex = '/^[0-9]{'+lval+'}\\.[0-9]'+rval+'$/';
  else
    regex = '/^[0-9]{'+lval+'}\\.[0-9]{'+rval+'}$/';
  //	var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    window.alert(formObj.value+' is not a valid '+objName+'.  Please re-enter the '+objName);
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validateDecimalR(formObj, lmin, lmax, rmin, rmax) {
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }
	
  (lmin == '*')? lmin = 0: lmin = parseInt(lmin);
  (lmax == '*')? lmax = '': lmax = parseInt(lmax);
  (rmin == '*')? rmin = 0: rmin = parseInt(rmin);
  (rmax == '*')? rmax = '': rmax = parseInt(rmax);
  var regex = '/^[0-9]{'+lmin+','+lmax+'}\\.[0-9]{'+rmin+','+rmax+'}$/';
  //	var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    window.alert(formObj.value+' is not a valid '+objName+'.  Please re-enter the '+objName);
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validateMoney(formObj, ds, grp, dml) {
  var objName = formatName(formObj.name);	

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }
	
  var regex;
  var moneySyntax = "";
  if (ds && grp && dml) {		// Dollar sign, grouping, and decimal
    regex = '/^\\$(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})$/';
    moneySyntax = "$XX,XXX.XX";
  }
  if (ds && grp && !dml) {	// Dollar sign and grouping
    regex = '/^\\$(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})$/';
    moneySyntax="$XX,XXX";
  }
  if (ds && !grp && dml) {	// Dollar sign and decimal
    regex = '/^\\$[0-9]*(\\.[0-9]{2})$/';
    moneySyntax="$XXXXX.XX"; 
  }
  if (!ds && grp && dml) {	// Grouping and decimal
    regex = '/^(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})?$/';
    moneySyntax="XX,XXX.XX"; 
  }
  if (ds && !grp && !dml) {	// Dollar sign only
    regex = '/^\\$[0-9]*$/';
    moneySyntax="$XXXXX"; 
  }
  if (!ds && grp && !dml) {	// Grouping only
    regex = '/^(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})$/'; 
    moneySyntax="XX,XXX"; 
  }
  if (!ds && !grp && dml)	{	// Decimal only
    regex = '/^[0-9]*(\\.[0-9]{2})$/'; 
    moneySyntax="XXXXX.XX"; 
  }
  if (!ds && !grp && !dml) {	// No params set, all special chars become optional
    regex = '/^\\$?(?:(?:[0-9]{1,3},?)(?:[0-9]{3},?)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})?$/';
    moneySyntax="[$]XX[,]XXX[.XX]"; 
  }
  //	var regex = new RegExp(moneyReg);
  if (!regex.test(formObj.value)) {
    window.alert(formObj.value+' does not match the required format of '+moneySyntax+' for '+objName+'.');
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}

/***************************************************************************/
function validateSelect(formObj) {
  var objName = formatName(formObj.name);
  if (formObj.selectedIndex == 0) {
    alert('Please select the '+objName);
    errorProcess(formObj,0,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validateSelectM(formObj, minS, maxS) {
  var objName = formatName(formObj.name);
  var selectCount = 0;
  if (maxS == 999) 
    maxS = formObj.length;
  for (var i=0; i<formObj.length; i++) {
    if (formObj.options[i].selected)
      selectCount++; 
  }
  if (selectCount < minS || selectCount > maxS) {
    alert('Please select between '+minS+' and '+maxS+' '+objName+'.\nYou currently have '+selectCount+' selected');
    errorProcess(formObj,0,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validateSelectI(formObj, indexes) {
  var objName = formatName(formObj.name);
  var arrIndexes =indexes.split(/[,]/);
  var selectOK = true;
  for (var i=0; i<arrIndexes.length; i++) {
    if (formObj.selectedIndex == arrIndexes[i])
      selectOK = false;
  }
  
  if (!selectOK) {
    alert('Please select a valid option for '+objName);
    errorProcess(formObj,0,1);
    return false;
  }
  return true;
}
		
/***************************************************************************/
function validateZip(formObj) {
  var objName = formatName(formObj.name);	

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }
  
  var regex = '/^[0-9]{5}(|[\- ]?[0-9]{4})$/';
  //	var regex = new RegExp(zipReg);
  if (!regex.test(formObj.value)) {
    window.alert("Please enter a valid 5 or 9 digit Zip code.    ");
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}

/***************************************************************************/
function validateEmail(formObj) {	
  var objName = formatName(formObj.name);

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  var emailStr = formObj.value;
  var emailReg1 = /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; // not valid
  var emailReg2 = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/; // valid
  if (!emailReg1.test(emailStr) && emailReg2.test(emailStr)) { // if syntax is valid
    return true;
  }
  else {
    window.alert("Please enter a valid email address.");
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validatePhone(formObj) {
  var objName = formatName(formObj.name);	

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  var regex = '/^(?:[\(][0-9]{3}[\)]|[0-9]{3})[-. ]?[0-9]{3}[-. ]?[0-9]{4}$/';
  if (regex.test(formObj.value)) {
    return true;
  }
  else {
    window.alert("Please enter a valid Phone number plus Area Code.");
    errorProcess(formObj,1,1);
    return false;
  }
  return true;
}
	
/***************************************************************************/
function validateCheckbox(formObj, FRM, chkbxName, minC, maxC) {
  var formObj = eval(FRM+'.'+chkbxName);
  var objName = chkbxName;
  var checkTotal = eval(FRM+'.'+chkbxName+'.length');
  var checkCount = 0;
  if (maxC == 999) maxC = checkTotal;
  for (var i=0; i<checkTotal; i++) {
    if (formObj[i].checked) checkCount++;
  }
  if (checkCount < minC || checkCount > maxC) {
    alert('Please select between '+minC+' and '+maxC+' options for '+objName+'.\nYou currently have '+checkCount+' selected');
    errorProcess(formObj[0],0,1);
    return false;
  }
  return true;
}

/***************************************************************************/	
function validateRadio(formObj, FRM, radioName) {	
  var radioLength = eval(FRM+'.'+radioName+'.length');
  var objName = formatName(formObj.name);
  var selectTotal = 0;
  for (i=0; i<radioLength; i++) {
    if (eval(FRM+'.'+radioName+'['+i+'].checked'))
      selectTotal++;	
  }
  if (selectTotal != 1) {
    alert('Please select an option for '+objName);
    errorProcess(formObj,0,1);
    return false;
  }		
  return true;
}

/***************************************************************************/
function formatName(wStr) {
  wStr = wStr.replace(/\-/g," ");
  wStr = wStr.replace(/_.*/,"");
  return wStr;
}

/***************************************************************************/	
function errorProcess(tempObj, sel, foc) {
  revertClass = tempObj.className;
  tempObj.className = errorClass;
  if (sel) tempObj.select();
  if (foc) tempObj.focus();
}

/***************************************************************************/
function clearStyle(tempObj) {
  if (tempObj.className == errorClass) tempObj.className = revertClass;
}

/****************************************** END EDIT WARNING ****************************************/	
	
/*****************************************************************************************************	
*	CREDIT CARD FUNCTIONS
*
*	If you want to use the credit card validating capabilities of this script, please read this
*	documentation before continuing
*
*--	Constants and Globals for Credit Card functions
*
*	Enter the DOM name of the SELECT object here. Make sure you pay attention to the values (CC Types)
*	used in the case statement for the function validateCC()
*/	var ccTypeObj = 'form1.Credit_Card_Type';
/*
*********** WARNING: DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING! ****************/	

function cleanupCCNum(ccNum) {
  return ccNum.replace(/\D/g,'');
}
	
/***************************************************************************/	
function validateCC(formObj) {
  var objName = formatName(formObj.name);	

  if (checkBlank(formObj)) { 
    if (blankOK) {
      blankOK=false;
      return true; 
    }
    else {
      alert('Sorry, you left ' +objName+ ' empty. This field is required.');
      errorProcess(formObj,0,1);
      return false; 
    }
  }

  switch (eval(ccTypeObj).value) {
  case 'VISA':
    var ccReg = /^4\d{12}(\d{3})?$/; 
    break;
  case 'MC': 
    var ccReg = /^5[1-5]\d{14}$/; 
    break;
  case 'DISC': 
    var ccReg = /^6011\d{12}$/; 
    break;
  case 'AMEX': 
    var ccReg = /^6011\d{12}$/; 
    break;		
  case 'DINERS':
    var ccReg = /^3[0|6|8]\d{12}$/; 
    break;
  case 'ENROUTE':
    var ccReg = /^2[014|149]\d{11}$/; 
    break;
  case 'JCB': 
    var ccReg = /^3[088|096|112|158|337|528]\d{12}$/; 
    break;
    // Add additonal card types here
  default: 
    alert('Error! Card Type not found!'); 
    return false;
  }

  var formatOK = ccReg.test(formObj.value);
  var luhnOK = validateLUHN(formObj.value);	
  if (!formatOK || !luhnOK) {
    alert('The '+objName+' you entered is not valid. Please check again and re-enter');
    errorProcess(formObj,1,1);
    return false;
  }		
  return true;
}

/***************************************************************************/	
function validateLUHN(ccString) {
  var odds = "";
  var evens = "";
  var i=1;
  for (i=0; i<ccString.length; i=i+2) {
    var digit = parseInt(ccString.charAt(i)) * 2;
    odds += digit+"";
  }
  for (i=1; i<ccString.length; i=i+2)
    evens += ccString.charAt(i);
  var luhnStr = odds + evens;
  var checkSum = 0;
  for (i=0; i<luhnStr.length; i++)
    checkSum += parseInt(luhnStr.charAt(i));
  var bool;
  (checkSum % 10 == 0)?bool=true:bool=false;
  return bool;
}
	
