//<script language="javascript">  //This tag is to fake Interdev into recognizing this file as a javascript file 
// Copyright (c) 2000-2002 Onyx Software Corporation All rights reserved.

var MainFrameRef;						
var bInitMainFrameRef = false;	
var mbResized = false;
var mhResizeInterval = null;
var mbScrollComplete = false;
var mhScrollInterval = null;

// name type constants
var INDIVIDUAL_NAME_FORMAT_LONG = 0;
var INDIVIDUAL_NAME_FORMAT_SHORT = 1;
var INDIVIDUAL_NAME_FORMAT_EMAIL = 2;
var INDIVIDUAL_NAME_FORMAT_MAILING = 3;
var INDIVIDUAL_NAME_FORMAT_RETRIEVELIST = 4;

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsRollover
DESCRIPTION		Changes the button state
PARAMETERS
	poImg: reference to image object to act on
RETURN VALUES
	none
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsRollover(poImg){
	var sSrc
	var sState
	sSrc = poImg.src.substr(0, (poImg.src.length - 5))
	sState = poImg.src.substr((poImg.src.length - 5),1)
	if (sState=="4"){
		return;
	}
	switch(event.type){
		case 'mousedown':
			sSrc = sSrc + '3'
			break
		case 'mouseup':
			sSrc = sSrc + '2'
			break
		case 'mouseover':
			sSrc = sSrc + '2'
			break
		case 'mouseout':
			sSrc = sSrc + '0'
			break
	}
	poImg.src = sSrc + '.gif'
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsResizeTest
DESCRIPTION		Polls to test when the resize event has ended
PARAMETERS
	psResizeFunction: Function to resize
RETURN VALUES
	none
CALLED PROCEDURES
	NONE
NOTES:		
	***** Not to be called directly *****
-----------------------------------------------------------------------------COMMENT*/	
function jsResizeTest(psResizeFunction) {
	if (!mbResized) {
		eval("var e; try {" + psResizeFunction + "} catch(e) {}");
		clearInterval(mhResizeInterval);
		mhResizeInterval = null;
	}
	mbResized = false;
}


/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsResizeProcess
DESCRIPTION		Replaces the function in the "onresize" event of the body
				e.g. <body onresize="jsResizeProcess('jsResize();'">
PARAMETERS
	psLocalResizeFunction: Function to handle the Resize
RETURN VALUES
	none
CALLED PROCEDURES
	jsResizeTest
-----------------------------------------------------------------------------COMMENT*/	
function jsResizeProcess(psLocalResizeFunction) {
	if (mhResizeInterval == null) {
		mhResizeInterval = setInterval("jsResizeTest('" + psLocalResizeFunction + "')",10)
	}
	mbResized = true;	
}


/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsScrollTest
DESCRIPTION		Polls to test when the scroll event has ended
PARAMETERS
	psLocalScrollFunction: Function to handle scroll
RETURN VALUES
	none
CALLED PROCEDURES
	NONE
NOTES:		
	***** Not to be called directly *****
-----------------------------------------------------------------------------COMMENT*/	
function jsScrollTest(psLocalScrollFunction) {
	if (!mbScrollComplete) {
		eval("var e; try {" + psLocalScrollFunction + "} catch(e) {}");
		clearInterval(mhScrollInterval);
		mhScrollInterval = null;
	}
	mbScrollComplete = false;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsScrollProcess
DESCRIPTION		Replaces the function in the "onscroll" event of the list body DIV 
				e.g. <body onresize="jsScrollProcess('jsResize();'">
PARAMETERS
	psLocalScrollFunction: Function to handle the scroll
RETURN VALUES
	none
CALLED PROCEDURES
	jsScrollTest
-----------------------------------------------------------------------------COMMENT*/	
function jsScrollProcess(psLocalScrollFunction) {
	if (mhScrollInterval == null) {
		mhScrollInterval = setInterval("jsScrollTest('" + psLocalScrollFunction + "')",10)
	}
	mbScrollComplete = true;	
}


/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsSetMainFrameRef
DESCRIPTION	Sets a reference to the main frame object (MainFrameRef).  This function should be used where you
						want to explicitly set a reference to the main frame rather than use jsInitMainFrameRef() to determine it
	
PARAMETERS
	poWindow						A window object to set the MainFrameRef variable to.
RETURN VALUES
	The window reference that was passed in
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsSetMainFrameRef(poWindow){
		MainFrameRef = poWindow
		bInitMainFrameRef = true;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsGetMainFrameRef
DESCRIPTION	Attempts to return a reference to the main frame window.  If the variable bInitMainFrameRef has been set
						to true it will return the value of MainFrameRef.  If not it will attempt to call window.top.jsGetMainFrameRef
						
	
PARAMETERS
	NONE
RETURN VALUES
	A reference to the main frame window or false
CALLED PROCEDURES
	jsGetMainFrameRef
-----------------------------------------------------------------------------COMMENT*/	
function jsGetMainFrameRef(){
	if (bInitMainFrameRef!=true){
		// if we reach the point where we are in the top window and still
		// haven't located a reference to main frame then things have gone
		// wrong, so return false

		if (window.top){
			if (window.top == window) {
				if (window.name == "main_frame"){
					MainFrameRef = window;
					bInitMainFrameRef = true;
					return MainFrameRef;
				}else{
					return false;
				}
			}
						
			MainFrameRef = window.top.jsGetMainFrameRef();
			bInitMainFrameRef = true;
			if (!MainFrameRef){
				return false;
			}
			if (!MainFrameRef.closed) {
				return MainFrameRef;
			}else{
				return false;
			}
		}else{
			return false;
		}
	}else{
		if (MainFrameRef){
			return MainFrameRef;
		}
	}
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsInitMainFrameRef
DESCRIPTION	Attempts to set and return a reference to the main frame window 
		
PARAMETERS
	NONE
RETURN VALUES
	A reference to the main frame window or Null
CALLED PROCEDURES
	jsGetMainFrameRef
-----------------------------------------------------------------------------COMMENT*/	
function jsInitMainFrameRef(){
	if (window.top){
		if (window.top.name != "main_frame"){
			if (!window.top.opener){			
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}
			if (!window.top.opener.closed){			
				MainFrameRef = window.top.opener.top.jsGetMainFrameRef();
				bInitMainFrameRef = true;
				return MainFrameRef;
			}else{
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}
		}else{
			MainFrameRef = jsGetMainFrameRef();
			if (!MainFrameRef) {
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}else{
				return MainFrameRef;
			}
		}
	}else{
		MainFrameRef = null;
		bInitMainFrameRef = false;
		return false;
	}
}


/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsInitMainFrameRef
DESCRIPTION	Attempts to set and return a reference to the main frame window 
		
PARAMETERS
	NONE
RETURN VALUES
	A reference to the main frame window or Null
CALLED PROCEDURES
	jsGetMainFrameRef
-----------------------------------------------------------------------------COMMENT*/	
function jsInitMainFrameRefforBS(){
	if (window.top){
		if (window.top.name != "main_frame"){
			if (!window.top.opener){			
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}
			if (!window.top.opener.closed){		
				if (window.top.opener.top.name == "main_frame")
				{			
					MainFrameRef = window.top.opener.top.jsGetMainFrameRef();
				}
				else
				{
					MainFrameRef = window.top.opener.top.opener.top.jsGetMainFrameRef();
				}
				bInitMainFrameRef = true;
				return MainFrameRef;
			}else{
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}
		}else{
			MainFrameRef = jsGetMainFrameRef();
			if (!MainFrameRef) {
				MainFrameRef = null;
				bInitMainFrameRef = false;
				return false;
			}else{
				return MainFrameRef;
			}
		}
	}else{
		MainFrameRef = null;
		bInitMainFrameRef = false;
		return false;
	}
}



/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsModalInitMainFrameRef
DESCRIPTION	Attempts to set and return a reference to the main frame window 
						This function assumes that the window.dialogArguments property contains a reference to
						the window that opened the modal dialog
PARAMETERS
	NONE
RETURN VALUES
	A reference to the main frame window or Null
CALLED PROCEDURES
	jsGetMainFrameRef
-----------------------------------------------------------------------------COMMENT*/	
function jsModalInitMainFrameRef(){
	var oOpener;
	var oMainFrameRef 
	var bCalledFromModalDialog = false
	var oError
	
	//look to see if this page was called from another modal dialog
	try{
		bCalledFromModalDialog = window.dialogArguments.mbIsModalDialog
	}catch(oError){
		bCalledFromModalDialog = false
	}
	
	//if not called from a modal dialog then do this to get the main_frame object ref
	if(bCalledFromModalDialog != true){
		oOpener = window.dialogArguments
	}
	//if not got the ref yet got to windows up
	if(!oOpener) oOpener = window.dialogArguments.dialogArguments
	//now we have the main_frame window object call the getMainFrameRef
	oMainFrameRef = oOpener.jsGetMainFrameRef()
	jsSetMainFrameRef(oMainFrameRef)
}	

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsFlashMaskedEdits
DESCRIPTION	Used to work around an issue with the Masked Edit control not displaying correctly on first load.
						it switches the prompt character to " " and back to force a refresh
		
PARAMETERS
	psMaskedEditName		The name of the masked edit control (or control array of controls) to act on.	
RETURN VALUES
	NONE
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsFlashMaskedEdits(psMaskedEditName){
	var arrUDFTemp = document.all(psMaskedEditName);
	var temp1;
	var e;
	
	// ***** Make sure we have at least one field on the form
	if (arrUDFTemp){
		// ***** check for only one field
		try {
			if (arrUDFTemp.length==null){
				e = eval(arrUDFTemp);
				temp1 = e.PromptChar;
				e.PromptChar ="  ";
				e.PromptChar =temp1;
				//e.PromptInclude =0;
			}else{
				e = eval(arrUDFTemp[0]);
				temp1 = e.PromptChar;
				for (var i=0;i<arrUDFTemp.length;i++){
					e = eval(arrUDFTemp[i])
					e.PromptChar ="  ";
					e.PromptChar =temp1;
					//e.PromptInclude =0;
				}		
		
			}
		} catch(e) {
		}

	}
	
	
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsGetMaskedEditText
DESCRIPTION	This function determines the data that needs to be saved for a particular masked edit control
						It will return either the data with the mask or and empty string.
						It is not valid for company or individual masks as they do not save the mask with the data.
		
PARAMETERS
	poMaskedEdit				A reference to the masked edit control to act upon
RETURN VALUES
	The text value of the masked edit control, if no text has been entered then this function will return an empty string
	(it will not return any of the mask as this should not be saved) if text has been entered then this function will return
	the text including the mask characters (but any mask prompt will be replaced with spaces)
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsGetMaskedEditText(poMaskedEdit){
	var sUDFTemp = "";
	var sOldPromptChar;
	var vOldPromptInclude;
	
	if (jsTrim(poMaskedEdit.cliptext)==""){
		sUDFTemp = ""
	}else	{
		// Switch out the prompt character so that it does not get saved
		sOldPromptChar = poMaskedEdit.PromptChar;
		vOldPromptInclude = poMaskedEdit.PromptInclude;
		poMaskedEdit.PromptChar = "  ";
		poMaskedEdit.PromptInclude = true;
		sUDFTemp = poMaskedEdit.Text;
		poMaskedEdit.PromptChar = sOldPromptChar;
		poMaskedEdit.PromptInclude = vOldPromptInclude;
	}
	return sUDFTemp;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsTrim
DESCRIPTION	Analogue to VBScript Trim function
		
PARAMETERS
	psValue							value to Trim
RETURN VALUES
	Trimmed string
CALLED PROCEDURES
	jsLTrim
	jsRTrim
-----------------------------------------------------------------------------COMMENT*/	
function jsTrim(psValue) {
   return jsRTrim(jsLTrim(psValue));
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsLTrim
DESCRIPTION	Analogue to VBScript LTrim function 
	(except also removes other whitespace chars e.g. crlf)
		
PARAMETERS
	psValue							value to LTrim
RETURN VALUES
	Trimmed string
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsLTrim(psValue) {
   var regEx;
   var ret;
   
   regEx = new RegExp(/^\s*/g);
   ret = psValue.replace(regEx, "");
   return ret;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsRTrim
DESCRIPTION	Analogue to VBScript RTrim function
	(except also removes other whitespace chars e.g. crlf)
		
PARAMETERS
	psValue							value to RTrim
RETURN VALUES
	Trimmed string
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsRTrim(psValue) {
   var regEx;
   var ret;
   
   regEx = new RegExp(/\s*$/g);
   ret = psValue.replace(regEx, "");
   return ret;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsReplace
DESCRIPTION	Analogue to VBScript Replace function
		
PARAMETERS
	psExpression							Expression to perform replace on
	psFind									Substring being searched for
	psReplaceWith						Replacement substring
RETURN VALUES
	A string with substitutions made
CALLED PROCEDURES
	NONE
-----------------------------------------------------------------------------COMMENT*/	
function jsReplace(psExpression,psFind,psReplaceWith){
	var oRegExp = new RegExp(psFind,"g");
	psExpression = psExpression.replace(oRegExp,psReplaceWith);
	return psExpression;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsPopCountrySelectList
DESCRIPTION	
		This function populates a select control with a list of countries from a cache on the client (oMainFrame.msCountryListHTML)
		and selects the correct id in the list
PARAMETERS
	poDiv							Reference to the Div containing the select object
	poSelect						Reference to the Select object
	psCurrentID					The currently selected id of the select object
RETURN VALUES
	NONE or False
CALLED PROCEDURES
	jsGetMainFrameRef					common.js
	jsReplace									common.js
-----------------------------------------------------------------------------COMMENT*/	
function jsPopCountrySelectList(poDiv, poSelect, psCurrentID) {
	var sCountryListHTML;
	var lCountry;
	var oOptions;
	var sSelectID = poSelect.id;
	var oMainFrame = jsGetMainFrameRef();
	
	if (oMainFrame) {
		sCountryListHTML = oMainFrame.msCountryListHTML;
	} else {
		return false;
	}
	poDiv.innerHTML = jsReplace(poDiv.innerHTML,poSelect.innerHTML,sCountryListHTML);
	oOptions = document.getElementById(sSelectID).options;

	psCurrentID = psCurrentID.toUpperCase();
	
	for (lCountry = 0; lCountry < oOptions.length; lCountry++) {
		if (oOptions(lCountry).value.toUpperCase() == psCurrentID) {
			oOptions(lCountry).selected = true;
			lCountry = oOptions.length;
		}
	}
}



function jsInitialiseTableSync(poHeaderTable, poDetailTable, poHeaderDiv, poBodyDiv) {
	var oGhostTableDiv, oGhostTable;
	var iColCount, iCurrColumn;
	var iHeaderTableColCount, iDetailTableColCount;
	var oTR, oTD;
	var iCurrColumnWidth;
	var oTableBody;
	var oCols;
	var bProcessCol;
	
	
	var GHOST_TABLE_ID_PREFIX = "ghost_";
	var GHOST_TABLE_DIV_ID_PREFIX = "div_";
	
	iColCount = poHeaderTable.cells.length;
	poHeaderTable.style.tableLayout = "fixed";
	poHeaderTable.style.width = "100%";
	poDetailTable.style.width = "100%";

	// We want to create a ghost table to get minimium widths
	if (iColCount > 0) {
		oGhostTableDiv = document.createElement("div");
		oGhostTable = document.createElement("table");
		
		oGhostTable.className = poHeaderTable.className;
		oGhostTableDiv.style.width = "4000";
		oGhostTableDiv.style.height = "0";
		oGhostTableDiv.style.overflow = "hidden";
		oGhostTableDiv.style.visibility = "hidden";
		oGhostTable.id = GHOST_TABLE_ID_PREFIX + poHeaderTable.id;
		oGhostTableDiv.id = GHOST_TABLE_DIV_ID_PREFIX + oGhostTable.id;
		oGhostTableDiv.appendChild(oGhostTable);
		
		oTableBody = document.createElement("tbody");
		oGhostTable.appendChild(oTableBody);
		
		oTR = document.createElement("tr"); 
		oTableBody.appendChild(oTR);
		oTR.className = poHeaderTable.rows[0].className;
		
		for (iCurrColumn=0; iCurrColumn < iColCount; iCurrColumn++) {
			oTD = document.createElement("td");
			oTD.innerHTML = poHeaderTable.cells[iCurrColumn].innerHTML;
			oTD.className = poHeaderTable.cells[iCurrColumn].className;
			oTR.appendChild(oTD);
		}
		
		document.body.appendChild(oGhostTableDiv);
		
	}

	// now we have ghost table setup, and are ready to start creating
	// new row to detail table to force minimum widths
	
	// Set detail table minimum column widths
	iHeaderTableColCount = poHeaderTable.rows[0].cells.length;
	iDetailTableColCount = poDetailTable.rows[0].cells.length;
	if (iDetailTableColCount > 0) {
		if (iHeaderTableColCount >= iDetailTableColCount) {
			oTR = document.createElement("TR");
			for (iCurrColumn = 0; iCurrColumn < iDetailTableColCount; iCurrColumn++) {
				oTD = document.createElement("TD");
				oTD.noWrap = true;
				oCols = poHeaderTable.getElementsByTagName("COL");
				bProcessCol = true;
				// test for col elements
				if (oCols) {
					if (oCols.length > iCurrColumn) {
						if (oCols[iCurrColumn].style.display == "none") {
							bProcessCol = false;
						}
					}
				}
				if (bProcessCol) {
					if (poHeaderTable.cells[iCurrColumn].style.display != "none") {
						iCurrColumnWidth = oGhostTable.cells[iCurrColumn].offsetWidth;
						// use empty <img> tags to set the width 
						oTD.innerHTML = '<img style="width:' + iCurrColumnWidth + 'px; height: 0px;">';
					}
					else {
						oTD.style.display = "none";
						oTD.innerHTML = '<img style="width: 0px; height: 0px;">';						
					}
				}
				oTR.setAttribute("widthspecifier","1");
				oTR.appendChild(oTD);
			}
			poDetailTable.tBodies[0].appendChild(oTR);
		}
	}


	//remove ghost table
	oGhostTableDiv.removeNode(true);

	// add additional size to header to ensure scrollbar is present (hidden)	
	var oTD = document.createElement("TD");
	oTD.noWrap = true;
	oTD.style.className = "row1";
	oTD.width = "100px";
	oTD.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;"
	poHeaderTable.rows[0].appendChild(oTD);
	
	mbTableSyncSetWidthDone = true;

}


function jsSyncronizeHeaderAndDetailColumnWidths(poHeaderTable, poDetailTable,poDivHeading,poDivBody) {
	var iHeaderTableColCount;
	var iDetailTableColCount;
	var iCurrColumn;
	
	iDetailTableColCount = poDetailTable.rows[0].cells.length;

	// set header column width equal to body cell width	
	if (iDetailTableColCount > 0) {
		for (iCurrColumn=0; iCurrColumn < iDetailTableColCount; iCurrColumn++) {
			if (poDetailTable.cells[iCurrColumn].offsetWidth != 0) {
				poHeaderTable.cells[iCurrColumn].width = poDetailTable.cells[iCurrColumn].offsetWidth;
			}
		}
	}
	poDivHeading.scrollLeft = poDivBody.scrollLeft;
}



/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsSyncTableColumns
DESCRIPTION	
		
PARAMETERS
	poTableHeading				reference to the table heading object
	poTableBody					reference to the table body object
	poDivHeading				reference to the table heading Div
	poDivBody					reference to the table body Div
	pbForceInitialise (optional)
								true: if you want to force initialise min width 
								false (or nothing): used on resize events only
RETURN VALUES
	NONE
CALLED PROCEDURES
	jsSetTableHeadingWidths	common.js
*/

// static var indicating init done (can override with pbForceInitialise)
// (e.g. for a second table on the same frame/page)
var mbTableSyncSetWidthDone = false; 

//-----------------------------------------------------------------------------COMMENT

function jsSyncTableColumns(poTableHeading, poTableBody, poDivHeading, poDivBody, pbForceInitialise) {
	var e, iWidth;	
	var bForceInitialise = false;
	
	if (arguments.length > 4) {
		bForceInitialise = pbForceInitialise;		
	}
	
	if(!poTableHeading || !poTableBody || !poDivHeading || !poDivBody) return
	
	try {
		if (!mbTableSyncSetWidthDone || bForceInitialise) {			
			jsInitialiseTableSync(poTableHeading, poTableBody, poDivHeading, poDivBody);			
		}
	} catch (e)  {	}				
	
	try {
		jsSyncronizeHeaderAndDetailColumnWidths(poTableHeading, poTableBody, poDivHeading, poDivBody);		
	} catch (e)  {	}				
}


// Sync the table header and body (divs) on a scroll event.
function jsSyncTableScroll(poDivHeading, poDivBody) {
	if (poDivHeading.scrollLeft != poDivBody.scrollLeft) {
		poDivHeading.scrollLeft = poDivBody.scrollLeft;
	}
}

function jsEoAttribute(psXML){
	var oRegEx
	var iEoElement
	var iEoAttribute
	   
	iEoAttribute = psXML.search(/\s/i)
	iEoElement = psXML.search(/>/i)
	if(iEoAttribute < iEoElement && iEoAttribute != -1){
		return(iEoAttribute)
	}
	else{
		if(iEoElement == -1){
			return(iEoAttribute)
		}
		else{
			return(iEoElement)
		}
	} 
	return(-1)
}


/*     ----- Example local sync function in client code ----
		Call this function on the following oDivBody events: onresize,onscroll and on initial display
		Note: the heading table must have style="table-layout:fixed", body must not be fixed.
		Client-code is responsible for changing the height/width of the results div on resize.
		
		example oDivBody element:
		<div id="divBody" style="height:250px;width:50px;overflow:auto;" 
				onscroll="jsLocalSyncColumns()" 
				onresize="setTimeout('jsLocalSyncColumns()',300)" >
				
// pbForceInit : optional		
function jsLocalSyncColumns(pbForceInit) {
	var oTableHeading, oTableBody, oDivBody, oDivHeading;	
	var e;
	
	// get results div/table object refs 
	try {
		oTableHeading = document.all.tableHeadingCustomer;
		oTableBody = document.all.tableBodyCustomer;
		oDivHeading = document.all.divResultsHeadingCustomer;
		oDivBody = document.all.divResultsBody;
	} catch (e) {}
	
	jsSyncTableColumns(oTableHeading, oTableBody, oDivHeading, oDivBody, pbForceInit);
}


*/

function jsTrapBackNavigation() {
	// we want to stop IE naviagting when the backspace key is pressed
	if (window.event.keyCode == 8) {
		// did the event come from somewhere that can handle text editing
		if (window.event.srcElement.isTextEdit) {
			// it did, check to see if event came from the body tag
			if (window.event.srcElement === document.body) {
				// it did, so stop the event
				window.event.returnValue = false;
			}
		} else {
			// the event source can't handle editting text, so swallow the backspace
			window.event.returnValue = false;
		}
	}
}
/*COMMENT-----------------------------------------------------------------------------
FUNCTION:		jsParseUrlSearchString
DESCRIPTION		Parses the search portion of a url string and places the parameters passed
				on the search string into a two dimensional array.
PARAMETERS
	psSearch		String containing the search portion of a url. 
				For example, the following string is the search portion of a url:
				"?mode=EDIT&ownerId=7E5B28A7-5979-45A7-B578-B4265BF03D7E&ownerType=2&commentId=44E16DF9-58D6-4C94-881F-1322E6C1BF6C&commentSecId=49312923816363019"
				"http://localhost/marylebone/website/comments/comment_edit.htm?mode=EDIT&ownerId=7E5B28A7-5979-45A7-B578-B4265BF03D7E&ownerType=2&commentId=53D885CF-2D87-4594-965D-A2EFF6FD7A0E&commentSecId=24304"
				
				You can get the search string from 'window.location.search'.
RETURN VALUES
				A two-dimensional array containing the parameters and their values. First dimension
				contains the parameter name and the second the parameter value. There is a row for each
				parameter in the string.
				
CALLED PROCEDURES
	NONE

SAMPLE CODE USING THE RETURNED ARRAY
				The following sample code gets values from the array and puts them in
				variables to be used within the code
				//********* begin sample code **********
				var idx;
				for (idx in paParameters) {							// Loop through all of the params
					switch (paParameters[idx][0].toUpperCase()) {	// look for specific params
						case "MODE":								// MODE is a parameter name
							sMode = paParameters[idx][1];			// the value is loaded into a variable named sMode
							break;
					case "COMMENTID":
						sCommentId = paParameters[idx][1];
						break;
					default:										
						break;	
					}
				}
				//********* end sample code **********

-----------------------------------------------------------------------------COMMENT*/	
function jsParseUrlSearchString(psSearch) {
	if (psSearch == "") {
		return psSearch;
	}
	else {
		var idx;
		var aNewArray = new Array();
		psSearch = psSearch.replace("?","");	//removed the ? at the start of the querystring
		var aParsed = psSearch.split("&");
		for (idx in aParsed) {
			aNewArray[idx] = aParsed[idx].split("=");
		}
		return aNewArray;
	}
}


/*COMMENT-----------------------------------------------------------------------------
FUNCTION:			jsFormatIndividualName
DESCRIPTION			Formats individual name using different display types/formats
		
PARAMETERS
	piType			name format type: long, short, email, mailing
	psPrefix			individual salutation/prefix
	psFirstName		individual first name
	psMiddleName		individual middle name
	psLastName		individual last name
	psSuffix			individual suffix

RETURN VALUES
	Concatenated/formatted individual name
CALLED PROCEDURES
	format_names.js:formatIndividualName(...) (via main_frame.js)  
-----------------------------------------------------------------------------COMMENT*/	

function jsFormatIndividualName(piType, psPrefix, psFirstName, psMiddleName, psLastName, psSuffix) {
    var oMainFrame = jsGetMainFrameRef();
    var oError;

    try {
    	if (oMainFrame == false){
            return "Internal Error: COMMON_JS.jsFormatIndividualName(): Cannot find main frame";
        }
        return oMainFrame.formatIndividualName(piType, psPrefix, psFirstName, psMiddleName, psLastName, psSuffix);
    } catch(oError){
        return "Internal Error: COMMON_JS.jsFormatIndividualName(): Unknown error occurred";
    }
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:			jsSafeHTMLtoStr(psStr)
DESCRIPTION			returns unescaped HTMl
		
PARAMETERS
	psStr - escaped string

RETURN VALUES
	unescaped HTML
CALLED PROCEDURES
	none 
-----------------------------------------------------------------------------COMMENT*/
function jsSafeHTMLtoStr(psStr){
	psStr = psStr.replace(/&lt;/g,"<");
	psStr = psStr.replace(/&gt;/g,">");
	psStr = psStr.replace(/&quot;/g,'"');
	psStr = psStr.replace(/&#39;/g,"'");
	psStr = psStr.replace(/&apos;/g,"'");
	psStr = psStr.replace(/&amp;/g,"&");
	
	return psStr;
}

/*COMMENT-----------------------------------------------------------------------------
FUNCTION:			jsSafeRegExp(psStr)
DESCRIPTION			returns unescaped HTMl
		
PARAMETERS
	psStr - string to make safe for regular expression

RETURN VALUES
	literal expression string
CALLED PROCEDURES
	none 
-----------------------------------------------------------------------------COMMENT*/
function jsSafeRegExp(psStr){
	psStr = psStr.replace(/\{$/gim,"\\{$");	
	psStr = psStr.replace(/\$/gim,"\\$");
	psStr = psStr.replace(/\}/gim,"\\}");
	psStr = psStr.replace(/\[/gim,"\\[");
	psStr = psStr.replace(/\]/gim,"\\]");
	psStr = psStr.replace(/\(/gim,"\\(");
	psStr = psStr.replace(/\)/gim,"\\)");
	var re = new RegExp("\\/","gim");
	psStr = psStr.replace(re,"\\/");
	psStr = psStr.replace(/\./gim,"\\.");
	psStr = psStr.replace(/\?/gim,"\\?");
	psStr = psStr.replace(/\s+/gim,"\\s+");
	return psStr;
}

/*-----------------------------------------------------------------------------
FUNCTION:			jsValidEmailAddress((psEmailAddress)
DESCRIPTION			returns unescaped HTMl
		
PARAMETERS
	psEmailAddres - string containing email address to validate

RETURN VALUES
	boolean
CALLED PROCEDURES
	none 
-----------------------------------------------------------------------------*/
function jsValidEmailAddress(psEmailAddress){
	// 03292007 twong: email address allow "slash" as character
	//var oFilter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
	var oFilter  = /^([a-zA-Z0-9_\'\_\/\_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
	return psEmailAddress == '' || oFilter.test(psEmailAddress)
}


/*-----------------------------------------------------------------------------
FUNCTION:			fillComboFromXmlNode
DESCRIPTION			fill a combo using xml data (with a node reference)
PARAMETERS
	poCombo [combo DOM object]
	poXmlNode [xml node]
		- node object as starting point for xpath 
	psItemNodeXPath [string]
		- string with the Xpath to each item node (this is used selectNodes) e.g. "items/item"
	pbIncludeBlank [boolean]
		- if true, will include a blank combo value [first item]	

RETURN VALUES
	success flag [boolean]
NOTES
	xml should contain a collection containing nodes "id" and "value" (e.g. the appcache xml for reference data)
-----------------------------------------------------------------------------*/
function fillComboFromXmlNode(poCombo, poXmlNode, psItemNodesXPath, pbIncludeBlank) {
	var oOption;
	var oColNode;
	var iColCount = 0;
	
	if (!poCombo) {
		return false;
	}
	if (!poXmlNode) {
		return false;
	}

	poCombo.options.length = 0
	if (pbIncludeBlank) {
		oOption = document.createElement("option");
		poCombo.options.add(oOption);
	}
	var oRows = poXmlNode.selectNodes(psItemNodesXPath);
	if (oRows) {
		var oRow = oRows.nextNode();
		var oOptions = poCombo.options;
		while (oRow) {
			oOption = document.createElement("option");
			oOption.value= oRow.selectSingleNode("id").text;
			oOption.text = oRow.selectSingleNode("value").text;
			oOptions.add(oOption);
			oRow = oRows.nextNode();
		}
	}
	
	return true;
}

//Consona CRM - IE8 Patch Begin
//Following two functions are to fix the IE8 XML problem.
//The XML problem bug numbers are 97510,97514,97528,97529,97530,97532,97533,97534,97535,97537.
function jsIE8FreeThreadXMLDOMFix(psSourceXML) {
    var tmpXMLDOM = new ActiveXObject("MSXML2.FreeThreadedDomDocument.3.0");
    tmpXMLDOM.loadXML(psSourceXML.xml);
    return tmpXMLDOM;
}

function jsIE8SimpleXMLDOMFix(psSourceXML) {
    var tmpXMLDOM = new ActiveXObject("Msxml2.DOMDocument");
    tmpXMLDOM.loadXML(psSourceXML.xml);
    return tmpXMLDOM.documentElement;
}

// Only create a timer reference if the timer code is switched on
function jsIE8InitializeTimer(){
	if (gbTimerEnabled && gbUseNewProfileCode) {
		goTimer = new XTimer();
		goTimer.initializeTimer(gsUserId,2);
	}
}	
//Consona CRM - IE8 Patch End
