//********************************************************************************************
//the following constants coorespond with server side constants in constants.vbs- keep in sync
//********************************************************************************************

var NOT_INITIALIZED = -1;
var SUCCESS = 0;

var BROWSER_IE = "IE";
var BROWSER_GECKO = "GECKO";
var BROWSER_KONQUEROR = "KONQUEROR";
var BROWSER_NETSCAPE = "NETSCAPE";
var BROWSER_OPERA = "OPERA";
var BROWSER_OTHER = "OTHER";

var OS_OTHER = "OTHER";
var OS_WIN95 = "WIN95";
var OS_WINNT = "WINNT";
var OS_WIN98 = "WIN98";
var OS_WINME = "WINME";
var OS_WIN2K = "WIN2K";
var OS_WINXP = "WINXP";
var OS_LINUX = "LINUX";
var OS_MAC = "MAC";

var MAX_URL_LENGTH = 1900;
var NULL_DB_DATE = new Date("12/31/1969 7:00:00 PM");

var MIN_CPP_DATE = new Date('1/1/1970 12:00:00 AM');
var MAX_CPP_DATE = new Date('1/19/2038 3:14:07 AM');

//********************************************************************************************
//end constants
//********************************************************************************************

function BrowserDetector() {
	this.UserAgent = fw_config_UserAgent;
	this.UserAgentRaw = fw_config_UserAgentRaw;
	this.OS = fw_config_OS;
	this.IsValid = fw_config_IsValid;
	this.SP = fw_config_SP;
}

var Browser = new BrowserDetector();

function IsEmpty(oObj) {
	return (oObj == null || oObj == "");
}

function IfEmpty(oObj, oAltObj) {
	return IsEmpty(oObj) ? oAltObj : oObj;
}

function GetBoolean(oObj) {
	if (!oObj) {
		return false;
	}

	switch (oObj.toString().toLowerCase()) {
		case "yes" :
		case "true" :
		case "1" :
			return true;
	}
	return false;
}

String.prototype.GetBoolean = function() {
	return GetBoolean(this);
}

function BoolToInt(bBool) {
	return bBool ? 1 : 0;
}

function GetInt(oObj) {
	var nNum = new Number(oObj);
	if (nNum.valueOf() != NaN) {
		return nNum.valueOf();
	} else {
		return 0;
	}
}

//Certain browsers dont support encodeURIComponent()- use escape() instead
if (typeof(encodeURIComponent) == "undefined") {
	var encodeURIComponent = function(sStr) {
		return escape(sStr);
	}
	
	var decodeURIComponent = function(sStr) {
		return unescape(sStr);
	}
}

//replaces special characters in strings with standard escape characters
function UrlEncode(sStr){
	if (typeof sStr == "undefined") {
		return "";
	}
	
	var sOutput = encodeURIComponent(sStr);
	
	//Workaround for discrepancy between Server.UrlEncode and JavaScript encodeURIComponent() function
	//encodes characters missed by encodeURIComponent()
	//important for cookie functions
	var arrChars = "! ' ( ) * - . _ /".split(" ");
	var arrEncoded = "%21 %27 %28 %29 %2A %2D %2E %5F %2F".split(" ");
	var oRe;
	
	for (var i=0; i<arrChars.length; i++) {
		oRe = new RegExp("\\" + arrChars[i], "gi");
		sOutput = sOutput.replace(oRe, arrEncoded[i]);
	}
	
	return sOutput;
}

String.prototype.urlEncode = function () {
	return UrlEncode(this);
}

function UrlDecode(sStr){
	if (typeof(sStr) == "undefined") {
		return '';
	}
	sStr = sStr.replace(/\+/gi, " ");
	
	try {
		return decodeURIComponent(sStr);
	} catch (e) {
		return unescape(sStr);
	}
}

String.prototype.urlDecode = function () {
	return UrlDecode(this);
}

function HTMLEncode(sStr) {
	if (!sStr) {
		return '';
	}
	if (sStr != '') {
		sStr = sStr.replace(/\&/gi, '&amp;');
		sStr = sStr.replace(/\"/gi, '&quot;');
		sStr = sStr.replace(/\</gi, '&lt;');
		sStr = sStr.replace(/\>/gi, '&gt;');
		sStr = sStr.replace(/\n/gi, '<br>');
	}
	return sStr;
}

String.prototype.HTMLEncode = function () {
	return HTMLEncode(this);
}

function HTMLDecode(sStr) {
	if (!sStr) {
		return '';
	}
	if (sStr != '') {
		sStr = sStr.replace(/\&amp\;/gi, '&');
		sStr = sStr.replace(/\&quot\;/gi, '"');
		sStr = sStr.replace(/\&lt\;/gi, '<');
		sStr = sStr.replace(/\&gt\;/gi, '>');
		sStr = sStr.replace(/\<br\>/gi, '\n');
	}
	return sStr;
}

String.prototype.HTMLDecode = function () {
	return HTMLDecode(this);
}

//simple search and replace function for strings
function Replace(sStr, sFind, sReplace){
	var sOutput = sStr;
	var nStart, nEnd;
	while (sOutput.indexOf(sFind) != -1){
		nStart = sOutput.indexOf(sFind);
		nEnd = sFind.length + nStart;
		sOutput = sOutput.substr(0, (nStart)) + sReplace + sOutput.substr(nEnd, sOutput.length);
	}
	return sOutput;
}

String.prototype.replaceAll = function (sFind, sReplace) {
	return Replace(this, sFind, sReplace);
}

function Trim(sStr) {
    var sOut = sStr;
	if (sOut != null) {
		//get rid of leading spaces 
	    while (sOut.substring(0,1) == ' ') {
	        sOut = sOut.substring(1, sOut.length);
		}
	
	    //get rid of trailing spaces 
	    while (sOut.substring(sOut.length-1, sOut.length) == ' ') {
	        sOut = sOut.substring(0, sOut.length-1);
		}
	} else {
		sOut = "";
	}

   	return sOut.toString();
	
	//Regular expressions dont work with empty strings on mac OS9
	//return Rtrim(Ltrim(sStr));
}

String.prototype.trim = function () {
	return Trim(this);
}

function TrimLineBreaks(sStr) {
	var sChar = sStr.substring(0,1);
	
	while (sChar == ' ' || sChar == '\n' || sChar == '\r' || sChar == '\f') {
		sStr = sStr.substring(1, sStr.length);
		sChar = sStr.substring(0,1);
	}
	
	sChar = sStr.substring(sStr.length-1, sStr.length);
	
	while (sChar == ' ' || sChar == '\n' || sChar == '\r' || sChar == '\f') {
		sStr = sStr.substring(0, sStr.length-1);
		sChar = sStr.substring(sStr.length-1, sStr.length);
	}
	
	return sStr;
	
	//older browsers dont support regular expressions
	//return sStr.replace(/^\s+/gim, '').replace(/\s+$/gim, '');
}

String.prototype.trimLineBreaks = function () {
	return TrimLineBreaks(this);
}

function Ltrim(sStr){
	while (sStr.substring(0,1) == ' ') {
		sStr = sStr.substring(1, sStr.length);
	}
	
	return sStr;
	
	//older browsers dont support regular expressions
	//return sStr.replace(/[\s]*$/gi, '');
}

String.prototype.ltrim = function () {
	return Ltrim(this);
}

function Rtrim(sStr){
	while (sStr.substring(sStr.length-1, sStr.length) == ' ') {
		sStr = sStr.substring(0, sStr.length-1);
	}
	
	return sStr;
	
	//older browsers dont support regular expressions
	//return sStr.replace(/^[\s]*/gi, '');
}

String.prototype.rtrim = function () {
	return Rtrim(this);
}

//generic method to get the value of a form field
function GetFormValue(oObj) {
	if (oObj[0] && oObj[0].type == 'radio') {
		return GetRadioValue(oObj);
	} else if (oObj.type == 'radio') {
		return GetRadioValue(oObj.form.elements[oObj.name]);
	} else if (oObj.tagName == 'SELECT') {
		return GetSelectValue(oObj);
	} else if (oObj.type == 'checkbox') {
		return oObj.checked ? oObj.value : '';
	} else {
		return oObj.value;
	}
}

//generic method to set the value of a form field
function SetFormValue(oObj, sValue) {
	if (oObj[0] && oObj[0].type == 'radio') {
		SetRadioValue(oObj, sValue);
	} else if (oObj.type == 'radio') {
		SetRadioValue(oObj.form.elements[oObj.name], sValue);
	} else if (oObj.tagName == 'SELECT') {
		SetSelectValue(oObj, sValue);
	} else {
		oObj.value = sValue;
	}
}

//returns the radio array's value 
function GetRadioValue(oRadio){
	if (oRadio){
		if (oRadio.length){
			for (var i=0; i<oRadio.length; i++) {
				if (oRadio[i].checked){
					return oRadio[i].value;
				}
			}
		} else {
			if (oRadio.checked){
				return oRadio.value;
			}
		}
	}
	return "";
}

function SetRadioValue(oRadio, sValue){
	if (oRadio){
		if (oRadio.length){
			for (var i=0; i<oRadio.length; i++) {
				if (oRadio[i].value == sValue){
					oRadio[i].checked = true;
				}
			}
		} else {
			if (oRadio.value == sValue){
				oRadio.checked = true;
			}
		}
	}
}

function GetSelectValue(oSelect) {
	if (oSelect) {
		if (oSelect.multiple) {
			var arr = new Array();
			for (var i=0; i<oSelect.options.length; i++) {
				if (oSelect.options[i].selected) {
					arr[arr.length] = oSelect.options[i].value;
				}
			}
			
			return arr.join(",");
		} else {
			if (oSelect.selectedIndex > -1) {
				return oSelect.options[oSelect.selectedIndex].value;
			}
		}
	}
	return "";
}

function GetSelectText(oSelect) {
	if (oSelect) {
		if (oSelect.multiple) {
			var arr = new Array();
			for (var i=0; i<oSelect.options.length; i++) {
				if (oSelect.options[i].selected) {
					arr[arr.length] = oSelect.options[i].text;
				}
			}
			
			return arr.join(",");
		} else {
			if (oSelect.selectedIndex > -1) {
				return oSelect.options[oSelect.selectedIndex].text;
			}
		}
	}
	return "";
}

function GetRadioLabelText(oRadio) {
	var i;
	var sSelectedID = null;
	if (oRadio){
		if (oRadio.length){
			for (i=0; i<oRadio.length; i++) {
				if (oRadio[i].checked){
					sSelectedID = oRadio[i].id;
				}
			}
		} else {
			if (oRadio.checked){
				sSelectedID = oRadio.id;
			}
		}
	}
	
	if (sSelectedID == null) {
		return "";
	} else {
		var arrLabels = document.getElementsByTagName("LABEL");
		for (i=0; i<arrLabels.length; i++) {
			if (arrLabels[i].htmlFor == sSelectedID) {
				return arrLabels[i].innerHTML;
			}
		}
		
		return "";
	}
}

function SetSelectValue(oSelect, sValue, bRemoveOthers) {
	if (!bRemoveOthers && oSelect.multiple) {
		oSelect.selectedIndex = -1;
	}
	if (oSelect) {
		for (var i=0; i<oSelect.options.length; i++) {
			if (oSelect.options[i].value == sValue) {
				oSelect.options[i].selected = true;
			}
		}
	}
	return null;
}

function BuildFormQueryString(frm) {
	var arrValues = new Array();
	var sValue;

	for (var i=0; i<frm.elements.length; i++) {
		if (!frm.elements[i].disabled) {
			sValue = UrlEncode(frm.elements[i].name) + '=' + UrlEncode(GetFormValue(frm.elements[i]))
			if (arrValues.indexOf(sValue) == -1) {
				arrValues[arrValues.length] = sValue;
			}
		}
	}
	
	return arrValues.join('&');
}

//takes any number of window names as arguments and closes them
function CleanWindows(){
	if (arguments.length > 0){
		for (var i=0; i<arguments.length; i++){
			if (eval(arguments[i])){
				eval(arguments[i]).close();
			}
		}
	}
}

//returns the first day of the given month and year, or the last day, if bLastDay is true
function GetDateFromMonth(nMonth, nYear, bLastDay) {
		var dDate = new Date(nMonth + "/1/" + nYear);
		if (bLastDay) {
			dDate.setMonth(dDate.getMonth() + 1);
			dDate.setDate(dDate.getDate() - 1);
		}
		
		return dDate;
}

//equivelent of ASP's Request.QueryString()
function GetQueryString(sKey, oDoc) {
	if (oDoc) {
		var sStr = oDoc.location.search;
	} else {
		var sStr = document.location.search;
	}
	
	//return an empty string if there is no qs
	if (sStr.indexOf('=') == -1){
		return '';
	//trim the opening '?'
	} else {
		var sStr = sStr.slice(1, sStr.length);
	}
	
	var arrValues = sStr.split('&');

	for (var i=0; i<arrValues.length; i++) {
		if (sKey.toLowerCase() == GetKeyFromPair(arrValues[i]).toLowerCase()) {
			return GetValueFromPair(arrValues[i]);
		}
	}
	return '';
}

function GetValueFromPair(sPair) {
	if (sPair.indexOf('=') == -1) {
		return '';
	}
	return UrlDecode(sPair.slice(sPair.indexOf('=')+1, sPair.length));
}

function GetKeyFromPair(sPair) {
	if (sPair.indexOf('=') == -1) {
		return '';
	}
	return sPair.slice(0, sPair.indexOf('='));
}

//takes a url, and inserts or replaces a key/value pair
//optionally removes any hash parameters
function AddValueToUrl(sUrl, sKey, sValue, bRemoveHash) {
	var sQs = "";
	var sUrlPath = "";
	var nPosQuestionMark = sUrl.toString().indexOf("?");
	var nPosHashSign = sUrl.toString().indexOf('#');
	var sHashRef = '';
	
	sUrl = sUrl.toString();

	if (sValue.length == 0) {
		var oRe = new RegExp(sKey + '\\=[\\&|$]');
		if (sUrl.search(oRe) != -1) {
			sUrl = sUrl.replace(oRe, '');
			return sUrl;
		} else {
			return sUrl;
		}
	}
	
	var bIsFullUrl = sUrl.indexOf("http") == 0;

	//if there is an anchor ref (#), temporarily remove it and send it to the end of the string
	if (nPosHashSign != -1) {
		if (!bRemoveHash) {
			sHashRef = sUrl.slice(nPosHashSign, sUrl.length);
		}
		sUrl = sUrl.slice(0, nPosHashSign);
	}
	
	
	//if this is a full URL and there is no querystring, simply add it
	if (bIsFullUrl && nPosQuestionMark == -1) {
		return sUrl + "?" + sKey + "=" + UrlEncode(sValue);
	//if it is a full url, and the question mark is last, add it without the question mark
	} else if (bIsFullUrl && nPosQuestionMark == sUrl.length-1) {
		return sUrl + sKey + "=" + UrlEncode(sValue);
	//if this is a full querystring, starting with the "?", remove it
	} else if (bIsFullUrl && nPosQuestionMark == 0) {
		sUrl = sUrl.substr(1);
	//an empty string is a special case- simply return the new key value pair
	} else if (sUrl == "" || sUrl == "?") {
		return sUrl + sKey + "=" + UrlEncode(sValue);
	}
	
	//now we can assume we have either a raw querystring or a full URL with a querystring
	sQs = sUrl.toString().slice(nPosQuestionMark+1);

	//if this is a url, extract the path from the full URL
	if (nPosQuestionMark != -1) {
		sUrlPath = sUrl.toString().slice(0, nPosQuestionMark);
	}

	sQs = sUrl.toString().slice(nPosQuestionMark+1);
	sUrlPath = sUrl.toString().slice(0, nPosQuestionMark);
	
	//search through each pair and make sure the key doesnt already exist
	var arrPairs = sQs.split('&');
	var nFoundIndex = arrPairs.length; //if not found, append to the end
	
	for (var i=0; i<arrPairs.length; i++) {
		if (GetKeyFromPair(arrPairs[i]).toLowerCase() == sKey.toLowerCase()) {
			nFoundIndex = i;
			break;
		}
	}
	
	arrPairs[nFoundIndex] = sKey + '=' + UrlEncode(sValue);
	
	if (nPosQuestionMark == -1) {
		return arrPairs.join('&') + sHashRef;
	} else {
		return sUrlPath + '?' + arrPairs.join('&') + sHashRef;
	}
}

function Url(sUrl) {
	var m_sUrl = sUrl.toString();
	
	this.hash = '';
	this.protocol = ''
	this.hostname = '';
	this.host = '';
	this.port = '';
	this.queryString = '';
	this.search = '';
	this.pathname = '';
	
	
	var Load = function(oObj) {
		var nTemp;
		var sTemp;
	
		//setup protocol
		if (m_sUrl.indexOf('https:') == 0) {
			oObj.protocol = 'https:';
		} else if (m_sUrl.indexOf('http:') == 0) {
			oObj.protocol = 'http:';
		}  
		
		//setup host
		if (m_sUrl.indexOf('://') != -1) {
			sTemp = m_sUrl.substr(m_sUrl.indexOf('://') + 3, m_sUrl.length);
			oObj.host = sTemp.substr(0, sTemp.search(/[\?\#\/]|$/i));
		} 
		
		//setup hostname & port
		if (oObj.host != '') {
			if (oObj.host.indexOf(':') != -1) {
				oObj.hostname = oObj.host.substr(0, oObj.host.indexOf(':'));
				oObj.port = oObj.host.substr(oObj.host.indexOf(':')+1, oObj.host.length);
			} else {
				oObj.hostname = oObj.host;
			}	
		}
		
		//setup hash
		if (m_sUrl.indexOf('#') != -1) {
			oObj.hash = m_sUrl.slice(m_sUrl.indexOf('#'), m_sUrl.length);
		}

		//setup queryString
		if (m_sUrl.indexOf('?') != -1) {
			oObj.queryString = m_sUrl.substr(m_sUrl.indexOf('?') + 1, m_sUrl.search(/\#|$/i));
			if (oObj.hash != '') {
				oObj.queryString = oObj.queryString.substr(0, oObj.queryString.indexOf(oObj.hash));
			}
			
			oObj.search = '?' + oObj.queryString;
		}

		//setup pathname
		if (oObj.host != '') {
			sTemp = m_sUrl.substr(m_sUrl.indexOf(oObj.host), m_sUrl.length);
			if (sTemp.search('\\/[^\\?\\#]{1,}') != -1) {
				oObj.pathname = m_sUrl.substr(m_sUrl.indexOf(oObj.host) + oObj.host.length, m_sUrl.length);
				if (oObj.queryString != '') {
					oObj.pathname = oObj.pathname.substr(0, oObj.pathname.indexOf('?' + oObj.queryString));
				}
				if (oObj.hash != '') {
					oObj.pathname = oObj.pathname.substr(0, oObj.pathname.indexOf(oObj.hash));
				}
			}
		}
	}
	
	Load(this);
	
	this.toString = function() {
		var sPort = this.port;
		var sProtocol = this.protocol;
		
		if (this.port != '') {
			sPort = ':' + this.port;
		}
		if (this.protocol != '') {
			sProtocol = this.protocol + '//';
		}
		
		return sProtocol + this.host + sPort + this.pathname + this.search + this.hash;
	}
	
	
	this.getItem = function(sKey) {
		var oHash = new HashTable(this.queryString);
		return oHash.getItem(sKey);
	}
	
	this.setItem = function (sKey, sValue) {
		var oHash = new HashTable(this.queryString);
		oHash.setItem(sKey, sValue);
		this.queryString = oHash.toQueryString();
		
		this.search = '';
		if ((this.queryString) != '') {
			this.search = '?' + this.queryString;
		}
	}
}

function HashTable(sQueryString) {
	this.keys = new Array();
	this.values = new Array();
	this.count = 0;
	
	this.setItem = function(sKey, sValue) {
		var nIndex = this.keys.indexOf(sKey);
		if (nIndex == -1) {
			this.keys.add(sKey);
			this.values.add(sValue);
			this.count++;
		} else {
			this.values[nIndex] = sValue;
		}
	}
	
	this.getItem = function(sKey) {
		for (var i=0; i<this.keys.length; i++) {
			if (this.keys[i] == sKey) {
				return this.values[i];
			}
		}
		
		return "";
	}
	
	this.loadQueryString = function(sQs) {
		this.keys = new Array();
		this.values = new Array();
		
		if (sQs != '') {
			var arrPairs = sQs.split('&');
			var arrTemp;
			
			for (var i=0; i<arrPairs.length; i++) {
				arrTemp = arrPairs[i].split('=');
				this.setItem(UrlDecode(arrTemp[0]), UrlDecode(arrTemp[1]));
			}
		}
	}
	
	this.toQueryString = function() {
		var arrTemp = new Array();
		for (var i=0; i<this.keys.length; i++) {
			arrTemp[arrTemp.length] = UrlEncode(this.keys[i]) + '=' + UrlEncode(this.values[i]);
		}
		return arrTemp.join('&');
	}
	
	if (sQueryString) {
		this.loadQueryString(sQueryString);
	}
}

function TrimTrailingComma(sStr) {
	if (sStr.charAt(sStr.length-1) == ',') {
		return sStr.slice(0, sStr.length - 1);
	}
	
	return sStr;
}

function PreloadImages() {
	if(document.images){ 
		
		if (!document.g_arrImages) {
			document.g_arrImages = new Array();
		}
		var arrReturn = new Array();
		var j = document.g_arrImages.length;
		var args = arguments; 
		
		for (var i=0; i < args.length; i++) {
			if (args[i].indexOf("#") != 0) { 
				document.g_arrImages[j] = new Image; 
				
				document.g_arrImages[j].isError = false;
				document.g_arrImages[j].onerror = Image_SetError; 
				document.g_arrImages[j].isLoaded = false;
				document.g_arrImages[j].onload = Image_SetLoaded; 
				
				document.g_arrImages[j].src = args[i];
				
				arrReturn[arrReturn.length] = document.g_arrImages[j];
				j++;
			}
		}
		return arrReturn;
	}
}

function Image_SetLoaded() {
	this.isLoaded = true;
}

function Image_SetError() {
	this.isError = true;
}

//this function returns the position of an image
//coordinate should be supplied as 'x' or 'y'
function GetImagePosition(sImageName, sCoordinate){
	var oImage = document.images[sImageName];
	var nPos = -1;
	if (document.layers) {
		nPos = eval("theImage." + sCoordinate);
	} else {
		if (sCoordinate == 'x'){
			nPos = GetIeX(oImage);
		} else {
			nPos = GetIeY(oImage);
		}
	}
	return nPos;
}

function GetIeX(oObj) {
    var xPos = oObj.offsetLeft;
    var oTemp = oObj.offsetParent;
    while (oTemp != null) {
        xPos += oTemp.offsetLeft;
        oTemp = oTemp.offsetParent;
    }
    return xPos;
}

function GetIeY(oObj) {
    var yPos = oObj.offsetTop;
    var oTemp = oObj.offsetParent;
    while (oTemp != null) {
        yPos += oTemp.offsetTop;
        oTemp = oTemp.offsetParent;
    }
    return yPos;
}

//returns custom attributes applied either in HTML, or as dynamic expando properties.
//returns an empty string if not found
function GetAttributeEx(oObj, sAttrName) {
	if (!oObj) {
		return "";
	} else if (Browser.OS != OS_MAC && typeof(eval('oObj.' + sAttrName)) != "undefined") {
		return eval('oObj.' + sAttrName);
	} else if (!oObj.getAttribute) {
		return "";
	} else if (oObj.getAttribute(sAttrName) == null) {
		return "";
	} else {
		return oObj.getAttribute(sAttrName);
	}
}

function KeyPressHandler(e){
	var nKey = (!document.all) ? e.which : window.event.keyCode;
	var oSrc;
	
	//HACK for IE on Mac
	if (Browser.OS == OS_MAC && Browser.UserAgent == BROWSER_IE) {
		if (!document.EnterKeyActionEnabled) {
			document.EnterKeyOverrideAction();
			return true;
		}
	}
	
	if (nKey == 13 || (Browser.OS == OS_MAC && nKey == 3)){
		if (!e) { 
			e = event;
		}
		
		if (e.srcElement) {
			oSrc = e.srcElement;
		} else if (e.explicitOriginalTarget) {
			oSrc = e.explicitOriginalTarget;
		}
		
		if (!oSrc) {
			return true;
		} else if (oSrc.tagName == 'TEXTAREA') {
			return true;
		} else if (oSrc.tagName == 'A') {
			return true;
		} else if (oSrc.tagName == 'INPUT' && oSrc.type == 'button') {
			return true;
		} else if (oSrc.tagName == 'INPUT' && oSrc.type == 'submit') {
			return true;
		}

		if (document.EnterKeyAction != '') {
			eval(document.EnterKeyAction);
			return false;
		}
	}
}

function SetEnterKeyAction(sAction) {
	document.EnterKeyAction = sAction;
	if (document.layers) {
		document.captureEvents(Event.KEYPRESS);
	}
	document.onkeypress = KeyPressHandler;
	SetEnterKeyActionOn();
}

//HACK for IE on Mac- allows enter key to behave properly on A and TEXTAREAs
function InitEnterKeyAction() {
	if (Browser.OS == OS_MAC && Browser.UserAgent == BROWSER_IE) {
		var arrLinks = document.getElementsByTagName('A');
		var arrTextAreas = document.getElementsByTagName('TEXTAREA');
		var arrButtons = document.getElementsByTagName('INPUT');

		for (var i=0; i<arrLinks.length; i++) {
			arrLinks[i].onfocus = SetEnterKeyActionOff;
			arrLinks[i].onblur = SetEnterKeyActionOn;
		}
		for (i=0; i<arrButtons; i++) {
			if (arrButtons[i].type == 'submit' || arrButtons[i].type == 'button') {
				arrButtons[i].onfocus = SetEnterKeyActionOff;
				arrButtons[i].onblur = SetEnterKeyActionOn;
			}
		}
		for (i=0; i<arrTextAreas; i++) {
			arrTextAreas[i].onfocus = SetEnterKeyActionOff;
			arrTextAreas[i].onblur = SetEnterKeyActionOn;
		}
	}
}

function SetEnterKeyActionOff() {
	document.EnterKeyActionEnabled = false;
	if (event.srcElement.onclick) {
		document.EnterKeyOverrideAction = event.srcElement.onclick;
	} else if (event.srcElement.href) {
		document.EnterKeyOverrideAction = function() {
			document.location = event.srcElement.href;
		}
	} else {
		document.EnterKeyOverrideAction = function() {
			//nothing;
		}
	}
}

function SetEnterKeyActionOn() {
	document.EnterKeyActionEnabled = true;
	document.EnterKeyOverrideAction = null;
}

function OnLoadHandler() {
	eval(document.OnLoadAction);
	document.OnLoadActionTaken = true;
}

//writes a peice of code which gets executed on the bottom of the page
function SetOnLoadAction(sAction) {
	document.OnLoadAction = sAction;
}

//appends to a peice of code which gets executed on the bottom of the page
function AddOnLoadAction(sAction) {
	if (document.OnLoadAction) {
		document.OnLoadAction += '\n' + sAction;
	} else {
		document.OnLoadAction = sAction;
	}
}

function FinishOnLoadAction() {
	if (!document.OnLoadActionTaken) {
		OnLoadHandler();
	}
}

/*
function LimitTextAreaLength(oObj, nLength, bRemoveLineBreaks) {
	if (oObj.value.length >= nLength) {
		oObj.value = oObj.value.slice(0, nLength);
		return false;
	}
	if (bRemoveLineBreaks) {
		if (oObj.value.search('[\f\n\r\t\v]') != -1) {
			oObj.value = oObj.value.replace(/[\f\n\r\t\v]/gim, '');
		}
	}
	return true;
}
*/

//if the text overflows in the given text field, this will give it a scrollbar
function CheckTextOverflow(oObj) {
	if (Browser.UserAgent != BROWSER_IE) {
		return;
	}
	
	if (oObj.type != 'text') {
		return;
	}
	
	if (oObj.scrollWidth == 0 || oObj.offsetWidth == 0) {
		return;
	}

	oObj.style.overflow = 'auto';

	if (oObj.scrollWidth >= oObj.offsetWidth-3) {
		oObj.style.height = '40px';
	} else {
		oObj.style.height = '';
	}
}

//Array enhancement functions
function FindInArray(arr, oValue, bCaseSensitiveOrCompareFunction) {
	var delegateCompareFunction;
	
	if (typeof(bCaseSensitiveOrCompareFunction) == "undefined") {
		delegateCompareFunction = CompareCaseSensitive;
	} else if (typeof(bCaseSensitiveOrCompareFunction) == "function") {
		delegateCompareFunction = bCaseSensitiveOrCompareFunction
	} else if (bCaseSensitiveOrCompareFunction == false) {
		delegateCompareFunction = CompareCaseInsensitive;
	} else if (bCaseSensitiveOrCompareFunction == true) {
		delegateCompareFunction = CompareCaseSensitive;
	}
	
	for (var i=0; i<arr.length; i++) {
		if (delegateCompareFunction(oValue, arr[i]) == 0) {
			return i;
		}
	}
		
	return -1;
}

function CompareCaseSensitive(o1, o2) {
	if (o1 > o2) {
		return 1;
	} else if (o1 < o2) {
		return -1;
	} else if (o1 == o1) {
		return 0;
	}
}

function CompareCaseInsensitive(o1, o2) {
	return CompareCaseSensitive(o1.toLowerCase(), o2.toLowerCase());
}

Array.prototype.indexOf = function(oValue, bCaseSensitiveOrCompareFunction) {
	return FindInArray(this, oValue, bCaseSensitiveOrCompareFunction);
}

//only works on sorted arrays
function BinarySearch(arr, oValue, bCaseSensitiveOrCompareFunction) {
	var delegateCompareFunction;
	
	if (typeof(bCaseSensitiveOrCompareFunction) == "undefined") {
		delegateCompareFunction = CompareCaseSensitive;
	} else if (typeof(bCaseSensitiveOrCompareFunction) == "function") {
		delegateCompareFunction = bCaseSensitiveOrCompareFunction
	} else if (bCaseSensitiveOrCompareFunction == false) {
		delegateCompareFunction = CompareCaseInsensitive;
	} else if (bCaseSensitiveOrCompareFunction == true) {
		delegateCompareFunction = CompareCaseSensitive;
	}
	
	var iLow, iHigh, iMid, iRound;
	iLow = 0;
	iHigh = arr.length - 1;
	iRound = 0;
 
	while (iLow <= iHigh) {
		iRound++;
		iMid = Math.floor((iLow + iHigh) / 2);
	
		var iCompare = delegateCompareFunction(oValue, arr[iMid]);
		
		if (iCompare < 0)
			iHigh = iMid - 1;
		else if (iCompare > 0)
			iLow = iMid + 1;
		else
			return iMid;
	}
	
	return -1;
}

Array.prototype.binarySearch = function(oValue, bCaseSensitiveOrCompareFunction) {
	return BinarySearch(this, oValue, bCaseSensitiveOrCompareFunction);
}

//only works on sorted arrays
function InsertInSortedArray(arr, oValue, bCaseSensitiveOrCompareFunction) {
	var delegateCompareFunction;
	
	if (typeof(bCaseSensitiveOrCompareFunction) == "undefined") {
		delegateCompareFunction = CompareCaseSensitive;
	} else if (typeof(bCaseSensitiveOrCompareFunction) == "function") {
		delegateCompareFunction = bCaseSensitiveOrCompareFunction
	} else if (bCaseSensitiveOrCompareFunction == false) {
		delegateCompareFunction = CompareCaseInsensitive;
	} else if (bCaseSensitiveOrCompareFunction == true) {
		delegateCompareFunction = CompareCaseSensitive;
	}
	
	var iLow, iHigh, iMid, iRound;
	iLow = 0;
	iHigh = arr.length - 1;
	iRound = 0;
 
	while (iLow <= iHigh) {
		iRound++;
		iMid = Math.floor((iLow + iHigh) / 2);
	
		var iCompare = delegateCompareFunction(oValue, arr[iMid]);
		
		if (iCompare < 0)
			iHigh = iMid - 1;
		else if (iCompare > 0)
			iLow = iMid + 1;
		else
			break;
	}
	
	var iCompare = delegateCompareFunction(oValue, arr[iMid]);
	
	if (iCompare > 0) {
		InsertInArray(arr, oValue, iMid+1);
	} else {
		InsertInArray(arr, oValue, iMid);
	}
}

Array.prototype.insertSorted = function(oValue, bCaseSensitiveOrCompareFunction) {
	return InsertInSortedArray(this, oValue, bCaseSensitiveOrCompareFunction);
}

function AddToArray(arr, oValue, bEnforceUnique, bCaseSensitiveOrCompareFunction) {
	if (!bEnforceUnique || arr.indexOf(oValue, bCaseSensitiveOrCompareFunction) == -1) {
		arr[arr.length] = oValue;
		return true;
	}
	
	return false;
}

Array.prototype.add = function(oValue, bEnforceUnique) {
	return AddToArray(this, oValue, bEnforceUnique);
}

function InsertInArray(arr, oValue, nIndex) {
	for (var i=arr.length; i>nIndex; i--) {
		arr[i] = arr[i-1];
	}
	
	arr[nIndex] = oValue;
	
	return true;
}

Array.prototype.insert = function(oValue, nIndex) {
	return InsertInArray(this, oValue, nIndex);
}

//Implementation of Array.splice() for older JavaScript engines which dont support it (IE Mac)
function Array_splice(nIndex, nCountDelete) {
	var arrTemp = new Array();
	var arrNew = new Array();
	var i = 0;
	
	for (i = 0; i < nIndex; i++) {
		arrTemp[arrTemp.length] = this[i];
	}
	for (i = 2; i < arguments.length; i++) {
		arrTemp[arrTemp.length] = arguments[i];
	}
	for (i = nIndex + nCountDelete; i < this.length; i++) {
		arrTemp[arrTemp.length] = this[i];
	}
	for (i = 0; i < nCountDelete; i++) {
		arrNew[i] = this[nIndex + i];
	}
	
	this.length = 0
	
	for (i = 0; i < arrTemp.length; i++) {
		this[this.length] = arrTemp[i];
	}
	
	return arrNew;
}

if (typeof Array.prototype.splice == "undefined") {
	Array.prototype.splice = Array_splice;
}

Array.prototype.remove = function(nIndex) {
	this.splice(nIndex, 1);
}

function RollOut(nImgID) { //v3.0
	var oImg = document.getElementById(nImgID);
	if (document.RolloverArray[nImgID]) {
		oImg.src = document.RolloverArray[nImgID];
	}
}

function RollOver(sImgID, sNewImgSrc) { //v3.0
	if (!document.RolloverArray) {
		document.RolloverArray = new Array();
	}
	var oImg = document.getElementById(sImgID);
	document.RolloverArray[sImgID] = oImg.src;
	oImg.src = sNewImgSrc + '?v=' + fw_config_Version;
}

var g_winTrace;

function Trace(sMsg) {
	var sUrl = '';
	
	if (!g_winTrace || g_winTrace.closed) {
		g_winTrace = window.open(sUrl, 'traceWin', 'width=400px,height=600px,left=0px,top=0px,screenX=0px,screenY=0px,resizable=yes,scrollbars=yes');
		
	}
	try {
		//g_winTrace.focus();
		g_winTrace.document.write(sMsg + '<br>');
		g_winTrace.scrollTo(0, g_winTrace.document.body.scrollHeight + 30);
		//window.focus();
	} catch (e) {
		alert('Error opening trace window. Check popup blocking settings.');
	}
}

function IsObjectVisible(oObj) {
	var oTemp = oObj;
	
	//finds the first parent with the visiblity property set
	while (oTemp.parentNode) {
		if (oTemp.style && (oTemp.style.visibility != "")) {
			if (oTemp.style.visibility == "hidden") {
				return false;
			} else if (oTemp.style.visibility == "visible") {
				//its visible, see if its display propery is set
				break;
			}
		}
		
		oTemp = oTemp.parentNode;
	}
	
	//sees if any parent node has display set to none (inheritance cant be overriden)
	oTemp = oObj;
	
	while (oTemp.parentNode) {
		if (oTemp.style && (oTemp.style.display != "")) {
			if (oTemp.style.display == "none") {
				return false;
			} 
		}
		
		oTemp = oTemp.parentNode;
	}
	
	return true;
}

//disables or enables links, cross browsers. Workaround for Netscape/IE inconsistencies.
function EnableLink(oLink, bDoEnable) {
	if (typeof(bDoEnable) == "undefined") {
		bDoEnable = true;
	}

	if (typeof(oLink.disabled) == "undefined") {
		oLink.disabled = true;
	}

	if (bDoEnable == !oLink.disabled) {
		return;
	}
	
	oLink.disabled = !bDoEnable;
	oLink.hideFocus = !bDoEnable;
	oLink.style.cursor = bDoEnable ? "" : "default";
	
	if (Browser.UserAgent != BROWSER_IE) {
		oLink.style.color = bDoEnable ? "" : "#BBBBBB";
	}

	if (bDoEnable && oLink.onclickdisabled) {
		oLink.onclick = oLink.onclickdisabled;
	} else if (!bDoEnable && oLink.onclick){
		oLink.onclickdisabled = oLink.onclick;
		oLink.onclick = function() {return false;}
	}
	
	if (bDoEnable && oLink.tabIndexDisabled) {
		oLink.tabIndex = oLink.tabIndexDisabled;
	} else if (!bDoEnable && oLink.onclick){
		oLink.tabIndexDisabled = oLink.tabIndex;
		oLink.tabIndex = -1;
	}
}

//HACK for Safari
if (!String.prototype.toLocaleLowerCase) {
	String.prototype.toLocaleLowerCase = function() {
		return this.toLowerCase();
	}
}
if (!String.prototype.localeCompare) {
	String.prototype.localeCompare = function(sStr) {
		if (this < sStr) {
			return -1;
		} else if (this == sStr) {
			return 0;
		} else {
			return 1;
		}
	}
}

function DisableDocument(oDoc) {
	var arrItems = oDoc.getElementsByTagName("A");
	for (var i=0; i<arrItems.length; i++) {
		arrItems[i].onclick = function() {return false;};
		arrItems[i].href = "#";
		arrItems[i].style.cursor = "default";
	}
}

function RenderLoadingMessage(sMessage, bSmall) 
{
	document.write('<div id="fw_loadingDiv" align="center">');
	document.write('<div style="width:250px; margin-top:60px; border:1px black solid; padding:10px;">');
	document.write('<img src="' + fw_config_ImageDirectory); 
	
	if(bSmall)
		document.write('/progress.gif">');
	else
		document.write('/progress.gif">');
	document.write('<br><br><span style="font-size: 12px; font-weight: bold; color: #124EC3;">' + sMessage + '</span><br>');
	document.write('</div>');
	document.write('</div>');
}

function HideLoadingMessage() {
	if (document.getElementById('fw_loadingDiv')) {
		document.getElementById('fw_loadingDiv').style.display = 'none';
	}
}

//workaround for the ASP Request object limit. InputManager will automatically reassemble input broken up by this function.
function PrepareLongTextField(oObj) {
	//Set the limit for field size.
	var FormLimit = 102399;
	var i = 0;
	
	//Get the value of the large input object.
	var TempVar = new String(oObj.value);
	
	//If the length of the object is greater than the limit, break it
	//into multiple objects.
	if (TempVar.length > FormLimit) {
		oObj.value = TempVar.substr(0, FormLimit);
		TempVar = TempVar.substr(FormLimit);
	
		while (TempVar.length > 0) {
			var objTEXTAREA = oObj.document.createElement("TEXTAREA");
			objTEXTAREA.name = oObj.name + '_fw_longtext_split_' + i;
			objTEXTAREA.value = TempVar.substr(0, FormLimit);
			objTEXTAREA.style.display = 'none';
			oObj.form.appendChild(objTEXTAREA);
			
			TempVar = TempVar.substr(FormLimit);
			i++;
		}
	}
}

//scrolls the specified multiselect so the first selected element is visible
function ScrollToFirstSelected(oSelect) {
	if (!document.ScrollFirstSelectedCount) {
		document.ScrollFirstSelectedCount = 1;
	}

	setTimeout('ScrollToFirstSelectedDirect(document.getElementById("' + oSelect.id + '"));', document.ScrollFirstSelectedCount);
	document.ScrollFirstSelectedCount++;
}

function ScrollToFirstSelectedDirect(oSelect) {
	var nIndex = -1;
	
	if (!oSelect || oSelect.disabled || oSelect.style.display == 'none') {
		return;
	}
	
	for (var i=0; i<oSelect.options.length; i++) {
		if (oSelect.options[i].selected) {
			nIndex = i;
			break;
		}
	}
	
	if (nIndex != -1) {
		for (i=nIndex + (oSelect.size-1); i>=nIndex; i--) {
			if (oSelect.options[i]) {
				oSelect.options[i].selected = !oSelect.options[i].selected;
				oSelect.options[i].selected = !oSelect.options[i].selected;
				break;
			}
		}
		
		oSelect.options[nIndex].selected = !oSelect.options[nIndex].selected;
		oSelect.options[nIndex].selected = !oSelect.options[nIndex].selected;
	}
}

function DisableMultiSelect(oSelect) {
	for (var i=0; i<oSelect.options.length; i++) {
		if (oSelect.options[i].selected) {
			oSelect.options[i].selectedDisabled = true;
			oSelect.options[i].selected = false;
			oSelect.options[i].style.backgroundColor = "#CCCCCC";
		}
	}
	
	//IE rendering bug fix- add and remove a new option, and the colors will refresh
	if (document.all) {
		oSelect.options.add(new Option("", ""));
		oSelect.options.remove(oSelect.options.length-1);
	}
	
	oSelect.style.backgroundColor = "#EEEEEE";
	oSelect.disabled = true;
}

function EnableMultiSelect(oSelect) {
	for (var i=0; i<oSelect.options.length; i++) {
		if (oSelect.options[i].selectedDisabled) {
			oSelect.options[i].selected = true;
			oSelect.options[i].selectedDisabled = null;
			oSelect.options[i].style.backgroundColor = "";
		}
	}
	
	oSelect.disabled = false;
	oSelect.style.backgroundColor = "#FFFFFF";
	
	//IE rendering bug fix- add and remove a new option, and the colors will refresh
	if (document.all) {
		oSelect.options.add(new Option("", ""));
		oSelect.options.remove(oSelect.options.length-1);
	}
}

function IfPlural(sSingular, sPlural, nCount) {
	if (nCount == 1) {
		return sSingular;
	} else {
		return sPlural;
	}
}

function JScriptString(sStr) {
	var sOut = new String(sStr);
	sOut = sOut.replace(/\\/gi, "\\\\");
	sOut = sOut.replace(/\'/gi, "\\'");
	sOut = sOut.replace(/\n/gi, "\\n");
	sOut = sOut.replace(/\r/gi, "\\r");
	sOut = sOut.replace(/\f/gi, "\\f");
	sOut = sOut.replace(/\f/gi, "\\f");
	//sOut = Replace(sOut, "<scr" & "ipt", "<scr' + 'ipt", 1, 1, 1)
	//sOut = Replace(sOut, "</scr" & "ipt>", "</scr' + 'ipt>", 1, 1, 1)
	sOut = sOut.replace(/\"/gi, "' + String.fromCharCode(34) + '");
	return sOut;
}

function NavigateChanged(sURL, bHideProgressBar) {
	if (document.IsChanged && document.ChangeHandler) {
		document.ChangeHandler(sURL);
	} else if (bHideProgressBar) {
		document.location = sURL;
	} else {
		NavigateProgressBar(sURL);	
	}
}


function DOMQuery() {
	SetCookie("dom_query", "1", 365)
}

document.onkeydown = function() {
	var sTempBorder;
	var nFoundIndex = -1;
	
	if (!document.all) {
		return;
	}

	if (event.ctrlKey && event.keyCode == 81 && GetCookie("dom_query") == "1") {
		var oObj = document.elementFromPoint(event.clientX, event.clientY);
		var sMessage = '';
		
		if (oObj.id && oObj.id != '') {
			sMessage += 'ID: ' + oObj.id + '\n';
		}
		if (oObj.name && oObj.name != '') {
			sMessage += 'name: ' + oObj.name + '\n';
		}
		
		var arrObj = document.getElementsByTagName(oObj.tagName);
		for (var i=0; i<arrObj.length; i++) {
			if (oObj == arrObj[i]) {
				nFoundIndex = i;
				break;
			}
		}
		if (nFoundIndex > -1) {
			sMessage += 'index: ' + oObj.tagName + ': ' + nFoundIndex;
		}
		
		sMessage += '\n\nAdditional Attributes:\n********************\n';

		for (var i=0; i<oObj.attributes.length; i++) {
			
			if (oObj.attributes[i].name != null && oObj.attributes[i].name != '' && oObj.attributes[i].value != null && oObj.attributes[i].value != '' && oObj.attributes[i].value != 'null') {
				sMessage += oObj.attributes[i].name + ': ' + oObj.attributes[i].value + '\n';
			}
		}
		
		alert(sMessage);
		
		event.cancelBubble = true;
		return false;
	} else {
		return true;
	}
}

function SetScrollToLastPosition() {
	window.onscroll = function() {
		SetCookie(document.location.pathname + '_scroll_to', document.body.scrollTop);
	}
	
	AddOnLoadAction("ScrollToLastPosition();");
}

function ScrollToLastPosition() {
	var nScrollTo = GetCookie(document.location.pathname + '_scroll_to');
	if (nScrollTo != '') {
		window.scrollTo(0, parseInt(nScrollTo));
	}
}

//supports vbscript dialogs
document.write('<scr' + 'ipt language="JavaScript" src="' + fw_config_ScriptDirectory + '/dialogs.js"></scr' + 'ipt>');
if (document.all) {
	document.write('<scr' + 'ipt language="VbScript" src="' + fw_config_ScriptDirectory + '/dialogs_vb.js"></scr' + 'ipt>');
}

document.FwScriptsLoaded = true;

