function parseVSSComment(pComment, pTagname) { return(pComment.substring(pTagname.length+2, pComment.length-1)); }

var HEADER_Common_js = parseVSSComment("$Header: /CPNG/FrontEnd/CPNGWebsite/scripts/core.js 12    9/17/08 1:15p Tgruby1 $", "Header");
var ARCHIVE_Common_js = parseVSSComment("$Archive: /CPNG/FrontEnd/CPNGWebsite/scripts/core.js $", "Archive");
var REVISION_Common_js = parseVSSComment("$Revision: 12 $", "Revision");
var AUTHOR_Common_js = parseVSSComment("$Author: Tgruby1 $", "Author");
var DATE_Common_js = parseVSSComment("$Date: 9/17/08 1:15p $", "Date");


if (document.Global == null)
document.Global = {};


/*-------------------------

NULL / Empty Handling Functions

Functions for testing and handling 'null' values.

-------------------------*/

var NULL_DATE = new Date("1/1/100 00:00:00");

var CHAR_AMP = '&';
var CHAR_LT = '<';
var CHAR_GT = '>';

blnContextMenuOpened = false; // +PERF+, BK 6/16/2008, moved this var from QuickMenu.js because QuickTable.js was breaking
objSelectedTableRow = null;//Object used for right click in QuickTable.js  // +PERF+, BK 6/16/2008, moved this var from QuickTable.js because QuickMenu.js was breaking in Inbox
gobjInactiveTabContent = new Array();
/*
	Function: isEmpty

		Returns 'true' if pTest is empty: null, undefined, empty string, empty array.

	Parameters:
		pTest - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		Returns 'true' if pTest is empty: null, undefined, empty string, empty array.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function isEmpty(pTest) { 
	var blnEmpty = false;
	try { if (pTest==null) blnEmpty = true; } catch(e) {}
	try { if (pTest==undefined) blnEmpty = true; } catch(e) {}
	try { if (pTest=="") blnEmpty = true; } catch(e) {}
	try { if (pTest.length==0) blnEmpty = true; } catch(e) {}
	return blnEmpty;
	}

/*
	Function: isNotEmpty

		Equivalent to not isEmpty(pTest).

	Parameters:
		pTest - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		Returns 'true' if parameter pTest is not null, undefined, empty string, or empty array.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function isNotEmpty(pTest) { 
	var blnEmpty = true;
	try { blnEmpty = isEmpty(pTest) } catch(e) {}
	return (!blnEmpty); 
	}

/*
	Function: isNotNull

		Returns 'true' if parameter pTest is not null.

	Parameters:
		pTest - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		Returns 'true' if parameter pTest is not null.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function isNotNull(pTest) { 
	var blnNull = true;
	try { if (pTest!=null) blnNull = false; } catch(e) {}
	return (!blnNull); 
	}	



/*
	Function: isNull

		Returns first parameter (pTest) if (pTest) is not empty, otherwise returns second parameter (pReplace).

	Parameters:
		pTest - TODO  Put description here
		pReplace - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		Returns first parameter (pTest) if (pTest) is not empty, otherwise returns second parameter (pReplace).

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function isNull(pTest,pReplace) { 
	var vReturn;
	try { vReturn = pReplace } catch(e) {}
	try { if (isNotEmpty(pTest)) vReturn = pTest } catch(e) {}
	return vReturn; 
	}

/*
	Function: isBlank
	
		Returns true if string parameter (pstrIn) is blank (all spaces or \n or \t).

	Parameters:
		pstrIn - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns true if string parameter is blank (all spaces or \n or \t).

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function isBlank(pstrIn) 
{
	try
	{
		myStr = parmStr(pstrIn,'').toString();
		for(var intIndex = 0; intIndex < myStr.length; intIndex++) {
			var strChar = myStr.charAt(intIndex);
			if ((strChar != ' ') && (strChar != '\n') && (strChar != '\t')) return false;
			}
	}
	catch(e){
		HandleError(new AppError("[Common.js]isBlank", null, null, e));
		}
	
	return true;
	}

/*
	Function: forceNumeric
	
		Cancels keystroke if not numeric

	Parameters:
		none

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	nothing

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/	
function forceNumeric() {
	try {
		if (window.event.keyCode < 48 || window.event.keyCode > 57) {
			window.event.returnValue = false;
		}
	}
	catch(e){}
}

/*
	Function: parmStr
	
		Returns first parameter (pstrParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second string parameter (pstrDefault -- default is empty string).

	Parameters:
		pstrParm - TODO  Put description here
		pstrDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pstrParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second string parameter (pstrDefault -- default is empty string).

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmStr(pstrParm,pstrDefault) { 
	var vReturn = '';
	try {if (isNotEmpty(pstrDefault)) vReturn = pstrDefault;} catch(e) {}
	try {if (isNotEmpty(pstrParm)) vReturn = pstrParm;} catch(e) {}
	return vReturn; 
	}
/*
	Function: parmInt
	
		Returns first parameter (pintParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second integer parameter (pintDefault -- default is 0). 

	Parameters:
		pintParm - TODO  Put description here
		pintDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pintParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second integer parameter (pintDefault -- default is 0). 

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmInt(pintParm,pintDefault) { 
	var vReturn = 0;
	try {if (isNotNull(pintDefault)) vReturn = pintDefault;} catch(e) {}
	try {if (isNotNull(pintParm)) vReturn = pintParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(pintParm, isNull(pintDefault,0)); 

/*
	Function: parmLng
	
		Returns first parameter (plngParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second long parameter (plngDefault -- default is 0). 

	Parameters:
		plngParm - TODO  Put description here
		plngDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (plngParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second long parameter (plngDefault -- default is 0). 
	
	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmLng(plngParm,plngDefault) { 
	var vReturn = 0;
	try {if (isNotNull(plngDefault)) vReturn = plngDefault;} catch(e) {}
	try {if (isNotNull(plngParm)) vReturn = plngParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(plngParm, isNull(plngDefault,0)); 

/*
	Function: parmDbl

		Returns first parameter (pdblParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second double parameter (pdblDefault -- default is 0). 

	Parameters:
		pdblParm - TODO  Put description here
		pdblDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pdblParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second double parameter (pdblDefault -- default is 0). 

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmDbl(pdblParm,pdblDefault) { 
	var vReturn = 0.0;
	try {if (isNotNull(pdblDefault)) vReturn = pdblDefault;} catch(e) {}
	try {if (isNotNull(pdblParm)) vReturn = pdblParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(plngParm, isNull(plngDefault,0)); 

/*
	Function: parmDt

		Returns first parameter (pdtParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second date parameter (pdtDefault -- default is today). 

	Parameters:
		pdtParm - TODO  Put description here
		pdtDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pdtParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second date parameter (pdtDefault -- default is today). 

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmDt(pdtParm,pdtDefault) { 
	var vReturn = NULL_DATE;
	try {if (isNotNull(pdtDefault)) vReturn = pdtDefault;} catch(e) {}
	try {if (isNotNull(pdtParm)) vReturn = pdtParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(plngParm, isNull(plngDefault,0)); 

/*
	Function: parmBln

		Returns first parameter (pblnParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second Boolean parameter (pblnDefault -- default is false). 

	Parameters:
		pblnParm - TODO  Put description here
		pblnDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pblnParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second Boolean parameter (pblnDefault -- default is false). 

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmBln(pblnParm,pblnDefault) { 
	var vReturn = false;
	try {if (pblnDefault != null || pblnDefault != undefined) vReturn = pblnDefault;} catch(e) {}
	try {if (pblnParm != null || pblnParm != undefined) vReturn = pblnParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(plngParm, isNull(plngDefault,0)); 

/*
	Function: parmObj

		Returns first parameter (pobjParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second object parameter (pobjDefault -- default is null). 

	Parameters:
		pobjParm - TODO  Put description here
		pobjDefault - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
	Returns first parameter (pobjParm) if it is not "empty" (null, undefined, empty string, empty array), otherwise returns the second object parameter (pobjDefault -- default is null). 

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function parmObj(pobjParm,pobjDefault) { 
	var vReturn = null;
	try {if (isNotNull(pobjDefault)) vReturn = pobjDefault;} catch(e) {}
	try {if (isNotNull(pobjParm)) vReturn = pobjParm;} catch(e) {}
	return vReturn;
	}			// was: isNull(plngParm, isNull(plngDefault,0)); 

var APP_PAGENAME = "default.aspx";
var URL_CURPAGE = window.location.toString();
var URL_CURPAGE_BASE = "";
var URL_CURPAGE_PARAMS = "";

if (URL_CURPAGE.indexOf('?')>=0)												// if there is a '?'
	URL_CURPAGE_BASE = URL_CURPAGE.substring(0,URL_CURPAGE.indexOf('?')+1)							// grab everything through the '?'
else if (URL_CURPAGE.substring(URL_CURPAGE.length-1,URL_CURPAGE.length)== '/')						// No '?' and ends with '/', then its just virtual dir "i.e. http://host/virtdir/"
	URL_CURPAGE_BASE = URL_CURPAGE + APP_PAGENAME + "?"									// so grab it all, and add the APP_PAGENAME (and the '?')
else if (URL_CURPAGE.toLowerCase().substring(URL_CURPAGE.length - APP_PAGENAME.length,URL_CURPAGE.length)== APP_PAGENAME)	// No '?' and ends with pagename?
	URL_CURPAGE_BASE = URL_CURPAGE + '?';											// grab it all and add the '?'

if (URL_CURPAGE.length > URL_CURPAGE_BASE.length) {
	URL_CURPAGE_PARAMS = URL_CURPAGE.substring(URL_CURPAGE_BASE.length, URL_CURPAGE.length);
	}


/*
	Function: ParseURL

	TODO  Put a high level overview of ParseURL here.

	Parameters:
		pstrURL - TODO  Put description here
		pstrKey - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function ParseURL(pstrURL, pstrKey) {
	try {
		var strURL2Parse = ((parmStr(pstrURL).length)&&(parmStr(pstrKey,'').length))?pstrURL:URL_CURPAGE;
		var strKey = ((parmStr(pstrURL).length)&&(parmStr(pstrKey,'').length))?pstrKey:pstrURL;

		if (strURL2Parse.indexOf("#") >= 0)
			strURL2Parse = strURL2Parse.substr(0,strURL2Parse.indexOf("#"));
			
		var pos = 0;
		var str = "";
		if ((pos = strURL2Parse.indexOf(strKey))>=0) {
			if (strURL2Parse.indexOf("&",pos)>=0) 								// If there is a trailing &, then more values
				str = strURL2Parse.substring(pos + strKey.length + 1,strURL2Parse.indexOf("&",pos))	// So grab from (start + length + 1 (=)) to the &  (lngXX=...&lngYY=)
			else											// otherwise
				str = strURL2Parse.substring(pos + strKey.length + 1,strURL2Parse.length);				// grab from there on..
			return	str;
			}
		else
			return "";

		}
	catch (exception) {	
		alert ("[Common.js]parseURL: " + isNull(exception.description,exception.message))
		}	
	}

var APP_USERNO = ParseURL("UserNo");

/*
	Function: GetURLFor

	TODO  Put a high level overview of GetURLFor here.

	Parameters:
		pstrPagePortletID - TODO  Put description here
		pblnFullURL - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function GetURLFor(pstrPagePortletID,pblnFullURL) {
	try {
		/*
		+PERF+
		BK, 5.23.2008
		Changed from string concatenation to array push
		*/		
		var s = [];

		s.push((parmBln(pblnFullURL,false))?URL_CURPAGE_BASE:(APP_PAGENAME + "?"));
	
		var aryPieces = parmStr(pstrPagePortletID,'').split(".");
	
		if (aryPieces.length > 0) s.push("XCI=" + aryPieces[0] + "&");
		if (aryPieces.length > 1) s.push("XCE=" + aryPieces[1] + "&");
		if (aryPieces.length > 2) s.push("InstanceId=" + aryPieces[2] + "&");
	
		if (parmStr(APP_USERNO, '').length)
			s.push("UserNo=" + APP_USERNO + "&");

		try
		{
			if (document.SessionSalt != null)
			{
				s.push("SessionSalt=" + document.SessionSalt + "&");
			}
			else
			{
				if (ParseURL("SessionSalt").length)
					s.push("SessionSalt=" + ParseURL("SessionSalt") + "&");
			}
		}
		catch(e)
		{ // if session salt variable has been set, or passed on URL, then use it, otherwise, gracefully bail
		}			

		var sb = s.join("");
		if (sb.substring(sb.length-1, sb.length)=="&")
			sb = sb.substring(0,sb.length-1);
	
		return sb;	
		}
	catch (exception) {	
		alert ("[Common.js]GetURLFor: " + isNull(exception.description,exception.message))
		}	
	}
/*
	Function: DatesetSystemDateTime

	TODO  Put a high level overview of DatesetSystemDateTime here.

	Parameters:
		pdtToday - TODO  Put description here
		pdtGMT - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DatesetSystemDateTime(pdtToday, pdtGMT) 
{
	try
	{
		if (pdtToday)
		{
			Date.prototype.SystemDateTime = new Date(pdtToday); 
			Date.prototype.SystemDelta = Date.prototype.SystemDateTime - new Date();
			
			var msDiff = new Date(pdtToday) - new Date(pdtGMT);
			Date.prototype.timeZoneOffset = msDiff / (1000 * 60 * 60);
	
			var dToday = new Date(pdtToday); dToday.setHours(0); dToday.setMinutes(0); dToday.setSeconds(0); dToday.setMilliseconds(0);
			Date.prototype.SystemDate = dToday; 
		}
		else
		{
			var tempDate = new Date();
			Date.prototype.SystemDateTime = new Date(tempDate.valueOf() + tempDate.SystemDelta); 

			var dToday = new Date(tempDate.SystemDateTime);
			dToday.setHours(0); dToday.setMinutes(0); dToday.setSeconds(0); dToday.setMilliseconds(0);
			Date.prototype.SystemDate = dToday; 
		}
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DatesetSystemDateTime", null, null, e));
	}
}
/*
	Function: DateUpdateSystemTime

	TODO  Put a high level overview of DateUpdateSystemTime here.

	Parameters:
		pstrTime - TODO  Put description here
		pstrUTC - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DateUpdateSystemTime(pstrTime, pstrUTC)
{
	try
	{
	
		if (parmStr(pstrTime,'').length)
		{
			DatesetSystemDateTime(pstrTime, pstrUTC);

		}
		else
		{
			DatesetSystemDateTime();
		}

		try
		{
			if (this.clockElement != null)
			{
				setEl(this.clockElement, this.GetClockTime());
			}
			
		}
		catch(e)
		{
			return e;
		}
	
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DateUpdateSystemTime", null, null, e));
	}
}
/*
	Function: getEl

	Obtain a reference to an HTML DOM element by its ID.

	Parameters:
		pID - TODO  Put description here
		oDocument - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function getEl(pID, oDocument) 
{ 
	try
	{
		if(typeof(oDocument)=="undefined") {
			oDocument = document;
		}
		
		// Get all elements with the id
		if (oDocument.implementation && oDocument.implementation.hasFeature("HTML","2.0")) { return oDocument.getElementById(pID); }
		var objElements = oDocument.getElementsByName(pID);
		
		if (gobjInactiveTabContent.length == 0 || objElements.length == 1) {
			// If there are no hidden tabs, or only a single item exists with that id, return the first item found.
			return(objElements[0]);
		}
		else {
			// Otherwise, loop throught the inactive tabs to see if that element is hidden
			if (gobjInactiveTabContent.length > 0) {
				for (var intX = 0; intX < objElements.length; intX++) {
					var blnVisible = true;
					for (var intY = 0; intY < gobjInactiveTabContent.length; intY++) {					
						if (gobjInactiveTabContent[intY].contains(objElements[intX])) {
							// Element is found inside an inactive tab, so we ignore it.
							blnVisible = false;
							break;
						}
					}
					if (blnVisible) {
						return(objElements[intX]);
					}
				}
			}
		}
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]getEl", null, null, e));
	}
}



/*
function getElOld(pID, oDocument) 
{ 
	try
	{
		if(typeof(oDocument)=="undefined")
			oDocument = document;
		return oDocument.getElementById(pID); 
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]getEl", null, null, e));
	}
}
*/

/*
	Function: getElDescendant

	Get the descendant of a given element with name or id matching the request.

	Parameters:
		elParent - The parent element
		strName - The descendant's name or id

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		The matching element, if found

	Comments:

	See Also:
*/
function getElDescendant(elParent, strName) {
	var doc = (elParent.nodeType == 9 ? elParent : elParent.ownerDocument) || document, node = null;
	if (doc && doc.implementation && doc.implementation.hasFeature("XPath","3.0")) {
		node = doc.evaluate(".//*[@id='%' or @name='%']".replace(/%/g, strName), elParent, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
	}
	else if (elParent.all && elParent.all.namedItem) {
		node =  elParent.all.namedItem(strName);
	}
	return node;
}

/*
	Function: StringReplace

	TODO  Put a high level overview of StringReplace here.

	Parameters:
		pstrFind - TODO  Put description here
		pstrReplace - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function StringReplace(pstrFind, pstrReplace) {
	try {
	        var reg = new RegExp(pstrFind, "g");  
	        return this.replace(reg, pstrReplace);
		}
	catch (exception) {	
		alert ("[Common.js]StringReplace: " + isNull(exception.description,exception.message))
		}
	}
/*
	Function: hasClass

	Determine if an element has a (CSS) class.

	Parameters:
		el - The element
		strClass - The class name

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		Whether or not the class applies to the element

	Comments:

	See Also:
*/
function hasClass(el, strClass) {
	try { 
		return -1 != (' ' + el.className + ' ').indexOf(' ' + strClass + ' ');
	}
	catch(e) {
		HandleError(new AppError("[core.js]hasClass", null, null, e));
	}
}
/*
	Function: removeClass

	Remove a (CSS) class from an element.

	Parameters:
		el - The element
		strClass - The class name

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		Nothing

	Comments:

	See Also:
*/
function removeClass(el, strClass) {
	try { 
		var arrClass = el.className.split(' ');
		for (var i = arrClass.length - 1; i >= 0; i--) {
			if (arrClass[i] == strClass) {
				arrClass.splice(i, 1);
			}
		}
		el.className = arrClass.join(' ');
	}
	catch(e) {
		HandleError(new AppError("[core.js]removeClass", null, null, e));
	}
}
/*
	Function: addClass

	Add a (CSS) class to an element.

	Parameters:
		el - The element
		strClass - The class name

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		Nothing

	Comments:

	See Also:
*/
function addClass(el, strClass) {
	try { 
		if (hasClass(el, strClass)) { return; }
		var arrClass = el.className.split(' ');
		arrClass.push(strClass);
		el.className = arrClass.join(' ');
	}
	catch(e) {
		HandleError(new AppError("[core.js]addClass", null, null, e));
	}
}
/*
	Function: toggleClass

	Toggle the application of a (CSS) class to an element, adding or removing it as called for.

	Parameters:
		el - The element
		strClass - The class name

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		Nothing

	Comments:

	See Also:
*/
function toggleClass(el, strClass) {
	try { 
		if (hasClass(el, strClass)) {
			removeClass(el, strClass);
		}
		else {
			addClass(el, strClass);
		}
	}
	catch(e) {
		HandleError(new AppError("[core.js]toggleClass", null, null, e));
	}
}

/*
	Function: attachEventListener

	Non-destructively attach an event listener to an element.

	Parameters:
		el - the element
		strEvent - event to which fnListener applies
		fnListener - event listener function
		blnUseCapture - whether or not to handle the event in capturing (as opposed to bubbling) phase [DEFAULT false]

	Returns:
		whether or not the listener was successfully attached
*/
function attachEventListener(el, strEvent, fnListener, blnUseCapture) {
	try {
		el = el || {};
		strEvent = 'on' + ('' + strEvent).toLowerCase().replace(/^on/, '');
		if (!fnListener || ('function' != (typeof fnListener) && !(fnListener instanceof Function))) {
			return null;
		}

		try {
			el.addEventListener(strEvent.substring(2, strEvent.length), fnListener, blnUseCapture ? true : false);
			return true;
		}
		catch (x) {
			return el.attachEvent(strEvent, fnListener);
		}
	}
	catch(e) {
		HandleError(new AppError("[core.js]attachEventListener", null, null, e));
	}
}

/*
	Function: detachEventListener

	Detach a previously-added event listener from an element.

	Parameters:
		el - the element
		strEvent - event to which fnListener applies
		fnListener - event listener function
		blnUseCapture - whether or not the event was handled in capturing (as opposed to bubbling) phase [DEFAULT false]

	Returns:
		whether or not the listener was successfully removed
*/
function detachEventListener(el, strEvent, fnListener, blnUseCapture) {
	try {
		el = el || {};
		strEvent = 'on' + ('' + strEvent).toLowerCase().replace(/^on/, '');
		if (!fnListener || ('function' != (typeof fnListener) && !(fnListener instanceof Function))) {
			return null;
		}

		try {
			el.removeEventListener(strEvent.substring(2, strEvent.length), fnListener, blnUseCapture ? true : false);
			return true;
		}
		catch (x) {
			el.detachEvent(strEvent, fnListener);
			return true;
		}
	}
	catch(e) {
		HandleError(new AppError("[core.js]detachEventListener", null, null, e));
	}
}

/*
	Function: setDocumentTitle

	This function is used to update the title of the window (Document).  This title is also displayed for the tab in multi-tabbed browsers.  It is also used for things like the Flashlist. 

	Parameters:
		pstrTitle - The title of this page, or this view of the page
		pblnAddPtName - A boolean to indicate whether the patient's name should be appended to the end (NOTE: This should be pulled into PatientPages and used as an override to this function.)

	Exceptions:
		o None.  All are caught and tossed

	Returns:
		None

	Comments:

	See Also:
*/
function setDocumentTitle(pstrTitle, pblnAddPtName) {
	try { 
		document.title = pstrTitle;
		if (parmBln(pblnAddPtName)) {
			try 
			{ 
				var nodePtName;
				if (getEl('PtHeader_PtID_PatientName')!= null)
				{
					nodePtName=getEl('PtHeader_PtID_PatientName');
					}
				else
				{
					nodePtName=getEl('PtHeader_PtID_PatientNameNonCollapse');
				}
				if (nodePtName != null)
				{
					document.title += ' for ' + nodePtName.innerHTML;
				}
				else
				{	// presumably, it just hasn't loaded.  try again in a bit, but let them know that we are trying.
					document.title += ' for (Loading...)';
					newTimeout('setDocumentTitle_AddPtName', "setDocumentTitle(\"" + pstrTitle + "\", true);", 100) 
				}	 
			} 
			catch(e) { 
				/* it was worth a try */ 
				}
			}
		}
	catch(e) {
		HandleError(new AppError("[Common.js]setDocumentTitle", null, null, e));
		}
	}
/*
	Function: setElURL

	TODO  Put a high level overview of setElURL here.

	Parameters:
		pID - TODO  Put description here
		pURL - TODO  Put description here
		pPost - TODO  Put description here
		pblnIsXML - TODO  Put description here
		pblnAsync - Boolean. True = perfome setElURL asynchonously. False=synchronously.
		
	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setElURL(pID, pURL, pPost, pblnIsXML, pblnAsync) 
{
	try
	{	
		if (isNotEmpty(pID)) {
			if (isNotEmpty(pURL)) {
				var XML_NONE = 0;
				var XML_MICROSOFT = 1;
				var XML_MOZILLA = 2;
				
				var intXML = XML_NONE; 
				var objXMLSrv = null;
				var strHTML = '';		
//				startWait();	//show 'wait' icon to user
				
				// See if we are Microsoft.XMLHTTP compliant
				try {	
					objXMLSrv = new ActiveXObject("Microsoft.XMLHTTP"); 
					if (objXMLSrv != null) intXML = XML_MICROSOFT;
					} catch(e) { }	// don't care about any error
			
				// See if we are Mozilla.XMLHttpRequest compliant
				try {
					if (objXMLSrv == null) {
						objXMLSrv = new XMLHttpRequest();
						if (objXMLSrv != null) intXML = XML_MOZILLA;
						}
					} catch(e) { }	// don't care about any error
			
				// add any other flavors that come along...
				//try {
				//	if (objXMLSrv == null) {
				//		objXMLSrv = blahblahblah
				//		if (objXMLSrv != null) intXML = XML_;
				//		}
				//	} catch(e) { }	// don't care about any error
				
				var isPost = (parmStr(pPost,'').length);
				var isAsync = (parmBln(pblnAsync,false));
			  
				function setIt()//try to actually perform the set
				{
					try {
//						endWait();
						if (parmBln(pblnIsXML)) setElXMLText(pID, strHTML);
						else setEl(pID, strHTML);
					}
					catch(e) 
					{ 
						alert ("[Common.js]setElURL.setIt: The following error occurred while attempting to set the Element ID [" + pID + "]\nwith the contents of the URL [" + pURL + "] :\n" + isNull(e.description,e.message))
					}				
				};

				switch(intXML) {
					case XML_MICROSOFT: 
						try {
							objXMLSrv.Open((isPost?'POST':'GET'),pURL,isAsync);
							if (isPost)
								objXMLSrv.setRequestHeader("Content-Type", "text/xml");			// do this to assist application in determining the type of request.
							if(isAsync)
							{
								objXMLSrv.onreadystatechange = function()
								{
									if(objXMLSrv.readyState != 4)	return;												
									else
									{				
										strHTML = objXMLSrv.responseText;													
										setIt();
									}
								};	
								objXMLSrv.Send(parmStr(pPost,null))										
							}
							else
							{
									objXMLSrv.Send(parmStr(pPost,null))
									strHTML = objXMLSrv.responseText;										
									setIt();					
							}
							}
						catch(e) { 
//							endWait();
							alert ("[Common.js]setElURL[Microsoft]: " + isNull(e.description,e.message))
							}
						break;
			
					case XML_MOZILLA: 
						try {
							objXMLSrv.open((isPost?'POST':'GET'), pURL, isAsync);
							if (isPost)
								objXMLSrv.setRequestHeader("Content-Type", "text/xml");			// do this to assist application in determining the type of request.
							if(isAsync)
							{
								objXMLSrv.onreadystatechange = function()
								{
									if(objXMLSrv.readyState != 4)	return;												
									else
									{				
										strHTML = objXMLSrv.responseText;													
										setIt();											
									}
								};	
								objXMLSrv.send(parmStr(pPost,null));							
							}
							else
							{
								objXMLSrv.send(parmStr(pPost,null));
								strHTML = objXMLSrv.responseText;										
								setIt();					
							}
							}
						catch(e) { 
//							endWait();
							alert ("[Common.js]setElURL[Mozilla]: " + isNull(e.description,e.message))
							}
						break;

					default:	//XML_NONE
						{
//							endWait();
							alert ("[Common.js]setElURL: XML does not appear to be supported on this client.");
						}
			
					}
//					endWait();
				}
			else {
				alert ("[Common.js]setElURL: No URL was given for this command.\nThe requested Element ID was: [" + pID + "]");
				}
			}
		else {
			if (isNotEmpty(pURL))
				alert ("[Common.js]setElURL: No Element ID was given for this command.\nThe requested URL was: [" + pURL + "]")
			else
				alert ("[Common.js]setElURL: No Element ID or URL was given for this command.")
			}		
	}
	catch(e)
	{
		HandleError(new AppError("[core.js]setElURL", null, null, e));
	}
}	
/*
	Function: setEl

	Set a given DOM element's innerHTML to the given HTML fragment string.

	Parameters:
		pID - TODO  Put description here
		pHTML - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setEl(pID, pHTML) 
{ 
	try
	{
		var el = getEl(pID); 
		if (el!=null)
		{
			if (/^input$/i.test(el.nodeName))
			{	// el is an INPUT element
				el.value = (pHTML || '');
			}
			else 
			{
				el.innerHTML = (((pHTML!=null)&&(pHTML!=undefined))?pHTML:''); 
			}
		}
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]setEl", null, null, e));
	}
}
var _setElXML_WorkingXML;

/*
	Function: setElXML

	Set a given DOM element's inner HTML to the resulting XHTML (XML compliant HTML) obtained from a given XML document/node.

	Parameters:
		pelDest - TODO  Put description here
		pnodeSrc - TODO  Put description here
		pblnThorough - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setElXML(pelDest, pnodeSrc, pblnThorough) {
	try {
		// If they requested using the "old method", then use it.
		if (parmBln(pblnThorough)) {
			return setElXMLThorough(pelDest, pnodeSrc);
			}

		if ((pelDest!=null)&&(pnodeSrc!=null)) {

			if (pelDest.innerHTML == null) {
				pelDest = getEl(pelDest);	// probably was name, not el
				}

			if (pelDest == null)			// probably was the name of an el that does not exist.
				throw(new AppError(null, null, "The destination DOM element (" + pelDest + ") could not be found.", null));

			// Start by clearing the previous contents
			pelDest.innerHTML = '';

			//var pnodeCopy = pnodeSrc.cloneNode(true);

			/*var nlEXE = pnodeCopy.selectNodes(".//script|.//xml")	// grab any "executable" blocks (scripts, xml, etc.)

			for (var i=0; i<nlEXE.length; i++) {			// and remove them (to be processed later.
				//pnodeCopy.removeChild(nlEXE[i]);		//... except that they don't seem to want to be removed (Node is not a child of this node.... which it is.)
				}*/

			//pelDest.innerHTML = XML2XHTML(pnodeCopy);		// after we tweak it for XHTML...
			pelDest.innerHTML = cleanSelfClosingHtml(serializeXml(pnodeSrc));

			// Now to process the "executables"...
			
			
			/* Handle "script" tags - OLD WAY
			var nlScripts = pnodeSrc.selectNodes(".//script[count(@defer) = 0]")	
			for (var i=0; i<nlScripts.length; i++) {
				var oNewNode;

				oNewNode = document.createElement(nlScripts[i].xml);
				oNewNode.text = nlScripts[i].text
				var head = document.getElementsByTagName('head').item(0)			// grab a ref to <HEAD>
				head.appendChild(oNewNode);
				}
				*/
				
			// New way of handling scripts tags.  Old way does not allow any xml tags inside of the script tag.
			var nlScripts = pelDest.getElementsByTagName("script");
			/*precompat*/ var arrClonedNodes = new Array();
			for (var i=0, vars, reSplit = /^var\s+|\s*,\s*|\s*;/g, promoteVars; i < nlScripts.length; i++)
			{
				try {
					promoteVars = ';\n\ntry{\n';
					vars = collapseJavascript(nlScripts[i].text, true).split(reSplit);
					for (var j = 0; j < vars.length; j++) {
						promoteVars += ('' == vars[j] ? '' : /*"try{" +/**/ "window['" + vars[j] + "']=" + vars[j] + ";"
								/*+ "}catch(e){HandleError(new AppError('[core.js]setElXML: Script var " + vars[j] + ": ',null,null,e));}"/**/ + "\n");
					}
					promoteVars += "void(0);}catch(e){HandleError(new AppError('[core.js]setElXML: Script var: ',null,null,e));}";
					try{(new Function(nlScripts[i].text + promoteVars)).call(null);}catch(x){throw {description: [x,promoteVars.replace(/\n+/g,' ')].join('::')};}
				}
				catch(x) {
					pnodeSrc = {xml: serializeXml(nlScripts[i]) || nlScripts[i].outerHTML || serializeXml(pnodeSrc)};
					throw {description: "Script: " + (x.description || x.message || x)};
				}
				/*precompat*/
					var oCloneNode = nlScripts[i].cloneNode(true);
					oCloneNode.text = nlScripts[i].text;
					arrClonedNodes.push(oCloneNode);
				/*precompat*/
			}
			/*precompat
				var head = document.getElementsByTagName('head').item(0)			// grab a ref to <HEAD>
				for (var i = 0; i < arrClonedNodes.length; i++)
				{
					head.appendChild(arrClonedNodes[i]);
				}
			/*precompat*/

			// Handle XML blocks
			var nlXML = xpathSelectXMLNodes(pnodeSrc, ".//xml")
			for (var i=0; i<nlXML.length; i++) {

				// Build a working XML document
				//_setElXML_WorkingXML = new ActiveXObject("Msxml2.DOMDocument.4.0");

				// Load it with the given XML
				//_setElXML_WorkingXML.loadXML(nlXML[i].firstChild.xml); 

				/*
				+PERF+
				BK, 5.23.2008
				Removed an eval() from next statement
				*/
				// Create a document wide pointer to it.
				document[getXMLAttribute(nlXML[i], "id","")] = parseXml(serializeXml(nlXML[i].firstChild));

				// Update the attributes of the XML object....
				//for (var j=0; j<nlXML[i].attributes.length; j++) {
				//	var strAttribName = nlXML[i].attributes[j].name.toString().jsEncode();
				//	var strAttribValue = nlXML[i].attributes[j].text.toString().jsEncode();
				//	var q = "setXMLAttribute(document." + getXMLAttribute(nlXML[i], "id","") + ",\"" + strAttribName + "\",\"" + strAttribValue + "\");"
				//	eval(q);
				//}
				// ....doesn't seem to work.

				// Clear our worker-bee
				//_setElXML_WorkingXML = null;

				}

			// add any other tags that need "special handling" here.

			}
		}
	catch (exception) {	
		alert ("[Common.js]setElXML: " + isNull(exception.description,exception.message) + "\nSource:\n\n" + pnodeSrc.xml)
		}
	}
function startWait(){
	document.body.style.cursor = "wait";
	window.status = "Processing...";
}
function endWait(){
	document.body.style.cursor = "default";
	window.status = "";
}

/*
	Function: setElXMLThorough

	TODO  Put a high level overview of setElXMLThorough here.

	Parameters:
		pelDest - TODO  Put description here
		pnodeSrc - TODO  Put description here
		pstrParentNodeType - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setElXMLThorough(pelDest, pnodeSrc, pstrParentNodeType) {
	try {
		if ((pelDest!=null)&&(pnodeSrc!=null)) {
			if (parmStr(pstrParentNodeType,'')=='')			// first call into the function
				pelDest.innerHTML = '';				// 	so, clear the contents
		
			//alert(pnodeSrc.xml);
			
			for (var i=0; i< pnodeSrc.childNodes.length; i++) {
				var oNode = pnodeSrc.childNodes.item(i);
		
				//alert(oNode.xml);
		
				var oNewNode;
		
				if (oNode.nodeType == 1) {
					var sNode = ["<" + oNode.nodeName];
					for (var j=0; j< oNode.attributes.length; j++) {
						sNode.push(" " + oNode.attributes.item(j).nodeName + "=\"" + oNode.attributes.item(j).nodeValue + "\""); 
						}
					sNode.push(">");
		
					//alert(sNode);
					
					oNewNode = document.createElement(sNode.join(""));
		
					pelDest.appendChild(oNewNode);
			
					}
				else {
					if (parmStr(pstrParentNodeType,'').toLowerCase() == "script") {		// script nodes store their contents in their .text, other properties will cause run-time error
						pelDest.text = oNode.text
					}
					else {
						//alert(oNode);
						pelDest.innerHTML += oNode.xml				// most other blocks just store in .innerHTML
						}
					}
		
				// if the source node has children...
				if (oNode.childNodes.length) {
					// if this is a "standard" node type, recursively add the children
					if (oNode.nodeName.toLowerCase() != "xml") {
						setElXMLThorough(oNewNode, oNode, oNode.nodeName)
						}
					// if this is an XML node, simply have the new XML "document" load the children (always in a root firstChild)
					else {
						//alert("loadXML: " + oNode.firstChild.xml);
						oNewNode.loadXML(oNode.firstChild.xml);
						}
					}				
				
				}	
			}
		}
	catch (exception) {	
		alert ("[Common.js]setElXMLThorough: " + isNull(exception.description,exception.message) + "\nSource:\n\n" + pnodeSrc.xml)
		}
	}
/*
	Function: setElXMLText

	TODO  Put a high level overview of setElXMLText here.

	Parameters:
		pstrDestEl - TODO  Put description here
		pstrXMLSrc - TODO  Put description here
		pblnThorough - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setElXMLText(pDestEl, pstrXMLSrc, pblnThorough) {
	try {
		var xmlTemp = parseXml(pstrXMLSrc);
		if (xmlTemp) {
			var elDest = ('string' == typeof pDestEl ? getEl(pDestEl) : pDestEl);
			if (elDest) {
				setElXML(elDest, xmlTemp.documentElement, parmBln(pblnThorough));
			}
			else {
				alert("[core.js]setElXMLText: Destination element ('" + pDestEl + "') not found.");
			}
		}
		else {
			alert("[core.js]setElXMLText: Source HTML did not properly load.");
		}
		xmlTemp = null;
	}
	catch (exception) {	
		alert("[core.js]setElXMLText: " + isNull(exception.description,exception.message))
	}
}


function setElPortion(pID, pPortionId)
{
	return setElURL(pID, '?' + escape(pPortionId) + '&XCI=WebSite_Portion&XCE=ViewPortion', null, true, false);
}



/*
	Function: logdebug

	Write a message to a debug log window

	Parameters:
		message - The message to log (can be string or object - if object, function displays object property values and types)
		
	Returns:
		Nothing

	Comments:
	This can be used to do some "printf" type of debugging.  This is usually done via alert(), but alert() can hide concurrency issues and is also really annoying.
	(start example)
for (var i = 0; i < 10; i++)
{
    logdebug("This is log message #" + i);
}
	(end)
*/
function logdebug(message, pPause, mode)
{
	if (mode != "array" && (!logdebug.window_ || logdebug.window_.closed))//create window
	{
		//window name dependent upon environment allows open logdebug window in multiple environments (no 'access is denied' error)
		var winName = (typeof document.nameProp == "string") ? (document.nameProp.replace(/\s*\W*/g,"")) : "DebugLog";
		var winTitle = winName == "DebugLog"?"Debug Log":"Debug Log - " + document.nameProp;		
		var win = window.open("", winName, "width=400,height=400,scrollbars=yes,resizable=yes,status=no,location=no,menubar=no,toolbar=no");
		if (!win) return;
		var doc = win.document;
		doc.write("<html><head><title>"+winTitle+"</title></head><body></body></html>");
		doc.close();
		logdebug.window_ = win;
	}
	var returnArray = []; //return logdebug output as array
	
	if(typeof message == "undefined") message = "undefined";
	if (message == null)
	{
		if (aryWatchObjects.length)
		{
			for (i=0; i< aryWatchObjects.length; i++)
			{
				if (parmStr(aryWatchObjects[i],'').length)
				{
					try 
					{
						/*
						+PERF+
						BK, 5.23.2008
						Removed an eval() from next 4 logdebug statements
						*/							
						logdebug('=======' + aryWatchObjects[i] + '=======');
						logdebug(" + aryWatchObjects[i] + ");
						logdebug('======= /' + aryWatchObjects[i] + '=======');
					}
					catch(e)
					{
						logdebug('*** ERROR: Could not watch variable [' + aryWatchObjects[i] + '] ****');
					}								
				}
			}
		}
		else writeToWindow("null");			
	}
	else
	{
		if(typeof message == "object") //deal w/ objects
		{ 
			try	// Node
			{ 
				var root = message.selectSingleNode("/*[1]"); 	// skip to catch if method fails
				var xpath = getXPath(message);
				if(xpath == undefined) { xpath = getXPath(root); message = root; } //more informative than undefined
				
				// Display node name				
				var objMessage = "[node] " + message.nodeName; 	
				writeToWindow(objMessage);			
				
				// Display node's attributes				 
				var atts = message.attributes;	
				for(var i = 0; i < atts.length; i++)
				{
					objMessage = "[attribute] " + atts[i].name + " = " + atts[i].value;
					writeToWindow(objMessage, 4);		
				}  
				
				// Display node data
				if(message.firstChild && message.firstChild.data){
				objMessage = "[data] " + message.firstChild.data;
				writeToWindow(objMessage, 4);	
				}
				
				// Display node xpath
				objMessage = "[xpath] " + xpath; 	
				writeToWindow(objMessage, 4);	
								
				// Display node's xml string		
				objMessage = "[xml] " + message.xml;
				writeToWindow(objMessage, 4);		 
			} 
			catch(err)	// Javascript object
			{ 		
				jsObject(message);
			}
		}
		else //deal with strings
		{
			writeToWindow(message);
		}
		
	if (parmBln(pPause, false))
		alert('You have debug message(s).\nPlease press any key to continue...');
	}
	
	function jsObject(message) //write properties of javascript object
	{
		try{
			 var objMessage = ""; // Get property names of the object and sort them alphabetically
			 var names = []; 
			 			 
			 for(var name in message) names.push(name); 
			 names.sort();
					
				// Now loop through those properties
					
		 	for(var i = 0; i < names.length; i++) 
			{ 
		    var name, value, type;
		    name = names[i];
			
		    try{ 
		         value = message[name];
		 				 type = typeof value;
		 			 }
		    catch(e){ 
		            value = "unknown value";
		 					  type = "unknown";
		 			 }
			
		   if (type == "function") // Display function name and arguments
		   { 
		      value = value.toString(); 
		      value = value.substring(0,value.indexOf("{"));
		   } 
		    objMessage = "[" + type + "] " + name + " = " + value; 
		    
		    writeToWindow(objMessage);
			}
		}		
		catch(e){}
	}	
	function writeToWindow(str, iIndent){ //iIndent is # of spaces to indent str
		if(!iIndent) iIndent = 0;
		var logLine = logdebug.window_.document.createElement("div");

		if(str == "") logLine.appendChild(logdebug.window_.document.createElement("<br>"));
		else
		{
			if(mode == "html")
			{
				logLine.innerHTML = message;
			}
			else
			{
				var textLine = logdebug.window_.document.createElement((iIndent)?"pre":"span");
				for(var i = 0; i < iIndent; i++)
					textLine.appendChild( logdebug.window_.document.createTextNode(' ') );
			
				textLine.appendChild(logdebug.window_.document.createTextNode(str));
				logLine.appendChild(textLine);
			}
		}
		if(mode == "array") returnArray.push(logLine);
		else logdebug.window_.document.body.appendChild(logLine);		
	}
	if(mode == "array") return returnArray;
}
/*
	Function: DatetoDate

	TODO  Put a high level overview of DatetoDate here.

	Parameters:
		pblnFull - TODO  Put description here
		pblnPad - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DatetoDate(pblnFull,pblnPad) 
{
	try
	{
		if (this.valueOf()!=NULL_DATE.valueOf()) {
			if (pblnFull)
				return (this.toMonth() + " " + this.getDate() + ", " + this.getFullYear());

			if (pblnPad) {
				var str = '';
				if ((this.getMonth()+1)<10) str += '0';
				str += (this.getMonth()+1) + "/";
				if (this.getDate()<10) str += '0';
				str += (this.getDate()) + "/" + (this.getFullYear());
				return str;
				}
			
			return ((this.getMonth()+1) + "/" + this.getDate() + "/" + this.getFullYear());
			}
		else return ("-N/A-");
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DatetoDate", null, null, e));
	}
}
/*
	Function: DatetoDateTimeAMPM

	TODO  Put a high level overview of DatetoDateTimeAMPM here.

	Parameters:
		pFull - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DatetoDateTimeAMPM(pFull) 
{ 
	try
	{
		return ((this.valueOf()!=NULL_DATE.valueOf())?(this.toDate(pFull) + " " + this.toTime(true)):("-N/A-")); 
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DatetoDateTimeAMPM", null, null, e));
	}
}
/*
	Function: DatetoTime

	TODO  Put a high level overview of DatetoTime here.

	Parameters:
		pFull - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DatetoTime(pFull) 
{
	try
	{
		if (this.valueOf()!=NULL_DATE.valueOf()) {
			var strMins = this.getMinutes().toString();
			if (strMins.length == 1) strMins = "0" + strMins;
		
			if (isEmpty(pFull)) {
				var strHrs = this.getHours().toString();
				return (((strHrs.length == 1)?("0"):("")) + strHrs + ":" + strMins);
				}
			else
				return (((this.getHours()%12)?(this.getHours()%12):12) + ":" + strMins + " " + ((this.getHours()<12)?"am":"pm"));
			}
		else return ("-N/A-");
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DatetoTime", null, null, e));
	}
}
/*
	Function: DateGetClockTime

	TODO  Put a high level overview of DateGetClockTime here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function DateGetClockTime()
{
	try
	{
		var oDate = new Date().SystemDateTime;
		
		return(oDate.toDateTimeAMPM()); 
	
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]DateGetClockTime", null, null, e));
	}
}

/*
	Function: HideDIVHelper

	TODO  Put a high level overview of HideDIVHelper here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function HideDIVHelper() {
	try {
		hideEl('DIVHelper');
		}
	catch(e) {
		HandleError(new AppError("[Menu.js]HideDIVHelper", null, null, e));
		}
	}
/*
	Function: hideEl

	Hide a given DOM element.

	Parameters:
		pID - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function hideEl(pID) 
{ 
	try
	{
		if(getEl(pID)!=null) 
			getEl(pID).style.display = 'none'; 
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]hideEl", null, null, e));
	}
}
/*
	Function: showEl

	Show a given DOM element.

	Parameters:
		pID - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function showEl(pID) 
{
	try
	{ 
		if(getEl(pID)!=null) 
		{ 
			getEl(pID).style.display = ''; 
			getEl(pID).style.visibility = 'visible'; 
		}
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]showEl", null, null, e));
	}
}

function htmlModalPut()
{
	try
	{
		var divModal = document.createElement("div");
		divModal.id = "ModalScreen";
		divModal.style.cssText = ("display: none; z-index: 999; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%;");
		divModal.onresize = function(){	divModal.style.display='none'; divModal.style.display=''; }
		
		/*
		+PERF+
		BK, 5.23.2008
		Changed from string concatenation to array push
		*/	
		// The onresize events were added to handle relatively positioned objects in modal portlets.  A redraw is necessary when the portlet resizes.
		var htmlModal = [];
		htmlModal.push("<table border=\"0\" width=\"100%\" height=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tbody>");
		htmlModal.push("<tr><td colspan=\"2\" width=\"100%\" height=\"1\" align=\"center\" valign=\"center\"><img src=\"images/spacer.gif\" width=\"100%\" height=\"1\" alt=\"\"/></td></tr>");
		htmlModal.push("<tr><td width=\"1\" height=\"100%\" align=\"center\" valign=\"center\"><img src=\"images/spacer.gif\" width=\"1\" height=\"100%\" alt=\"\"/></td>");
		htmlModal.push("<td width=\"100%\" height=\"100%\" align=\"center\" valign=\"center\">");
		htmlModal.push("<table onresize=\"this.style.display='none'; this.style.display='';\" id=\"ModalTable\"><tbody></tbody></table>");
		htmlModal.push("</td></tr></tbody></table>");
		divModal.innerHTML = htmlModal.join("");
		document.body.appendChild(divModal);		
	}
	catch(e)
	{
		HandleError(new AppError("[Core.js]htmlModalPut", null, null, e));
	}
}

function divHelperPut()
{
	try
	{
		var iframe = document.createElement("iframe");
		iframe.id = "DIVHelper";
		iframe.src = "javascript:false;";
		iframe.scrolling = "no";
		iframe.frameborder = "0";
		iframe.onmouseover = HideDIVHelper;
		iframe.onmouseout = HideDIVHelper;
		iframe.style.cssText = "position: absolute; top: 0px; left: 0px; display: none;";
		document.body.appendChild(iframe);
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]divHelperPut", null, null, e));
	}
}
var _CancelKeyPress_ = false;

/*
	Function: keyPress

	TODO  Put a high level overview of keyPress here.

	Parameters:
		e - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function keyPress(e) 
{        
	try
	{
		if (!(_CancelKeyPress_==true)) {
			var charCode = (isNav) ? e.which : window.event.keyCode;
			var altKey = (isNav) ? (e.modifiers && Event.ALT_KEY) : window.event.altKey;
			var ctrlKey = (isNav) ? (e.modifiers && Event.CTRL_KEY) : window.event.ctrlKey;
			var shiftKey = (isNav) ? (e.modifiers && Event.SHIFT_KEY) : window.event.shiftKey;
			var myEvent = (isNav) ? e : window.event;
	//alert(charCode);

			switch (charCode) {	
				
				case 9:				// Ctrl+Shift+I
					try { goURL("qinit.aspx"); } catch(e) { }
					window.event.cancelBubble = true;
					return false;					
					break;


				case 4:				// Ctrl+Shift+D
					try { 
						toggleEl('Common_Portlet.Debug');
						var el = getEl('Common_Portlet.Debug.Text');
						try { el.focus() } catch(e) { }
						} catch(e) { }
					window.event.cancelBubble = true;
					return false;
					break;



//				case 13:				// Enter
//					//if (document.forms.length>0) document.forms[0].submit();	// Presume Form[0] 
//					try { validateForm(); } catch(e) { }
//					return false;
//					break;
				case 27:				// Esc
					HideDIVHelper();
					try { balloonHelp(''); } catch(e) {}	// if balloonHelp is defined, hide it.
					// if there is a barset called 'StructureMenu', then tell it to hide all bars.... otherwise, don't worry about it.
					try { if (document.bars['StructureMenu'] != undefined) document.bars['StructureMenu'].hideall(); }  catch(e) { }													

					return false;
					break;

				case 112:				// F1 key  (NOTICE: The F1 key can be given an event, but IE Help will ALSO run if just F1, or Ctrl+F1, which is typically not desired)
					if (altKey)
					{
						openHelp();
						window.event.cancelBubble = true;
						return false;
					}
					else
					{
						return true;
					}
					break;

				case 113:				// F2 key
					break;


				case 192:				// ~
					if (altKey) {			// Alt+~
						try { showWindows(); } catch(e) { }
						return false;
						}
					break;
				}


			}
		return true;
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]keyPress", null, null, e));
	}
}

/*
	Function: keyDown

	TODO  Put a high level overview of keyDown here.

	Parameters:
		e - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function keyDown(e) 
{        
	try
	{
		if (!(_CancelKeyPress_==true)) {
			e = e || window.event;
			var charCode = e.which || e.keyCode;
			var altKey = e.altKey || (e.modifiers && 'undefined' != typeof(Event) && Event.ALT_KEY);
			var ctrlKey = e.ctrlKey || (e.modifiers && 'undefined' != typeof(Event) && Event.CTRL_KEY);
			var shiftKey = e.shiftKey || (e.modifiers && 'undefined' != typeof(Event) && Event.SHIFT_KEY);
			var myEvent = e;
	//if (charCode >= 20) alert(charCode);

			document.Global.ctrlKey = ctrlKey;
			
			switch (charCode) {	
				
				case 8:				// Backspace  
					var targ;
					try {if (myEvent.target) targ = myEvent.target;} catch(innerE) {}
					try {if (myEvent.srcElement) targ = myEvent.srcElement;} catch(innerE) {}
					try {if (targ.nodeType == 3) /* defeat Safari bug */ targ = targ.parentNode;} catch(innerE) {}

					if ((targ.nodeName.toLowerCase() != "input") && (targ.nodeName.toLowerCase() != "textarea"))
					{
						if (window.confirm("You have attempted to leave this page by pressing the [Backspace] button.\n\nDo you wish to continue to your previous page?\n(Any unsaved work will be lost)"))
						{
							// Yes, continue
							// do nothing, let it go.
							return true;
						}
						else
						{ 
							// Do NOT continue
							myEvent.cancelBubble = true;
							try { myEvent.stopPropagation(); }catch(x){}
							try { myEvent.preventDefault(); }catch(x){}
							return false;
						}
					}
					break;

				/*                                                              
				case 81:				// Ctrl+Shift+Q         
					if (ctrlKey && shiftKey)                                
					{                                                       
						try { goURL("qinit.aspx"); } catch(e) { }       
						window.event.cancelBubble = true;               
						return false;					
					}                                                       
					break;                                                  
				*/
				

				}


			}
		return true;
	}
	catch(e)
	{
		HandleError(new AppError("[core.js]keyDown", null, null, e));
	}
}
/*
	Function: goURL

	TODO  Put a high level overview of goURL here.

	Parameters:
		strURL - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function goURL(strURL) 
{
	try
	{
		window.location= strURL;
		return false;
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]goURL", null, null, e));
	}
}

/*
	Function: noScrollbars

	TODO  Put a high level overview of noScrollbars here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function noScrollbars() { if(document.body == null){setTimeout(noScrollbars,0);return;}if (document.body.scroll!= undefined) { document.body.scroll="no"; } else { document.width= window.innerWidth; document.height=window.innerHeight; } }

attachEventListener(window, "onload", htmlModalPut);
attachEventListener(window, "onload", divHelperPut);
function setOnKeypress()
{
	document.onkeypress = keyPress;
	document.body.onkeypress = keyPress;
}
function setOnKeydown()
{
	document.onkeydown = keyDown;
	document.body.onkeydown = keyDown;
}

attachEventListener(window, "onload", setOnKeypress);
attachEventListener(window, "onload", setOnKeydown);
String.prototype.REreplace = StringReplace;
Date.prototype.toDate = DatetoDate;
Date.prototype.toTime = DatetoTime;
Date.prototype.toDateTimeAMPM = DatetoDateTimeAMPM;
Date.prototype.GetClockTime = DateGetClockTime;
Date.prototype.UpdateSystemTime = DateUpdateSystemTime;

var isIE = /MSIE/.test(navigator.userAgent);
var isNav = !isIE && /Mozilla/.test(navigator.userAgent);

var _timerStart = new Date();		// might as well start the clock this millisecond! ;)
var _timerStop = 0;
var _timerDelta = 0;
/*
	Function: PortletKeyPress

	TODO  Put a high level overview of PortletKeyPress here.

	Parameters:
		pelPortlet - TODO  Put description here
		pEvent - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function PortletKeyPress(pelPortlet, pEvent) {
	try {
		if (!(_CancelKeyPress_==true)) {
			var charCode = (isNav) ? pEvent.which : pEvent.keyCode;
			var altKey = (isNav) ? (pEvent.modifiers && Event.ALT_KEY) : pEvent.altKey;
			var ctrlKey = (isNav) ? (pEvent.modifiers && Event.CTRL_KEY) : pEvent.ctrlKey;

	//alert(charCode);

			switch (charCode) {	
				case 16:				// Ctrl+Shift+P	(Portlet Dashboard)
					openModalPortlet('DevPage_Portlet.DashboardEdit','&PortletName=' + pelPortlet.id);
					return false;
					break;

				case 19:				// Ctrl+Shift+S (Sandbox)
					if (document.body.LoadingSandbox == undefined) {   
						document.body.LoadingSandbox = true; 		// Prevent a duplicate submission once this fires
						var sURLParams = '';
						var vPort = document.Portlets[pelPortlet.id] 
						if (vPort != null) {
							if ((vPort.urlParams != null) && (vPort.urlParams.length>0)) {
								sURLParams += escape(document.Portlets[pelPortlet.id].urlParams);
								}
							}
						if (sURLParams.length == 0) {
							if (typeof(PatientNo) != 'undefined') sURLParams += escape('&PatientNo=' + PatientNo);
							if (typeof(EncounterNo) != 'undefined') sURLParams += escape('&EncounterNo=' + EncounterNo);
							}
						goURL(GetURLFor('DevPage.Sandbox') + '&PortletID=' + pelPortlet.id + '&URLParams=' + sURLParams); 						} 
					return false;
					break;


				case 112:				// F1 key  (NOTICE: The F1 key can be given an event, but IE Help will ALSO run if just F1, or Ctrl+F1, which is typically not desired)
					if (altKey)
					{
						openHelp(pelPortlet.id);
						window.event.cancelBubble = true;
						return false;
					}
					else
					{
						return true;
					}
					break;



				}


			}
		return true;
		}
	catch(e) {
		HandleError(new AppError("[Common.js]PortletKeyPress", null, null, e));
		}
	}	
	
/*
	Function: setMsg

	TODO  Put a high level overview of setMsg here.

	Parameters:
		msg - TODO  Put description here

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function setMsg(msg) 
{
	try
	{
		window.status = parmStr(msg,'');
		return true;
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]setMsg", null, null, e));
	}
}

/*
	Function: parseXml

	Get a DOM tree from an XML string

	Parameters:
		pstrXml - the XML string

	Returns:
		a DOM tree (XML document)
*/

function parseXml(pstrXml) {
	try {
		var doc;
		if (typeof(DOMParser) != 'undefined') {
			doc = (new DOMParser()).parseFromString(pstrXml, "text/xml");
		}
		else if (typeof(ActiveXObject) != 'undefined') {
			try {
				doc = new ActiveXObject("Msxml2.DOMDocument.4.0");
			}
			catch (x) {
				doc = new ActiveXObject("Microsoft.XMLDOM");
			}
			var success = doc.loadXML(pstrXml);
			if (success) {
				doc.setProperty("SelectionLanguage", "XPath");
			}
			else {
				doc = null;
			}
		}
		else if (typeof(XMLHttpRequest) != 'undefined') {
			var doc = new XMLHttpRequest();
			doc.open('GET', 'data:text/xml;charset=utf-8,' + encodeURIComponent(pstrXml), false);
			if (doc.overrideMimeType) { doc.overrideMimeType("text/xml"); }
			doc.send(null);
			doc = doc.responseXML;
		}
		return doc;
	}
	catch (e) {
		HandleError(new AppError("[Common.js]parseXml", null, null, e));
	}
}

function cleanSelfClosingHtml(pstrHtml) {
	return pstrHtml.replace(/<([^ \/>]+)(([^\/>]|\/[^>])*)\/>/g, '<$1$2></$1>').replace(/<(img|col|input|br|hr)([^>]*)><\/\1>/g, '<$1$2 />');
}

function serializeXml(pn) {
	try {
		return (new XMLSerializer()).serializeToString(pn);
	}
	catch (x) {
		return pn.xml;
	}
}

function collapseJavascript(strScript, blnToVars) {
	strScript = (strScript || '').toString();
	var reSimple = /'|"|'|\/\/|\/\*|\/(?:[^\/\\]|\\.)+\/{1}/i;
	var reComplex = /(\s(function)(?:\s+([^\s(]*))?\s*\([^)]*\)\s*\{|\{|\(|\[|(\svar\s+))|(\}|\)|\]|;)|(,\s*)/mg;
	var reComplex_iOpen = 1, reComplex_iFunction = 2, reComplex_iIdentifier = 3, reComplex_iVar = 4, reComplex_iClose = 5, reComplex_iVarSplit = 6;
	var reComplex_mates = {'function': '}', '{': '}', '(': ')', '[': ']', 'var': ';'};
	var match, matchType = {value: null, FUNCTION: 'function', VAR: 'var'}, matchOpen, nesting = [], inFunctions = [], vars = [], out = '';
	while (match = reSimple.exec(strScript)) {
		// this could be sped up dramatically by incorporating these constructed regular expressions into reSimple and making it global, thus avoiding alteration of strScript
		// see reComplex.lastIndex below for how to complete
		switch (match[0]) {
			case "'":	// string
			case '"':	// string
				out += strScript.substring(0, match.index) + match[0] + match[0];
				strScript = strScript.replace(new RegExp('^(.|\n){' + (match.index + match[0].length) + '}([^' + match[0] + '\\\\]|\\\\.)*' + match[0]), '');
				break;
			case '//':	// single line comment
				out += strScript.substring(0, match.index);
				strScript = strScript.replace(new RegExp('^(.|\n){' + (match.index + match[0].length) + '}.*'), '');
				break;
			case '/*':	// multiline comment
				out += strScript.substring(0, match.index);
				strScript = strScript.replace(new RegExp('^(.|\n){' + (match.index + match[0].length) + '}([^*]|\\*[^/])*\\*/', 'm'), '');
				break;
			default:	// regular expression
				out += strScript.substring(0, match.index) + '/$/';
				strScript = strScript.substring(match.index + match[0].length);
		}
	}
	out = out + strScript;

	if (blnToVars) {
		strScript = ' ' + out.replace(/([{}();,<>=+*%&|^!~?:\/]|\]|-)/g, ' $1 ') + '\n ;';	// add whitepace
		while (match = reComplex.exec(strScript)) {	// remove complexity
			if (match[reComplex_iOpen]) {	// open nesting
				matchOpen = match[reComplex_iOpen];
				matchType.value = (match[reComplex_iFunction] && matchType.FUNCTION) || (match[reComplex_iVar] && matchType.VAR) || matchOpen.ltrim().charAt(0);
				nesting.unshift({type: matchType.value, open: matchOpen, close: reComplex_mates[matchType.value]});	// remember details about nesting
				if (matchType.value == matchType.FUNCTION) {	// remember functions
					if (0 == inFunctions.length && match[reComplex_iIdentifier]) { vars.push(match[reComplex_iIdentifier]); }	// global function with name
					inFunctions.unshift(matchOpen);
				}
			}
			else if (match[reComplex_iClose] && nesting.length > 0 && match[reComplex_iClose] == nesting[0].close) {	// close nesting
				if (nesting[0].type == matchType.FUNCTION) { inFunctions.shift(); }
				nesting.shift();
			}

			// remember variable declarations outside of functions
			if (0 == inFunctions.length && nesting.length > 0 && nesting[0].type == matchType.VAR && (match[reComplex_iOpen] || match[reComplex_iVarSplit])) {
				reComplex.lastIndex = strScript.indexOf(' ', match.index + match[0].length);
				vars.push(strScript.substring(match.index + match[0].length, reComplex.lastIndex).rtrim());
			}
		}
		out = (vars.length > 0 ? 'var ' + vars.join(' , ') + ' ;' : '');
		
		/* dummy code for functionality testing
		collapseJavascript(collapseJavascript.toString(), true) == "var collapseJavascript ;"
		collapseJavascript(collapseJavascript.toString().match(/\{(.|\n)*\}/m)[0], true) == "var reSimple , reComplex ,"
				+ " reComplex_iOpen , reComplex_iFunction , reComplex_iIdentifier , reComplex_iVar , reComplex_iClose ,"
				+ " reComplex_iVarSplit , reComplex_mates , match , matchType , matchOpen , nesting , inFunctions ,"
				+ " vars , out , TEST , SUCCESSFUL , \uD00D ;"
		*/ function TEST(){var FAILED;}; for(var SUCCESSFUL=null,\uD00D=0;SUCCESSFUL;){}
	}

	return out;
}

/*
	Function: StringRTrim

	TODO  Put a high level overview of StringRTrim here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function StringRTrim() 
{
	try
	{
		for (var i = this.length-1; (i>=0) && ((this.charAt(i)==' ')||(this.charAt(i)=='\n')||(this.charAt(i)=='\r')||(this.charAt(i)=='\t')); i--);
		return this.substr(0,i+1);
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]StringRTrim", null, null, e));
	}
}

/*
	Function: StringLTrim

	TODO  Put a high level overview of StringLTrim here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function StringLTrim() 
{
	try
	{
		for (var i = 0; (i<this.length) && ((this.charAt(i)==' ')||(this.charAt(i)=='\n')||(this.charAt(i)=='\r')||(this.charAt(i)=='\t')); i++);
		return this.substr(i,this.length);
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]StringLTrim", null, null, e));
	}
}

/*
	Function: StringTrim

	TODO  Put a high level overview of StringTrim here.

	Exceptions:
		o TODO  Put exceptions thrown here.

	Returns:
		TODO  Put return value information here, if applicable.

	Comments:
	TODO  Put comments in here
	(start example)
		TODO  Put code example here, if desired.
	(end)

	See Also:
		TODO  Put references to related items here.  Enclose them in <angle brackets> and they'll be automatically linked.
*/
function StringTrim() 
{
	try
	{
		return this.ltrim().rtrim();
	}
	catch(e)
	{
		HandleError(new AppError("[Common.js]StringTrim", null, null, e));
	}
}

String.prototype.ltrim = StringLTrim;
String.prototype.rtrim = StringRTrim;
String.prototype.trim = StringTrim;

/*
	Function: xpathSelectXMLNodes

	Select XML nodes by XPath

	Parameters:
		pnContext - the context node
		pstrXpath - the XPath expression
		pfnNamespaceResolver - a function for returning the namespace URI associated with the input namespace prefix [OPTIONAL]

	Returns:
		an array of matching nodes
*/
function xpathSelectXMLNodes(pnContext, pstrXpath, pfnNamespaceResolver) {
	try {
		var doc = (pnContext.nodeType == 9 ? pnContext : pnContext.ownerDocument) || document, nodes = [];
		if (doc && doc.implementation && doc.implementation.hasFeature("XPath","3.0")) {
			for (var n = doc.evaluate(pstrXpath, pnContext, pfnNamespaceResolver || null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), i = 0; i < n.snapshotLength; i++) {
				nodes.push(n.snapshotItem(i));
			}
		}
		else {
			nodes =  pnContext.selectNodes(pstrXpath);
		}
		return nodes;
	}
	catch (e) {
		HandleError(new AppError("[Common.js]xpathSelectXMLNodes", null, null, e));
	}
}

//ScriptMapper.register("Core");
//attachEventListener(window, "onload", function(){ScriptMapper.register("CompleteLoad");});
