// This file contains general-purpose client-side funtions that are cross-browser compatible back to at least 4.0 browsers
function RemoveFromList(strList, strItem, bolCaseSensitive) {
// Returns the comma delimited list strList with the item passed to strItem removed from the list, if the item was found
// This function is NOT case sensitive unless you pass true to the optional third parameter
// Spaces are trimmed from the beginning and end of the List and the Item
// Items in the List can have a single space after the separating comma, but not before
// This functions assumes that items in the list are unique. It does not do multiple replacements.
	if (Trim(strList) == Trim(strItem)) {
		return "";
	}
	if (strList == "" || strList == null) {
		return "";
	}
	if (strItem == "") {
		return strList;
	}
	var tempList;
	var tempItem;
	if (bolCaseSensitive) {
		tempList = strList;
		tempItem = strItem;
	} else {
		tempList = strList.toLowerCase();
		tempItem = strItem.toLowerCase();
	}
	var commaEndedList = "," + Trim(tempList) + ","; // Adding commas to the ends of the list allows you to search for the Item with a beginning and ending comma added
	var correctCaseCommaEndedList = "," + Trim(strList) + ",";
	var itemWithCommas = "," + Trim(tempItem) + ","; // Searching for the Item plus a beginning and ending comma guarantees that you are matching the entire value and not a subset of another value
	var itemWithCommasAndSpace = ", " + Trim(tempItem) + ",";
	var itemWithCommasFound = commaEndedList.indexOf(itemWithCommas) >= 0;
	var itemWithCommasAndSpaceFound = commaEndedList.indexOf(itemWithCommasAndSpace) >= 0;

	if (itemWithCommasFound || itemWithCommasAndSpaceFound) {
		var itemFound
		var replacementDelimiter
		if (itemWithCommasFound) {
			itemFound = itemWithCommas
			replacementDelimiter = ","
		} else if (itemWithCommasAndSpaceFound) {
			itemFound = itemWithCommasAndSpace
			replacementDelimiter = ", "
		}
		var itemStartPos = commaEndedList.indexOf(itemFound)
		var itemEndPos = itemStartPos + itemFound.length
		return Trim(correctCaseCommaEndedList.substring(0, itemStartPos) + replacementDelimiter + correctCaseCommaEndedList.substring(itemEndPos, correctCaseCommaEndedList.length), ",");
	} else {
		return strList;
	}
}

function SetSelectedValues(theSelect, strValues, bolClearFirst, bolCaseSensitive) {
// This function is NOT case sensitive unless you pass true to the optional fourth parameter
// bolClearFirst is an optional parameter that will cause previously selected values to be 
// unselected if they are not among those passed to strValues. It only has an effect for select 
// objects that are set to allow multiple selections.
// strValues can be a comma delimited list.
// If a comma delimited list is passed to strValues, but the select object is not set to allow
// multiple selections, the FIRST value in the list will be used.
// If more than one item in the select object has the same value, the FIRST one will be selected.
// This function cannot select an item whose value is an empty string
	var selectedValueFound = false;
	for (var i = 0; i < theSelect.options.length; i++) {
		if (IsInList(strValues, theSelect.options[i].value, bolCaseSensitive)) {
			theSelect.options[i].selected = true;
			selectedValueFound = true;
			if (theSelect.type != "select-multiple") {
				break;
			}
		} else if (theSelect.type == "select-multiple" && bolClearFirst) {
			theSelect.options[i].selected = false;
		}
	}
	return selectedValueFound;
}

function GetSelectedValues(theSelect) {
// Returns a comma delimited list of all selected values of all selected options
// Returns an empty string if no options were selected, or if only options with a value of an empty string were selected
// Selected options with a value of an empty string do not add to the comma delimited list
	var selectedValues = ""
	for (var i = 0; i < theSelect.options.length; i++) {
		if (theSelect.options[i].selected) {
			if (selectedValues != "" && theSelect.options[i].value != "") {
				selectedValues = selectedValues + ", ";
			}
			if (theSelect.options[i].value != "") {
				selectedValues = selectedValues + theSelect.options[i].value;
			}
		}
	}
	return selectedValues;
}

function GetSelectedText(theSelect) {
// Returns the displayed text (rather than the value) of the selected option 
// of a select object (drop-down) that doesn't use the MULTIPLE attribute
	return theSelect.options[theSelect.selectedIndex].text;
}

function ClearSelect(theSelect) {
	for (var i = 0; i < theSelect.options.length; i++) {
		theSelect.options[i].selected = false;
	}
}

function GetRadioValue(theRadioGroup) {
	for (var i = 0; i < theRadioGroup.length; i++) {
		if (theRadioGroup[i].checked) {
			return theRadioGroup[i].value;
		}
	}
	return null; // If no radio button in the group was checked, return null
}

function getRandomString(stringLength, characterGroups) {
// This function is useful for generating temporary passwords
// A value of 1 for characterGroups will use only lowercase letters for the string
// A value of 2 for characterGroups will use only lowercase letters and number characters for the string
// A value of 3 for characterGroups will use lowercase letters, number characters and uppercase letters for the string
// Values higher than 3 for characterGroups will make lowercase letters increasingly more likely to be used over number characters and uppercase letters for the string
	var randomString, i;
	randomString = "";
	for (i = 0; i < stringLength; i++) {
		var currentGroup = Math.floor(characterGroups * Math.random()) + 1;
		var intAscii;
		if (currentGroup == 1) {
			intAscii = Math.floor((26 * Math.random()) + 97); // Lowercase letters
		} else if (currentGroup == 2) {
			//var intAscii = Math.floor((10 * Math.random()) + 48); // Numbers
			intAscii = Math.floor((8 * Math.random()) + 50); // Numbers, except 0 and 1 which can be confused with uppercase o and lowercase l
		} else if (currentGroup == 3) {
			intAscii = Math.floor((26 * Math.random()) + 65); // Uppercase letters
		} else {
			intAscii = Math.floor((26 * Math.random()) + 97); // Lowercase letters
		}
		randomString += unescape("%" + intAscii.toString(16));
	}
	return randomString;
}

function GetDelimitedFormValues(theForm, clickedButtonName) {
// Returns the equivalent of the query string that would be generated by a form submission where method="get"
// clickedButtonName is optional
	var BCardQuery = "";
	var queryDelimiter = "";
	for (var i = 0; i < theForm.elements.length; i++) {
		var elem = theForm.elements[i];
		var elemValue;
		var addQueryValue = false;
		if (elem.name != null && elem.name != "") { // Only return form elements that have a name
			if (elem.type == "checkbox" || elem.type == "radio") { // Only return checkboxes and radio buttons if they are checked
				if (elem.checked) {
					elemValue = elem.value;
					addQueryValue = true;
				}
			} else if (elem.type == "select-one" || elem.type == "select-multiple") { // Return a comma delimited list of all selected options in a select object
				elemValue = GetSelectedValues(elem);
				addQueryValue = true;
			} else if (elem.type == "submit" || elem.type == "image") {
				// Because we have no direct way of knowing if a submit button (or image button) was clicked, don't 
				// return submit button values. The only exception is if the name of one is passed into the optional
				// clickedButtonName parameter, which would require keeping track of which one was clicked in code.
				// In a normal form submission, only the submit button that was clicked is returned, so that 
				// you can tell at the web server which button was clicked in cases where there are multiple 
				// submit buttons for different purposes.
				if (clickedButtonName != null && clickedButtonName != "") {
					if (clickedButtonName == elem.name) {
						elemValue = elem.value;
						addQueryValue = true;
					}
				}
			} else if (elem.type == "button" || elem.type == "reset") { // Don't return buttons or reset buttons.)
				// Use the default value of false for addQueryValue
			} else { // Return all other elements, even if their value is an empty string
				elemValue = elem.value;
				addQueryValue = true;
			}
		}
		if (addQueryValue) {
			BCardQuery += queryDelimiter + elem.name + "=" + escape(elemValue);
			queryDelimiter = "&";
		}
	}
	return BCardQuery;
}

function SetCookie(cookieName, cookieValue, cookieExpirationDays, cookiePath) {
// cookiePath and cookieExpirationDays are optional
// cookieValue should be no more than 4K of data, after escaping special characters
	if (cookieValue != "") {
		var cookiePathSetting = "";
		if (cookiePath != null && cookiePath != "") {
			// Make the cookie apply to the given path if one was set, otherwise allow the cookie to default to the current folder (and any subfolders)
			// Pass "/" for cookiePath if the current file is not in the root of the web and you want to make the cookie available to the entire web
			cookiePathSetting = "; path=" + cookiePath;
		}
		var cookieExpirationSetting = "";
		if (cookieExpirationDays != null && cookieExpirationDays != "" && !isNaN(cookieExpirationDays)) {
			// Make the cookie persistent if a number of days was set
			var now = new Date();
			var cookieExpirationDate = new Date(now.getTime() + (cookieExpirationDays * 24 * 60 * 60 * 1000));  // cookieExpirationDays from now, calculated in milliseconds
			cookieExpirationSetting = "; expires=" + cookieExpirationDate.toGMTString();
		}
		document.cookie = cookieName + "=" + cookieValue + cookiePathSetting + cookieExpirationSetting;
	} else {
		DeleteCookie(cookieName, cookiePath); // Delete the cookie if it has no value
	}
}

function GetCookieValue(cookieName, unescapeReturnValue) {
// unescapeReturnValue is optional
	if (unescapeReturnValue == true) { // because unescapeReturnValue is optional, we can't use it directly as a boolean, so we compare it to true
		return unescape(GetValueFromPairList(document.cookie, ";", cookieName))
	} else {
		return GetValueFromPairList(document.cookie, ";", cookieName)
	}
}

function GetCookieSubValue(cookieName, subValueName) {
// For use with ASP style dictionary cookies where the value of an individual cookie contains an ampersand delimited list of name=value pairs. 
// Dictionary cookies are a way around the 10 cookie limit of many browsers.
	return GetValueFromPairList(GetCookieValue(cookieName, false), "&", subValueName)
}

function GetValueFromPairList(nameValuePairList, delimiter, valueName) {
// Gets a value from a string containing name=value pairs
	var pairStart = nameValuePairList.indexOf(valueName + "=");
	if (pairStart == -1) {
		return "";
	}
	var valueStart = nameValuePairList.indexOf("=", pairStart) + 1; // Start with the first character after the equal sign
	var valueEnd = nameValuePairList.indexOf(delimiter, valueStart); // Go to the next delimiter if it exists
	if (valueEnd == -1) valueEnd = nameValuePairList.length; // If there is no delimiter after the equal sign it should be the last value in the string, so go to the end of the string
	return nameValuePairList.substring(valueStart, valueEnd); // Retrieve the value
}

function DeleteCookie(cookieName, cookiePath) {
// cookiePath is optional
	document.cookie = cookieName + "=; expires=Thu, 01-Jan-80 00:00:01 GMT; path=/"; // Delete cookies with the given name that have been set globally for the current web
	document.cookie = cookieName + "=; expires=Thu, 01-Jan-80 00:00:01 GMT"; // Delete cookies with the given name that have the path set to the folder of the current file (the default path)
	if (cookiePath != null && cookiePath != "") {
		document.cookie = cookieName + "=; expires=Thu, 01-Jan-80 00:00:01 GMT; path=" + cookiePath; // Delete cookies with the given name that have the path set to the given path
	}
}

// **** ASSOCIATIVE ARRAY COOKIE FUNCTIONS ****
// These functions are useful for working with cookies in the nested format that
// ASP uses, where a single cookie value can contain multiple name=value pairs

function AssocArrayToPairs(assocArray, delimiter, discardEmptyValues) {
// discardEmptyValues is optional
// Puts the values of an associative array into a string of delimited name=value pairs
	discardEmptyValues = (discardEmptyValues == null) ? false : discardEmptyValues
	var nameValuePairList = "";
	var currentDelimiter = "";
	for (var name in assocArray) {
		currentDelimiter = (nameValuePairList == "") ? "" : delimiter;
		if (name != "length" && name != null && name != "" && name != "0") {
			if (assocArray[name] != null && assocArray[name] != "null") {
				if (!discardEmptyValues || assocArray[name] != "") {
					nameValuePairList += currentDelimiter + name + "=" + assocArray[name];
				}
			}
		}
	}
	return nameValuePairList;
}

function PairsToAssocArray(nameValuePairList, delimiter) {
// Puts the values of a delimited string of name=value pairs into an associative array
	var assocArray = new Array();
	var pairStart = 0;
	var pairEnd = 0;
	while (pairEnd < nameValuePairList.length) {
		pairEnd = nameValuePairList.indexOf(delimiter, pairStart);
		if (pairEnd == -1) pairEnd = nameValuePairList.length;
		var pair = nameValuePairList.substring(pairStart, pairEnd);
		var pairName = pair.substring(0, pair.indexOf("="));
		var pairValue = unescape(pair.substring(pair.indexOf("=") + 1, pair.length));
		assocArray[pairName] = pairValue;
		pairStart = pairEnd + 1;
	}
	return assocArray;
}

// **** END OF ASSOCIATIVE ARRAY COOKIE FUNCTIONS ****

function OpenPopUpWindow(popUpPageURL, windowName, width, height, left, top) {
// This function opens a non-modal window for IE and Netscape 4, modal for Netscape 6 and up
	if (IE4OrNewer) {
		windowProperties = "resizable=yes,scrollbars=yes,status=yes";
		windowProperties += ",width=" + width + ",height=" + height;
		if (IE5OrNewer) {
			if (window.screenLeft != null && left != "" && top != "") {
				windowProperties += ",left=" + (screenLeft + left) + ",top=" + (screenTop + top);
			}
		}
	} else {
		windowProperties = "scrollbars,resizable";
		if (Mozilla5OrNewer){
			windowProperties += ",modal";
			windowProperties += ",width=" + width + ",height=" + height;
			if (screenX < screen.width - 100 && screenY < screen.height - 100) {
				windowProperties += ",left=" + (screenX + left) + ",top=" + (screenY + AbsValue(top));
			}
		}
	}
	var myWin = window.open(popUpPageURL, windowName, windowProperties);
	return myWin;
}

function ShowSizedModalPopUp(popUpPageURL, windowName, width, height, left, top) {
/*
The popup window will only be modal if possible. Netscape 4 windows will NOT be modal.
Internet Explorer (IE4OrNewer) requires the file DialogFrame.asp, which loads the target file in a frame, 
	which allows links and form submissions to remain inside the modal window
The function returns whatever value an IE4OrNewer window returns, true for Mozilla5OrNewer, false otherwise 
	(such as for Netscape 4)
To have code run only when an action is performed in the popup window, and not when the popup window is simply 
	closed, it is cleaner across all browser types to call a function in the opening window to handle the 
	return of the popup when it is closed, rather than using return values, as in the following:
	if (opener.HandlePopUpReturn != null) opener.HandlePopUpReturn(); self.close();
*/
	if (popUpPageURL.toLowerCase().indexOf("popup=") == -1) {
		var queryDelimiter = "?"
		if (popUpPageURL.indexOf("?") >= 0) {
			queryDelimiter = "&"
		}
		popUpPageURL += queryDelimiter + "PopUp=True"
	}
	var windowProperties = "";
	var returnValue = false;
	var useModalDialogBox = IE4OrNewer && !AnyMac;
	if (useModalDialogBox) {
		windowProperties = "help:no;resizable:yes";
		windowProperties += ";dialogWidth:" + width + "px;dialogHeight:" + height + "px";
		if (IE5OrNewer) {
			if (window.screenLeft != null) {
				windowProperties += ";dialogLeft:" + (screenLeft + left) + ";dialogTop:" + (screenTop + top);
			}
		}
		returnValue = window.showModalDialog("DialogFrame.asp?Target=" + escape(popUpPageURL), "", windowProperties);
	} else {
		windowProperties = "scrollbars,resizable";
		if (Mozilla5OrNewer){
			windowProperties += ",modal";
			windowProperties += ",width=" + width + ",height=" + height;
			if (screenX < screen.width - 100 && screenY < screen.height - 100) {
				windowProperties += ",left=" + (screenX + left) + ",top=" + (screenY + AbsValue(top));
			}
		}
		var myWin = window.open(popUpPageURL, windowName, windowProperties);
		if (Mozilla5OrNewer) {
			returnValue = true;
		}
	}
	return returnValue;
}

function AbsValue(number) {
	if (number < 0) {
		return -number
	} else {
		return number
	}
}

function ShowModalPopUp(popUpPageURL, windowName) {
/*
The popup window will only be modal if possible. Netscape 4 windows will NOT be modal.
The popup window will be slightly smaller than the opening window, except for Netscape 4 which will 
	usually create a (non-modal) popup window the same size as the opening window
The popup window will be approximately centered over the opening window, except for Netscape 4 which 
	will usually open the popup directly over the opening window and except for Mozilla5OrNewer if the 
	opening window is not on the primary screen, in which case the window may run partially off the screen 
	initially, and need to be centered on screen before using
Internet Explorer (IE4OrNewer) requires the file DialogFrame.asp, which loads the target file in a frame, 
	which allows links and form submissions to remain inside the modal window
The function returns whatever value an IE4OrNewer window returns, true for Mozilla5OrNewer, false otherwise 
	(such as for Netscape 4)
To have code run only when an action is performed in the popup window, and not when the popup window is simply 
	closed, it is cleaner across all browser types to call a function in the opening window to handle the 
	return of the popup when it is closed, rather than using return values, as in the following:
	if (opener.HandlePopUpReturn != null) opener.HandlePopUpReturn(); self.close();
*/
	if (popUpPageURL.toLowerCase().indexOf("popup=") == -1) {
		var queryDelimiter = "?"
		if (popUpPageURL.indexOf("?") >= 0) {
			queryDelimiter = "&"
		}
		popUpPageURL += queryDelimiter + "PopUp=True"
	}
	var windowProperties = "";
	var returnValue = false;
	var useModalDialogBox = IE4OrNewer && !AnyMac;
	if (useModalDialogBox) {
		windowProperties = "help:no;resizable:yes";
		windowProperties += ";dialogWidth:" + (document.body.offsetWidth - 20) + "px;dialogHeight:" + (document.body.offsetHeight - 20) + "px";
		if (IE5OrNewer) {
			if (window.screenLeft != null) {
				windowProperties += ";dialogLeft:" + (screenLeft + 10) + ";dialogTop:" + (screenTop + 10);
			}
		}
		returnValue = window.showModalDialog("DialogFrame.asp?Target=" + escape(popUpPageURL), "", windowProperties);
	} else {
		windowProperties = "scrollbars,resizable";
		if (Mozilla5OrNewer){
			windowProperties += ",modal";
			windowProperties += ",width=" + (outerWidth - 50) + ",height=" + (outerHeight - 75);
			if (screenX < screen.width - 100 && screenY < screen.height - 100) {
				windowProperties += ",left=" + (screenX + 35) + ",top=" + (screenY + 25);
			}
		}
		var myWin = window.open(popUpPageURL, windowName, windowProperties);
		if (Mozilla5OrNewer) {
			returnValue = true;
		}
	}
	return returnValue;
}

function ClosePopUp(popUpReturnValue) {
	var useModalDialogBox = IE4OrNewer && !AnyMac;
	if (useModalDialogBox) {
		if (popUpReturnValue != null) {
			self.returnValue = popUpReturnValue
		} else {
			self.returnValue = ""
		}
	} else if (opener != null) {
		if (opener.HandlePopUpReturn != null) {
			opener.HandlePopUpReturn(popUpReturnValue);
		}
	}
	self.close();
}

// Return text of selected item of a select element
function GetSelectElementText(elemId) {
try {
	var elemObj = GetDOMElement(elemId);
	return elemObj.options[elemObj.selectedIndex].text;
}
catch (e) {
}
}

// Set innerHTML of a given HTML element object
function SetElemObjInnerHTML(elemObj, elemInnerHTML) {
	if (elemObj) {
		elemObj.innerHTML = elemInnerHTML;
	}
}

// Set innerHTML of a given HTML element id
function SetElemInnerHTML(elemId, elemInnerHTML) {
	var elemObj = GetDOMElement(elemId);
	SetElemObjInnerHTML(elemObj, elemInnerHTML);
}

// Check the item with a given value in a collection
function SetCheckedValue(elemObj, val, adjHTML, adjHTMLBlank) {
try {
	var isChecked = false;
	if (elemObj) {
		if (elemObj.type == "radio") {
			if (elemObj.value == val) {
				DOMInsertAdjacentHTML(elemObj, "beforeBegin", adjHTML);
				elemObj.click();
				isChecked = true;
			}
		}
		else {
			for (var i = 0; i < elemObj.length; i++) {
				if (elemObj[i].value == val) {
					DOMInsertAdjacentHTML(elemObj[i], "beforeBegin", adjHTML);
					elemObj[i].click();
					isChecked = true;
				}
				else {
					DOMInsertAdjacentHTML(elemObj[i], "beforeBegin", adjHTMLBlank);
				}
			}
		}
	}
	return isChecked;
}
catch (e) {
}
}

// Set select element text
function SetSelectElementText(elemObj, txt) {
try {
	if (elemObj) {
		if (elemObj.options) {
			for (var i = 0; i < elemObj.options.length; i++) {
				if (elemObj.options[i].text == txt) {
					elemObj.selectedIndex = i;
					elemObj.onchange();
					break;
				}
			}
		}
	}
}
catch (e) {
}
}

// Disable element
function DisableElement(elemObj) {
try {
	if (elemObj) {
		if (elemObj.length > 0 && !elemObj.options) {
			for (var i = 0; i < elemObj.length; i++) {
				elemObj[i].disabled = true;
			}
		}
		else {
			elemObj.disabled = true;
		}
	}
}
catch (e) {
}
}

// Return event key code
function GetEventKeyCode(evnt) {
	return evnt.keyCode ? evnt.keyCode : evnt.charCode ? evnt.charCode : evnt.which ? evnt.which : void 0;
}

// Validate max characters in a given string
function ValidateMaxChar(str, maxChar) {
    var evntKeyCode = null;
    if (window.event) {
        evntKeyCode = GetEventKeyCode(window.event);
    }
    else if (jspellWindow && jspellWindow.event) {
        evntKeyCode = GetEventKeyCode(jspellWindow.event);
    }
    if (evntKeyCode != null) {
    	// Ignore keys such as Delete, Backspace, Shift, Ctrl, Alt, Insert, Delete, Home, End, Page Up, Page Down and arrow keys
        var escChars = ",8,17,18,19,33,34,35,36,37,38,39,40,45,46,";
    	if (escChars.indexOf(evntKeyCode) == -1) {
            if (str.length >= maxChar) {
                alert("You can enter " + maxChar + " characters max.");
                return false;
            }
        }
    }
    return true;
}

// Return page scroll top position
function GetPageScrollTop() {
	if (document.all) {
		return document.body.scrollTop;
	}
	else {
		return window.pageYOffset;
	}
}

// Set page scroll top position
function SetPageScrollTop(topPos) {
	if (document.all) {
		document.body.scrollTop = topPos;
	}
	else {
		window.pageYOffset = topPos;
	}
}

function IncludeJS(jsPath) {
	document.write("<script type=\"text/javascript\" src=\"" + jsPath + "\"></script>");
}

// IMPORTANT: CoreUtil.js has to be included with this JavaScript
IncludeJS('/CommonWeb/JavaScript/CoreUtil.js');
