//------------------------------------------------------------------------------------
//JS UTILITY STRING FUNCTIONS: (TO BE USED THROUGHOUT THE APPLICATION - GLOBAL SCOPE):

//	jsIsNumber(astrValue)
//	jsIsInteger(astrValue, ablnAllowNegative, ablnAllowThousands)
//	jsIsZipCode(astrValue)
//	jsIsEmail(astrValue)
//	jsIsDate(astrValue)
//  jsReplace()
//	jsTrim(astrValue)
//	jsLTrim(astrValue)
//	jsRTrim(astrValue)
//	jsRight(astrValue, aintLength)
//	jsLeft(astrValue, aintLength)
//	js2Decimal(astrValue, ablnThousandsSeparator)
//	js4Decimal(astrValue, ablnThousandsSeparator)
//	js2Digit(astrValue)
//	jsGetBrowser()
//	jsValidateDate(aobjInput)
//	jsValidateNumber(aobjInput)

//------------------------------------------------------------------------------------
function jsCStr(astrValue){ 
	return astrValue + "";
}
//------------------------------------------------------------------------------------
function jsCInt(astrValue){ 
	return (astrValue * 1);
}
//------------------------------------------------------------------------------------
function jsCBln(astrValue){ 
	astrValue = jsTrim(astrValue.toLowerCase());
	return (astrValue == "true"?true:false);
}
//------------------------------------------------------------------------------------
function jsIsNumber(astrValue){
	if (astrValue == ""){
		return true;
	}
	
	//Since this is an IsNumber function, we
	//can expect valid numbers to have "." and "," and "-".  Due to
	//the fact that isNaN() returns false when a value has commas,
	//we remove them all prior to the isNaN() check.  However, if they
	//are in the wrong location, then we immediately return false:
	if (astrValue.indexOf(",") != -1){
		//There is an assumption here that the function that called
		//this function trimmed all leading and trailing spaces off
		//of astrValue: (This must be done!)
		
		//Since a possibility of a decimal point has to be taken
		//into consideration, we check for one decimal point, if there
		//are more than one decimal points, then we immediately return
		//false, we only perform this check if we are checking commas,
		//else the isNaN() function handles the decimal point check
		//internally:
		var larrTemp = astrValue.split(".");
		if (larrTemp.length > 2){			
			return false;
		}		
		//If there is only one valid decimal point, then
		//we find the length of the string after the decimal
		//point including the decimal point.  This is then
		//subtracted from the astrValue.length value below:
		var lintTempLen = 0;
		
		if (larrTemp.length == 2){
			var lstrTemp = astrValue.substr(astrValue.indexOf("."));
			lintTempLen = lstrTemp.length;			
		}
		var lstrValidate = astrValue.substr(0,astrValue.length - lintTempLen);
		
		//Next, we perform basically the same check for the negative symbol:
		larrTemp = astrValue.split("-"); 
		if (larrTemp.length > 2){	
			return false;
		}	
		
		if (larrTemp.length == 2){
			//Make sure the "-" is the first character:
			if (astrValue.charAt(0) != "-"){
				return false;
			}
			else {
				//Remove the "-" from the string to be validated:
				lstrValidate = lstrValidate.substr(1);
			}		
		}
				
		switch (lstrValidate.length){
			//1,000 - 10,000 - 100,000
			case 5: case 6: case 7:  //1,000.00
				//Check to make sure there is only one comma:
				larrTemp = lstrValidate.split(",");
				if (larrTemp.length > 2){
					return false;
				}
				if (lstrValidate.charAt(lstrValidate.length - 4) != ","){
					return false;
				}
				break;			
			//1,000,000 - 10,000,000 - 100,000,000
			case 9: case 10: case 11:
				//Check to make sure there are only two commas:
				larrTemp = lstrValidate.split(",");
				if (larrTemp.length > 3){
					return false;
				}
				if (lstrValidate.charAt(lstrValidate.length - 4) != "," || 
						lstrValidate.charAt(lstrValidate.length - 8) != ","){
					return false;
				}
				break;
			//Any other length and the comma is in the wrong location,
			//so we return false:
			default:
				return false;	
		}
	}
	//Remove commas if there are any, since we checked for proper location
	//above and isNaN() will return false if the string has any commas:
	astrValue = astrValue.split(",").join("");	
	
	//Check to see if its a valid number:
	if (isNaN(astrValue)){
		return false;
	}
	//If we made it here, then its a number so we return true:
	return true;
}
//------------------------------------------------------------------------------------
function jsIsInteger(astrValue, ablnAllowNegative, ablnAllowThousands){
	if (astrValue == ""){
		return true;
	}
	
	//Since this is a function for checking for integers, the
	//isNaN() function does most of the work for us, however,
	//the isNaN() function allows "." and "-" so we must 
	//check for the presence of these two symbols.  If either
	//exist in the string, then we return false:
	if (astrValue.indexOf(".") != -1){
		return false;
	}
	if (ablnAllowNegative == false){
		if (astrValue.indexOf("-") != -1){
			return false;
		}	
	}		
	
	if (ablnAllowThousands == false){
		if (astrValue.indexOf(",") != -1){
			return false;
		}	
	}
	else {
		//Strip out thousands "," incase they put them in because
		//isNaN will return true if they are there:
		astrValue = jsReplace(astrValue, ",", "");
	}		
	
	//Check for e or E since isNaN allows them:
	if (astrValue.indexOf("e") != -1){
		return false;
	}
	if (astrValue.indexOf("E") != -1){
		return false;
	}
	
	//Finish the validation:
	if (isNaN(astrValue)){
		return false;
	}
	//If we made it here, then its a integer so we return true:
	return true;
}
//------------------------------------------------------------------------------------
function jsIsZipCode(astrValue){	
	if (astrValue == ""){
		return true;
	}
	
	if (astrValue.length != 5 && astrValue.length != 10){
		return false;
	}
	
	if (astrValue.length == 5){				
		return jsIsInteger(astrValue, false);	
	}
	else {		
		//Make sure the dash is in the right place:
		if (astrValue.indexOf("-") != 5){
			return false;
		}
		//If its in the right place, then we break
		//the string up into two parts and test them:
		var lstrParts = astrValue.split("-");
		if (jsIsInteger(lstrParts[0], false) == false){
			return false;
		}
		if (jsIsInteger(lstrParts[1], false) == false){
			return false;
		}
		// If we get this far, then it is valid:
		return true;			
	}				
}	
//------------------------------------------------------------------------------------
function jsIsEmail(astrValue){
	if (astrValue == ""){
		return true;
	}
	
    //Check for an @ symbol:    
    if (astrValue.indexOf("@") == -1){
        return false;
    }
    //Check for more than 1 @ symbol:    
    if (astrValue.indexOf("@") != astrValue.lastIndexOf("@")){
        return false;
    }
    
    //Check for an . symbol after @ symbol:    
    if (astrValue.lastIndexOf(".") < astrValue.indexOf("@")){
        return false;
    }
    
    //Check for invalid symbols:
    if (astrValue.indexOf("*") != -1){
        return false;
    }
    if (astrValue.indexOf("%") != -1){
        return false;
    }
    if (astrValue.indexOf(",") != -1){
        return false;
    }
    if (astrValue.indexOf(";") != -1){
        return false;
    }
    if (astrValue.indexOf("'") != -1){
        return false;
    }
    if (astrValue.indexOf("\"") != -1){
        return false;
    }
    if (astrValue.indexOf(":") != -1){
        return false;
    }
    return true;
}
//------------------------------------------------------------------------------------
function jsIsDate(astrValue){
	if (astrValue == ""){
		return true;
	}
	//Valid dates formats:
	//1.  mm(m)/dd(d)/yy(yyyy) 
	//2.  mm(m)-dd(d)-yy(yyyy) 
	
	//First we make sure the date can validate based
	//on javascript's built in date object:
	var ldatObject = new Date(astrValue);
	//If the date object does not validate to a number, then
	//the string passed is not a valid date:
	if (isNaN(ldatObject)){
		return false;
	}
	//Since, the date string passed the first validation.  We next
	//check to make sure the string is in on of the two formats listed
	//at the top of this function:
	var larrDashes = astrValue.split("-");
	var larrSlashes = astrValue.split("/");
	var lstrSeperator = "";
	var lstrMonth = "";
	var lstrDay = "";
	var lstrYear = "";
	
	//Ensure that the user did not enter mixed seperator symbols:
	if (larrDashes.length - 1 == 1 && larrSlashes.length - 1 == 1){
		return false;
	}
		
	//Dashes:
	if (larrDashes.length - 1 == 2){
		//Populate the month, day, and year variables:	
		lstrMonth = "00" + larrDashes[0];
		lstrDay = "00" + larrDashes[1];
		lstrYear = larrDashes[2];
	}
	//Slashes:
	else {
		//Populate the month, day, and year variables:	
		lstrMonth = "00" + larrSlashes[0];
		lstrDay = "00" + larrSlashes[1];
		lstrYear = larrSlashes[2];		
	}
		
	//Validate the month portion of the date:
	lstrMonth = lstrMonth.substr(lstrMonth.length - 2);
	if (lstrMonth < "01" || lstrMonth > "12"){
		return false;
	}	
	
	//Validate the year portion of the date:
	if (lstrYear.length != 2 && lstrYear.length != 4){
		return false;
	}
	//Check for invalid characters in the year string:
	for (i = 0; i < lstrYear.length; i++){
		if (lstrYear.charAt(i) < "0" || lstrYear.charAt(i) > "9"){			
			return false;
		}
	}
		
	//Validate the day portion of the date:
	lstrDay = lstrDay.substr(lstrDay.length - 2);
	switch (lstrMonth){
		case "01": case "03": case "05": case "07": 
		case "08": case "10": case "12":
			if (lstrDay < "01" || lstrDay > "31"){				
				return false;
			}	
			break;
		case "04": case "06": case "09": case "11": 
			if (lstrDay < "01" || lstrDay > "30"){					
				return false;
			}	
			break;
		case "02":
			//First, we must determine if we are in a leap
			//year or not:
			var lblnLeap = false;
			
			//If lstrYear is 2 Digits, then we convert it to 
			//the 4 year string:
			if (lstrYear.length == 2){
				if (lstrYear >= "00" && lstrYear <= "80"){
					lstrYear = "20" + lstrYear;	
				}
				else {
					lstrYear = "19" + lstrYear;
				}
			}
			var lintYear = lstrYear * 1;
						
			if ((lintYear % 4) == 0){
				if ((lintYear % 100) == 0){	
					if ((lintYear % 400) == 0){	
						lblnLeap = true;
					}
				}
				else {
					lblnLeap = true;
				}			
			}
			
			if (lblnLeap){				
				//If we are in a leap year:
				if (lstrDay < "01" || lstrDay > "29"){					
					return false;
				}		
			}
			else {					
				//If we are not in a leap year:
				if (lstrDay < "01" || lstrDay > "28"){					
					return false;
				}	
			}			
			break;
	}			
	
	//If we make it to hear, then it is a valid date:
	return true;		
}
//------------------------------------------------------------------------------------
function jsIsEmpty(astrValue){	
	if (astrValue == null || astrValue == ""){		
		return true;
	}
	else {
		return false;
	}	
}
//------------------------------------------------------------------------------------
function jsReplace(astrValue, astrRemove, astrInsert){
	return astrValue.split(astrRemove).join(astrInsert);	
}
//------------------------------------------------------------------------------------
function jsTrim(astrValue){
	return jsLTrim(jsRTrim(astrValue));	
}
//------------------------------------------------------------------------------------
function jsLTrim(astrValue){	
	var lintSpace = astrValue.search( /^\s*(\S.*)/ );
	return ( ( lintSpace == -1 ) ? "" : RegExp.$1 );
}
//------------------------------------------------------------------------------------
function jsRTrim(astrValue){	
	var lintSpace = astrValue.search( /\s+$/ );
	return ( ( lintSpace == -1 ) ? astrValue : astrValue.substr( 0, lintSpace ) );
} 
//------------------------------------------------------------------------------------
function jsRight(astrValue, aintLength){
	return astrValue.substr(astrValue.length - aintLength);
}
//------------------------------------------------------------------------------------
function jsLeft(astrValue, aintLength){
	return astrValue.substr(0, aintLength);
}
//------------------------------------------------------------------------------------
function jsFormatNumber(astrValue, ablnThousandsSeparator, ablnShowDecimals){	
	var tmpValue = astrValue * 100;
	
	if ( tmpValue.toString( ) == "NaN" )  return astrValue;
	var intSign = 1;
	if ( tmpValue < 0 )   {
		intSign = -1;
		tmpValue = tmpValue * -1;
	}
	tmpValue = Math.round( tmpValue ).toString( );
	if ( tmpValue.length == 1 )        tmpValue = "00" + tmpValue;
	else if ( tmpValue.length == 2 )   tmpValue = "0" + tmpValue;
	tmpValue = tmpValue.substr( 0, tmpValue.length - 2 ) + "." + tmpValue.substr( tmpValue.length - 2, 2 )
	if ( ablnThousandsSeparator == true )   {
		var intSearch = tmpValue.search( /[^-]...\./ );
		do   {
			if ( intSearch >= 0 )
				tmpValue = tmpValue.substr( 0, intSearch + 1 ) + "," + tmpValue.substr( intSearch + 1 );
			intSearch = tmpValue.search( /[^,-]...,/ );
		}  while ( intSearch >= 0 );
	}
	if ( intSign == -1 )   tmpValue = "-" + tmpValue;
	
	if (ablnShowDecimals){
		return tmpValue;
	}
	else {
		return tmpValue.substr(0, tmpValue.length - 3);	
	}
}
//------------------------------------------------------------------------------------
function js2Digit(astrValue){ 
	var lstrValue = astrValue.toString();
	if (lstrValue.length == 1)   lstrValue = "0" + lstrValue;
	return lstrValue;
}
//------------------------------------------------------------------------------------
function js2Decimal(astrValue, ablnThousandsSeparator){
	var tmpValue = astrValue * 100;
	if ( tmpValue.toString( ) == "NaN" )  return astrValue;
	var intSign = 1;
	if ( tmpValue < 0 )   {
		intSign = -1;
		tmpValue = tmpValue * -1;
	}
	tmpValue = Math.round( tmpValue ).toString( );
	if ( tmpValue.length == 1 )        tmpValue = "00" + tmpValue;
	else if ( tmpValue.length == 2 )   tmpValue = "0" + tmpValue;
	tmpValue = tmpValue.substr( 0, tmpValue.length - 2 ) + "." + tmpValue.substr( tmpValue.length - 2, 2 )
	if ( ablnThousandsSeparator == true )   {
		var intSearch = tmpValue.search( /[^-]...\./ );
		do   {
			if ( intSearch >= 0 )
				tmpValue = tmpValue.substr( 0, intSearch + 1 ) + "," + tmpValue.substr( intSearch + 1 );
			intSearch = tmpValue.search( /[^,-]...,/ );
		}  while ( intSearch >= 0 );
	}
	if ( intSign == -1 )   tmpValue = "-" + tmpValue;
	return tmpValue;
}
//------------------------------------------------------------------------------------
function js4Decimal(astrValue, ablnThousandsSeparator){
	var tmpValue = astrValue * 10000;
	if ( tmpValue.toString( ) == "NaN" )  return astrValue;
	var intSign = 1;
	if ( tmpValue < 0 )   {
		intSign = -1;
		tmpValue = tmpValue * -1;
	}
	tmpValue = Math.round( tmpValue ).toString( );
	if ( tmpValue.length == 1 )        tmpValue = "0000" + tmpValue;
	else if ( tmpValue.length == 2 )   tmpValue = "000" + tmpValue;
	else if ( tmpValue.length == 3 )   tmpValue = "00" + tmpValue;
	else if ( tmpValue.length == 4 )   tmpValue = "0" + tmpValue;
	tmpValue = tmpValue.substr( 0, tmpValue.length - 4 ) + "." + tmpValue.substr( tmpValue.length - 4, 4 )
	if ( ablnThousandsSeparator == true )   {
		var intSearch = tmpValue.search( /[^-]...\./ );
		do   {
			if ( intSearch >= 0 )
				tmpValue = tmpValue.substr( 0, intSearch + 1 ) + "," + tmpValue.substr( intSearch + 1 );
			intSearch = tmpValue.search( /[^,-]...,/ );
		}  while ( intSearch >= 0 );
	}
	if ( intSign == -1 )   tmpValue = "-" + tmpValue;
	return tmpValue;
}	
//------------------------------------------------------------------------------------
function jsGetBrowser(){
	// need the platform, looks like "MAC" or "WIN"
	var lstrPlatform = window.navigator.platform.substr( 0, 3 ).toUpperCase( );

	// need the browser type, looks like "IE" or "NN" or "??"
	var lstrBrowserType = window.navigator.appName;
	if ( lstrBrowserType == "Microsoft Internet Explorer" )   
		lstrBrowserType = "IE";
	else if ( lstrBrowserType == "Netscape" )   
		lstrBrowserType = "NN";
	else
		lstrBrowserType = "??";

	// need the browser version.  For IE, have to pull it out of the middle
	var lintIndex
	if ( lstrBrowserType = "IE" )   {
		lintIndex = window.navigator.appVersion.indexOf( "MSIE" );
		var lstrVersion = window.navigator.appVersion.substr( lintIndex * 1 + 5, 1 )
	}
	else
		lstrVersion = window.navigator.appVersion.substr( 0, 1 );

	// the result looks like WIN_IE4 or MAC_IE5
	return lstrPlatform + "_" + lstrBrowserType + lstrVersion;

}
//------------------------------------------------------------------------------------
function jsValidateDate(aobjInput){
	var lstrValue = jsTrim(aobjInput.value);
	if (jsIsDate(lstrValue) == false){
		aobjInput.focus();
		alert("Please enter a valid date.");
	}
}
//------------------------------------------------------------------------------------
function jsValidateNumber(aobjInput){
	var lstrValue = jsTrim(aobjInput.value);
	if (jsIsNumber(lstrValue) == false){
		aobjInput.focus();
		alert("Please enter a valid number.");
	}
}
//------------------------------------------------------------------------------------

// ***************************************************************************************************************
// DEBUGGING FUNCTIONS

// debugging function - store milliseconds since last time this function was called
var mstrCPUString, mintCPUTime = 0, mintCPUTime1 = 0;
function jsCPU( astrText )
{
	var tmp1 = new Date( );
	var tmp2 = Date.parse( tmp1 ) + tmp1.getMilliseconds( );
	if ( mintCPUTime == 0 )   {
		mstrCPUString = "\t\t" + astrText + "\n";
		mintCPUTime1 = tmp2;
	}
	else
		mstrCPUString += ( tmp2 - mintCPUTime ) + "\t" + ( tmp2 - mintCPUTime1 ) + "\t" + astrText + "\n";
	mintCPUTime = tmp2;
}

// debugging function - show dump of time checkpoints
function jsShowCPU( )
{
	alert( mstrCPUString );
	mintCPUTime = 0;
	mintCPUTime1 = 0;
}

// shows a message box with the current function call-stack
function jsShowFunctionCallStack( atxtTarget )
{
	var i;
	var lstrMessage = "";
	var lobjFunction = jsShowFunctionCallStack.caller;
	do   {
		var lstrFunction = lobjFunction.toString( );
		var lintParen = lstrFunction.indexOf( "(" )
		if ( lintParen < 0 )   lintParen = 50;
		lstrMessage += lstrFunction.substr( 9, lintParen - 9 ) + "( ";
		var larrArguments = lobjFunction.arguments;
		var lintCount = larrArguments.length;
		for ( i = 0; i < lintCount; i++ )   {
			lstrMessage += ( ( i > 0 ) ? ", " : "" ) + larrArguments[ i ];
		}
		lstrMessage += " )\n";
		lobjFunction = lobjFunction.caller;
	}   while ( lobjFunction != null );
	if ( atxtTarget == null )
		alert( lstrMessage );
	else
		atxtTarget.value = lstrMessage;
}