/** * @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 0) { if (includeChildren == true || includeChildren == true) { for (var i=0; i 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, ">"); 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 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 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 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; } } // = 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; } } // = 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; } console.timeEnd('execute time'); console.groupEnd();