/** * @projectDescription The SDX controller library for the Workplace Object datatype. * @namespace i2b2 * @inherits i2b2 * @author Nick Benik * @version 1.0 * @see i2b2.sdx * ---------------------------------------------------------------------------------------- * updated 7-31-08: initial launch [Nick Benik] * updated 1-12-09: added QDEF, QGDEF and default XML object handling for SDX subsystem */ console.group('Load & Execute component file: WORK > SDX > Workplace Object'); console.time('execute time'); // ********************************* Patient Record Set Stuff ********************************* i2b2.sdx.TypeControllers.WRK = {}; i2b2.sdx.TypeControllers.WRK.model = {}; // ********************************* Patient Record Set Stuff ********************************* // ********************************************************************************* // ENCAPSULATE DATA // ********************************************************************************* i2b2.sdx.TypeControllers.WRK.getEncapsulateInfo = function() { // this function returns the encapsulation head information return {sdxType: 'WRK', sdxKeyName: 'index', sdxControlCell:'WORK', sdxDisplayNameKey: 'name'}; } i2b2.sdx.TypeControllers.WRK.SaveToDataModel = function(sdxData, sdxParentNode) { // save to WORK 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.WRK.LoadFromDataModel = function(key_value) {} i2b2.sdx.TypeControllers.WRK.ClearAllFromDataModel= function(sdxOptionalParent) { return false; } // ********************************************************************************* // GENERATE HTML (DEFAULT HANDLER) // ********************************************************************************* i2b2.sdx.TypeControllers.WRK.RenderHTML= function(sdxData, options, targetDiv) { // this function extracts the datatype from the SDX's original XML object and relies upon it's // original SDX type controller to render the HTML var sdxCode = false; var sdxPackage = {}; var subclassHTML = ""; var newOptions = options; newOptions.title = ""; newOptions.showchildren = false; newOptions.click = ""; newOptions.dblclick = ""; switch (sdxData.origData.encapType) { case "PREV_QUERY": // this is a QueryMaster object sdxCode = "QM"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges that perform no resolving var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::query_master_id/..")[0]; // extract and create an SDX object for this node var o = {}; o.xmlOrig = x; o.query_master_id = i2b2.h.getXNodeVal(x, "query_master_id"); o.id = o.query_master_id; o.name = i2b2.h.getXNodeVal(x, "name"); o.group = i2b2.h.getXNodeVal(x, "group_id"); o.userid = i2b2.h.getXNodeVal(x, "user_id"); o.created = null; newOptions.icon = "sdx_CRC_QM_workplace.jpg"; newOptions.showchildren = false; newOptions.title = o.name; break; case "PATIENT_COLL": // this is a PatientRecordSet object sdxCode = "PRS"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges that perform no resolving var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::result_instance_id/..")[0]; var o = {}; o.xmlOrig = x; o.result_type = "PATIENTSET"; o.size = i2b2.h.getXNodeVal(x, "set_size"); o.result_instance_id = i2b2.h.getXNodeVal(x, "result_instance_id"); o.PRS_id = o.result_instance_id; o.QI_id = i2b2.h.getXNodeVal(x, "query_instance_id"); o.QM_id = o.QI_id; // TODO: This needs to be properly resolved o.start_date = i2b2.h.getXNodeVal(x, "start_date"); o.end_date = i2b2.h.getXNodeVal(x, "end_date"); o.description = i2b2.h.getXNodeVal(x, "description"); o.title = sdxData.sdxInfo.sdxDisplayName newOptions.icon = "sdx_CRC_PRS.jpg"; newOptions.showchildren = false; newOptions.title = o.title; break; case "ENCOUNTER_COLL": // this is a EncounterRecordSet object sdxCode = "ENS"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges that perform no resolving var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::result_instance_id/..")[0]; var o = {}; o.xmlOrig = x; o.result_type = "ENCOUNTERSET"; o.size = i2b2.h.getXNodeVal(x, "set_size"); o.result_instance_id = i2b2.h.getXNodeVal(x, "result_instance_id"); o.PRS_id = o.result_instance_id; o.QI_id = i2b2.h.getXNodeVal(x, "query_instance_id"); o.QM_id = o.QI_id; // TODO: This needs to be properly resolved o.description = i2b2.h.getXNodeVal(x, "description"); o.start_date = i2b2.h.getXNodeVal(x, "start_date"); o.end_date = i2b2.h.getXNodeVal(x, "end_date"); o.title = sdxData.sdxInfo.sdxDisplayName newOptions.icon = "sdx_CRC_PRS.jpg"; newOptions.showchildren = false; newOptions.title = o.title; break; case "PATIENT": // this is an PatientRecord object sdxCode = "PR"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges that perform no resolving var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::patient/..")[0]; var o = {}; o.xmlOrig = x; o.result_type = "PATIENTSET"; o.patient_id = i2b2.h.XPath(x, "descendant::patient/patient_id/text()")[0].nodeValue; o.PRS_id = i2b2.h.XPath(x, "@patient_set_id")[0].nodeValue; o.PRS_name = i2b2.h.XPath(x, "@patient_set_name")[0].nodeValue; o.title = sdxData.origData.name; newOptions.icon = "sdx_CRC_PR.jpg"; newOptions.showchildren = false; newOptions.title = o.title; break; case "CONCEPT": sdxCode = "CONCPT"; var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant-or-self::concept")[0]; var o = {}; o.xmlOrig = x; o.key = i2b2.h.getXNodeVal(x, "key"); o.level = i2b2.h.getXNodeVal(x, "level"); o.name = i2b2.h.getXNodeVal(x, "name"); o.column_name = i2b2.h.getXNodeVal(x, "columnname"); o.dim_code = i2b2.h.getXNodeVal(x, "dimcode"); o.operator = i2b2.h.getXNodeVal(x, "operator"); o.table_name = i2b2.h.getXNodeVal(x, "tablename"); o.tooltip = i2b2.h.getXNodeVal(x, "tooltip"); o.hasChildren = i2b2.h.getXNodeVal(x, "visualattributes"); var bCanExp = false; if (o.hasChildren.substring(1,0) === "C"){ // render as category icon = 'root'; sDD = ''; sIG = ' isGroup="Y"'; bCanExp = true; } else if (o.hasChildren.substring(1,0) === "F") { // render as possibly having children icon = 'branch'; bCanExp = true; //var sCanExpand = ' canExpand="Y"'; } else if (o.hasChildren.substring(1,0) === "O") { // render as possibly having children icon = 'root'; bCanExp = true; //var sCanExpand = ' canExpand="Y"'; } else if (o.hasChildren.substring(1,0) === "D") { // render as possibly having children icon = 'branch'; bCanExp = true; //var sCanExpand = ' canExpand="Y"'; } else { // render as not having children var icon = 'leaf'; bCanExp = false; } newOptions.icon = { root: "sdx_ONT_CONCPT_"+icon+".gif", branch: "sdx_ONT_CONCPT_"+icon+".gif", leaf: "sdx_ONT_CONCPT_"+icon+".gif" }; newOptions.showchildren = false; newOptions.title = o.name; break; case "PATIENT_COUNT_XML": // Patient Record Count sdxCode = "PRC"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges that perform no resolving var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::result_instance_id/..")[0]; var o = {}; o.xmlOrig = x; o.result_instance_id = i2b2.h.getXNodeVal(x, "result_instance_id"); o.PRC_id = o.result_instance_id; o.QI_id = i2b2.h.getXNodeVal(x, "query_instance_id"); o.QM_id = ""; o.start_date = i2b2.h.getXNodeVal(x, "start_date"); o.end_date = i2b2.h.getXNodeVal(x, "end_date"); o.result_type = "PATIENT_COUNT_XML"; o.size = i2b2.h.getXNodeVal(x, "set_size"); if (o.size > 10) { o.title = "Patient Count - "+o.size+" patients"; } else { if (i2b2.h.isSHRINE()) { o.title = "Patient Count - 10 patients or less"; } else { o.title = "Patient Count - "+o.size+" patients"; } } newOptions.showchildren = false; newOptions.icon = "sdx_CRC_PRC.jpg" newOptions.title = o.title; break; case "GROUP_TEMPLATE": // Query Group Definition (Query Panel) sdxCode = "QGDEF"; // XPath query exploits faults in XML message namespace declarations to avoid creation of namespace resolver kluges var x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::panel_number/..")[0]; var o = {}; o.xmlOrig = x; o.result_type = "GROUP_TEMPLATE"; o.QGDEF_name = i2b2.h.XPath(x, "@name")[0].nodeValue; o.key = false; newOptions.showchildren = false; newOptions.icon = "sdx_CRC_QGDEF.jpg" break; case "QUERY_DEFINITION": sdxCode = "QDEF"; x = i2b2.h.XPath(sdxData.origData.xmlOrig, "work_xml/descendant::query_name/..")[0]; var o = {}; o.xmlOrig = x; o.result_type = "QUERY_DEFINITION"; o.QDEF_name = i2b2.h.XPath(x,"//descendant::query_name/text()")[0].nodeValue; o.key = false; newOptions.showchildren = false; newOptions.icon = "sdx_CRC_QDEF.jpg"; break; default: var t = "No SDX Object exists to represent data-type "+sdxData.origData.encapType; console.warn(t); // encapsulate as a Generic XML object sdxCode = "XML"; var o = {}; var t = i2b2.h.XPath(sdxData.origData.xmlOrig, "descendant::work_xml")[0].childNodes; for (i=0; i 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.WRK.DragDrop.prototype.onDragOver = function(e, id) { // fire the onHoverOver (use SDX so targets can override default event handler) var t = this.yuiTreeNode.data.i2b2_SDX.sdxUnderlyingPackage; if (t) { try { if (this.DDM.ids[t.sdxInfo.sdxType][id]) { i2b2.sdx.Master.onHoverOver(t.sdxInfo.sdxType, e, id, this); } else { // fall back to WRK type processing i2b2.sdx.Master.onHoverOver('WRK', e, id, this); } } catch(e) {} } else { i2b2.sdx.Master.onHoverOver('WRK', e, id, this); } }; i2b2.sdx.TypeControllers.WRK.DragDrop.prototype.onDragOut = function(e, id) { // fire the onHoverOut handler (use SDX so targets can override default event handlers) // fire the onHoverOver (use SDX so targets can override default event handler) var t = this.yuiTreeNode.data.i2b2_SDX.sdxUnderlyingPackage; if (t) { try { if (this.DDM.ids[t.sdxInfo.sdxType][id]) { i2b2.sdx.Master.onHoverOut(t.sdxInfo.sdxType, e, id, this); } else { // fall back to WRK type processing i2b2.sdx.Master.onHoverOut('WRK', e, id, this); } } catch(e) {} } else { i2b2.sdx.Master.onHoverOut('WRK', e, id, this); } }; i2b2.sdx.TypeControllers.WRK.DragDrop.prototype.onDragDrop = function(e, id) { // retreive the concept data from the dragged element var draggedTvNode = this.yuiTreeNode; var draggedData = draggedTvNode.data.i2b2_SDX; var t = this.yuiTreeNode.data.i2b2_SDX.sdxUnderlyingPackage; if (t) { try { if (this.DDM.ids[t.sdxInfo.sdxType][id]) { i2b2.sdx.Master.onHoverOut(t.sdxInfo.sdxType, e, id, this); } else { i2b2.sdx.Master.onHoverOut('WRK', e, id, this); } } catch(e) { i2b2.sdx.Master.onHoverOut('WRK', e, id, this); } } else { i2b2.sdx.Master.onHoverOut('WRK', e, id, this); } try { // restraints on Workplace moves var parentTree = YAHOO.widget.TreeView.findTreeByChildDiv(id); var targetTvNode = parentTree.getNodeByProperty('nodeid', id); if (targetTvNode.isDescendant(draggedTvNode)) { return false; } // can't drag parents into their children if (draggedTvNode.parent.data.nodeid == targetTvNode.data.nodeid) { return false; } // ignore moving a child onto it's current parent if (targetTvNode.data.i2b2_SDX.sdxInfo.sdxType=="WRK") { // drop onto a WRK node if (Object.isUndefined(draggedData.sdxUnderlyingPackage)) { // dragging a folder object i2b2.WORK.ctrlr.main.moveFolder(draggedTvNode, targetTvNode); } else { // dragging encapsulated data node // START bug fix: handle a bug in YUI (dragdrop.js @ lines 872-881) if (this._handledDragDropAlready) { return true; } else { this._handledDragDropAlready = true; var scopeHackThis = this; var resetClosure = function() { delete scopeHackThis._handledDragDropAlready; }; setTimeout(resetClosure, 100); } // END bug fix // Server handles moving of non-folder items by deleting them from their old location and creating a new record as a child of the new location // Filter list of TV nodes to refresh so attempts are not made to refresh non-existent children (and kill DD reattachment) var tvRefreshList = []; tvRefreshList.push(targetTvNode); tvRefreshList.push(draggedTvNode.parent); tvRefreshList = i2b2.WORK.ctrlr.main._generateRefreshList(tvRefreshList); var funcRefresh = function() { // this function is fired after all the threads in the mutex have finished execution var cl_tvRefreshList = tvRefreshList; // closure var // whack the "already loaded" status out of the node that need refreshing and // initiate a dynamic loading of the childs nodes (including our newest addition) for (var i=0; i DROP HANDLER // !!!! DO NOT EDIT - ATTACH YOUR OWN CUSTOM ROUTINE USING // !!!! THE i2b2.sdx.Master.setHandlerCustom FUNCTION // ********************************************************************************* i2b2.sdx.TypeControllers.WRK.DropHandler = function(sdxData) { alert('[Workplace Object DROPPED] You need to create your own custom drop event handler.'); } console.timeEnd('execute time'); console.groupEnd();