/* <%--
//
//	File: 		validate/number.js
//	Purpose:	Provide numeric JavaScript validation operations
//  Usage:    This file contains functions for validating numeric fields
//            using JavaScript.
//            See the file header.js for details on the validation process.



// ------ PUBLIC FUNCTION INDEX
// VAL_IsDigit( c )
// VAL_IsDigitString( str )
// VAL_IsLetterOrDigit( c )
// VAL_IsInteger( str )
// VAL_IsIntegerMin( str, min )
// VAL_IsIntegerMinExclusive( str, min )
// VAL_IsIntegerMax( str, max )
// VAL_IsIntegerMaxExclusive( str, max )
// VAL_IsIntegerRange( str, min, max )
// VAL_IntegerBoundsCheck ( str, min, max )
// VAL_IsIntegerColumn (form, baseField, count, blankOK, keepHidden)
// VAL_BadIntegerColAppend (form, baseField, count, message, blankOK, keepHidden)
// VAL_IsIntegerColumnRange ( form, baseField, count, min, max, blankOK, keepHidden)
// VAL_IsIntegerRangeFormat(form,	fieldName, min, max, numberFormat)
// VAL_BadIntegerRangeColAppend (form, baseField, count, min, max, message, blankOK, keepHidden)
// VAL_IsFloat( str, maxPrecision )
// VAL_IsFloatMin ( str, min, exclusive )
// VAL_IsFloatMinPrecision ( str, min, maxPrecision, exclusive )
// VAL_IsFloatMax ( str, max, exclusive )
// VAL_IsFloatMaxPrecision ( str, max, maxPrecision, exclusive )
// VAL_IsFloatMinPrecisionFormat(form, fieldName, min, maxPrecision, numberFormat, exclusive)
// VAL_IsFloatRange ( str, min, max, minExclusive, maxExclusive )
// VAL_IsFloatRangeFormat ( form, fieldName, min, max, minExclusive, maxExclusive )
// VAL_IsFloatRangePrecision ( str, min, max, maxPrecision, minExclusive, maxExclusive )
// VAL_IsFloatColumn ( form, baseField, count, keepHidden )
// VAL_BadFloatColAppend ( form, baseField, count, message, keepHidden )
// VAL_IsMoney( str )
// VAL_IsPosOrNegMoney (str)
// VAL_IsMoneyColumn ( form, baseField, blankOK, keepHidden, startIndex, stopCount )
// VAL_BadMoneyColAppend ( form, baseField, message, blankOK, keepHidden, startIndex, stopCount )
// VAL_ValidateNumber ( field, fieldType, fieldLabel, message )
// VAL_ValidateNumberLimit (form, field, fieldType, fieldLabel, numberFormat, limit, message )
// VAL_ValidateNumberColumn (form, baseField, fieldType, fieldLabel, message)
// VAL_ValidateNumberCompare (form, field1, field2, fieldType, fieldLabel1,fieldLabel2, numberFormat1,numberFormat2, message )
// VAL_IsBlankNumber( form, fieldName )
// VAL_NumberSet( form, fieldName, numberType, numberFormat, numberString )
// VAL_NumberGet( form, fieldName)
// VAL_IsIntegerFormat (	form,	fieldRef, numberFormat )
// VAL_IsIntegerMinFormat (	form,	fieldName, min, numberFormat )
// VAL_IsMoneyFormat (	form,	fieldName, numberFormat )
// VAL_IntegerBoundsCheckFormat( form, fieldName, min, max,	numberFormat )
// VAL_ValidateNumberFormat ( form, fieldRef, numberType, fieldLabel, numberFormat, message )
// VAL_NumberRequiredWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat )
// VAL_NumberCheckLimitWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, requiredFlag, limit, message )
// VAL_NumberCheckWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, requiredFlag, message )
// VAL_CurrencyStringToCurrencyValue ( currencyString, numberFormat )
// formatCurrency(num)
// VAL_CurrencyValueToCurrencyString( currencyValue, numberFormat)
// VAL_NumberWithoutFormat( numberRef)
	
//------ EXAMPLE JAVASCRIPT for VAL_BadFloatColAppend()
function SubmitForm()
{
	VAL_Initialize();
	var form = frames[1].document.forms[0];
	var count = <%= data.rowCount( "SVBClaim" ) %>;

	VAL_BadFloatColAppend (form, "SVBClaim_AmountSubmitted", count, true,
		"Amount Submitted must be either blank or numeric!", false);

	// now either submit the form or display any error messages
	VAL_SubmitForm (form);
}
// ------ END EXAMPLE JAVASCRIPT

--%> */

// ------ GLOBAL PREFERENCES

// decimal point character differs by language and culture
var VAL_decimalDelim = new String(".");
var VAL_thousandDelim = new String( ",");


// ------------------------------------------------------------------------ //
// Returns true if character c is a thousand separator

function VAL_IsThousandSeparator(
	c // character to check
)
{
	return (c == VAL_thousandDelim);
}


// ------------------------------------------------------------------------ //
// Returns true if a number is fully divided by a factor

function VAL_IsDivided(
	n, // number to check
	f // factor
)
{
	return ((n % f) == 0);
}


// ------------------------------------------------------------------------ //
// Returns true if character c is a digit

function VAL_IsDigit(
	c // character to check
)
{
	return ((c >= "0") && (c <= "9"));
}

// ------------------------------------------------------------------------ //
// Returns true if string str contains all digits

function VAL_IsDigitString(
	str // string to check
)
{
	for (var i = 0; i < str.length; i++)
	{
		// Check that current character is number.
		var c = str.charAt(i);
		if (!VAL_IsDigit(c))
			return false;
	}
	return true;
}

// ------------------------------------------------------------------------ //
//Returns true if character c is a letter
function VAL_IsLetter(
	c //character to check
)
{
	if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z"))
		return true;
	else
		return false;
}

//-------------------------------------------------------------------------- //
// Returns true if character c is a letter OR digit
function VAL_IsLetterOrDigit(
	c // character to check
)
{
	return (VAL_IsLetter(c) || VAL_IsDigit(c));
}

function VAL_IsAlphaNumeric (str)
{
	var retVal = true;
	for (var i = 0; i < str.length; i++)
	{
		// Check that current character is number.
		var c = str.charAt(i);
		if (!VAL_IsLetterOrDigit(c))
			retVal = false;
	}
	return retVal;
}


// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value.  This can
// include signs.
// Don't use parseInt because that would accept a string with trailing
// non-numeric characters.

function VAL_IsInteger(
	str // string to check
)
{
	var startPos = 0;

	// skip leading + or -
	if ( (str.charAt(0) == "-") || (str.charAt(0) == "+") )
		 startPos = 1;

	var tempStr = str.substring (startPos, str.length);
	if (VAL_IsBlank(tempStr)) { return false; }

	// Search through string's characters one by one until we find a non-numeric
	// character. When we do, return false; if we don't, return true.

	
	for (var i = 0; i < tempStr.length; i++)
	{
		// Check that current character is number.
		var c = tempStr.charAt(i);
		if (!VAL_IsDigit(c))
		{
			if (!VAL_IsThousandSeparator (c))
				return false;
			else
			{
				if (tempStr.length < 4)
					return false;
				if (!VAL_IsDivided ((tempStr.length - i), 4))
					return false;
			}
		}
	}

	// All characters are numbers, with commas at correct places.
	return true;
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value and is greater
// than or equal to the value passed in.
// See VAL_IsInteger for parsing details.

function VAL_IsIntegerMin(
	str, // string to check
	min  // minimum value
)
{
	return VAL_IsInteger( str ) && (parseInt( str, 10 ) >= min);
	
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value and is greater
// than the value passed in.
// See VAL_IsInteger for parsing details.

function VAL_IsIntegerMinExclusive(
	str, // string to check
	min  // minimum value	
)
{	
	return VAL_IsInteger( str ) && (parseInt( str, 10 ) > min);	
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value and is less than
// or equal to the value passed in.
// See VAL_IsInteger for parsing details.

function VAL_IsIntegerMax(
	str, // string to check
	max  // maxumum value	
)
{	
	return VAL_IsInteger( str ) && (parseInt( str, 10 ) <= max);	
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value and is less than
// the value passed in.
// See VAL_IsInteger for parsing details.

function VAL_IsIntegerMaxExclusive(
	str, // string to check
	max  // maxumum value	
)
{	
	return VAL_IsInteger( str ) && (parseInt( str, 10 ) < max);	
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is an integer value and is in the
// passed in range (inclusive).
// See VAL_IsInteger for parsing details.

function VAL_IsIntegerRange(
	str, // string to check
	min, // minimum value
	max  // maximum value
)
{
	return VAL_IsInteger( str ) && (parseInt( str, 10 ) >= min) && (parseInt( str, 10 ) <= max);
}


// ------------------------------------------------------------------------ //
// Performs min, max, or range check depending on which boundaries supplied.
//
function VAL_IntegerBoundsCheck ( str, min, max )
{
	var noMin = ( min == null || ! VAL_IsInteger ( "" + min ) );
	var noMax = ( max == null || ! VAL_IsInteger ( "" + max ) );
	if ( noMin && noMax ) return false;
	else if ( noMin ) return VAL_IsIntegerMax  ( str, max );
	else if ( noMax ) return VAL_IsIntegerMin  ( str, min );
	else return VAL_IsIntegerRange ( str, min, max );
}


// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT an integer.
// Returns index to offending field or -1 if all are valid integers.
// Skips over hidden fields unless specified to keep them.
// See VAL_GetFieldArrayRef() for more details.
// You should probably use VAL_BadIntegerColAppend() since it calls this.
//
function VAL_IsIntegerColumn (form, baseField, count, blankOK, keepHidden)
{
	var fieldRef;
	var badField = -1;

	for (var index = 0; index < count; index ++)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);

		if (
			VAL_FieldBlankOrHiddenOk ( fieldRef, ! blankOK, keepHidden )
			&& ! VAL_IsInteger ( fieldRef.value )
		){
			badField = index;
			break;
		}
	}
	return badField;
}


// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT an integer.
// Appends error message to running list and returns true if there's a problem,
// otherwise returns false. See VAL_IsIntegerColumn() for more details.
// keepHidden is usually false.
//
function VAL_BadIntegerColAppend (form, baseField, count, message, blankOK, keepHidden)
{
	var fieldRef;
	var status = false;	// no problems yet
	var badField = VAL_IsIntegerColumn (form, baseField, count, blankOK, keepHidden);

	if (badField != -1)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, badField);
		VAL_AppendError (message, fieldRef);
		status = true;	// oops, there's a problem
	}

	return status;
}


// ------------------------------------------------------------------------ //
// Determines if any integer in an array of fields (column) is out of bounds.
// Returns index to offending field or -1 if all are within range.
// Supply blank min or max to have skip lower or upper bounds check.
// Skips over hidden fields unless specified to keep them.
// See VAL_GetFieldArrayRef() for more details.
// You should probably use VAL_BadIntegerRangeColAppend() since it calls this.
//
function VAL_IsIntegerColumnRange ( form, baseField, count, min, max, blankOK, keepHidden)
{
	var fieldRef;
	var badField = -1;

	for (var index = 0; index < count; index ++)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);

		if (
			VAL_FieldBlankOrHiddenOk ( fieldRef, ! blankOK, keepHidden )
			&& ! VAL_IntegerBoundsCheck ( fieldRef.value, min, max )
		){
			badField = index;
			break;
		}
	}
	return badField;
}


// ------------------------------------------------------------------------ //
// Determines if any integer in an array of fields (column) is out of bounds.
// Appends error message to running list and returns true if there's a problem,
// otherwise returns false. See VAL_IsIntegerColumnRange() for more details.
// keepHidden is usually false.
//
function VAL_BadIntegerRangeColAppend (form, baseField, count, min, max, message, blankOK, keepHidden)
{
	var fieldRef;
	var status = false;	// no problems yet
	var badField = VAL_IsIntegerColumnRange (form, baseField, count, min, max, blankOK, keepHidden);

	if (badField != -1)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, badField);
		VAL_AppendError (message, fieldRef);
		status = true;	// oops, there's a problem
	}

	return status;
}


// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating point value.  This can
// include signs.  Integer values are accepted as floating point values.
// Does not accept exponential notation.

function VAL_IsFloat (
	str, // string to check
	maxPrecision  // number of decimal points
)
{
	if (VAL_IsBlank(str)) { return false; }

	var startPos = 0;

	// skip leading + or -
	if ( (str.charAt(0) == "-") || (str.charAt(0) == "+") )
		 startPos = 1;

	var i;
	var decimalPos = str.indexOf(VAL_decimalDelim);

	if (decimalPos != -1)
	{
		var num = str.substring (startPos, decimalPos);
		var dec = str.substring (decimalPos + 1, str.length);
		if (maxPrecision != null && dec.length > maxPrecision) {
			return false;
		}

		if (decimalPos == startPos){
			if(num.length == 0 && dec.length == 0)
				return false;
			else
				return VAL_IsNumericString (dec);
		}	else {
			if (!VAL_IsInteger (num))
				return false;
			else
				return VAL_IsNumericString (dec);
		}
	}

	else
	{
		if (VAL_IsInteger (str))
			return true;
		else
			return false;
	}
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is greater
// than or equal to the value passed in. Use the exclusive arg for "greater
// than" versus "greater than or equal to" comparison. If you don't include
// the arg in the function call then inclusive is the default.
// See SVAL_IsFloat for parsing details.

function VAL_IsFloatMin (
	str, // string to check
	min, // minimum value
	exclusive // optional, true means ">", false or null means inclusive ">=" (default)
)
{
	return VAL_IsFloatMinPrecision( str, min, null, exclusive );
}


// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is greater
// than or equal to the value passed in and has the maximum number of digits
// for precision.  Use the exclusive arg for "greater
// than" versus "greater than or equal to" comparison. If you don't include
// the arg in the function call then inclusive is the default.
// See SVAL_IsFloat for parsing details.

function VAL_IsFloatMinPrecision (
	str, // string to check
	min, // minimum value
	maxPrecision,  // number of decimal points
	exclusive // optional, true means ">", false or null means inclusive ">=" (default)
)
{
	var op = ">=";
	if ( exclusive ) op = ">";
	return eval ( "( VAL_IsFloat( str, maxPrecision ) && parseFloat( str ) " + op + " min )" );
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is less than
// or equal to the value passed in. Use the exclusive arg for "less than"
// versus "less than or equal to" comparison. If you don't include the arg
// in the function call then inclusive is the default.
// See SVAL_IsFloat for parsing details.

function VAL_IsFloatMax (
	str, // string to check
	max, // maximum value
	exclusive // optional, true means "<", false or null means inclusive "<=" (default)
)
{
	return VAL_IsFloatMaxPrecision( str, max, null, exclusive );
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is less than
// or equal to the value passed in and has the maximum number of digits
// for precision. Use the exclusive arg for "less than"
// versus "less than or equal to" comparison. If you don't include the arg
// in the function call then inclusive is the default.
// See SVAL_IsFloat for parsing details.

function VAL_IsFloatMaxPrecision (
	str, // string to check
	max, // maximum value
	maxPrecision,  // number of decimal points
	exclusive // optional, true means "<", false or null means inclusive "<=" (default)
)
{
	var op = "<=";
	if ( exclusive ) op = "<";
	return eval ( "( VAL_IsFloat( str, maxPrecision ) && parseFloat( str ) " + op + " max )" );
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is in the
// passed in range. Use minExclusive and maxExclusive for boundaries. If you
// don't include these args in the function call then inclusive is the default.

function VAL_IsFloatRange (
	str, // string to check
	min, // minimum value
	max, // maximum value
	minExclusive, // minimum
	maxExclusive
)
{
	return VAL_IsFloatRangePrecision( str, min, max, null, minExclusive, maxExclusive );
}

// ------------------------------------------------------------------------ //
// Returns true if the passed in string is a floating value and is in the
// passed in range and has the maximum number of digits for precision.
// Use minExclusive and maxExclusive for boundaries. If you
// don't include these args in the function call then inclusive is the default.
function VAL_IsFloatRangePrecision (
	str, // string to check
	min, // minimum value
	max, // maximum value
	maxPrecision,  // number of decimal points
	minExclusive, // minimum
	maxExclusive
)
{
	return VAL_IsFloatMin ( str, min, maxPrecision, minExclusive )
			&& VAL_IsFloatMax ( str, max, maxPrecision, maxExclusive );
}

// ------------------------------------------------------------------------ //
function VAL_IsNumericString (
	str // string to check
)
{
	// Search through dec string's characters one by one until we find a non-numeric
	// character. When we do, return false; if we don't, return true.

	for (var i = 0; i < str.length; i++)
	{
		// Check that current character is number.
		var c = str.charAt(i);
		if (!VAL_IsDigit(c))
			return false;
	}
	// All characters are OK
	return true;
}

// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT a float.
// Returns index to offending field or -1 if all are valid floats.
// Skips over hidden fields unless specified to keep them.
// See VAL_GetFieldArrayRef() for more details.
// You should probably use VAL_BadFloatColAppend() since it calls this.
//
function VAL_IsFloatColumn (form, baseField, count, blankOK, keepHidden)
{
	var fieldRef;
	var badField = -1;

	for (var index = 0; index < count; index ++)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);

		if (
			VAL_FieldBlankOrHiddenOk ( fieldRef, ! blankOK, keepHidden )
			&& ! VAL_IsFloat ( fieldRef.value )
		){
			badField = index;
			break;
		}
	}
	return badField;
}

// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT a float.
// Appends error message to running list and returns true if there's a
// problem, otherwise returns false. See VAL_IsFloatColumn() and example
// above for more details, keepHidden is usually false.
//
function VAL_BadFloatColAppend (form, baseField, count, message, blankOK, keepHidden)
{
	var fieldRef;
	var status = false;	// no problems yet
	var badField = VAL_IsFloatColumn (form, baseField, count, blankOK, keepHidden);

	if (badField != -1)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, badField);
		VAL_AppendError (message, fieldRef);
		status = true;	// oops, there's a problem
	}

	return status;
}


// ------------------------------------------------------------------------ //
// Returns true if the passed-in string is a validly formated money amount.
// Positive integer values and real values with 2 digits after the decimal point are
// accepted as correct format.
function VAL_IsMoney ( str )
{
	if (VAL_IsBlank(str)) { return false; }

	if (!VAL_IsFloat(str, 2)) { return false; }

	if (!VAL_IsInteger(str))
	{
		if (parseFloat(str) < 0) { return false;}

		return true;

	} else
	{
			if (parseInt(str) < 0) { return false; }
			else { return true; }
	}
}

function VAL_IsPosOrNegMoney (str)
{
	if (VAL_IsBlank(str)) { return false; }//check if blank

	if (!VAL_IsFloat(str)) { return false; }//check if its a float

	if (!VAL_IsInteger (str))							//float
	{
		var decimalPos = str.indexOf(VAL_decimalDelim);
		var decimalDigit = str.length - (decimalPos + 1);

		if (decimalDigit > 2 || decimalDigit < 1) { return false; }
		else { return true; }
	}
	return true;													//integer
}

// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT money.
// Returns index to offending field or -1 if all are valid money.
// Skips over hidden fields unless specified to keep them.
// See VAL_GetFieldArrayRef() for more details.
// You should probably use VAL_BadMoneyColAppend() since it calls this.
//
function VAL_IsMoneyColumn (
	form,		// html form reference
	baseField,	// table_field name
	blankOK,	// blank values considered valid, usually true
	keepHidden,	// check hidden fields also, usually false
	startIndex,	// optional, starting row index, default 0
	stopCount	// optional, exclusive end index, default (all)
) {
	startIndex = VAL_NVL ( startIndex, 0 );
	if ( stopCount == "" ) stopCount = null;
	var index = startIndex;
	var fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
	var badField = -1;

	while ( fieldRef != null && badField < 0
	&& ( stopCount == null || ( stopCount != null && index < stopCount ) ) ) {
		if (
			VAL_FieldBlankOrHiddenOk ( fieldRef, ! blankOK, keepHidden )
			&& ! VAL_IsMoney ( fieldRef.value )
		){
			badField = index;
		} else {
			index ++;
			fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
		}
	}

	return badField;
}

// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT money.
// Appends error message to running list and returns true if there's a
// problem, otherwise returns false. See VAL_IsMoneyColumn() and example
// above for more details, keepHidden is usually false.
//
function VAL_BadMoneyColAppend ( form, baseField, message, blankOK, keepHidden, startIndex, stopCount )
{
	var fieldRef;
	var status = false;	// no problems yet
	var badField = VAL_IsMoneyColumn ( form, baseField, blankOK, keepHidden, startIndex, stopCount );

	if ( badField >= 0 ) {
		fieldRef = VAL_GetFieldArrayRef (form, baseField, badField);
		VAL_AppendError (message, fieldRef);
		status = true;	// oops, there's a problem
	}

	return status;
}

// ------------------------------------------------------------------------ //
// Sums a column of values, assumes values are valid.
//
function VAL_ColumnSum ( form, baseField, keepHidden )
{
	if ( keepHidden == null ) keepHidden = true;
	var sum = 0.0;
	var index = 0;
	var fieldRef = VAL_GetFieldArrayRef (form, baseField, index);

	while ( fieldRef != null ) {
		if ( ! VAL_IsBlank ( fieldRef.value ) )
			sum += parseFloat ( fieldRef.value );
		index ++;
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
	}

	return sum;
}

// ------------------------------------------------------------------------ //
// validates the entered value, add error message if not valid
// fieldType = money, moneynegorpos, integer, integerminone, float
// message is optional

function VAL_ValidateNumber ( field, fieldType, fieldLabel, message )
{
	var invalid = false;
	if ( ! VAL_IsBlank( field.value ) ) {
		if ( fieldType.toLowerCase() == "money" ) {
			if ( ! VAL_IsMoney ( field.value ) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "moneynegorpos" ) {
			if ( ! VAL_IsPosOrNegMoney ( field.value ) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integer" ) {
			if ( ! VAL_IsIntegerMin ( field.value, 0) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integerminone" ) {
			if ( ! VAL_IsIntegerMin ( field.value, 1) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidPositiveIntegerMsg );
				invalid = true;
			}
		}		
		if ( fieldType.toLowerCase() == "float" ) {
			if ( ! VAL_IsFloatMin ( field.value, 0) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidFloatMsg );
				invalid = true;
			}
		}
		if ( invalid ) {
			if (errorMessage.indexOf( "%s" ) >= 0) {
				VAL_AppendError( sprintf( errorMessage, fieldLabel ), field );
			} else {
				// this one left in for backwards compatibility
				VAL_AppendError( fieldLabel + " " + errorMessage, field );
			}
		}
	}

	return !invalid;
}

// ------------------------------------------------------------------------ //
// validates the entered value and check against the limit, add error message if not valid
// fieldType = moneylessthan, moneylessequal, moneygreaterthan, moneygreaterequal, integerlessthan,
//	       integerlesseuqal,integergreaterthan,integergreaterequal
// message is optional

function VAL_ValidateNumberLimit (form, field, fieldType, fieldLabel, numberFormat, limit, message )
{
	var invalid = false;
	var limitNumber;
	
	// translate value from shadow field
	field.value = VAL_CurrencyStringToCurrencyValue(form.elements[VAL_GetShadowFieldName(field.name)].value, numberFormat);
	
	if ( ! VAL_IsBlank( field.value ) ) {
		if ( fieldType.toLowerCase() == "moneylessthan" ) {
			limitNumber = parseFloat(limit);
			if (VAL_IsMoney ( field.value )) {
				VAL_NumberSetWithoutFormat(field);
				if ( ! VAL_IsFloatMax(field.value, limitNumber, true)) {
					invalid = true;
				}
			} else {
				invalid = true;
			}

			if (invalid) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyLessThanMsg );
			}
		}
		
		if ( fieldType.toLowerCase() == "moneylessequal" ) {
			limitNumber = parseFloat(limit);
			if (VAL_IsMoney ( field.value )) {
				VAL_NumberSetWithoutFormat(field);
				if ( ! VAL_IsFloatMax(field.value, limitNumber, false)) {
					invalid = true;
				}
			} else {
				invalid = true;
			}
			
			if (invalid) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyLessEqualMsg );
			}
		}

		if ( fieldType.toLowerCase() == "moneygreaterthan" ) {
			limitNumber = parseFloat(limit);
			if (VAL_IsMoney ( field.value )) {
				VAL_NumberSetWithoutFormat(field);
				if ( !VAL_IsFloatMin(field.value, limitNumber, true)) {
					invalid = true;
				}
			} else {
				invalid = true;
			}
			
			if (invalid) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyGreaterThanMsg );
			}
		}

		if ( fieldType.toLowerCase() == "moneygreaterequal" ) {
			limitNumber = parseFloat(limit);
			if (VAL_IsMoney ( field.value )) {
				VAL_NumberSetWithoutFormat(field);
				if ( !VAL_IsFloatMin(field.value, limitNumber, false)) {
					invalid = true;
				}
			} else {
				invalid = true;
			}
			
			if (invalid) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyGreaterEqualMsg );
			}
		}		

		if ( fieldType.toLowerCase() == "integerlessthan" ) {
			limitNumber = parseInt(limit);
			if ( ! VAL_IsIntegerMaxExclusive( field.value, limitNumber) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerLessThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integerlesseuqal" ) {
			limitNumber = parseInt(limit);
			if ( ! VAL_IsIntegerMax ( field.value, limitNumber) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerLessEqualMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integergreaterthan" ) {
			limitNumber = parseInt(limit);
			if ( ! VAL_IsIntegerMinExclusive( field.value, limitNumber) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerGreaterThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integergreaterequal" ) {
			limitNumber = parseInt(limit);
			if ( ! VAL_IsIntegerMin( field.value, limitNumber) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerGreaterEqualMsg );
				invalid = true;
			}
		}
		
		
		if ( invalid ) {
			if (errorMessage.indexOf( "%s" ) >= 0) {
			VAL_AppendError( sprintf( errorMessage, fieldLabel, VAL_CurrencyValueToCurrencyString(limit,numberFormat) ), field );
			} else {
				// this one left in for backwards compatibility
				VAL_AppendError( fieldLabel + " " + errorMessage, field );
			}
		}
	}

	if (invalid == false) { 
		VAL_NumberSetWithoutFormat(field); 
	}
	
	return !invalid;
}



// ------------------------------------------------------------------------ //
// validates the entered value and check another one, add error message if not valid
// fieldType = moneylessthan, moneylessequal, moneygreaterthan, moneygreaterequal, integerlessthan,
//	       integerlesseuqal,integergreaterthan,integergreaterequal
// message is optional

function VAL_ValidateNumberCompare (form, field1, field2, fieldType, fieldLabel1,fieldLabel2, numberFormat1,numberFormat2, message )
{
	var invalid = false;
	var limitNumber;
	
	// translate value from shadow field
	field1.value = VAL_CurrencyStringToCurrencyValue(form.elements[VAL_GetShadowFieldName(field1.name)].value, numberFormat1);
	field2.value = VAL_CurrencyStringToCurrencyValue(form.elements[VAL_GetShadowFieldName(field2.name)].value, numberFormat2);
	
	if ( ! VAL_IsBlank( field.value ) ) {
		if ( fieldType.toLowerCase() == "moneylessthan" ) {
			
			if ( ! (VAL_IsMoney ( field1.value ) && VAL_IsMoney ( field2.value ) && VAL_IsFloatMax(field1.value,field2.value, true))) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyLessThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "moneylessequal" ) {
			
			if ( ! (VAL_IsMoney ( field1.value ) && VAL_IsMoney ( field2.value ) && VAL_IsFloatMax(field1.value, field2.value, false))) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyLessEqualMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "moneygreaterthan" ) {
			
			if ( ! (VAL_IsMoney ( field1.value ) && VAL_IsMoney ( field2.value ) && VAL_IsFloatMin(field1.value, field2.value, true)) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyGreaterThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "moneygreaterequal" ) {
			
			if ( ! (VAL_IsMoney ( field1.value ) && VAL_IsMoney ( field2.value )  && VAL_IsFloatMin(field1.value, field2.value, false)) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidMoneyGreaterEqualMsg );
				invalid = true;
			}
		}		
		if ( fieldType.toLowerCase() == "integerlessthan" ) {
			
			if ( ! VAL_IsIntegerMaxExclusive ( field1.value, field2.value) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerLessThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integerlesseuqal" ) {
			
			if ( ! VAL_IsIntegerMax ( field1.value, field2.value) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerLessEqualMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integergreaterthan" ) {
			
			if ( ! VAL_IsIntegerMinExclusive ( field1.value, field2.value) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerGreaterThanMsg );
				invalid = true;
			}
		}
		if ( fieldType.toLowerCase() == "integergreaterequal" ) {
			
			if ( ! VAL_IsIntegerMin ( field1.value, field2.value) ) {
				var errorMessage = VAL_NVL( message, VAL_invalidIntegerGreaterEqualMsg );
				invalid = true;
			}
		}
		
		
		if ( invalid ) {
			if (errorMessage.indexOf( "%s" ) >= 0) {
			VAL_AppendError( sprintf( errorMessage, fieldLabel1, fieldLabel2 ), field1 );
			} else {
				// this one left in for backwards compatibility
				VAL_AppendError( fieldLabel + " " + errorMessage, field );
			}
		}
	}

	if (invalid == false) { 
		VAL_NumberSetWithoutFormat(field1); 
		VAL_NumberSetWithoutFormat(field2); 
	}
	
	return !invalid;
}


// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT a valid data type.
// add error message if not valid
function VAL_ValidateNumberColumn (form, baseField, fieldType, fieldLabel, message)
{
	var fieldRef;
	var invalid = false;
	var index = 0;

	fieldRef = form.elements[baseField];
	if ( fieldRef != null ) { // Non-Array field
		if (VAL_ValidateNumber ( fieldRef, fieldType, fieldLabel, message ) != true ) {
			invalid = true;
		}
	} else { // Array field
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
		while ( fieldRef != null && invalid != true )
		{
			if ( VAL_ValidateNumber ( fieldRef, fieldType, fieldLabel, message ) != true ) {
				invalid = true;
			} else {
				index ++;
				fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
			}
		}
	}
}

// ------------------------------------------------------------------------ //
// Determines if any entry in an array of fields (column) is NOT a valid data type.
// add error message if not valid
function VAL_ValidateNumberColumnFormat (form, baseField, fieldType, fieldLabel, numberFormat, message)
{
	var fieldRef;
	var invalid = false;
	var index = 0;

	fieldRef = form.elements[baseField];
	if ( fieldRef != null ) { // Non-Array field
		if (VAL_ValidateNumberFormat ( form, fieldRef, fieldType, fieldLabel,numberFormat, message ) != true ) {
			invalid = true;
		}
	} else { // Array field

		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
		while ( fieldRef != null && invalid != true )
		{
			if ( VAL_ValidateNumberFormat (form, fieldRef, fieldType, fieldLabel, numberFormat, message ) != true ) {
				invalid = true;
			} else {
				index ++;
				fieldRef = VAL_GetFieldArrayRef (form, baseField, index);
			}
		}
	}
}


function VAL_IsFloatMinPrecisionFormat (
	form,
	fieldName, // string to check
	min, // minimum value
	maxPrecision,
	numberFormat,
	exclusive // optional, true means ">", false or null means inclusive ">=" (default)
)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);

	return VAL_IsFloatMinPrecision( form.elements[fieldName].value, min, maxPrecision, exclusive );
}

function VAL_IsIntegerRangeFormat(
	form,
	fieldName, // string to check
	min, // minimum value
	max,  // maximum value
	numberFormat

)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);

	return (VAL_IsIntegerRange( form.elements[fieldName].value, min, max));
}

function VAL_IsFloatRangeFormat (
	form,
	fieldName, // string to check
	min, // minimum value
	max, // maximum value
	numberFormat,
	minExclusive, // minimum
	maxExclusive // optional, true means ">", false or null means inclusive ">=" (default)
)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);
	if ( VAL_IsFloatRange( form.elements[fieldName].value, min, max, minExclusive, maxExclusive )) {
		VAL_NumberSetWithoutFormat(form.elements[fieldName]);
		return true;
	} else {
		return false;
	}

}


// ------------------------------------------------------------------------ //
// Copies and converts from user specific number format to internal number format
// a column of Currency InputShadow fields to the "real" currency fields.
//
function VAL_CurrencyShadowColumnCopy (form, baseField, count, numberFormat)
{
	var fieldRef;

	for (var index = 0; index < count; index ++)
	{
		fieldRef = VAL_GetFieldArrayRef (form, baseField, index);

		fieldRef.value = VAL_CurrencyStringToCurrencyValue(
							form.elements[VAL_GetShadowFieldName(fieldRef.name)].value, numberFormat);
		VAL_NumberSetWithoutFormat(fieldRef);

	}
}


function VAL_IsPosOrNegMoneyFormat ( 
	form,       // a form reference with the date to validate
	fieldName,  // the field name
	numberFormat
)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
							form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);

	if (VAL_IsPosOrNegMoney(form.elements[fieldName].value)) {
		VAL_NumberSetWithoutFormat(form.elements[fieldName]);
		return true;
	} else {
		return false;
	}

}

// VAL_IsMoneyColumn 
// VAL_BadMoneyColAppend


function VAL_IsBlankNumber(
      form,      // a form reference with the number to validate
      fieldName // the field name
)
{
  return VAL_IsBlankField(form, fieldName, "INPUTSHADOW");
}

// ------------------------------------------------------------------------ //
// Sets a number field from a number value
function VAL_NumberSet(
	form,          // a form reference with the number to validate
	fieldName,     // the name of the number field
	numberType,    // the number type for the field ("money", "integer")
	numberFormat,  // number format to use
	numberString   // number string value to set (without formatting)
)
{
	// assumming numberString is legall value
	// for shadows set the real field to blank if the shadow one is
	var shadowName = VAL_GetShadowFieldName(fieldName);
	var retVal ="";

	if ( numberType.toLowerCase() == "money" ) {
		form.elements[fieldName].value = numberString;
		retVal = VAL_CurrencyValueToCurrencyString(numberString,numberFormat);
	}

	if ( numberType.toLowerCase() == "integer" ) {

		// round it
		retVal = Math.round(numberString);

		form.elements[fieldName].value = retVal;
		retVal = VAL_CurrencyValueToCurrencyString(retVal,numberFormat);

		var len = retVal.length;
		retVal = retVal.substr(0, len-3);
	}	
			
	form.elements[shadowName].value = retVal;	
}

// Gets a number shadow field value
// If it is not a shadow field, then return its own value
function VAL_NumberGet(
	form,          // a form reference with the number to validate
	fieldName     // the name of the number field
)
{
	// assumming numberString is legal value
	// for shadows set the real field to blank if the shadow one is
	
	
	var shadowName = VAL_GetShadowFieldName(fieldName);
	var retVal ="";
	
	if (eval( form.elements[shadowName] )) {
		retVal = form.elements[shadowName].value;
	} else {
		retVal = form.elements[fieldName].value;
	}
	
	return retVal;	
}

function VAL_IsIntegerFormat(
	form,
	fieldRef,  // string to check
	numberFormat
)
{
  form.elements[fieldRef.name].value = VAL_CurrencyStringToCurrencyValue(
                  form.elements[VAL_GetShadowFieldName(fieldRef.name)].value, numberFormat);

  if (VAL_IsInteger(form.elements[fieldRef.name].value)) {
  	VAL_NumberSetWithoutFormat(fieldRef);
  	return true;
  } else {
  	return false;
  }
      
  return retVal;
}


function VAL_IsIntegerMinFormat(
	form, 
	fieldName,  // string to check
	min,  // minimum value
	numberFormat
)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);
 	if (VAL_IsIntegerMin(form.elements[fieldName].value, min)) {
	  	VAL_NumberSetWithoutFormat(form.elements[fieldName]);
	  	return true;
	} else {
	  	return false;
  	}
	
}

function VAL_IsMoneyFormat ( 
	form,       // a form reference with the date to validate
	fieldName,  // the field name
	numberFormat
)
{
	numberFormat = VAL_NVL(numberFormat, VAL_thousandDelim + VAL_decimalDelim);

	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
							form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);


	if (VAL_IsMoney(form.elements[fieldName].value)) {
		VAL_NumberSetWithoutFormat(form.elements[fieldName]);
		return true;
	} else {
		return false;
	}
			
}

function VAL_IntegerBoundsCheckFormat(
	form,
	fieldName, // string to check
	min, // minimum value
	max,  // maximum value
	numberFormat

)
{
	form.elements[fieldName].value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldName)].value, numberFormat);
	if (VAL_IntegerBoundsCheck( form.elements[fieldName].value, min, max)) {
			VAL_NumberSetWithoutFormat(form.elements[fieldName]);
			return true;
		} else {
			return false;
	}
	
}

// ------------------------------------------------------------------------ //
// validates the entered value, add error message if not valid
// fieldType = money, moneynegorpos, integer, integerminone, float
// message is optional

function VAL_ValidateNumberFormat ( form, fieldRef, numberType, fieldLabel, numberFormat, message )
{
	var valid = true;
	
	fieldRef.value = VAL_CurrencyStringToCurrencyValue(
									form.elements[VAL_GetShadowFieldName(fieldRef.name)].value, numberFormat);
	
	if ( VAL_ValidateNumber( fieldRef, numberType, fieldLabel, message)) {
		VAL_NumberSetWithoutFormat(fieldRef);
		return true;
	} else {
		return false;
	}	

}

function VAL_NumberRequiredWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, message )
{
	return VAL_NumberCheckWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, true, message);
}

function VAL_NumberRequiredWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat )
{
	return VAL_NumberCheckWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, true, "");
}

// ------------------------------------------------------------------------ //
// Builds an error message if the supplied number field contains a non-blank
// invalid number. Returns true if blank or valid, false if invalid. 
function VAL_NumberCheckWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, requiredFlag, message )
{
	
	return VAL_NumberCheckLimitWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, requiredFlag, null, message );
	
}

function VAL_NumberCheckLimitWithMessage ( form, fieldRef, numberType, fieldLabel, numberFormat, requiredFlag, limit, message )
{
	var retVal = true;	
	
	if (eval( form.elements[VAL_GetShadowFieldName(fieldRef.name)] )) {
		if ( VAL_IsBlankNumber ( form, fieldRef.name ) ) {			
			if (requiredFlag == true) {				
				VAL_AppendRequired ( fieldLabel, fieldRef );
				retVal = false;
			}
		} else {
			if (limit == null ) {
				retVal = VAL_ValidateNumberFormat( form, fieldRef, numberType, fieldLabel, numberFormat, message);
			}
			else {
				retVal = VAL_ValidateNumberLimit( form, fieldRef, numberType, fieldLabel, numberFormat, limit, message);
			}
		}
	}
	
	return retVal;
	

}
 
// ------------------------------------------------------------------------ //
// turns a date string into a date value.  Assumes that the input is valid

function VAL_CurrencyStringToCurrencyValue (
      currencyString, 
      numberFormat
      )
{
  var currencyValue = "";
	var groupingSeparator = numberFormat.charAt(0);
	var decimalSeparator = numberFormat.charAt(1);	
	
  if ( currencyString != "" )
  {
  
  	//  If the number has the letters 't' or 'd' convert them to our invalid character letters
  	//  (y,z).  Otherwise t/d will get converted to ,/. and possibly make the number valid.
    currencyValue = VAL_searchAndReplace( currencyString, 't', 'y' );
	  currencyValue = VAL_searchAndReplace( currencyValue, 'd', 'z' );

		//  Need to convert the current number separators to 2 distinct separators not used by any 
		//  number format.  Otherwise a format of ###.###,##  would convert to ###.###.## incorrectly.
		currencyValue = VAL_searchAndReplace( currencyValue, groupingSeparator.charAt(0), 't' );
		currencyValue = VAL_searchAndReplace( currencyValue, decimalSeparator.charAt(0), 'd' );

		//  If the number has any ,s or .s convert them to something invalid.  Otherwise,
		//  if the number format is supposed to be ###.###,## a number like 80.00 is not 
		//  caught as invalid.
		currencyValue = VAL_searchAndReplace( currencyValue, '.', 'z' );
		currencyValue = VAL_searchAndReplace( currencyValue, ',', 'y' );

		//  Finally convert t/d to our internal separators ,/.
		currencyValue = VAL_searchAndReplace( currencyValue, 'd', VAL_decimalDelim.charAt(0) );
		currencyValue = VAL_searchAndReplace( currencyValue, 't', VAL_thousandDelim.charAt(0) );
  }
  
  return currencyValue;
}

//copied from javascript.internet.com/forms/currency-format.html
//removed $ from original script

function formatCurrency(num) {
	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num))
	num = "0";
	sign = (num == (num = Math.abs(num)));
	num = Math.floor(num*100+0.50000000001);
	cents = num%100;
	num = Math.floor(num/100).toString();
	if(cents<10)
	cents = "0" + cents;
	for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
	num = num.substring(0,num.length-(4*i+3))+','+
	num.substring(num.length-(4*i+3));
	return (((sign)?'':'-') + num + '.' + cents);
}

function VAL_CurrencyValueToCurrencyString(
	currencyValue, 
      	numberFormat
      	)
{

	// it would return 0.00 if there are illegal characters in 
	// so we need to make sure currencyValue is valid value before using this function


	var currencyString = "";
	var groupingSeparator = numberFormat.charAt(0);
	var decimalSeparator = numberFormat.charAt(1);	
	var currencyStringUS = formatCurrency(currencyValue);
	
	// currencyStringUS is ###,###.## format
	
	currencyString = VAL_searchAndReplace( currencyStringUS, ',', groupingSeparator.charAt(0) );
	currencyString = VAL_searchAndReplace( currencyString, '.', decimalSeparator.charAt(0) );
	return currencyString;
}

function VAL_NumberSetWithoutFormat(
	numberRef // has to be a valid number with US format
      	)
{
	numberRef.value = VAL_searchAndReplace( numberRef.value, ',', '' );
}

