diff --git a/shrine-webclient/src/main/html/i2b2_config_data.js b/shrine-webclient/src/main/html/i2b2_config_data.js index c7055a079..e6e922154 100644 --- a/shrine-webclient/src/main/html/i2b2_config_data.js +++ b/shrine-webclient/src/main/html/i2b2_config_data.js @@ -1,24 +1,26 @@ { urlProxy: "/shrine-proxy/request", urlFramework: "js-i2b2/", loginTimeout: 15, // in seconds //JIRA|SHRINE-519:Charles McGow username_label:"SHRINE Username:", //Username Label password_label:"SHRINE Password:", //Password Label clientHelpUrl: 'help/pdf/shrine-client-guide.pdf', networkHelpUrl:'help/pdf/shrine-network-guide.pdf', wikiBaseUrl: 'https://open.med.harvard.edu/wiki/display/SHRINE/', + obfuscation: 10, + resultName: "patients", //JIRA|SHRINE-519:Charles McGow // ------------------------------------------------------------------------------------------- // THESE ARE ALL THE DOMAINS A USER CAN LOGIN TO lstDomains: [ { domain: "i2b2demo", name: "SHRINE", urlCellPM: "http://127.0.0.1/i2b2/services/PMService/", allowAnalysis: false, debug: true, isSHRINE: true } ] // ------------------------------------------------------------------------------------------- } diff --git a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryStatus.js b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryStatus.js index 19a689f36..798408277 100644 --- a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryStatus.js +++ b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryStatus.js @@ -1,657 +1,630 @@ /** * @projectDescription The Asynchronous Query Status controller (GUI-only controller). * @inherits i2b2.CRC.ctrlr * @namespace i2b2.CRC.ctrlr.QueryStatus * @author Nick Benik, Griffin Weber MD PhD * @version 1.0 * ---------------------------------------------------------------------------------------- * updated 8-10-09: Initial Creation [Nick Benik] */ function cgmUtcDateParser(dateString){ //Date format: 2011-02-21T14:35:03.480-05:00 try{ splitDateAndTime = dateString.split("T"); vrDate = splitDateAndTime[0].split("-"); vrTime = splitDateAndTime[1].split(":"); strYear = vrDate[0]; strMonth = vrDate[1] - 1; strDay = vrDate[2]; /* alert("Year: "+ strYear); alert("Month: "+ strMonth); alert("Day: "+ strDay);*/ strHours = vrTime[0]; strMins = vrTime[1]; strSecs = null; strMills = null; vSecs = vrTime[2].split("."); strSecs = vSecs[0]; vMills = vSecs[1].split("-"); strMills = vMills[0]; /* alert("Hours: "+ strHours); alert("Minutes: "+ strMins); alert("Seconds: "+ strSecs); alert("MilliSeconds: "+ strMills);*/ return new Date(strYear, strMonth, strDay, strHours, strMins, strSecs, strMills); } catch(e){ return null; } } i2b2.CRC.ctrlr.QueryStatus = function(dispDIV) { this.dispDIV = dispDIV; }; i2b2.CRC.ctrlr.currentQueryResults = null; function trim(sString) { while (sString.substring(0,1) == '\n') { sString = sString.substring(1, sString.length); } while (sString.substring(sString.length-1, sString.length) == '\n') { sString = sString.substring(0,sString.length-1); } return sString; } i2b2.CRC.ctrlr.QueryStatus.prototype = function() { var private_singleton_isRunning = false; var private_startTime = false; var private_refreshInterrupt = false; function private_refresh_status() { // callback processor to check the Query Instance var scopedCallbackQRSI = new i2b2_scopedCallback(); scopedCallbackQRSI.scope = self; scopedCallbackQRSI.callback = function(results) { if (results.error) { alert(results.errorMsg); return; } else { // find our query instance var ri_list = results.refXML.getElementsByTagName('query_result_instance'); var l = ri_list.length; for (var i=0; i<l; i++) { var temp = ri_list[i]; var description = i2b2.h.XPath(temp, 'descendant-or-self::description')[0].firstChild.nodeValue; self.dispDIV.innerHTML += "<div style=\"clear: both; padding-top: 10px; font-weight: bold;\">" + description + "</div>"; } var crc_xml = results.refXML.getElementsByTagName('crc_xml_result'); l = crc_xml.length; for (var i=0; i<l; i++) { var temp = crc_xml[i]; var xml_value = i2b2.h.XPath(temp, 'descendant-or-self::xml_value')[0].firstChild.nodeValue; var xml_v = i2b2.h.parseXml(xml_value); var params = i2b2.h.XPath(xml_v, 'descendant::data[@column]/text()/..'); for (var i2 = 0; i2 < params.length; i2++) { var name = params[i2].getAttribute("name"); if (i2b2.PM.model.isObfuscated) { if ( params[i2].firstChild.nodeValue < 4) { var value = "<3"; } else { var value = params[i2].firstChild.nodeValue + "±3" ; } } else { var value = params[i2].firstChild.nodeValue; } self.dispDIV.innerHTML += "<div style=\"clear: both; margin-left: 20px; float: left; height: 16px; line-height: 16px;\">" + params[i2].getAttribute("column") + ": <font color=\"#0000dd\">" + value + "</font></div>"; } var ri_id = i2b2.h.XPath(temp, 'descendant-or-self::result_instance_id')[0].firstChild.nodeValue; } //self.dispDIV.innerHTML += this.dispMsg; } } var self = i2b2.CRC.ctrlr.currentQueryStatus; // this private function refreshes the display DIV var d = new Date(); var t = Math.floor((d.getTime() - private_startTime)/100)/10; var s = t.toString(); if (s.indexOf('.') < 0) { s += '.0'; } if (private_singleton_isRunning) { self.dispDIV.innerHTML = '<div style="clear:both;"><div style="float:left; font-weight:bold">Running Query: "'+self.QM.name+'"</div>'; // display the current run duration self.dispDIV.innerHTML += '<div style="float:right">['+s+' secs]</div>'; } else { self.dispDIV.innerHTML = '<div style="clear:both;"><div style="float:left; font-weight:bold">Finished Query: "'+self.QM.name+'"</div>'; self.dispDIV.innerHTML += '<div style="float:right">['+s+' secs]</div>'; // self.dispDIV.innerHTML += '<div style="margin-left:20px; clear:both; height:16px; line-height:16px; "><div height:16px; line-height:16px; ">Compute Time: ' + (Math.floor((self.QI.end_date - self.QI.start_date)/100))/10 + ' secs</div></div>'; // self.dispDIV.innerHTML += '</div>'; $('runBoxText').innerHTML = "Run Query"; } self.dispDIV.innerHTML += '</div>'; if ((!private_singleton_isRunning) && (undefined != self.QI.end_date)){ self.dispDIV.innerHTML += '<div style="margin-left:20px; clear:both; line-height:16px; ">Compute Time: '+ (Math.floor((self.QI.end_date - self.QI.start_date)/100))/10 +' secs</div>'; } var foundError = false; for (var i=0; i < self.QRS.length; i++) { var rec = self.QRS[i]; if (rec.QRS_time) { var t = '<font color="'; switch(rec.QRS_Status) { case "ERROR": self.dispDIV.innerHTML += '<div style="clear:both; height:16px; line-height:16px; "><div style="float:left; font-weight:bold; height:16px; line-height:16px; ">'+rec.title+'</div><div style="float:right; height:16px; line-height:16px; "><font color="#dd0000">ERROR</font></div>'; // self.dispDIV.innerHTML += '<div style="float:right; height:16px; line-height:16px; "><font color="#dd0000">ERROR</font></div>'; //['+rec.QRS_time+' secs]</div>'; foundError = true; break; case "COMPLETED": case "FINISHED": foundError = false; //t += '#0000dd">'+rec.QRS_Status; break; case "INCOMPLETE": case "WAITTOPROCESS": case "PROCESSING": self.dispDIV.innerHTML += '<div style="clear:both; height:16px;line-height:16px; "><div style="float:left; font-weight:bold; height:16px; line-height:16px; ">'+rec.title+'</div><div style="float:right; height:16px; line-height:16px; "><font color="#00dd00">PROCESSING</font></div>'; // self.dispDIV.innerHTML += '<div style="float:right; height:16px; line-height:16px; "><font color="#00dd00">PROCESSING</font></div>'; //['+rec.QRS_time+' secs]</div>'; alert('Your query has timed out and has been rescheduled to run in the background. The results will appear in "Previous Queries"'); foundError = true; //t += '#00dd00">'+rec.QRS_Status; break; } t += '</font> '; //self.dispDIV.innerHTML += '<div style="float:right; height:16px; line-height:16px; ">'+t+'['+rec.QRS_time+' secs]</div>'; } self.dispDIV.innerHTML += '</div>'; if (foundError == false) { if (rec.QRS_DisplayType == "CATNUM") { //make call to get QRSI. i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryResultInstanceId("CRC:QueryStatus", {qr_key_value: rec.QRS_ID}, scopedCallbackQRSI); } else if ((rec.QRS_DisplayType == "LIST") && (foundError == false)) { self.dispDIV.innerHTML += "<div style=\"clear: both; padding-top: 10px; font-weight: bold;\">" + rec.QRS_Description + "</div>"; } else if (i2b2.h.isDQ) { self.dispDIV.innerHTML += "<div style=\"margin-left:20px; clear:both; height:16px; line-height:16px; \"><div style=\"float:left; height:16px; line-height:16px; \">" + rec.title + "</div><div style=\"float:right; height:16px; line-height:16px; \"><font color=\"#0000dd\">" + rec.QRS_Status + "</font> [" + rec.QRS_time + " secs]</div></div>"; } if (rec.QRS_Type == "PATIENTSET") { // Check to see if timeline is checked off, if so switch to timeline var t2 = $('dialogQryRun').select('INPUT.chkQueryType'); for (var i=0;i<t2.length; i++) { var curItem = t2[i].nextSibling.data; if (curItem != undefined) { curItem = curItem.toLowerCase(); //curitem = curItem.trim(); } if ((t2[i].checked == true) && (rec.size > 0) && (curItem == " timeline") && !(i2b2.h.isBadObjPath('i2b2.Timeline.cfg.config.plugin')) ) { i2b2.hive.MasterView.setViewMode('Analysis'); i2b2.PLUGINMGR.ctrlr.main.selectPlugin("Timeline"); //Process PatientSet rec.QM_id = self.QM.id; rec.QI_id = self.QI.id; rec.PRS_id = rec.QRS_ID; rec.result_instance_id = rec.PRS_id; var sdxData = {}; sdxData[0] = i2b2.sdx.Master.EncapsulateData('PRS', rec); i2b2.Timeline.prsDropped(sdxData); i2b2.Timeline.setShowMetadataDialog(false); //Process Concepts, put all concepts in one large set sdxData = {}; for (var j2 = 0; j2 < i2b2.CRC.model.queryCurrent.panels.length; j2++) { var panel_list = i2b2.CRC.model.queryCurrent.panels[j2] var panel_cnt = panel_list.length; for (var p2 = 0; p2 < panel_cnt; p2++) { // Concepts for (var i2=0; i2 < panel_list[p2].items.length; i2++) { sdxData[0] = panel_list[p2].items[i2]; i2b2.Timeline.conceptDropped(sdxData); } } } //$('Timeline-pgstart').value = '1'; //$('Timeline-pgsize').value = '10'; //i2b2.Timeline.pgGo(0); i2b2.Timeline.yuiTabs.set('activeIndex', 1); i2b2.Timeline.setShowMetadataDialog(true); } } } } } if ((undefined != self.QI.message) && (foundError == false)) { self.dispDIV.innerHTML += '<div style="clear:both; float:left; padding-top: 10px; font-weight:bold">Status</div>'; var mySplitResult = self.QI.message.split("<?xml"); for(i3 = 1; i3 < mySplitResult.length; i3++){ var xml_v = i2b2.h.parseXml(trim("<?xml " + mySplitResult[i3])); for (var i2 = 0; i2 < xml_v.childNodes.length; i2++) { try { if (i2b2.PM.model.isObfuscated) { if (i2b2.h.XPath(xml_v, 'descendant::total_time_second/text()/..')[i2].firstChild.nodeValue < 4) { var value = "<3"; } else { var value = i2b2.h.XPath(xml_v, 'descendant::total_time_second/text()/..')[i2].firstChild.nodeValue + "±3"; } } else { var value = i2b2.h.XPath(xml_v, 'descendant::total_time_second/text()/..')[i2].firstChild.nodeValue; } self.dispDIV.innerHTML += '<div style="margin-left:20px; clear:both; line-height:16px; ">' + i2b2.h.XPath(xml_v, 'descendant::name/text()/..')[i2].firstChild.nodeValue + '<font color="#0000dd">: ' + value + ' secs</font></div>'; //self.dispDIV.innerHTML += '<div style="float: left; height: 16px; margin-right: 100px; line-height: 16px;"><font color="#0000dd">: ' + i2b2.h.XPath(xml_v, 'descendant::total_time_second/text()/..')[i2].firstChild.nodeValue + ' secs</font></div>'; } catch (e) {} } } } self.dispDIV.style.display = 'none'; self.dispDIV.style.display = 'block'; if (!private_singleton_isRunning && private_refreshInterrupt) { // make sure our refresh interrupt is turned off try { clearInterval(private_refreshInterrupt); private_refreshInterrupt = false; } catch (e) {} } } function private_cancelQuery() { if (private_singleton_isRunning) { try { var self = i2b2.CRC.ctrlr.currentQueryStatus; i2b2.CRC.ctrlr.history.queryDeleteNoPrompt(self.QM.id); clearInterval(private_refreshInterrupt); private_refreshInterrupt = false; private_singleton_isRunning = false; $('runBoxText').innerHTML = "Run Query"; self.dispDIV.innerHTML += '<div style="clear:both; height:16px; line-height:16px; text-align:center; color:r#ff0000;">QUERY CANCELLED</div>'; i2b2.CRC.ctrlr.currentQueryStatus = false; } catch (e) {} } } function private_startQuery() { var self = i2b2.CRC.ctrlr.currentQueryStatus; var resultString = ""; //BG if (private_singleton_isRunning) { return false; } private_singleton_isRunning = true; //BG var downloadDataTab = $('infoDownloadStatusData'); if(downloadDataTab) downloadDataTab.innerHTML=""; i2b2.CRC.ctrlr.currentQueryResults = new i2b2.CRC.ctrlr.QueryResults(resultString); //BG self.dispDIV.innerHTML = '<b>Processing Query: "'+this.name+'"</b>'; self.QM.name = this.name; self.QRS = []; self.QI = {}; // callback processor to run the query from definition this.callbackQueryDef = new i2b2_scopedCallback(); this.callbackQueryDef.scope = this; this.callbackQueryDef.callback = function(results) { try { //if error if (results.error) { var temp = results.refXML.getElementsByTagName('response_header')[0]; if (undefined != temp) { results.errorMsg = i2b2.h.XPath(temp, 'descendant-or-self::result_status/status')[0].firstChild.nodeValue; if (results.errorMsg.substring(0,9) == "LOCKEDOUT") { results.errorMsg = 'As an "obfuscated user" you have exceeded the allowed query repeat and are now LOCKED OUT, please notify your system administrator.'; } } alert(results.errorMsg); private_cancelQuery(); return; } //query was successful so update global settings. clearInterval(private_refreshInterrupt); private_refreshInterrupt = false; private_singleton_isRunning = false; resultString = ""; //BG //update the ui var self = i2b2.CRC.ctrlr.currentQueryStatus; // this private function refreshes the display DIV var d = new Date(); var t = Math.floor((d.getTime() - private_startTime)/100)/10; var s = t.toString(); if (s.indexOf('.') < 0) { s += '.0'; } self.dispDIV.innerHTML = '<div style="clear:both;"><div style="float:left; font-weight:bold">Finished Query: "'+self.QM.name+'"</div>'; self.dispDIV.innerHTML += '<div style="float:right">['+s+' secs]</div><br/>'; resultString += 'Finished Query: "' + self.QM.name + '"\n'; //BG resultString += '[' + s + ' secs]\n'; //BG $('runBoxText').innerHTML = "Run Query"; //------------ QI Logic -------------------// //BG find user id var temp = results.refXML.getElementsByTagName('query_master')[0]; //Update the userid element when query is run first time var userId = i2b2.h.getXNodeVal(temp,'user_id'); if(userId) { var existingUserIdElemList = $$("#userIdElem"); if(existingUserIdElemList) { existingUserIdElemList.each(function(existingUserIdElem){ existingUserIdElem.remove(); }); } $("crcQueryToolBox.bodyBox").insert(new Element('input',{'type':'hidden','id':'userIdElem','value':userId})); } //End BG // find our query instance var qi_list = results.refXML.getElementsByTagName('query_instance'); //Original code commented by BG var l = qi_list.length; for (var i=0; i<l; i++) { var qiNode = qi_list[i]; var qi_id = i2b2.h.XPath(qiNode, 'descendant-or-self::query_instance_id')[0].firstChild.nodeValue; this.QI.message = i2b2.h.getXNodeVal(qiNode, 'message'); //start date. this.QI.start_date = i2b2.h.getXNodeVal(qiNode, 'start_date'); if (!Object.isUndefined(this.QI.start_date)) { this.QI.start_date = new Date(this.QI.start_date.substring(0,4), this.QI.start_date.substring(5,7)-1, this.QI.start_date.substring(8,10), this.QI.start_date.substring(11,13),this.QI.start_date.substring(14,16),this.QI.start_date.substring(17,19),this.QI.start_date.substring(20,23)); } //end date. this.QI.end_date = i2b2.h.getXNodeVal(qiNode, 'end_date'); if (!Object.isUndefined(this.QI.end_date)) { this.QI.end_date = new Date(this.QI.end_date.substring(0,4), this.QI.end_date.substring(5,7)-1, this.QI.end_date.substring(8,10), this.QI.end_date.substring(11,13),this.QI.end_date.substring(14,16),this.QI.end_date.substring(17,19),this.QI.end_date.substring(20,23)); } // found the query instance, extract the info this.QI.status = i2b2.h.XPath(qiNode, 'descendant-or-self::query_status_type/name')[0].firstChild.nodeValue; this.QI.statusID = i2b2.h.XPath(qiNode, 'descendant-or-self::query_status_type/status_type_id')[0].firstChild.nodeValue; } //add the compute time. self.dispDIV.innerHTML += '</div>'; resultString += '\n'; //BG self.dispDIV.innerHTML += '<div style="margin-left:20px; clear:both; line-height:16px; ">Compute Time: '+ s +' secs</div>'; resultString += 'Compute Time: '+ s + ' secs\n'; //BG // -- query result instance vars -- // var qriNodeList = results.refXML.getElementsByTagName('query_result_instance'), qriIdx, qriNode, qriObj, breakdownType, errorObjects = [], brdNodeList, brdNode, brdIdx, brdObj; //iterate through each query result. for (qriIdx = 0; qriIdx < qriNodeList.length; qriIdx++) { //init qri vars. qriNode = qriNodeList[qriIdx]; qriObj = parseQueryResultInstance(qriNode); breakdownType = ''; //which hospital self.dispDIV.innerHTML += '<div style="clear:both;"><br/><div style="float:left; font-weight:bold; margin-left:20px;">' + qriObj.description + ' "' +self.QM.name+ '"</div>'; resultString += '\n'; //BG resultString += qriObj.description + ' "' + self.QM.name+ '"\n'; //BG //if there was an error display it. if((qriObj.statusName == "ERROR") || (qriObj.statusName == "UNAVAILABLE")){ errorObjects.push(qriObj.problem); self.dispDIV.innerHTML += " - <span title='" + qriObj.statusDescription +"'> <b><a class='query-error-anchor' href='#' style='color:#ff0000'> <b><span color='#ff0000'>" + qriObj.problem.summary+ "</span></b></a></b></span>"; resultString += 'ERROR : ' + qriObj.problem.summary + '\n'; //BG continue; } else if((qriObj.statusName == "PROCESSING")){ self.dispDIV.innerHTML += " - <span><b><font color='#00dd00'>Still Processing Request</font></b></span>"; resultString += 'Still Processing Request : Still Processing Request\n'; //BG continue; } else if(["COMPLETED","FINISHED"].indexOf(qriObj.statusName) < 0){ self.dispDIV.innerHTML += " - <span><b><font color='#dd0000'>Results not available</font></b></span>"; resultString += 'Results not available : Results not available\n'; //BG continue; } self.dispDIV.innerHTML += "<div style=\"clear: both; margin-left: 30px; float: left; height: 16px; line-height: 16px;\">" + "Patient Count" + ": <font color=\"#0000dd\">" - + getObfuscatedResult(qriObj.setSize, 10) + + i2b2.h.getFormattedResult(qriObj.setSize) + "</font></div>"; - resultString += 'Patient Count' + getObfuscatedResult(qriObj.setSize, 10) + '\n'; //BG + resultString += 'Patient Count' + i2b2.h.getFormattedResult(qriObj.setSize) + '\n'; //BG //grab breakdown data. brdNodeList = i2b2.h.XPath(qriNode, 'descendant-or-self::breakdown_data/column'); for(brdIdx = 0; brdIdx < brdNodeList.length; brdIdx ++){ //init brd vars. brdNode = brdNodeList[brdIdx]; brdObj = parseBreakdown(brdNode); if(brdObj.parentResultType !== breakdownType){ breakdownType = brdObj.parentResultType; self.dispDIV.innerHTML += "<div style=\"clear: both; margin-left: 30px; float: left; height: 16px; line-height: 16px;\"><br/><font>" + getBreakdownTitle(brdObj.parentResultType) + ":</font></div>"; resultString += '\n'; //BG resultString += getBreakdownTitle(brdObj.parentResultType) + '\n'; //BG self.dispDIV.innerHTML += "<div style=\"clear: both; margin-left: 40px; float: left; height: 16px; line-height: 16px;\"></div>"; } self.dispDIV.innerHTML += "<div style=\"clear: both; margin-left: 40px; float: left; height: 16px; line-height: 16px;\">" + brdObj.name + ": <font color=\"#0000dd\">" - + getObfuscatedResult(brdObj.value, 10) + + i2b2.h.getFormattedResult(brdObj.value) + "</font></div>"; - resultString += brdObj.name + getObfuscatedResult(brdObj.value, 10) + '\n'; //BG + resultString += brdObj.name + i2b2.h.getFormattedResult(brdObj.value) + '\n'; //BG } } i2b2.CRC.ctrlr.currentQueryResults = new i2b2.CRC.ctrlr.QueryResults(resultString); $hrine.EnhancedError.createErrorDialogue(self.dispDIV, errorObjects); i2b2.CRC.ctrlr.history.Refresh(); } catch(err) { console.error(err); } } /** * * @param qriNode * @returns {{qiStatusName: string, qiStatusDescription: string, qiSetSize: string, qiDescription: string, qiResultName: string, qiResultDescription: string}} */ function parseQueryResultInstance(qriNode){ var qriObj = { statusName: grabXmlNodeData(qriNode, 'descendant-or-self::query_status_type/name'), statusDescription: grabXmlNodeData(qriNode, 'descendant-or-self::query_status_type/description'), description: grabXmlNodeData(qriNode, 'descendant-or-self::description') }; if(qriObj.statusName == "ERROR"){ qriObj.problem = $hrine.EnhancedError.parseProblem(qriNode); return qriObj; } qriObj.setSize = grabXmlNodeData(qriNode, 'descendant-or-self::set_size'); qriObj.resultName = grabXmlNodeData(qriNode, 'descendant-or-self::query_result_type/name'); qriObj.resultDescription = grabXmlNodeData(qriNode, 'descendant-or-self::query_result_type/description'); return qriObj; } /** * * @param brdNode */ function parseBreakdown(brdNode){ var brdObj = { name: grabXmlNodeData(brdNode, 'name'), value: grabXmlNodeData(brdNode, 'value'), parentResultType: grabXmlNodeData(brdNode, 'parent::breakdown_data/resultType') } return brdObj; } /** * Return breakdown title based on breakdown type. * @param breakdownType * @returns {*} */ function getBreakdownTitle(breakdownType) { return { 'PATIENT_AGE_COUNT_XML': 'Patient Age Count Breakdown', 'PATIENT_GENDER_COUNT_XML': 'Patient Gender Count Breakdown', 'PATIENT_RACE_COUNT_XML': 'Patient Race Count Breakdown', 'PATIENT_VITALSTATUS_COUNT_XML':'Patient Vital Status Count Breakdown' }[breakdownType]; }; - /** - * Method for hiding the precise value of a query below a certain result. - * @param resultCount - the number of results from a query. - * @param obfuscationSetting - do not reveal this number of results - */ - function getObfuscatedResult(resultCount, obfuscationSetting) { - - var resultTitle = " - ", - name = " patients", - offsetText = " +-10", // todo fix with SHRINE-1716 - isException = i2b2.PM.model.isObfuscated === false; - - //default to 10. - obfuscationSetting = (arguments.length > 1) ? arguments[1] : 10; - - //if user role is an exception. return result. - if (isException) { - return resultTitle += resultCount + name; - } - - resultTitle += ((resultCount >= obfuscationSetting)? - resultCount + offsetText + name: obfuscationSetting + name + " or fewer"); - - return resultTitle; - } - - /** * Grab data for node, return empty string if none. * @param node * @param xPathString * @returns {string} */ function grabXmlNodeData(node, xPathString){ var nodeVal = i2b2.h.XPath(node, xPathString); return (nodeVal.length)? nodeVal[0].firstChild.nodeValue : ''; } // switch to status tab i2b2.CRC.view.status.showDisplay(); // timer and display refresh stuff private_startTime = new Date(); private_refreshInterrupt = setInterval("i2b2.CRC.ctrlr.currentQueryStatus.refreshStatus()", 100); // AJAX call i2b2.CRC.ajax.runQueryInstance_fromQueryDefinition("CRC:QueryTool", this.params, this.callbackQueryDef); } return { name: "", polling_interval: 1000, QM: {id:false, status:""}, QI: {id:false, status:""}, QRS:{}, displayDIV: false, running: false, started: false, startQuery: function(queryName, ajaxParams) { this.name = queryName; this.params = ajaxParams; private_startQuery.call(this); }, cancelQuery: function() { private_cancelQuery(); }, isQueryRunning: function() { return private_singleton_isRunning; }, refreshStatus: function() { private_refresh_status(); } }; }(); i2b2.CRC.ctrlr.currentQueryStatus = false; diff --git a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryTool.js b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryTool.js index 983206931..e7138bd75 100644 --- a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryTool.js +++ b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_ctrlr_QryTool.js @@ -1,2951 +1,2955 @@ /** * @projectDescription Event controller for CRC's Query Tool. * @inherits i2b2.CRC.ctrlr * @namespace i2b2.CRC.ctrlr.QT * @author Nick Benik, Griffin Weber MD PhD * @version 1.3 * ---------------------------------------------------------------------------------------- * updated 9-15-08: RC4 launch [Nick Benik] */ console.group('Load & Execute component file: CRC > ctrlr > QueryTool'); console.time('execute time'); i2b2.CRC.ctrlr.QT = new QueryToolController(); function QueryToolController() { i2b2.CRC.model.queryCurrent = {}; this.queryIsDirty = true; this.queryIsRunning = false; this.queryNamePrompt = false; this.queryTiming = 'ANY'; this.temporalGroup = 0; this.tenporalBuilders = 0; this.hasModifier = false; this.queryNameDefault = 'New Query'; this.queryStatusDefaultText = 'Drag query items to one or more groups then click Run Query.'; this.panelControllers = []; this.panelControllers[0] = new i2b2_PanelController(this); this.panelControllers[1] = new i2b2_PanelController(this); this.panelControllers[2] = new i2b2_PanelController(this); // ================================================================================================== // this.doSetQueryName = function(inName) { this.queryIsDirty = true; $('queryName').innerHTML = inName; i2b2.CRC.model.queryCurrent.name = inName; } // ================================================================================================== // this.doQueryClear = function() { // function to clear query from memory delete i2b2.CRC.model.queryCurrent; delete i2b2.CRC.ctrlr.currentQueryResults; i2b2.CRC.model.queryCurrent = {}; i2b2.CRC.ctrlr.QT.temporalGroup = 0; var dm = i2b2.CRC.model.queryCurrent; dm.panels = []; dm.panels[0] = new Array(); dm.panels[1] = new Array(); dm.panels[2] = new Array(); this.doSetQueryName.call(this,''); this.doShowFrom(0); this._redrawPanelCount(); this.queryNamePrompt = false; this.queryIsDirty = true; this.hasModifier = false; $('infoQueryStatusText').innerHTML = ""; $('infoQueryStatusChart').innerHTML = ""; $('infoQueryStatusReport').innerHTML = ""; $('infoDownloadStatusData').innerHTML = ""; $('crc.temoralBuilder').hide(); $('crc.innerQueryPanel').show(); this.panelControllers[0].refTitle.innerHTML = 'Group 1'; $("defineTemporal-button").innerHTML = "Population in which events occur"; i2b2.CRC.view.QT.setQueryTiming(0); } // ================================================================================================== // this.doQueryLoad = function(qm_id) { // function to load query from history // clear existing query i2b2.CRC.ctrlr.QT.doQueryClear(); // show on GUI that work is being done i2b2.h.LoadingMask.show(); // callback processor var scopedCallback = new i2b2_scopedCallback(); scopedCallback.scope = this; scopedCallback.callback = function(results) { var cl_queryMasterId = qm_id; // THIS function is used to process the AJAX results of the getChild call // results data object contains the following attributes: // refXML: xmlDomObject <--- for data processing // msgRequest: xml (string) // msgResponse: xml (string) // error: boolean // errorStatus: string [only with error=true] // errorMsg: string [only with error=true] i2b2.CRC.view.QT.queryRequest = results.msgRequest; i2b2.CRC.view.QT.queryResponse = results.msgResponse; // switch to status tab i2b2.CRC.view.status.showDisplay(); // did we get a valid query definition back? var qd = i2b2.h.XPath(results.refXML, 'descendant::query_name/..'); if (qd.length != 0) { i2b2.CRC.ctrlr.QT.doQueryClear(); var dObj = {}; //1.17 dObj.name = i2b2.h.getXNodeVal(results.refXML,'name'); dObj.name = i2b2.h.getXNodeVal(results.refXML,'query_name'); $('queryName').innerHTML = dObj.name; dObj.specificity = i2b2.h.getXNodeVal(qd[0],'specificity_scale'); dObj.panels = []; //1.17 for (var j=0; j <qd.length; j++) { /* 1.17 qp variable initialization was if else for i2b2. if (j==0) var qp = i2b2.h.XPath(qd[j], 'panel'); else */ var qp = i2b2.h.XPath(qd[j], 'descendant::panel');//1.17 var total_panels = qp.length; for (var i1=0; i1<total_panels; i1++) { //1.17 i2b2.CRC.ctrlr.QT.temporalGroup = j; i2b2.CRC.ctrlr.QT.temporalGroup = 0; //1.17 //1.17 i2b2.CRC.ctrlr.QT._redrawAllPanels(); // extract the data for each panel var po = {}; po.panel_num = i2b2.h.getXNodeVal(qp[i1],'panel_number'); var t = i2b2.h.getXNodeVal(qp[i1],'invert'); po.exclude = (t=="1"); //po.timing = i2b2.h.getXNodeVal(qp[i1],'panel_timing'); // 1.4 queries don't have panel_timing, and undefined doesn't work // so default to ANY po.timing = i2b2.h.getXNodeVal(qp[i1],'panel_timing') || 'ANY'; i2b2.CRC.view.QT.setPanelTiming(po.panel_num, po.timing); var t = i2b2.h.getXNodeVal(qp[i1],'total_item_occurrences'); po.occurs = (1*t)-1; //1.17 var t = i2b2.h.getXNodeVal(qp[i1],'panel_accuracy_scale'); // 1.17 po.relevance = t; var t = i2b2.h.getXNodeVal(qp[i1],'panel_date_from'); if (t) { //section added for 1.17 t = t.replace('Z',''); t = t.split('-'); po.dateFrom = {}; po.dateFrom.Year = t[0]; po.dateFrom.Month = t[1]; po.dateFrom.Day = t[2]; /** * Commented out for 1.17. po.dateFrom = {}; po.dateFrom.Year = t.substring(0,4); //t[0]; po.dateFrom.Month = t.substring(5,7); //t[1]; po.dateFrom.Day = t.substring(8,10); //t[2]; **/ } else { po.dateFrom = false; } var t = i2b2.h.getXNodeVal(qp[i1],'panel_date_to'); if (t) { //added for 1.17 t = t.replace('Z',''); t = t.split('-'); po.dateTo = {}; po.dateTo.Year = t[0]; po.dateTo.Month = t[1]; po.dateTo.Day = t[2]; /** * Commented out for 1.17. po.dateTo = {}; po.dateTo.Year = t.substring(0,4); //t[0]; po.dateTo.Month = t.substring(5,7); // t[1]; po.dateTo.Day = t.substring(8,10);// t[2]; */ } else { po.dateTo = false; } //process query items. po.items = []; var pi = i2b2.h.XPath(qp[i1], 'descendant::item[item_key]'); for (i2=0; i2<pi.length; i2++) { var item = {}; // get the item's details from the ONT Cell var ckey = i2b2.h.getXNodeVal(pi[i2],'item_key'); //1.17 WE MUST QUERY THE ONT CELL TO BE ABLE TO DISPLAY THE TREE STRUCTURE CORRECTLY var cdetails = i2b2.ONT.ajax.GetTermInfo("CRC:QueryTool", {concept_key_value:ckey, ont_synonym_records: true, ont_hidden_records: true} ); //1.17 this is what comes out of the old AJAX call var c = i2b2.h.XPath(cdetails.refXML, 'descendant::concept'); //this entire if block is for 1.17. if (c.length > 0) { c = c[0]; var o = new Object; o.xmlOrig = c; o.table_name = i2b2.h.getXNodeVal(c,'tablename'); o.column_name = i2b2.h.getXNodeVal(c,'columnname'); o.operator = i2b2.h.getXNodeVal(c,'operator'); o.icd9 = i2b2.h.getXNodeVal(c,'basecode'); o.level = i2b2.h.getXNodeVal(c,'level'); o.name = i2b2.h.getXNodeVal(c,'name'); o.key = i2b2.h.getXNodeVal(c,'key'); o.tooltip = i2b2.h.getXNodeVal(c,'tooltip'); o.dim_code = i2b2.h.getXNodeVal(c,'dimcode'); o.visual_attribs = i2b2.h.getXNodeVal(c,'visualattributes'); o.hasChildren = i2b2.h.getXNodeVal(c,'visualattributes').substring(0,2); // these are not needed? o.fact_table_column = i2b2.h.getXNodeVal(c,'facttablecolumn'); o.column_name_datatype = i2b2.h.getXNodeVal(c,'columndatatype'); o.synonym_cd = i2b2.h.getXNodeVal(c,'synonym_cd'); o.totalnum = i2b2.h.getXNodeVal(c,'totalnum'); //1.17 process lab values. var lvd = i2b2.h.XPath(pi[i2], 'descendant::constrain_by_value'); if (lvd.length>0){ lvd = lvd[0]; // pull the LabValue definition for concept var lvdef = i2b2.h.XPath(c, "descendant::metadataxml/ValueMetadata[Loinc]"); if (lvdef.length > 0) { lvdef = lvdef[0]; } else { lvdef = false; } // extract & translate var t = i2b2.h.getXNodeVal(lvd,"value_constraint"); o.LabValues = {}; o.LabValues.NumericOp = i2b2.h.getXNodeVal(lvd,"value_operator"); o.LabValues.GeneralValueType = i2b2.h.getXNodeVal(lvd,"value_type"); switch(o.LabValues.GeneralValueType) { case "NUMBER": o.LabValues.MatchBy = "VALUE"; if (t.indexOf(' and ')!=-1) { // extract high and low values t = t.split(' and '); o.LabValues.ValueLow = t[0]; o.LabValues.ValueHigh = t[1]; } else { o.LabValues.Value = t; } break; case "STRING": o.LabValues.MatchBy = "VALUE"; o.LabValues.ValueString = t; break; case "TEXT": // this means Enum? o.LabValues.MatchBy = "VALUE"; try { o.LabValues.ValueEnum = eval("(Array"+t+")"); } catch(e) { console.error("Conversion Failed: Lab Value data = "+t); } break; case "FLAG": o.LabValues.MatchBy = "FLAG"; o.LabValues.ValueFlag = t break; default: o.LabValues.Value = t; } }//1.17 end lab values section var sdxDataNode = i2b2.sdx.Master.EncapsulateData('CONCPT',o); if (o.LabValues) { // We do want 2 copies of the Lab Values: one is original from server while the other one is for user manipulation sdxDataNode.LabValues = o.LabValues; } //push item on po. po.items.push(sdxDataNode); } else { console.error("CRC's ONT Handler could not get term details about '"+ckey+"'!"); } } dObj.panels[po.panel_num] = po; } // reindex the panels index (panel [1,3,5] should be [0,1,2]) dObj.panels = dObj.panels.compact(); i2b2.CRC.model.queryCurrent.panels[j] = dObj.panels; var qpc = i2b2.CRC.ctrlr.QT.panelControllers[0]; var dm = i2b2.CRC.model.queryCurrent; for (var k=0; k<dm.panels.length; k++) { //length of panels should always be 1. for (var pi=0; pi<dm.panels[k].length; pi++) { // create a treeview root node and connect it to the treeview controller dm.panels[k][pi].tvRootNode = new YAHOO.widget.RootNode(qpc.yuiTree); qpc.yuiTree.root = dm.panels[k][pi].tvRootNode; dm.panels[k][pi].tvRootNode.tree = qpc.yuiTree; qpc.yuiTree.setDynamicLoad(i2b2.CRC.ctrlr.QT._loadTreeDataForNode,1); // load the treeview with the data var tvRoot = qpc.yuiTree.getRoot(); for (var pii=0; pii<dm.panels[k][pi].items.length; pii++) { var withRenderData = qpc._addConceptVisuals(dm.panels[k][pi].items[pii], tvRoot, false); if (dm.panels[k][pi].items[pii].ModValues) { withRenderData.ModValues = dm.panels[k][pi].items[pii].ModValues; } if (dm.panels[k][pi].items[pii].LabValues) { withRenderData.LabValues = dm.panels[k][pi].items[pii].LabValues; } dm.panels[k][pi].items[pii] = withRenderData; } } } // redraw the Query Tool GUI i2b2.CRC.ctrlr.QT._redrawPanelCount(); i2b2.CRC.ctrlr.QT.doScrollFirst(); // hide the loading mask i2b2.h.LoadingMask.hide(); } i2b2.CRC.ctrlr.QT.temporalGroup = 0; i2b2.CRC.ctrlr.QT._redrawAllPanels(); } } // AJAX CALL i2b2.CRC.ajax.getRequestXml_fromQueryMasterId("CRC:QueryTool", { qm_key_value: qm_id }, scopedCallback); } // ================================================================================================== // this.doQueryRun = function() { // function to build and run query if (i2b2.CRC.ctrlr.currentQueryStatus != false && i2b2.CRC.ctrlr.currentQueryStatus.isQueryRunning()) { i2b2.CRC.ctrlr.currentQueryStatus.cancelQuery(); i2b2.CRC.ctrlr.currentQueryStatus = false; //alert('A query is already running.\n Please wait until the currently running query has finished.'); return void(0); } /* * Method added for edge case where * dragging previous query does not add items to panel. Will occur when ontology * @param panels */ function hasItems(panel) { return panel.length > 0 && panel[0].items.length > 0; } if (i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length < 1) { alert('You must enter at least one concept to run a query.'); return void(0); } // make sure a shrine topic has been selected if (i2b2.PM.model.shrine_domain) { var topicSELECT = $('queryTopicSelect'); //@pcori_webclient if(topicSELECT){ if (topicSELECT.selectedIndex == null || topicSELECT.selectedIndex == 0) { alert('You must select a Topic to run a SHRINE query.'); return void(0); } var topicid = topicSELECT.options[topicSELECT.selectedIndex].value; } } // callback for dialog submission var handleSubmit = function() { // submit value(s) if(this.submit()) { // run the query var t = $('dialogQryRun'); var queryNameInput = t.select('INPUT.inputQueryName')[0]; var options = {}; var t2 = t.select('INPUT.chkQueryType'); for (var i=0;i<t2.length; i++) { if (t2[i].checked == true) { options['chk_'+t2[i].value] = t2[i].checked; } } $('queryName').innerHTML = queryNameInput.value; i2b2.CRC.model.queryCurrent.name = queryNameInput.value; i2b2.CRC.ctrlr.QT._queryRun(queryNameInput.value, options); } } // display the query name input dialog this._queryPromptRun(handleSubmit); // autogenerate query name var myDate=new Date(); var hours = myDate.getHours() if (hours < 10){ hours = "0" + hours } var minutes = myDate.getMinutes() if (minutes < 10){ minutes = "0" + minutes } var seconds = myDate.getSeconds() if (seconds < 10){ seconds = "0" + seconds } //var ds = myDate.toLocaleString(); var ts = hours + ":" + minutes + ":" + seconds; //ds.substring(ds.length-5,ds.length-13); var defQuery = this._getQueryXML.call(this); var qn = defQuery.queryAutoName+'@'+ts; // display name var queryNameInput = $('dialogQryRun').select('INPUT.inputQueryName')[0]; queryNameInput.value = qn; } // ================================================================================================== // this._queryRun = function(inQueryName, options) { // make sure name is not blank if (inQueryName.blank()) { alert('Cannot run query with without providing a name!'); return; } // Query Parameters var query_definition = this._getQueryXML(inQueryName); var params = { result_wait_time: i2b2.CRC.view.QT.params.queryTimeout, psm_query_definition: query_definition.queryXML } // SHRINE topic if we are running SHRINE query if (i2b2.h.isSHRINE()) { var topicSELECT = $('queryTopicSelect'); //@pcori_webclient if(topicSELECT){ if (topicSELECT.selectedIndex == null || topicSELECT.selectedIndex == 0) { alert("Please select a Topic to run the query."); return false; } params.shrine_topic = "<shrine><queryTopicID>"+topicSELECT.options[topicSELECT.selectedIndex].value+"</queryTopicID></shrine>"; } } // generate the result_output_list (for 1.3 backend) var result_output = ""; for(var name in options) { if (name) { i++; result_output += '<result_output priority_index="'+i+'" name="' + name.substring(4).toLowerCase() + '"/>\n'; } } //@pcori_webclient //result_output = '<result_output priority_index="11" name="patient_count_xml"/>'; params.psm_result_output = '<result_output_list>'+result_output+'</result_output_list>\n'; // create query object $('runBoxText').innerHTML = "Cancel Query"; i2b2.CRC.ctrlr.currentQueryStatus = new i2b2.CRC.ctrlr.QueryStatus($('infoQueryStatusText')); i2b2.CRC.ctrlr.currentQueryStatus.startQuery(inQueryName, params); } // ================================================================================================== // this._queryRunningTime = function() { if (i2b2.CRC.ctrlr.QT.queryIsRunning) { var d = new Date(); var t = Math.floor((d.getTime() - queryStartTime)/100)/10; var el = $('numSeconds'); if (el) { var s = t.toString(); if (s.indexOf('.') < 0) { s += '.0'; } el.innerHTML = s; window.setTimeout('i2b2.CRC.ctrlr.QT._queryRunningTime()',100); } } } // ================================================================================================== // this._queryPromptRun = function(handleSubmit) { if (!i2b2.CRC.view.dialogQryRun) { var handleCancel = function() { this.cancel(); }; var loopBackSubmit = function() { i2b2.CRC.view.dialogQryRun.submitterFunction(); }; i2b2.CRC.view.dialogQryRun = new YAHOO.widget.SimpleDialog("dialogQryRun", { width: "400px", fixedcenter: true, constraintoviewport: true, modal: true, zindex: 700, buttons: [{ text: "OK", handler: loopBackSubmit, isDefault: true }, { text: "Cancel", handler: handleCancel }] }); $('dialogQryRun').show(); i2b2.CRC.view.dialogQryRun.validate = function(){ // now process the form data var msgError = ''; var queryNameInput = $('dialogQryRun').select('INPUT.inputQueryName')[0]; if (!queryNameInput || queryNameInput.value.blank()) { alert('Please enter a name for this query.'); return false; } return true; }; i2b2.CRC.view.dialogQryRun.render(document.body); } // manage the event handler for submit delete i2b2.CRC.view.dialogQryRun.submitterFunction; i2b2.CRC.view.dialogQryRun.submitterFunction = handleSubmit; // display the dialoge i2b2.CRC.view.dialogQryRun.center(); i2b2.CRC.view.dialogQryRun.show(); } // ================================================================================================== // this._queryPromptName = function(handleSubmit) { if (!i2b2.CRC.view.dialogQmName) { var handleCancel = function() { this.cancel(); }; var loopBackSubmit = function() { i2b2.CRC.view.dialogQmName.submitterFunction(); }; i2b2.CRC.view.dialogQmName = new YAHOO.widget.SimpleDialog("dialogQmName", { width: "400px", fixedcenter: true, constraintoviewport: true, modal: true, zindex: 700, buttons: [{ text: "OK", handler: loopBackSubmit, isDefault: true }, { text: "Cancel", handler: handleCancel }] }); $('dialogQmName').show(); i2b2.CRC.view.dialogQmName.validate = function(){ // now process the form data var msgError = ''; var queryNameInput = $('inputQueryName'); if (!queryNameInput || queryNameInput.value.blank()) { alert('Please enter a name for this query.'); return false; } return true; }; i2b2.CRC.view.dialogQmName.render(document.body); } // manage the event handler for submit delete i2b2.CRC.view.dialogQmName.submitterFunction; i2b2.CRC.view.dialogQmName.submitterFunction = handleSubmit; // display the dialoge i2b2.CRC.view.dialogQmName.center(); i2b2.CRC.view.dialogQmName.show(); } // ================================================================================================== // this._getQueryXML = function(queryName) { var i; var isTemporal = false; var el; var concept; var panel_list = i2b2.CRC.model.queryCurrent.panels[0]; //i2b2.CRC.ctrlr.QT.temporalGroup]; var panel_cnt = panel_list.length; var auto_query_name_len = 15; var auto_query_name = ''; if (this.queryTiming == "TEMPORAL") { isTemporal = true; } if (panel_cnt > 0) { auto_query_name_len = Math.floor(15/panel_cnt); if (auto_query_name_len < 1) {auto_query_name_len = 1;} } // build Query XML var s = '<query_definition>\n'; if (isTemporal) { queryName = '(t) ' + queryName; } s += '\t<query_name>' + i2b2.h.Escape(queryName) + '</query_name>\n'; if (this.queryTiming == "SAMEVISIT") { s += '\t<query_timing>SAMEVISIT</query_timing>\n'; } else if (this.queryTiming == "ANY") { s += '\t<query_timing>ANY</query_timing>\n'; } else if (this.queryTiming == "TEMPORAL") { s += '\t<query_timing>ANY</query_timing>\n'; } else { s += '\t<query_timing>SAMEINSTANCENUM</query_timing>\n'; } s += '\t<specificity_scale>0</specificity_scale>\n'; if (i2b2.PM.model.shrine_domain) { s += '\t<use_shrine>1</use_shrine>\n'; } for (var ip = 0; ip < i2b2.CRC.model.queryCurrent.panels.length; ip++) { panel_list = i2b2.CRC.model.queryCurrent.panels[ip]; //i2b2.CRC.ctrlr.QT.temporalGroup]; panel_cnt = panel_list.length; if (isTemporal && ip > 0) { //if equal to one than add subquery_contraint if (ip == 1) { for (var tb=0; tb <= this.tenporalBuilders; tb++) { s += '\t<subquery_constraint>\n'; s += '\t\t<first_query>\n'; s += '\t\t\t<query_id>' + $('instancevent1[' + tb + ']').options[$('instancevent1[' + tb + ']').selectedIndex].value + '</query_id>\n'; s += '\t\t\t<join_column>' + $('preloc1[' + tb + ']').options[$('preloc1[' + tb + ']').selectedIndex].value + '</join_column>\n'; s += '\t\t\t<aggregate_operator>' + $('instanceopf1[' + tb + ']').options[$('instanceopf1[' + tb + ']').selectedIndex].value + '</aggregate_operator>\n'; s += '\t\t</first_query>\n'; s += '\t\t<operator>' + $('postloc[' + tb + ']').options[$('postloc[' + tb + ']').selectedIndex].value + '</operator>\n'; s += '\t\t<second_query>\n'; s += '\t\t\t<query_id>' + $('instancevent2[' + tb + ']').options[$('instancevent2[' + tb + ']').selectedIndex].value + '</query_id>\n'; s += '\t\t\t<join_column>' + $('preloc2[' + tb + ']').options[$('preloc2[' + tb + ']').selectedIndex].value + '</join_column>\n'; s += '\t\t\t<aggregate_operator>' + $('instanceopf2[' + tb + ']').options[$('instanceopf2[' + tb + ']').selectedIndex].value + '</aggregate_operator>\n'; s += '\t\t</second_query>\n'; if ( $('bytime1[' + tb + ']').checked) { s += '\t\t<span>\n'; s += '\t\t\t<operator>' + $('byspan1[' + tb + ']').options[$('byspan1[' + tb + ']').selectedIndex].value + '</operator>\n'; s += '\t\t\t<span_value>' + $('bytimevalue1[' + tb + ']').value + '</span_value>\n'; s += '\t\t\t<units>' + $('bytimeunit1[' + tb + ']').options[$('bytimeunit1[' + tb + ']').selectedIndex].value + '</units>\n'; s += '\t\t</span>\n'; } if ( $('bytime2[' + tb + ']').checked) { s += '\t\t<span>\n'; s += '\t\t\t<operator>' + $('byspan2[' + tb + ']').options[$('byspan2[' + tb + ']').selectedIndex].value + '</operator>\n'; s += '\t\t\t<span_value>' + $('bytimevalue2[' + tb + ']').value + '</span_value>\n'; s += '\t\t\t<units>' + $('bytimeunit2[' + tb + ']').options[$('bytimeunit2[' + tb + ']').selectedIndex].value + '</units>\n'; s += '\t\t</span>\n'; } s += '\t</subquery_constraint>\n'; } } if (panel_list[0].items.length == 0) break; s += '<subquery>\n '; s += '<query_id>Event '+ ip +'</query_id>\n'; s += '<query_type>EVENT</query_type>\n'; s += '<query_name>Event '+ ip +'</query_name>\n'; s += '<query_timing>SAMEINSTANCENUM</query_timing>\n'; s += '<specificity_scale>0</specificity_scale>\n'; } for (var p = 0; p < panel_cnt; p++) { s += '\t<panel>\n'; s += '\t\t<panel_number>' + (p+1) + '</panel_number>\n'; // date range constraints if (panel_list[p].dateFrom) { s += '\t\t<panel_date_from>'+panel_list[p].dateFrom.Year+'-'+padNumber(panel_list[p].dateFrom.Month,2)+'-'+padNumber(panel_list[p].dateFrom.Day,2)+'T00:00:00.000-05:00</panel_date_from>\n'; } if (panel_list[p].dateTo) { s += '\t\t<panel_date_to>'+panel_list[p].dateTo.Year+'-'+padNumber(panel_list[p].dateTo.Month,2)+'-'+padNumber(panel_list[p].dateTo.Day,2)+'T00:00:00.000-05:00</panel_date_to>\n'; } s += "\t\t<panel_accuracy_scale>" + panel_list[p].relevance + "</panel_accuracy_scale>\n"; // Exclude constraint (invert flag) if (panel_list[p].exclude) { s += '\t\t<invert>1</invert>\n'; } else { s += '\t\t<invert>0</invert>\n'; } // Panel Timing s += '\t\t<panel_timing>' + panel_list[p].timing + '</panel_timing>\n'; // Occurs constraint s += '\t\t<total_item_occurrences>'+((panel_list[p].occurs*1)+1)+'</total_item_occurrences>\n'; // Concepts for (i=0; i < panel_list[p].items.length; i++) { var sdxData = panel_list[p].items[i]; s += '\t\t<item>\n'; switch(sdxData.sdxInfo.sdxType) { case "QM": s += '\t\t\t<item_key>masterid:' + sdxData.origData.id + '</item_key>\n'; s += '\t\t\t<item_name>' + sdxData.origData.title + '</item_name>\n'; s += '\t\t\t<tooltip>' + sdxData.origData.name + '</tooltip>\n'; s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n'; s += '\t\t\t<hlevel>0</hlevel>\n'; break; case "PRS": s += '\t\t\t<item_key>patient_set_coll_id:' + sdxData.sdxInfo.sdxKeyValue + '</item_key>\n'; s += '\t\t\t<item_name>' + sdxData.sdxInfo.sdxDisplayName + '</item_name>\n'; s += '\t\t\t<tooltip>' + sdxData.sdxInfo.sdxDisplayName + '</tooltip>\n'; s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n'; s += '\t\t\t<hlevel>0</hlevel>\n'; break; case "ENS": s += '\t\t\t<item_key>patient_set_enc_id:' + sdxData.sdxInfo.sdxKeyValue + '</item_key>\n'; s += '\t\t\t<item_name>' + sdxData.sdxInfo.sdxDisplayName + '</item_name>\n'; s += '\t\t\t<tooltip>' + sdxData.sdxInfo.sdxDisplayName + '</tooltip>\n'; s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n'; s += '\t\t\t<hlevel>0</hlevel>\n'; break; default: if (sdxData.origData.isModifier) { var modParent = sdxData.origData.parent; var level = sdxData.origData.level; var key = sdxData.origData.parent.key; var name = (sdxData.origData.parent.name != null ? i2b2.h.Escape(sdxData.origData.parent.name) : i2b2.h.Escape(sdxData.origData.name)) ; var tooltip = sdxData.origData.tooltip; var itemicon = sdxData.origData.hasChildren; while (modParent != null) { if (modParent.isModifier) { modParent = modParent.parent; } else { level = modParent.level; key = modParent.key; name = modParent.name; tooltip = modParent.tooltip; itemicon = modParent.hasChildren; break; } } s += '\t\t\t<hlevel>' + level + '</hlevel>\n'; s += '\t\t\t<item_key>' + key + '</item_key>\n'; s += '\t\t\t<item_name>' + name + '</item_name>\n'; // (sdxData.origData.newName != null ? sdxData.origData.newName : sdxData.origData.name) + '</item_name>\n'; s += '\t\t\t<tooltip>' + tooltip + '</tooltip>\n'; s += '\t\t\t<item_icon>' + itemicon + '</item_icon>\n'; s += '\t\t\t<class>ENC</class>\n'; s += '\t\t\t\t<constrain_by_modifier>\n'; s += '\t\t\t\t\t<modifier_name>' + sdxData.origData.name + '</modifier_name>\n'; s += '\t\t\t\t\t<applied_path>' + sdxData.origData.applied_path + '</applied_path>\n'; s += '\t\t\t\t\t<modifier_key>' + sdxData.origData.key + '</modifier_key>\n'; if (sdxData.ModValues) { s += this.getValues( sdxData.ModValues); } s += '\t\t\t\t</constrain_by_modifier>\n'; } else { sdxData.origData.key = (sdxData.origData.key).replace(/</g,"<"); sdxData.origData.name = (sdxData.origData.name).replace(/</g,"<"); if (undefined != sdxData.origData.tooltip) sdxData.origData.tooltip = (sdxData.origData.tooltip).replace(/</g,"<"); s += '\t\t\t<hlevel>' + sdxData.origData.level + '</hlevel>\n'; //s += '\t\t\t<item_name>' + (sdxData.origData.newName != null ? i2b2.h.Escape(sdxData.origData.newName) : i2b2.h.Escape(sdxData.origData.name)) + '</item_name>\n'; s += '\t\t\t<item_name>' + (sdxData.origData.name != null ? i2b2.h.Escape(sdxData.origData.name) : i2b2.h.Escape(sdxData.origData.newName)) + '</item_name>\n'; s += '\t\t\t<item_key>' + sdxData.origData.key + '</item_key>\n'; s += '\t\t\t<tooltip>' + sdxData.origData.tooltip + '</tooltip>\n'; s += '\t\t\t<class>ENC</class>\n'; s += '\t\t\t<item_icon>' + sdxData.origData.hasChildren + '</item_icon>\n'; } try { var t = i2b2.h.XPath(sdxData.origData.xmlOrig,'descendant::synonym_cd/text()'); t = (t[0].nodeValue=="Y"); } catch(e) { var t = "false"; } s += '\t\t\t<item_is_synonym>'+t+'</item_is_synonym>\n'; if (sdxData.LabValues) { //s += '\t\t\t<constrain_by_value>\n'; s += this.getValues( sdxData.LabValues); } break; } //TODO add contraint to the item in the future /* s += '\t\t\t<constrain_by_date>\n'; if (panel_list[p].dateFrom) { s += '\t\t\t\t<date_from>'+panel_list[p].dateFrom.Year+'-'+padNumber(panel_list[p].dateFrom.Month,2)+'-'+padNumber(panel_list[p].dateFrom.Day,2)+'Z</date_from>\n'; } if (panel_list[p].dateTo) { s += '\t\t\t\t<date_to>'+panel_list[p].dateTo.Year+'-'+padNumber(panel_list[p].dateTo.Month,2)+'-'+padNumber(panel_list[p].dateTo.Day,2)+'Z</date_to>\n'; } s += '\t\t\t</constrain_by_date>\n'; */ s += '\t\t</item>\n'; if (i==0) { if (undefined != sdxData.origData.name) { auto_query_name += sdxData.origData.name.substring(0,auto_query_name_len); } else if (undefined != sdxData.origData.title) { auto_query_name += sdxData.origData.title.substring(0,auto_query_name_len); } else { auto_query_name += "new query"; } if (p < panel_cnt-1) {auto_query_name += '-';} } } s += '\t</panel>\n'; } if (isTemporal && ip > 0) { s += '</subquery>\n '; } if (isTemporal == false) { break; } } s += '</query_definition>\n'; this.queryMsg = {}; this.queryMsg.queryAutoName = auto_query_name; if (undefined===queryName) { this.queryMsg.queryName = this.queryNameDefault; } else { this.queryMsg.queryName = queryName; } this.queryMsg.queryXML = s; return(this.queryMsg); } this.getValues = function(lvd) { var s = '\t\t\t<constrain_by_value>\n'; //var lvd = sdxData.LabValues; switch(lvd.MatchBy) { case "FLAG": s += '\t\t\t\t<value_type>FLAG</value_type>\n'; s += '\t\t\t\t<value_operator>EQ</value_operator>\n'; s += '\t\t\t\t<value_constraint>'+i2b2.h.Escape(lvd.ValueFlag)+'</value_constraint>\n'; break; case "VALUE": if (lvd.GeneralValueType=="ENUM") { var sEnum = []; for (var i2=0;i2<lvd.ValueEnum.length;i2++) { sEnum.push(i2b2.h.Escape(lvd.ValueEnum[i2])); } //sEnum = sEnum.join("\", \""); sEnum = sEnum.join("\',\'"); sEnum = '(\''+sEnum+'\')'; s += '\t\t\t\t<value_type>TEXT</value_type>\n'; s += '\t\t\t\t<value_constraint>'+sEnum+'</value_constraint>\n'; s += '\t\t\t\t<value_operator>IN</value_operator>\n'; } else if (lvd.GeneralValueType=="STRING") { s += '\t\t\t\t<value_type>TEXT</value_type>\n'; s += '\t\t\t\t<value_operator>'+lvd.StringOp+'</value_operator>\n'; s += '\t\t\t\t<value_constraint><![CDATA['+i2b2.h.Escape(lvd.ValueString)+']]></value_constraint>\n'; } else if (lvd.GeneralValueType=="LARGESTRING") { if (lvd.DbOp) { s += '\t\t\t\t<value_operator>CONTAINS[database]</value_operator>\n'; } else { s += '\t\t\t\t<value_operator>CONTAINS</value_operator>\n'; } s += '\t\t\t\t<value_type>LARGETEXT</value_type>\n'; s += '\t\t\t\t<value_constraint><![CDATA['+lvd.ValueString+']]></value_constraint>\n'; } else { s += '\t\t\t\t<value_type>'+lvd.GeneralValueType+'</value_type>\n'; s += '\t\t\t\t<value_unit_of_measure>'+lvd.UnitsCtrl+'</value_unit_of_measure>\n'; s += '\t\t\t\t<value_operator>'+lvd.NumericOp+'</value_operator>\n'; if (lvd.NumericOp == 'BETWEEN') { s += '\t\t\t\t<value_constraint>'+i2b2.h.Escape(lvd.ValueLow)+' and '+i2b2.h.Escape(lvd.ValueHigh)+'</value_constraint>\n'; } else { s += '\t\t\t\t<value_constraint>'+i2b2.h.Escape(lvd.Value)+'</value_constraint>\n'; } } break; case "": break; } s += '\t\t\t</constrain_by_value>\n'; return s; } // ================================================================================================== // this.panelAdd = function(yuiTree) { // this function is used to create a new panel, it initializes the data structure in the if (!i2b2.CRC.model.queryCurrent.panels) { i2b2.CRC.model.queryCurrent.panels = []; i2b2.CRC.model.queryCurrent.panels[0] = new Array(); i2b2.CRC.model.queryCurrent.panels[1] = new Array(); i2b2.CRC.model.queryCurrent.panels[2] = new Array(); // i2b2.CRC.model.queryCurrent.panels = new Array(new Array()); } var dm = i2b2.CRC.model.queryCurrent; var pi = dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length; if (pi == undefined) { dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup] = new Array(); pi = 0; } var tTiming = i2b2.CRC.ctrlr.QT.queryTiming; if ((tTiming == "TEMPORAL") && (i2b2.CRC.ctrlr.QT.temporalGroup > 0)) tTiming = "SAMEINSTANCENUM"; if ((tTiming == "TEMPORAL") && (i2b2.CRC.ctrlr.QT.temporalGroup == 0)) tTiming = "ANY"; // setup the data model for this panel dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi] = {}; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateTo = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateFrom = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].exclude = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].occurs = '0'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].relevance = '100'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].timing = tTiming; // i2b2.CRC.ctrlr.QT.queryTiming; //'ANY'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].items = []; // create a treeview root node and connect it to the treeview controller dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode = new YAHOO.widget.RootNode(this.yuiTree); yuiTree.root = dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode.tree = yuiTree; yuiTree.setDynamicLoad(i2b2.CRC.ctrlr.QT._loadTreeDataForNode,1); if (dm.panels.length == 1) { var tTiming = i2b2.CRC.ctrlr.QT.queryTiming; if (i2b2.CRC.ctrlr.QT.queryTiming == "TEMPORAL") tTiming = "ANY"; i2b2.CRC.ctrlr.QT.temporalGroup = 1; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup] = {}; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi] = {}; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateTo = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateFrom = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].exclude = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].occurs = '0'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].relevance = '100'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].timing = tTiming; //i2b2.CRC.ctrlr.QT.queryTiming; //'ANY'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].items = []; // create a treeview root node and connect it to the treeview controller dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode = new YAHOO.widget.RootNode(this.yuiTree); yuiTree.root = dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode.tree = yuiTree; yuiTree.setDynamicLoad(i2b2.CRC.ctrlr.QT._loadTreeDataForNode,1); i2b2.CRC.ctrlr.QT.temporalGroup = 2; if (i2b2.CRC.ctrlr.QT.queryTiming == "TEMPORAL") tTiming = "SAMEINSTANCENUM"; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup] = {}; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi] = {}; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateTo = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].dateFrom = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].exclude = false; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].occurs = '0'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].relevance = '100'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].timing = tTiming; //i2b2.CRC.ctrlr.QT.queryTiming; //'ANY'; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].items = []; // create a treeview root node and connect it to the treeview controller dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode = new YAHOO.widget.RootNode(this.yuiTree); yuiTree.root = dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode; dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi].tvRootNode.tree = yuiTree; yuiTree.setDynamicLoad(i2b2.CRC.ctrlr.QT._loadTreeDataForNode,1); i2b2.CRC.ctrlr.QT.temporalGroup = 0; } // update the count on the GUI this._redrawPanelCount(); // return a reference to the new panel object this.doSetQueryName.call(this,''); return dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup][pi]; } // ================================================================================================== // this._loadTreeDataForNode = function(node, onCompleteCallback) { i2b2.sdx.Master.LoadChildrenFromTreeview(node, onCompleteCallback); } // ================================================================================================== // this.ToggleNode = function(divTarg, divTreeID) { // get the i2b2 data from the yuiTree node var tvTree = YAHOO.widget.TreeView.findTreeByChildDiv(divTarg); // this is a custom extention found in "hive_helpers.js" var tvNode = tvTree.getNodeByProperty('nodeid', divTarg.id); tvNode.toggle(); } // ================================================================================================== // this.panelDelete = function(index) { // alter the data model's panel elements var dm = i2b2.CRC.model.queryCurrent; if(index <0 || index>=dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length) { return false;} dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup].splice(index,1); // redraw the panels this.doShowFrom(this.panelControllers[0].panelCurrentIndex); // BUG FIX: force the panels to fully reattach the yuiRootNode to the controllers for (var i=0; i<this.panelControllers.length; i++) { this.panelControllers[i].doRedraw(); } this._redrawPanelCount(); this.doSetQueryName.call(this,''); } // ================================================================================================== // this.doShowFrom = function(index_offset) { // have all panel controllers redraw using new index offest $('infoQueryStatusText').innerHTML = ""; if (index_offset===false) { return true; } if (index_offset < 0) { index_offset = 0; } for (var i=0; i<3; i++) { if ((i2b2.CRC.ctrlr.QT.queryTiming == "TEMPORAL") && (i==0)) { var sText = defineTemporalButton.get("label"); if (sText != "Population in which events occur") this.panelControllers[i].refTitle.innerHTML = 'Anchoring Observation'; else this.panelControllers[i].refTitle.innerHTML = 'Group 1'; } else { this.panelControllers[i].refTitle.innerHTML = "Group "+(index_offset+i+1); } this.panelControllers[i].setPanelRecord(index_offset+i, i); if (i > 0) { if (index_offset+i <= i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length) { $('queryBalloonAnd'+(i)).style.display = 'block'; } else { $('queryBalloonAnd'+(i)).style.display = 'none'; } } } this._redrawScrollBtns(); } // ================================================================================================== // this._redrawAllPanels = function() { $('infoQueryStatusText').innerHTML = ""; for (var i=0; i<3; i++) { this.panelControllers[i].doRedraw(); if (i > 0) {//@pcori panel fix. for panels[i2b2.CRC.ctrlr.QT.temporalGroup] if (this.panelControllers[i].panelCurrentIndex-1 < i2b2.CRC.model.queryCurrent.panels.length) { $('queryBalloonAnd'+(i)).style.display = 'block'; } else { $('queryBalloonAnd'+(i)).style.display = 'none'; } } } } // ================================================================================================== // this._redrawPanelCount = function() { var c = i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length; if (c == 1) { var s = '1 Group'; } else { var s = c + ' Groups'; } $('groupCount').innerHTML = s; } // ================================================================================================== // this.laodQueryStatus = function( queryMasterId, queryName) { var QRS = {}; var newHTML = ""; var qi_id = ""; $('infoQueryStatusText').innerHTML = ""; var scopedCallbackQI = new i2b2_scopedCallback(); scopedCallbackQI.scope = this; scopedCallbackQI.callback = function(results) { if (results.error) { alert(results.errorMsg); return; } else { // find our query instance var qi_list = results.refXML.getElementsByTagName('query_instance'); var l = qi_list.length; for (var i=0; i<l; i++) { var temp = qi_list[i]; qi_id = i2b2.h.XPath(temp, 'descendant-or-self::query_instance_id')[0].firstChild.nodeValue; var start_date = i2b2.h.XPath(temp, 'descendant-or-self::start_date')[0].firstChild.nodeValue; if (!Object.isUndefined(start_date)) { //alert(sDate.substring(0,4) + ":" + sDate.substring(5,7) + ":" + sDate.substring(8,10)); //012345678901234567890123 //2010-12-21T16:12:01.427 start_date = new Date(start_date.substring(0,4), start_date.substring(5,7)-1, start_date.substring(8,10), start_date.substring(11,13), start_date.substring(14,16),start_date.substring(17,19),start_date.substring(20,23)); } var end_date = i2b2.h.XPath(temp, 'descendant-or-self::end_date')[0].firstChild.nodeValue; if (!Object.isUndefined(end_date)) { //alert(sDate.substring(0,4) + ":" + sDate.substring(5,7) + ":" + sDate.substring(8,10)); end_date = new Date(end_date.substring(0,4), end_date.substring(5,7)-1, end_date.substring(8,10), end_date.substring(11,13),end_date.substring(14,16), end_date.substring(17,19), end_date.substring(20,23)); } $('infoQueryStatusText').innerHTML = '<div style="clear:both;"><div style="float:left; font-weight:bold">Finished Query: "'+queryName+'"</div>'; $('infoQueryStatusText').innerHTML += '<div style="float:right">['+ (Math.floor((end_date - start_date)/100))/10 +' secs]</div></div>'; // $('infoQueryStatusText').innerHTML += '<div style="clear:both;"><div style="float:left; font-weight:bold">Finished Query: "'+queryName+'"</div><div style="margin-left:20px; clear:both; height:16px; line-height:16px; "><div height:16px; line-height:16px; ">Compute Time: ' + (Math.floor((end_date - start_date)/100))/10 + ' secs</div></div>'; i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryInstanceId("CRC:QueryTool", {qi_key_value: qi_id}, scopedCallbackQRS); } } } // this is a private function that is used by all QueryStatus object instances to check their status // callback processor to check the Query Instance var scopedCallbackQRSI = new i2b2_scopedCallback(); scopedCallbackQRSI.scope = this; scopedCallbackQRSI.callback = function(results) { if (results.error) { alert(results.errorMsg); return; } else { // find our query instance var ri_list = results.refXML.getElementsByTagName('query_result_instance'); var l = ri_list.length; for (var i=0; i<l; i++) { var temp = ri_list[i]; var description = i2b2.h.XPath(temp, 'descendant-or-self::description')[0].firstChild.nodeValue; $('infoQueryStatusText').innerHTML += "<div style=\"clear: both; padding-top: 10px; font-weight: bold;\">" + description + "</div>"; } var crc_xml = results.refXML.getElementsByTagName('crc_xml_result'); l = crc_xml.length; for (var i=0; i<l; i++) { var temp = crc_xml[i]; var xml_value = i2b2.h.XPath(temp, 'descendant-or-self::xml_value')[0].firstChild.nodeValue; var xml_v = i2b2.h.parseXml(xml_value); i2b2.PM.model.userRoles.indexOf("DATA_LDS") == -1 // var proj_data = i2b2.PM.view.admin.currentProject; var params = i2b2.h.XPath(xml_v, 'descendant::data[@column]/text()/..'); for (var i2 = 0; i2 < params.length; i2++) { var name = params[i2].getAttribute("name"); // $('infoQueryStatusText').innerHTML += "<div style=\"margin-left: 20px; clear: both; height: 16px; line-height: 16px;\">"; $('infoQueryStatusText').innerHTML += "<div style=\"clear: both; margin-left: 20px; float: left; height: 16px; line-height: 16px;\">" + params[i2].getAttribute("column") + ": <font color=\"#0000dd\">" + params[i2].firstChild.nodeValue + "" + (i2b2.PM.model.userRoles.indexOf("DATA_LDS") == -1 ? "±3" : "") + "</font></div>"; //$('infoQueryStatusText').innerHTML += "</div>"; //i2b2.h.XPath(newxml, 'descendant-or-self::result/data')[0].firstChild.nodeValue; } var ri_id = i2b2.h.XPath(temp, 'descendant-or-self::result_instance_id')[0].firstChild.nodeValue; } } } // callback processor to check the Query Result Set var scopedCallbackQRS = new i2b2_scopedCallback(); scopedCallbackQRS.scope = this; scopedCallbackQRS.callback = function(results) { if (results.error) { alert(results.errorMsg); return; } else { // find our query instance var qrs_list = results.refXML.getElementsByTagName('query_result_instance'); var l = qrs_list.length; var resultStr = ""; for (var i=0; i<l; i++) { var temp = qrs_list[i]; var qrs_id = i2b2.h.XPath(temp, 'descendant-or-self::result_instance_id')[0].firstChild.nodeValue; if (QRS.hasOwnProperty(qrs_id)) { var rec = QRS[qrs_id]; } else { var rec = new Object(); rec.QRS_ID = qrs_id; // resultStr += i2b2.h.getXNodeVal(temp, 'description'); // resultStr += i2b2.h.XPath(temp, 'descendant-or-self::query_status_type/name')[0].firstChild.nodeValue; // resultStr += "<br/>"; rec.QRS_DisplayType = i2b2.h.XPath(temp, 'descendant-or-self::query_result_type/display_type')[0].firstChild.nodeValue; rec.QRS_Type = i2b2.h.XPath(temp, 'descendant-or-self::query_result_type/name')[0].firstChild.nodeValue; rec.QRS_Description = i2b2.h.XPath(temp, 'descendant-or-self::description')[0].firstChild.nodeValue; rec.QRS_TypeID = i2b2.h.XPath(temp, 'descendant-or-self::query_result_type/result_type_id')[0].firstChild.nodeValue; } rec.QRS_Status = i2b2.h.XPath(temp, 'descendant-or-self::query_status_type/name')[0].firstChild.nodeValue; rec.QRS_Status_ID = i2b2.h.XPath(temp, 'descendant-or-self::query_status_type/status_type_id')[0].firstChild.nodeValue; // create execution time string QRS[rec.QRS_ID] = rec; if (rec.QRS_DisplayType == "CATNUM") { i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryResultInstanceId("CRC:QueryTool", {qr_key_value: rec.QRS_ID}, scopedCallbackQRSI); } else if (rec.QRS_DisplayType == "LIST") { $('infoQueryStatusText').innerHTML += "<div style=\"clear: both; padding-top: 10px; font-weight: bold;\">" + rec.QRS_Description + "</div>"; } } // $('infoQueryStatusText').innerHTML = resultStr; } } //first get instance id i2b2.CRC.ajax.getQueryInstanceList_fromQueryMasterId("CRC:QueryTool", {qm_key_value: queryMasterId}, scopedCallbackQI); //if (qi_id != "") { // i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryInstanceId("CRC:QueryTool", {qi_key_value: qi_id}, scopedCallbackQRS); // for (var q in QRS) { // i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryResultInstanceId("CRC:QueryTool", {qr_key_value: QRS[q].QRS_ID}, scopedCallbackQRSI); // } //} } // ================================================================================================== // this.doAddTemporal = function() { var html = $('temporalbuilders').innerHTML; this.tenporalBuilders = this.tenporalBuilders + 1; html = $('temporalbuilders').innerHTML + ' <div class="relationshipAmongEvents" id="temporalbuilder_' + this.tenporalBuilders + '"> ' + ' <select id="preloc1[' + this.tenporalBuilders + ']" name="preloc1[' + this.tenporalBuilders + ']" style="width:100px;"><option value="STARTDATE">Start of</option><option value="ENDDATE">End of</option></select> ' + ' <select id="instanceopf1[' + this.tenporalBuilders + ']" name="instanceopf1[' + this.tenporalBuilders + ']" style="width:150px;"><option value="FIRST">the First Ever</option><option value="LAST">the Last Ever</option><option value="ANY">any</option></select> ' + ' <select id="instancevent1[' + this.tenporalBuilders + ']" name="instancevent1[' + this.tenporalBuilders + ']" style="width:100px;"><option selected="selected">Event 1</option><option>Event 2</option>'; for (var j =3; j < i2b2.CRC.model.queryCurrent.panels.length; j ++) { html += '<option>Event ' + j + '</option>'; } html += ' </select> <br/> ' + ' <select id="postloc[' + this.tenporalBuilders + ']" name="postloc[' + this.tenporalBuilders + ']" style="width:150px;"><option value="LESS">Occurs Before</option><option value="LESSEQUAL">On Or After</option> ' + ' <option value="EQUAL">Equals</option> ' + ' <option value="GREATER">Occurs On Or After</option> ' + ' <option value="GREATEREQUAL">Occurs After</option> ' + ' </select> ' + ' <br/> ' + ' <select id="preloc2[' + this.tenporalBuilders + ']" name="preloc2[' + this.tenporalBuilders + ']" style="width:100px;"><option value="STARTDATE">Start of</option><option value="ENDDATE">End of</option></select> ' + ' <select id="instanceopf2[' + this.tenporalBuilders + ']" name="instanceopf2[' + this.tenporalBuilders + ']" style="width:150px;"><option value="FIRST">the First Ever</option><option value="LAST">the Last Ever</option><option value="ANY">any</option></select> ' + ' <select id="instancevent2[' + this.tenporalBuilders + ']" name="instancevent2[' + this.tenporalBuilders + ']" style="width:100px;"><option>Event 1</option><option selected="selected">Event 2</option>'; for (var j =3; j < i2b2.CRC.model.queryCurrent.panels.length; j ++) { html += '<option>Event ' + j + '</option>'; } html += ' </select> <br/> ' + ' <input id="bytime1[' + this.tenporalBuilders + ']" name="bytime1[' + this.tenporalBuilders + ']" type="checkbox">By <select id="byspan1[' + this.tenporalBuilders + ']" name="byspan1[' + this.tenporalBuilders + ']" style="width:50px;"><option value="GREATER">></option><option value="GREATEREQUAL" selected="selected">≥</option><option value="EQUAL">=</option><option value="LESSEQUAL">≤</option><option value="LESS"><</option></select> ' + ' <input id="bytimevalue1[' + this.tenporalBuilders + ']" name="bytimevalue1[' + this.tenporalBuilders + ']" style="width:50px;" type="text" value="1"> ' + ' <select id="bytimeunit1[' + this.tenporalBuilders + ']" name="bytimeunit1[' + this.tenporalBuilders + ']" style="width:100px;"> ' + ' <option value="HOUR">hour(s)</option> ' + ' <option value="DAY" selected="selected">day(s)</option> ' + ' <option value="MONTH">month(s)</option> ' + ' <option value="YEAR">year(s)</option></select> ' + ' <br/> ' + ' <input id="bytime2[' + this.tenporalBuilders + ']" name="bytime2[' + this.tenporalBuilders + ']" type="checkbox">And <select id="byspan2[' + this.tenporalBuilders + ']" name="byspan2[' + this.tenporalBuilders + ']" style="width:50px;"><option value="GREATER">></option><option value="GREATEREQUAL">≥</option><option value="EQUAL">=</option><option value="LESSEQUAL" selected="selected">≤</option><option value="LESS"><</option></select> ' + ' <input id="bytimevalue2[' + this.tenporalBuilders + ']" name="bytimevalue2[' + this.tenporalBuilders + ']" style="width:50px;" type="text" value="1"> ' + ' <select id="bytimeunit2[' + this.tenporalBuilders + ']" name="bytimeunit2[' + this.tenporalBuilders + ']" style="width:100px;"> ' + ' <option value="HOUR">hour(s)</option> ' + ' <option value="DAY" selected="selected">day(s)</option> ' + ' <option value="MONTH">month(s)</option> ' + ' <option value="YEAR">year(s)</option></select> ' + ' </div> '; '<div class="relationshipAmongEvents" id="temporalbuilder_' + this.tenporalBuilders + '">' + html + '</div>'; $('temporalbuilders').innerHTML = html; } // ================================================================================================== // this.doRemoveTemporal = function() { // nw096 - WEBCLIENT-155 Removes last temporal relationship if(this.tenporalBuilders == 0){ alert('You must leave a minimum of one temporal relationship.'); } else { if(jQuery("[id^='temporalbuilder_']").length > 1){ this.tenporalBuilders = this.tenporalBuilders - 1; $('temporalbuilders').lastChild.remove(); } } } // ================================================================================================== // this.doScrollFirst = function() { this.doShowFrom(0); } // ================================================================================================== // this.doScrollPrev = function() { var i = this.panelControllers[0].panelCurrentIndex - 1; if (i<0) { i=0; } this.doShowFrom(i); } // ================================================================================================== // this.doScrollNext = function() { var i = this.panelControllers[0].panelCurrentIndex + 1; var dm = i2b2.CRC.model.queryCurrent; if (i > (dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length-3)) { i=dm.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length-3; } this.doShowFrom(i); } // ================================================================================================== // this.doScrollLast = function() { var i = i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length - 3; if (i<0) { i = 0; } this.doShowFrom(i); } // ================================================================================================== // this.doScrollNew = function() { var i = i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length - 2; if (i<0) { i = 0; } this.doShowFrom(i); } // ================================================================================================== // this._redrawScrollBtns = function() { // enable & disable scroll buttons (at least the look of the buttons) var dir = i2b2.hive.cfg.urlFramework + 'cells/CRC/assets/'; if (i2b2.CRC.ctrlr.QT.panelControllers[0].panelCurrentIndex == 0) { $('panelScrollFirst').src = dir+"QryTool_b_first_hide.gif"; $('panelScrollPrev').src = dir+"QryTool_b_prev_hide.gif"; } else { $('panelScrollFirst').src = dir+"QryTool_b_first.gif"; $('panelScrollPrev').src = dir+"QryTool_b_prev.gif"; } if ((i2b2.CRC.model.queryCurrent.panels[i2b2.CRC.ctrlr.QT.temporalGroup].length - i2b2.CRC.ctrlr.QT.panelControllers[0].panelCurrentIndex) > 3) { $('panelScrollNext').src = dir+"QryTool_b_next.gif"; $('panelScrollLast').src = dir+"QryTool_b_last.gif"; } else { $('panelScrollNext').src = dir+"QryTool_b_next_hide.gif"; $('panelScrollLast').src = dir+"QryTool_b_last_hide.gif"; } }, // =====================================================================================================// /*************** * Print Query ****************/ this.doPrintQuery = function() { var v_i2b2_quey_name = i2b2.CRC.model.queryCurrent.name; var crc_bcgrnd1 = "<td style='border:1px solid #667788;'>"; var crc_bcgrnd2 = "<td style='border:1px solid #667788;background:#7FFFD4'>"; var crc_cur_bcgrnd = null; if( (v_i2b2_quey_name == null) || (v_i2b2_quey_name == undefined) || (v_i2b2_quey_name.length == 0) ){ v_i2b2_quey_name = 'No Query Name is currently provided.'; } var v_cnt_panels = i2b2.CRC.model.queryCurrent.panels[0].length; if(v_cnt_panels > 0){ var win_html_inner = "<table style='border:1px solid #667788;width:700px;' cellpadding=3px>"+ "<tbody>"; //Get Query Name if available win_html_inner += "<tr>"+ "<td style='background:#6677AA none repeat scroll 0%;border:1px solid #667788;'>"+ "<span style='color:#FFFFFF;font-weight:bold;font-family:arial,helvetica;font-size:13px;'>"+ "Query Name: "+ v_i2b2_quey_name + "<br>Temporal Constraint: "; var v_querytiming = i2b2.CRC.ctrlr.QT.queryTiming; if (v_querytiming == "ANY") { win_html_inner += "Treat all groups independently"; } else if (v_querytiming == "SAMEVISIT") { win_html_inner += "Selected groups occur in the same financial encounter"; } else if (v_querytiming == "TEMPORAL") { win_html_inner += "Define sequence of events"; } else { win_html_inner += "Items Instance will be the same"; } win_html_inner += "</span></td></tr>"; var isTemporal = false; if (this.queryTiming == "TEMPORAL") { isTemporal = true; } for (var ip = 0; ip < i2b2.CRC.model.queryCurrent.panels.length; ip++) { var v_cnt_panels = i2b2.CRC.model.queryCurrent.panels[ip].length; //Get information for each query panel for(x =0; x < v_cnt_panels; x++){ var v_dateTo = i2b2.CRC.model.queryCurrent.panels[ip][x].dateTo; var v_dateFrom = i2b2.CRC.model.queryCurrent.panels[ip][x].dateFrom; var v_exclude = i2b2.CRC.model.queryCurrent.panels[ip][x].exclude; var v_occurs = i2b2.CRC.model.queryCurrent.panels[ip][x].occurs; var v_relevance = i2b2.CRC.model.queryCurrent.panels[ip][x].relevance; var v_timing = i2b2.CRC.model.queryCurrent.panels[ip][x].timing; var v_items = i2b2.CRC.model.queryCurrent.panels[ip][x].items; if((x % 2) == 0){ crc_cur_bcgrnd = crc_bcgrnd1; } else{ crc_cur_bcgrnd = crc_bcgrnd2; } var v_strDateTo = null; var v_strDateFrom = null; //Handle JS Dates if((v_dateTo == null) || (v_dateTo == undefined) || (v_dateTo == false) ){ v_strDateTo = "none"; } else{ v_strDateTo = v_dateTo.Month +"/"+ v_dateTo.Day +"/" + v_dateTo.Year; } //QueryTiming if (v_querytiming == "ANY") { v_timing = "Treat Independently"; } else if (v_querytiming == "SAMEVISIT") { if (v_timing == "ANY") { v_timing = "Treat Independently"; } else { v_timing = "Occurs in Same Encounter"; } } else { if (v_timing == "ANY") { v_timing = "Treat Independently"; } else { v_timing = "Items Instance will be the same"; } } //Handle JS Dates if((v_dateFrom == null) || (v_dateFrom == undefined) || (v_dateFrom == false) ){ v_strDateFrom = "none"; } else{ v_strDateFrom = v_dateFrom.Month +"/"+ v_dateFrom.Day +"/" + v_dateFrom.Year; } if (isTemporal) { var tempalTitle = "Population in which events occur"; if (ip > 0) tempalTitle = "Event " + ip; win_html_inner += "<tr>"+ crc_cur_bcgrnd; win_html_inner += "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:12px;'>"+ tempalTitle "</span></td></tr>"; } win_html_inner += "<tr>"+ crc_cur_bcgrnd; win_html_inner += "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:12px;'>"+ "Group "+ (x + 1) "</span></td></tr>"; win_html_inner += "<tr><td style='border:1px solid #667788;'>"+ "<table width=100% cellpadding=2px cellspacing=0>"+ "<tbody>"+ "<tr style='border:1px solid #667788;'>"+ "<td colspan=3>"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Date From: </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ v_strDateFrom + "</span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> </span>"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Date To: </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ v_strDateTo + "</span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> </span>"+ "<!--Excluded-->"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Excluded? </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ v_exclude + "</span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> </span>"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Occurs X times: </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>> "+ v_occurs + "</span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> </span>"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Relevance %: </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> "+ v_relevance + "</span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'> </span>"+ "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>"+ " Temporal Constraint: </span>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ v_timing + "</span>"+ "</td>"+ "</tr>"; win_html_inner += "<!--Header Columns-->"+ "<tr>"+ "<!--Path-->"+ "<td width=40% style='background:#6677AA none repeat scroll 0%;align:center;border-left-style:solid;border-bottom-style:solid;border-top-style:solid;border-right-style:solid;'>"+ "<span style='color:#FFFFFF;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>Path</span>"+ "</td>"+ "<!--Concept-->"+ "<td width=30% style='background:#6677AA none repeat scroll 0%;align:center;border-bottom-style:solid;border-top-style:solid;border-right-style:solid;'>"+ "<span style='color:#FFFFFF;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>Concept/Term</span>"+ "</td>"+ "<!--Other Information-->"+ "<td width=30% style='background:#6677AA none repeat scroll 0%;align:center;border-bottom-style:solid;border-top-style:solid;border-right-style:solid;'>"+ "<span style='color:#FFFFFF;font-weight:bold;font-family:arial,helvetica;font-size:11px;'>Other Information</span>"+ "</td>"+ "</tr>"; win_html_inner += "<!--Data Columns-->"; for(n = 0; n < v_items.length; n++){ //str_shrine_path = v_items[n].sdxInfo.sdxKeyValue; //Using tooltips str_shrine_path = v_items[n].origData.tooltip; win_html_inner += "<tr>"; win_html_inner += "<td width=40% style='align:center;border-left-style:solid;border-bottom-style:solid;border-right-style:solid;'>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ str_shrine_path + "</span></td>"; win_html_inner += "<td width=30% style='align:center;solid;border-bottom-style:solid;border-right-style:solid;'>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"+ v_items[n].origData.name + "</span></td>"; win_html_inner += "<td width=30% style='align:center;border-bottom-style:solid;border-right-style:solid;'>"+ "<span style='color:black;font-weight:normal;font-family:arial,helvetica;font-size:11px;'>"; if((v_items[n].LabValues == null) || (v_items[n].LabValues == undefined) || (v_items[n].LabValues.length <= 0) ){ win_html_inner += " "; } else{ var v_lab_values = v_items[n].LabValues; var str_lab_values = ""; if(v_lab_values.GeneralValueType == "NUMBER") { str_lab_values = v_lab_values.NumericOp +" : "; if((v_lab_values.ValueLow != null) || (v_lab_values.ValueLow != undefined) ){ str_lab_values += v_lab_values.ValueLow + " - "+ v_lab_values.ValueHigh; } else { str_lab_values += v_lab_values.Value; } str_lab_values += " "+ v_lab_values.UnitsCtrl; } //String else if((v_lab_values.ValueString != null) || (v_lab_values.ValueString != undefined) ){ str_lab_values = "By String: "+ v_lab_values.ValueString; } //Flag else if((v_lab_values.ValueFlag != null) || (v_lab_values.ValueFlag != undefined) ){ var v_flag = "Normal"; if(v_lab_values.ValueFlag == "H"){ v_flag = "High"; } else if(v_lab_values.ValueFlag == "L"){ v_flag = "Low"; } str_lab_values = "By Flag: "+ v_flag; } win_html_inner += str_lab_values; } win_html_inner += "</span></td></tr>"; } //end if (isTemporal == false) break; } win_html_inner += "</tbody></table>"; } if (isTemporal) { win_html_inner += "<tr>"+ crc_cur_bcgrnd; win_html_inner += "<span style='color:black;font-weight:bold;font-family:arial,helvetica;font-size:12px;'><center>"+ $('instancevent1[0]').options[$('instancevent1[0]').selectedIndex].value + " " + $('preloc1[0]').options[$('preloc1[0]').selectedIndex].value +" " + $('instanceopf1[0]').options[$('instanceopf1[0]').selectedIndex].value +"<br/>" + $('postloc[0]').options[$('postloc[0]').selectedIndex].value + "<br/>" + $('instancevent2[0]').options[$('instancevent2[0]').selectedIndex].value + " " + $('preloc2[0]').options[$('preloc2[0]').selectedIndex].value + " " + $('instanceopf2[0]').options[$('instanceopf2[0]').selectedIndex].value +" "; if ( $('bytime1[0]').checked) { win_html_inner += "<br/>" + $('byspan1[0]').options[$('byspan1[0]').selectedIndex].value + " " + $('bytimevalue1[0]').value + " " + $('bytimeunit1[0]').options[$('bytimeunit1[0]').selectedIndex].value +" "; } if ( $('bytime2[0]').checked) { win_html_inner += "<br/>" + $('byspan2[0]').options[$('byspan2[0]').selectedIndex].value + " " + $('bytimevalue2[0]').value + " " + $('bytimeunit2[0]').options[$('bytimeunit2[0]').selectedIndex].value; } win_html_inner += "</center></span></td></tr>"; } win_html_inner += "</tbody></table>"; //Query Status window var self = i2b2.CRC.ctrlr.currentQueryStatus; if( (self != null) && (self != undefined) && (self.dispDIV != null) && (self.dispDIV != undefined) ){ win_html_inner += self.dispDIV.innerHTML; } var win = window.open("",'shrinePrintWindow','width=800,height=750,menubar=yes,resizable=yes,scrollbars=yes'); win.document.writeln('<div id="shrinePrintQueryPage">'); win.document.writeln(win_html_inner); win.document.writeln('</div>'); } else{ alert("Currently no query is available for printing. \nPlease generate a query before clicking on [Print Query] button."); } }, // =====================================================================================================// /********************** * Query Report BG **********************/ // Print Query variables this.queryPanelObjForPrinting = {}; this.QI_Rec_ForPrinting = new Object(); this.QueryResultsForPrinting = {}; this.QueryResultsForPrintingIndex = 0; this.QueryResultsNum = 0; this.query_user_id=null; this.XMLResultsStringForPrint = ""; var uniqueItems = $H(); var queryReportWin = null; // End Print Query variables this.ClearVariablesForPrinting = function() { this.queryPanelObjForPrinting = {}; this.QI_Rec_ForPrinting = new Object(); this.QueryResultsForPrinting = {}; this.QueryResultsForPrintingIndex = 0; this.QueryResultsNum = 0; this.query_user_id=null; this.XMLResultsStringForPrint = ""; var uniqueItems = $H(); queryReportWin = null; }; this.createQueryReport = function(queryNameInput,previewQueryOnly) { //This request is to populate the query report panel in the query results section //If the status box is empty no need to proceed if($('infoQueryStatusText').innerHTML=="") return; //Clean the corresponding div before repopulating $("infoQueryStatusReport").innerHTML=""; //Clean and populate the variables for printing this.ClearVariablesForPrinting(); if(queryNameInput.length>0 || previewQueryOnly) this.queryPanelObjForPrinting.name = queryNameInput; else{ var nameObj = document.getElementById("queryName"); var v_i2b2_quey_name = i2b2.CRC.model.queryCurrent.name; if(nameObj){ this.queryPanelObjForPrinting.name = nameObj.innerHTML; } } var userIdElm = $("userIdElem"); if(userIdElm) this.query_user_id = userIdElm.value; var v_cnt_panels = i2b2.CRC.model.queryCurrent.panels[0].length; if(v_cnt_panels > 0){ this.queryPanelObjForPrinting.timing = i2b2.CRC.ctrlr.QT.queryTiming; var isTemporal = false; if (this.queryTiming == "TEMPORAL") { isTemporal = true; } this.queryPanelObjForPrinting.subQryRelationStructure = []; this.queryPanelObjForPrinting.mainQryStructure = []; this.queryPanelObjForPrinting.subQryStructure = []; this.queryPanelObjForPrinting.hasSubquery = false; for (var ip = 0; ip < i2b2.CRC.model.queryCurrent.panels.length; ip++) { var v_cnt_panels = i2b2.CRC.model.queryCurrent.panels[ip].length; //Get information for each query panel var panels = []; for(x =0; x < v_cnt_panels; x++){ var po = {}; po.dateTo = i2b2.CRC.model.queryCurrent.panels[ip][x].dateTo; po.dateFrom = i2b2.CRC.model.queryCurrent.panels[ip][x].dateFrom; po.exclude = i2b2.CRC.model.queryCurrent.panels[ip][x].exclude; po.occurs = i2b2.CRC.model.queryCurrent.panels[ip][x].occurs; po.relevance = i2b2.CRC.model.queryCurrent.panels[ip][x].relevance; po.timing = i2b2.CRC.model.queryCurrent.panels[ip][x].timing; po.subquery = false; if (isTemporal && ip>0){ po.name = "Event" + ip; po.subquery = true; } var v_items = i2b2.CRC.model.queryCurrent.panels[ip][x].items; var v_strDateTo = null; var v_strDateFrom = null; //Handle JS Dates if((po.dateTo == null) || (po.dateTo == undefined) || (po.dateTo == false) ){ v_strDateTo = "none"; } else{ v_strDateTo = po.dateTo.Month +"/"+ po.dateTo.Day +"/" + po.dateTo.Year; } po.dateTo = v_strDateTo //Handle JS Dates if((po.dateFrom == null) || (po.dateFrom == undefined) || (po.dateFrom == false) ){ po.strDateFrom = "none"; } else{ v_strDateFrom = po.dateFrom.Month +"/"+ po.dateFrom.Day +"/" + po.dateFrom.Year; } po.dateFrom = v_strDateFrom; po.items = []; for(n = 0; n < v_items.length; n++){ var itemObj = {}; itemObj.tooltip = v_items[n].origData.tooltip? v_items[n].origData.tooltip:""; itemObj.name = v_items[n].origData.result_instance_id ? (v_items[n].origData.title ? v_items[n].origData.title : (v_items[n].origData.titleCRC ? v_items[n].origData.titleCRC : "")) :(v_items[n].origData.newName ? v_items[n].origData.newName : (v_items[n].origData.name?v_items[n].origData.name:"")); itemObj.hasChildren = v_items[n].origData.hasChildren; po.items.push(itemObj); //itemObj.level = } panels[x] = po; } if(panels.length>0){ if (isTemporal) { if (ip > 0) this.queryPanelObjForPrinting.subQryStructure.push(panels); else this.queryPanelObjForPrinting.mainQryStructure.push(panels); } else this.queryPanelObjForPrinting.mainQryStructure.push(panels); } } if(isTemporal) { var evntRelDiv = document.getElementById('temporalbuilders'); if(evntRelDiv) { var relationNodes = evntRelDiv.childNodes; this.queryPanelObjForPrinting.subQryRelationStructure = []; var subQryRelationStructureIndex = 0; for(i=0; i < relationNodes.length; i++) { var thisRelNode = relationNodes[i]; var rel = {}; rel.spans = []; var spanIndex = 0; var spanObj = {}; var bytime1 = false; var bytime2 = false; var allChildren = thisRelNode.childNodes; for(j=0; j < allChildren.length; j++) { var currentNode = allChildren[j]; if(currentNode.id){ if(currentNode.id.indexOf("preloc1") >= 0) { rel.firstQryJoinCol = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("instanceopf1") >= 0) { rel.firstQryOp = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("instancevent1") >= 0) { rel.firstQryEvntNm = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("postloc") >= 0) { rel.operator = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("preloc2") >= 0) { rel.secondQryJoinCol = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("instanceopf2") >= 0) { rel.secondQryOp = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf("instancevent2") >= 0) { rel.secondQryEvntNm = getSelectedValueFromOptions(currentNode.options); } if((currentNode.id.indexOf('bytime1') >= 0) && currentNode.checked) { bytime1 = true; } if(currentNode.id.indexOf('byspan1') >= 0 && bytime1) { spanObj.oprator = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf('bytimevalue1') >= 0 && bytime1) { spanObj.value = currentNode.value; } if(currentNode.id.indexOf('bytimeunit1') >= 0 && bytime1) { spanObj.units = getSelectedValueFromOptions(currentNode.options); rel.spans[spanIndex++] = spanObj; } if((currentNode.id.indexOf('bytime2') >= 0) && currentNode.checked) { bytime2 = true; spanObj = {}; } if(currentNode.id.indexOf('byspan2') >= 0 && bytime2) { spanObj.oprator = getSelectedValueFromOptions(currentNode.options); } if(currentNode.id.indexOf('bytimevalue2') >= 0 && bytime2) { spanObj.value = currentNode.value; } if(currentNode.id.indexOf('bytimeunit2') >= 0 && bytime2) { spanObj.units = getSelectedValueFromOptions(currentNode.options); rel.spans[spanIndex++] = spanObj; } } } if(allChildren.length > 0) this.queryPanelObjForPrinting.subQryRelationStructure[subQryRelationStructureIndex++] = rel ; } } } //All variables are ready to print. var infoQueryStatusTextObj = $('infoQueryStatusText'); this.createHTMLForPrinting(previewQueryOnly); } else{ alert("Currently no query is available for printing. \nPlease generate a query before clicking on [Print Query] button."); } }; this.PrintQueryTemplate = "<head>"+ "<title>Query Report</title>"+ // "<script type=\"text/javascript\" src=\"js-i2b2/cells/CRC/CRC_ctrlr_Query_Report.js\"></script>"+ "<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>"+ "<link rel='stylesheet' TYPE='text/css' href='js-i2b2/cells/CRC/assets/query_report.css'>"+ "<link href='js-ext/c3code/c3.css' rel='stylesheet' type='text/css'>"+ "</head>"+ "<body>"+ "</body>"; this.PrintQueryBody = "<div id=\"QueryReportLoading\"><img src=\"js-i2b2/cells/CRC/assets/loading.gif\" alt=\"Loading\"/></div>"+ "<div id='QueryReportContainer' class='no-show'>"+ "<span style='float:right;'><img src='assets/images/title.png'/></span>"+ "<span class='no-print' style='font-family:Arial'><img src=\"js-i2b2/cells/CRC/assets/print.png\"/> <a href='javascript:window.print()' title='Click here to print the report.'>Print Report</a></span>"+ "<div class='QRMainHeader'>Query Report</div>"+ "<table id='queryDetailsTable'></table>"+ "<div class='descHead'>Query Definition</div>"+ "<table id='qdHeaderTable'></table>"+ "<table id='qdContainerTable'></table><br>"+ "<table id='temporalQryEventsContainerTable'></table><br>"+ "<table id='temporalQryEventsRelationsTable'></table>"+ "<div id='qrsTitle' class='descHead'>Query Results</div>"+ "<br><div id='queryResultsContainer'><div id='tablesContainer'></div><div id='graphsContainer'></div></div>" + "<span class='no-print' style='font-family:Arial'><img src=\"js-i2b2/cells/CRC/assets/print.png\"/> <a href='javascript:window.print()' title='Click here to print the report.'>Print Report</a></span>"+ "</div>"; this.createHTMLForPrinting = function(previewQueryOnly) { var QueryReportWin = null; var QueryReportDiv = null; var ua = window.navigator.userAgent; var msie = ua.indexOf("MSIE "); var browserIsIE = false; if (msie > 0) browserIsIE = true; if(!(window.ActiveXObject) && "ActiveXObject" in window) browserIsIE = true; var savedHTML = null; if(this.queryPanelObjForPrinting.mainQryStructure.length > 0){ if( previewQueryOnly){ if(browserIsIE){ i2b2.CRC.ctrlr.QT.queryReportViewer.yuiPanel = null; i2b2.CRC.ctrlr.QT.queryReportViewer.show(); QueryReportDiv = jQuery(i2b2.CRC.ctrlr.QT.queryReportViewer.yuiPanel.body)//.find('#queryReport-viewer-body'); } else{ //Open a new window for printing query for non-IE browsers QueryReportWin = window.open("",'shrinePrintWindow','width=800,height=750,menubar=yes,resizable=yes,scrollbars=yes'); //Request came for query preview generation. Need to load the child window with template // if(previewQueryOnly){ var doc = QueryReportWin.document; doc.write(this.PrintQueryTemplate); doc.write(this.PrintQueryBody); doc.close(); // } } } else { QueryReportDiv = $('infoQueryStatusReport'); QueryReportDiv.innerHTML=this.PrintQueryBody; var printLinks = $$('.no-print'); if(printLinks) printLinks.each(function(printLink){ var link = printLink.down('a'); if(link) link.href="javascript:i2b2.CRC.ctrlr.QT.PrintElem('infoQueryStatusReport')"; }); } //Populate the query details section try{ if(QueryReportWin) this.getQueryDetails(this.queryPanelObjForPrinting,this.query_user_id,previewQueryOnly,QueryReportWin,"queryDetailsTable"); if(QueryReportDiv) this.getQueryDetails(this.queryPanelObjForPrinting,this.query_user_id,previewQueryOnly,false,"queryDetailsTable"); } catch(e) { console.error(e); } //Populate the query description section try{ if(QueryReportWin) this.getQrTiming(this.queryPanelObjForPrinting,QueryReportWin,"qdHeaderTable"); if(QueryReportDiv) this.getQrTiming(this.queryPanelObjForPrinting,false,"qdHeaderTable"); } catch(e) { console.error(e); } //Populate the query structure description section var qdDescription = this.getQueryDescription(this.queryPanelObjForPrinting.mainQryStructure); if(qdDescription) { try{ var Row = "<tr><td width=\"5px\"><div class=\"tabSpace\"></div></td>"; var Cell = "<td class=\"eventsRelHdr\">" + "All Groups" + "</td>"; Row = Row + Cell; if(QueryReportWin) jQuery("#qdContainerTable",QueryReportWin.document).append(Row); if(QueryReportDiv) jQuery("#qdContainerTable").append(Row); if(QueryReportWin) jQuery("#qdContainerTable",QueryReportWin.document).append(qdDescription); if(QueryReportDiv) jQuery("#qdContainerTable").append(qdDescription); } catch(e) { console.error(e); } } //Populate temporal query events description section var qdDescription = this.getQueryDescription(this.queryPanelObjForPrinting.subQryStructure); if(qdDescription) { try{ var Row = "<tr><td width=\"5px\"><div class=\"tabSpace\"></div></td>"; var Cell = "<td class=\"eventsRelHdr\">" + "All Events" + "</td>"; Row = Row + Cell; if(QueryReportWin) jQuery("#temporalQryEventsContainerTable",QueryReportWin.document).append(Row); if(QueryReportDiv) jQuery("#temporalQryEventsContainerTable").append(Row); if(QueryReportWin) jQuery("#temporalQryEventsContainerTable",QueryReportWin.document).append(qdDescription); if(QueryReportDiv) jQuery("#temporalQryEventsContainerTable").append(qdDescription); } catch(e) { console.error(e); } } //Populate temporal query events relation section if(this.queryPanelObjForPrinting.subQryStructure && this.queryPanelObjForPrinting.subQryStructure.length>0){ var temporalQEventsRelTable = null; if(QueryReportWin) temporalQEventsRelTable = QueryReportWin.document.getElementById("temporalQryEventsRelationsTable"); if(QueryReportDiv) temporalQEventsRelTable = $("temporalQryEventsRelationsTable"); try{ var qdDescription = this.getTemporalQueryEventRelations(temporalQEventsRelTable); } catch(e) { console.error(e); } } if(!previewQueryOnly){ //Populate the query results section var resultsArray = i2b2.CRC.view.graphs.parseInputIntoArray(i2b2.CRC.ctrlr.currentQueryResults.resultString, true); if(resultsArray && resultsArray.length>0){ try{ if(QueryReportWin) this.createResultsForPrint(resultsArray,QueryReportWin); else{ this.createResultsForPrint(resultsArray,false); } } catch(e) { console.error(e); } } else // There is no results, so no need to show Query Results section { var resultTitleDiv = null; if(QueryReportWin) resultTitleDiv = QueryReportWin.document.getElementById("qrsTitle"); if(QueryReportDiv) resultTitleDiv = $("qrsTitle"); if(resultTitleDiv){ resultTitleDiv.parentNode.removeChild(resultTitleDiv); } } } else // This window is to only show the query structure preview, so no need to show Query Results section { var resultTitleDiv = null; if(QueryReportWin) resultTitleDiv = QueryReportWin.document.getElementById("qrsTitle"); if(QueryReportDiv) resultTitleDiv = $("qrsTitle"); if(resultTitleDiv){ resultTitleDiv.parentNode.removeChild(resultTitleDiv); } } var loaderDiv = null; if(QueryReportWin) loaderDiv = QueryReportWin.document.getElementById("QueryReportLoading"); if(QueryReportDiv){ // if(browserIsIE && printFromId) loaderDiv = jQuery(QueryReportDiv).find('#QueryReportLoading'); // else // loaderDiv = jQuery("#infoQueryStatusReport #QueryReportLoading"); } if(loaderDiv) jQuery(loaderDiv).addClass("no-show"); var resultsDiv = null; if(QueryReportWin) resultsDiv = QueryReportWin.document.getElementById("QueryReportContainer"); if(QueryReportDiv){ // if(browserIsIE && printFromId) resultsDiv = jQuery(QueryReportDiv).find('#QueryReportContainer'); // else // resultsDiv = $("#infoQueryStatusReport #QueryReportContainer"); } if(resultsDiv) jQuery(resultsDiv).removeClass("no-show"); if(browserIsIE && previewQueryOnly) { // this.PrintElem(); // jQuery(resultsDiv).html(savedHTML); } } else{ alert("Currently no query is available for printing. \nPlease generate a query before clicking on [Print Query] button."); } }; this.getQueryDetails = function(queryObj,query_user_id,previewQueryOnly,QueryReportWin,objId){ var username = this.getQueryUserFullName(query_user_id); var instanceRec = this.QI_Rec_ForPrinting; var dateInfoProvided = false; var diff = ""; var text = ""; var qrNameNotProvided = false; if(queryObj.name.length <= 0){ text = 'No Query Name is currently provided'; qrNameNotProvided = true; } else{ if(previewQueryOnly) text = 'The query is entitled "' + queryObj.name + '"'; else text = 'The query entitled "' + queryObj.name ; } var formattedResObj = i2b2.CRC.ctrlr.currentQueryResults; var resString = formattedResObj.resultString; var computeTime = null; if(resString.toLowerCase().indexOf("compute time")>0) { var textCompTime = resString.match(new RegExp("Compute Time" + "(.*)" + "\n")); if(textCompTime.length>0) { var compText = textCompTime[0]; var splitcompText = compText.split(":"); if(splitcompText && splitcompText.length>1) computeTime = splitcompText[1]; } } text = (qrNameNotProvided ? 'The query "' : '') + text + '" was completed in '+ computeTime + '. This query was performed by "'+ username +'".'; if(QueryReportWin) jQuery("#" + objId,QueryReportWin.document).append('<tr><td>' + text.toString() + '</td></tr>'); else jQuery("#" + objId).append('<tr><td>' + text.toString() + '</td></tr>'); }; this.getQrTiming = function(queryObj,QueryReportWin,objId){ var tdText = ""; if(queryObj.timing) { switch(queryObj.timing) { case "ANY": tdText = " Temporal Constraint: Treat All Groups Independently"; break; case "SAMEVISIT": tdText = " Temporal Constraint: Selected groups occur in the same financial encounter"; break; case "TEMPORAL": //Temporal query query_order = "Groups occur in the same sequence from left to right"; tdText = " Temporal Constraint: Population in which events occur"; } if(QueryReportWin) jQuery("#" + objId,QueryReportWin.document).append('<tr><td>' + tdText + '</td></tr>'); else jQuery("#" + objId).append('<tr><td>' + tdText + '</td></tr>'); } }; this.getQueryDescription = function(queryObj) { var elemToAppend = ""; if(queryObj.length > 0) { elemToAppend = "<tr>"; var panelNum = 0; elemToAppend = elemToAppend + "<td width=\"5px\"><div class=\"tabSpace\"></div></td>"; var tdObj = "<td width=\"610px\">"; queryObj.each(function(queryData){ var andCounter = 0; var subQryEventNameDisplayed = false; queryData.each(function(panelData){ var orCounter = 0; var numItemsInPanel = panelData.items.length; var panelContdivObj = "<div class=\"panelContainer"; var PanelTableObj = "<table width=\"615px\" border=\"0\">"; var PanelTableTrObj = "<tr>"; var PanelTableTd1Obj = "<td width=\"5px\"><div class=\"tabSpace\"></div></td>"; PanelTableTrObj = PanelTableTrObj + PanelTableTd1Obj; var PanelTableTd2Obj = "<td width=\"610px\">"; panelNum++ ; var panelOperatorDivId = "PanelOp-" + panelNum; var panelOperatorDiv = "<div id=\"" + panelOperatorDivId + "\" class=\"opDiv\">"; if(andCounter == 0){ andCounter++ ; if (panelData.exclude) { panelOperatorDiv = panelOperatorDiv + "NOT"; panelContdivObj = panelContdivObj + " notOpPanel"; } } else { var text = "AND"; if (panelData.exclude) { text = "AND NOT"; panelContdivObj = panelContdivObj + " notOpPanel"; } panelOperatorDiv = panelOperatorDiv + text; andCounter++ ; } var panelItemDiv = "<div class=\"panelItem\">"; var panelTiming = ""; switch(panelData.timing) { case "ANY": panelTiming = "Independent of Visit"; break; case "SAMEVISIT": panelTiming = "Occurs in Same Encounter"; break; case "SAMEINSTANCENUM": panelTiming = "Items Instance will be the same"; break; } var panelDateFrom = ""; if(panelData.dateFrom) { if(panelData.dateFrom.Month && panelData.dateFrom.Day && panelData.dateFrom.Year) panelDateFrom = panelData.dateFrom.Month + "/" + panelData.dateFrom.Day + "/" + panelData.dateFrom.Year; else { panelDateFrom = panelData.dateFrom; } } var panelDateTo = ""; if(panelData.dateTo) { if(panelData.dateTo.Month && panelData.dateTo.Day && panelData.dateTo.Year) panelDateTo = panelData.dateTo.Month + "/" + panelData.dateTo.Day + "/" + panelData.dateTo.Year; else { panelDateTo = panelData.dateTo; } } var panelDateRangeText = "From earliest date available to latest date available"; if(panelData.dateFrom && panelData.dateTo) { if(panelDateFrom == "none") panelDateFrom = "earliest date available"; if(panelDateTo == "none") panelDateTo = "latest date available"; panelDateRangeText = "From " + panelDateFrom + " to " + panelDateTo; } else { if(panelDateFrom == "none") panelDateFrom = "earliest date available"; if(panelDateTo == "none") panelDateTo = "latest date available"; if(panelData.dateFrom && !panelData.dateTo) panelDateRangeText = "From " + panelDateFrom + " to latest date available"; if(!panelData.dateFrom && panelData.dateTo) panelDateRangeText = "From earliest date available to " + panelDateTo; } var panelItemOccurrenceText = "# of times an item is recorded is > " + panelData.occurs; panelData.items.each(function(itemData){ var data = itemData; if(!(typeof itemData.origData == 'undefined')) data = itemData.origData; var qrPanelItemTableObj = "<table class=\"qrPanelItemTable\">"; var qrPanelItemTableTrObj = "<tr>"; var imageObj = null; //Evaluate the lab values var str_lab_values = ""; if(data.LabValues){ var v_lab_values = data.LabValues; if(v_lab_values.GeneralValueType == "NUMBER") { var labOp = ""; switch(v_lab_values.NumericOp) { case "LT": labOp = " <"; break; case "LE": labOp = " <="; break; case "EQ": labOp = " ="; break; case "BETWEEN": labOp = " Between"; break; case "GE": labOp = " >="; break; case "GT": labOp = " >"; break; } str_lab_values = labOp +" "; if((v_lab_values.ValueLow != null) || (v_lab_values.ValueLow != undefined) ){ str_lab_values += v_lab_values.ValueLow + " - "+ v_lab_values.ValueHigh; } else { str_lab_values += v_lab_values.Value; } str_lab_values += " "+ v_lab_values.UnitsCtrl; } //String else if((v_lab_values.ValueString != null) || (v_lab_values.ValueString != undefined) ){ str_lab_values = "By String: "+ v_lab_values.ValueString; } //Flag else if((v_lab_values.ValueFlag != null) || (v_lab_values.ValueFlag != undefined) ){ var v_flag = "Normal"; if(v_lab_values.ValueFlag == "H"){ v_flag = "High"; } else if(v_lab_values.ValueFlag == "L"){ v_flag = "Low"; } str_lab_values = "By Flag: "+ v_flag; } // End evaluate lab values } if(data.hasChildren) //It is a previous query inside a query, so no item-icon provided { if( data.hasChildren.indexOf("LA") >=0 ) { imageObj = "<img src=\"js-i2b2/cells/ONT/assets/sdx_ONT_CONCPT_leaf.gif\" style=\"float:left;margin-top:5px;margin-right:5px;\">"; } else { imageObj = "<img src=\"js-i2b2/cells/ONT/assets/sdx_ONT_CONCPT_branch-exp.gif\" style=\"float:left;margin-top: 5px;margin-right: 5px;\">"; } } if(imageObj) { var nameText = ""; if(data.newName) nameText = data.newName; else nameText = data.name; var qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-weight:bold; font-size:18px;\"><div width=\"400px\" style=\"display:inline;\">" + imageObj + "<div>" + " " + nameText + str_lab_values + "</div></div>" + "</td>"; } else { var qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-weight:bold; font-size:18px;\">" + data.name + str_lab_values + "</td>"; } qrPanelItemTableTrObj = qrPanelItemTableTrObj + qrPanelItemTableTdObj; qrPanelItemTableObj = qrPanelItemTableObj + qrPanelItemTableTrObj + "</tr>"; qrPanelItemTableTrObj = "<tr>"; qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-weight:bold; font-size:14px;\">" + data.tooltip + "</td>"; qrPanelItemTableTrObj = qrPanelItemTableTrObj + qrPanelItemTableTdObj + "</tr>"; qrPanelItemTableObj = qrPanelItemTableObj + qrPanelItemTableTrObj; qrPanelItemTableTrObj = "<tr>"; qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-size:14px;\">" + panelTiming + "</td>" ; qrPanelItemTableTrObj = qrPanelItemTableTrObj + qrPanelItemTableTdObj + "</tr>"; qrPanelItemTableObj = qrPanelItemTableObj + qrPanelItemTableTrObj; qrPanelItemTableTrObj = "<tr>"; qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-size:14px;\">" + panelDateRangeText + "</td>" ; qrPanelItemTableTrObj = qrPanelItemTableTrObj + qrPanelItemTableTdObj + "</tr>"; qrPanelItemTableObj = qrPanelItemTableObj + qrPanelItemTableTrObj; qrPanelItemTableTrObj = "<tr>"; qrPanelItemTableTdObj = "<td width=\"610px\" style=\"font-size:14px;\">" + panelItemOccurrenceText + "</td>" ; qrPanelItemTableTrObj = qrPanelItemTableTrObj + qrPanelItemTableTdObj + "</tr>"; qrPanelItemTableObj = qrPanelItemTableObj + qrPanelItemTableTrObj; qrPanelItemTableObj = qrPanelItemTableObj + "</table>"; panelItemDiv = panelItemDiv + "<br>" + qrPanelItemTableObj + "<br>"; if(++orCounter < numItemsInPanel) { var orDiv = "<div style=\"font-size: 20px;font-style: italic;font-weight: bold;\">" + "OR" + "</div>"; panelItemDiv = panelItemDiv + orDiv; } }); panelItemDiv = panelItemDiv + "</div>"; PanelTableTd2Obj = PanelTableTd2Obj + panelItemDiv + "</td>"; PanelTableTrObj = PanelTableTrObj + PanelTableTd2Obj + "</tr>"; PanelTableObj = PanelTableObj + PanelTableTrObj + "</table>"; panelContdivObj = panelContdivObj + "\">" + PanelTableObj + "</div>"; panelOperatorDiv = panelOperatorDiv + "</div>"; if(panelData.subquery) { if(!subQryEventNameDisplayed){ var eventNameDiv = "<div class=\"opDiv\">" + panelData.name + "</div>"; tdObj = tdObj + eventNameDiv + panelOperatorDiv + panelContdivObj; subQryEventNameDisplayed = true; } else tdObj = tdObj + panelOperatorDiv + panelContdivObj; } else tdObj = tdObj + panelOperatorDiv + panelContdivObj; }); }); } if(elemToAppend) elemToAppend = elemToAppend + tdObj + "</td></tr>"; return elemToAppend; }; this.getTemporalQueryEventRelations = function(eventsRelTable){ if(this.queryPanelObjForPrinting.subQryRelationStructure.length > 0 ) { var Row = new Element('tr'); var Cell = new Element('td',{'width':'5px'}); var divInCell = new Element('div',{'class':'tabSpace'}); Row.insert(Cell.insert(divInCell)); Cell = new Element('td',{'class':'eventsRelHdr'}).update('Order of Events'); Row.insert(Cell); var tempDiv = new Element('div'); tempDiv.insert(Row); jQuery(eventsRelTable).append(jQuery(tempDiv).html()); } this.queryPanelObjForPrinting.subQryRelationStructure.each(function(relation){ var Row = new Element('tr'); var Cell = new Element('td',{'width':'5px'}); var divInCell = new Element('div',{'class':'tabSpace'}); Row.insert(Cell.insert(divInCell)); Cell = new Element('td', {'class' : 'eventsRel'}); var mnSpan = new Element('span', {'class' : 'eventsRelSpan'}); var mainSpan = new Element('center'); var textFirst = relation.firstQryJoinCol + " " + relation.firstQryOp + " occurrence for " + relation.firstQryEvntNm; var firstSpan = new Element('span').update(textFirst); mainSpan.insert(firstSpan).insert(new Element('br')); var relationOperator = ""; switch(relation.operator) { case "LESS": relationOperator = "Occurs Before"; break; case "LESSEQUAL": relationOperator = "Occurs On Or Before"; break; case "EQUAL": relationOperator = "Occurs Simultaneously With"; break; case "GREATER": relationOperator = "Occurs After"; break; case "GREATEREQUAL": relationOperator = "Occurs On or After"; break; default: break; } var textOperator = relationOperator.length>0 ? relationOperator : relation.operator; var opSpan = new Element('span').update(textOperator); mainSpan.insert(opSpan).insert(new Element('br')); var textSecond = relation.secondQryJoinCol + " of " + relation.secondQryOp + " occurrence of " + relation.secondQryEvntNm; var secondSpan = new Element('span').update(textSecond); mainSpan.insert(secondSpan).insert(new Element('br')); var firstSpan = true; relation.spans.each(function(thisSpan){ switch(thisSpan.oprator) { case "GREATER" : thisSpan.oprator = ">"; break; case "GREATEREQUAL" : thisSpan.oprator = ">="; break; case "EQUAL" : thisSpan.oprator = "="; break; case "LESSEQUAL" : thisSpan.oprator = "<="; break; case "LESS" : thisSpan.oprator = "<"; break; default: break; } var text = ""; if(firstSpan) { text = " By " + thisSpan.oprator + " " + thisSpan.value + " " + thisSpan.units; firstSpan = false; } else { text = " And " + thisSpan.oprator + " " + thisSpan.value + " " + thisSpan.units; } mainSpan.insert((new Element('span')).update(text)).insert(new Element('br')); }); mnSpan.insert(mainSpan); Row.insert((Cell).insert(mnSpan)); var tempDiv = new Element('div'); tempDiv.insert(Row); jQuery(eventsRelTable).append(jQuery(tempDiv).html()); }); }; this.createResultsForPrint = function(dataArray,child){ var _2DResultsArray = i2b2.CRC.view.downloadData.getFormattedResults(dataArray); if(_2DResultsArray && _2DResultsArray.length>0) { //Populate the tables var clonedArray = _2DResultsArray.slice(0); var allSites = $H(); var allSitesRow = clonedArray[0]; if(allSitesRow && allSitesRow.length>0) { for(var x = 1; x < allSitesRow.length ; x++) { var siteName = allSitesRow[x]; allSites.set(siteName,x); //SiteName,Index pairs } } clonedArray = _2DResultsArray.slice(0); var allUniqueBreakDowns = $H(); for(var i = 0 ; i < clonedArray.length ; i++) { var brkDownEntry = clonedArray[i][0]; if(brkDownEntry.length>0) { var tmpBrkDown = brkDownEntry.split("|"); if(tmpBrkDown && tmpBrkDown.length>1) { thisBrkDown = tmpBrkDown[0]; allUniqueBreakDowns.set(thisBrkDown,thisBrkDown); } } } //Take care of the patient number element separately //Create the data array for table creation clonedArray = _2DResultsArray.slice(0); var dataArray = new Array(); var thisRow = clonedArray[0].slice(0); thisRow[0] = ""; dataArray.push(thisRow); thisRow = clonedArray[1].slice(0); thisRow[0] = "Total Patients Count"; dataArray.push(thisRow); if(dataArray && dataArray.length>0) { jQuery('#tablesContainer').append("<br/>"); jQuery('#tablesContainer').append("<div class='subTitleDivs'>Total Number of Cases</div>" ); var sortArray = i2b2.CRC.ctrlr.QT.createShorterDataArray(dataArray); if(sortArray && sortArray.length>0) i2b2.CRC.ctrlr.QT.createTable(sortArray); else i2b2.CRC.ctrlr.QT.createTable(dataArray); } //Create tables for the breakdowns allUniqueBreakDowns.each(function(brkDown) { clonedArray = _2DResultsArray.slice(0); dataArray = new Array(); var thisRow = _2DResultsArray[0].slice(0); thisRow[0] = ""; dataArray.push(thisRow); var category = ""; for(var i = 1; i<clonedArray.length;i++) { var thisbrkDown = clonedArray[i][0]; if(thisbrkDown.toLowerCase().indexOf(brkDown.key.toLowerCase())>=0) { thisRow = clonedArray[i]; var tmpBrkDown = thisbrkDown.split("|"); if(tmpBrkDown && tmpBrkDown.length>1) { category = tmpBrkDown[0]; thisRow[0][0] = tmpBrkDown[1]; } dataArray.push(thisRow); } } if(dataArray && dataArray.length>0) { jQuery('#tablesContainer').append("<br/>"); jQuery('#tablesContainer').append("<div class='subTitleDivs'>Total Unique Patients by " + category +"</div>" ); var sortArray = i2b2.CRC.ctrlr.QT.createShorterDataArray(dataArray); if(sortArray && sortArray.length>0) i2b2.CRC.ctrlr.QT.createTable(sortArray); else i2b2.CRC.ctrlr.QT.createTable(dataArray); } }); //Populate charts jQuery('#tablesContainer').append("<br/><br/>"); i2b2.CRC.view.graphs.createGraphs("graphsContainer", i2b2.CRC.ctrlr.currentQueryResults.resultString, true); } }; this.createShorterDataArray = function(dataArray) { try{ if(dataArray.length>0) { var siteRow = dataArray[0]; var totalNumOfSites = siteRow.length - 1; if(totalNumOfSites > 10) { var finalArr = []; var loopNum = 0; var totalLoopsRequired = Math.floor(totalNumOfSites/10); if(totalNumOfSites%10 >0) totalLoopsRequired++; while(loopNum<totalLoopsRequired){ var newRow = new Array(11); for(var i = 0; i < dataArray.length; i++) { newRow = new Array(11); //Decide the first column entry for current row var thisRow = dataArray[i]; newRow[0] = thisRow[0]; for(var j=1; j<=10; j++) { var actualCol = 10*loopNum + j; if(actualCol < thisRow.length) newRow[j] = thisRow[actualCol]; else break; } finalArr.push(newRow); } loopNum++; } return finalArr; } else return dataArray; } else return dataArray; } catch(e) { console.error(e); } }; this.createTable = function(dataArray) { var content = "<table class='reultsTable'>"; for(var i = 0 ; i < dataArray.length ; i++) { var thisRow = dataArray[i]; if(i==0) { content += "<tr>"; for(var j = 0 ; j < thisRow.length ; j++) { content += "<th class='descResultshead'>" + thisRow[j] + "</th>"; } content += "</tr>"; } else { content += "<tr>"; var thisRowIsHeader = false; for(var j = 0 ; j < thisRow.length ; j++) { var thisRowColItem = thisRow[j]; if(thisRowColItem) { - if((thisRowColItem.trim().indexOf("10 patients or fewer"))>0) + + if(i2b2.h.isMinObfuscation(thisRowColItem.trim()) + { thisRowColItem = 0; + } + if(i==0 && j==0) content += "<td class='descResults'> </td>"; else{ if(thisRowColItem==' '){ if(j == 0) thisRowIsHeader = true; if(thisRowIsHeader) content += "<td class='descResults descResultshead'> </td>"; else content += "<td class='descResults'> </td>"; } else{ if(thisRowIsHeader) content += "<td class='descResults descResultshead'>" + thisRowColItem + "</td>"; else content += "<td class='descResults'>" + thisRowColItem + "</td>"; } } } else{ if(j == 0) thisRowIsHeader = true; if(thisRowIsHeader) content += "<td class='descResults descResultshead'> </td>"; else content += "<td class='descResults'> </td>"; } } content += "</tr>"; } } content += "</table>"; jQuery('#tablesContainer').append(content); } this.getQueryUserFullName = function(query_user_id) { var returnValue = query_user_id; if(query_user_id) { try { var response = i2b2.PM.ajax.getUser("CRC:PrintQueryNew", {user_id:query_user_id}); response.parse(); var data = response.model[0]; if (data.full_name) { returnValue = data.full_name;} } catch (e) {} } return returnValue; }; function getSelectedValueFromOptions(options) { var value = null; for(k = 0; k < options.length; k++) { var thisOption = options[k]; if(thisOption.selected == true) { value = options[k].innerHTML; break; } } return value; }; this.PrintElem = function(divIdToPrint) { // Popup(jQuery("#" + divToPrint).html()); if(jQuery("#" + divIdToPrint)){ var contents = jQuery("#" + divIdToPrint).html(); var frame1 = jQuery("<iframe />"); frame1[0].name = "frame1"; frame1.css({ "position": "absolute", "top": "-1000000px" }); jQuery("body").append(frame1); var frameDoc = frame1[0].contentWindow ? frame1[0].contentWindow : frame1[0].contentDocument.document ? frame1[0].contentDocument.document : frame1[0].contentDocument; frameDoc.document.open(); //Create a new HTML document. frameDoc.document.write("<html><head><title>Query Report</title>"); //Append the external CSS file. frameDoc.document.write("<link rel=\"stylesheet\" href=\"js-i2b2/cells/CRC/assets/query_report.css\">"); frameDoc.document.write('<link href=\'js-ext/c3code/c3.css\' rel=\'stylesheet\' type=\'text/css\'></head><body>'); frameDoc.document.write("</head><body>"); //Append the DIV contents. frameDoc.document.write(contents); frameDoc.document.write('</body></html>'); frameDoc.document.close(); setTimeout(function () { window.frames["frame1"].focus(); window.frames["frame1"].print(); frame1.remove(); }, 500); } else alert("Query report can't be printed!"); }; /********************** * End Query Report BG **********************/ } console.timeEnd('execute time'); console.groupEnd(); diff --git a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_sdx_QI.js b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_sdx_QI.js index c7ba435c1..3c508a24a 100644 --- a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_sdx_QI.js +++ b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_sdx_QI.js @@ -1,747 +1,747 @@ /** * @projectDescription The SDX controller library for the QueryInstance data-type. * @namespace i2b2.sdx.TypeControllers.QI * @inherits i2b2.sdx.TypeControllers * @author Nick Benik, Griffin Weber MD PhD * @version 1.3 * @see i2b2.sdx * ---------------------------------------------------------------------------------------- * updated 9-15-08: RC4 launch [Nick Benik] */ console.group('Load & Execute component file: CRC > SDX > QueryInstance'); console.time('execute time'); i2b2.sdx.TypeControllers.QI = {}; i2b2.sdx.TypeControllers.QI.model = {}; // ********************************************************************************* // ENCAPSULATE DATA // ********************************************************************************* /** * Get the sdxInfo data template for all QueryMaster. * @memberOf i2b2.sdx.TypeControllers.QM * @method * @return {Object} Returns a data object containing sdxType, sdxKeyName, sdxControlCell info for QueryMaster-type objects. * @author Nick Benik * @version 1.0 * @alias i2b2.sdx.Master.EncapsulateData */ i2b2.sdx.TypeControllers.QI.getEncapsulateInfo = function() { // this function returns the encapsulation head information return {sdxType: 'QI', sdxKeyName: 'query_instance_id', sdxControlCell:'CRC', sdxDisplayNameKey:'title'}; } // ********************************************************************************* // GENERATE HTML (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.QI.RenderHTML= function(sdxData, options, targetDiv) { // OPTIONS: // title: string // showchildren: true | false // cssClass: string // icon: [data object] // icon: (filename of img, appended to i2b2_root+cellDir + '/assets') // iconExp: (filename of img, appended to i2b2_root+cellDir + '/assets') // dragdrop: string (function name) // context: string // click: string // dblclick: string if (Object.isUndefined(options)) { options = {}; } var render = {html: retHtml, htmlID: id}; var conceptId = sdxData.name; var id = "CRC_ID-" + i2b2.GUID(); // process drag drop controllers if (!Object.isUndefined(options.dragdrop)) { // NOTE TO SELF: should attachment of node dragdrop controller be handled by the SDX system as well? // This would ensure removal of the onmouseover call in a cross-browser way var sDD = ' onmouseover="' + options.dragdrop + '(\''+ targetDiv.id +'\',\'' + id + '\')" '; } else { var sDD = ''; } if (Object.isUndefined(options.cssClass)) { options.cssClass = 'sdxDefaultQI';} // user can override bCanExp = true; if (Object.isBoolean(options.showchildren)) { bCanExp = options.showchildren; } render.canExpand = bCanExp; render.iconType = "QI"; if (!Object.isUndefined(options.icon)) { render.icon = i2b2.hive.cfg.urlFramework + 'cells/CRC/assets/'+ options.icon } if (!Object.isUndefined(options.iconExp)) { render.iconExp = i2b2.hive.cfg.urlFramework + 'cells/CRC/assets/'+ options.iconExp } // in cases of one set icon, copy valid icon to the missing icon if (Object.isUndefined(render.icon) && !Object.isUndefined(render.iconExp)) { render.icon = sdxData.iconExp; } if (!Object.isUndefined(render.icon) && Object.isUndefined(render.iconExp)) { render.iconExp = sdxData.icon; } // handle the event controllers var sMainEvents = sDD; var sImgEvents = sDD; // **** Render the HTML *** var retHtml = '<DIV id="' + id + '" ' + sMainEvents + ' style="white-space:nowrap;cursor:pointer;">'; retHtml += '<DIV '; if (Object.isString(options.cssClass)) { retHtml += ' class="'+options.cssClass+'" '; } else { retHtml += ' class= "sdxDefaultQI" '; } retHtml += sImgEvents; retHtml += '>'; retHtml += '<IMG src="'+render.icon+'"/> '; if (!Object.isUndefined(options.title)) { retHtml += options.title; } else { console.warn('[SDX RenderHTML] no title was given in the creation options for an CRC>QI node!'); retHtml += ' QI '+id; } retHtml += '</DIV></DIV>'; render.html = retHtml; render.htmlID = id; var retObj = {}; Object.extend(retObj, sdxData); retObj.renderData = render; return retObj; } // ********************************************************************************* // HANDLE HOVER OVER TARGET ENTRY (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.QI.onHoverOver = function(e, id, ddProxy) { var el = $(id); if (el) { Element.addClassName(el,'ddQITarget'); } } // ********************************************************************************* // HANDLE HOVER OVER TARGET EXIT (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.QI.onHoverOut = function(e, id, ddProxy) { var el = $(id); if (el) { Element.removeClassName(el,'ddQITarget'); } } // ********************************************************************************* // ADD DATA TO TREENODE (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.QI.AppendTreeNode = function(yuiTree, yuiRootNode, sdxDataPack, callbackLoader) { var myobj = { html: sdxDataPack.renderData.html, nodeid: sdxDataPack.renderData.htmlID} var tmpNode = new YAHOO.widget.HTMLNode(myobj, yuiRootNode, false, true); if (sdxDataPack.renderData.canExpand && !Object.isUndefined(callbackLoader)) { // add the callback to load child nodes sdxDataPack.sdxInfo.sdxLoadChildren = callbackLoader; } tmpNode.data.i2b2_SDX= sdxDataPack; tmpNode.toggle = function() { if (!this.tree.locked && ( this.hasChildren(true) ) ) { var data = this.data.i2b2_SDX.renderData; var img = this.getContentEl(); img = Element.select(img,'img')[0]; if (this.expanded) { img.src = data.icon; this.collapse(); } else { img.src = data.iconExp; this.expand(); } } }; if (!sdxDataPack.renderData.canExpand) { tmpNode.dynamicLoadComplete = true; } return tmpNode; } /** * Get the child records for the given QueryInstance. * @param {Object} sdxParentNode The parent node we want to find the children of. * @param {ScopedCallback} onCompleteCallback A scoped-callback function to be executed using the results array. * @return {Boolean} Returns true to the calling function. * @return {Array} Returns an array of QueryInstance data represented as SDX Objects (without render data) to the callback function passed. * @memberOf i2b2.sdx.TypeControllers.QI * @method * @author Nick Benik * @version 1.0 * @alias i2b2.sdx.Master.getChildRecords */ i2b2.sdx.TypeControllers.QI.getChildRecords = function(sdxParentNode, onCompleteCallback, options) { var scopedCallback = new i2b2_scopedCallback(); scopedCallback.scope = sdxParentNode; scopedCallback.callback = function(results) { var cl_node = sdxParentNode; var cl_onCompleteCB = onCompleteCallback; // THIS function is used to process the AJAX results of the getChild call // results data object contains the following attributes: // refXML: xmlDomObject <--- for data processing // msgRequest: xml (string) // msgResponse: xml (string) // error: boolean // errorStatus: string [only with error=true] // errorMsg: string [only with error=true] var retMsg = { error: results.error, msgRequest: results.msgRequest, msgResponse: results.msgResponse, msgUrl: results.msgUrl, results: null }; var retChildren = []; // find parent node QI node in data model var dm = i2b2.CRC.model.QueryMasters; var dm_loc = 'i2b2.CRC.model.QueryMasters'; // Here comes REAL fun, a self-recursive anonymous function instantiated by iteration // via recursive "collection" calls on Hash objects (Prototype toolkit) var findFunc = function(item_rec) { var hash_key = item_rec.key; var gen_rec = item_rec.value; var cl_keyValue = keyValue; // <-- closure variable: keyValue must be set before running function if (gen_rec.sdxInfo.sdxType=="QI") { // see if this record matches our search if (gen_rec.sdxInfo.sdxKeyValue == cl_keyValue) { return gen_rec; } } else { // recurse into the object's children var match_children = gen_rec.children.collect(findFunc); return match_children; } } var keyValue = cl_node.sdxInfo.sdxKeyValue.toString(); var parent_QM = dm.collect(findFunc); parent_QM = parent_QM.flatten(); parent_QM = parent_QM.compact(); if (parent_QM[0]) { var pn = parent_QM[0]; } else { console.error('Parent QM node was not found in the CRC data model!'); return false; } // extract records from XML msg var ps = results.refXML.getElementsByTagName('query_result_instance'); var dm = i2b2.CRC.model.QueryMasters; var x_plusmn_pats = 3; for(var i1=0; i1<ps.length; i1++) { var o = new Object; o.xmlOrig = ps[i1]; o.QI_id = pn.sdxInfo.sdxKeyValue; o.QM_id = pn.parent.sdxInfo.sdxKeyValue; o.size = i2b2.h.getXNodeVal(ps[i1],'set_size'); o.start_date = i2b2.h.getXNodeVal(ps[i1],'start_date'); o.end_date = i2b2.h.getXNodeVal(ps[i1],'end_date'); o.description = i2b2.h.getXNodeVal(ps[i1],'description'); o.qs_name = i2b2.h.getXNodeVal(ps[i1],'query_status_type/name'); //try{ o.result_type = i2b2.h.getXNodeVal(ps[i1],'query_result_type/name'); //o.result_type = i2b2.h.XPath(ps[i1],'query_result_type/name/text()')[0].nodeValue; //} //catch(e){ if(typeof o.result_type == 'undefined'){ try{ o.result_type = "SHRINE_ERROR" ; o.qs_name = i2b2.h.getXNodeVal(ps[i1],'query_status_type/name'); o.description = i2b2.h.getXNodeVal(ps[i1],'description'); o.qs_description = i2b2.h.getXNodeVal(ps[i1],'query_status_type/description'); } catch(e){ o.result_type = "OTH_ERROR" ; } } //} var sdxDataNodeChild = null; //Added for previous query issue -> oRecord should be o object oRecord = o; var title = null; //If Query status = PROCESSING skip printing results if(o.qs_name == "PROCESSING"){ var t = o.description; if (!t) { t="Unknown"; } var d = new Date().getTime(); o.result_instance_id = d; title = t+" - Still Processing Request"; o.titleCRC = title; o.title = pn.parent.sdxInfo.sdxDisplayName + ' [PATIENT_COUNT_XML_'+ d +']'; //o.title = 'PATIENT_COUNT_XML_'+o.PRC_id; sdxDataNodeChild = i2b2.sdx.Master.EncapsulateData('PRC',o); } //All other Query Status else{ switch (o.result_type) { case "PATIENTSET": o.PRS_id = i2b2.h.getXNodeVal(ps[i1],'result_instance_id'); // use given title if it exist otherwise generate a title try { var t = o.description; if((t != null) && (t == "AGGREGATED") ){ x_plusmn_pats = ((ps.length) - 1) * 3; } } catch(e) { var t = null; } if (!t) { t="Patient Set"; } // create the title using shrine setting if (oRecord.size >= 10) { if (i2b2.PM.model.userRoles.lastIndexOf("DATA_AGG") > -1) { title = t+" - "+oRecord.size+" patients"; } else { title = t+" - "+oRecord.size+" ±"+ x_plusmn_pats + " patients"; } } else { if (i2b2.PM.model.userRoles.lastIndexOf("DATA_AGG") > -1) { title = t+" - "+oRecord.size+" patients"; } else { - title = t+" - 10 patients or fewer"; + title = t + " - " + i2b2.h.getMinResultText(); } } o.titleCRC = title; o.title = pn.parent.sdxInfo.sdxDisplayName + ' [PATIENTSET_'+o.PRS_id+']'; o.result_instance_id = o.PRS_id; sdxDataNodeChild = i2b2.sdx.Master.EncapsulateData('PRS',o); break; case "PATIENT_COUNT_XML": o.PRC_id = i2b2.h.getXNodeVal(ps[i1],'result_instance_id'); // use given title if it exist otherwise generate a title try { var t = o.description; if((t != null) && (t == "AGGREGATED") ){ x_plusmn_pats = ((ps.length) - 1) * 3; } } catch(e) { var t = null; } if (!t) { t="Patient Count"; } // create the title using shrine setting if (oRecord.size >= 10) { //@pcori_webclient if (i2b2.PM.model.userRoles.lastIndexOf("DATA_AGG") > -1) { title = t+" - "+oRecord.size+" patients"; } else { title = t+" - "+oRecord.size+" ±"+ x_plusmn_pats + " patients"; } } else { if (i2b2.PM.model.userRoles.lastIndexOf("DATA_AGG") > -1) { title = t+" - "+oRecord.size+" patients"; } else { - title = t+" - 10 patients or fewer"; + title = t + " - " + i2b2.h.getMinResultText(); } } o.titleCRC = title; o.title = pn.parent.sdxInfo.sdxDisplayName + ' [PATIENT_COUNT_XML_'+o.PRC_id+']'; //o.title = 'PATIENT_COUNT_XML_'+o.PRC_id; o.result_instance_id = o.PRC_id; sdxDataNodeChild = i2b2.sdx.Master.EncapsulateData('PRC',o); break; case "SHRINE_ERROR": try{ if(o.qs_name == "UNAVALIABLE"){ title = o.description +" - "+ o.qs_description; } else{ title = o.description +" - "+ o.qs_description; } } catch(e){ title = o.description +" - "+ e.message; } var d = new Date().getTime(); o.titleCRC = title; o.result_instance_id = d; o.title = pn.parent.sdxInfo.sdxDisplayName + ' [PATIENT_COUNT_XML_'+ d +']'; //o.title = 'PATIENT_COUNT_XML_'+o.PRC_id; //o.result_instance_id = o.PRC_id; sdxDataNodeChild = i2b2.sdx.Master.EncapsulateData('PRC',o); break; } } // save record in the SDX system sdxDataNode = i2b2.sdx.Master.Save(sdxDataNodeChild, pn); // append the data node to our returned results retChildren.push(sdxDataNode); } pn.children.loaded = true; // TODO: broadcast a data update event of the CRC data model retMsg.results = retChildren; if (getObjectClass(cl_onCompleteCB)=='i2b2_scopedCallback') { cl_onCompleteCB.callback.call(cl_onCompleteCB.scope, retMsg); } else { cl_onCompleteCB(retMsg); } } i2b2.CRC.ajax.getQueryResultInstanceList_fromQueryInstanceId("CRC:SDX:QueryInstance", {qi_key_value: sdxParentNode.sdxInfo.sdxKeyValue}, scopedCallback); } i2b2.sdx.TypeControllers.QI.SaveToDataModel = function(sdxData, sdxParentNode) { // save to CRC data model if (!sdxParentNode) { return false; } var qm_id = sdxData.sdxInfo.sdxKeyValue; var qm_hash = i2b2.sdx.Master._KeyHash(qm_id); // class for all SDX communications function i2b2_SDX_Encapsulation_EXTENDED() {} // create an instance and populate with info var t = new i2b2_SDX_Encapsulation_EXTENDED(); t.origData = Object.clone(sdxData.origData); t.sdxInfo = Object.clone(sdxData.sdxInfo); t.parent = sdxParentNode; t.children = new Hash(); t.children.loaded = false; // add to hash sdxParentNode.children.set(qm_hash, t); // TODO: send data update signal (use JOINING-MUTEX or AGGREGATING-MUTEX to avoid rapid fire of event!) return t; } i2b2.sdx.TypeControllers.QI.LoadFromDataModel = function(key_value) {} i2b2.sdx.TypeControllers.QI.ClearAllFromDataModel= function(sdxOptionalParent) { if (sdxOptionalParent) { try { var findFunc = function(item_rec) { // this function expects the second argument to be the target node's key value var hash_key = item_rec[0]; var QM_rec = item_rec[1]; if (QM_rec.sdxInfo.sdxKeyValue == this.strip()) { return true; } } var dm_loc = 'i2b2.CRC.model.QueryMasters.'+i2b2.sdx.Master._KeyHash(sdxOptionalParent.sdxInfo.sdxKeyValue); var targets = i2b2.CRC.model.QueryMasters.findAll(findFunc, sdxOptionalParent.sdxInfo.sdxKeyValue); for (var i=0; i < targets.length; i++) { var t = parent_QM[i].value; t.children = new Hash(); } } catch(e) { console.error('Could not clear children of given parent node!'); } } else { var dm_loc = 'i2b2.CRC.model.QueryMasters'; i2b2.CRC.model.QueryMasters.each(function(item_rec) { try { item_rec[1].children = new Hash(); } catch(e) { console.error('Could not clear children of all QueryMasters'); } }); } // TODO: send data update signal (use JOINING-MUTEX or AGGREGATING-MUTEX to avoid rapid fire of event!) // updated dm_loc of the data model return true; } i2b2.sdx.TypeControllers.QI.LoadChildrenFromTreeview = function(node, onCompleteCallback) { var scopedCallback = new i2b2_scopedCallback(); scopedCallback.scope = node.data.i2b2_SDX; scopedCallback.callback = function(retCellPack) { var cl_node = node; var cl_onCompleteCB = onCompleteCallback; var results = retCellPack.results; for(var i1=0; i1<1*results.length; i1++) { var o = results[i1]; // add visual element switch (o.sdxInfo.sdxType) { case "PRS": // patient record set // add visual element if (i2b2.PM.model.userRoles.indexOf("DATA_LDS") == -1) { var renderOptions = { dragdrop: "i2b2.sdx.TypeControllers.PRS.AttachDrag2Data", icon: "sdx_CRC_PRS.jpg", title: o.origData.titleCRC, showchildren: false }; } else { var renderOptions = { dragdrop: "i2b2.sdx.TypeControllers.PRS.AttachDrag2Data", icon: "sdx_CRC_PRS.jpg", title: o.origData.titleCRC, showchildren: true }; } break; case "ENS": // encounter record set // add visual element if (i2b2.PM.model.userRoles.indexOf("DATA_LDS") == -1) { var renderOptions = { dragdrop: "i2b2.sdx.TypeControllers.ENS.AttachDrag2Data", icon: "sdx_CRC_PRS.jpg", title: o.origData.titleCRC, showchildren: false }; } else { var renderOptions = { dragdrop: "i2b2.sdx.TypeControllers.ENS.AttachDrag2Data", icon: "sdx_CRC_PRS.jpg", title: o.origData.titleCRC, showchildren: true }; } break; case "PRC": // patient record count var renderOptions = { dragdrop: "i2b2.sdx.TypeControllers.PRC.AttachDrag2Data", icon: "sdx_CRC_PRC.jpg", title: o.origData.titleCRC, showchildren: false }; break; } var sdxRenderData = i2b2.sdx.Master.RenderHTML(cl_node.tree.id, o, renderOptions); i2b2.sdx.Master.AppendTreeNode(cl_node.tree, cl_node, sdxRenderData); } // handle the callback if (getObjectClass(cl_onCompleteCB)=='i2b2_scopedCallback') { cl_onCompleteCB.callback.call(cl_onCompleteCB.scope, retCellPack); } else { cl_onCompleteCB(retCellPack); } } var sdxParentNode = node.data.i2b2_SDX; var options = i2b2.CRC.params; i2b2.sdx.Master.getChildRecords(sdxParentNode, scopedCallback, options); } // ********************************************************************************* // ATTACH DRAG TO DATA (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.QI.AttachDrag2Data = function(divParentID, divDataID){ if (Object.isUndefined($(divDataID))) { return false; } // get the i2b2 data from the yuiTree node var tvTree = YAHOO.widget.TreeView.getTree(divParentID); var tvNode = tvTree.getNodeByProperty('nodeid', divDataID); if (!Object.isUndefined(tvNode.DDProxy)) { return true; } // attach DD var t = new i2b2.sdx.TypeControllers.QI.DragDrop(divDataID); t.yuiTree = tvTree; t.yuiTreeNode = tvNode; tvNode.DDProxy = t; // clear the mouseover attachment function var tdn = $(divDataID); if (!Object.isUndefined(tdn.onmouseover)) { try { delete tdn.onmouseover; } catch(e) { tdn.onmouseover; } } if (!Object.isUndefined(tdn.attributes)) { for (var i=0;i<tdn.attributes.length; i++) { if (tdn.attributes[i].name=="onmouseover") { try { delete tdn.onmouseover; } catch(e) { tdn.onmouseover; } } } } } // ********************************************************************************* // DRAG DROP PROXY CONTROLLER // ********************************************************************************* i2b2.sdx.TypeControllers.QI.DragDrop = function(id, config) { if (id) { this.init(id, 'QI',{isTarget:false}); this.initFrame(); } var s = this.getDragEl().style; s.borderColor = "transparent"; s.opacity = 0.75; s.filter = "alpha(opacity=75)"; s.whiteSpace = "nowrap"; s.overflow = "hidden"; s.textOverflow = "ellipsis"; // add this QM to other DragDrop groups (for translation functionality) this.addToGroup("PRS"); }; YAHOO.extend(i2b2.sdx.TypeControllers.QI.DragDrop, YAHOO.util.DDProxy); i2b2.sdx.TypeControllers.QI.DragDrop.prototype.startDrag = function(x, y) { var dragEl = this.getDragEl(); var clickEl = this.getEl(); dragEl.innerHTML = clickEl.innerHTML; dragEl.className = clickEl.className; dragEl.style.backgroundColor = '#FFFFEE'; dragEl.style.color = clickEl.style.color; dragEl.style.border = "1px solid blue"; dragEl.style.width = "160px"; dragEl.style.height = "20px"; this.setDelta(15,10); }; i2b2.sdx.TypeControllers.QI.DragDrop.prototype.endDrag = function(e) { // remove DragDrop targeting CCS var targets = YAHOO.util.DDM.getRelated(this, true); for (var i=0; i<targets.length; i++) { var targetEl = targets[i]._domRef; try { var ddCtrlr = YAHOO.util.DragDropMgr.getDDById(targetEl.id); if(ddCtrlr.groups['QI']) { i2b2.sdx.Master.onHoverOut('QI', e, targetEl, this); } } catch(e) {} } }; i2b2.sdx.TypeControllers.QI.DragDrop.prototype.alignElWithMouse = function(el, iPageX, iPageY) { var oCoord = this.getTargetCoord(iPageX, iPageY); if (!this.deltaSetXY) { var aCoord = [oCoord.x, oCoord.y]; YAHOO.util.Dom.setXY(el, aCoord); var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); var newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ]; } else { var posX = (oCoord.x + this.deltaSetXY[0]); var posY = (oCoord.y + this.deltaSetXY[1]); var scrSize = document.viewport.getDimensions(); var maxX = parseInt(scrSize.width-25-160); var maxY = parseInt(scrSize.height-25); if (posX > maxX) {posX = maxX;} if (posX < 6) {posX = 6;} if (posY > maxY) {posY = maxY;} if (posY < 6) {posY = 6;} YAHOO.util.Dom.setStyle(el, "left", posX + "px"); YAHOO.util.Dom.setStyle(el, "top", posY + "px"); } this.cachePosition(oCoord.x, oCoord.y); this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); }; i2b2.sdx.TypeControllers.QI.DragDrop.prototype.onDragOver = function(e, id) { // check to see if on-the-fly object type translation is needed var translateTo = false; if (Object.isUndefined(this.DDM.dragOvers[id])) { return false; } // we must save which target we are over for the DragOut event later this.lastDragOver = this.DDM.dragOvers[id]; var t = this.DDM.dragOvers[id].groups; if (!t['QI']) { // TRANSLATION NEEDED! if (t['PRS']) { translateTo = "PRS"; } } else { var translateTo = "QI"; } // fire the onHoverOver (use SDX so targets can override default event handler) if (translateTo) { i2b2.sdx.Master.onHoverOver(translateTo, e, id, this); } }; i2b2.sdx.TypeControllers.QI.DragDrop.prototype.onDragOut = function(e, id) { // fire the onHoverOut handler (use SDX so targets can override default event handlers) // check to see if on-the-fly object type translation is needed var translateTo = false; if (Object.isUndefined(this.lastDragOver)) { return false; } var t = this.lastDragOver.groups; if (!t['QI']) { // TRANSLATION NEEDED! if (t['PRS']) { translateTo = "PRS"; } } else { var translateTo = "QI"; } // fire the onHoverOver (use SDX so targets can override default event handler) if (translateTo) { i2b2.sdx.Master.onHoverOut(translateTo, e, id, this); } }; i2b2.sdx.TypeControllers.QI.DragDrop.prototype.onDragDrop = function(e, id) { // check to see if on-the-fly object type translation is needed var translateTo = false; if (Object.isUndefined(this.lastDragOver)) { return false; } var t = this.lastDragOver.groups; if (!t['QI']) { // TRANSLATION NEEDED! if (t['PRS']) { translateTo = "PRS"; } } else { var translateTo = "QI"; } // fire the onHoverOver (use SDX so targets can override default event handler) if (translateTo) { i2b2.sdx.Master.onHoverOut(translateTo, e, id, this); // retreive the concept data from the dragged element // PERFROM on-the-fly OBJECT TRANSLATION HERE!! var draggedData; switch (translateTo) { case "QI": // no translation needed var draggedData = this.yuiTreeNode.data.i2b2_SDX; // send no so translated info to the drop target handler i2b2.sdx.Master.ProcessDrop(draggedData, id); break; case "PRS": var draggedData = this.yuiTreeNode.data.i2b2_SDX; if (draggedData.children.size() == 0) { // a little explaination about the below code: loading/expanding the // treeview recursively via asynchronous calls i2b2.sdx.Master.LoadChildrenFromTreeview(this.yuiTreeNode, (function(){ var cl_tn1 = this.yuiTreeNode; var cl_id1 = id; cl_tn1.dynamicLoadComplete = true; cl_tn1.expand(); for (var i1=0; i1<cl_tn1.children.length; i1++) { var draggedData = cl_tn1.children[i1].data.i2b2_SDX; // send translated info to the drop target handler i2b2.sdx.Master.ProcessDrop(draggedData, cl_id2); } })); } else { // dump PRS hash as an array of SDX objects i2b2.sdx.Master.ProcessDrop(draggedData.children.values(), id); } break; } } }; // ********************************************************************************* // <BLANK> DROP HANDLER // !!!! DO NOT EDIT - ATTACH YOUR OWN CUSTOM ROUTINE USING // !!!! THE i2b2.sdx.Master.setHandlerCustom FUNCTION // ********************************************************************************* i2b2.sdx.TypeControllers.QI.DropHandler = function(sdxData) { alert('[QueryInstance DROPPED] You need to create your own custom drop event handler.'); } console.timeEnd('execute time'); console.groupEnd(); diff --git a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_view_DownloadData.js b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_view_DownloadData.js index 8ad86d037..883db6cc9 100644 --- a/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_view_DownloadData.js +++ b/shrine-webclient/src/main/html/js-i2b2/cells/CRC/CRC_view_DownloadData.js @@ -1,414 +1,416 @@ /** * @projectDescription View controller for the download data window (which is a GUI-only component of the CRC module). * @inherits i2b2.CRC.view * @namespace i2b2.CRC.view.DownloadData * @author Bhaswati Ghosh * @version 1.3 * ---------------------------------------------------------------------------------------- */ console.group('Load & Execute component file: CRC > view > DownloadData'); console.time('execute time'); // create and save the screen objects i2b2.CRC.view.downloadData = new i2b2Base_cellViewController(i2b2.CRC, 'downloadData'); i2b2.CRC.view.downloadData.visible = false; i2b2.CRC.view.downloadData.show = function() { i2b2.CRC.view.downloadData.visible = true; $('crcDownloadDataBox').show(); } i2b2.CRC.view.downloadData.hide = function() { i2b2.CRC.view.downloadData.visible = false; $('crcDownloadDataBox').hide(); } i2b2.CRC.view.downloadData.hideDisplay = function() { $('infoDownloadStatusData').hide(); } i2b2.CRC.view.downloadData.showDisplay = function() { var targs = $('infoDownloadStatusData').parentNode.parentNode.select('DIV.tabBox.active'); // remove all active tabs targs.each(function(el) { el.removeClassName('active'); }); // set us as active $('infoDownloadStatusData').parentNode.parentNode.select('DIV.tabBox.tabDownloadData')[0].addClassName('active'); $('infoQueryStatusText').hide(); $('infoQueryStatusChart').hide(); $('infoQueryStatusReport').hide(); $('infoDownloadStatusData').show(); var output = ""; if(typeof i2b2.CRC.view.downloadData.active_qm_id === 'undefined'){ } else { output = "<div style=\"padding:15px;text-align:center;font-size:16px;\"><img src=\"js-i2b2/cells/plugins/biobankportal/BiobankDatafile/assets/csv_icon.png\" align=\"absmiddle\"/> You can download the de-identified data for this query as an Excel/CSV file. "; output += "<input onclick=\"loadDownloadData();i2b2.BiobankDatafile.queryAutoDropped(i2b2.CRC.view.downloadData.active_qm_id);\" type=\"button\" class=\"BiobankDatafile-button\" value=\"Proceed to the Download\">"; output += "</div>"; } $('infoDownloadStatusData').innerHTML = output; } i2b2.CRC.view.downloadData.createCSV = function() { var formattedResObj = i2b2.CRC.ctrlr.currentQueryResults; var resString = formattedResObj.resultString; if(resString && resString.length>0) { var asInputFragments = i2b2.CRC.view.graphs.parseInputIntoArray(resString,true); i2b2.CRC.view.downloadData.getFormattedResults(asInputFragments); i2b2.CRC.view.downloadData.getCSVFromResultsHash(); } } allSiteNamesHash = $H(); //This hash keeps all the facility names. finalOrderdSiteNamesHash = $H(); //In this hash we order the names of all facilities and assign them an index number resultsHash = $H(); //This hashtable keeps {'breakdown|category',{{'facility Name',{integer value,obfuscated value}}} pairs errorsHash = $H(); //This hastable keeps {facility name, error message} pairs for all sites that returns error finalResultsArray = new Array([]); // This is a 2-D array. Keeps data in tabular format where the columns are the sites and rows are the category of results.This array wiil be used to create the CSV table easily. breakdownHash = $H(); //This hashtable will keep al breakdown categories in lowercase letters. This will help resolve case sensitivity issues for same categories i2b2.CRC.view.downloadData.getFormattedResults = function(inpArray) { try{ //Clear all the hashtables allSiteNamesHash = $H(); resultsHash = $H(); errorsHash = $H(); breakdownHash = $H(); //Populate the facility names hash and results hash tables inpArray.each(function(item){ var qryName = item[0]; var brkDownCategoryOrError = item[1]; var facilityName = item[2]; var brkDownLabelorErrorMsg = item[3]; var brkDownValue = item[4]; var obfuscatedEntry = item[5]; var obfuscatedVal = item[5]; if(obfuscatedVal) { var tempObfuscated = obfuscatedEntry.split(" - "); if(tempObfuscated && tempObfuscated.length>1) obfuscatedVal = tempObfuscated[1]; } var errorEntry = false; if(brkDownCategoryOrError && brkDownCategoryOrError.indexOf("ERROR") > -1) errorEntry = true; if(brkDownCategoryOrError && brkDownCategoryOrError.indexOf("Still Processing Request") > -1) errorEntry = true; if(brkDownCategoryOrError && brkDownCategoryOrError.indexOf("Results not available") > -1) errorEntry = true; if(facilityName && qryName) allSiteNamesHash.set(facilityName.trim(),qryName.trim()); //Is this a result entry or error entry if(errorEntry) { if(facilityName && qryName) errorsHash.set(facilityName.trim(),brkDownLabelorErrorMsg.trim()); } else //this is a result entry { if(brkDownCategoryOrError && brkDownLabelorErrorMsg && obfuscatedVal) { var brkDownCategory = brkDownCategoryOrError.trim(); var brkDownLabel = brkDownLabelorErrorMsg.trim(); var keyId = brkDownCategory + "|" + brkDownLabel; if(resultsHash.get(keyId)) { var thisKeyDict = resultsHash.get(keyId); //Save this site entry in proper breakdown hash thisKeyDict.set(facilityName,{'integerValue' : brkDownValue, 'obfuscated':obfuscatedVal}); } else { //Create a dictionary for the site in the very first entry var thisKeyDict = $H(); //Create a dictionary for break down category for the very first site in input array var thisSiteDict = $H(); thisSiteDict.set(facilityName,{'integerValue' : brkDownValue, 'obfuscated':obfuscatedVal}); resultsHash.set(keyId,thisSiteDict); } } } }); //We have all our required data hashed. Now lets make a tabular format from it. var maxRowsNum = resultsHash.size(); var maxColsNum = allSiteNamesHash.size(); finalResultsArray = new Array(maxRowsNum+1); for (var i = 0; i <= maxRowsNum; i++) { finalResultsArray[i] = new Array(maxColsNum+1); } for(var i = 0 ; i<=maxRowsNum ; i++) { for(var j = 0 ;j<=maxColsNum; j++) { finalResultsArray[i][j]=' '; } } finalOrderdSiteNamesHash = $H(); var count = 1; allSiteNamesHash.keys().sort().each(function(orderedEntry) { finalOrderdSiteNamesHash.set(orderedEntry,count); count++; }); //Fill in the first row of the 2-D array with all site names in alphabetic order finalResultsArray[0][0]='Site names'; finalOrderdSiteNamesHash.each(function(entry) { var col = entry.value; var colEntry = entry.key; finalResultsArray[0][col]=colEntry; }); //Fill in the first column of the 2-D array with all the break down categories var i=0; var rowIndex = 0; var temporaryCatgryArr = new Array(maxRowsNum); resultsHash.keys().sort().each(function(breakdown){ try{ var patCountRow = false; var lowerCaseBrkDown = breakdown.toLowerCase(); //Resolving case issue for same breakdown fact if(breakdown.indexOf("Patient Count") > -1) patCountRow = true; if(!patCountRow) { if(!(breakdownHash.get(lowerCaseBrkDown))){ breakdownHash.set(lowerCaseBrkDown,rowIndex+2); rowIndex++; } } else { //Reserve the 2nd row for patient count data finalResultsArray[1][0] = breakdown; breakdownHash.set(lowerCaseBrkDown,1); } temporaryCatgryArr[i++] = breakdown; } catch(err1) { console.error("Error while sorting the breakdown categories : " + err1); } }); //Fill in the rest of data in the array for(var i = 0 ; i < temporaryCatgryArr.length ; i++) { try{ var breakdownCat = temporaryCatgryArr[i]; var lowerCaseBrkDown = breakdownCat.toLowerCase(); var rowIndex = breakdownHash.get(lowerCaseBrkDown); if(rowIndex){ var patCountRow = false; if(breakdownCat.indexOf("Patient Count") > -1) patCountRow = true; if(resultsHash.get(breakdownCat)) { var thisBrkDnHash = resultsHash.get(breakdownCat); if(patCountRow) //Fill in the 2nd row with patient count data finalResultsArray[1][0] = 'All Patients'; else finalResultsArray[rowIndex][0] = breakdownCat; thisBrkDnHash.each(function(item){ var siteName = item.key; var siteIndex = finalOrderdSiteNamesHash.get(siteName); var integerVal = item.value.integerValue; finalResultsArray[rowIndex][siteIndex] = integerVal; }); } else { var err = "Caltegory " + breakdown + " was not found in resullt hashtable"; console.error(err); } } } catch(err1) { console.error("Error while putting together the results table : " + err1); continue; } } return finalResultsArray; } catch(err) { console.error(err); return null; } }; i2b2.CRC.view.downloadData.getCSVFromResultsHash = function() { var numberOfSites = finalOrderdSiteNamesHash.size(); if(numberOfSites>0) { var maxRowsNum = breakdownHash.size()+1; var maxColNumber = numberOfSites+1; var content = "<img src=\"js-i2b2/cells/CRC/assets/csv.png\"/> <a href='#' onclick='javascript:i2b2.CRC.view.downloadData.exportTableToCSV();return false;'>Download CSV File</a><br/><br/><br/>"; content += "<table id='resultsTable'>"; content += "<tr>"+ //Beginning of Site names row "<th colspan=\"" + maxColNumber + "\">SHRINE QUERY RESULTS (OBFUSCATED PATIENT COUNTS)</th>"+ "</tr>"; for(var i = 0 ; i < maxRowsNum ; i++) { content += "<tr>"; for(var j = 0 ; j < maxColNumber ; j++) { var thisRowColItem = finalResultsArray[i][j]; if(thisRowColItem) { - if((thisRowColItem.trim().indexOf("10 patients or fewer"))>0) + if(i2b2.h.isMinObfuscation(thisRowColItem.trim()){ thisRowColItem = 0; + } + if(i==0 && j==0) content += "<td> </td>"; else{ if(thisRowColItem==' ') content += "<td> </td>"; else content += "<td>" + thisRowColItem + "</td>"; } } else content += "<td> </td>"; } content += "</tr>"; } content += "</table>"; jQuery('#infoDownloadStatusData').append(content); } else {} } i2b2.CRC.view.downloadData.exportTableToCSV = function () { var table = jQuery('#resultsTable'); var filename = 'export.csv'; var rows = table.find('tr:has(td)'); // Temporary delimiter characters unlikely to be typed by keyboard // This is to avoid accidentally splitting the actual contents var tmpColDelim = String.fromCharCode(11); // vertical tab character var tmpRowDelim = String.fromCharCode(0); // null character // actual delimiter characters for CSV format var colDelim = '","'; var rowDelim = '"\r\n"'; // Grab text from table into CSV formatted string var csv = '"' + jQuery(rows).map(function (i, row) { var row = jQuery(row), cols = row.find('td'); return jQuery(cols).map(function (j, col) { var col = jQuery(col), text = col.text(); if(i==0 && j==0) text = "SHRINE QUERY RESULTS (OBFUSCATED PATIENT COUNTS)"; else { if(elementIsEmpty(col)) text = ""; } text = text.replace(/"/g, '""'); // escape double quotes return text.replace(/,/g, '",'); // escape comma inside a field }).get().join(tmpColDelim); }).get().join(tmpRowDelim) .split(tmpRowDelim).join(rowDelim) .split(tmpColDelim).join(colDelim) + '"'; // Check Browser var ua = window.navigator.userAgent; var msie = ua.indexOf("MSIE "); var trident = ua.indexOf('Trident/'); var edge = ua.indexOf('Edge/'); var browserIsIE = false; if (msie > 0) { // IE 10 or older browserIsIE = true; } else if (trident > 0) { // IE 11 browserIsIE = true; } else if (edge > 0) { // Edge browserIsIE = true; } else browserIsIE = false; if(browserIsIE) { if (window.navigator.msSaveOrOpenBlob) { // IE 10+ // var fileData = ['\ufeff'+csv]; // blobObject = new Blob(fileData); var blobObject = new Blob([decodeURIComponent(encodeURI(csv))], { type: "text/csv;charset=utf-8;" }); navigator.msSaveOrOpenBlob(blobObject, filename); return false; } else { var IEwindow = window.open(); IEwindow.document.write('sep=,\r\n' + csv); IEwindow.document.close(); var success = IEwindow.document.execCommand('SaveAs', true, filename); IEwindow.close(); if (!success) alert("Sorry, your browser does not support this feature"); } } else { var mylink = document.createElement('a'); var csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv); mylink.download = filename; mylink.href = csvData; document.body.appendChild(mylink); mylink.click(); } } function elementIsEmpty(td) { if (td.text == '' || td.text() == ' ' || td.html() == ' ' || td.is(":not(:visible)")) { return true; } return false; } // ================================================================================================== // console.timeEnd('execute time'); console.groupEnd(); \ No newline at end of file diff --git a/shrine-webclient/src/main/html/js-i2b2/hive/hive_helpers.js b/shrine-webclient/src/main/html/js-i2b2/hive/hive_helpers.js index df9acbe50..a8731e7b3 100644 --- a/shrine-webclient/src/main/html/js-i2b2/hive/hive_helpers.js +++ b/shrine-webclient/src/main/html/js-i2b2/hive/hive_helpers.js @@ -1,807 +1,853 @@ /** * @projectDescription Various helper functions used by the i2b2 framework and cells. * @inherits i2b2 * @namespace i2b2 * @author Nick Benik, Griffin Weber MD PhD * @version 1.3 * ---------------------------------------------------------------------------------------- * updated 9-15-08: RC4 launch [Nick Benik] */ console.group('Load & Execute component file: hive > helpers'); console.time('execute time'); if (Object.isUndefined(i2b2.h)) i2b2.h = {}; // ================================================================================================== // // Hack PrototypeJS to accept multiple parameters for its Object.isUndefined function call // (utilize a closure to store a protected reference to prototype's original Object.isUndefined object) i2b2.protoObjhack = (function() { var origFunction = Object.isUndefined; var newFunction = function(){ for(var i=0; i<arguments.length; i++) { if (origFunction(arguments[i])) { return true; } } return false; }; return newFunction; }); Object.isUndefined = i2b2.protoObjhack(); delete i2b2.protoObjhack; // ================================================================================================== // i2b2.h.parseXml = function(xmlString){ var xmlDocRet = false; var isActiveXSupported = false; try { new ActiveXObject ("MSXML2.DOMDocument.6.0"); isActiveXSupported = true; } catch (e) { isActiveXSupported = false; } if (isActiveXSupported) { //Internet Explorer xmlDocRet = new ActiveXObject("Microsoft.XMLDOM"); xmlDocRet.async = "false"; xmlDocRet.loadXML(xmlString); xmlDocRet.setProperty("SelectionLanguage", "XPath"); } else { //Firefox, Mozilla, Opera, etc. parser = new DOMParser(); xmlDocRet = parser.parseFromString(xmlString, "text/xml"); } return xmlDocRet; }; i2b2.h.XPath = function(xmlDoc, xPath) { var retArray = []; if (!xmlDoc) { console.warn("An invalid XMLDoc was passed to i2b2.h.XPath"); return retArray; } try { if (window.ActiveXObject || "ActiveXObject" in window) { if((!!navigator.userAgent.match(/Trident.*rv\:11\./)) && (typeof xmlDoc.selectNodes == "undefined")) { // IE11 handling var doc = new ActiveXObject('Microsoft.XMLDOM'); doc.loadXML(new XMLSerializer().serializeToString(xmlDoc)); xmlDoc = doc; } // Microsoft's XPath implementation // HACK: setProperty attempts execution when placed in IF statements' test condition, forced to use try-catch try { xmlDoc.setProperty("SelectionLanguage", "XPath"); } catch(e) { try { xmlDoc.ownerDocument.setProperty("SelectionLanguage", "XPath"); } catch(e) {} } retArray = xmlDoc.selectNodes(xPath); } else if (document.implementation && document.implementation.createDocument) { // W3C XPath implementation (Internet standard) var ownerDoc = xmlDoc.ownerDocument; if (!ownerDoc) {ownerDoc = xmlDoc; } var nodes = ownerDoc.evaluate(xPath, xmlDoc, null, XPathResult.ANY_TYPE, null); var rec = nodes.iterateNext(); while (rec) { retArray.push(rec); rec = nodes.iterateNext(); } } } catch (e) { console.error("An error occurred while trying to perform XPath query."); console.dir(e); } return retArray; }; i2b2.h.getXNodeVal = function(xmlElement, nodeName, includeChildren) { var gotten = i2b2.h.XPath(xmlElement, "descendant-or-self::"+nodeName+"/text()"); var final = ""; if (gotten.length > 0) { if (includeChildren == true || includeChildren == true) { for (var i=0; i<gotten.length; i++) { final += gotten[i].nodeValue; } } else { final = gotten[0].nodeValue; } } else { final = undefined; } return final; } i2b2.h.GenerateAlphaNumId = function(ReqIdLength) { var IdLen = 0; var retId = ""; while (IdLen <= ReqIdLength) { IdLen++; switch(Math.floor(Math.random() * 3)) { case 0: // add a number retId += Math.floor(Math.random() * 10).toString(); break; case 1: // upper case letter retId += String.fromCharCode(Math.floor(Math.random() * 26)+65); break; case 2: // lower case letter retId += String.fromCharCode(Math.floor(Math.random() * 26)+97); break; } } return retId; }; i2b2.h.GenerateISO8601DateTime = function(inDate) { if (!inDate) { inDate = new Date(); } var year = inDate.getYear(); if (year < 2000) year = year + 1900; var month = inDate.getMonth() + 1; var day = inDate.getDate(); var hour = inDate.getHours(); var hourUTC = inDate.getUTCHours(); var diff = hour - hourUTC; var hourdifference = Math.abs(diff); var minute = inDate.getMinutes(); var minuteUTC = inDate.getUTCMinutes(); var minutedifference; var second = inDate.getSeconds(); var timezone; if (minute != minuteUTC && minuteUTC < 30 && diff < 0) { hourdifference--; } if (minute != minuteUTC && minuteUTC > 30 && diff > 0) { hourdifference--; } if (minute != minuteUTC) { minutedifference = ":30"; } else { minutedifference = ":00"; } if (hourdifference < 10) { timezone = "0" + hourdifference + minutedifference; } else { timezone = "" + hourdifference + minutedifference; } if (diff < 0) { timezone = "-" + timezone; } else { timezone = "+" + timezone; } if (month <= 9) month = "0" + month; if (day <= 9) day = "0" + day; if (hour <= 9) hour = "0" + hour; if (minute <= 9) minute = "0" + minute; if (second <= 9) second = "0" + second; return (year + "-" + month + "-" + day + "T" + hour + ":" + minute + ":" + second + timezone); }; i2b2.h.Escape = function(inStrValue) { if (typeof inStrValue == "number") { var t = inStrValue.toString(); } else { var t = new String(inStrValue); } t = t.replace(/&/g, "&"); t = t.replace(/</g, "<"); t = t.replace(/>/g, ">"); return t; }; i2b2.h.Unescape = function(inStrValue) { var t = new String(inStrValue); t = t.replace(/>/g, ">"); t = t.replace(/</g, "<"); t = t.replace(/&/g, "&"); return t; }; i2b2.h.EscapeTemplateVars = function(refTemplateVals, arryIgnoreVars) { for (var vname in refTemplateVals) { var ignore = false; for (var i=0; i<arryIgnoreVars.length; i++) { if (vname == arryIgnoreVars[i]) { ignore = true; break; } } if (!ignore) { // escaping value refTemplateVals[vname] = this.Escape(refTemplateVals[vname]); } } }; i2b2.h.LoadingMask = { show: function() { var sz = document.viewport.getDimensions(); var w = window.innerWidth || (window.document.documentElement.clientWidth || window.document.body.clientWidth); var h = window.innerHeight || (window.document.documentElement.clientHeight || window.document.body.clientHeight); if (w < 840) {w = 840;} if (h < 517) {h = 517;} var mn = $('topMask'); mn.style.width=w-10; mn.style.height=h-10; mn.innerHTML = "<TABLE height='100%' width='100%'><TR><TD align='center' valign='center'><BR/><H1><FONT size='12' color='white'>LOADING</FONT></H1></TD></TR></TABLE>"; mn.zindex = 50000; // mn.style.cursor = 'wait'; mn.show(); }, hide: function() { // hide the loading mask var mn = $('topMask'); mn.innerHTML=''; mn.hide(); } }; // created this object to allow the joining of forked execution paths (Waiting for Multiple AJAX calls) i2b2.h.JoiningMutex = { _contexts: {}, _contextGenID: 0, _createContextProxy: function(contextRef) { // create a proxy object (via closure) to encapsulate data // and route actions to the JoinMutex singleton var cl_JoinMutextRef = contextRef; function JoiningMutexContextProxy() { this._JoiningMutexContext = cl_JoinMutextRef; this._alreadyRun = false; this.name = function() { return this._JoiningMutexContext.name; }; this.openThreads = function() { return this._JoiningMutexContext.openThreads; }; this.executeOnce = function() { return this._JoiningMutexContext.executeOnce; }; this.executionCount = function() { return this._JoiningMutexContext.executionCount; }; this.isActive = function() { return this._JoiningMutexContext.active; }; this.ThreadFinished = function() { if (!this._JoiningMutexContext.active) { return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because the giving context is no longer active'}; } if (this._JoiningMutexContext._alreadyRun) { return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because the MutexProxy has already been run'}; } if (this._JoiningMutexContext.openThreads > 0) { this._JoiningMutexContext.openThreads--; this._alreadyRun = true; if (this._JoiningMutexContext.openThreads == 0) { // all threads finished if (this._JoiningMutexContext.executeOnce) { // this is going to be our only run of the callback function this._JoiningMutexContext.active = false; } this._JoiningMutexContext.executionCount++; this._JoiningMutexContext.callbackFinished(); return true; } else { // everything is OK but there are still outstanding threads to finish return false; } } else { return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because there are no outstanding thread executions'}; } }; } return new JoiningMutexContextProxy; }, contextCreate: function(sContextName, fZeroRunFunction, bSingleRun) { // make sure context is new var validName = sContextName; try { if (!validName) { this._contextGenID++; validName = "AUTOGEN-"+this._contextGenID; } if (this._contexts[validName]) { return {error: true, errorObj: undefined, errorMsg: 'JoiningMutex.contextCreate() failed because the giving context name already exists'}; } // verify that the name can be used as an object identifier (with throw an error if invalid) this._contexts[validName] = true; delete this._contexts[validName]; } catch(e) { return {error: true, errorObj: e, errorMsg: 'an error occurred within JoiningMutex.contextCreate()'}; } // create new context object function JoiningMutexContext(inName, inFinishFunction, inSingleExecution) { this.name = inName; this.callbackFinished = inFinishFunction; this.openThreads = 0; this.executeOnce = inSingleExecution; this.executionCount = 0; this.active = true; } var bSingleRun = Boolean.parseTo(bSingleRun); this._contexts[validName] = new JoiningMutexContext(validName, fZeroRunFunction, bSingleRun); // add ourselves to the thread count var cl_JoinMutextRef = this._contexts[validName]; cl_JoinMutextRef.openThreads++; return this._createContextProxy(cl_JoinMutextRef); }, contextJoin: function(sContextName) { // make sure context already exists var validName = sContextName; if (!this._contexts[validName]) { return {error: true, errorObj: undefined, errorMsg: 'JoiningMutex.contextCreate() failed because the context name does not exist'}; } var cl_JoinMutextRef = this._contexts[validName]; // Add this thread to the count cl_JoinMutextRef.openThreads++; return this._createContextProxy(cl_JoinMutextRef); }, contextJoinCreate: function(sContextName, fZeroRunFunction, bSingleRun) { // Join context or create it if it exists var ctx = false; if (!sContextName || !this._contexts[sContextName]) { ctx = this.contextCreate.call(this, sContextName, fZeroRunFunction, bSingleRun); } else { ctx = this.contextJoin.call(this, sContextName); } return ctx; }, contextDestroy: function(sContextName) { if (!sContextName || !this._contexts[sContextName]) { return false; } else { // Garbage collection will not execute until all // the JoiningMutexContextProxy are deleted so // invalidate the context as well as delete it! this._contexts[sContextName].active = false; this._contexts[sContextName].callbackFinished = function() { return null; }; delete this._contexts[sContextName]; return true; } } }; // this function will hide/show elements tagged with the "debug" classname i2b2.h.debugElements = function(rootElement) { var el = $(rootElement); if (!el) { return; } var tns = el.select('.debug'); var sflg = i2b2.h.inDebugMode(); for (var i=0; i<tns.length; i++) { if (sflg) { tns[i].show(); } else { tns[i].hide(); } } } i2b2.events.afterLogin.subscribe( (function(en,co,a) { // remove debugging functionality from GUI i2b2.h.debugElements(document.documentElement); // remove the analysis link if configuration tells us to if (!i2b2.h.allowAnalysis()) { $('allowAnalysis').hide(); } }) ); i2b2.h.isBadObjPath = function(sObjectHierarchy) { try { var t = eval("("+sObjectHierarchy+")"); return Object.isUndefined(t); } catch (e) { return true; } } // Extend JS Objects // ================================================================================================== // String.prototype.repeat = function(l){ return new Array(l+1).join(this); }; // ================================================================================================== // function padNumber(num, req_digits) { num = parseInt(num, 10)+""; var pad = req_digits - num.length; if (pad > 0 ) num = "0".repeat(pad)+num; return num; } // wrap YUI functions into the JS Object constructor to augment Protype-JS functions // ================================================================================================== // Object.isObject = function(testObj) { return YAHOO.lang.isObject(testObj); } Object.isNull = function(testObj) { return YAHOO.lang.isNull(testObj); } Object.isBoolean = function(testObj) { return YAHOO.lang.isBoolean(testObj); } Boolean.parseTo = function(inputValue) { if (typeof inputValue == "string") { return /\btrue/i.match(inputValue); } return (inputValue==true); } // This is a special closure-based function to return a unique ID every time called. // The closure counter gets wrapped into a private "bubble" within the JsVM that // is not accessable from other calls... Let the scope-chain bending begin! // ================================================================================================== // i2b2.GUID = (function() { var closure_Counter = 0 ; function closure_nextID() { var prevID = closure_Counter; closure_Counter++; if (prevID > closure_Counter) console.error("[i2b2.GUID function's internal counter encountered an overflow!!!]"); return closure_Counter; } return (function() { return closure_nextID(); }); })(); // Global helper functions // ================================================================================================== // function parseBoolean(inputStr) { return /\btrue/i.match(inputStr); } // function needed to perform processing // only on objects that match a specific type // ================================================================================================== // Object.getClass = getObjectClass; function getObjectClass(obj) { if (obj && obj.constructor && obj.constructor.toString) { var arr = obj.constructor.toString().match(/function\s*(\w+)/); if (arr && arr.length == 2) { return arr[1]; } } return undefined; } // Extend the YAHOO.widget.TreeView object // ================================================================================================== // YAHOO.widget.TreeView.findTreeByChildDiv = function(divChild) { var parentNode; var isDone = false; var tdiv = $(divChild); if (!tdiv) { return undefined; } do { if (tdiv.id) { var tree = this.getTree(tdiv.id); if (tree) { isDone = true; } } if (tdiv.parentNode) { tdiv = tdiv.parentNode; } else { isDone = true; } } while (!isDone) return tree; } YAHOO.widget.TreeView.getNode_orig = YAHOO.widget.TreeView.getNode; YAHOO.widget.TreeView.getNode = function(treeId, nodeIndex) { // This is an enhanced version which overrides the default function within the // YUI library, This is needed to handle HTML <-> data structure mismatches // which occurs because we are separating and redisplaying our Root nodes // in different treesview controller instances. This function falls back on // the original function calls which should prevent any problems with future versions var retNode = YAHOO.widget.TreeView.getNode_orig(treeId, nodeIndex); if (!retNode) { // start special processing to find our node in the list of other tree controllers for (var ntn in YAHOO.widget.TreeView.trees) { var nexttree = YAHOO.widget.TreeView.trees[ntn]; if (nexttree.toString) { var n = nexttree.toString(); var s = n.split(' ',2); if (s[0] == "TreeView") { retNode = YAHOO.widget.TreeView.getNode_orig(s[1], nodeIndex); if (retNode) { break; } } } } } return retNode; } // ================================================================================================== // YAHOO.widget.Node.prototype.refresh_orig = YAHOO.widget.Node.prototype.refresh; YAHOO.widget.Node.prototype.refresh = function() { // Intercept call to default node.refresh() and extend it to fire original call // then fire the YAHOO.util.DDM.reattachHandlers() function to reattach // drag & drop handlers that are used by the trees. var ret = this.refresh_orig.call(this); YAHOO.util.DDM.reattachHandlers(); console.warn("reattach DD handlers"); return ret; } // ================================================================================================== // YAHOO.widget.TreeView.attachRootNodeToTree = function(obRootNode, objTree) { if (obRootNode == objTree.root) return true; // this is our recursive set tree function var recursiveSetTree = function(oTree, oNode, recFunc) { if (oNode.tree) { oNode.tree = oTree; } try { for (var i=0; i<oNode.children.length; i++) { recFunc(oTree, oNode.children[i], recFunc); } } catch(e) {} } var recursiveTreePopulate = function(oTreeArrayNode, oNode, recFunc) { if (oNode.index) { oTreeArrayNode[oNode.index] = oNode; } try { for (var i=0; i<oNode.children.length; i++) { recFunc(oTreeArrayNode, oNode.children[i], recFunc); } } catch(e) {} } var recursiveApplyParent = function(oNode, recFunc) { try { for (var i=0; i<oNode.children.length; i++) { oNode.children[i].applyParent(oNode); recFunc(oNode.children[i], recFunc); } } catch(e) {} } objTree._nodes.clear(); // attach the new root node to the tree objTree.root = obRootNode; obRootNode.tree = objTree; for (var i=0; i<obRootNode.children.length; i++) { obRootNode.children[i].applyParent(obRootNode); } //recursiveSetTree(objTree, objTree.root, recursiveSetTree); recursiveTreePopulate(objTree._nodes, objTree.root, recursiveTreePopulate); // reattach the dynamic load event if it was lost objTree.setDynamicLoad(i2b2.CRC.ctrlr.QT._loadTreeDataForNode,1); return true; } YAHOO.widget.Node.prototype.isDescendant = function(srchNode) { // is the current node a descendant of srchNode? Used to prevent parents being dragged into its child nodes. var thisNode = this; if (!srchNode) { return undefined; } while (thisNode.parent) { if (thisNode == srchNode) { return true; } thisNode = thisNode.parent; } return false; } // this function is a very clever hack to reattach all YUI drag & drop handlers which have // gotten detached and have (newer copies of) their elements in the visible DOM tree YAHOO.util.DDM.reattachHandlers = function() { for (var grps in YAHOO.util.DDM.ids) { // interaction groups for (var el in YAHOO.util.DDM.ids[grps]) { try { var t = YAHOO.util.DDM.ids[grps][el]; // copy the info var ddId = t.id; var ddGrps = Object.clone(t.groups); var ddCfg = Object.clone(t.config); var ddTargeted = t.isTarget; var fEl = $(el); if (!fEl) { if (t.available) { // remove DD for non-existent HTML elements and // only after the DD has been initialized t._domRef = null; t.unreg(); } } else { // reattach if (t._domRef != fEl) { t._domRef = fEl; t.init(ddId); t.groups = Object.clone(ddGrps); t.isTarget = ddTargeted; } } } catch(e) { console.warn("Error while reattaching DD handlers: "+e.message); } } } } // ================================================================================================== // // Patch a bug in the YUI overlay subsystem which ignores/destroys zIndex parameter given // to modal forms during initial creation. TODO: REMOVE THIS WHEN YAHOO FIXES THIS BUG! i2b2.bugfix1 = function () {}; i2b2.bugfix1.prototype.bringToTop = function() { var Dom = YAHOO.util.Dom; var Overlay = YAHOO.widget.Overlay; var Lang = YAHOO.lang; var aOverlays = [], oElement = this.element; function compareZIndexDesc(p_oOverlay1, p_oOverlay2) { var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"), sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"), nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10), nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10); if (nZIndex1 > nZIndex2) { return -1; } else if (nZIndex1 < nZIndex2) { return 1; } else { return 0; } } function isOverlayElement(p_oElement) { var oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY), Panel = YAHOO.widget.Panel; if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) { if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) { aOverlays[aOverlays.length] = p_oElement.parentNode; } else { aOverlays[aOverlays.length] = p_oElement; } } } Dom.getElementsBy(isOverlayElement, "DIV", document.body); aOverlays.sort(compareZIndexDesc); var oTopOverlay = aOverlays[0], nTopZIndex; if (oTopOverlay) { nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex"); if (!isNaN(nTopZIndex)) { var bRequiresBump = false; if (oTopOverlay != oElement) { bRequiresBump = true; } else if (aOverlays.length > 1) { var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex"); // Don't rely on DOM order to stack if 2 overlays are at the same zindex. if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) { bRequiresBump = true; } } // <PATCH: make sure the zIndex is >= any zIndex given in the initial creation settings> if (!Lang.isUndefined(this.cfg.config.zindex)) { if (parseInt(this.cfg.config.zindex.value, 10) >= parseInt(nTopZIndex,10)) { nTopZIndex = this.cfg.config.zindex.value; bRequiresBump = true; } } // </PATCH: make sure the zIndex is >= any zIndex given in the initial creation settings> if (bRequiresBump) { this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2)); } } } }; i2b2.bugfix2 = function() { YAHOO.lang.augmentProto(YAHOO.widget.Overlay, i2b2.bugfix1, true); delete i2b2.bugfix1; delete i2b2.bugfix2; }; setTimeout('i2b2.bugfix2()',200); // AJAX/XML // ================================================================================================== // function getHtmlText(node) { if (node.innerText) { // IE; return node.innerText; } else { if (node.textContent) { return node.textContent; } } console.error('getHtmlText(): no innerText or textContent.'); } // ================================================================================================== // function showXML(c,r,t) { switch (t) { case "Request": var s = i2b2[c].view[r]['query'+t]; if (s) { s = s.replace(new RegExp('<','g'),'<'); s = s.replace(new RegExp('>','g'),'>'); } else { s = ''; } i2b2.hive.MsgSniffer.showSingleMsgRequest(s); break; case "Response": var s = i2b2[c].view[r]['query'+t]; if (s) { s = s.replace(new RegExp('<','g'),'<'); s = s.replace(new RegExp('>','g'),'>'); } else { s = ''; } i2b2.hive.MsgSniffer.showSingleMsgResponse(s); break; case "Stack": if (c=="WORK" && r=="main") { i2b2.hive.MsgSniffer.showStack("Workplace", ["WORK:Workplace"], ["WORK"]); return; } if (c=="ONT" && r=="nav") { i2b2.hive.MsgSniffer.showStack("Ontology Navigation", ["ONT:SDX:Concept","ONT:generalView"], ["ONT"]); return; } if (c=="ONT" && r=="find") { i2b2.hive.MsgSniffer.showStack("Ontology Search", ["ONT:SDX:Concept","ONT:FindBy","ONT:generalView"], ["ONT"]); return; } if (c=="CRC" && r=="history") { i2b2.hive.MsgSniffer.showStack("History", ["CRC:History", "CRC:SDX:QueryMaster", "CRC:SDX:QueryInstance", "CRC:SDX:PatientRecordSet"], ["CRC"]); return; } if (c=="CRC" && r=="QT") { i2b2.hive.MsgSniffer.showStack("Query Tool", ["CRC:QueryTool"]); return; } if (c=="PLUGINMGR" && r=="PlugView") { i2b2.hive.MsgSniffer.show(); return; } if (c=="PM" && r=="Admin") { i2b2.hive.MsgSniffer.showStack("PM Admin", ["PM:Admin"]); return; } alert("captured "+c+" :: "+r+" :: "+t); break; } } // ================================================================================================== // i2b2.h.Xml2String = function(x) { var xmlSerializer; try { xmlSerializer = new XMLSerializer(); var s = xmlSerializer.serializeToString(x); if (s) { return s; } else { return 'Browser not supported yet. (Try Firefox)'; } } catch (e) { return x.xml; } } // helper function to build a sniffer package for Cell Communications events i2b2.h.BuildSniffPack = function(cellName, cellFuncName, results, signalOrigin) { //i2b2.h.BuildSniffPack = function(viewName, cellName, cellFuncName, results) { function i2b2_CellCommPackage() {} var sniffPackage = new i2b2_CellCommPackage(); // if (undefined == viewName) { // sniffPackage.ViewName = viewName; // } sniffPackage.CellName = cellName; sniffPackage.CellAction = cellFuncName; sniffPackage.CommDetails = results; sniffPackage.SignalOrigin = signalOrigin; return sniffPackage; } +i2b2.h.getFormattedResult = getFormattedResult; +i2b2.h.getMinResultText = getMinResultText; +i2b2.h.isMinObfuscation = isMinObfuscation; +/** + * Method for creating obfuscation text + * @param: rawResult - If null or undefined, will default to 0. + */ +function getFormattedResult(rawResult) { + + var resultTitle = ' - '; + var obfuscationSetting = i2b2.hive.cfg.obfuscation; + var isException = i2b2.PM.model.isObfuscated === false; + rawResult = rawResult || 0; + + if (isException) { + return resultTitle += rawResult + ' ' + i2b2.hive.cfg.resultName; + } + + resultTitle += (rawResult >= obfuscationSetting) ? getResultText(rawResult) : getMinResultText(); + + return resultTitle; +} + +/** + * Method for getting default result text if result is less than minimum obfuscation value. + */ +function getMinResultText() { + i2b2.hive.cfg.obfuscation + ' ' + i2b2.hive.cfg.resultName + ' or fewer'; +} + +/** + * True if title represents a result value that is less than the obfuscation minimum value. + * @param: title of a node. + */ +function isMinObfuscation (title) { + return !!title.indexOf(getMinResultText()) > 0; +} + +/** + * Format raw query count as texxt + * @param: Raw query count. + */ +function getResultText(rawResult) { + var text = rawResult + ' +-' + i2b2.hive.cfg.obfuscation + ' ' + i2b2.hive.cfg.resultName; + return text; +} console.timeEnd('execute time'); console.groupEnd();