// -------------------------------------------------------------------
// FormValidation.js
//   encapsulates the FormValidation object, and contains all of the 
//   supprting validation methods
//
// Requirements:
//   PrestoCommon.js
//
// Version: 
//   $Id: $
// -------------------------------------------------------------------

var gBadCharsArray = new Array("<", ">", "{", "}", "&", "%", "$", "\\", ";", "/", "[", "]"); 
var gSkipValidation = false;


var kStringTest_ContainsPrintable = new RegExp("[\u0021-\u007e\u00a1-\u05ff\u0604-\u06dc\u06de-\u070e\u0710-\u167f\u1681-\u17b3\u17b6-\u180d\u180f-\u1fff\u2010-\u2027\u2030-\u205e\u2064-\u2069\u2070-\u2fff\u3001-\udfff\uf900-\ufefe\uff00-\ufff8\ufffc-\ufffe]");

var kStringTest_IsPrintableOrWS = new RegExp("^[\u0009\u000a\u000b\u000d\u0020-\u007e\u00a0-\u05ff\u0604-\u06dc\u06de-\u070e\u0710-\u17b3\u17b6-\u200a\u2010-\u2027\u202f-\u205f\u2064-\u2069\u2070-\udfff\uf900-\ufefe\uff00-\ufff8\ufffc-\ufffe]+$", "m");

var kStringTest_IsPrintableOrLWS = new RegExp("^[\u0009\u0020-\u007e\u00a0-\u05ff\u0604-\u06dc\u06de-\u070e\u0710-\u17b3\u17b6-\u200a\u2010-\u2027\u202f-\u205f\u2064-\u2069\u2070-\udfff\uf900-\ufefe\uff00-\ufff8\ufffc-\ufffe]+$", "m");


// -------------------------------------------------------------------
// TabToNextPhoneField()
// Function to auto-tab to the next phone field
// Arguments:
//	 e:					The event trapped from the onKeyUp				
//   currentElement:	The input object (this)							
//	 nextElementId:		The id of the next element to focus				
//   maxChars:			Tab ahead when input value reaches this length	
// -------------------------------------------------------------------
//
function TabToNextPhoneField(e, currentElement, nextElementId, maxChars) {
	// get the keycode from the event. 
	//
	var keycode;
	if (e.keyCode) {keycode=e.keyCode;} 
	else {keycode=e.which;}
	_DEBUG("TabToNextPhoneField: keypress is: " + keycode);
	
	// advance to the next field, when you reach the 
	// max number of chars for this field, unless the key code is:
	//			unknown			[Tab]			[Shift]			[Enter]		[LeftArrow]		[RightArrow]
	if (keycode != 0 && keycode != 9 && keycode != 16 && keycode != 13 && keycode != 37 && keycode != 39) {
		var nextElement = document.getElementById(nextElementId);
		if (currentElement.value.length == maxChars) {
			nextElement.focus();
			if (nextElement.value.length > 0) {
				nextElement.select();
			}
		}
	}
}

// -------------------------------------------------------------------
// SkipValidation()
// Sets the global skip var to true. 
// -------------------------------------------------------------------
//
function SkipValidation() {
	gSkipValidation = true;
}


// -------------------------------------------------------------------
// PhoneNumberObject()
// An object containing the elements that make up a phone number. 
// Arguments:
//   area:		 The area code HTML element							
//   pre:		 The prefix number HTML element
//   subscriber: The subscriber number HTML element
// -------------------------------------------------------------------
//
function PhoneNumberObject(area, pre, subscriber) {
	this.Areacode 			= area;
	this.Prefix				= pre;
	this.SubscriberNumber 	= subscriber;
	this.ValuesAreNull		= true;

	// now let's figure out if the value of this object are null
	//
	if (this.Areacode.value != "" || this.Prefix.value != "" || this.SubscriberNumber.value != "") {
		this.ValuesAreNull = false;
	}
}


// -------------------------------------------------------------------
// ValidationObject()
// the basic validation object. 
// Arguments:
//   element:		 The object to validate							
//   message:		 The error message to report if validation fails
//   vType:			 (optional) The type of validation				
//   compareElement: (optional) The id of an element to compare to	
//	 tabToFocus:	 (optional) function to call to focus the element
// -------------------------------------------------------------------
//
function ValidationObject(element, message, vType, compareElement, tabToFocus, detail) {
	if(element != "") {
		// if the arguments are being passed in, 
		// populate the object with them. 
		//
		this.HtmlElement	= element;
		this.ErrorMessage	= message;
		this.ValidationType	= vType;
		this.CompareElement = compareElement;
		this.Tab			= tabToFocus;
		this.ErrorDetail	= detail;
	} else {
		// otherwise, let's just create the empty object.
		//
		this.HtmlElement	= null;
		this.ErrorMessage	= null;
		this.ValidationType = null;
		this.CompareElement = null;
		this.Tab			= null;
		this.ErrorDetail	= null;
	}
	
	_DEBUG("Completed creating "+ vType +" v.object for " + this.HtmlElement.id);
}

// -------------------------------------------------------------------
// Validate()
//    validates the form
// Arguments:
//    vo - an array of validationObjects to run through.	
// -------------------------------------------------------------------
//
function Validate(vo) {
	// if we can skip the valiation, let it pass. 
	//
	if (gSkipValidation) { return true; }
	
	_DEBUG("Begining Validation method with " + vo.length + " v.objects.");

	// loop through all the validationObjects
	//
	for(var i=0; i<vo.length; i++) {

		// now, let's determine the type of validation to use. 
		// if the ValidationType property is null, we'll just 
		// do the simple "IsRequired" validation. 
		//
		
		if(vo[i].ValidationType == "noSpaces") {
			// verify the field contains no spaces
			//
			if(!HasSpaces(vo[i].HtmlElement.value)) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "email") {
			// verify the field contains an email address
			//
			if(!IsEmailAddress(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "emailArray") {
			// verify the field contains all valid email addresses
			//
			if(!IsEmailAddressArray(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "altemail") {
			// verify the field contains an email address or is empty
			//
			if(vo[i].HtmlElement.value != "")
			{
				if(!IsEmailAddress(vo[i])) {
					AlertAndFocus(vo[i]);
					return false;
				}
			}
		
		} else if(vo[i].ValidationType == "emailName") {
			// verify the field contains an email name
			//
			if(!IsEmailName(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "compare") {
			// verify the field, and the compareElement match
			//
			if(!CompareFields(vo[i].HtmlElement, vo[i].CompareElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "notmatch") {
			// verify the field, and the compareElement match
			// however, if the values are both empty, that's OK. 
			//
			if(CompareFields(vo[i].HtmlElement, vo[i].CompareElement) && vo[i].HtmlElement.value!= "") {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "checked") {
			// verify the field, and the compareElement match
			//
			if(!IsChecked(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "empty") {
			// verify the field has something in it
			//
			if(!IsEmpty(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "character") {
			// verify the field contains only characters and not numbers
			//
			if(!IsCharacter(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "numeric") {
			// verify the field, and the compareElement match
			//
			if(!IsNumeric(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		} else if(vo[i].ValidationType == "minlength") {
			// verify the field has the right length, 
			// and pass it through the IsRequired
			//
			if(vo[i].HtmlElement.value.length < vo[i].CompareElement || !IsRequiredField(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "maxlength") {
			// verify the field doesn't exceed the maximum 
			// number of characters
			//
			if(vo[i].HtmlElement.value.length > vo[i].CompareElement) {
				AlertAndFocus(vo[i]);
				return false;
			}
				
		} else if(vo[i].ValidationType == "POBox") {
			// verify the shipping address field 
			// is not a PO Box
			//
			if(isPOBox(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
				
		} else if(vo[i].ValidationType == "username") {
			// verify the field doesn't have any spaces or @ signs
			//
			if(!IsUsername(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "reqnames") {
			// verify only the field doesn't have any bad characters
			//
			if(!IsReqName(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "nonreqnames") {
			// verify only the field doesn't have any bad characters
			//
			if(!IsNonReqName(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "xmlresponse") {
			// verify the gStatusObj came back as true, then focus on the
			// compareElement (the username).
			//
			if(!vo[i].HtmlElement.NameAvailable.Result) {
				AlertAndFocus(vo[i], vo[i].CompareElement);
				return false;
			}
	
		} else if(vo[i].ValidationType == "domaincheck") {
			// check that the field doesn't contain a particular domain
			//
			if(!NotFromDomain(vo[i].HtmlElement, vo[i].CompareElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}	

		} else if(vo[i].ValidationType == "phonenumber") {
			// check the array of objects for the phonenumber
			// in this case, the CompareElement is a boolean toggle for if
			// we can all the phone number to be all nulls or not. 
			// remember, the HtmlElement here is actually a phoneNumberObject.
			//
			if(!IsPhonenumber(vo[i].HtmlElement, vo[i].CompareElement)) {
				AlertAndFocus(vo[i], vo[i].HtmlElement.Areacode);
				return false;
			}

		} else if(vo[i].ValidationType == "creditcard") {
			if(!IsCreditCard(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "cardnumberandtype") {
			if(!CardNumberMatchesCardType(vo[i].HtmlElement, vo[i].CompareElement)) {
				AlertAndFocus(vo[i], vo[i].CompareElement);
				return false;
			}

		} else if(vo[i].ValidationType == "expired") {
			if(IsNotExpired(vo[i].HtmlElement, vo[i].CompareElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "isDollars") {
			// verify the dollar amount is greater than 1 cent
			// and less than the amount passed in
			//
			if((!IsDollarsandCents(vo[i].HtmlElement)) || (!IsDollarsValue(vo[i].HtmlElement, vo[i].CompareElement))) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		}  else if(vo[i].ValidationType == "dollarsCents") {
			//  verify the amount is in dollars and cents format
			if(!IsDollarsandCents(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
		
		}  else if(vo[i].ValidationType == "password") {
			//if(!IsUsername(vo[i].HtmlElement)) {
			//	AlertAndFocus(vo[i]);
			//	return false;
			//}
		
		} else if(vo[i].ValidationType == "zipcode") {
			if(!IsZipcode(vo[i].HtmlElement)) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "alphanumeric") {
			// contains only letters and or numbers
			//
			if(!IsAlphanumeric(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "whitelist") {
			// basic validation can be empty or null
			//
			if(!IsEmailAddress(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "date") {
			// basic validation can be empty or null
			//
			if(!isDate(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "isRequiredMessage") {
			// validation for required message fields
			//
			if(!IsRequiredMessageField(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else if(vo[i].ValidationType == "NonRequiredMessageField") {
			// basic validation of message fields, can be empty or null
			//
			if(!NonRequiredMessageField(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		}else if(vo[i].ValidationType == "simplenonreq") {
			// basic validation can be empty or null
			//
			if(!SimpleNonRequiredValidation(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
			
		} else {
			// perform basic "not empty" validation
			//
			if(!IsRequiredField(vo[i])) {
				AlertAndFocus(vo[i]);
				return false;
			}
		}
	}
}

// -------------------------------------------------------------------
// AlertAndFocus()
//    Generates the alert message, and focuses on the element. 
// Arguments:
//   vo:				 The Validation object that failed				
//   customFocusElement: (optional) A particular element to focus on (overrides vo).
// -------------------------------------------------------------------
//
function AlertAndFocus(vo, customFocusElement) {
	// focus the tab if needed
	//
	if (vo.Tab != null)	{
		eval(vo.Tab);
	}
	
	// focus the element
	//
	if (customFocusElement != null) {
		customFocusElement.focus();
	} 
	
	// set the message
	//
	if (vo.ErrorDetail != null) {
		vo.ErrorMessage = vo.ErrorMessage + "\n" + vo.ErrorDetail;
	}
	
	// alert the message
	//
	alert(vo.ErrorMessage);
}

// ----------------------------------------------------------------
// ContainsPrintable()
//	  Returns true if the string contains any printable characters.
// ----------------------------------------------------------------
//
function ContainsPrintable(vo) {
	var str = Trim(vo.HtmlElement.value);
    return kStringTest_ContainsPrintable.test(str);
}

// ----------------------------------------------------------------
// IsPrintableOrLWS()
//    Returns true if the string is not empty and contains 
//    only printable characters and/or linear whitespace.
// ----------------------------------------------------------------
//
function IsPrintableOrLWS(vo) {
	var str = Trim(vo.HtmlElement.value);
    return kStringTest_IsPrintableOrLWS.test(str);
}

// ----------------------------------------------------------------
// IsPrintableOrWS()
//    Returns true if the string is not empty and contains 
//    only printable characters and/or whitespace.
// ----------------------------------------------------------------
//
function IsPrintableOrWS(vo) {
	var str = Trim(vo.HtmlElement.value);
    return kStringTest_IsPrintableOrWS.test(str);
}

// -------------------------------------------------------------------
// IsRequiredMessageField()
//    Returns true if the string is not empty and contains 
//    only printable characters. 
// -------------------------------------------------------------------
//
function IsRequiredMessageField(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(inputStr == "" || inputStr == null) {
		return false;
	}
	if(!ContainsPrintable(vo)) { 
		return false;
	}
	if(!IsPrintableOrLWS(vo)) {
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// NonRequiredMessageField()
//    Returns true if the string contains only printable characters.  
// -------------------------------------------------------------------
//
function NonRequiredMessageField(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(!IsPrintableOrWS(vo)) { 
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// IsRequiredField()
//    basic form field validation. Returns false if the string is empty, 
//    all spaces, or has any illegal chars. 
// -------------------------------------------------------------------
//
function IsRequiredField(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(inputStr == "" || inputStr == null) {
		_DEBUG("IsRequiredField(): input string is null");
		return false;
	}
	inputStr = inputStr.replace(/[\n\r\l]+/g, " ");
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
			vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	var charRegxp = /^[ A-Za-z0-9\~\`\!\@\#\^\*\(\)\_\-\+\=\|\"\'\:\?\.\,]+$/;
	if (!charRegxp.test(inputStr)) {
		_DEBUG("IsRequiredField(): String " + inputStr + " failed regex.");
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// SimpleNonRequiredValidation()
//    basic form field validation. Returns false if the string has any illegal chars. 
// -------------------------------------------------------------------
//
function SimpleNonRequiredValidation(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(inputStr != null) {
		inputStr = inputStr.replace(/[\n\r\l]+/g, " ");
		if(inputStr != "" && inputStr != null) {
			for(var i=0; i<gBadCharsArray.length; i++) {
				if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
					_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
					vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
					return false;
				}
			}
			var charRegxp = /^[ A-Za-z0-9\~\`\!\@\#\^\*\(\)\_\-\+\=\|\"\'\:\?\.\,]+$/;
			if (!charRegxp.test(inputStr)) {
				_DEBUG("IsRequiredField(): String " + inputStr + " failed regex.");
				return false;
			}
		}
	}
	return true;
}

// -------------------------------------------------------------------
// IsAlphanumeric()
//    Returns false if values contains any characters 
//	  other than letters or numbers
// -------------------------------------------------------------------
//
function IsAlphanumeric(e1) {
	var inputStr = Trim(vo.HtmlElement.value)
	var charRegxp = /^[ A-Za-z0-9]+$/;
	if (!charRegxp.test(inputStr)) {
		_DEBUG("IsAlphanumeric(): String " + inputStr + " failed regex.");
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// HasSpaces()
//    basic validation. Returns false if values contains spaces
// -------------------------------------------------------------------
//
function HasSpaces(e1) {
	if(e1.indexOf(' ') > 0) {
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// CompareFields()
//    basic comparision validation. Returns false if values don't match
// -------------------------------------------------------------------
//
function CompareFields(e1, e2) {
	if(e1.value == e2.value) {
		return true;
	}
	return false;
}

// -------------------------------------------------------------------
// IsEmailAddress()
//    email address field validation. 
// -------------------------------------------------------------------
//
function IsEmailAddress(vo) {
	// first let's do the easy work, and just look for 1 @ sign. 
	//
	var e	 = vo.HtmlElement;
	var bits = e.value.split("@");
	if (bits.length != 2) {return false;}
	if (Trim(e.value).indexOf(" ") != -1) {return false;}
	
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(Trim(e.value).indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsEmailAddress(): Char " + gBadCharsArray[i] + " is reserved.");
			vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	
	// now do the regex.
	//
	var emailRegxp = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (!emailRegxp.test(Trim(e.value))) {
		_DEBUG("IsEmailAddress(): " + e.value + " is failing email regex.");
		vo.ErrorMessage = "Valid email address characters are A-z, 0-9, '_', '.', '-' and '+'.";
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// IsEmailAddressArray()
//    email address array field validation. 
// -------------------------------------------------------------------
//
function IsEmailAddressArray(vo) {
	var emailRegxp = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	var addresses = vo.HtmlElement.value.toString();
	addresses = addresses.replace(/,/g, ' ');
	addresses = addresses.replace(/\;/g, ' ');
	addresses = addresses.replace(/  /g, ' ');
	var eArray = addresses.split(/\s/g);
	var i = 0;
	for (i = 0; i < eArray.length; i++) {
		if(eArray[i].length > 0) {
			var bits = eArray[i].split("@");
			
			if ((bits.length != 2) || (!emailRegxp.test(Trim(eArray[i])))) {
				vo.ErrorMessage = eArray[i] + " does not appear to be a valid email address.";
				return false;
			}
		} 
	}
	return true;
}

// -------------------------------------------------------------------
// IsEmailName()
//    email name field validation. 
// -------------------------------------------------------------------
//
function IsEmailName(vo) {
	// first let's do the easy work, and just look for spaces or illegal characters. 
	//
	var e	 = vo.HtmlElement;
	if (Trim(e.value).indexOf(" ") != -1) {return false;}
	
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(Trim(e.value).indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsEmailAddress(): Char " + gBadCharsArray[i] + " is reserved.");
			vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	
	// now do the regex.
	//
	var emailRegxp = /^[\a-zA-Z0-9_\-]+$/;
	if (!emailRegxp.test(Trim(e.value))) {
		_DEBUG("IsEmailAddress(): " + e.value + " is failing email regex.");
		vo.ErrorMessage = "Valid email may consist of A-z, 0-9 (-) and (_).";
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// IsUsername()
//    username field validation. allows only 'a-z', '0-9' and '_'
//    as legal chars. 
// -------------------------------------------------------------------
//
function IsUsername(e) {
	var username = Trim(e.value);
	var usernameRegex = /^[\a-zA-Z0-9_]+$/;
	if (!usernameRegex.test(username)) {
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// IsReqName()
//    required name field validation. allows all non-bad chars. 
// -------------------------------------------------------------------
//
function IsReqName(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(inputStr == "" || inputStr == null) {
		_DEBUG("IsRequiredField(): input string is null");
		return false;
	}
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
			vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	return true;
}

// -------------------------------------------------------------------
// IsNonReqName()
//    Non-required name field validation. allows all non-bad chars. 
// -------------------------------------------------------------------
//
function IsNonReqName(vo) {
	var inputStr = Trim(vo.HtmlElement.value)
	if(inputStr == "" || inputStr == null) {
		return true;
	}
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
			vo.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	return true;
}

// -------------------------------------------------------------------
// IsZipcode()
//    zipcode field validation. allows either 5 numerical digits, or
//	  the standard 5 + 4 (for military)
// -------------------------------------------------------------------
//
function IsZipcode(e) {
	var zip	= Trim(e.value);
	var zipRegex = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
	if (!zipRegex.test(zip)) { 
		return false;
	}
	return true;
}

// -------------------------------------------------------------------
// IsChecked()
//    validates that a checkbox is checked 
// -------------------------------------------------------------------
//
function IsChecked(e) {
	if(e.checked) {
		return true
	}
	return false;
}

// -------------------------------------------------------------------
// IsEmpty()
//    validates that there is a value in a text field. 
// -------------------------------------------------------------------
//
function IsEmpty(e) {

    // Set the var inputStr to the value of the field
    //
	var inputStr = Trim(e.HtmlElement.value)
	
	// Now check to see if there is anything in the field.
	// if there isn't anything, return false
	//
	if(inputStr == "" || inputStr == null) {
		_DEBUG("IsRequiredField(): input string is null");
		return false;
	}
	
	// Check for any bad characters in this string
    //
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
			e.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}

	return true;
}

// -------------------------------------------------------------------
// IsCharacter()
//    validates that a value is composed only of characters and not numbers. 
// -------------------------------------------------------------------
//
function IsCharacter(e) {
	var inputStr = Trim(e.HtmlElement.value)

    //Check for any bad characters in this string
    //
	for(var i=0; i<gBadCharsArray.length; i++) {
		if(inputStr.indexOf(gBadCharsArray[i])!=-1) {
			_DEBUG("IsRequiredField(): Char " + gBadCharsArray[i] + " is reserved.");
			e.ErrorMessage = "The '" + gBadCharsArray[i] + "' character is not allowed in this field.";
			return false;
		}
	}
	//Set up the regex we will use
	//
	var charRegxp = /^[ A-Za-z\~\`\!\@\#\^\*\(\)\_\-\+\=\|\"\'\:\?\.\,]+$/;
	
	//Check to see if we have a valid string based on the regex
	if (!charRegxp.test(inputStr)) {
		_DEBUG("IsRequiredField(): String " + inputStr + " failed regex.");
		return false;
	}
	
	return true;
}

// -------------------------------------------------------------------
// IsNumeric()
//    validates that a value is numeric. 
// -------------------------------------------------------------------
//
function IsNumeric(e) {
	possibleNum = e.value;
	var numbersRegex = /^[0-9]+$/;

	if (possibleNum == null || possibleNum == "") {
		return false;
	} else {
		return numbersRegex.test(possibleNum);
	}
}

// -------------------------------------------------------------------
// IsDollarsValue()
//    validates that a value is greater than 1 cent and less than
//	  a dollar amount passed in (max). 
// -------------------------------------------------------------------
//
function IsDollarsValue(e, max) {
	var dollars = new Number(e.value);
	if(dollars < 0.01) {
		return false;
	}
	if(dollars > max) {
		return false;
	} else {
		return true;
	}
}

// -------------------------------------------------------------------
// IsDollarsandCents()
//    validates that a value is in dollars and cents format
//	  i.e. xxx.xx 
// -------------------------------------------------------------------
//
function IsDollarsandCents(e) {
	dollars = e.value;
	if(dollars.indexOf(".") < 0) {
		return false;
	}
	dec = dollars.indexOf(".");
	if(dollars.length > (dec + 3)) {
		return false;
	} else {
		return true;
	}
}

// -------------------------------------------------------------------
// NotFromDomain()
//    Validates that the value isn't from a particular domain.
// -------------------------------------------------------------------
//
function NotFromDomain(e, domain) {
	if (e.value.indexOf(domain) == -1) {
		return true;
	} else {
		return false;
	}
}

// -------------------------------------------------------------------
// IsPhonenumber()
//    validate that the 3 elements contain values that are all the 
//    right length, and numeric.
// Arguments: 
//    e - a PhoneNumberObject
//    allowNulls - bool for toggling if the phone number can be null
// -------------------------------------------------------------------
//
function IsPhonenumber(phoneObj, allowNulls) {

	var areacode = phoneObj.Areacode;
	var prefix   = phoneObj.Prefix;
	var lineno	 = phoneObj.SubscriberNumber;
	
	// check for nulls. 
	//
	if (allowNulls && phoneObj.ValuesAreNull) {return true;}
	if (!allowNulls && phoneObj.ValuesAreNull) {return false;}
	
	// verify the fields are numeric.
	//
	if(!IsNumeric(areacode) || !IsNumeric(prefix) || !IsNumeric(lineno)) {
		phoneObj.ErrorMessage = "Only numbers are allowed for phone numbers.";
		return false;
	}
	
	// check for spaces.
	if(areacode.value.indexOf(" ") != -1 || prefix.value.indexOf(" ") != -1 || lineno.value.indexOf(" ") != -1) {
		phoneObj.ErrorMessage = "Spaces are not allowed in phone number.";
		return false;
	}
	
	// verfy the length of the fields.
	//
	if(areacode.value.length != 3 || prefix.value.length != 3 || lineno.value.length != 4) {
		phoneObj.ErrorMessage = "Incorrect number of digits in phone number.";
		return false;
	} 
	return true;
}

// -------------------------------------------------------------------
// IsCreditCard()
//    validate that a field contains a LUHN10 creditcard number.
// Arguments: 
//    e - the HTML element containing the number
// -------------------------------------------------------------------
//
function IsCreditCard(e)  {
	
	e.value = e.value.ReplaceAll("-", "");
	e.value = e.value.ReplaceAll(" ", "");

	var ccNum = e.value;                     
    if (ccNum.length > 19 || ccNum.length < 14) {
        return false;
	}
	
	if (isNaN(ccNum)) {
		return false;
	}

	sum = 0; 
	mul = 1; 
	l	= ccNum.length;
	
	for (i = 0; i < l; i++) {
		digit = ccNum.substring(l-i-1,l-i);
		tproduct = parseInt(digit ,10)*mul;
		
		if (tproduct >= 10) {
			sum += (tproduct % 10) + 1;
		} else {
			sum += tproduct;
		}
		
		if (mul == 1) {
			mul++;
		} else {
			mul--;
		}
	}
	
	if ((sum % 10) == 0) {
		return true;
	} else {
		return false;
	}
}


// -------------------------------------------------------------------
// CardNumberMatchesCardType()
//    validate that card number looks like it's from the issuer
// Arguments: 
//    e1 - the HTML element containing the number
//	  e2 - the HTML element containing the card type
// -------------------------------------------------------------------
//
function CardNumberMatchesCardType(e1, e2) {
	var cardType = e2.value;
	var cardNum	 = e1.value;
	
	switch (cardType) {
		case "Visa" : 
			if (cardNum.charAt(0) == "4")
				return true;
			else 
				return false;
		
		case "Amex" : 
			if (cardNum.charAt(0) == "3")
				return true;
			else 
				return false;
	
		case "MC" : 
			if (cardNum.charAt(0) == "5")
				return true;
			else 
				return false;
	
		case "Discover" : 
			if (cardNum.charAt(0) == "6")
				return true;
			else 
				return false;		
				
	}

}


// -------------------------------------------------------------------
// IsNotExpired()
//    validate that a billing month/year combo isn't expired.
// Arguments: 
//    e1 - the HTML element containing month
//	  e2 - the HTML element containing year
// -------------------------------------------------------------------
//
function IsNotExpired(e1, e2) {
	var month = e1.value;
	var year  = e2.value; 
	
	var expDate = new Date();
	var today	= new Date();
	expDate.setFullYear(year, month-1, 1);
	
	if (expDate > today) {
		return false;
	} else {
		return true;
	}
}

// -------------------------------------------------------------------
// cleanTextField(stringToFix)
//    Remove characters in bad charcters as defined in the gBadCharsArray
// Arguments: 
//    stringToFix - the HTML element containing characters that need to 
//                  be "cleaned" of bad characters.
// -------------------------------------------------------------------
//
function cleanTextField(stringToFix)
{
	var replacementString;
	var oldString = document.getElementById(stringToFix);
	var regEx;
	var regExString;
	var escapeCharsString = "$\\";
	
	//adding a first line check to make sure that we are getting an object and not a null
	//
	if(oldString != null)
	{
	    //Check to see if the element has a value in it. If it does then
	    //move on else return true and exit function
	    //
	    if(oldString.value != "" && oldString.value != null)
	    {
	        //Now loop thru every element in the gBadCharsArray
	        //
	        for(var i = 0; i< gBadCharsArray.length; i++)
	        {
	            //Now check to make sure that the passed in element contains a "bad
	            //character. If it doesnt then move on to the next character. 
	            //Else move into the  if statement
	            //
	            if(oldString.value.indexOf(gBadCharsArray[i]) != -1)
	            {
	                //This is here to make sure that certain characters such as $ or \
	                //get escaped
	                //
	                if(escapeCharsString.indexOf(gBadCharsArray[i]) != -1 )
	                {
	                    regExString = ("\\" + gBadCharsArray[i]);
	                }
	                else
	                {
	                    regExString = gBadCharsArray[i]
	                }
    	            
	                //Set Reg Ex for the Character to use in the replace method
		            //
			        regEx = new RegExp(regExString);
    	            
	                //While this character exists in the string keep cleaning it
	                //
		            while(oldString.value.indexOf(gBadCharsArray[i]) != -1)
		            {   
                        //Set the replacementString to the cleaned string
                        //
			            replacementString = oldString.value.replace(regEx, "", "g");
    			        
			            //Set the oldString value to the new string
			            //
			            oldString.value = replacementString;
		            }

			    }
	        }
	    }
	}
	return true;
}

// -------------------------------------------------------------------
// isPOBox()
//    validate that a shipping address is not a PO Box.
// Arguments: 
//    e1 - the HTML element containing address
// -------------------------------------------------------------------
//
function isPOBox(argPOBox) 
{
	var adr = argPOBox.HtmlElement.value;
	var str = adr.toUpperCase();
	
	//Check for empty string or null values
	//
	if(str != "" && str != null)
	{
		//Run through possible variations on PO BOX
		//and return true if a match is found.
		//
		if(str.indexOf("PO BOX") >= 0)
			return true
		else if(str.indexOf(" PO ") >= 0)
			return true
		else if(str.indexOf("P.O.") >= 0)
			return true
		else if(str.indexOf("POB ") >= 0)
			return true
		else if(str.indexOf(" POB ") >= 0)
			return true
		else if(str.indexOf("POBOX") >= 0)
			return true
		else if(str.indexOf("P.OBOX") >= 0)
			return true
		else if(str.indexOf("P.O BOX") >= 0)
			return true
		else if(str.indexOf("PO. BOX") >= 0)
			return true
			
		//Now do checks for zero instead of letter O
		
		else if(str.indexOf("P0 BOX") >= 0)
			return true
		else if(str.indexOf(" P0 ") >= 0)
			return true
		else if(str.indexOf("P.0.") >= 0)
			return true
		else if(str.indexOf("P0.") >= 0)
			return true
		else if(str.indexOf("P0B ") >= 0)
			return true
		else if(str.indexOf(" P0B ") >= 0)
			return true
		else if(str.indexOf("P0BOX") >= 0)
			return true
		else if(str.indexOf("P.0BOX") >= 0)
			return true
		else if(str.indexOf("P.0 BOX") >= 0)
			return true
		else if(str.indexOf("P0. BOX") >= 0)
			return true
		else if(str.indexOf("P0 B0X") >= 0)
			return true
		else if(str.indexOf("P0B0X") >= 0)
			return true
		else if(str.indexOf("P.0B0X") >= 0)
			return true
		else if(str.indexOf("P.0 B0X") >= 0)
			return true
		else if(str.indexOf("P0. B0X") >= 0)
			return true
		else if(str.indexOf("P0.Box") >= 0)
			return true
		else 
			return false
	}
	return false
}

// -------------------------------------------------------------------
// isDate(vo)
//    Date validation routines
// -------------------------------------------------------------------
//
function isDate(vo){
	var dtStr = vo.HtmlElement.value;
	var daysInMonth = DaysArray(12)
	var pos1=dtStr.indexOf(dtCh)
	var pos2=dtStr.indexOf(dtCh,pos1+1)
	var strMonth=dtStr.substring(0,pos1)
	var strDay=dtStr.substring(pos1+1,pos2)
	var strYear=dtStr.substring(pos2+1)
	strYr=strYear
	if (strDay.charAt(0)=="0" && strDay.length>1) strDay=strDay.substring(1)
	if (strMonth.charAt(0)=="0" && strMonth.length>1) strMonth=strMonth.substring(1)
	for (var i = 1; i <= 3; i++) {
		if (strYr.charAt(0)=="0" && strYr.length>1) strYr=strYr.substring(1)
	}
	month=parseInt(strMonth)
	day=parseInt(strDay)
	year=parseInt(strYr)
	if (pos1==-1 || pos2==-1){
		return false
	}
	if (strMonth.length<1 || month<1 || month>12){
		return false
	}
	if (strDay.length<1 || day<1 || day>31 || (month==2 && day>daysInFebruary(year)) || day > daysInMonth[month]){
		return false
	}
	if (strYear.length != 4 || year==0 || year<minYear || year>maxYear){
		return false
	}
	if (dtStr.indexOf(dtCh,pos2+1)!=-1 || isInteger(stripCharsInBag(dtStr, dtCh))==false){
		return false
	}
	return true
}

// Check that All characters are numbers.
// 
function isInteger(s){
	var i;
    for (i = 0; i < s.length; i++){   
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) 
			return false;
	}
	return true;
}

// Search through string's characters one by one.
// If character is not in bag, append to returnString.
//
function stripCharsInBag(s, bag){
	var i;
    var returnString = "";
        for (i = 0; i < s.length; i++){   
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

// February has 29 days in any year evenly divisible by four,
// EXCEPT for centurial years which are not also divisible by 400.
//    
function daysInFebruary (year){
	return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}

function DaysArray(n) {
	for (var i = 1; i <= n; i++) {
		this[i] = 31
		if (i==4 || i==6 || i==9 || i==11) {this[i] = 30}
		if (i==2) {this[i] = 29}
   } 
   return this
}

var dtCh= "/";
var minYear=1900;
var maxYear=2100;


// function ValidateForm(){
//	var dt=document.frmSample.txtDate
//	if (isDate(dt.value)==false){
//		dt.focus()
//		return false
//	}
//  return true
// }
