var VALID_VALUE = 0, MISSING_VALUE = 1, BAD_VALUE = 2, PROG_ERROR = 3;

/*
	Description:
		construct a formItem object containing the provided data members
	Expects:
		objField - the field object to be validated
		strFieldType - the type of field value (string, float, integer, list, radio, checkbox)
		strName - display name for the associated field
		intMin - minimum accepted value for the field (null if no minimum)
		intMax - maximum accepted value for the field (null if no maximum)		
		blnRequired - flag denoting if a value is required for the field
	Returns:
		newly created formItem object
*/
function formItem( objField, strFieldType, strName, intMin, intMax, blnRequired ) {
	this.objField = objField;
	this.strFieldType = strFieldType;
	this.strName = strName;
	this.intMin = intMin;
	this.intMax = intMax;
	this.blnRequired = blnRequired;
}

/*
	Description:
		construct a returnValue object containing the provided data members
	Expects:
		intCode - integer return code (0, 1, 2, 3)
		strMessage - message string if method is not successful
	Returns:
		newly created returnValue object
*/
function returnValue( intCode, strMessage ) {
	this.intCode = intCode;
	this.strMessage = strMessage;
}

/*
	Description:
		validate each item provided in the formItem array parameter according to its
		type and criteria
	Expects:
		arrFormItems - array of formItem objects
		blnStopOnError - flag denoting if the method should return on the first error
			or validate every formItem prior to returning
	Returns:
		boolean denoting success or failure
*/
function validateFormItems( arrFormItems, blnStopOnError ) {
	var retValue;
	var blnError = false;
	var strMessage = "The following errors occurred validating the form:\n";
	var objItem = null;

	for( var intCount = 0; intCount < arrFormItems.length; intCount++ ) {
		objItem = arrFormItems[intCount]; 

		//	Determine the field type, and call the appropriate validation function
		switch ( objItem.strFieldType.toUpperCase( ) ) {
		case "DATE":
			retValue = chkDate( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "INTEGER":
			retValue = chkInteger( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "FLOAT":
			retValue = chkFloat( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "CURRENCY":
			retValue = chkCurrency( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "STRING":
			retValue = chkString( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "LIST":
			retValue = chkList( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "RADIO":
			retValue = chkRadio( objItem.objField, objItem.strName, objItem.blnRequired );
			break;
		case "CHECKBOX":
			retValue = chkCheckbox( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "ZIP":
			retValue = chkUSZip( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		case "PHONE":
			retValue = chkPhone( objItem.objField, objItem.strName, objItem.intMin, objItem.intMax, objItem.blnRequired );
			break;
		default:
			retValue = new returnValue( PROG_ERROR, "Invalid field type provided" );
		}

		//	Examine the return value and determine if the function should return immediately
		if( retValue.intCode == PROG_ERROR ) {
			alert( retValue.strMessage );
			return false;
		} else if( retValue.intCode == BAD_VALUE || retValue.intCode == MISSING_VALUE ) {
			if( blnStopOnError == true ) {
				alert( retValue.strMessage );
				blnError = true;
				break;
			} else {
				strMessage += "\n" + retValue.strMessage;
				blnError = true;
			}
		}
	}
	
	if( blnError == true ) alert( strMessage );
	return !blnError;		
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum string value length	(null if no minimum)
					 intMax - maximum string value length (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkString(objField, strName, intMin, intMax, blnRequired) {
	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided type is valid
	if ( !( objField.type == "text" || objField.type == "textarea" 
			|| objField.type == "password" || objField.type == "hidden" 
			|| objField.type == "file" ) ) {
		//	Only text controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform string validation" );
	} else if( intMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( intMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum string field size parameter not a valid number" );
		}
	} else if( intMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( intMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum string field size parameter not a valid number" );
		}
	}
	
	//	Trim out leading and trailing spaces
	objField.value = Trim( objField.value );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	The field contains data - determine if it's in range
		if( intMin != null && intLength < intMin ) {
			return new returnValue( BAD_VALUE, strName + ": The provided string is too short - expecting at least " + intMin.toString( ) + " characters" );
		}
		
		if( intMax != null && intLength > intMax ) {
			return new returnValue( BAD_VALUE, strName + ": The provided string is too long - expecting no more than " + intMax.toString( ) + " characters" );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value (null if no minimum)
					 intMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkInteger(objField, strName, intMin, intMax, blnRequired) {
	var num = "-0123456789";
	var strCompare = "";

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}

	//	Determine if the provided data is valid
	if (!( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform integer validation" );
	} else if( intMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( intMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( intMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( intMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}
	
	//	Trim out leading and trailing spaces
	objField.value = Trim( objField.value );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	The field is numeric - determine if it is within range
		var chCurrent;
		for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
			chCurrent = objField.value.charAt( intLoop );
			
			//	Remove any commas
			if( chCurrent != "," ) {
				strCompare = strCompare + chCurrent;
			} else {
				continue;
			}
				
			if ( num.indexOf( chCurrent ) == -1 ) {
				//	The field contained a character not in our defined mask
				return new returnValue( BAD_VALUE, strName + ": The provided value is not an integer" );
			}
		}
		
		//	Check against the min if it was provided
		if( intMin != null && parseInt( strCompare ) < intMin ) {
			//	The value is less than the minimum
			return new returnValue( BAD_VALUE, strName + ": The provided number is too small - expecting at least " + intMin.toString( ) );
		}
			
		//	Check against the max if it was provided
		if( intMax != null && parseInt( strCompare ) > intMax ) {
			//	The value is greater than the maximum
			return new returnValue( BAD_VALUE, strName + ": The provided number is too large - expecting no more than " + intMax.toString( ) );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}	
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value (null if no minimum)
					 intMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkFloat(objField, strName, fltMin, fltMax, blnRequired) {
	var num = "-.0123456789";
	var strCompare = "";

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided data is valid
	if (!( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform float validation" );
	} else if( fltMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( fltMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( fltMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( fltMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}
	
	//	Trim out leading and trailing spaces
	objField.value = Trim( objField.value );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	The field is numeric - determine if it is within range
		var chCurrent;
		var blnDecimalFound = false;
		for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
			chCurrent = objField.value.charAt( intLoop );
			
			//	Check decimal
			if( chCurrent == "." && blnDecimalFound == true ) {
				return new returnValue( BAD_VALUE, strName + ": The provided value contains more than one decimal point" );				
			} else if( chCurrent == "." ) {
			 blnDecimalFound = true;
			}
			
			//	Remove any commas
			if( chCurrent != "," ) {
				strCompare = strCompare + chCurrent;
			} else {
				continue;
			}
				
			if( num.indexOf( chCurrent ) == -1 ) {
				//	The field contained a character not in our defined mask
				return new returnValue( BAD_VALUE, strName + ": The provided value is not a number" );
			}
		}
		
		//	Check against the min if it was provided
		if( fltMin != null && parseFloat( strCompare ) < fltMin ) {
			//	The value is less than the minimum
			return new returnValue( BAD_VALUE, strName + ": The provided number is too small - expecting at least " + fltMin.toString( ) );
		}
			
		//	Check against the max if it was provided
		if( fltMax != null && parseFloat( strCompare ) > fltMax ) {
			//	The value is greater than the maximum
			return new returnValue( BAD_VALUE, strName + ": The provided number is too large - expecting no more than " + fltMax.toString( ) );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}	
}

	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value (null if no minimum)
					 intMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkCurrency(objField, strName, fltMin, fltMax, blnRequired) {
	var num = "-.0123456789";
	var strCompare = "";

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided data is valid
	if (!( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform currency validation" );
	} else if( fltMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( fltMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( fltMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( fltMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}
	
	//	Trim out leading and trailing spaces
	objField.value = Trim( objField.value );

	//	Obtain the length	
	var intLength = objField.value.length;
	
	//	Trim out the dollar sign if included
	if( objField.value.charAt(0) == '$' )
		objField.value = objField.value.substr(1, --intLength)
		
	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	The field is numeric - determine if it is within range
		var chCurrent;
		var blnDecimalFound = false;
		for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
			chCurrent = objField.value.charAt( intLoop );
			
			//	Check decimal
			if( chCurrent == "." && blnDecimalFound == true ) {
				return new returnValue( BAD_VALUE, strName + ": The provided value contains more than one decimal point" );				
			} else if( chCurrent == "." ) {
			 blnDecimalFound = true;
			}
			
			//	Remove any commas
			if( chCurrent != "," ) {
				strCompare = strCompare + chCurrent;
			} else {
				continue;
			}
				
			if( num.indexOf( chCurrent ) == -1 ) {
				//	The field contained a character not in our defined mask
				return new returnValue( BAD_VALUE, strName + ": The provided value is not a currency" );
			}
		}
		
		//	Check against the min if it was provided
		if( fltMin != null && parseFloat( strCompare ) < fltMin ) {
			//	The value is less than the minimum
			return new returnValue( BAD_VALUE, strName + ": The provided dollar amount is too small - expecting at least $" + fltMin.toString( ) );
		}
			
		//	Check against the max if it was provided
		if( fltMax != null && parseFloat( strCompare ) > fltMax ) {
			//	The value is greater than the maximum
			return new returnValue( BAD_VALUE, strName + ": The provided dollar amount is too large - expecting no more than $" + fltMax.toString( ) );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}	
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value (null if no minimum)
					 intMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkList(objField, strName, intMin, intMax, blnRequired) {
	var intCount, intNumSelected = 0;

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided data is valid
	if ( objField.type.indexOf( "select" ) == -1 ) {
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform select list validation" );
	} else if( intMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( intMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( intMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( intMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}

	//	Determine if any options have been selected
	for( intCount = 0, intNumSelected = 0; intCount < objField.length; intCount++ ) {
		if( objField.options[intCount].selected == true && objField.options[intCount].value != "" )
			++intNumSelected;
	}
	
	if( intNumSelected > 0 ) {
		//	Options have been selected - determine if the number is in range
		if( intMin != null && intNumSelected < intMin ) {
			//	Not enough have been selected - return intBadValue
			return new returnValue( BAD_VALUE, strName + ": Not enough options selected - expecting at least " + intMin.toString( ) );
		}
		
		if( intMax != null && intNumSelected > intMax ) {
			//	Too many have been selected - return intBadValue
			return new returnValue( BAD_VALUE, strName + ": Too many options selected - expecting no more than " + intMax.toString( ) );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value (null if no minimum)
					 intMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkCheckbox(objField, strName, intMin, intMax, blnRequired) {
	var intCount, intNumSelected = 0;
	
	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided data is valid
	if ( objField.type == "checkbox" ) {
		//	Only radio controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform checkbox validation" );
	}

	//	Determine if any options have been selected
	for( intCount = 0; intCount < objField.length; intCount++ ) {
		if( objField[intCount].checked == true )	{
			++intNumSelected;
		}
	}
	
	if( intNumSelected > 0 ) {
		//	Options have been selected - determine if the number is in range
		if( intMin != null && intNumSelected < intMin ) {
			//	Not enough have been selected - return intBadValue
			return new returnValue( BAD_VALUE, strName + ": Not enough options selected - expecting at least " + intMin.toString( ) );
		}
		
		if( intMax != null && intNumSelected > intMax ) {
			//	Too many have been selected - return intBadValue
			return new returnValue( BAD_VALUE, strName + ": Too many options selected - expecting no more than " + intMax.toString( ) );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required - return intValid
			return new returnValue( VALID_VALUE, "" );
		}
	}
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkRadio(objField, strName, blnRequired) {
	var intCount, blnSelected = false;
	
	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}
	
	//	Determine if the provided data is valid
	if ( objField.type == "radio" ) {
		//	Only radio controls valid for this function
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform radio button validation" );
	}

	//	Determine if any options have been selected
	for( intCount = 0; intCount < objField.length; intCount++ ) {
		if( objField[intCount].checked == true )	{
			blnSelected = true;
			break;
		}
	}
		
	if( blnSelected == false && blnRequired == true ) {
		//	The field is required
		return new returnValue( MISSING_VALUE, strName + ": An answer is required for this field" );
	} else {
		//	The field is not required
		return new returnValue( VALID_VALUE, "" );
	}
}
	
/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 dtMin - minimum value (null if no minimum)
					 dtMax - maximum value (null if no maximum)
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkDate(objField, strName, dtMin, dtMax, blnRequired) {
	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}

	//	Determine if the provided data is valid
	if( !( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function - return intError
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform date validation" );
	} else if( dtMin != null ) {
		//	A min was provided - is it a valid date
		if( isNaN( Date.parse( dtMin ) ) ) {
			//	Not a valid date - return intError
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value is not a date type" );
		}
	} else if( dtMax != null ) {
		//	A max was provided - is it a valid date
		if( isNaN( Date.parse( dtMax ) ) ) {
			//	Not a valid date - return intError
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value is not a date type" );
		}
	}	

	//	Trim out leading and trailing spaces
	objField.value = Trim( objField.value );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	The field contains data - are the provided parameters dates
		if( !isNaN( Date.parse( objField.value ) ) ) {
			//	The field is a date - is it in within the valid range 
			if( dtMin != null ) {
				//	A minimum date is provided - check against it
				if( Date.parse( objField.value ) < Date.parse( dtMin ) ) {
					//	The field is not within the valid range
					return new returnValue( BAD_VALUE, strName + ": The provided date is too early - expecting a date after " + dtMin.toString( ) );
				}
			}
			
			if( dtMax != null ) {
				//	A maximum date is provided - check against it
				if( Date.parse( objField.value ) > Date.parse( dtMax ) ) {
					//	The field is not within the valid range - return intBadValue
					return new returnValue( BAD_VALUE, strName + ": The provided date is too late - expecting a date before " + dtMax.toString( ) );
				}
			}
			
			//	If we are here, then the value is in range so return intValid				
			return new returnValue( VALID_VALUE, "" );
		} else {	
			//	The field is not a date
			return new returnValue( BAD_VALUE, strName + ": The provided value is not a date" );
		}
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required
			return new returnValue( VALID_VALUE, "" );
		}
	}
}

/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum value
					 intMax - maximum value
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkUSZip(objField, strName, intMin, intMax, blnRequired) {
	var num = "0123456789";
	var noise = "-";

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}

	//	Determine if the provided data is valid
	if( !( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function - return intError
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform date validation" );
	} else if( intMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( intMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( intMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( intMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}	

	//	Trim out leading and trailing spaces
	objField.value = Trim( Scrub( objField.value, noise ) );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	Ensure that each character is numeric
		var chCurrent;
		for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
			chCurrent = objField.value.charAt( intLoop );
	
			if ( num.indexOf( chCurrent ) == -1 ) {
				//	The field contained a character not in our defined mask
				return new returnValue( BAD_VALUE, strName + ": The provided value is not a valid zip code" );
			}
		}
			
		//	determine if it's in range
		if( intMin != null && intLength < intMin ) {
			return new returnValue( BAD_VALUE, strName + ": The provided zip code is too short - expecting at least " + intMin.toString( ) + " numbers" );
		}
		
		if( intMax != null && intLength > intMax ) {
			return new returnValue( BAD_VALUE, strName + ": The provided zip is too long - expecting no more than " + intMax.toString( ) + " numbers" );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required
			return new returnValue( VALID_VALUE, "" );
		}
	}
}

/*
	Description: Ensures that the provided field's value is valid
	Expects: objField - field to be validated
					 strName - display name for the field
					 intMin - minimum length
					 intMax - maximum length
					 blnRequired - true if a value is required, false otherwise
	Returns: 0 - Valid
					 1 - Missing
					 2 - Out of range
					 3 - Programming error
*/
function chkPhone(objField, strName, intMin, intMax, blnRequired) {
	var num = "0123456789";
	var noise = "().-";

	//	Check for a field display name
	if( strName.length == 0 ) {
		strName = objField.name;
	}

	//	Determine if the provided data is valid
	if( !( objField.type == "text" || objField.type == "hidden" ) ) {
		//	Only text controls valid for this function - return intError
		return new returnValue( PROG_ERROR, objField.name + ": Invalid field type ( " + objField.type + " )  to perform date validation" );
	} else if( intMin != null ) {
		//	A min was provided - is it a valid number
		if( isNaN( intMin ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided minimum value parameter not a valid number" );
		}
	} else if( intMax != null ) {
		//	A max was provided - is it a valid number
		if( isNaN( intMax ) ) {
			//	Not a valid number
			return new returnValue( PROG_ERROR, objField.name + ": Provided maximum value parameter not a valid number" );
		}
	}

	//	Trim out leading and trailing spaces
	objField.value = Trim( Scrub( objField.value, noise ) );
	var intLength = objField.value.length;

	//	Determine if the field contains data
	if( intLength > 0 ) {
		//	Ensure that each character is numeric
		var chCurrent;
		for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
			chCurrent = objField.value.charAt( intLoop );
	
			if ( num.indexOf( chCurrent ) == -1 ) {
				//	The field contained a character not in our defined mask
				return new returnValue( BAD_VALUE, strName + ": The provided value is not a valid phone number" );
			}
		}
			
		//	determine if it's in range
		if( intMin != null && intLength < intMin ) {
			return new returnValue( BAD_VALUE, strName + ": The provided phone number is too short - expecting at least " + intMin.toString( ) + " numbers" );
		}
		
		if( intMax != null && intLength > intMax ) {
			return new returnValue( BAD_VALUE, strName + ": The provided phone number is too long - expecting no more than " + intMax.toString( ) + " numbers" );
		}
			
		//	If we are here, then the value is in range so return intValid				
		return new returnValue( VALID_VALUE, "" );
	} else {
		//	The field contains no data - is it required
		if( blnRequired == true ) {
			//	The field is required - return intMissing
			return new returnValue( MISSING_VALUE, strName + ": A value is required for this field" );
		} else {
			//	The field is not required
			return new returnValue( VALID_VALUE, "" );
		}
	}
}

//Utility functions======================================================================

//  Scrub out specified characters
function Scrub( inputValue, noise ) {
	var intLength = inputValue.length;
	var chCurrent;
	var scrubbed = "";

	for ( var intLoop = 0; intLoop < intLength; intLoop++ ) {
		chCurrent = inputValue.charAt( intLoop );
		
		//	Remove any noise characters
		if ( noise.indexOf( chCurrent ) >= 0 ) {
			continue;
		} else {
			scrubbed = scrubbed + chCurrent;
		}
	}
	
	//	Return the scrubbed value
	return scrubbed;
}

//	Trim out spaces from both ends of a string
function Trim( strInput ) {
	var intCount, intBegin = -1, intEnd = -1;
	var strReturn = "", strChar;
	
	//	Read from the beginning until a non-space character
	//	or the end of the string is reached
	for( intCount = 0; intCount < strInput.length; intCount++ ) {
		//	Examine the character
		if( strInput.charAt( intCount ) != " " ) {
			//	Non-space character found, record the location
			intBegin = intCount;
			break;
		}
	}
	
	//	If the begin flag is -1, then the entire string
	//	is filled with space characters, so we're done
	if( intBegin == -1 ) {
		return "";
	} else {
		//	Read from the end until a non-space character
		//	or the beginning of the string is reached (shouldn't happen)
		for( intCount = strInput.length - 1; intCount >= 0; intCount-- ) {
			//	Examine the character
			if( strInput.charAt( intCount ) != " " ) {
				//	Non-space character found, record the location
				intEnd = intCount;
				break;
			}
		}
		
		//	This shouldn't happen, but if the end flag is -1
		//	then the string is filled with space characters
		if( intEnd == -1 ) {
			return "";
		} else {
			//	Return the substring
			return strInput.substr( intBegin, intEnd - intBegin + 1 );
		}
	}
}

function validEmail(email) {
	var atSignIndex = email.indexOf('@');
	var dotIndex = email.lastIndexOf('.');
	
	if( email.length > 0 )
		return ( atSignIndex > 0 && atSignIndex < dotIndex && dotIndex == ( email.length - 4 ) );
	else
		return false;
}