// Copyright 2002 KK-TEK. All rights reserved.
var enableAlerts = false;
var lastValidationFieldName;
var lastValidationFieldValue;
var lastValidationMethod;
var lastValidationErrorMsg;

function initValidation(field, method) {
	lastValidationFieldName = field.name;
	lastValidationFieldValue = field.value;
	lastValidationMethod = method;
	lastValidationErrorMsg = '';
}
function doAlert(val) {
	if (enableAlerts)
		alert(val);

	re = /\n/gi;
	lastValidationErrorMsg = val.replace(re, " ");
}

/********************************************************************
 * StripSpaces()													*
 *																	*
 * Removes spaces from the string passed in and returns that string	*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		val				string		Value to strip spaces from		*
 *																	*
 * Returns: String													*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function StripSpaces(val) {
	re = /\ /gi;
	return val.replace(re, "");
}

/********************************************************************
 * StripDigits()													*
 *																	*
 * Removes digits from the string passed in and returns that string	*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		val				string		Value to strip digits from		*
 *																	*
 * Returns: String													*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function StripDigits(val) {
	re = /1|2|3|4|5|6|7|8|9|0/gi;
	return val.replace(re, "");
}

/********************************************************************
 * SetDelim()														*
 *																	*
 * Replaces any delimiting character from the string passed in with	*
 * a common delimiter and returns the resulting string.				*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		val				string		Value to strip characters from	*
 *		delim			string		new delimiter character			*
 *																	*
 * Returns: String													*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function SetDelim(val, delim) {
	newstr = val;

	re1 = /\ /gi;
	newstr = newstr.replace(re1, delim);
	re1 = /\./gi;
	newstr = newstr.replace(re1, delim);
	re1 = /,/gi;
	newstr = newstr.replace(re1, delim);
	re1 = /\(/gi;
	newstr = newstr.replace(re1, delim);
	re1 = /\)/gi;
	newstr = newstr.replace(re1, delim);
	re1 = /-/gi;
	newstr = newstr.replace(re1, delim);
	re1 = /\//gi;
	newstr = newstr.replace(re1, delim);
	re1 = /\\/gi;
	newstr = newstr.replace(re1, delim);
	
	return newstr;
}

/********************************************************************
 * StripDelim()														*
 *																	*
 * Removes any delimiting character from the string passed in and	*
 * returns the resulting string.									*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		val				string		Value to strip characters from	*
 *																	*
 * Returns: String													*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function StripDelim(val, delim) {
	return SetDelim(val,"");
}

/********************************************************************
 * StripZipOrPhone()												*
 *																	*
 * Removes any delimiting character from the string passed in and	*
 * returns a string of only numbers.								*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		val				string		Value to strip characters from	*
 *																	*
 * Returns: String													*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function StripZipOrPhone(val) {
	newstr = SetDelim(val, "");
	return newstr;
}

/********************************************************************
 * CheckRequired() / CheckRequiredFocused()							*
 *																	*
 * Checks the field passed in to make sure it passes the validation	*
 * requirements.  If the field fails validation, the message is		*
 * displayed and the field keeps focus() if CheckRequiredFocused() is used.	*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		minlen			int			Minimum length for the field	*
 *		maxlen			int			Maximum length for the field	*
 *		response		string		What to display in the alert	*
 *		validation		string		Type of data for the field		*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckRequiredFocused (field, minlen, maxlen, response, validation) {
	if (CheckRequired(field, minlen, maxlen, response, validation))
		return true;
	// else
	field.focus();
	return false;
}

function CheckRequired (field, minlen, maxlen, response, validation) {
	newstr = StripSpaces(field.value);
	var re = /,/gi;
	var numstr = newstr.replace(re, "");
	var format = validation.toLowerCase();
	
	initValidation(field, format);

	if ((numstr == "") && (minlen == 0)) {
		return true;
	}
	else if ((numstr == "") && (minlen != 0)) {
		if (response != "")
			doAlert('The ' + response + ' is required.\nPlease enter your ' + response + '.');
		return false;
	}
	else if ((minlen > 0) && (minlen == maxlen) && (newstr.length != minlen)) {
		if (response != "")
			doAlert('The ' + response + ' must be ' + minlen + ' characters.');
		return false;
	}
	else if ((minlen > 0) && (newstr.length < minlen)) {
		if (response != "")
			doAlert('The ' + response + ' is too short.\nThe ' + response + ' must be at least ' + minlen + ' characters.');
		return false;
	}
	else if ((maxlen > 0) && (newstr.length > maxlen)) {
		if (response != "")
			doAlert('The ' + response + ' is too long.\nPlease limit ' + response + ' to ' + maxlen + ' characters.');
		return false;
	}
	else if ((format == "statecode") && (newstr.length != 2)) {
		if (response != "")
			doAlert('The ' + response + ' is invalid.\nState alpha codes must be EXACTLY 2 characters.');
		return false;
	}
	else if (isNaN(numstr) && (format == "numeric")) {
		if (response != "")
			doAlert('The ' + response + ' must be numeric.');
		return false;
	}
	else if (isNaN(numstr) && (format == "nonzero")) {
		if (response != "")
			doAlert('The ' + response + ' must be numeric and non-zero.');
		return false;
	}
	else if ((format == "currency") && (isNaN(numstr) || (numstr.indexOf(".") < numstr.length - 3))) {
		if (response != "")
			doAlert('The ' + response + ' must be a valid dollar amount.');
		return false;
	}
	else if ((format == "currency") && (maxlen > 0) && (numstr.indexOf(".") < 0) && (newstr.length > maxlen - 3)) {
		if (response != "")
			doAlert('The ' + response + ' must be less than ' + Math.pow(10, maxlen - 3) + '.00 dollars.');
		return false;
	}
	else if ((format == "currency") && (parseFloat(numstr) <= 0.01)) {
		if (response != "")
			doAlert('The ' + response + ' must be greater than zero.');
		return false;
	}
	else if ((format == "nonzero") && (parseInt(numstr, 10) <= 0)) {
		if (response != "")
			doAlert('The ' + response + ' must not be zero.');
		return false;
	}
	else if (!isNaN(numstr) && (format == "non-numeric")) {
		if (response != "")
			doAlert('The ' + response + ' must not be numeric.');
		return false;
	}
	else if (format == "alpha") {
		var iChars = "0123456789!@*|,\":<>[]{}`\';()&$#%.?/\\+=-";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(newstr.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if (format == "name") {
		var iChars = "0123456789!@*|,\":<>[]{}`\;()&$#%.?/\\+=";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(newstr.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if (format == "alphanumeric") {
		iChars = "!@*|,\":<>[]{}`\';()&$#%.?/\\+=-";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(newstr.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if (format == "addressline") {
		iChars = "!@*|,\"<>[]{}`\;()&$#%?\\+=";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(newstr.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if (format == "nospace") {
		iChars = "\ !@*|,\":<>[]{}`\';()&$#%.?/\\+=-";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(field.value.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if (format == "password") {
		iChars = "\ \"`\';/\\";

		for (var i = 0; i < newstr.length; i++) {
			if (iChars.indexOf(field.value.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid characters found in ' + response + '.');
				return false;
			}
		}
		return true;
	}
	else if ((format == "numeric") || (format == "nonzero") || (format == "orderprice") || (format == "currency")) {
		field.value = numstr;
		return true;
	}
	else if ((format == "fein") || (format == "duns") || (format == "ssn")) {
		// FEIN format:		nn-nnnnnnn
		// DUNS Number:		nn-nnn-nnnn
		// SSN format:		nnn-nn-nnnn
		if (isNaN(numstr) || (numstr.length != 9)) {
			if (response != "")
				doAlert('The ' + response + ' must be 9 numeric characters.');
			return false;
			}
		else if (format == "fein") {
			field.value = newstr.substr(0, 2) + "-" + newstr.substr(2, 7);
			return true;
		}
		else if (format == "duns") {
			field.value = newstr.substr(0, 2) + "-" + newstr.substr(2, 3) + "-" + newstr.substr(5, 4);
			return true;
		}
		else if (format == "ssn") {
			field.value = newstr.substr(0, 3) + "-" + newstr.substr(3, 2) + "-" + newstr.substr(5, 4);
			return true;
		}
	}
	else if ((format == "month") && (isNaN(numstr) || (parseInt(numstr, 10) < 1) || (parseInt(numstr, 10) > 12))) {
		if (response != "")
			doAlert('The ' + response + ' must be a valid month.');
		return false;
	}
	else if ((format == "year") && isNaN(numstr)) {
		if (response != "")
			doAlert('The ' + response + ' must be a valid year.');
		return false;
	}
	else if (format == "date") {
		return CheckDate(field, true, response);
	}
	else if (format == "phone") {
		return CheckPhone(field, true, response);
	}
	else if (format == "email") {
		return CheckEmail(field, true, response);
	}
	else if (format == "zipcode") {
		return CheckZip(field, true, response);
	}
	else if (format == "canadazip") {
		return CheckCanadianZip(field, true, response);
	}
	else {
		return true;
	}
}

/********************************************************************
 * CheckRadio()														*
 *																	*
 * Determins if a value has been selected from a group of radio		*
 * buttons															*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckRadio(field, response) {
	initValidation(field, 'radio');

	for (i=0; i<field.length; i++) {
		if (field[i].checked) {
			return true;
		}
	}
	if (response != "")
		doAlert('One of the options for ' + response + ' must be selected.');
	return false;
}

/********************************************************************
 * GetRadioValue()													*
 *																	*
 * Returns the value of a radio group								*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *																	*
 * Returns: the value of the radio selected											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function GetRadioValue(field) {
	var retVal = null;
	for (i=0; i<field.length; i++) {
		if (field[i].checked) {
			value = field[i].value
			break;
		}
	}
	return value;
}

/********************************************************************
 * CheckDate()														*
 *																	*
 * Checks the date field to make sure it is enterd properly.  If	*
 * it failed, then an alert is displayed.	*
 * Otherwise, field is reformatted as MM-DD-YYYY					*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/

function CheckDate (field, required, response) {
	var	newstr = SetDelim(field.value, "-");
	
	initValidation(field, 'date');
	if (newstr == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			return true;
		}
	}
	else if ((newstr.indexOf("-") < 0) && (newstr.length != 4) && (newstr.length != 6) && (newstr.length != 8)) {
		if (response != "")
			doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
		return false;
	}
	else if ((newstr.indexOf("-") < 0) && (isNaN(newstr))) {
		if (response != "")
			doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
		return false;
	}
	else {
		var nToday = new Date();
		var nMonth = 0;
		var nDay = 0;
		var nYear = 0;
		var DateParts = newstr.split("-");
		
		if (newstr.indexOf("-") < 0) {
			nMonth = newstr.substr(0, 2);
			nDay = newstr.substr(2, 2);
			
			if (newstr.length == 4) {
				nYear = nToday.getYear();
				if (nYear < 1000) {
					nYear += 1900;	/** Support for Netscape getYear() behavior **/
				}
			}
			else if (newstr.length == 6) {
				nYear = newstr.substr(4, 2);
			}
			else {
				nYear = newstr.substr(4, 4);
			}
		}
		else if (DateParts.length == 2) {
			nMonth = DateParts[0];
			nDay = DateParts[1];
			nYear = nToday.getYear();
			if (nYear < 1000) {
				nYear += 1900;	/** Support for Netscape getYear() behavior **/
			}
		}
		else if (DateParts.length == 3) {
			nMonth = DateParts[0];
			nDay = DateParts[1];
			nYear = DateParts[2];
		}
		
		if ((nMonth == '') || (nDay == '') || (nYear == '')) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if (isNaN(nMonth) || isNaN(nDay) || isNaN(nYear)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if ((nMonth < 1) || (nMonth > 12)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if ((nDay < 1) || (nDay > 31)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if (((nMonth == 4 || nMonth == 6 || nMonth == 9 || nMonth == 11)) && (nDay > 30)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if ((nMonth == 2) && (nDay > 29)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if ((nMonth == 2) && (nDay > 28) && ((nYear % 4 != 0) || ((nYear % 100 == 0) && (nYear % 400 != 0)))) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if ((nYear > 99) && (nYear < 1900)) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else if (nYear > 2099) {
			if (response != "")
				doAlert('The ' + response + ' field is not a valid date.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			if (nMonth < 10) {
				nMonth = "0" + parseInt(nMonth, 10);
			}
			else {
				nMonth = parseInt(nMonth, 10);
			}
			if (nDay < 10) {
				nDay = "0" + parseInt(nDay, 10);
			}
			else {
				nDay = parseInt(nDay, 10);
			}
			nYear =  parseInt(nYear, 10);
			if (nYear < 90) {
				nYear += 2000;
			}
			if (nYear < 100) {
				nYear += 1900;
			}
			field.value = nMonth + '-' + nDay + '-' + nYear;
			return true;
		}
	}
}

/********************************************************************
 * CheckPhone()														*
 *																	*
 * Checks the phone number to make sure it is enterd properly.  If	*
 * it failed, then an alert is displayed.	*
 * Otherwise, field is reformatted as (###)###-####					*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/

function CheckPhone (field, required, response) {
	initValidation(field, 'phone');
	newstr = StripZipOrPhone(field.value);
	if (newstr == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			return true;
		}
	}
	else if ((newstr.length == 10) && (!isNaN(newstr))) {
		field.value = "(" + newstr.substr(0, 3) + ")" + newstr.substr(3, 3) + "-" + newstr.substr(6, 4);
		return true;
	}
	else {
		if (response != "")
			doAlert('The ' + response + ' is not a valid phone number.\nUse the format of ###-###-####.');
		return false;
	}
}

/********************************************************************
 * CheckCanadianZip()												*
 *																	*
 * Checks the ZIP code to make sure it is enterd properly.  If		*
 * it failed, then an alert is displayed.	*
 * Otherwise, field is reformatted as A#A_#A#						*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckCanadianZip (field, required, response) {
	newstr = StripZipOrPhone(field.value);
	initValidation(field, 'canadazip');
	if (newstr == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			return true;
		}
	}
	else if (newstr.length == 6) {
		newstr = newstr.substr(0, 3) + " " + newstr.substr(3, 4);
		newstr = newstr.toUpperCase();
		
		if ((newstr.charAt(0) == 'W') || (newstr.charAt(0) == 'Z')) {
			if (response != "")
				doAlert('Invalid ' + response + '. ('+newstr+')');
			return false;
		}
		else {
			iChars = "ABCEGHJKLMNPRSTVWXYZ";	//Can't have chars = "DFIOQU"
			iNums = "1234567890";
			if ((iChars.indexOf(newstr.charAt(0)) == -1) ||
				(iNums.indexOf(newstr.charAt(1)) == -1) ||
				(iChars.indexOf(newstr.charAt(2)) == -1) ||
				(iNums.indexOf(newstr.charAt(4)) == -1) ||
				(iChars.indexOf(newstr.charAt(5)) == -1) ||
				(iNums.indexOf(newstr.charAt(6)) == -1)) {
				if (response != "")
					doAlert('Invalid ' + response + '. ('+newstr+')');
				return false;
			}
			else {
				field.value = newstr.toUpperCase();
				return true;
			}
		}
	}
	else {
		if (response != "")
			doAlert('The ' + response + ' is not a valid Canadian ZIP Code.\nUse the format of A#A #A#.');
		return false;
	}
}

/********************************************************************
 * CheckUSZip()														*
 *																	*
 * Checks the ZIP code to make sure it is enterd properly.  If		*
 * it failed, then an alert is displayed.	*
 * Otherwise, field is reformatted as ##### or #####-####			*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckUSZip (field, required, response) {
	newstr = StripZipOrPhone(field.value);
	initValidation(field, 'zipcode');
	if (newstr == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			return true;
		}
	}
	else if ((newstr.length == 9) && (!isNaN(newstr))) {
		field.value = newstr.substr(0, 5) + "-" + newstr.substr(5, 4);
		return true;
	}
	else if ((newstr.length == 5) && (!isNaN(newstr))) {
		field.value = newstr;
		return true;
	}
	else {
		if (response != "")
			doAlert('The ' + response + ' is not a valid ZIP Code.\nUse a format of ##### or #####-####');
		return false;
	}
}

/********************************************************************
 * CheckZip()														*
 *																	*
 * Checks the ZIP code to make sure it is enterd properly.  If		*
 * it failed, then an alert is displayed.	*
 * Otherwise, field is reformatted as ##### or #####-####			*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: True or False											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckZip (field, required, response) {
	newstr = StripZipOrPhone(field.value);
	initValidation(field, 'zipcode');
	if (newstr == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter a valid ' + response + '.');
			return false;
		}
		else {
			return true;
		}
	}
	else if ((newstr.length == 9) && (!isNaN(newstr))) {
		field.value = newstr.substr(0, 5) + "-" + newstr.substr(5, 4);
		return true;
	}
	else if ((newstr.length == 6) && (isNaN(newstr))) {
		return CheckCanadianZip(field, required, response);
	}
	else if ((newstr.length == 5) && (!isNaN(newstr))) {
		field.value = newstr;
		return true;
	}
	else {
		if (response != "")
			doAlert('The ' + response + ' is not a valid ZIP Code.\nUse a format of ##### or #####-####\nor A#A #A# for Canadian addresses.');
		return false;
	}
}

/********************************************************************
 * CheckEmail()														*
 *																	*
 * Checks an email field to make sure it is entered properly.		*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: true or false											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckEmail(field, required, response) {
	initValidation(field, 'email');

	/**  If the field is blank and it is required, then bail  **/
	if (field.value == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter your ' + response + '.');
			return false;
		}
		return true;
	}

	/**  Split the string into an array using the @ since Email is username@domain  **/
	atArray = field.value.split('@');
	if (atArray.length != 2) {
		if (response != "")
			doAlert('Invalid Email address detected.\nPlease verify your Email address.');
		return false;
	}

	/**  if the username is in quotes then the rules are wide open  **/
	var UserName = atArray[0]

	if ((UserName.charAt(0) == '\"') && (UserName.charAt(UserName.length - 1) == '\"')) {
		quoteArray = UserName.split('\"');
		if (quoteArray.length != 3) {
			/**  should be only 2 quotes which means 3 string parts (null,name,null)  **/
			if (response != "")
				doAlert('Invalid name in Email address detected.\nPlease verify your Email address.');
			return false;
		}

	} else {
		var iChars = "*|,\":<>[]{}`\';()&$#% ";
		for (var i = 0; i < UserName.length; i++) {
			if (iChars.indexOf(UserName.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid name detected in Email address.\nPlease verify your Email address.');
				return false;
			}
		}
	}

	var DomainName = atArray[1]
	/**  Split the domain into an array using the .  **/
	dotArray = DomainName.split('.');

	/**  if the e-mail domain is at an IP address (joe@[123.124.233.4]) make sure the IP address is valid.  **/
	var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/
	var IPPattern = DomainName.match(ipDomainPat)

	if ((IPPattern != null) && (dotArray.length == 4)) {
		/* this is an IP address */
		for (var i=0; i<4; i++) {
		    if ((dotArray[i] > 255) || (dotArray[i] < 1)) {	/**  still need to check for non-routable IPs  **/
				if (response != "")
		            doAlert("Destination IP address is invalid!\nPlease verify your Email address.");
		        return false;
		    }
		}
	}
	else if (dotArray.length < 2) {
		if (response != "")
			doAlert('Unrecognizable domain detected.\nPlease verify your Email address.');
		return false;
	} 
	else if (dotArray[dotArray.length-1].length < 2) {
			/**  If there isn't a xxx or xx at the end, then it is bad  **/
			if (response != "")
				doAlert('Invalid Email address top domain detected.\nPlease verify your Email address.');
			return false;
	}
	else {
		var iChars = "*|,\":<>[]{}`\';()&$#% ";

		for (var i = 0; i < DomainName.length; i++) {
			if (iChars.indexOf(DomainName.charAt(i)) != -1) {
				if (response != "")
					doAlert('Invalid Email domain address detected.\nPlease verify your Email address.');
				return false;

			}
		}
	}
	return true;
}
/********************************************************************
 * CheckLUHN()														*
 *																	*
 * Checks a numeric value (e.g. credit card) with LUHN algorhythm	*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		field			field		Field object to verify			*
 *		required		boolean		True if the field is required	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: true or false											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckLUHN(field, required, response) {
	initValidation(field, 'creditcard');

	/**  If the field is blank and it is required, then bail  **/
	if (field.value == "") {
		if (required) {
			if (response != "")
				doAlert('The ' + response + ' field is required.\nPlease enter your ' + response + '.');
			return false;
		}
	}

	newstr = StripZipOrPhone(field.value);
	if (isNaN(newstr)) {
		if (response != "")
			doAlert('The ' + response + ' field must be numeric.');
		return false;
	}

	var luhnVal = 0;
	for (var i = newstr.length; i > 0; i--) {
		var luhnDigit = parseInt(newstr.charAt(i-1), 10);
		if ((newstr.length - i) % 2 != 0) {
			luhnDigit += luhnDigit;
			if (luhnDigit > 9)
				luhnDigit -= 9;
		}
		luhnVal += luhnDigit;
	}

	if (luhnVal % 10 == 0)
		return true;

	if (response != "")
		doAlert('The ' + response + ' field is not valid.');
	return false;
}

/********************************************************************
 * CheckCCNum()														*
 *																	*
 * Checks a credit card number for valid ranges and LUHN checksum	*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		numfield		field		CC Number Field to verify		*
 *		typefield		field		CC Card type Field to verify	*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: true or false											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckCCNum(numfield, typefield, response) {
	var errMsg = response + " Credit Card Number";

	initValidation(numfield, 'creditcard');
	if (CheckLUHN(numfield, true, errMsg)) {
		// we passed the LUHN algorhythm, so validate the CC# by type
		ccNumber = StripZipOrPhone(numfield.value);
		switch (typefield.value) {
			case "AmExCard":
				if ((ccNumber.length == 15) &&
						("34,37".indexOf(ccNumber.substr(0,2)) >= 0))
					return true;
				break;

			case "DinersClubCard":
				if ((ccNumber.length == 14) &&
						(("36,38".indexOf(ccNumber.substr(0,2)) >= 0) ||
						("300,301,302,303,304,305".indexOf(ccNumber.substr(0,3)) >= 0)))
					return true;
				break;

			case "Discover":
				if ((ccNumber.length == 16) &&
						("6011".indexOf(ccNumber.substr(0,4)) >= 0))
					return true;
				break;

			case "enRouteCard":
				if ((ccNumber.length == 15) &&
						("2014,2149".indexOf(ccNumber.substr(0,4)) >= 0))
					return true;
				break;

			case "JCBCard":
				if ((ccNumber.length == 15) &&
						("2131,1800".indexOf(ccNumber.substr(0,4)) >= 0))
					return true;
				if ((ccNumber.length == 16) &&
						(ccNumber.charAt(0) == '3'))
					return true;
				break;

			case "MasterCard":
				if ((ccNumber.length == 16) &&
						("51,52,53,54,55".indexOf(ccNumber.substr(0,2)) >= 0))
					return true;
				break;

			case "Visa":
				if (((ccNumber.length == 13) || (ccNumber.length == 16)) &&
						(ccNumber.charAt(0) == '4'))
					return true;
				break;

			default:
				doAlert('Invalid ' + response + ' Credit Card Type detected.');
				return false;
		}

		// otherwise, the number was invalid for this type of credit card.
		doAlert('Invalid ' + typefield.value + ' Credit Card Number detected.');
		return false;

	} else {
		// LUHN check failed and an error was displayed
		return false;
	}
}

/********************************************************************
 * CheckCreditCard()												*
 *																	*
 * Checks a credit card against known algorhythms					*
 *																	*
 * Parameters														*
 *		Name			Type		Description						*
 *		-----------------------------------------------------------	*
 *		numfield		field		CC Number Field to verify		*
 *		typefield		field		CC Card type Field to verify	*
 *		monthfield		field		Expiry month Field to verify	*
 *		yearfield		field		Expiry year Field to verify		*
 *		response		string		What to display in the alert	*
 *																	*
 * Returns: true or false											*
 *																	*
 * Modifications													*
 *																	*
 * By			On			Description								*
 * ---------------------------------------------------------------- *
 ********************************************************************/															

function CheckCreditCard(numfield, typefield, monthfield, yearfield, response) {
	initValidation(numfield, 'creditcard');
	var bReturn = CheckCCNum(numfield, typefield, response) &&
					CheckRequired(monthfield, 2, 2, "Expiration Month", "month") &&
					CheckRequired(yearfield, 4, 4, "Expiration Year", "year");

	if (bReturn) {
		var thetime=new Date();
		var nmonth=thetime.getMonth();
		var nyear=thetime.getYear();
		if (nyear < 1000) 
			nyear += 1900;	/**  Support for Netscape getYear() behavior  **/
		
		if (parseInt(yearfield.value, 10) < nyear) {
			doAlert(response + ' Credit Card has expired.');
			return false;
		}
		if (parseInt(yearfield.value, 10) > nyear)
			return true;

		// nmonth is in range 0-11, so this month appears expired.
		if (parseInt(monthfield.value, 10) > nmonth + 1)
			return true;

		// else the card expired this month, or earlier this year
		doAlert(response + ' Credit Card has expired.');
		return false;
	}
	return bReturn;
}