//-------------------------------------------------------------------------------- 
// Window related Browser / Client Side Script Functions
// Note : Assumption is that browsers download this js and then cache it
//        So Bandwidth Optimisation isn't such an issue. This needs confirmation!
//--------------------------------------------------------------------------------
// Global popup window handle
var hpopupWindow = null;
var enterKeyCancel = false;
var bModal = false;
var XML_NULLVALUE_STR = '[NULL]';
var N=null;
var F=false;
var T=true;
var XML_TAG_ROOT_OPEN = '<xml>';
var XML_TAG_ROOT_CLOSE = '</xml>';

// Note : Currently, there is NO WAY in javascript to determine which element has the focus.
// We must track it MANUALLY as per the following
var m_elmInFocus;

function trackFocus() {
// alert('have just set focus on ' + v_elmObject.name + ' which is a ' + v_elmObject.type);
	try{
		m_elmInFocus = event.srcElement;
// alert('Focus is now on ' + v_sElement + ' which is a ' + document.genericCapture.getElementById(v_sElement).type);
	}
	catch(e){
	}
}

// Set Focus Tracker handlers for all Elements in the Form
function setFocusTracker(v_form){
	var n;
	var e;
	for (n=0; n < v_form.elements.length; n++) { 
		try{
			e = v_form.elements[n];
			e.attachEvent('onfocus', function() {trackFocus()});
		}
		catch(e){
		}
	}
}

//--------------------------------------------------------------------------------
// Creates a new window (Modal or Modeless) and loads the specified URL past
function OpenNewWindow(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle){
    var sFeatures;
    var nLeft = (screen.Width - nWidth) / 2;
    var nTop = (screen.Height - nHeight) / 2;
    var hWindow;

	// We are going to be appending the bModal flag to the QString
    sURL=setURLParam(sURL, 'bModal', utlMiscBoolToInt(bModal))
    sFeatures = 'status=yes,resizable=no,toolbar=no,menubar=no,location=no,center=yes,help=no';
    // Noting that Modal Dialogs and Modeless Windows use different styles
    if (bModal){
        // Stuff knows why dialogs want : and ; ...
        sFeatures+=';dialogHeight:'+nHeight+"px";
        sFeatures+=';dialogWidth:'+nWidth+"px";
        sFeatures+=';dialogLeft:'+nLeft+"px";
        sFeatures+=';dialogTop:'+nTop+"px";
    }
    else{
	    if (bHideScrollBars)
		    sFeatures += ',scrollbars=no';
	    else
		    sFeatures += ',scrollbars=yes';

	    sFeatures += ',height=' + nHeight;
	    sFeatures += ',width=' + nWidth;
	    sFeatures += ',left=' + nLeft;
	    sFeatures += ',top=' + nTop;
    }
	if (hToCloseHandle != null){
		hToCloseHandle.close();
		hToCloseHandle = null;
	}
    if (bModal){
	    // Joe Fawcett  http://p2p.wrox.com/topic.asp?TOPIC_ID=6749 - only way to access an "Opener" from an IE Modal Window
        hWindow = window.showModalDialog(sURL, self, sFeatures);
    }
    else{
	    hWindow = window.open(sURL, '_blank', sFeatures);
	    hWindow.focus();
    }

	return hWindow;
}

//--------------------------------------------------------------------------------
// High Bandwidth Squeeze "Optimisation" of the Above
function ONW(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle)
{
    return OpenNewWindow(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle);
}

// Open a new MODAL Window
function OpenNewModalWindow(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle){
    bModal = true;
    OpenNewWindow(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle);
    bModal = false;
}

// High bandwidth version of the above
function ONMW(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle){
    OpenNewModalWindow(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle);
}

//--------------------------------------------------------------------------------
// Creates a new window and loads the specified URL past
function OpenNewWindowNoReturn(sURL, nHeight, nWidth, bHideScrollBars, hToCloseHandle)
{
var sFeatures;
var nLeft = (screen.Width - nWidth) / 2;
var nTop = (screen.Height - nHeight) / 2;
var hWindow;

	sFeatures = 'status=yes,resizable=no,toolbar=no,menubar=no,location=no';
	if (bHideScrollBars)
		sFeatures += ',scrollbars=no';
	else
		sFeatures += ',scrollbars=yes';
	sFeatures += ',height=' + nHeight;
	sFeatures += ',width=' + nWidth;
	sFeatures += ',left=' + nLeft;
	sFeatures += ',top=' + nTop;

	if (hToCloseHandle != null)
	{
		hToCloseHandle.close();
		hToCloseHandle = null;
	}
		
	hWindow = window.open(sURL, '_blank', sFeatures);
	hWindow.focus();
}

//--------------------------------------------------------------------------------
// 
//--------------------------------------------------------------------------------
function resizeWindow(nWidth, nHeight) {
	window.resizeTo(nWidth, nHeight);
}

//--------------------------------------------------------------------------------
// Displays the 'sMessage' parameter string on the status bar of the browser.
function statusbarMessage(sMessage) {
	window.status = sMessage;
}

//--------------------------------------------------------------------------------
// Abbreviated BW sensitive version of above
function setSBM(sMessage) {
	statusbarMessage(sMessage);
}

//--------------------------------------------------------------------------------
function setClass(oThis, sClassName) {
	oThis.className = sClassName;
}

//--------------------------------------------------------------------------------
// FUNTION NAME:  GETTURLPARAM
//--------------------------------------------------------------------------------
// Gets a Parameter from the URL
function getURLParam(v_sURL, v_sParamName)
{
var nPos1 = v_sURL.indexOf('?');
var sParms = '?';
var sValue = '';
var sPARAMNAME = v_sParamName.toUpperCase();
var nPARAMNAME = v_sParamName.length;

	if (nPos1 != -1)
	{
	  var saSplit = v_sURL.substr(nPos1 + 1).split('&');
		v_sURL = v_sURL.substr(0, nPos1)

		var bFound = 0;
	  for (var i = 0; i < saSplit.length; i++)
	  {
			if (saSplit[i].substr(0, nPARAMNAME).toUpperCase() == sPARAMNAME)
			{
			  var saKVPair = saSplit[i].split('=');
			  if (saKVPair[1] != null)
					sValue = saKVPair[1];
			}
	  }
	}

	return(sValue);
}

//--------------------------------------------------------------------------------
// FUNTION NAME:  SETURLPARAM
//--------------------------------------------------------------------------------
// Adds a new Parameter to the URL   or   Replaces an existing parameter's value
function setURLParam(v_sURL, v_sParamName, v_sParamValue) {
var nPos1 = v_sURL.indexOf('?');
var sParms = '?';
var sPARAMNAME = v_sParamName.toUpperCase();
var nPARAMNAME = v_sParamName.length;

	if (nPos1 != -1) {
	    var saSplit = v_sURL.substr(nPos1 + 1).split('&');
		v_sURL = v_sURL.substr(0, nPos1)

		var bFound = 0;
	    for (var i = 0; i < saSplit.length; i++) {
			if (saSplit[i].substr(0, nPARAMNAME).toUpperCase() == sPARAMNAME) {
				if (i > 0) sParms += '&';
				sParms += v_sParamName + '=' + v_sParamValue;
				bFound = 1;
			}
			else {
				if (i > 0) sParms += '&';
				sParms += saSplit[i];
			}
	    }
	    if (bFound == 0) {  // If not found, add to parameter string of URL
			sParms += '&' + v_sParamName + '=' + v_sParamValue;
		}
		v_sURL += sParms;
	}
	else {
		v_sURL += sParms + v_sParamName + '=' + v_sParamValue;
	}

	return(v_sURL);
}

//--------------------------------------------------------------------------------
// FUNCTION NAME:  removeURLPARAM
//--------------------------------------------------------------------------------
// Removes an existing parameter
function removeURLParam(v_sURL, v_sParamName) {
var nPos1 = v_sURL.indexOf('?');
var sParms = '?';
var sPARAMNAME = v_sParamName.toUpperCase();
var nPARAMNAME = v_sParamName.length;

	if (nPos1 != -1) {
	    var saSplit = v_sURL.substr(nPos1 + 1).split('&');
		v_sURL = v_sURL.substr(0, nPos1)

		for (var i = 0; i < saSplit.length; i++) {
			if (saSplit[i].substr(0, nPARAMNAME).toUpperCase() == sPARAMNAME) {
				continue;
			}
			if (i > 0) sParms += '&';
			sParms += saSplit[i];
	    }
		v_sURL += sParms;
	}
	else {
		v_sURL += sParms + v_sParamName + '=' + v_sParamValue;
	}

	return(v_sURL);
}

//--------------------------------------------------------------------------------
// FUNTION NAME:  windowShowProcessing
//--------------------------------------------------------------------------------
// Swops client frontend displays with processing message
function windowShowProcessing() {
	enterKeyCancel = true;
	document.all.divForm.style.display = "none";
	document.all.divProcessing.style.display = "block"			
}

//--------------------------------------------------------------------------------
// FUNTION NAME:  formatFloat
//--------------------------------------------------------------------------------
// Formats a floating point number (up to max of 6 decimal places)
//--------------------------------------------------------------------------------
// Surely there has to be a *#@(* out of the box function to do this ...
function formatFloat(num, decimals) {
    var sReturn = num.toString();
    // Add in a decimal point if not already one present
    if (sReturn.indexOf('.') < 0){
        sReturn += '.';
    }
    // Realistic amount of trailing zeroes
    sReturn += '000000';

    // RMCQ 5696 - Nuke the (&*(@# thousands separator ...
    sReturn = sReturn.replace(',', '');
    var numA = sReturn.split('.');

    sReturn = numA[0].toString() +'.'+ numA[1].toString().substr(0,decimals);
    return sReturn;
}

//--------------------------------------------------------------------------------
// FUNTION NAME:  Trim
function Trim(strValue) {	
	objRegExp = /^(\s*)([\W\w]*)(\b\s*$)/;
    if(objRegExp.test(strValue)) {
       //remove leading and trailing whitespace characters
       strValue = strValue.replace(objRegExp, '$2');
    }
  	return strValue;
}


//--------------------------------------------------------------------------------
// FUNTION NAME:  doDateOptChange
function doDateOptChange(nDateType, oDateFrom) {
	if(nDateType==3) 
		oDateFrom.style.visibility = 'visible'
	else
		oDateFrom.style.visibility = 'hidden'
}		

//--------------------------------------------------------------------------------
// FUNTION NAME:  doPopulateDateFields
function doPopulateDateFields(nDateType, oDateField, dtDateFrom, dtDateTo){		
	
	if(!dtDateFrom) dtDateFrom = "";
	if(!dtDateTo) dtDateTo = "";
	
	switch (nDateType) {
		case '0': //on						
			if(Trim(dtDateFrom).length>0)
				oDateField.value = dtDateFrom + ';' + dtDateFrom;
			break;
		case '1': //before
			if(Trim(dtDateFrom).length>0)
				oDateField.value = ';' + dtDateFrom;
			break;
		case '2': //after	
			if(Trim(dtDateFrom).length>0)
				oDateField.value = dtDateFrom + ';';	
			break;
		case '3': //between			
			if(Trim(dtDateFrom).length==0 && Trim(dtDateTo).length==0)
				oDateField.value = "";
			else
				oDateField.value = dtDateFrom + ';' + dtDateTo;			
			break;
	}	
}

//--------------------------------------------------------------------------------
// FUNCTION NAME:  godoSOAP Do a "Soap" Call from Browser back to Server
// URL is of the form
// <g_sDirCommon>Execute.asp?sProgID=CCPresentation.CP_XYZ&sAction=SOME_ACTION&sXML=<xml>xxx</xml>&sActionDescription=SomeDescription&bReturnXML=true"
function godoSOAPOld(sURL){
	try{
	    var dom = new ActiveXObject("MSXML.DOMDocument");
	    dom.async = false;
	    if (dom.load(sURL))
		    return dom;
	    else {
            alert('Could not dom.Load URL ' + sURL);
		    return null;
		}
    }
    catch (e){
        alert(e.description + ' - ' + e.number);
        if (dom == null)
            alert('DOM IS NULL');
    }
}


// Due to increasing number of (?possibly a Windows Update or Security Issue), make the "Old" soap look like new SOAP
function godoSOAP(v_sURL){
    var sXML;
    var sURL;
    
    sURL = v_sURL;
    // RMACM00006282 : Must URL decode the XML first
    sXML = urlDecode(getURLParam(sURL, "sXML"));
    sURL = removeURLParam(sURL,  "sXML");

    return godoBigSOAP(sURL, sXML);
}


//--------------------------------------------------------------------------------
// As per godoSOAP, however, uses the XMLHTTP object and not DOM.load. This is because DOM.load has an inherent limitation of
// 2048 bytes in the "Send" URL, since DOM.load uses GET and not POST!
// Note that the XML must be passed separately (i.e. not sXML=<xml>....)
function godoBigSOAP(sURL, sXML){
	var xhtp = new ActiveXObject("Microsoft.XMLHTTP");
	var dom = new ActiveXObject(XML_DOMDOCUMENT_PROGID);
	dom.async = false;	
    xhtp.open('POST', sURL + '&bBigXML=1', false);
	xhtp.send(sXML);
	// Still trying to find decent status codes. 0 doesn't mean success.
    // if (xhtp.status != 0){
    //    alert('SOAP Error : ' + xhtp.responseText);
    //    return null;
    // }

    // Big fugly, but use the Globals to indicate status back to caller
    g_nErrorNumber = 0;
    g_sErrorMessage = '';

    dom.loadXML(xhtp.responseText);
	// Note that g_nErrorNumber globals are declared in CC2Handlers.js :( 
    // Think they belong here ...    
    if (dom != null){
		var ndeErr = dom.selectSingleNode('//nErrorNumber');
		if (ndeErr != null){
			g_nErrorNumber = utlMiscZeroIfNull(ndeErr.text);
			g_sErrorMessage = dom.selectSingleNode('//sDisplayStatus').text;
		}
    }
    else {
        g_nErrorNumber = -1;
        g_sErrorMessage = 'SOAP Call Failed';
    }
    
    return dom;
}

// Javascript Function decodes escape / special chars encoded within XML
// In : sXMLIn - String - String to decode
// Return : String - Decoded XML
function xmlDecode(sXMLIn) {
    var sXMLOut;
    sXMLOut = sXMLIn;
    sXMLOut = sXMLOut.replace("&gt;", ">");
    sXMLOut = sXMLOut.replace("&lt;", "<");
    sXMLOut = sXMLOut.replace("&quot;", '"');
    sXMLOut = sXMLOut.replace("&apos;", "'");
    sXMLOut = sXMLOut.replace("&amp;", "&");	 // Note, '&amp;' needs to be decoded last!!

    return sXMLOut;
}

// Javascript Function encodes escapes / special chars encoded within XML
// In : sXMLIn - String - String to encode
// Return : String - Encoded XML
function xmlEncode(sXMLIn) {
    var sXMLOut;
    sXMLOut = sXMLIn;
	sXMLOut = vbReplace(sXMLOut, "&", "&amp;");
	sXMLOut = vbReplace(sXMLOut, ">", "&gt;");
	sXMLOut = vbReplace(sXMLOut, "<", "&lt;");
	sXMLOut = vbReplace(sXMLOut, '"', "&quot;");
	sXMLOut = vbReplace(sXMLOut, "'", "&apos;");
    return sXMLOut;
}

// Used in SOAP calls to encode the XML String
// Surely there must be a vanilla jscript function to do this !!!
function urlEncode(sIn) {
    var sOut = sIn;
    sOut = sOut.replace("&", "%26");
    sOut = sOut.replace(" ", "%20");
    sOut = sOut.replace("?", "%3F");
    return sOut;
}

// Used in SOAP calls to encode the XML String
// Surely there must be a vanilla jscript function to do this !!!
function urlDecode(sIn) {
    var sOut = sIn;
    sOut = sOut.replace("%26", "&");
    sOut = sOut.replace("%20", " ");
    sOut = sOut.replace("%3F", "?");
    return sOut;
}

// Function suited to 'scraping' numerics off formatted input fields, notably by removing currency and and thousands separators
function stringToNumber(sIn){
    var sOut = sIn;
    sOut = sOut.replace(",", "");
    sOut = sOut.replace("%", "");
    sOut = sOut.replace("R", "");
    sOut = sOut.replace(" ", "");
    return sOut;
}

// Simple function to redirect the page
function redirect(sURL){
	window.location.href = sURL;
}
// Returns Zero if the value is NULL or non numeric etc
function utlMiscZeroIfNull(vVal){
    // Catch GIGO first
	if (vVal == null){
        return 0;
    }
    if (vVal == undefined){
        return 0;
    }

    vVal = vVal.toString();
	if (vVal.indexOf('.') >= 0) {
		// Try for Float
		if (isNaN(parseFloat(vVal))){
			return 0;
		}
		else {
			return parseFloat(vVal);
		}
	}
	else {
		// Try for Integer
		if (isNaN(parseInt(vVal))){
			return 0;
		}
		else {
			return parseInt(vVal);
		}
	}
}
// Return a blank if vVal is null
function utlMiscBlankIfNull(vVal){
    if (vVal == null){
        return '';
    }
    return vVal;
}
// Return a blank if vVal is null
function utlMiscDefaultIfNull(vVal, vDefault){
    // Note : The ASP VB Script version is more comprehensive - it detects the 'type' of vDefault and determines if vVal is of Same Type
    // However, doesn't seem as if have nice 'isDate' and 'isNumber' (parseInt) type functions in JavaScript
    if (vVal == null){
        return vDefault;
    }
    else {
        return vVal;
    }
}


// Return an Integer representation of a Boolean (True = 1, False = 0)
function utlMiscBoolToInt(vBool){
    if (vBool){
        return 1;
    }
    else{
        return 0;
    }
}

// Close a Quick Menu (e.g. Requirements, Quick Add etc)
function closeQuickMenu(ind){
	eval("qmenuOpen"+ind).style.visibility="hidden";
	eval("qmenuClose"+ind).style.visibility="visible";
	eval("qmenuClose"+ind).style.display="block";
}

// Open a Quick Menu
function openQuickMenu(ind){
	eval("qmenuOpen"+ind).style.visibility="visible";
	eval("qmenuOpen"+ind).style.display="block";
	eval("qmenuClose"+ind).style.visibility="hidden";
}

function encodeCalcOperands(sCalcOps){
    // JS doesn't like NL's in Strings
    return sCalcOps.replace( /(\r?\n|\r){1,2}/g, ' '); 
}
function onShowAllRecords(nVal){
	location=setURLParam(self.location.href,"bNoLimitLists",nVal);
}
function onHideDeleted(nVal){
	location=setURLParam(self.location.href,"bHideDeleted",nVal);
}
// Return the window's opener (Works for both MODAL and Non-Modal Windows
// Returns NULL if can't find one!
function getOpener(){
    // NB : Resist the temptation to call this var "opener!!!"
    var o;
    try{
        var o = window.opener;
        if (o == null){
            // A Null opener typically means this is a modal dialog. 
            // Thanks to Joe Fawcett  http://p2p.wrox.com/topic.asp?TOPIC_ID=6749 - only way to access an "Opener" from an IE Modal Window
            o = window.dialogArguments;
        }
    }
    catch(e){
        o = null;
    }
    return o;
}
// XML Function to return the Text of a Node (Element)
// XML Dom Overload
function utlXMLGetNodeTextDOMNoNull(v_oDOM, v_sNodeName){
	var oNode;
	var vValue;

	if (v_oDOM != null){
		oNode = v_oDOM.selectSingleNode(v_sNodeName);
		if (oNode != null){
			vValue = oNode.text;
			if (vValue == XML_NULLVALUE_STR){
				vValue = "";
			}
            else{
				vValue = xmlDecode(vValue);
			}
        }
	}
    return vValue;
}
// Refresh the Page to the same Location
function refreshPage(){
	self.location.href=self.location.href;

}
// Moved from incFormDisplay.asp
function setfocus(sFocusItem){
	try {
		var itmFocus = document.genericCapture.getElementById(sFocusItem);
        if (itmFocus){
			itmFocus.select();
			itmFocus.focus();
		}
	}
    
  catch(ex){
    // Sweep any annoying script errors under the carpet
	}
}
// NB : Note that JavaScripts string.replace method only replaces first occurrence
// Thanks to Neil Mitchell http://www.nmitchell.co.uk/code/javascript.htm
function vbReplace(str, find, rep){
    var res = str.toString();
    var i = 0;
    while(true) {
        i = res.indexOf(find, i);
        if (i == -1) 
			break;
        res = res.substr(0, i) + rep + res.substr(i + find.length);
        i += rep.length;
    }
    return res;
}

// Get the "Current" URL (e.g. to replace the VB m_sThisURL function
function getCurrentURL(){
	return window.location.href;
}

// Method called when needing to search Validation/Code Tables by Description
// ie: Event, Activity on Person Event and On Disease Add screen
function DoGenericLookUp(v_oSearch, v_oElement, v_sDescLookUpURL){
	if (v_oSearch.value != "") {
		if (v_oSearch.value.toString().length > 2) {
			DoLookup(v_oElement, v_sDescLookUpURL, null, "", true);
		}
		else {
			alert("Please enter at least THREE characters to Search On.");
			v_oSearch.select();
			v_oSearch.focus();
			return;
		}
	}
	else {
		v_oElement.options.length = 0;
	}
				
	if (v_oElement.options.length > 1){
		v_oElement.className = "InputField";
		v_oElement.options(0).text = "Please select one from the list...";
		if (v_oElement.options.length == 2) {
			v_oElement.selectedIndex = 1;
		}
	}
	else {
		v_oElement.className = "InputFieldEmpty";
		v_oElement.options.length = 0;
		AddOption(v_oElement, "", "No Codes Found Matching Search");
	}
	v_oElement = null;
}

// Adds an option to a Drop Down Combo
function AddOption(v_objDropDown, v_sKey, v_sDescription){
	var opt;
	
	opt = document.createElement("OPTION");
		
	opt.text = v_sDescription;
	opt.value = v_sKey;
	v_objDropDown.add(opt);
		
	opt = null;
}

function DoLookup(v_objDropDown, v_sLookupURL, v_objGetIDFrom, v_sFilterTagName, v_bAllowNull) {
	var dom;
	var ndl;
	var nde;
	
	if (v_objGetIDFrom != null) {
		// Add in extra filter (Assumes that XML is the last Param on the Q String!!)
		v_sLookupURL = v_sLookupURL + "<" + v_sFilterTagName + ">" + v_objGetIDFrom.value + "</" + v_sFilterTagName + ">";
	}
	v_objDropDown.options.length = 0;

	if (v_bAllowNull){
		AddOption(v_objDropDown, "", "");
	}
	
	var xhtp = new ActiveXObject("Microsoft.XMLHTTP");
	var dom = new ActiveXObject(XML_DOMDOCUMENT_PROGID);
	dom.async = false;	
    xhtp.open("GET", v_sLookupURL, false);
	xhtp.send("");
    if (dom.loadXML(xhtp.responseText)) {
		ndl = dom.selectNodes("//LookUp");
		for (var i = 0; i < ndl.length; i++) {
			nde = ndl(i);
			AddOption(v_objDropDown, nde.selectSingleNode("sKey").text, nde.selectSingleNode("sDescription").text);
		}
	}

	v_objDropDown.fireEvent('onchange');

	dom = null;
	ndl = null;
	nde = null;
}
