var validateBatchMode = false;
var errorLocations = new Array(); //used to store the ids of areas on the page with error messages written to them (so that they can be reset with each batch validation)


//called onBlur - validates a single form field
function validateInline(formField) {

	var validationRules = getValidationRules(formField);
	if (validationRules === null) 
		return true; //if there is no validation specified, quit right now
	
	var valid = validateField(formField,validationRules);
		
	if (!valid) 
	{
		showErrors(formField); //show the user the errors in the field
		
		formField.errorText = ""; //clear the error values for the next run
	} 
	else {
		if (!validateBatchMode) clearErrors(formField);
	}

	return valid;
}


//called from the form submit function - loops through all the fields in the form
function validateBatch(formObject) {
clearPreviousErrors(); //erase any existing error messages
validateBatchMode = true; //flag to tell the showErrors function not to erase previous errors
var valid = true;

	for (var i = 0; i < formObject.length; i++) {
		
		//in this case, radio buttons all have default values and we're not interested in checkboxes
		if (formObject.elements[i].type && (formObject.elements[i].type == "text" || formObject.elements[i].type == "password" || formObject.elements[i].type.indexOf("select") != -1)) {
			
			if (pageHasReflexiveContent == true) { //then validate only visible elements
				if (formObject.elements[i].reflexiveParent && document.getElementById(formObject.elements[i].reflexiveParent).offsetHeight != 0) {
					if (validateInline(formObject.elements[i]) == false) valid = false;
				}
		
			} else { //otherwise, validate everything
				if (validateInline(formObject.elements[i]) == false) valid = false;
			}
		}
	}

validateBatchMode = false;
return valid;
}

// Team Nomad (Kern) -- 09/18/2006 : Javascript Fields Focus				
function validateBatchFocus(formObject) {
	clearPreviousErrors(); //erase any existing error messages
	validateBatchMode = true; //flag to tell the showErrors function not to erase previous errors
	var valid = "success";

	for (var i = (formObject.length - 1); i >= 0; i--) {
		
		//in this case, radio buttons all have default values and we're not interested in checkboxes
		if (formObject.elements[i].type && (formObject.elements[i].type == "text" || formObject.elements[i].type == "password" || formObject.elements[i].type.indexOf("select") != -1)) {
			
			if (pageHasReflexiveContent == true) { //then validate only visible elements
				if (formObject.elements[i].reflexiveParent && document.getElementById(formObject.elements[i].reflexiveParent).offsetHeight != 0) {
					if (validateInline(formObject.elements[i]) == false)
						valid = formObject.elements[i].name;
					else
						clearErrorsFocus(formObject.elements[i]);
				}
		
			} else { //otherwise, validate everything
				if (validateInline(formObject.elements[i]) == false)
					valid = formObject.elements[i].name;
				else
					clearErrorsFocus(formObject.elements[i]);
			}
		}
	}

	validateBatchMode = false;
	return valid;
}


//parse the validation code that was added to the field in config.js
function getValidationRules(formField) {
	var validationRules = null;
	
	if (formField.validationRules != null) {
		validationRules = new Array();
		validationRules["required"] = (formField.validationRules.substring(0,1) == "R") ? true : false;
		validationRules["valueType"] = formField.validationRules.substring(1,2);
		validationRules["lengthType"] = formField.validationRules.substring(2,3);
		validationRules["valueLength"] = parseInt(formField.validationRules.substring(3,8),10);
	}
		
	return validationRules;
}


//write any error messages to the appropriate place, show field label in red, disable mouseover highlighting
function showErrors(formField) {
	formField.parentNode.style.color = "#FF0000";
	formField.parentNode.onmouseover = "";
	formField.parentNode.onmouseout = "";
	document.getElementById(formField.errorDisplayId).style.display = "block";
	document.getElementById(formField.errorDisplayId).style.color = "#FF0000";
	document.getElementById(formField.errorDisplayId).firstChild.innerText += formField.errorText;
	storeErrorLocation(formField.errorDisplayId);
}


//do the reverse of showErrors()
function clearErrors(formField) {
	formField.parentNode.style.color = "#000000";
	formField.parentNode.onmouseover = highlightHelp;
	formField.parentNode.onmouseout = unHighlightHelp;
	document.getElementById(formField.errorDisplayId).style.display = "none";
	document.getElementById(formField.errorDisplayId).firstChild.innerText = "";
}

// Team Nomad (Kern) -- 09/18/2006 : Javascript Fields Focus clear errors			
function clearErrorsFocus(formField) {
	formField.parentNode.style.color = "#000000";
	formField.parentNode.onmouseover = highlightHelp;
	formField.parentNode.onmouseout = unHighlightHelp;
}


//keep a record of the ids of areas on the page that display error messages (used to reset them)
function storeErrorLocation(errorFieldId)
{
	if (!errorLocations[errorFieldId])
	{
		errorLocations[errorFieldId] = errorFieldId;
	}
}


//using the array elements created in storeErrorLocation(), erase any existing errors before writing new ones
function clearPreviousErrors()
{
	for (var i in errorLocations)
	{
		document.getElementById(errorLocations[i]).firstChild.innerText = "";
	}
}


//master validation function - first check if the value is required, then validate it by type
function validateField(formField,validationRules)
{
	var valid = true;
	var fieldDisplayName = formField.displayName;
	if (typeof(formField.errorText == "undefined")) formField.errorText = "\n";

	if (validationRules["required"] == true && (formField.type == "text" || formField.type == "password"))
	{
		if (!isFilled(formField)) 
		{
			formField.errorText += fieldDisplayName + " is a required field.\n";
			
			// Team Nomad (Kern) -- 09/18/2006 : Javascript Fix				
			
			//var sPhase2User = hdnPhase2User;
			//if(sPhase2User.length != 0) 
			//{
			//	if (fieldDisplayName=="Recurring Contribution")
			//	{
			//		formField.errorText = "You must first enter a recurring contribution amount.\n";
			//	}
			//}
		}
	}

	switch (validationRules["valueType"])
	{
	
		case "A" : //Alphanumeric
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isAlphaNumeric(formField))
			{
				formField.errorText += fieldDisplayName + " may only contain alphabet characters, numbers from 0-9, hyphens, spaces and apostrophes.\n";
			}
		break;
		
		case "B" ://ABA Routing Number
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isRoutingNumber(formField)) {
				formField.errorText += fieldDisplayName + " must be a valid bank routing number.\n";
			}
		break;		

		case "C" ://Currency
			formField.errorText += "";
		break;

		case "D" ://Day
			formField.errorText += "";
		break;

		case "E" ://Email
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isEmail(formField))
			{
				formField.errorText += fieldDisplayName + " is not valid.\n";
			}
		break;

		case "F" ://Bene portfolio allocation total
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isValidTotal(100,document.getElementById("txtPortfolioTotal").value))
			{
				formField.errorText += fieldDisplayName + " must equal 100%.\n";
			}
		break;
		
		case "L" ://Portfolio percentages on the Beneficiary Investment page
			if (formField.value == "" || formField.value == null || formField.value == 0) 
			{
				break;
			}
			else if (!isValidPortfolioPct(formField) || isGreaterThan(formField,100))
			{
				formField.errorText += fieldDisplayName + " must have a value of at least " + iPctMinimum + "% but not more than 100%.\n";
			}
		break;
		
		case "M" ://Month
			formField.errorText += "";
		break;

		case "N" ://Numeric
			formField.errorText += "";
		break;

		case "P" ://Phone Number
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isPhone(formField)) {
				formField.errorText += fieldDisplayName + " must be a phone number in this format: (XXX) XXX-XXXX.\n";
			}
		break;
		
		case "Q" ://Duplicate Password
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isEqualTo(formField,document.getElementById("txtPasswordCreate"))) {
				formField.errorText += fieldDisplayName + " must be identical to Create Password.\n";
			}
		break;
		
		case "S" ://Social Security #
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isTaxId(formField)) {
				formField.errorText += fieldDisplayName + " must be a Social Security Number in this format: 123-45-6789.\n";
			}
		break;

		case "T" ://Timestamp/Date/Time
			formField.errorText += "";
		break;

		case "U" ://Bene percent of recurring contribution
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isValidBeneAmt(formField))
			{
				formField.errorText += fieldDisplayName + " must have a value of " + iAcctMin + " or greater.\n";
			}
		break;	
//Kumudini 12/26/2002 Begin
		case "V" :
				
			if (validationRules["required"] == true) {
				
				if (document.getElementById("chkCorporate").checked == true){					
					
					if (formField.value == "" || formField.value == null) {
						formField.errorText += "You must select a value for " + fieldDisplayName + 						".\n";
					
					}
				}
			}
			break;
//Kumudini 12/26/2002 End


		case "W" ://Password
			var minPasswordLength = 6;
			var maxPasswordLength = 12;
			var mustContain = ""; //specifies a character the password must contain
		
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isPassword(formField,minPasswordLength,maxPasswordLength,mustContain)) {
				formField.errorText += fieldDisplayName + " must contain between " + minPasswordLength + " and " + maxPasswordLength + " characters.\n";
				if (mustContain != "") formField.errorText += fieldDisplayName + ' must contain also contain at least one "' + mustContain + '".';
			}
		break;		

		case "X" ://Dropdowns
			if (validationRules["required"] == true) {
				if (formField.options[formField.selectedIndex].defaultSelected == true) {
					formField.errorText += "You must select a value for " + fieldDisplayName + ".\n";
				}
			}
		break;
		
		case "Y" ://Year
			if (formField.value == "" || formField.value == null || formField.value == 0) 
			{
				break;
			}
			else if (!isValidYear(formField))
			{
				formField.errorText += fieldDisplayName + " must be a four digit number and may not be later than this year.\n";
			}
		break;
				
		case "Z" ://ZipCode
			if (formField.value == "" || formField.value == null) 
			{
				break;
			}
			else if (!isZipCode(formField)) {
				formField.errorText += fieldDisplayName + " must contain 5 digits.\n";
			}
		break;
		
		default:
		break;
	
	}
	//Kumudini 12/24/2002 Begin

	switch (validationRules["lengthType"])
	{
		case "A": 
			
			if (formField.value == "" || formField.value == null) 
			{
				formField.errorText += fieldDisplayName +" can not be NULL.\n";

			}	
//NEXtgen 01/08/2003 BEGIN		
			else 
			{
				var agentid=formField.value;
				var agentid1=agentid.replace("-","");
				if(agentid1.length != validationRules["valueLength"])	
				{
					formField.errorText += fieldDisplayName +" must be 8 characters.\n";	
				}

			}

//NEXtgen 01/08/2003 End		
			break;
		default:
		break;	
	}	 

	//Kumudini 12/24/2002 End

	
	if (formField.errorText != "\n") valid = false;
	return valid;

}


function isFilled(formField)
{
	return (formField.value.length > 0 && formField.value.charAt(0) != " "); //not counting a single space as filled
}


function isAlphaNumeric(formField)
{
	var isAlphaNumeric = /^[a-zA-Z0-9-'\s]+$/;
	return isAlphaNumeric.test(formField.value);
}


function isValidLength(formField)
{
	return (formField.value.length <= getValidLength(formField));
}

//Kumudini 12/24/2002 Begin

function getValidLength(formField)
{
	var fieldDisplayName = formField.displayName;
	return (formField.value.length <= getValidLength(formField));
}

//Kumudini 12/24/2002 End

function isZipCode(formField)
{
	return formField.value.length == 5; //the input masking will ensure that these are only numbers 
}


function isValidYear(formField) {
	var today = new Date();
	var thisYear = today.getFullYear();
	return formField.value.length == 4 && parseInt(formField.value,10) <= thisYear;
}


function isNumber(formField)
{
	var isNumber = /^[0-9]+$/;
	return isNumber.test(formField.value);
}


function isPhone(formField)
{
	formatPhoneNumber(formField); //first, try to format the value to look like a phone number
	var isPhone = RegExp("[(][0-9]{3}[)][\\s][0-9]{3}[\-][0-9]{4}$");
	return isPhone.test(formField.value);
}


function isEmail(formField)
{
	var isEmail = new RegExp("[a-z0-9\.\-\_]+@[a-z0-9\.\-\_]+[\.]+[a-z]+");
	return isEmail.test(formField.value.toLowerCase());
}


function isTaxId(formField)
{
	formatTaxId(formField); //first, try to format the value to look like an SSN
	var isTaxId = RegExp("[0-9]{3}[\-][0-9]{2}[\-][0-9]{4}$");
	return isTaxId.test(formField.value);
}


function isRoutingNumber(formField) //derived from the 529 ESW demo code
{

  var n = 0;
  var t = stripNonNumbers(formField.value);

  // Check the length, it should be nine digits.
  if (t.length != 9) return false;

  // Now run through each digit and calculate the total.
  for (i = 0; i < t.length; i += 3) {
    n += parseInt(t.charAt(i),     10) * 3
      +  parseInt(t.charAt(i + 1), 10) * 7
      +  parseInt(t.charAt(i + 2), 10);
  }

  // If the resulting sum is an even multiple of ten (but not zero),
  // the aba routing number is good.

	if (n != 0 && n % 10 == 0) {
    	return true;
	} else {
    	return false;
	}
	
}


function isValidTotal(requiredTotal)
{

	var total = 0;

	for (var i = 1; i < arguments.length; i++)
	{
		total += arguments[i];
	}

	return total == requiredTotal;

}


function isPassword(formField, minimumLength, maximumLength, mustContain)
{
	var valid = (formField.value.length >= minimumLength && formField.value.length <= maximumLength);
	if (mustContain != "") valid += formField.value.indexOf(mustContain) != -1; //returns true or false
	return valid;
}


function isValidBeneAmt()
{
	var iBeneTotalAmt = parseInt(document.getElementById("txtBeneRecurAmt").value,10);
	return (iBeneTotalAmt >= iAcctMin);
}


function isValidPortfolioPct(formField) {
	return (parseInt(formField.value,10) >= iPctMinimum);
}


function isEqualTo(formField1,formField2)
{
	return formField1.value == formField2.value;
}


function isGreaterThan(formField,testValue)
{
	return (formField.value > testValue);
}


function isLessThan(formField,testValue)
{
	return (formField.value < testValue);
}


//returns string formatted (999) 999-9999
function formatPhoneNumber(formField)
{
var phone = stripNonNumbers(formField.value);
var newNumber = "";

	for (var i = 0; i < phone.length; i++) {
		if (i==0) newNumber += "(";
		if (i==3) newNumber += ") ";
		if (i==6) newNumber += "-";
		newNumber += phone.charAt(i);
	}

formField.value = newNumber;
return true;
}


//Returns string formatted as SSN or TIN
function formatTaxId(formField)
{
var taxId = stripNonNumbers(formField.value);
var newNumber = "";

	for (var i = 0; i < taxId.length; i++) {
		if (i == 3 || i == 5) newNumber += "-";
		newNumber += taxId.charAt(i);
	}

formField.value = newNumber;
return true;
}


//This function strips all non-numeric characters from a user-provided string.
function stripNonNumbers(inputValue)
{
var newNumber = "";

	for (var i=0; i < inputValue.length; i++) {
	
		if (parseInt(inputValue.charAt(i),10) >= "0" && parseInt(inputValue.charAt(i),10) <= "9") {
			newNumber += inputValue.charAt(i);
		}
	
	}   

return newNumber;

}


//compare the user's keypress against a regular expression - there are three predefined values: 0 = numbers only, 1 = numbers and dashes, 2 = numbers, dashes and periods
function maskInput(maskType) 
{
	var mask = "0-9\b";
	var inputCharacter = String.fromCharCode(window.event.keyCode); //convert the keystroke into a string
	
	if (maskType > 0) mask += "-";
	if (maskType > 1) mask += ".";
	if (maskType > 2) mask += ",";
	var maskValue = new RegExp("[" + mask + "]");
	 
	if (!maskValue.test(inputCharacter)) //test the current character against the regular expression

	{ 
		window.event.returnValue=false; //if they don't match, this nullifies the keystroke and the character does not appear
	}
	else
	{
		window.event.returnValue = true; //here we do allow the character to appear
	}
}


/*
by: JNL
Returns a valid integer when parsing a
number passed in.

Returns 0 if it cannot figure out the number
passed.
*/
function getValidInt(numberIn)
{
    var numberOut = 0;
    if(isNaN(parseInt(numberIn)))
        return numberOut;

    return parseInt(numberIn);
}

/*
by: JNL
Returns a valid float when parsing a
number passed in.

Returns 0.00 if it cannot figure out the number
passed.
*/
function getValidFloat(numberIn)
{
    var numberOut = 0.00;
    if(isNaN(parseFloat(numberIn)))
        return numberOut;

    return parseFloat(numberIn);
}

/*
by: JNL
Returns a String formatted to two decimal places.

Has known problems if the numberIn attribute
looks like "123.00" then the return value is
"123.00.00"
*/
function formatTwoDecimals(numberIn)
{
    var tempNum;
    var remainder;
    var stringToReturn = numberIn.toString();

    tempNum = getValidInt((getValidFloat(numberIn) * 100));
    remainder = tempNum % 100;
    if (remainder == 0)
        return stringToReturn + ".00"
    remainder = tempNum % 10;
    if (remainder == 0)
        return stringToReturn + "0"

    return stringToReturn;
}
