﻿/////////////////////////////////////////
// *** OCFrontEnd version 5.2.3005.0 ***
/////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
//
//  Resultmaker JavaScript Library for the Process Platform pages.
//  Copyright Resultmaker 2000-2008. All rights reserved.
//
////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------
var rm_isIE = (navigator.userAgent.indexOf("MSIE") > -1);
var rm_OnlineConsultant = document.getElementById("OnlineConsultant");
var rm_SecurityDomainIsSet = false;
//-------------------------------------------------------

// Settings that may be overwritten by config settings:
var rm_SessionRefreshOnClientActivity = true;
var rm_SessionExpirationWarningFactor = 0.75;
var rm_SessionExpiredDisplayAlert = true;
//-------------------------------------------------------

var rm_wndRefresher;
var rm_SessionTimeoutMinutes;
var rm_SessionTimeoutStart;
var rm_blockSessionExpirationByClock = false;
var rm_wasClientActive = false;

var rm_Text_SessionExpiredWarning = "";
var rm_Text_SessionExpiredAlert = "";

var com_resultmaker_CanOpenLink = true;

//--------------------------------------------------------------------
String.prototype.StartsWith = function(strPrefix)
{
	return (this.substr(0, strPrefix.length) == strPrefix);
}

String.prototype.EndsWith = function(strSuffix)
{
	return (this.substr(this.length - strSuffix.length) == strSuffix);
}
//--------------------------------------------------------------------

// string trim functions:

//cut leftmost spaces:
String.prototype.LTRim = function()
{
	return this.replace(/^[ ]+/, "");
}

// cut rightmost spaces:
String.prototype.RTRim = function()
{
	return this.replace(/[ ]+$/, "");
}

// cut leftmost spaces & tabs:
String.prototype.LTRimTab = function()
{
	return this.replace(/^[ \t]+/, "");
}

// cut rightmost spaces & tabs:
String.prototype.RTRimTab = function()
{
	return this.replace(/[ \t]+$/, "");
}

// full trim: cut leftmost & rightmost spaces:
String.prototype.TRim = function()
{
	return this.LTRim().RTRim();
}

// full trim including tabs: cut leftmost & rightmost, spaces & tabs:
String.prototype.TRimTab = function()
{
	return this.LTRimTab().RTRimTab();
}

//--------------------------------------------------------------------

function RM_getElementById(strId)
{
	var mObj = document.getElementById(strId);
	if(mObj)
	{
		if(RM_JavaScriptDebug  &&  mObj.id != strId) // wrong casing, may fail in some browsers
		{
			alert("Alert for the form designer:\n\n"
				+ "RM_getElementById():\n"
				+ "The element of Id = '" + mObj.id + "' is referenced in the script with the wrong casing "
				+ "and it may be not found when running in some other web browsers.\n"
				+ "'" + mObj.id + "' should be used instead of\n'" + strId + "'\nto reference it in the script.");
		}
	}
	return mObj;
}

function RM_getElementsByName(strName)
{
	var mObj = document.getElementsByName(strName);
	if(mObj  &&  mObj.length > 0)
	{
		if(RM_JavaScriptDebug)
		{
			var foundName = mObj[0].name;
			if(foundName != strName) // wrong casing, may fail in some browsers
			{
				alert("Alert for the form designer:\n\n"
					+ "RM_getElementsByName():\n"
					+ "The element of Name = '" + foundName + "' is referenced in the script with the wrong casing "
					+ "and it may be not found when running in some other web browsers.\n"
					+ "'" + foundName + "' should be used instead of\n'" + strName + "'\nto reference it in the script.");
			}
		}
	}
	return mObj;
}

function RM_IsClientActive()
{
	rm_wasClientActive = true;
}

function RM_OnKeyAction(pEvent)
{
	try
	{
		if(pEvent.keyCode == 8) // Backspace
		{
			var bBlock = false;
			var eventSource = pEvent.target;
			if(( ! eventSource)  &&  rm_isIE)
			{
				eventSource = pEvent.srcElement; // IE
			}

			if(eventSource  &&  RM_IsTextBox(eventSource)  &&  eventSource.readOnly) // Bcksp clicked on read-only text box
			{
				bBlock = true;
			}
			else
			{
				if(rm_isIE)
				{
					// In IE, handle the scenario when user dbclicks on disabled text box,
					// which makes its value selected, then presses the Backspace button:
					// as text box is disabled, the event is not triggered on it, but on it's container instead, which may contain many other elements.
					// The text box can be reached by "document.selection":
					var mSel = document.selection;
					if(mSel  &&  mSel.createRange)
					{
						var mRange = mSel.createRange();
						if(mRange  &&  mRange.parentElement)
						{
							var selElem = mRange.parentElement();
							if(selElem  &&  RM_IsTextBox(selElem)  &&  selElem.disabled) // Bcksp clicked on selection in disabled text box
							{
								bBlock = true;
							}
						}
					}
				}
			}

			if(bBlock)
			{
				RM_CancelEventDefault(pEvent); // to prevent going "back" in history when user expects the selection will be deleted
				return false;
			}
		}
	}
	catch(e) { }
	return true;
}

function RM_OnKeyDown(pEvent)
{
	return RM_OnKeyAction(pEvent);
}

function RM_OnKeyPress(pEvent)
{
	return RM_OnKeyAction(pEvent);
}

//--------------------------------------------------------------------

function RM_SessionExpirationTrace(pWndRefresher, pMinutes)
{
	rm_wndRefresher = pWndRefresher;
	rm_SessionTimeoutMinutes = pMinutes;
	rm_SessionTimeoutStart = new Date();
	var iMilliSecs = 60000 * pMinutes;
	if(rm_SessionExpirationWarningFactor > 1)
	{
		rm_SessionExpirationWarningFactor = 0; // disable the warning
	}
	else
	{
		rm_SessionExpirationWarningFactor = Math.min(rm_SessionExpirationWarningFactor, 0.95);
	}
	if(rm_SessionExpirationWarningFactor != 0) // {0} means "infinity", which disables the warning
	{
		rm_wndRefresher.setTimeout("try { window.parent.RM_SessionExpirationWarning(); } catch(e) { }", iMilliSecs * rm_SessionExpirationWarningFactor);
	}
	var iMilliSecsExpired = iMilliSecs;
	if( ! rm_SessionExpiredDisplayAlert) // no confirm() will be displayed before RM_ResumeCurrent()
	{
		iMilliSecsExpired += 1000; // some extra delay added here to make sure the session really expires
	}
	rm_wndRefresher.setTimeout("try { window.parent.RM_SessionExpirationByClock(); } catch(e) { }", iMilliSecsExpired);
	rm_blockSessionExpirationByClock = false;
	rm_wasClientActive = false;
}

function RM_SessionExpirationProlong()
{
	if(rm_wndRefresher)
	{
		rm_wndRefresher.open(rm_wndRefresher.document.URL, "_self"); // [document.URL = document.URL] doesn't work in some browsers (e.g. Firefox, Netscape) where [document.URL] is a read-only property
	}
}

function RM_SessionExpirationGetFullMessage(pResource)
{
	var startMsecs = rm_SessionTimeoutStart.getTime();
	var expirMsecs = startMsecs + (rm_SessionTimeoutMinutes * 60000);
	var nowMsecs = (new Date()).getTime();
	var expirMoment = new Date(expirMsecs);

	var passedMilliSecs = nowMsecs - startMsecs;
	var passedMinutes = Math.floor(passedMilliSecs / 60000);
	
	var leftMilliSecs = expirMsecs - nowMsecs;
	var leftMinutes = Math.ceil(leftMilliSecs / 60000);

	var msgText = pResource;
	msgText = msgText.replace(/@@@passedMinutes@@@/g, passedMinutes.toString());
	msgText = msgText.replace(/@@@leftMinutes@@@/g, Math.abs(leftMinutes).toString()); // Math.abs() used for ev. displaying the positive time since expiration
	msgText = msgText.replace(/@@@t@@@/g, RM_FormatTime(expirMoment));
	return msgText;
}

function RM_SessionExpirationWarning()
{
	try
	{
		if(com_resultmaker_CanOpenLink)
		{
			if( ! (rm_SessionRefreshOnClientActivity  &&  rm_wasClientActive))
			{
				com_resultmaker_CanOpenLink = false;
				rm_blockSessionExpirationByClock = true;

				var msgText = RM_SessionExpirationGetFullMessage(rm_Text_SessionExpiredWarning);
				RM_Alert(msgText);

				com_resultmaker_CanOpenLink = true; // after "confirm" dialog is ended
			}
			RM_SessionExpirationProlong(); // also if expired, as refresher reacts on expiration
		}
	}
	catch(e) { }
}

function RM_SessionExpirationByClock()
{
	try
	{
		if(com_resultmaker_CanOpenLink)
		{
			if( ! rm_blockSessionExpirationByClock)
			{
				RM_SessionExpiration();
			}
		}
	}
	catch(e) { }
}

function RM_SessionExpiration() // called if Session expiration detected
{
	var bResume = true;
	if(rm_SessionExpiredDisplayAlert)
	{
		var msgText = RM_SessionExpirationGetFullMessage(rm_Text_SessionExpiredAlert);
		bResume = RM_Confirm(msgText);
	}
	if(bResume)
	{
		RM_ResumeCurrent(); // submit to diplay "Session expired" page
	}
}

//--------------------------------------------------------------------

function RM_FormatTime(pDateTime)
{
	return TwoDigits(pDateTime.getHours()) + ":" + TwoDigits(pDateTime.getMinutes()) + ":" + TwoDigits(pDateTime.getSeconds());
	function TwoDigits(pNumber)
	{
		var mStr = "0" + pNumber.toString();
		return mStr.substr(mStr.length - 2, 2);
	}
}

function UrlEncode(pStr) // similar to server-side System.Web.HttpUtility.UrlEncodeUnicode() (and to escape(), but e.g. "+" must be escaped too [while escape() doesn't do it])
{
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/([^\x21\x27-\x2A\x2D-\x2E\w])/g, // (\w is equivalent to [A-Za-z0-9_])
				function($0, $1)
				{
					var iCode = $1.toString().charCodeAt(0);
					var strDigs = "000" + iCode.toString(16);
					var iLen, strPrefix;
					if(iCode < 128)
					{
						iLen = 2;
						strPrefix = "%"; // convert to "%" + 2-digits hex code
					}
					else // Unicode encoding:
					{
						iLen = 4;
						strPrefix = "%u"; // convert to "%u" + 4-digits hex code
					}
					return strPrefix + strDigs.substr(strDigs.length - iLen, iLen);
				} );
	}
	return strRet;
}


/*
function UrlEncode(pStr) // similar to server-side System.Web.HttpUtility.URLEncode() (and to escape(), but e.g. "+" must be escaped too [while escape() doesn't do it])
{
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/([^\x21\x27-\x2A\x2D-\x2E\w])/g, // (\w is equivalent to [A-Za-z0-9_])
				function($0, $1)
				{
					var iCode = $1.toString().charCodeAt(0);
					if(iCode < 128)	
					{
						var strDigs = "0" + iCode.toString(16);
						return "%" + strDigs.substr(strDigs.length - 2, 2); // convert to "%" + 2-digits hex code
					}
					else
					{
						var iU1 = 128 + (iCode % 64);
						if(iCode < 2048)
						{
							var iU2 = Math.floor(iCode / 64) + 192;
							return "%" +  iU2.toString(16) + "%" + iU1.toString(16);
						}
						else
						{
							var iU2 = 128 + ((Math.floor(iCode / 64) % 64));
							var iU3 = Math.floor(iCode / 4096 ) + 224;
							return "%" +  iU3.toString(16) + "%" +  iU2.toString(16) + "%" + iU1.toString(16);
						}
					}
				} );
	}
	return strRet;
}
*/

function URLEncode(pStr)
{
	return UrlEncode(pStr);
}


function HtmlEncode(pStr) // similar to Server.HtmlEncode() of web server
{
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/(\W)/g, // \W is equivalent to [^A-Za-z0-9_]
				function($0, $1)
				{
					return "&#" + $1.toString().charCodeAt(0).toString() + ";";
				} );
	}
	return strRet;
}

function HTMLEncode(pStr)
{
	return HtmlEncode(pStr);
}

function HtmlEncodeLineBreaksOnly(pStr)
{
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/\r\n/g, "<br/>").replace(/[\r\n]/g, "<br/>");
		// end of line sequence {13, 10} to HTML-new-line, then any single {13} or single {10} to HTML-new-line
	}
	return strRet;
}

function HtmlEncodeWithLineBreaks(pStr)
{
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/([^\w\r\n])/g, // \w is equivalent to [A-Za-z0-9_]
				function($0, $1)
				{
						return "&#" + $1.toString().charCodeAt(0).toString() + ";";
				} );
		strRet = HtmlEncodeLineBreaksOnly(strRet);
	}
	return strRet;
}


function RM_SetCookie(pName, pValue, pPermanent)
{
	var sCookie = pName + "=" + pValue;
	if(pPermanent)
	{
		var expDate = new Date();
		expDate.setFullYear(expDate.getFullYear() + 10);
		sCookie += "; expires=" + expDate.toUTCString();
	}
	sCookie += "; path=/";
	try
	{
		document.cookie = sCookie;
	}
	catch(e)
	{ }
}

//-----------------------------------------------

function RM_TrySelect(pInput)
{
	bRet = false;
	try
	{
		if(pInput  &&  pInput.select)
		{
			pInput.select();
			bRet = true; // only if no error above
		}
	}
	catch(e) { }
	return bRet;
}

function RM_TryFocus(pInput)
{
	bRet = false;
	try
	{
		if(pInput  &&  pInput.focus)
		{
			pInput.focus();
			bRet = true; // only if no error above
		}
	}
	catch(e) { }
	return bRet;
}

function RM_TryBlur(pInput)
{
	bRet = false;
	try
	{
		if(pInput  &&  pInput.blur)
		{
			pInput.blur();
			bRet = true; // only if no error above
		}
	}
	catch(e) { }
	return bRet;
}


//displays message connected with input & sets focus on the related input
function RM_FocusedAlert(pInput, pMsg) // public
{
	if(pInput)
	{
		RM_TrySelect(pInput);
		RM_TryFocus(pInput);
	}
	RM_Alert(pMsg);
	if(pInput)
	{
		RM_TryFocus(pInput);
	}
}


function RM_TextIsBlank(strString)
{	
	return(String(strString).replace(/[\s]+$/, "") == ""); 	//(\s is equivalent to [\f\n\r\t\v])
}


function RM_RegExpPattern(pStr)
{	// Some characters have special meaning in Regular Expression pattern,
	// these are:  \ ^ $ * + - ? . , : = { } ( ) [ ] |
	// If any special character must exist in pattern as a character as-it-is, with no special meaning,
	// it must be escaped with \ or converted to hex- or Unicode-encoded value
	var strRet = "";
	if(typeof(pStr) == "string"  &&  pStr != "")
	{
		strRet = pStr.replace(/(\W)/g, // (\W is equivalent to [^A-Za-z0-9_])
				function($0, $1)
				{
					var iCode = $1.toString().charCodeAt(0);
					var strDigs = "000" + iCode.toString(16);
					var iLen, strPrefix;
					if(iCode < 128)
					{
						iLen = 2;
						strPrefix = "\\x"; // convert to "\x" + 2-digits hex code
					}
					else // Unicode encoding:
					{
						iLen = 4;
						strPrefix = "\\u"; // convert to "\u" + 4-digits hex code
					}
					return strPrefix + strDigs.substr(strDigs.length - iLen, iLen);
				} );
	}
	return strRet;
}


function RM_RealNumber(pNumber, pDecimals)
{
	var nRet;
	if(typeof(pNumber) == "number")
	{
		nRet = pNumber;
	}
	else if(typeof(pNumber) == "string")
	{
		var strNum = pNumber.replace(/[\s]+/g, ""); // remove spaces
		if(strNum != ""  &&  strNum != com_resultmaker_DecimalSymbol) // empty string or lonely decimal symbol is not a number
		{
			var bOk = true;

			var arrDecimal = strNum.split(com_resultmaker_DecimalSymbol);
			if(arrDecimal.length <= 2) // none or one decimal symbol found (otherwise invalid number)
			{
				var strIntegerPart = arrDecimal[0]; // may be "" for fractional input like ".123" (=0.123)
				if(strIntegerPart == "")
				{
					strIntegerPart = "0";
				}
				else
				{
					var arrGroups = strIntegerPart.split(com_resultmaker_DigitGroupSymbol); // detect group (thousand) symbol
					if(arrGroups.length > 1) // at least one group (thousand) symbol found in the integer part
					{
						for(var i=1; i<arrGroups.length; i++) // start iterating from 2nd group (1st group may contain any number of digits)
						{
							if(arrGroups[i].length % 3 != 0) // number of digits in group not dividable by 3
							{
								bOk = false;
								break;
							}
						}
						if(bOk)
						{
							strIntegerPart = arrGroups.join(""); // no group (thousand) symbol now
						}
					}
				}

				if(bOk)
				{
					if(arrDecimal.length == 1) // no decimal symbol
					{
						strNum = strIntegerPart; 
					}
					else // decimal symbol found
					{
						var strFractPart = arrDecimal[1];
						strNum = strIntegerPart + "." + strFractPart; // now use "." as decimal separator
					}

					nRet = Number(strNum);

					if(typeof(pDecimals) == "number"  &&  isFinite(pDecimals)  &&  isFinite(nRet))
					{
						nRet = RM_round(nRet, pDecimals);
					}
				}
			}
		}
	}
	return nRet;
}

function RM_FormatNumber(pNumber, pDecimals)
{
	var strRet = "";
	if(isFinite(pNumber))
	{
		if(typeof(pDecimals) == "number"  &&  isFinite(pDecimals))
		{
			strRet = RM_round(pNumber, pDecimals).toString();
			if(pDecimals > 0)
			{
				if(strRet.indexOf('.') == -1)
				{
					strRet += ".";
				}

				while(strRet.length < (strRet.indexOf('.') + pDecimals + 1))
				{
					strRet += "0";
				}
			}
		}
		else
		{
			strRet = pNumber.toString();
		}
		strRet = strRet.replace(/\./g, com_resultmaker_DecimalSymbol);
	}
	return strRet;
}

//checks if provided value is numeric 
function RM_TextIsNumeric(strNumber)
{
	if(RM_TextIsBlank(strNumber)) 
	{
		return false;
	}
	return isFinite(RM_RealNumber(strNumber));
}

//checks whether the number or numeric string contains non-zero fractional part
function RM_ContainsFraction(pNumber)
{
	var mNum = RM_RealNumber(pNumber);
	return (isFinite(mNum)  &&  mNum != Math.floor(mNum));
	// Math.floor() is used above;  Math.round() wrongly "rounded" numbers > 2^52, e.g. Math.round(4503599627370497) = 4503599627370498
}

//-----------------------------------------------

function RM_DisplayAlert(pAlert, pFocusId, pSync)
{
	if(pAlert)
	{
		if( ! pSync)
		{
			window.setTimeout('RM_DisplayAlert(unescape("' + escape(pAlert) + '"), '
			+ (pFocusId ? 'unescape("' + escape(pFocusId) + '")' : 'null')
			+ ", true);", 10);
			return;
		}
		var oElem;
		if(pFocusId)
		{
			oElem = RM_getElementById(pFocusId);
		}
		RM_FocusedAlert(oElem, pAlert);
	}
}

function RM_WithoutFullProtocol(pUrl)
{
	var strRet = pUrl;
	strRet = DeletePrefixIf(strRet, "http://");
	strRet = DeletePrefixIf(strRet, "https://");
	return strRet;
	function DeletePrefixIf(pInput, pPrefix)
	{
		var strNoPrefix = pInput;
		if(pInput.substr(0, pPrefix.length).toLowerCase() == pPrefix)
		{
			strNoPrefix = pInput.substr(pPrefix.length);
		}
		return strNoPrefix;
	}
}

function RM_GetCurrentProtocol()
{
	return (document.URL.substr(0,5).toLowerCase() == "https" ? "https" : "http");
}

function RM_GetUrlWithProperProtocol(pUrl)
{
	return RM_GetCurrentProtocol() + "://" + RM_WithoutFullProtocol(pUrl);
}

function RM_GetUrlWithoutQueryString(pUrl)
{
	var strRet = pUrl;
	var iIdx = strRet.indexOf("?");
	if(iIdx >= 0)
	{
		strRet = strRet.substr(0, iIdx);
	}
	return strRet;
}

function RM_GetUrlRoot(pUrl) // gets "http://mydomain.com:80" part
{
	var strRet = "";
	var mUrlNoQS = RM_GetUrlWithoutQueryString(pUrl);
	var iIdx = mUrlNoQS.indexOf("//");
	if(iIdx >= 0)
	{
		iIdx = mUrlNoQS.indexOf("/", iIdx + "//".length);
		if(iIdx >= 0)
		{
			strRet = mUrlNoQS.substr(0, iIdx);
		}
		else
		{
			strRet = mUrlNoQS.substr(0);
		}
	}
	return strRet;
}

function RM_GetUrlFolder(pUrl) // gets "http://mydomain.com:80/Folder1/Folder2" part
{
	var strRet = "";
	var mUrlNoQS = RM_GetUrlWithoutQueryString(pUrl);
	if(mUrlNoQS.EndsWith("/")) // this is folder
	{
		strRet = mUrlNoQS.substr(0, mUrlNoQS.length - 1);
	}
	else
	{
		var iIdx = mUrlNoQS.lastIndexOf("/");
		if(mUrlNoQS.substr(iIdx - 1, 1) == "/"  &&  mUrlNoQS.lastIndexOf("/", iIdx - 2) < 0) // prev. char is also "/" and no preceding "/" - this is "http://mydomain.com:80"
		{
			strRet = mUrlNoQS; // this is "http://mydomain.com:80"
		}
		else
		{
			var mLast = mUrlNoQS.substr(iIdx + 1);
			if(mLast.indexOf(".") >= 0) // last part is file
			{
				strRet = mUrlNoQS.substr(0, iIdx);
			}
			else // no dot, so it is folder
			{
				strRet = mUrlNoQS;
			}
		}
	}
	return strRet;
}

function RM_SetSecurityDomain(pDomain)
{
	// Domain to be set is based on the value determined on the server, and not on the client (like through the "location" object),
	// so this solution doesn't compromise the security (see description of "document.domain").
	if(pDomain)
	{
		try
		{
			document.domain = pDomain;
			rm_SecurityDomainIsSet = true;
		}
		catch(e) { }
	}
}


function RM_IsButton(oElem)
{
	var bRet = false;
	if(oElem  &&  oElem.nodeName)
	{
		var nodeNameLC = oElem.nodeName.toLowerCase();
		bRet =	(nodeNameLC == "button"
				||
				(nodeNameLC == "input"  &&  oElem.type  &&
						(  oElem.type.toLowerCase() == "button"
						|| oElem.type.toLowerCase() == "image"
						|| oElem.type.toLowerCase() == "submit"
						|| oElem.type.toLowerCase() == "reset")
				));
	}
	return bRet;
}

function RM_IsTextBox(oElem)
{
	var bRet = false;
	if(oElem  &&  oElem.nodeName)
	{
		var nodeNameLC = oElem.nodeName.toLowerCase();
		bRet =	(nodeNameLC == "textarea"
				||
				(nodeNameLC == "input"  &&  oElem.type  &&
						(  oElem.type.toLowerCase() == "text"
						|| oElem.type.toLowerCase() == "password"
						|| oElem.type.toLowerCase() == "file")
				));
	}
	return bRet;
}

function RM_MoveFocusToFirstField()
{
	return RM_TrySetFocusThisOrDescendant(rm_OnlineConsultant);

	function RM_TrySetFocusThisOnly(checkElem)
	{
		var retCheckElem;
		if(checkElem  &&  checkElem.nodeName)
		{
			if(	(checkElem.nodeName.toLowerCase() == "input"  &&
					(  checkElem.type.toLowerCase() == "text"
					|| checkElem.type.toLowerCase() == "password"
					|| checkElem.type.toLowerCase() == "file"
					|| checkElem.type.toLowerCase() == "checkbox"
					|| checkElem.type.toLowerCase() == "radio")
				)
				|| checkElem.nodeName.toLowerCase() == "textarea"
				|| checkElem.nodeName.toLowerCase() == "select"
				|| (RM_IsButton(checkElem)  &&  checkElem.id != "RM_HelpButton"  &&  checkElem.id != "RM_BackButton") // non-Help non-Back button
			)
			{
				if( ! checkElem.disabled)
				{
					var iTab = Number(checkElem.tabIndex);
					if(isNaN(iTab) || iTab >= 0) // i.e. skip if negative tabIndex
					{
						if(RM_TryFocus(checkElem))
						{
							retCheckElem = checkElem; // only if no error in setting the focus
						}
					}
				}
			}
		}
		return retCheckElem;
	}

	function RM_TrySetFocusThisOrDescendant(thisElem)
	{
		var retElem;
		if(RM_TrySetFocusThisOnly(thisElem))
		{
			retElem = thisElem;
		}
		else
		{
			var mColl = thisElem.childNodes; // use recursively {.childNodes}, not directly {.elements}, to include also {input type="image"} which doesn't belong to {.elements}
			if(mColl)
			{
				var mElem;
				for(var i=0; i<mColl.length; i++)
				{
					mElem = mColl[i];
					if(mElem.nodeType == 1) // Element node
					{
						retElem = RM_TrySetFocusThisOrDescendant(mElem);
						if(retElem)
						{
							break;
						}
					}
				}
			}
		}
		return retElem;
	}
}

function RM_OnLoad()
{
	RM_MoveFocusToFirstField();
	if(window.OCC_OnLoad)
	{
		OCC_OnLoad(); // it may set the focus on another element, so executed as last
	}
	RM_UnWaitPage();
}

function RM_ExecuteFuncByName(funcName)
{
	try
	{
		eval(funcName + "();");
	}
	catch(e)
	{
		alert("Cannot find \"" + funcName +"()\" function to execute on load.");
	}
}

function RM_AttachOnLoadEvent(funcName)
{
	if(funcName)
	{
		var mPointer;
		try
		{
			mPointer = eval(funcName);
		}
		catch(e) { }

		if(mPointer  &&  window.attachEvent)
		{
			window.detachEvent('onload', mPointer); // first try to detach, to avoid attaching more than once
			window.attachEvent('onload', mPointer);
		}
		else if(mPointer  &&  window.addEventListener)
		{
			window.addEventListener('load', mPointer, false);
		}
		else
		{
			if(window.setTimeout)
			{
				window.setTimeout("RM_ExecuteFuncByName('" + funcName + "');", 100);
			}
			else
			{
				RM_ExecuteFuncByName(funcName);
			}
		}
	}
}

function RM_DetachOnResizeEvent(eventObject, funcPointer)
{
	if(eventObject  &&  funcPointer)
	{
		if(eventObject.detachEvent)
		{
			eventObject.detachEvent('onresize', funcPointer);
		}
		else if(eventObject.removeEventListener)
		{
			eventObject.removeEventListener('resize', funcPointer, false);
		}
	}
}

function RM_AttachOnResizeEvent(eventObject, funcPointer)
{
	if(eventObject  &&  funcPointer)
	{
		if(eventObject.attachEvent)
		{
			eventObject.detachEvent('onresize', funcPointer); // first try to detach, to avoid attaching more than once
			eventObject.attachEvent('onresize', funcPointer);
		}
		else if(eventObject.addEventListener)
		{
			eventObject.addEventListener('resize', funcPointer, false); // bubbling phase, no capture
		}
	}
}

function RM_DetachOnClickEvent(eventObject, funcPointer)
{
	if(eventObject  &&  funcPointer)
	{
		if(eventObject.detachEvent)
		{
			eventObject.detachEvent('onclick', funcPointer);
		}
		else if(eventObject.removeEventListener)
		{
			eventObject.removeEventListener('click', funcPointer, false);
		}
	}
}

function RM_AttachOnClickEvent(eventObject, funcPointer)
{
	if(eventObject  &&  funcPointer)
	{
		if(eventObject.attachEvent)
		{
			eventObject.detachEvent('onclick', funcPointer); // first try to detach, to avoid attaching more than once
			eventObject.attachEvent('onclick', funcPointer);
		}
		else if(eventObject.addEventListener)
		{
			eventObject.addEventListener('click', funcPointer, false); // bubbling phase, no capture
		}
	}
}

function RM_CreateHiddenInput(pName)
{
	var mObj;
	if(rm_isIE)
	{
		mObj = document.createElement("<input name='" + pName + "' type='hidden' />");
	}
	else
	{
		mObj = document.createElement("input");
		mObj.name = pName;
		mObj.type = "hidden";
	}
	com_resultmaker_Form.appendChild(mObj); // append to form, to be submitted
	return mObj;
}

function RM_EnsureHiddenInput(pIdName)
{
	var mObj = document.getElementById(pIdName);
	if( ! mObj)
	{
		mObj = RM_CreateHiddenInput(pIdName);
		mObj.id = pIdName;
	}
	return mObj;
}


function RM_OpenURL(url, options)
{
//	if (com_resultmaker_CanOpenLink)
//	{
		if(options == null)
		{
			options = "height=540, width=750, directories=no, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no";
		}
		window.open(url, "RM_OpenURL", options); // custom name used to identify the window
//	}
}

function isArray(obj)
{
	var bRet = false;
	if(typeof(obj) != "undefined")
	{
		if(typeof(obj.length) == "number")
		{
			bRet = true;
		}
		else
		{
			if(obj.constructor  &&  obj.constructor.toString().indexOf("Internal function") == -1)
			{
				bRet = (obj.constructor.toString().indexOf("Array") >= 0);
			}
			else
			{
				if(obj[0])
				{
					bRet = true;
				}
			}
		}
	}
	return bRet;
}


//--------------------------------------------------------------------
// CSS class functions:

// Add given class name to the element's className property
function PMaddClassName(el, name)
{
	if(el  &&  ! PMhasClassName(el, name))
	{
		el.className = el.className + " " + name;
	}
}

// Return true if the given element currently has the given class name.
function PMhasClassName(el, name)
{
	if(el  &&  el.className)
	{
		var curList = el.className.split(" ");
		for(var i=0; i<curList.length; i++)
		{
			if(curList[i] == name)
			{
				return true;
			}
		}
	}
	return false;
}

// Replace className 'name' with the given 'newName' value
function PMreplaceClassName(el, name, newName)
{
	if(el  &&  el.className)
	{
		var curList = el.className.split(" ");
		for(var i=0; i<curList.length; i++)
		{
			if(curList[i] == name)
			{
				curList[i] = newName;
			}
		}
		el.className = curList.join(" ");
	}
}

// Remove the given class name from the element's className property.
function PMremoveClassName(el, name)
{
	if(el  &&  el.className)
	{
		var newList = new Array();
		var curList = el.className.split(" ");
		for(var i=0; i<curList.length; i++)
		{
			if(curList[i] != name)
			{
				newList[newList.length] = curList[i];
			}
		}
		el.className = newList.join(" ");
	}
}

function RM_MakeClass(el, pClass, pApply)
{
	if(el)
	{
		if(pApply)
		{
			PMaddClassName(el, pClass);
		}
		else
		{
			PMremoveClassName(el, pClass);
		}
	}
}

function RM_ToggleClass(el, pClass)
{
	if(el)
	{
		if(PMhasClassName(el, pClass))
		{
			PMremoveClassName(el, pClass);
		}
		else
		{
			PMaddClassName(el, pClass);
		}
	}
}

//--------------------------------------------------------------------

// tooltip functions

function RM_showtooltipDescription(pQName, e)
{
	var oDesc = getDescriptionHiddenObj(pQName);
	if(oDesc)
	{
		var strDesc = oDesc.innerHTML;
		if(strDesc  &&  strDesc != "")
		{
			RM_showtooltip(strDesc, e);
		}
	}
}

function RM_showtooltip(str, e, IDString, PositionObjString)
{
	if( ! IDString)
	{
		 IDString = "RM_showtooltip_object";
	}
	if(str && document.documentElement)
	{
		if(str.length > 0)
		{
			str = '<div class="displayquestiondescription">' + HtmlEncodeLineBreaksOnly(str) + '</div>';
			// assumption: str may contain HTML, so it is not being HtmlEncoded here; only linebreaks replaced with "<br/>"
			if( ! RM_getElementById(IDString))
			{
				var newobject = document.createElement("div");
				newobject.id = IDString;
				newobject.className = "RM_showtooltip RM_showtooltip_object_hide";
				newobject.style.position = "absolute";
				newobject.style.zIndex = "9";
				document.body.appendChild(newobject);
			}

			var RM_showtooltip_object = RM_getElementById(IDString);
			var x,y;

			if (PositionObjString != null)
			{
				var PositionObj = RM_getElementById(PositionObjString);
				x = (getAbsPos(PositionObj, "Left") + 8)  + "px";
				y = (getAbsPos(PositionObj, "Top") + 3)  + "px";
			}
			else
			{
				var EventObj;

				if (window.event)
					EventObj = event;
					
				else
					EventObj = e;
					
				if (document.documentElement.scrollTop)
				{
					x = (EventObj.clientX + document.documentElement.scrollLeft + 15) + "px";
					y = (EventObj.clientY + document.documentElement.scrollTop + 10)  + "px";
				}
				else
				{
					x = (EventObj.clientX + document.body.scrollLeft + 15) + "px";
					y = (EventObj.clientY + document.body.scrollTop + 10)  + "px";
				}
			}
			RM_showtooltip_object.innerHTML = str;
			RM_showtooltip_object.style.left = x;
			RM_showtooltip_object.style.top = y;
			PMremoveClassName(RM_getElementById(IDString),"RM_showtooltip_object_hide");
		}
	}

	function getAbsPos(elt,which) {
		iPos = 0;
		while (elt != null)
		{
			iPos += elt["offset" + which];
			elt = elt.offsetParent;
		}
	}

}

function RM_Hidetooltip(IDString)
{
	if(IDString == null)
	{
		 IDString = "RM_showtooltip_object";
	}
	var mObj = RM_getElementById(IDString);
	if(mObj)
	{
		PMaddClassName(mObj,"RM_showtooltip_object_hide");
	}
}

function IsVisible(HTMLTag)
{
	if (PMhasClassName(HTMLTag, "RM_Hide") || (HTMLTag.style && HTMLTag.style.visibility == "hidden"))
		return false;
	else if (HTMLTag.parentNode)
		return IsVisible(HTMLTag.parentNode)
	else
		return true;
}

function RM_GoBackToProjectList(url)
{
	if(url)
	{
		window.open(url, "_self", null, false);
	}
	else
	{
		if(com_resultmaker_CanOpenLink)
		{
			com_resultmaker_CanOpenLink = false;
			com_resultmaker_Form.elements["NextAction"].value = "ProjectList";
			com_resultmaker_Form.submit();
		}
	}
}

function RM_ResumeCurrent()
{
	if(com_resultmaker_CanOpenLink)
	{
		com_resultmaker_CanOpenLink = false;
		com_resultmaker_Form.elements["NextAction"].value = "ResumeCurrent";
		com_resultmaker_Form.submit();
	}
}

function RM_PositionObject(moveObj, refObj, extraX, extraY)
{
	moveObj.style.left = (getAbsX(refObj) + (typeof(extraX) == "number" ? extraX : 0)).toString() + "px";
	moveObj.style.top  = (getAbsY(refObj) + (typeof(extraY) == "number" ? extraY : 0)).toString() + "px";

	function getAbsX(obj) { return obj.x ? obj.x : getAbsPos(obj, "Left") ; }

	function getAbsY(obj) { return obj.y ? obj.y : getAbsPos(obj, "Top"); }

	function getAbsPos(obj, which)
	{
		var iPos = 0;
		while(obj)
		{
			iPos += obj["offset" + which];
			obj = obj.offsetParent;
		}
		return iPos;
	}
}

function RM_ShowError(e, oName)
{
	var oEvent = e;
	if( ! e) oEvent = window.event;
	if(oEvent.shiftKey  &&  oEvent.ctrlKey)
	{
		try
		{
			if(document.selection  &&  document.selection.empty)
			{
				document.selection.empty();
			}
		}
		catch(e) { }
		RM_ToggleClass(RM_getElementById(oName), "RM_Hide");
	}
}

function RM_Error(msg, file, line)
{
	if( ! RM_JavaScriptDebug)
		return true;
	else
	{
		if (!(RM_ErrorBox = RM_getElementById("RM_ErrorBox")))
		{
			RM_ErrorBox = document.createElement("div");
			RM_ErrorBox.id = "RM_ErrorBox";
			RM_ErrorBox.className = "RM_ErrorBox RM_Hide";
			document.body.appendChild(RM_ErrorBox);
		}
		
		var errString = RM_ErrorBox.innerHTML;

		if (msg)
			errString += "JavaScript Error: " + msg + "<br />";
		if (file)
			errString += "File: " + file + "<br />";
		if (line)
			errString += "Line Number: " + line + "<br />";
		
		RM_ErrorBox.innerHTML = errString;
		PMremoveClassName(RM_ErrorBox, "RM_Hide");
		alert(msg);
		
		return false;
	}
}




//===========================================================================
// Instantiates a new DataSelector window, running the specified application,
// and brings it into focus.
//
// Parameters:
// =================
// baseUrl:			Base url of the DataSelector 
//					(ex.: "http://www.test.com/DataSelector.aspx")
// applicationName:	Name of the application to run.
// fieldMap:		Comma-separated list of fieldMap triplets. A triplet
//					consists of DOM element id, application field name and
//					DOM element value, separated by pipe ("|").
//					(ex.: "myInputField|ZipCode|2000,myOtherField|City|")
// width:			Width of the DataSelector in pixels.
// height:			Height of the DataSelector in pixels.
//===========================================================================
function RunDataSelector( baseUrl, applicationName, fieldMap, width, height )
{
	var url = baseUrl + '?applicationName=' + URLEncode(applicationName) + '&fieldMap=' + URLEncode(fieldMap);
	var dataSelectorWindow = window.open(url, "RunDataSelector", 'width=' + width + ',height=' + height + ',directories=no,location=no,menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no', true); // custom name used to identify the window
	dataSelectorWindow.focus();
}

function RunAdvancedPicker( baseUrl, applicationName, fieldMap, width, height, positionElement )
{
	var url = baseUrl + '?applicationName=' + URLEncode(applicationName) + '&fieldMap=' + URLEncode(fieldMap) + '&clientscriptscope=parent';
	RM_NewWindowAdvanced(com_resultmaker_ImagePath, url, width, height, positionElement);
}

var RM_NewWindowAdvanced_NAME = "RM_AdvancedWindow";
var RM_AdvancedWindow = null;

function RM_NewWindowAdvanced(graphicsPath, url, width, height, position, x, y)
{
	if (!(RM_AdvancedWindow = RM_getElementById(RM_NewWindowAdvanced_NAME)))
	{
		RM_AdvancedWindow = document.createElement("div");
		RM_AdvancedWindow.id = RM_NewWindowAdvanced_NAME;
		RM_AdvancedWindow.className = "RM_AdvancedWindow RM_Hide";
		document.body.appendChild(RM_AdvancedWindow);
	}

	if (position  != null)
	{
		RM_PositionObject(RM_AdvancedWindow, position, 0, 25);
	}
	else if (x && y)
	{
		RM_AdvancedWindow.style.left = x + "px";
		RM_AdvancedWindow.style.top = y + "px";
	}
	else if (screen.width)
	{
		RM_AdvancedWindow.style.left = (screen.width - width) / 2 + "px";
		RM_AdvancedWindow.style.top = "100px";
	}
	else
	{
		RM_AdvancedWindow.style.left = "100px";
		RM_AdvancedWindow.style.top = "100px";
	}

	RM_AdvancedWindow.style.width = width;
	RM_AdvancedWindow.style.height = height;

	RM_AdvancedWindow.innerHTML = "<iframe src=\"" + HtmlEncode(url) + "\"></iframe>"; // "" (and not '') is used for delimiting the src, because ev. " existing inside would be encoded, while ' wouldn't
	PMremoveClassName(RM_AdvancedWindow, "RM_Hide");
	window.setTimeout("RM_AttachOnClickEvent(document, RM_CloseWindowAdvanced);", 100);
}

function RM_CloseWindowAdvanced()
{
	if (RM_AdvancedWindow)
	{
		PMaddClassName(RM_AdvancedWindow, "RM_Hide");
		RM_DetachOnClickEvent(document, RM_CloseWindowAdvanced);
	}
}

function UserClosedWindow()
{
	ResultmakerPopupClosed();
}

function ResultmakerPopupClosed()
{
	RM_CloseWindowAdvanced();
}

//--------------------------------------------------------------------

function RM_MenuHighlight(obj)
{
	PMaddClassName(obj, "MenuHighlight");
}

function RM_MenuUnHighlight(obj)
{
	PMremoveClassName(obj, "MenuHighlight");
}


//--------------------------------------------------------------------

// Event cancellation:

function RM_CancelEventDefault(pEvent)
{
	if(window.event) // IE
	{
		window.event.returnValue = false;
	}
	else
	{
		if(pEvent  &&  pEvent.preventDefault)
		{
			pEvent.preventDefault();
		}
	}
	return false;
}

function RM_CancelEventPropagation(pEvent)
{
	if(window.event) // IE
	{
		window.event.cancelBubble = true;
	}
	else
	{
		if(pEvent  &&  pEvent.stopPropagation)
		{
			pEvent.stopPropagation();
		}
	}
	return false;
}


function RM_CancelEventFull(pEvent)
{
	RM_CancelEventDefault(pEvent);
	RM_CancelEventPropagation(pEvent);
	return false;
}


//--------------------------------------------------------------------

// Page-dimming and waiting:
var rm_arrDropdownsDisabling;

function RM_DropdownsDisabling(bHide)
{
	if(bHide)
	{
		if(rm_arrDropdownsDisabling) // already defined, this is subsequent call to hide
		{
			return;
		}
		rm_arrDropdownsDisabling = new Array();
	}
	else
	{
		if( ! rm_arrDropdownsDisabling)
		{
			return;
		}
	}
	var colSelects = document.getElementsByTagName("select");
	var mElem;
	for(var i=0; i < colSelects.length; i++)
	{
		mElem = colSelects[i];
		if(bHide)
		{
			rm_arrDropdownsDisabling[i] = mElem.disabled;
			mElem.disabled = true;
		}
		else
		{
			mElem.disabled = rm_arrDropdownsDisabling[i];
		}
	}
	if( ! bHide) // after restoring
	{
		rm_arrDropdownsDisabling = null;
	}
}

function RM_DropdownsMakeDisabled()
{
	if(rm_isIE)
	{
		if(rm_OnlineConsultant.currentStyle  &&  rm_OnlineConsultant.currentStyle.filter)
		{
			RM_DropdownsDisabling(true);
		}
	}
}

function RM_DropdownsUnMakeDisabled()
{
	if(rm_isIE)
	{
		RM_DropdownsDisabling(false);
	}
}

function RM_PageState(bHide, pClassName)
{
	// (setting the className may take most of execution time)
	if(bHide)
	{
		PMaddClassName(rm_OnlineConsultant, pClassName);
		PMaddClassName(document.body, pClassName);
	}
	else
	{
		PMremoveClassName(document.body, pClassName);
		PMremoveClassName(rm_OnlineConsultant, pClassName);
	}
}

//----

function RM_DimmingPage(bHide)
{
	if(rm_isIE)
	{
		RM_PageState(bHide, "RM_DimmedPage");
		if(bHide)
		{
			RM_DropdownsMakeDisabled();
		}
		else
		{
			RM_DropdownsUnMakeDisabled();
		}
	}
}

function RM_DimPage()
{
	RM_DimmingPage(true);
}

function RM_UnDimPage()
{
	RM_DimmingPage(false);
}

//----

function RM_WaitingPage(bHide)
{
	RM_PageState(bHide, "RM_WaitingPage");
	// no RM_DropdownsMakeDisabled() here, to not interfere with validation that checks "disabled" for elements
}

function RM_WaitPage()
{
	RM_WaitingPage(true);
}

function RM_UnWaitPage()
{
	RM_WaitingPage(false);
}

//--------------------------------------------------------------------

// Page-dimming "alert" and "confirm":

var rm_origAlertPointer   = window.alert;
var rm_origConfirmPointer = window.confirm;

function RM_Alert(pMsg)
{
	RM_DimPage();
	rm_origAlertPointer(pMsg); // call native alert()
	RM_UnDimPage();
}

function RM_Confirm(pMsg)
{
	RM_DimPage();
	var bRet = rm_origConfirmPointer(pMsg); // call native confirm()
	RM_UnDimPage();
	return bRet;
}

try
{
	window.alert = RM_Alert;
	window.confirm = RM_Confirm;
}
catch(e)
{ }

//--------------------------------------------------------------------

/// Finds the descendant of the node, specified by "name" attribute
/// Returns null if not found.
function RM_FindDescendantByCustomName(node, customName)
{
	var nodeFound;
	if(node  &&  customName)
	{
		var mColl = node.childNodes;
		if(mColl)
		{
			var nodeIter;
			for(var i=0; i<mColl.length; i++)
			{
				nodeIter = mColl[i];
				if(nodeIter.name == customName)
				{
					nodeFound = nodeIter;
					break;
				}
				else
				{
					nodeFound = RM_FindDescendantByCustomName(nodeIter, customName);
					if(nodeFound)
					{
						break;
					}
				}
			}
		}
	}
	return nodeFound;
}

/// Finds the ancestor (or self) of the node, specified by tag name.
/// Returns null if not found.
function RM_FindAncestor(node, nodeName)
{
	var nodeFound;
	if(node  &&  nodeName)
	{
		if(typeof(node.nodeName) == "string"  &&  node.nodeName.toLowerCase() == nodeName.toLowerCase())
		{
			nodeFound = node;
		}
		else
		{
			nodeFound = RM_FindAncestor(node.parentNode, nodeName);
		}
	}
	return nodeFound;
}

/// Finds the previous/next sibling of the node, specified by tag name.
/// Necessary for browsers that return the text node as an immediate sibling of e.g. "TR" node (e.g. Firefox).
/// Returns null if not found.
function RM_FindSibling(node, nodeName, bNextOrPrev)
{
	var nodeFound;
	if(node  &&  nodeName)
	{
		var nodeIter = node;
		while(nodeIter)
		{
			if(bNextOrPrev)
			{
				nodeIter = nodeIter.nextSibling;
			}
			else
			{
				nodeIter = nodeIter.previousSibling;
			}
			
			if(nodeIter)
			{
				if(typeof(nodeIter.nodeName) == "string"  &&  nodeIter.nodeName.toLowerCase() == nodeName.toLowerCase())
				{
					nodeFound = nodeIter;
					break;
				}
			}
		}
	}
	return nodeFound;
}

function RM_FindSiblingPrevious(node, nodeName)
{
	return RM_FindSibling(node, nodeName, false);
}

function RM_FindSiblingNext(node, nodeName)
{
	return RM_FindSibling(node, nodeName, true);
}

function RM_FindFirstChild(node)
{
	var nodeFound;
	if(node)
	{
		var nodeIter = node.firstChild;
		while(nodeIter)
		{
			if(nodeIter.nodeType == 1) // Element node
			{
				nodeFound = nodeIter;
				break;
			}
			nodeIter = nodeIter.nextSibling;
		}
	}
	return nodeFound;
}

