// *** BROWSER VERSION ***
var agt = navigator.userAgent.toLowerCase();
var isIE  = (agt.indexOf("msie") != -1);
var isIE4 = (isIE  && (agt.indexOf("msie 4.") != -1));
var isNav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
           && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
           && (agt.indexOf('webtv')==-1));
var isNav4 = (isNav  && (agt.indexOf("mozilla/4.") != -1));
var isNav6 = (isNav  && (agt.indexOf("netscape6") != -1));


/** ***************************************************************************
Function   	limitToNumber
Purpose  	Limits input to numeric elements (and designated exceptions).
@param		evt: event from onKeyPress event
@param     	exceptions (optional): string of non-numeric exceptions allowed
				e.g. to allow decimal, comma, and negative sign, you would pass ".,-"  
				in this parameter.

@return		boolean: returns false to reject non-numeric (or authorized exception)

Change History:
Date			Person		Description
=======		=========	================================
27Jun2000	JWoodger  	Initial creation.
24Apr2001	JWoodger  	Enhanced to accept European/French decimal character (comma)
************************************************************************** */
function limitToNumber(evt, exceptions) {
   var charCode = (isNav) ? evt.which : evt.keyCode;
   var i;
   var isException = false;

	//document.formMain.txtCurrEarn.value = charCode; // audit values, unfortunately no tabs/backtabs

	// if exceptions list includes a decimal place and the user preference is French, 
	// then also accept European/French decimal separator (i.e. comma)
	if(lang == 'F' && (exceptions != null) && exceptions.indexOf('.') > -1) {
		exceptions = exceptions + '-';
	}

   // first check if it is non-numeric
   if (((charCode > 31) && (charCode < 48)) ||
      (charCode > 57)) {

      // if exception list provided, check if it is on that list
      if ((exceptions != null) && (exceptions.length > 0)) {
         for(i = 0; i < exceptions.length; i++) {
            if (charCode == exceptions.charCodeAt(i)) {
               isException = true;
               break;
            }
         }
      }

      // reject, if it was not a number or acceptable exception
      if (! isException) 
         return false;
   }
   // don't return true (to avoid Mac bug)
} // end function

/** ***************************************************************************
Function   	flagBadInput
Purpose  	Indicates bad input and set focus to offending field.
@param		obj: form object with bad input
@param     	displayMsg: error message to display
@param     	selectObject (boolean): whether object should also be selected.

@return		None

Change History:
Date			Person		Description
=======		=========	================================
15Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function flagBadInput (obj, displayMsg, selectObj) {
	obj.focus();
	window.alert(displayMsg);
	// default is to also select object
	if(selectObj == true) {
		obj.select();
	}
} // end function

/** ***************************************************************************
Function   	mandErrorMsg
Purpose  	Returns wording (only) for missing input data element.
@param     	displayName: name of column

@return		None

Change History:
Date			Person		Description
=======		=========	================================
18Jul2004	JWoodger  	Initial creation.
************************************************************************** */
function mandErrorMsg (displayName) {
	var msg;
	
	if(lang == "E" || lang == "EN") { 
		msg = displayName + " must be specified";
	} else { 
		msg = displayName + " doit être spécifié";
	}
	
	return(msg);
	
} // end function

/** ***************************************************************************
Function   	validateInteger
Purpose  	Does standard validation for an integer.
@param		obj: form object to check
@param     	displayName: display name of field to display in error message.
@param     	lowerBound:  lower bound for validation ("" means no lower bound checking)
@param     	upperBound:  upper bound for validation ("" means no upper bound checking)
@param     	optional: indicates if Integer is optional (mandatory check is skipped, if true)

@return		Boolean: indicates if validation passed

Change History:
Date			Person		Description
=======		=========	================================
16Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function validateInteger (obj, displayName, lowerBound, upperBound, optional) {
	var intValue;
	var badInput = false;
	var checkLower = (!isNaN(lowerBound) && typeof lowerBound == "number");
	var checkUpper = (!isNaN(upperBound) && typeof upperBound == "number");
	var msg;

	intValue = obj.value;
	
	if (optional && intValue.length == 0) { 
		// no validation to do when optional field has no data
	} else { 
		// need to validate data 
		if(intValue == "") {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " must be specified";
			} else { 
				msg = displayName + " doit être spécifié";
			}
			flagBadInput(obj,msg ,true);
		} else if(isNaN(intValue)) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " must be a number";
			} else { 
				msg = displayName + " doit être un nombre";
			}
			flagBadInput(obj,msg,true);
		} else if(parseInt(intValue) != intValue) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " must be a whole number (no decimals)";
			} else { 
				msg = displayName + " doit être un nombre entier (pas dedécimal)";
			}
			flagBadInput(obj,msg,true);
		} else if(checkUpper && intValue > upperBound) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " cannot exceed " + upperBound;
			} else { 
				msg = displayName + " ne peut dépasser " + upperBound;
			}
			obj.value = upperBound;
			flagBadInput(obj,msg,true);
		} else if(checkLower && intValue < lowerBound) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " cannot be less than " + lowerBound;
			} else { 
				msg = displayName + " ne peut être inférieur à " + lowerBound ;
			}
			flagBadInput(obj,msg,true);
		} else { 
			// input is good but we want to fix values JS considers a number but Java does not (e.g. +2, 3., space 5)
			obj.value = intValue * 1; // effectively puts core number back into field
		} // end if 
	} // end outer if

	if (badInput) {
		return false;
	} else { 
		return true;
	}
} // end function

/** ***************************************************************************
Function   	validateDecimal
Purpose  	Does standard validation for a decimal number.
@param		obj: form object to display
@param     	displayName: display name of field to display in error message.
@param     	lowerBound:  lower bound for validation ("" means no lower bound checking)
@param     	upperBound:  upper bound for validation ("" means no upper bound checking)
@param     	optional: indicates if Integer is optional (mandatory check is skipped, if true)

@return		Boolean: indicates if validation passed

Change History:
Date			Person		Description
=======		=========	================================
16Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function validateDecimal (obj, displayName, numDecimals, lowerBound, upperBound, optional) {
	var decValue;
	var badInput = false;
	var checkLower = (!isNaN(lowerBound)  && typeof lowerBound == "number");
	var checkUpper = (!isNaN(upperBound)  && typeof upperBound == "number");
	var roundNum   = (!isNaN(numDecimals) && typeof numDecimals == "number");
	var hasCommas = false;

	decValue = obj.value;

	if (lang == 'F') {
		if(decValue.indexOf(',') > -1) {
			hasCommas = true;
			// replace commas with decimals, so number checks will work
			decValue = decValue.replace(",",".");
		}
	}

	if (optional && decValue.length == 0) { 
		// no validation to do when optional field has no data
	} else { 
		// need to validate data 
		if(decValue == "") {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " must be specified";
			} else { 
				msg = displayName + " doit être spécifié";
			}
			flagBadInput(obj,msg ,true);
		} else if(isNaN(decValue)) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " must be a number";
			} else { 
				msg = displayName + " doit être un nombre";
			}
			flagBadInput(obj,msg,true);
		} else if(checkUpper && decValue > upperBound) {
			badInput = true;
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " cannot exceed " + upperBound;
			} else { 
				msg = displayName + " ne peut dépasser " + upperBound;
			}
			obj.value = upperBound;
			flagBadInput(obj,msg,true);
		} else if(checkLower && decValue < lowerBound) {
			badInput = true;
			if(lang == "E" || lang == "EN") { 
				msg = displayName + " cannot be less than " + lowerBound;
			} else { 
				msg = displayName + " ne peut être inférieur à " + lowerBound;
			}
			flagBadInput(obj,msg,true);
		} else { 
			// at this stage, input is good: just do any applicable formatting
			if (roundNum) { 
				// round it, then pad appropriate number of places after decimal
				decValue = Math.round(decValue*Math.pow(10,numDecimals)) / Math.pow(10,numDecimals);
				obj.value = padDecimal(decValue,numDecimals); 
			} else { 
				// no rounding wanted
				// fix values JS considers a number but Java does not (e.g. +2, space 5)
				obj.value = decValue * 1; // effectively puts core number back into field
			} // end if
		} // end if 
	} // end outer if

	if (badInput) {
		return false;
	} else { 
		return true;
	}
} // end function


/** ***************************************************************************
Function   	findInSelList
Purpose  	Locate specified value is in selection list (if it is there).
@param		val: value to search for in selection list
@param     	selList: Selection list to search

@return		index: index where found (-1 if not found) 

Change History:
Date			Person		Description
=======		=========	================================
01May2000	JWoodger  	Initial creation.
************************************************************************** */
function findInSelList(val, selList) { 
   // this function determines if the specified value is in the selection list
   var i = 0;
   var index = -1;
	var listLength = selList.length;

   // loop thru and check each list entry
   while ((i < listLength) && (index == -1))  {
      // check if current list entry is equal (ensure string-to-string comparison for Navigator)
      if (selList.options[i].value == (val + "")) {
			index = i;
      }
      i++
   }
   return(index)
} // end function

/** ***************************************************************************
Function   	padDecimal
Purpose  	Takes a decimal number and returns a string that is fully padded to the 
				specified number of decimals. 
@param		num: input number
@param     	requiredDecimals: num decimals required, after padding

@return		String equivalent of number, padded as specified.

Change History:
Date			Person		Description
=======		=========	================================
29Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function padDecimal(num, requiredDecimals) {
	var result;
	var padLen;
	var numDecimals;
	var i = 0;
	num = Math.round(num*Math.pow(10,requiredDecimals)) / Math.pow(10,requiredDecimals);

	if(requiredDecimals == 0) { 
		result = num + ""; // rounding is all that is required
	} else { 
		numDecimals = countDecimals(num)
		// determine how many trailing zeroes need to be added
		padLen = requiredDecimals - numDecimals;

		// format the result
		result = num + "";

		// add decimal place, if none there
		if(numDecimals == 0) { 
			result = result + ".";
		}

		// pad extra zeroes to get required number of decimals
		for(i = 0; i < padLen; i++) {
			result = result + "0";
		}	
	} // end outer-if

	return result;
}

/** ***************************************************************************
Function   	countDecimals
Purpose  	Takes a decimal number and counts how many decimal places it has. 
@param		num: input number
@param     	requiredDecimals: num decimals required, after padding

@return		number of decimals this number has.

Change History:
Date			Person		Description
=======		=========	================================
29Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function countDecimals(num) {
	var numDecimals;
	var decIndex;
	var strNum = num + "";

	decIndex = strNum.indexOf('.');

	if (decIndex == -1) { 
		numDecimals = 0;
	} else { 
		numDecimals = strNum.length - decIndex - 1;
	} 
	return numDecimals;
}


/** ***************************************************************************
Function   	formatNum
Purpose  	Format number, according to formatting details (with commas, decimals). 
@param		num: number to format
@param     	numDecimals: number of decimals for formatted number (default is zero)
@param      sepDecimal: decimal separator (defaults to period)
@param      sepThousands: thousands separator (defaults to comma)

@return		formatted number (as a String)

Change History:
Date			Person		Description
=======		=========	================================
01May2000	JWoodger  	Initial creation.
************************************************************************** */
function formatNum(num, numDecimals, sepDecimal, sepThousands) {
  var decimalStr = "";
  var intStr = "";
 
  if (!numDecimals) numDecimals = 0;   // default is no decimals
  if ((numDecimals < 0) || (Math.round(numDecimals) != numDecimals)) numDecimals = 0;
  if (!sepThousands) sepThousands="";  // default is no thousands separator
  if (!sepDecimal) sepDecimal=".";
 
  num = "" + Math.round(num*Math.pow(10,numDecimals));
 
  if (numDecimals != 0) {
    decimalStr = num.substr(num.length-numDecimals);
    while (decimalStr.length < numDecimals) decimalStr += "0"; 
    decimalStr = sepDecimal + decimalStr;
  }
 
  num = num.substr(0, num.length-numDecimals);
 
  while (num.length > 3) {
    intStr = sepThousands + num.substr(num.length-3) + intStr;
    num = num.substr(0,num.length-3);
  }

  intStr = num + intStr; // add final leading digits
  if (intStr.length == 0) intStr = "0";
  return (intStr + decimalStr);

} // end function


/** ***************************************************************************
Function   	notNull
Purpose  	Converts null values to empty string. 
@param		val: input value

@return		String: "" if val is null, otherwise just returns val.

Change History:
Date			Person		Description
=======		=========	================================
01Aug2000	JWoodger  	Initial creation.
************************************************************************** */
function notNull(val) {

	if(val == "null") { 
		return "";
	} else { 
		return val;
	}
}


/** ***************************************************************************
Function   	cookieCheck
Purpose  	Checks if cookies are enabled on client, giving a message when not enabled. 
@param		None.

@return		None.

Change History:
Date			Person		Description
=======		=========	================================
09Dec2001	JWoodger  	Initial creation.
************************************************************************** */
function cookieCheck() {

	document.cookie = "Y"; // set cookie value
	var testcookie = document.cookie;
	document.cookie = ""; // clears value previously set
	if (testcookie == document.cookie) {
	        alert("You may not have cookies enabled.  Please go into your browser's preferences and enable cookies so that RetirementAdvisor.ca's advanced tools will function correctly");
	}
} // end function

/** ***************************************************************************
Function   	hide
Purpose  	Hides the specified object, using browser-appropriate code (tested on 
				Nav4, IE4, Nav6 and IE5).
				Notes: 
					- Nav4 can only hide text (not data input) object or entire forms 
						(i.e. not data elements within a form).  
					- With tables, it was found that items within a TD element could be 
						hidden or an entire table could be hidden.  It was not possible to hide 
						table rows.
@param		objName: name of object to hide (so far, this object has always been a DIV or SPAN tag)
				// CAREFUL with Nav6: it is case-sensitive to the name passed! (unusual for HTML/JS)

@return		None.

Change History:
Date			Person		Description
=======		=========	================================
28May2002	JWoodger  	Initial creation.
************************************************************************** */
function hide (objName) {
	var theObj;
	if(isNav4) { 
		//document.Prompt1.visibility = 'hidden';
		theObj = eval("document." + objName);
		if(eval("document." + objName) != null) {
			theObj.visibility = 'hidden';
		}
	} else if(isIE4) { 
		//document.form1.all.Prompt1.style.visibility
			//theObj = eval("document." + formName + ".all." + objName + ".style");
			theObj = eval("document.all." + objName + ".style");
		theObj.visibility = 'hidden';
	} else { // IE5+ or Nav6+
		document.getElementById(objName).style.visibility='hidden';
	}
} // end function

/** ***************************************************************************
Function   	show
Purpose  	Shows (make visible) the specified object, using browser-appropriate code.
				It is the inverse of the hide function described in more detail above.
@param		objName: name of object to hide (so far, this object has always been a DIV tag)

@return		None.

Change History:
Date			Person		Description
=======		=========	================================
28May2002	JWoodger  	Initial creation.
************************************************************************** */
function show (objName) {
	if(isNav4) { 
		theObj = eval("document." + objName);
		if(eval("document." + objName) != null) {
			theObj.visibility = 'visible';
		}
	} else if(isIE4) { 
		//theObj = eval("document." + formName + ".all." + objName + ".style");
		theObj = eval("document.all." + objName + ".style");
		theObj.visibility = 'visible';
	} else { // IE5+ or Nav6+
		document.getElementById(objName).style.visibility='visible';
	}
} // end function
