otsdaq_utilities  v2_04_01
DesktopWindowContentCode.js
1 //=====================================================================================
2 //
3 // Created Jan, 2013
4 // by Ryan Rivera ((rrivera at fnal.gov))
5 //
6 // DesktopWindowContentCode.js
7 //
8 // Requirements:
9 // 1. paste the following:
10 //
11 // <script type="text/JavaScript" src="/WebPath/js/Globals.js"></script>
12 // <script type="text/JavaScript" src="/WebPath/js/Debug.js"></script>
13 // <script type="text/JavaScript" src="/WebPath/js/DesktopWindowContentCode.js"></script>
14 //
15 // ...anywhere inside the <head></head> tag of a window content html page
16 // 2. for proper functionality certain handlers are used:
17 // cannot overwrite handlers for window: onfocus, onscroll, onblur, onmousemove
18 // (if you must overwrite, try to call the DesktopContent handlers from your handlers)
19 //
20 // Recommendations:
21 // 1. use Debug to output status and errors, e.g.:
22 // Debug.log("this is my status",Debug.LOW_PRIORITY); //LOW_PRIORITY, MED_PRIORITY, HIGH_PRIORITY
23 // 2. call window.focus() to bring your window to the front of the Desktop
24 //
25 // The code of Requirement #1 should be inserted in the header of each page that will be
26 // the content of a window in the ots desktop.
27 //
28 // This code handles bringing the window to the front when the content
29 // is clicked or scrolled.
30 //
31 // This code also handles server requests and response handlers for the content code:
32 // -DesktopContent.XMLHttpRequest(requestURL, data, returnHandler <optional>,
33 // reqParam <optional>, progressHandler <optional>, callHandlerOnErr <optional>,
34 // doNotShowLoadingOverlay <optional>, targetSupervisor <optional>, ignoreSystemBlock <optional>)
35 //
36 // ... here is an example request:
37 //
38 // DesktopContent.XMLHttpRequest("Request?" +
39 //
40 // //get data
41 // "RequestType=exportFEMacro" +
42 // "&MacroName=" + macroName +
43 // "&PluginName=" + targetFEPluginName,
44 //
45 // //post data
46 // "MacroSequence=" + macroSequence +
47 // "&MacroNotes=" + encodeURIComponent(macroNotes),
48 //
49 // //request handler
50 // function(req)
51 // {
52 // //..do something on successful response
53 // Debug.log("Success!",Debug.INFO_PRIORITY);
54 // }, //end request handler
55 // 0 /*reqParam*/, 0 /*progressHandler*/, false /*callHandlerOnErr*/,
56 // false /*doNotShowLoadingOverlay*/); //end XMLHttpRequest() call
57 //
58 // ... after a server request, returnHandler is called with response in req and reqParam if user defined
59 // ... here is a returnHandler declaration example:
60 //
61 // function returnHandler(req,reqParam,errStr)
62 // {
63 // if(errStr != "") return; //error occured!
64 //
65 // var err = DesktopContent.getXMLValue(req,"Error"); //example application level error
66 // if(err)
67 // {
68 // Debug.log(err,Debug.HIGH_PRIORITY); //log error and create pop-up error box
69 // return;
70 // }
71 //
72 // if(reqParam = 0)
73 // { //... do something }
74 // else if(reqParam = 1)
75 // { //... do something else}
76 // else
77 // { //... do something else}
78 //
79 // //..do more things
80 //
81 // }
82 //
83 // -DesktopContent.getXMLValue(req, name)
84 // ... to get string value from XML server response. field name is needed.
85 //
86 // ... or to get array of elements by tag name
87 // var els = req.responseXML.getElementsByTagName(name);
88 // for(var i=0;i<els.length;++i)
89 // Debug.log(els[i].getAttribute("value"));
90 //
91 //
92 // Additional Functionality:
93 // DesktopContent.popUpVerification(prompt, func [optional], val [optional], bgColor [optional],
94 // textColor [optional], borderColor [optional], getUserInput [optional],
95 // dialogWidth [optional], cancelFunc [optional], yesButtonText [optional])
96 // DesktopContent.tooltip(uid,tip)
97 // DesktopContent.getWindowWidth()
98 // DesktopContent.getWindowHeight()
99 // DesktopContent.getWindowScrollLeft()
100 // DesktopContent.getWindowScrollTop()
101 // DesktopContent.getMouseX()
102 // DesktopContent.getMouseY()
103 // DesktopContent.getDefaultWindowColor() // returns "rgb(#,#,#)"
104 // DesktopContent.getDefaultDashboardColor()// returns "rgb(#,#,#)"
105 // DesktopContent.getDefaultDesktopColor() // returns "rgb(#,#,#)"
106 // DesktopContent.getUsername()
107 // DesktopContent.openNewWindow(name,subname,windowPath,unique,completeHandler)
108 // DesktopContent.openNewBrowserTab(name,subname,windowPath,unique,completeHandler)
109 //
110 //=====================================================================================
111 
112 var DesktopContent = DesktopContent || {}; //define Desktop namespace
113 
114 if (typeof Debug == 'undefined')
115  alert('ERROR: Debug is undefined! Must include Debug.js before DesktopWindowContentCode.js');
116 if (typeof Globals == 'undefined')
117  alert('ERROR: Globals is undefined! Must include Globals.js before DesktopWindowContentCode.js');
118 
119 
120 //"public" function list:
121 // DesktopContent.XMLHttpRequest(requestURL, data, returnHandler, reqParam, progressHandler, callHandlerOnErr, doNotShowLoadingOverlay, targetSupervisor, ignoreSystemBlock)
122 // DesktopContent.getXMLValue(req, name)
123 // DesktopContent.getXMLNode(req, name)
124 // DesktopContent.getXMLDataNode(req)
125 // DesktopContent.getXMLAttributeValue(req, name, attribute)
126 // DesktopContent.getXMLChildren(req, nodeName)
127 // DesktopContent.getXMLRequestErrors(req)
128 // DesktopContent.popUpVerification(prompt, func, val, bgColor, textColor, borderColor, getUserInput, dialogWidth, cancelFunc)
129 // DesktopContent.setPopUpPosition(el,w,h,padding,border,margin,doNotResize,offsetUp)
130 // DesktopContent.tooltip(uid,tip)
131 // DesktopContent.getWindowWidth()
132 // DesktopContent.getWindowHeight()
133 // DesktopContent.getWindowScrollLeft()
134 // DesktopContent.getWindowScrollTop()
135 // DesktopContent.getBodyWidth()
136 // DesktopContent.getBodyHeight()
137 // DesktopContent.getMouseX()
138 // DesktopContent.getMouseY()
139 // DesktopContent.getDefaultWindowColor()
140 // DesktopContent.getDefaultDashboardColor()
141 // DesktopContent.getDefaultDesktopColor()
142 // DesktopContent.getUsername()
143 // DesktopContent.openNewWindow(name,subname,windowPath,unique,completeHandler)
144 // DesktopContent.mouseMoveSubscriber(newHandler)
145 // DesktopContent.openNewBrowserTab(name,subname,windowPath,unique,completeHandler)
146 // DesktopContent.getParameter(index, name)
147 // DesktopContent.getDesktopParameter(index, name)
148 // DesktopContent.getDesktopWindowTitle()
149 // DesktopContent.showLoading()
150 // DesktopContent.hideLoading()
151 
152 //"private" function list:
153 // DesktopContent.init()
154 // DesktopContent.handleFocus(e)
155 // DesktopContent.handleBlur(e)
156 // DesktopContent.handleScroll(e)
157 // DesktopContent.mouseMove(mouseEvent)
158 // DesktopContent.checkCookieCodeRace()
159 // DesktopContent.clearPopUpVerification(func)
160 // DesktopContent.parseColor(colorStr)
161 // DesktopContent.tooltipSetAlwaysShow(srcFunc,srcFile,srcId,neverShow,temporarySilence)
162 // DesktopContent.tooltipConditionString(str);
163 
164 DesktopContent._isFocused = false;
165 DesktopContent._theWindow = 0;
166 DesktopContent._myDesktopFrame = 0;
167 DesktopContent._zMailbox = 0;
168 DesktopContent._mouseOverXmailbox = 0;
169 DesktopContent._mouseOverYmailbox = 0;
170 DesktopContent._windowMouseX = -1;
171 DesktopContent._windowMouseY = -1;
172 
173 DesktopContent._serverOrigin = "";
174 DesktopContent._localOrigin = "";
175 DesktopContent._serverUrnLid = 0;
176 DesktopContent._localUrnLid = 0;
177 
178 DesktopContent._cookieCodeMailbox = 0;
179 DesktopContent._updateTimeMailbox = 0;
180 DesktopContent._needToLoginMailbox = 0;
181 DesktopContent._openWindowMailbox = 0;
182 DesktopContent._blockSystemCheckMailbox = 0;
183 
184 DesktopContent._lastCookieCode = 0;
185 DesktopContent._lastCookieTime = 0;
186 
187 
188 DesktopContent._verifyPopUp = 0;
189 DesktopContent._verifyPopUpId = "DesktopContent-verifyPopUp";
190 
191 DesktopContent._windowColorPostbox = 0;
192 DesktopContent._dashboardColorPostbox = 0;
193 DesktopContent._desktopColor = 0;
194 
195 DesktopContent._sequence = 0;
196 
197 DesktopContent._mouseMoveSubscribers = [];
198 
199 
200 //=====================================================================================
201 //initialize content's place in the world
202 // caution when using "window" anywhere outside this function because
203 // desktop window can be at different levels depending on page depth (page may be inside frame)
204 // use instead DesktopContent._theWindow
205 DesktopContent.init = function() {
206 
207  if(typeof Desktop !== 'undefined') return; //skip if Desktop exists (only using for tooltip
208 
209  var tmpCnt = 0;
210  DesktopContent._theWindow = self;
211  while(tmpCnt++ < 5 && DesktopContent._theWindow && //while can not find the top window frame in the desktop
212  DesktopContent._theWindow.window.name.search("DesktopWindowFrame") < 0)
213  DesktopContent._theWindow = DesktopContent._theWindow.parent;
214  DesktopContent._theWindow = DesktopContent._theWindow.window;
215 
216  DesktopContent._myDesktopFrame = DesktopContent._theWindow.parent.document.getElementById(DesktopContent._theWindow.name);
217  DesktopContent._zMailbox = DesktopContent._theWindow.parent.document.getElementById("Desktop-windowZmailbox");
218  DesktopContent._mouseOverXmailbox = DesktopContent._theWindow.parent.document.getElementById("Desktop-mouseOverXmailbox");
219  DesktopContent._mouseOverYmailbox = DesktopContent._theWindow.parent.document.getElementById("Desktop-mouseOverYmailbox");
220 
221  DesktopContent._cookieCodeMailbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-cookieCodeMailbox");
222  DesktopContent._updateTimeMailbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-updateTimeMailbox");
223  DesktopContent._needToLoginMailbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-needToLoginMailbox");
224  DesktopContent._openWindowMailbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-openWindowMailbox");
225  DesktopContent._blockSystemCheckMailbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-blockSystemCheckMailbox");
226 
227  DesktopContent._windowColorPostbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-windowColorPostbox");
228  DesktopContent._dashboardColorPostbox = DesktopContent._theWindow.parent.document.getElementById("DesktopContent-dashboardColorPostbox");
229 
230  if(DesktopContent._theWindow.parent.document.body)
231  DesktopContent._desktopColor = DesktopContent._theWindow.parent.document.body.style.backgroundColor;
232 
233  window.onfocus = DesktopContent.handleFocus;
234  window.onmousedown = DesktopContent.handleFocus;
235  window.onscroll = DesktopContent.handleScroll;
236  window.onblur = DesktopContent.handleBlur;
237  window.onmousemove = DesktopContent.mouseMove; //setup mouse move handler
238  window.focus(); //before this fix, full screen in new tab would not give window focus
239 
240  DesktopContent._serverUrnLid = DesktopContent.getDesktopWindowParameter(0,"urn");//((DesktopContent._theWindow.parent.window.location.search.substr(1)).split('='))[1];
241  if(typeof DesktopContent._serverUrnLid == 'undefined')
242  Debug.log("ERROR -- Supervisor Application URN-LID not found",Debug.HIGH_PRIORITY);
243  Debug.log("Supervisor Application URN-LID #" + DesktopContent._serverUrnLid);
244  DesktopContent._serverOrigin = DesktopContent._theWindow.parent.window.location.origin;
245  Debug.log("Supervisor Application Origin = " + DesktopContent._serverOrigin);
246 
247  DesktopContent._localUrnLid = DesktopContent.getParameter(0,"urn");
248  if(typeof DesktopContent._localUrnLid == 'undefined')
249  DesktopContent._localUrnLid = 0;
250  Debug.log("Local Application URN-LID #" + DesktopContent._localUrnLid);
251  DesktopContent._localOrigin = window.location.origin;
252  Debug.log("Local Application Origin = " + DesktopContent._localOrigin);
253 
254  //get Wizard sequence (if in Wizard mode)
255  DesktopContent._sequence = DesktopContent.getDesktopParameter(0,"code");
256  if(!DesktopContent._sequence || DesktopContent._sequence == "")
257  DesktopContent._sequence = 0; //normal desktop mode
258  else
259  Debug.log("In Wizard Mode with Sequence=" + DesktopContent._sequence);
260 }
261 
262 //DesktopContent.getParameter ~
263 // returns the value of the url GET parameter specified by index
264 // if using name, then (mostly) ignore index
265 // Note: in normal mode the first two params are only separated by = (no &'s) for historical reasons
266 DesktopContent.getParameter = function(index,name) {
267  // Debug.log(window.location)
268  var params = (window.location.search.substr(1)).split('&');
269  var spliti, vs;
270  //if name given, make it the priority
271  if(name)
272  {
273  for(index=0;index<params.length;++index)
274  {
275  spliti = params[index].indexOf('=');
276  if(spliti < 0) continue; //poorly formed parameter?
277  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
278  if(decodeURIComponent(vs[0]) == name)
279  return decodeURIComponent(vs[1]);
280  }
281  return; //return undefined .. name not found
282  }
283 
284  //using index
285  if(index >= params.length) return; //return undefined
286 
287  spliti = params[index].indexOf('=');
288  if(spliti < 0) return; //return undefined
289  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
290  return decodeURIComponent(vs[1]); //return value
291 }
292 
293 //DesktopContent.getDesktopParameter ~
294 // returns the value of the url GET parameter specified by index of the Desktop url
295 // if using name, then (mostly) ignore index
296 DesktopContent.getDesktopParameter = function(index, name) {
297  // Debug.log(window.location)
298 
299  var win = DesktopContent._theWindow;
300  if(!win) //for parameter directly from desktop code
301  win = window.parent.window;
302  else
303  win = win.parent.parent.window;
304  var params = (win.location.search.substr(1)).split('&');
305  if(index >= params.length) return; //return undefined
306  var spliti, vs;
307  //if name given, make it the priority
308  if(name)
309  {
310  for(var index=0;index<params.length;++index)
311  {
312  spliti = params[index].indexOf('=');
313  if(spliti < 0) continue; //poorly formed parameter?
314  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
315  if(vs[0] == name)
316  return decodeURIComponent(vs[1]);
317  }
318  return; //return undefined .. name not found
319  }
320 
321  spliti = params[index].indexOf('=');
322  if(spliti < 0) return; //return undefined
323  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
324  return decodeURIComponent(vs[1]); //return value
325 }
326 
327 //DesktopContent.getDesktopWindowParameter ~
328 // returns the value of the url GET parameter specified by index of the Window frame url
329 // if using name, then (mostly) ignore index
330 DesktopContent.getDesktopWindowParameter = function(index, name) {
331  // Debug.log(window.location)
332 
333  var win = DesktopContent._theWindow;
334  if(!win) //for parameter directly from desktop code
335  win = window;
336  else
337  win = win.parent.window;
338 
339  //fix/standardize search string
340  var searchStr = win.location.search.substr(1);
341  var i = searchStr.indexOf("=securityType");
342  if(i > 0) searchStr = searchStr.substr(0,i) + '&' + searchStr.substr(i+1);
343 
344  var params = ((searchStr)).split('&');
345  if(index >= params.length) return; //return undefined
346  var spliti, vs;
347  //if name given, make it the priority
348  if(name)
349  {
350  for(var index=0;index<params.length;++index)
351  {
352  spliti = params[index].indexOf('=');
353  if(spliti < 0) continue; //poorly formed parameter?
354  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
355  if(vs[0] == name)
356  return decodeURIComponent(vs[1]);
357  }
358  return; //return undefined .. name not found
359  }
360 
361  spliti = params[index].indexOf('=');
362  if(spliti < 0) return; //return undefined
363  vs = [params[index].substr(0,spliti),params[index].substr(spliti+1)];
364  return decodeURIComponent(vs[1]); //return value
365 }
366 
367 //DesktopContent.handleFocus ~
368 DesktopContent.handleFocus = function(e) { //access z-index mailbox on desktop, increment by 1 and set parent's z-index
369 
370  if(!DesktopContent._myDesktopFrame) return; //only happen if not part of desktop
371 
372  //commented below because, at times, desktop window movement led to wrong focus assumptions
373  //if(DesktopContent._isFocused ) {Debug.log("already"); return; }//only focus when unfocused
374  DesktopContent._isFocused = true;
375  DesktopContent._myDesktopFrame.parentNode.parentNode.style.zIndex = DesktopContent._zMailbox.innerHTML;
376  DesktopContent._zMailbox.innerHTML = parseInt(DesktopContent._zMailbox.innerHTML) + 1;
377  return true;
378 }
379 DesktopContent.handleBlur = function(e) {
380  DesktopContent._isFocused = false;
381 }
382 DesktopContent.handleScroll = function(e) {
383  window.focus();
384 }
385 DesktopContent.mouseMove = function(mouseEvent) {
386  //call each subscriber
387  for(var i=0; i<DesktopContent._mouseMoveSubscribers.length; ++i)
388  DesktopContent._mouseMoveSubscribers[i](mouseEvent);
389 
390  if(!DesktopContent._myDesktopFrame) return; //only happens if not part of desktop
391 
392  DesktopContent._windowMouseX = parseInt(mouseEvent.clientX);
393  DesktopContent._windowMouseY = parseInt(mouseEvent.clientY);
394 
395  //add window frame position(absolute) + iframe position within window + mouse position within iframe
396  DesktopContent._mouseOverXmailbox.innerHTML = parseInt(DesktopContent._myDesktopFrame.parentNode.parentNode.offsetLeft) +
397  parseInt(DesktopContent._myDesktopFrame.offsetLeft) + DesktopContent._windowMouseX;
398  DesktopContent._mouseOverYmailbox.innerHTML = parseInt(DesktopContent._myDesktopFrame.parentNode.parentNode.offsetTop) +
399  parseInt(DesktopContent._myDesktopFrame.offsetTop) + DesktopContent._windowMouseY;
400 }
401 
402 DesktopContent.mouseMoveSubscriber = function(newHandler) {
403  DesktopContent._mouseMoveSubscribers.push(newHandler);
404 }
405 
406 
407 DesktopContent.init(); //initialize handlers
408 
409 
410 //=====================================================================================
411 // XML request helpers
412 //=====================================================================================
413 
414 //used by DesktopContent.XMLHttpRequest to reject multiple calls to same handler
415 //(this is a result of bad error handling in the desktop window page.. so this is meant to inform the developer to fix the issue)
416 DesktopContent._arrayOfFailedHandlers = new Array();
417 
418 //=====================================================================================
419 //=====================================================================================
420 //Loading pop up helpers
421 DesktopContent._loadBox = 0;
422 DesktopContent._loadBoxId = "DesktopContent-load-box";
423 DesktopContent._loadBoxTimer = 0;
424 DesktopContent._loadBoxRequestStack = 0; //load box is not removed until back to 0
425 
426 //=====================================================================================
427 //DesktopContent.showLoading
428 // Pass nextFunction to launch something immediately after showing load box
429 // with hideLoading() called after the function
430 DesktopContent.showLoading = function(nextFunction) {
431 
432  localDoIt();
433  if(nextFunction)
434  {
435  window.setTimeout(function()
436  {
437  nextFunction();
438  DesktopContent.hideLoading();
439  },10);
440  }
441  return;
442 
444  function localDoIt()
445  {
446  Debug.log("DesktopContent.showLoading " + DesktopContent._loadBoxRequestStack);
447 
448  if(DesktopContent._loadBoxRequestStack++) //box should still be open, add to stack
449  return;
450 
451  //check if DesktopContent._loadBox has been set
452  if(!DesktopContent._loadBox)
453  {
454  //check if there is already an error box with same id and share
455  var el = document.getElementById(DesktopContent._loadBoxId);
456  if(!el) //element doesn't already exist, so we need to create the element
457  {
458  var body = document.getElementsByTagName("BODY")[0];
459  if(!body) //maybe page not loaded yet.. so wait to report
460  {
461  //try again in 1 second
462  window.setTimeout(function() { Debug.errorPop(err,severity)}, 1000);
463  return;
464  }
465 
466  //create the element
467  el = document.createElement("div");
468  el.setAttribute("id", DesktopContent._loadBoxId);
469  el.style.display = "none";
470  var str = "";
471 
472  str += "<table height='100%' width='100%'><td id='" +
473  DesktopContent._loadBoxId + "-td'>Loading...</td></table>";
474  el.innerHTML = str;
475  body.appendChild(el); //add element to body of page
476 
477 
478  //add style for loading to page HEAD tag
479  var css = "";
480 
481 
482  //load box style
483  css += "#" + DesktopContent._loadBoxId +
484  "{" +
485  "position: absolute; display: none; border: 2px solid gray;" +
486  "background-color: rgba(0,0,0,0.8); overflow-y: auto;" +
487  "overflow-x: auto; padding: 5px; -moz-border-radius: 2px;" +
488  "-webkit-border-radius: 2px; border-radius: 2px;" +
489  "font-size: 18px; z-index: 2147483647;" + //max 32 bit number z-index
490  "color: white; " +
491  "font-family: 'Comfortaa', arial; text-align: left;" +
492  "left: 8px; top: 8px; margin-right: 8px; height:400px; " +
493  "}\n\n";
494  css += "#" + DesktopContent._loadBoxId + " table" +
495  "{" +
496  "background-color: rgba(0,0,0,0.8);" +
497  "border: 0;" +
498  "}\n\n";
499 
500  //load box text style
501  // css += "#" + DesktopContent._loadBoxId + "-td" +
502  // "{" +
503  // "color: white; font-size: 18px;" +
504  // "font-family: 'Comfortaa', arial;" +
505  // "text-align: center;" +
506  // "}\n\n";
507 
508  //add style element to HEAD tag
509  var style = document.createElement('style');
510 
511  if (style.styleSheet) {
512  style.styleSheet.cssText = css;
513  } else {
514  style.appendChild(document.createTextNode(css));
515  }
516 
517  document.getElementsByTagName('head')[0].appendChild(style);
518  }
519  DesktopContent._loadBox = el;
520  }
521 
522  //have load popup element now, so display it at center of page
523 
524  var W = 100;
525  var H = 60;
526 
527  var WW,WH; //window width and height
528  //get width and height properly
529  if(typeof DesktopContent != 'undefined') //define width using DesktopContent
530  {
531  WW = DesktopContent.getWindowWidth();
532  WH = DesktopContent.getWindowHeight();
533  }
534  else if(typeof Desktop != 'undefined' && Desktop.desktop) //define width using Desktop
535  {
536  WW = DesktopContent.getDesktopWidth();
537  WH = DesktopContent.getDesktopHeight();
538  }
539 
540  var X = DesktopContent.getWindowScrollLeft() + (WW - W - 4)/2; //for 2px borders
541  var Y = DesktopContent.getWindowScrollTop() + (WH - H -4)/2; //for 2px borders
542 
543  //show the load box whereever the current scroll is
544  DesktopContent._loadBox.style.left = (X) + "px";
545  DesktopContent._loadBox.style.top = (Y) + "px";
546  DesktopContent._loadBox.style.width = (W) + "px";
547  DesktopContent._loadBox.style.height = (H) + "px";
548 
549  DesktopContent._loadBox.style.display = "block";
550 
551  //===================
552  //setup Loading.. animation
553  var loadBoxStr = "..";
554  var el = document.getElementById(DesktopContent._loadBoxId + "-td");
555  el.innerHTML = "Loading" + loadBoxStr;
556 
558  var loadBoxAnimationFunction = function() {
559  if(loadBoxStr.length > 3) loadBoxStr = "";
560  else
561  loadBoxStr += ".";
562  el.innerHTML = "Loading" + loadBoxStr;
563  }; //end loadBoxAnimationFunction
564 
565  window.clearInterval(DesktopContent._loadBoxTimer);
566  DesktopContent._loadBoxTimer = window.setInterval(loadBoxAnimationFunction, 300);
567  } //end localDoIt()
568 } //end showLoading()
569 //=====================================================================================
570 DesktopContent._loadBoxHideTimer = 0;
571 DesktopContent.hideLoading = function() {
572 
573 // if(--DesktopContent._loadBoxRequestStack) //subtract from stack, but dont hide if stack remains
574 // return;
575 
576  //hide in a little bit, to provide more continuity to
577  // back to back loading box requests
578 // window.clearInterval(DesktopContent._loadBoxHideTimer);
579 // DesktopContent._loadBoxHideTimer = window.setTimeout(
580 // localHideLoadBox, 300);
581 
582 
583 
584 // /////////////////////////
585 // function localHideLoadBox()
586 // {
587 // window.clearInterval(DesktopContent._loadBoxTimer); //kill loading animation
588 // Debug.log("DesktopContent.hideLoading");
589 // document.getElementById(DesktopContent._loadBoxId).style.display = "none";
590 // } //end localHideLoadBox
591 
592  window.setTimeout(localHideLoadBox, 300);
594  function localHideLoadBox()
595  {
596  if(--DesktopContent._loadBoxRequestStack) //subtract from stack, but dont hide if stack remains
597  return;
598 
599  window.clearInterval(DesktopContent._loadBoxTimer); //kill loading animation
600  Debug.log("DesktopContent.hideLoading");
601  document.getElementById(DesktopContent._loadBoxId).style.display = "none";
602 
603  } //end localHideLoadBox
604 
605 } //end hideLoading()
606 //=====================================================================================
607 //DesktopContent.XMLHttpRequest
608 // forms request properly for ots server, POSTs data
609 // and when request is returned, returnHandler is called with
610 // req result on success, if failure (e.g. due to bad url) called with 0 and
611 // error description in errStr.
612 //
613 // For proper request need: urnLid, cookieCode
614 //
615 // Handler always receives standard xml response if server is ok:
616 // <ROOT>
617 // <HEADER><CookieCode value=''/></HEADER>
618 // <DATA> ... </DATA>
619 // </ROOT>
620 //
621 // Where CookieCode and DisplayName can change upon every server response
622 //
623 // reqParam is used to give the returnHandler an index to route responses to.
624 // progressHandler can be given to receive progress updates (e.g. for file uploads)
625 // callHandlerOnErr can be set to true to have handler called with errStr parameter
626 // otherwise, handler will not be called on error.
627 //
628 DesktopContent.XMLHttpRequest = function(requestURL, data, returnHandler,
629  reqParam, progressHandler, callHandlerOnErr, doNotShowLoadingOverlay,
630  targetSupervisor, ignoreSystemBlock) {
631 
632  // Sequence is used as an alternative approach to cookieCode (e.g. ots Config Wizard).
633  var sequence = DesktopContent._sequence;
634  var errStr = "";
635  var req;
636 
637  var callerLocation = "";
638  try
639  {
640  callerLocation = (new Error).stack.split("\n")[2];
641  var tmpCallerLocation = callerLocation.slice(0,callerLocation.indexOf(' ('));
642  callerLocation = callerLocation.slice(tmpCallerLocation.length+2,
643  callerLocation.length-1);
644  }
645  catch(e) {} //ignore error
646 
647 
648  if((!ignoreSystemBlock && DesktopContent._blockSystemCheckMailbox && //we expect the system to be down during system block
649  DesktopContent._blockSystemCheckMailbox.innerHTML != "") ||
650  (DesktopContent._needToLoginMailbox &&
651  DesktopContent._needToLoginMailbox.innerHTML == "1"))
652  {
653  //check if already marked the mailbox.. and do nothing because we know something is wrong
654 
655  errStr = "The system appears to be down.";
656  errStr += " (Try reconnecting/reloading the page, or alert ots admins if problem persists.)";
657  Debug.log("Error: " + errStr,Debug.HIGH_PRIORITY);
658  req = 0; //force to 0 to indicate error
659  var found = false;
660  if(DesktopContent._arrayOfFailedHandlers.length < 2) //only give pop up behavior for first 2 failures (then go quiet)
661  {
662  for(var rh in DesktopContent._arrayOfFailedHandlers)
663  if(DesktopContent._arrayOfFailedHandlers[rh] == returnHandler)
664  {
665  errStr = "Blocking multiple error responses to same handler. \nRecurring error should be handled by returnHandler: " + returnHandler;
666  Debug.log(errStr.substr(0,200) + "...",Debug.HIGH_PRIORITY);
667  found = true; break;
668  }
669  }
670  else
671  {
672  errStr = "Quiet Mode. Blocking multiple error responses to ALL handlers. \nRecurring error should be handled by returnHandler:" + returnHandler;
673  Debug.log(errStr.substr(0,200) + "...",Debug.HIGH_PRIORITY);
674  found = true;
675  }
676 
677  if(!found) DesktopContent._arrayOfFailedHandlers.push(returnHandler);
678 
679  //only call return handler once
680  if(returnHandler && !found && callHandlerOnErr) returnHandler(req, reqParam, errStr);
681  return;
682  }
683 
684  req = new XMLHttpRequest();
685 
686  if(progressHandler) req.upload.addEventListener("progress", progressHandler, false); //add progress listener if defined
687 
688  //set timeout to detect infinite loops or long waits
689  var timeoutTimer;
690  var timeoutFunction = function()
691  {
692  Debug.log("It has been 60 seconds.. still waiting for a response. " +
693  "Is there an infinite loop occuring at the server? " +
694  "Or is this just a really long request..",
695  Debug.HIGH_PRIORITY);
696  timeoutTimer = window.setTimeout(timeoutFunction, 60000);
697  }
698  timeoutTimer = window.setTimeout(timeoutFunction, 60000);
699 
700  //setup response handler
701  req.onreadystatechange = function() {
702  //Debug.log(req.readyState + " " + req.status);
703  if (req.readyState==4)
704  { //when readyState=4 return complete, status=200 for success, status=400 for fail
705  window.clearTimeout(timeoutTimer);
706 
707  if(!doNotShowLoadingOverlay)
708  DesktopContent.hideLoading();
709 
710  if(req.status==200)
711  {
712  //Debug.log("Request Response Text " + req.responseText + " ---\nXML " + req.responseXML,Debug.LOW_PRIORITY);
713 
714  DesktopContent._lastCookieTime = parseInt((new Date()).getTime()); //in ms
715 
716  //check if failed due to cookieCode and go to login prompt
717  if(req.responseText == Globals.REQ_NO_PERMISSION_RESPONSE)
718  {
719  errStr = "Request failed do to insufficient account permissions.";
720  //return;
721  }
722  else if(req.responseText == Globals.REQ_USER_LOCKOUT_RESPONSE)
723  {
724  errStr = "Request failed because another user has locked ots. Put your mouse over the lock icon at the top of the dashboard to see who.";
725  //return;
726  }
727  else if(req.responseText == Globals.REQ_NO_LOGIN_RESPONSE)
728  {
729  errStr = "Login has expired.";
730 
731  if((ignoreSystemBlock || (DesktopContent._blockSystemCheckMailbox &&
732  DesktopContent._blockSystemCheckMailbox.innerHTML == "")) && //make sure system is alive
733  DesktopContent._needToLoginMailbox) //if login mailbox is valid, force login
734  DesktopContent._needToLoginMailbox.innerHTML = "1"; //force to login screen on server failure
735  //return;
736  }
737  else if(req.responseText == Globals.REQ_LOCK_REQUIRED_RESPONSE)
738  {
739  errStr = "Request failed because the request requires the user to lockout the system. Please take over the lock in the Settings area to proceed.";
740  }
741  else if(!sequence)
742  {
743 
744  if(!req.responseXML) //invalid XML received
745  {
746  errStr = "Request response is invalid XML!";
747  //return;
748  }
749  else
750  {
751  //handle cookie code mailbox
752  DesktopContent._lastCookieCode = DesktopContent.getXMLValue(req,'CookieCode');
753  if (typeof DesktopContent._lastCookieCode == 'undefined')
754  { //clear req, server failed
755  errStr = "Request Failed - Missing Cookie in Response.";
756 
757  if((ignoreSystemBlock || (DesktopContent._blockSystemCheckMailbox &&
758  DesktopContent._blockSystemCheckMailbox.innerHTML == "")) && //make sure system is alive
759  DesktopContent._needToLoginMailbox) //if login mailbox is valid, force login
760  DesktopContent._needToLoginMailbox.innerHTML = "1"; //force to login screen on server failure
761 
762  }
763  else if(DesktopContent._lastCookieCode != "AllowNoUser")
764  { //check if should update cc mailbox
765 
766  //check twice to handle race conditions with other content code
767  if(parseInt(DesktopContent._updateTimeMailbox.innerHTML) < DesktopContent._lastCookieTime) //then current code is newer
768  {
769  DesktopContent._updateTimeMailbox.innerHTML = DesktopContent._lastCookieTime;
770  DesktopContent._cookieCodeMailbox.innerHTML = DesktopContent._lastCookieCode;
771 
772  setTimeout(DesktopContent.checkCookieCodeRace, Math.random()*1000|0+500); //random wait (500-1500ms) before checking if race conditions occured
773  }
774  }
775  }
776  }
777  }
778  else if(req.status == 0) //request was interrupted (probably window was closed)
779  {
780 // Debug.log("Status=0. Likely this means a window was closed, or the server crashed, in the middle of a request. " +
781 // "\n(It also could mean 'potential security risk' like a cross-domain request) ",Debug.HIGH_PRIORITY);
782  errStr = "Request was interrupted (Status=0). " +
783  "Likely this means the server crashed (or the desktop window making the request was closed), " +
784  " in the middle of a request. " +
785  "\n(It also could mean 'potential security risk' like a cross-domain request) ";
786  //return;
787  }
788  else //bad address response
789  {
790 
791  errStr = "Request Failed (code: " + req.status + ") - Bad Address:\n" + requestURL;
792 
793  if((ignoreSystemBlock || (DesktopContent._blockSystemCheckMailbox &&
794  DesktopContent._blockSystemCheckMailbox.innerHTML == "")) && //make sure system is alive
795  DesktopContent._needToLoginMailbox) //if login mailbox is valid, force login
796  DesktopContent._needToLoginMailbox.innerHTML = "1"; //force to login screen on server failure
797 
798  //handle multiple failed handlers
799  var found = false;
800  if(DesktopContent._arrayOfFailedHandlers.length < 2) //only give pop up behavior for first 2 failures (then go quiet)
801  {
802  for(var rh in DesktopContent._arrayOfFailedHandlers)
803  if(DesktopContent._arrayOfFailedHandlers[rh] == returnHandler)
804  {
805  errStr = "Blocking multiple error responses to same handle. \nPoor error handling (Developer should fix) by returnHandler: " + returnHandler;
806  Debug.log(errStr.substr(0,200) + "...",Debug.HIGH_PRIORITY);
807  found = true; break;
808  }
809  }
810  else
811  {
812  errStr = "Quiet Mode. Blocking multiple error responses to ALL handles. \nPoor error handling (Developer should fix) by returnHandler: " + returnHandler;
813  Debug.log(errStr.substr(0,200) + "...",Debug.HIGH_PRIORITY);
814  found = true;
815  }
816 
817  if(!found) DesktopContent._arrayOfFailedHandlers.push(returnHandler);
818  if(found) return; //do not call handler for failed server for user code multiple times..
819  }
820 
821  //if not calling handler on error, then get and display errors for user
822  var errArr = (callHandlerOnErr || !req.responseXML)?[]:DesktopContent.getXMLRequestErrors(req);
823  if(errArr.length && !callHandlerOnErr)
824  {
825  for(var i=0;i<errArr.length;++i)
826  {
827  errStr += (i?"\n\n":"") + errArr[i];
828 
829  console.log("Initial request location: \n" + callerLocation);
830  Debug.log("Error: " + errArr[i],
831  (ignoreSystemBlock || requestURL.indexOf("TooltipRequest?") >= 0)?
832  Debug.LOW_PRIORITY: //do not alert if tooltip (auto request) - problematic when not logged-in and causing unnecessary alerts
833  Debug.HIGH_PRIORITY);
834  }
835  }
836  else if(errStr != "")
837  {
838  errStr += "\n\n(Try refreshing the page, or alert ots admins if problem persists.)";
839 
840  console.log("Initial request location: \n" + callerLocation);
841  Debug.log("Error: " + errStr,
842  (callHandlerOnErr ||
843  ignoreSystemBlock ||
844  requestURL.indexOf("TooltipRequest?") >= 0)?
845  Debug.LOW_PRIORITY: //do not alert if tooltip (auto request) - problematic when not logged-in and causing unnecessary alerts
846  Debug.HIGH_PRIORITY);
847  //alert(errStr);
848  req = 0; //force to 0 to indicate error
849  }
850 
851  //success, call return handler
852  if(returnHandler && (errStr=="" || callHandlerOnErr))
853  {
854  returnHandler(req, reqParam, errStr);
855 
856  //RAR commented out.. not sure if it is working as intended (weird desktop behavior is occurring during disconnects)
857  // if(errStr=="" && DesktopContent._arrayOfFailedHandlers.length)
858  // {
859  // //since we had success, search through failed handler and remove if there
860  // for(var i = 0; i<DesktopContent._arrayOfFailedHandlers.length; ++i)
861  // if(DesktopContent._arrayOfFailedHandlers[i] == returnHandler)
862  // {
863  // DesktopContent._arrayOfFailedHandlers.splice(i,1); //remove that handler
864  // break;
865  // }
866  // }
867  }
868 
869  }
870  }
871 
872  if(!sequence)
873  {
874  if(!DesktopContent._cookieCodeMailbox) //attempt to fix (e.g. for Desktop)
875  DesktopContent._cookieCodeMailbox = document.getElementById("DesktopContent-cookieCodeMailbox");
876  var cc = DesktopContent._cookieCodeMailbox?DesktopContent._cookieCodeMailbox.innerHTML:""; //get cookie code from mailbox if available
877  data = "CookieCode="+cc+((data===undefined)?"":("&"+data));
878  }
879  else
880  {
881  data = "sequence="+sequence+"&"+((data===undefined)?"":("&"+data));
882  }
883 
884 
885  var urn = DesktopContent._localUrnLid;
886  var origin = DesktopContent._localOrigin;
887 
888  if(!urn || targetSupervisor) //desktop supervisor, instead of local application
889  {
890  urn = DesktopContent._serverUrnLid;
891  origin = DesktopContent._serverOrigin;
892  }
893 
894 
895  if(!doNotShowLoadingOverlay)
896  DesktopContent.showLoading();
897 
898 
899  requestURL = origin+"/urn:xdaq-application:lid="+urn+"/"+requestURL;
900  //Debug.log("Post " + requestURL + "\n\tData: " + data);
901  req.open("POST",requestURL,true);
902  req.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
903  req.send(data);
904 } // end XMLHttpRequest()
905 
906 //check cookie code race conditions
907 DesktopContent.checkCookieCodeRace = function() {
908  //Debug.log("Checking cookie race conditions");
909  if(parseInt(DesktopContent._updateTimeMailbox.innerHTML) < DesktopContent._lastCookieTime) //then current code is newer
910  {
911  Debug.log("Cookie race occured!");
912 
913  DesktopContent._updateTimeMailbox.innerHTML = DesktopContent._lastCookieTime;
914  DesktopContent._cookieCodeMailbox.innerHTML = DesktopContent._lastCookieCode;
915  }
916 }
917 
918 //=====================================================================================
919 //returns an array of error strings from xml request response
920 DesktopContent.getXMLRequestErrors = function(req) {
921  //make sure to give an error if the response is bad
922  if(!req || !req.responseXML)
923  return ["Unknown error occured " +
924  "(XML response may have been illegal)!"];
925 
926  var errNodes = DesktopContent.getXMLChildren(req,"Error");
927  var errArr = [];
928  for(var i=0;i<errNodes.length;++i)
929  errArr.push(errNodes[i].getAttribute("value"));
930  return errArr;
931 } //end getXMLRequestErrors()
932 
933 //=====================================================================================
934 //returns xml entry value for an attribute
935 DesktopContent.getXMLAttributeValue = function(req, name, attribute) {
936  var el;
937  if(el = DesktopContent.getXMLNode(req,name))
938  return el.getAttribute(attribute);
939  else if(name == "Error" && //make sure Error gives an error if the response is bad
940  (!req || !req.responseXML))
941  return "Unknown error occured " +
942  "(XML response may have been illegal)!";
943  else
944  return undefined;
945 }
946 
947 //=====================================================================================
948 //returns xml entry value for attribue 'value'
949 // if !name assume req is xml node already
950 DesktopContent.getXMLValue = function(req, name) {
951  if(!name)
952  return req.getAttribute("value");
953  return DesktopContent.getXMLAttributeValue(req,name,"value");
954 }
955 
956 //=====================================================================================
957 //returns array of xml children nodes
958 // with tags that match nodeName
959 DesktopContent.getXMLChildren = function(req, nodeName) {
960 
961  if(req && req.responseXML) //to allow for arbitrary starting xml node
962  req = req.responseXML;
963  return req.getElementsByTagName(nodeName);
964 }
965 
966 //=====================================================================================
967 //returns xml entry node (first node with name)
968 // Note: could be any depth (not just depth 1)
969 // ...uses getElementsByTagName(name)
970 DesktopContent.getXMLNode = function(req, name) {
971  var els;
972  if(req && req.responseXML) //to allow for arbitrary starting xml node
973  req = req.responseXML;
974  if(req)
975  {
976  //find DATA
977  var i;
978  els = req.getElementsByTagName(name);//req.responseXML.childNodes[0].childNodes;
979  if(els.length)
980  return els[0];
981  //reverted to former way
982 
983  //for depth 1 sometime?
984  // for(var i=0;i<els.length;++i)
985  // if(els[i].nodeName == "DATA")
986  // {
987  // els = req.responseXML.childNodes[0].childNodes[i].childNodes;
988  //
989  // for(i=0;i<els.length;++i)
990  // if(els[i].nodeName == name)
991  // return els[i];
992  // break;
993  // }
994  }
995 
996  return undefined;
997 }
998 
999 //=====================================================================================
1000 //returns xml entry node (first node with name DATA)
1001 DesktopContent.getXMLDataNode = function(req, name) {
1002  return DesktopContent.getXMLNode("DATA");
1003 }
1004 
1005 //=====================================================================================
1006 //tooltip ~~
1007 // use uid to determine if tip should still be displayed
1008 // - ask server about user/file/function/id combo
1009 // - if shouldShow:
1010 // then show
1011 // add checkbox to never show again
1012 // id of "ALWAYS".. disables never show handling (no checkboxes)
1013 
1014 DesktopContent.tooltipConditionString = function(str) {
1015  return str.replace(/<INDENT>/g,
1016  "<div style='margin-left:60px;'>").replace(/<\/INDENT>/g,
1017  "</div>");
1018 }
1019 
1020 DesktopContent.tooltip = function(id,tip) {
1021 
1022  if(typeof Desktop !== 'undefined') //This call is from Desktop page.. so can use it
1023  {
1024  DesktopContent._serverUrnLid = urnLid;
1025  DesktopContent._serverOrigin = "";
1026 
1027  DesktopContent._sequence = DesktopContent.getDesktopParameter(0,"code");
1028  if(!DesktopContent._sequence || DesktopContent._sequence == "")
1029  DesktopContent._sequence = 0; //normal desktop mode
1030  else
1031  Debug.log("In Wizard Mode with Sequence=" + DesktopContent._sequence);
1032  }
1033 
1034 
1035  var srcStackString,srcFunc,srcFile;
1036 
1037  if(Debug.BROWSER_TYPE == 1) //chrome
1038  {
1039  srcStackString = (new Error).stack.split("\n")[2];
1040  srcFunc = srcStackString.trim().split(' ')[1];
1041  }
1042  else if(Debug.BROWSER_TYPE == 2) //firefox
1043  {
1044  srcStackString = (new Error).stack.split("\n")[1];
1045  srcFunc = srcStackString.trim().split('@')[0];
1046  }
1047 
1048  srcFile = srcStackString.substr(srcStackString.lastIndexOf('/')+1);
1049  if(srcFile.indexOf('?') >= 0)
1050  srcFile = srcFile.substr(0,srcFile.indexOf('?'));
1051  if(srcFile.indexOf(':') >= 0)
1052  srcFile.substr(0,srcFile.indexOf(':'));
1053 
1054 
1055  if(tip === undefined)
1056  {
1057  Debug.log("Undefined tooltip string at " + srcStackString + "\n" +
1058  srcFunc + "\n" + srcFile +".\n\n Tooltip Usage: <id> <tip>", Debug.HIGH_PRIORITY);
1059  return;
1060  }
1061 
1062 
1063  var oldId = id;
1064  //remove all special characters from ID
1065  id = "";
1066  for(var i=0;i<oldId.length;++i)
1067  if((oldId[i] >= 'a' && oldId[i] <= 'z') ||
1068  (oldId[i] >= 'A' && oldId[i] <= 'Z') ||
1069  (oldId[i] >= '0' && oldId[i] <= '9'))
1070  id += oldId[i];
1071 
1072  DesktopContent.XMLHttpRequest(
1073  "TooltipRequest?RequestType=check" +
1074  "&srcFunc=" + srcFunc +
1075  "&srcFile=" + srcFile +
1076  "&srcId=" + id
1077  ,""
1078  , function(req) {
1079 
1080  var showTooltip = DesktopContent.getXMLValue(req,"ShowTooltip");
1081  //Debug.log("showTooltip: " + showTooltip);
1082 
1083  if(showTooltip|0)
1084  {
1085  var str = "";
1086 
1087  //add checkbox
1088  if(id != "ALWAYS")
1089  {
1090  str += "<input type='checkbox' " +
1091  "id='DesktopContent-tooltip-SetNeverShowCheckbox-above-" +
1092  id + "' " +
1093  "onclick='" +
1094  "DesktopContent.tooltipSetAlwaysShow(\"" +
1095  srcFunc + "\",\"" +
1096  srcFile + "\",\"" +
1097  id + "\", this.checked);" + "'>";
1098  str += " ";
1099  str += "<a onclick='" +
1100  "var el = document.getElementById(\"" +
1101  "DesktopContent-tooltip-SetNeverShowCheckbox-above-" +
1102  id + "\");" +
1103  "el.checked = !el.checked;" +
1104  "DesktopContent.tooltipSetAlwaysShow(\"" +
1105  srcFunc + "\",\"" +
1106  srcFile + "\",\"" +
1107  id + "\", el.checked);" +
1108  "'>";
1109  str += "Never show the Tooltip below, or...";
1110  str += "</a>";
1111  str +="</input>";
1112 
1113  //snooze button
1114  str += "<br>"
1115  str += "<input type='checkbox' " +
1116  "id='DesktopContent-tooltip-SetNeverShowCheckbox-hour-" +
1117  id + "' " +
1118  "onclick='" +
1119  "DesktopContent.tooltipSetAlwaysShow(\"" +
1120  srcFunc + "\",\"" +
1121  srcFile + "\",\"" +
1122  id + "\", 0 /*neverShow*/, this.checked);" + "'>";
1123  str += " ";
1124  str += "<a onclick='" +
1125  "var el = document.getElementById(\"" +
1126  "DesktopContent-tooltip-SetNeverShowCheckbox-hour-" +
1127  id + "\");" +
1128  "el.checked = !el.checked;" +
1129  "DesktopContent.tooltipSetAlwaysShow(\"" +
1130  srcFunc + "\",\"" +
1131  srcFile + "\",\"" +
1132  id + "\", 0 /*neverShow*/, el.checked);" +
1133  "'>";
1134  str += "Silence this Tooltip for a week (can be reset in Settings):";
1135  str += "</a>";
1136  str +="</input>";
1137  }
1138 
1139  //add title
1140  if(id != "ALWAYS")
1141  {
1142  str += "<br><br>";
1143  str += "<center><b>'" + oldId + "' Tooltip</b></center><br>";
1144  }
1145  else
1146  str += "<br><br>";
1147 
1148  str += DesktopContent.tooltipConditionString(tip);
1149 
1150  str += "<br><br>";
1151 
1152  //add checkbox
1153  if(id != "ALWAYS")
1154  {
1155  str += "<input type='checkbox' " +
1156  "id='DesktopContent-tooltip-SetNeverShowCheckbox-below-" +
1157  id + "' " +
1158  "onclick='" +
1159  "DesktopContent.tooltipSetAlwaysShow(\"" +
1160  srcFunc + "\",\"" +
1161  srcFile + "\",\"" +
1162  id + "\", this.checked);" + "'>";
1163  str += " ";
1164  str += "<a onclick='" +
1165  "var el = document.getElementById(\"" +
1166  "DesktopContent-tooltip-SetNeverShowCheckbox-below-" +
1167  id + "\");" +
1168  "el.checked = !el.checked;" +
1169  "DesktopContent.tooltipSetAlwaysShow(\"" +
1170  srcFunc + "\",\"" +
1171  srcFile + "\",\"" +
1172  id + "\", el.checked);" +
1173  "'>";
1174  str += "Never show the Tooltip above.";
1175  str += "</a>";
1176  str +="</input>";
1177  }
1178 
1179  Debug.log("srcStackString " + srcStackString);
1180  Debug.log(str,Debug.TIP_PRIORITY);
1181  }
1182  },0,0,0,true,true); //show loading, and target supervisor
1183 
1184 }
1185 
1186 //=====================================================================================
1187 //setSecurityOne
1188 // make server request to enable random security sequence for URL
1189 DesktopContent.setSecurityOn = function(on) {
1190  console.log("Reached");
1191  DesktopContent.XMLHttpRequest(
1192  "ToggleSecurityCodeGeneration?RequestType=TurnGenerationOn" +
1193  "&srcFunc=0"
1194  ,""
1195  ,DesktopContent.toggleSecurityCodeGenerationHandler
1196  ,0,0,0,true,true);
1197  }
1198 
1199 //=====================================================================================
1200 //toggleSecurityCodeGenerationHandler ~~
1201 DesktopContent.toggleSecurityCodeGenerationHandler = function(req) {
1202  var status = DesktopContent.getXMLValue(req,"Status");
1203  Debug.log("Status: " + status);
1204  if (status == "Generation_Success") {
1205  Debug.log("Successfully switched to using authentication sequence!");
1206  Debug.closeErrorPop();
1207  Debug.log("If you wish to return to the default security generation, you can use the 'Reset User Information' in the " +
1208  "'Edit User Data' app.");
1209  Debug.log("Plase refer to the console for the new link!", Debug.INFO_PRIORITY);
1210  }
1211 }
1212 
1213 //=====================================================================================
1214 //tooltipSetNeverShow ~~
1215 // set value of never show for target tip to 1/0 based on alwaysShow
1216 DesktopContent.tooltipSetAlwaysShow = function(srcFunc,srcFile,id,neverShow,temporarySilence) {
1217  Debug.log("neverShow = " + neverShow + " tempSilence = " + temporarySilence);
1218 
1219  if(temporarySilence)
1220  neverShow = false; //force temporary to have priority
1221  DesktopContent.XMLHttpRequest(
1222  "TooltipRequest?RequestType=setNeverShow" +
1223  "&srcFunc=" + srcFunc +
1224  "&srcFile=" + srcFile +
1225  "&srcId=" + id +
1226  "&doNeverShow=" + (neverShow?1:0) +
1227  "&temporarySilence=" + (temporarySilence?1:0)
1228  ,""
1229  ,0,0,0,0,true,true); //show loading, and target supervisor
1230 
1231  if(temporarySilence) return;
1232 
1233  //make sure all checkboxes mirror choice
1234  document.getElementById("DesktopContent-tooltip-SetNeverShowCheckbox-below-" +
1235  id).checked = neverShow;
1236  document.getElementById("DesktopContent-tooltip-SetNeverShowCheckbox-above-" +
1237  id).checked = neverShow;
1238 } //end DesktopContent.tooltipSetAlwaysShow
1239 
1240 //=====================================================================================
1241 //popUpVerification ~~
1242 // asks user if sure
1243 // replace REPLACE in prompt with value passed as val (e.g. pass document.getElementById("myElementId").value)
1244 // call func (if exists) when user selects "Yes"
1245 //
1246 // Can change background color and text color with strings bgColor and textColor (e.g. "rgb(255,0,0)" or "red")
1247 // Default is yellow bg with black text if nothing passed.
1248 DesktopContent.popUpVerification = function(prompt, func, val, bgColor, textColor, borderColor, getUserInput,
1249  dialogWidth, cancelFunc, yesButtonText) {
1250 
1251  // Debug.log("X: " + DesktopContent._mouseOverXmailbox.innerHTML +
1252  // " Y: " + DesktopContent._mouseOverYmailbox.innerHTML +
1253  // " W: " + DesktopContent.getWindowWidth() +
1254  // " H: " + DesktopContent.getWindowHeight());
1255 
1256 
1257  //remove pop up if already exist
1258  if(DesktopContent._verifyPopUp)
1259  DesktopContent._verifyPopUp.parentNode.removeChild(DesktopContent._verifyPopUp);
1260 
1261  //replace REPLACE with val
1262  if(val != undefined)
1263  prompt = prompt.replace(/REPLACE/g, val);
1264 
1265 
1266  //create popup and add to body
1267 
1268 
1269  //setup style first
1270  if(!bgColor) bgColor = "rgb(255,241,189)"; //set default
1271  if(!textColor) textColor = "black"; //set default
1272  if(!borderColor) borderColor = "black";
1273  if(!dialogWidth) dialogWidth = 200;
1274 
1275  var css = "";
1276  //pop up div style
1277  //note: z-index of 2000 is above config gui treeview
1278  css += "#" + DesktopContent._verifyPopUpId + " " +
1279  "{position: absolute; z-index: 2000; border-radius: 5px; padding: 10px;" +
1280  "background-color: " + bgColor + "; border: 2px solid " + borderColor + ";" +
1281  "color: " + textColor + ";text-align: center; overflow: auto;" +
1282  "}\n\n";
1283  //pop up text style
1284  css += "#" + DesktopContent._verifyPopUpId + "-text " +
1285  "{" +
1286  "color: " + textColor + ";width: " + dialogWidth + "px; padding-bottom: 10px;" +
1287  "}\n\n";
1288  //..and anything in the text div
1289  css += "#" + DesktopContent._verifyPopUpId + " *" +
1290  "{" +
1291  "color: " + textColor + ";" +
1292  "}\n\n";
1293 
1294  //add style element to HEAD tag
1295  var style = document.createElement('style');
1296 
1297  if (style.styleSheet) {
1298  style.styleSheet.cssText = css;
1299  } else {
1300  style.appendChild(document.createTextNode(css));
1301  }
1302 
1303  document.getElementsByTagName('head')[0].appendChild(style);
1304 
1305 
1306  var body = document.getElementsByTagName("BODY")[0];
1307 
1308  var el = document.createElement("div");
1309  el.setAttribute("id", DesktopContent._verifyPopUpId);
1310 
1311  var userInputStr = "";
1312  if(getUserInput)
1313  userInputStr +=
1314  "<input type='text' id='DesktopContent_popUpUserInput' " +
1315  "onclick='event.stopPropagation(); '" +
1316  ">";
1317 
1318  var str = "<div id='" + DesktopContent._verifyPopUpId + "-text'>" +
1319  prompt + "<br>" + userInputStr + "</div>" +
1320  "<input type='submit' value='" +
1321  (yesButtonText?yesButtonText:"Yes") +
1322  "' " +
1323  "onclick='event.stopPropagation();' " +
1324  "> " + //onmouseup added below so func can be a function object (and not a string)
1325  "&nbsp;&nbsp;&nbsp;" +
1326  "<input type='submit' " +
1327  "onclick='event.stopPropagation();' " +
1328  "value='Cancel'>";
1329  el.innerHTML = str;
1330 
1331  //onmouseup for "Yes" button
1332  el.getElementsByTagName('input')[0 + (getUserInput?1:0)].onmouseup =
1333  function(event){event.stopPropagation(); DesktopContent.clearPopUpVerification(func);};
1334  //onmouseup for "Cancel" button
1335  el.getElementsByTagName('input')[1 + (getUserInput?1:0)].onmouseup =
1336  function(event){event.stopPropagation(); DesktopContent.clearPopUpVerification(cancelFunc);};
1337 
1338 
1339  Debug.log(prompt);
1340  DesktopContent._verifyPopUp = el;
1341  el.style.left = "-1000px"; //set off page so actual dimensions can be determined, and then div relocated
1342  body.appendChild(el);
1343 
1344 
1345  if(getUserInput) //place cursor
1346  {
1347  el.getElementsByTagName('input')[0].focus();
1348  el.getElementsByTagName('input')[0].setSelectionRange(0,0);
1349 
1350  //accept enter to close
1351  el.getElementsByTagName('input')[0].onkeydown =
1352  function(event)
1353  {
1354  if(event.keyCode == 13) // ENTER
1355  {
1356  Debug.log("Accepting enter key");
1357  event.preventDefault();
1358  event.stopPropagation();
1359  DesktopContent.clearPopUpVerification(func);
1360  }
1361  else if(event.keyCode == 27) // ESC
1362  {
1363  Debug.log("Accepting escape key");
1364  event.preventDefault();
1365  event.stopPropagation();
1366  DesktopContent.clearPopUpVerification(cancelFunc);
1367  }
1368  }; //end keydown handler
1369  }
1370  else //focus on button, since no text
1371  el.getElementsByTagName('input')[0].focus();
1372 
1373  //add key handler to body too for enter & esc
1374  el.onkeydown =
1375  function(event)
1376  {
1377  if(event.keyCode == 13) // ENTER
1378  {
1379  Debug.log("Accepting enter key");
1380  event.preventDefault();
1381  event.stopPropagation();
1382  DesktopContent.clearPopUpVerification(func);
1383  }
1384  else if(event.keyCode == 27) // ESC
1385  {
1386  Debug.log("Accepting escape key");
1387  event.preventDefault();
1388  event.stopPropagation();
1389  DesktopContent.clearPopUpVerification(cancelFunc);
1390  }
1391  }; //end keydown handler
1392 
1393  //determine position
1394  var w = el.offsetWidth;
1395  var h = el.offsetHeight;
1396  var x = DesktopContent.getMouseX();
1397  var y = DesktopContent.getMouseY();
1398  x -= w/2; //center on x, but try to avoid having mouse lineup with buttons to avoid accidental double click by user
1399  Debug.log("X: " + x +
1400  " Y: " + y +
1401  " W: " + w +
1402  " H: " + h);
1403 
1404  while(x+w > DesktopContent.getWindowWidth())
1405  x -= w;
1406  if(y > DesktopContent.getWindowHeight()/2 + h/2)
1407  y -= h; //move to top half of screen
1408  while(y+h > DesktopContent.getWindowHeight())
1409  y -= h;
1410 
1411  if(x <= 0) x = 10;
1412  if(y <= 0) y = 10;
1413 
1414  Debug.log("X: " + x +
1415  " Y: " + y +
1416  " W: " + w +
1417  " H: " + h);
1418  //var
1419  el.style.left = (DesktopContent.getWindowScrollLeft() + x) + "px";
1420  el.style.top = (DesktopContent.getWindowScrollTop() + y) + "px";
1421 } //end popUpVerification()
1422 //=====================================================================================
1423 //clearPopUpVerification ~~
1424 // call func after clearing, if exists
1425 DesktopContent.clearPopUpVerification = function(func) {
1426 
1427  //get parameter value if exists
1428 
1429  var userEl = document.getElementById("DesktopContent_popUpUserInput");
1430  var param = userEl?userEl.value:undefined;
1431 
1432  //remove pop up if already exist
1433  if(DesktopContent._verifyPopUp) DesktopContent._verifyPopUp.parentNode.removeChild(DesktopContent._verifyPopUp);
1434  DesktopContent._verifyPopUp = 0;
1435 
1436  if(func)
1437  func(param); //return user input value if present
1438 } //end clearPopUpVerification()
1439 
1440 
1441 //=====================================================================================
1442 //setPopUpPosition ~~
1443 // centers element based on width and height constraint
1444 //
1445 // Note: assumes a padding and border size if not specified
1446 // Note: if w,h not specified then fills screen (minus margin)
1447 // Note: offsetUp and can be used to position the popup vertically (for example if the dialog is expected to grow, then give positive offsetUp to compensate)
1448 //
1449 // Note: the input element el will need local styling, e.g.:
1450 // #popUpDialog * {
1451 // color: black;
1452 // }
1453 // #popUpDialog a {
1454 // color: rgb(44, 44, 187);
1455 // font-size: 13px;
1456 // }
1457 DesktopContent.setPopUpPosition = function(el,w,h,padding,border,
1458  margin,doNotResize,offsetUp) {
1459 
1460  Debug.log("DesktopContent.setPopUpPosition");
1461 
1462  if(padding === undefined) padding = 10;
1463  if(border === undefined) border = 1;
1464  if(margin === undefined) margin = 0;
1465 
1466  var x,y;
1467 
1468  //:::::::::::::::::::::::::::::::::::::::::
1469  //popupResize ~~
1470  // set position and size
1471  DesktopContent.setPopUpPosition.stopPropagation = function(event) {
1472  //Debug.log("DesktopContent.setPopUpPosition stop propagation");
1473  event.stopPropagation();
1474  }
1475 
1476  //:::::::::::::::::::::::::::::::::::::::::
1477  //popupResize ~~
1478  // set position and size
1479  DesktopContent.setPopUpPosition.popupResize = function() {
1480 
1481  try //check if element still exists
1482  {
1483  if(!el) //if element no longer exists.. then remove listener and exit
1484  {
1485  window.removeEventListener("resize",DesktopContent.setPopUpPosition.popupResize);
1486  window.removeEventListener("scroll",DesktopContent.setPopUpPosition.popupResize);
1487  return;
1488  }
1489  }
1490  catch(err) {return;} //do nothing on errors
1491 
1492  //else resize el
1493  //Debug.log("DesktopContent.setPopUpPosition.popupResize");
1494 
1495 
1496  var ww = DesktopContent.getWindowWidth()-(padding+border)*2;
1497  var wh = DesktopContent.getWindowHeight()-(padding+border)*2;
1498 
1499  //ww & wh are max window size at this point
1500 
1501  var ah = el.offsetHeight;//actual height, in case of adjustments
1502 
1503  if(w === undefined || h === undefined)
1504  {
1505  w = ww - (margin)*2;
1506  h = wh - (margin)*2;
1507  }
1508  //else w,h are inputs and margin is ignored
1509 
1510  x = (DesktopContent.getWindowScrollLeft() + ((ww-w)/2));
1511  y = (DesktopContent.getWindowScrollTop() + ((wh-h)/2)) - (offsetUp|0) - 100; //bias up (looks nicer)
1512 
1513  if(y < DesktopContent.getWindowScrollTop() +
1514  margin + padding)
1515  y = DesktopContent.getWindowScrollTop() + margin +
1516  padding; //don't let it bottom out though
1517 
1518  //if dialog is smaller than window, allow scrolling to see the whole thing
1519  if(w > ww-margin-padding)
1520  x = -DesktopContent.getWindowScrollLeft();
1521  if(ah > wh-margin-padding)
1522  y = -DesktopContent.getWindowScrollTop();
1523 
1524  el.style.left = x + "px";
1525  el.style.top = y + "px";
1526  };
1527  DesktopContent.setPopUpPosition.popupResize();
1528 
1529  //window width and height are not manipulated on resize, only setup once
1530  el.style.width = w + "px";
1531  el.style.height = h + "px";
1532 
1533 
1534  //#popUpDialog {
1535  // position: absolute;
1536  // z-index: 10000;
1537  // border: 1px solid #770000;
1538  // background-color: #efeaea;
1539  // text-align: center;
1540  // padding: 10px;
1541  // color: black;
1542  //}
1543  el.style.position = "absolute";
1544  el.style.zIndex = "10000";
1545  el.style.border = "1px solid #770000";
1546  el.style.backgroundColor = "#efeaea";
1547  el.style.textAlign = "center";
1548  el.style.padding = "10px";
1549  el.style.color = "black";
1550 
1551  if(!doNotResize)
1552  {
1553  window.addEventListener("resize",DesktopContent.setPopUpPosition.popupResize);
1554  window.addEventListener("scroll",DesktopContent.setPopUpPosition.popupResize);
1555  }
1556  el.addEventListener("keydown",DesktopContent.setPopUpPosition.stopPropagation);
1557  el.addEventListener("mousemove",DesktopContent.setPopUpPosition.stopPropagation);
1558  el.addEventListener("mousemove",DesktopContent.mouseMove);
1559 
1560  el.style.overflow = "auto";
1561 
1562  return {"w" : w, "h" : h, "x" : x, "y" : y};
1563 
1564 } //end setPopUpPosition()
1565 
1566 //=====================================================================================
1567 //parseColor ~~
1568 DesktopContent.parseColor = function(colorStr) {
1569  //used to ignore the alpha in the color when returning to user
1570 
1571  //in general need to create an element.. but since all the color strings are rgb or rgba from settings, can simplify
1572  var m = colorStr.split("(")[1].split(")")[0].split(",");
1573  if( m) return "rgb("+m[0]+","+m[1]+","+m[2]+")";
1574  else throw new Error("Color "+colorStr+" could not be parsed.");
1575 }
1576 
1577 //=====================================================================================
1578 //getColorAsRGBA ~~
1579 // http://stackoverflow.com/questions/11068240/what-is-the-most-efficient-way-to-parse-a-css-color-in-javascript
1580 // except the solution is broken.. unless you add element to page
1581 DesktopContent.getColorAsRGBA = function(colorStr) {
1582 
1583  //in general need to create an element..
1584  var div = document.createElement('div');
1585  var m;
1586 
1587  div.style.color = colorStr;
1588  div.style.display = "none";
1589  document.body.appendChild(div);
1590 
1591  m = getComputedStyle(div).color.split("(")[1].split(")")[0].split(",");
1592 
1593  document.body.removeChild(div);
1594 
1595  if(m && m.length == 3) return "rgba("+m[0]+","+m[1]+","+m[2]+",255)";
1596  else if(m && m.length == 4) return "rgba("+m[0]+","+m[1]+","+m[2]+","+m[3]+")";
1597  else throw new Error("Color "+colorStr+" could not be parsed.");
1598 }
1599 
1600 
1601 //=====================================================================================
1602 //get window and mouse info ~~
1603 DesktopContent.getWindowWidth = function() { return window.innerWidth; }
1604 DesktopContent.getWindowHeight = function() { return window.innerHeight; }
1605 DesktopContent.getBodyWidth = function() { return document.body.offsetWidth; }
1606 DesktopContent.getBodyHeight = function() { return document.body.offsetHeight; }
1607 DesktopContent.getWindowScrollLeft = function() { return document.documentElement.scrollLeft || document.body.scrollLeft || 0; }
1608 DesktopContent.getWindowScrollTop = function() { return document.documentElement.scrollTop || document.body.scrollTop || 0; }
1609 DesktopContent.getMouseX = function() { return DesktopContent._windowMouseX | 0; } //force to int
1610 DesktopContent.getMouseY = function() { return DesktopContent._windowMouseY | 0; } //force to int
1611 DesktopContent.getDefaultWindowColor = function() {
1612  //return the alpha mix of window color and desktop color
1613  if(!DesktopContent._windowColorPostbox || !DesktopContent._desktopColor)
1614  {
1615  //likely in wizard mode
1616  Debug.log("Color post boxes not setup! So giving default.",Debug.MED_PRIORITY);
1617  return "rgb(178,210,240)";
1618  }
1619 
1620  wrgba = DesktopContent._windowColorPostbox.innerHTML.split("(")[1].split(")")[0].split(",");
1621  drgb = DesktopContent._desktopColor.split("(")[1].split(")")[0].split(",");
1622  for(var i in drgb)
1623  drgb[i] = (drgb[i]*(1-wrgba[3]) + wrgba[i]*wrgba[3])|0; //floor of blend
1624  return "rgb("+drgb[0]+","+drgb[1]+","+drgb[2]+")";
1625 }
1626 
1627 //=====================================================================================
1628 //get color scheme ~~
1629 DesktopContent.getDefaultDashboardColor = function() { return DesktopContent.parseColor(DesktopContent._dashboardColorPostbox.innerHTML); }
1630 DesktopContent.getDefaultDesktopColor = function() {
1631  if(!DesktopContent._desktopColor)
1632  {
1633  //likely in wizard mode
1634  Debug.log("Color post boxes not setup! So giving default.",Debug.MED_PRIORITY);
1635  return "rgb(15,34,105)";
1636  }
1637  return DesktopContent._desktopColor;
1638 }
1639 
1640 //=====================================================================================
1641 //getUsername ~~
1642 DesktopContent.getUsername = function() {
1643  var dispName = DesktopContent._theWindow.parent.document.getElementById("DesktopDashboard-user-displayName").innerHTML
1644  return dispName.substr(dispName.indexOf(",")+2);
1645 }
1646 
1647 
1648 //=====================================================================================
1649 //openNewWindow ~~
1650 // first wait for mailbox to be clear
1651 // then take mailbox
1652 DesktopContent.openNewWindow = function(name,subname,windowPath,unique,completeHandler) {
1653 
1654  Debug.log("DesktopContent.openNewWindow= " + windowPath);
1655  Debug.log("name= " + name);
1656  Debug.log("subname= " + subname);
1657  Debug.log("unique= " + unique);
1658 
1659  //extract params from DesktopContent._openWindowMailbox
1660  //get parameters
1661  var paramsStr = DesktopContent._openWindowMailbox.innerHTML;
1662 
1663 
1664  var tryAgainCount = 0;
1665 
1666 
1667  if(paramsStr != "") //then wait
1668  {
1669  Debug.log("Window creation is busy, trying again soon!");
1670 
1671  ++tryAgainCount;
1672 
1673  if(tryAgainCount > 50)
1674  {
1675  Debug.log("It looks like the window failed to open. Perhaps the Desktop is disconnected from the server; " +
1676  "please reconnect and try again.", Debug.WARN_PRIORITY);
1677  return;
1678  }
1679 
1680  setTimeout(function(){ DesktopContent.openNewWindow(windowPath); }, 100);
1681  return;
1682  }
1683 
1684  //free to attempt to open window!
1685  var str = "requestingWindowId=" + DesktopContent._myDesktopFrame.id.split('-')[1];
1686  str += "&windowName=" + name;
1687  str += "&windowSubname=" + subname;
1688  str += "&windowUnique=" + unique;
1689  str += "&windowPath=" + windowPath;
1690  DesktopContent._openWindowMailbox.innerHTML = str;
1691 
1692  Debug.log("Waiting for complete...");
1693 
1694  tryAgainCount = 0;
1695  var timeoutHandler = function() {
1696  Debug.log("Checking for complete...");
1697 
1698  ++tryAgainCount;
1699 
1700  if(tryAgainCount > 50)
1701  {
1702  Debug.log("It looks like the window failed to open. Perhaps the Desktop is disconnected from the server; " +
1703  "please reconnect and try again.", Debug.WARN_PRIORITY);
1704  return;
1705  }
1706 
1707  //extract params from DesktopContent._openWindowMailbox
1708  //get parameters
1709  var paramsStr = DesktopContent._openWindowMailbox.innerHTML;
1710  var spliti = paramsStr.indexOf('&amp;');
1711  params = [paramsStr.substr(0,spliti),paramsStr.substr(spliti+5)];
1712  var varPair;
1713  var requestingWindowId = "", done = "";
1714  for(var i=0;i<params.length;++i)
1715  {
1716  spliti = params[i].indexOf('=');
1717  varPair = [params[i].substr(0,spliti),params[i].substr(spliti+1)];
1718  if(varPair[0] == "requestingWindowId")
1719  requestingWindowId = varPair[1];
1720  else if(varPair[0] == "done")
1721  done = varPair[1];
1722  }
1723 
1724  if(paramsStr = "" || (requestingWindowId != "" && done != ""))
1725  {
1726  //assume done!
1727  Debug.log("requestingWindowId=" + requestingWindowId);
1728  Debug.log("done=" + done);
1729  if(requestingWindowId != DesktopContent._myDesktopFrame.id.split('-')[1])
1730  Debug.log("There was a mismatch in window id!",Debug.MED_PRIORITY);
1731 
1732  //clear mailbox
1733  DesktopContent._openWindowMailbox.innerHTML = "";
1734 
1735  if(completeHandler)
1736  completeHandler(); //call parameter handler
1737  return;
1738  }
1739  else //try again
1740  setTimeout(timeoutHandler, 100); //try again
1741 
1742  }; //end setTimeout handler
1743 
1744  setTimeout(timeoutHandler,
1745  100); //end setTimeout
1746 
1747 } // end openNewWindow
1748 
1749 //=====================================================================================
1750 //openNewBrowserTab ~~
1751 // first wait for mailbox to be clear
1752 // then take mailbox
1753 //
1754 // Note: to open a window just using the Desktop icon name, leave subname and unique undefined
1755 // window path can optionially be used to send the window additional parameters, or left undefined.
1756 DesktopContent.openNewBrowserTab = function(name,subname,windowPath,unique) {
1757 
1758  if(windowPath !== undefined)
1759  {
1760  //remove leading ? because Desktop.js handling expects no leading ?
1761  if(windowPath[0] == '?')
1762  windowPath = windowPath.substr(1);
1763 
1764  //for windowPath, need to check lid=## is terminated with /
1765  // check from = that there is nothing but numbers
1766  try
1767  {
1768  var i = windowPath.indexOf("urn:xdaq-application:lid=") + ("urn:xdaq-application:lid=").length;
1769  var isAllNumbers = true;
1770  for(i;i<windowPath.length;++i)
1771  {
1772  //Debug.log(windowPath[i]);
1773 
1774  if(windowPath[i] < "0" || windowPath[i] > "9")
1775  {
1776  isAllNumbers = false;
1777  break;
1778  }
1779  }
1780  if(isAllNumbers)
1781  windowPath += "/";
1782  }
1783  catch(e)
1784  {
1785  Debug.log("An error occurred while trying to open the window. " +
1786  "The window path seems to be invalid: " + e, Debug.HIGH_PRIORITY);
1787  return;
1788  }
1789  }
1790  Debug.log("DesktopWindow= " + windowPath);
1791 
1792  Debug.log("name= " + name);
1793  Debug.log("subname= " + subname);
1794  Debug.log("unique= " + unique);
1795 
1796  var search = DesktopContent._theWindow.parent.parent.window.location.search;
1797  url = DesktopContent._theWindow.parent.parent.window.location.pathname;
1798 
1799  var str = "requestingWindowId=" + DesktopContent._myDesktopFrame.id.split('-')[1];
1800  str += "&windowName=" + name;
1801  str += "&windowSubname=" + subname;
1802  str += "&windowUnique=" + unique;
1803  str += "&windowPath=" + windowPath;
1804 
1805  //if there is no search, need to check lid=## is terminated with /
1806  // check from = that there is nothing but numbers
1807 
1808  if(search == "")
1809  {
1810  var i = url.indexOf("urn:xdaq-application:lid=") + ("urn:xdaq-application:lid=").length;
1811  var isAllNumbers = true;
1812  for(i;i<url.length;++i)
1813  {
1814  Debug.log(url[i]);
1815 
1816  if(url[i] < "0" || url[i] > "9")
1817  {
1818  isAllNumbers = false;
1819  break;
1820  }
1821  }
1822  if(isAllNumbers)
1823  url += "/";
1824  url += "?" + str;
1825  }
1826  else
1827  {
1828  //remove, possibly recursive, former new windows through url
1829  var i = search.indexOf("requestingWindowId");
1830  if(i >= 0)
1831  search = search.substr(0,i);
1832  //only add & if there are other parameters
1833  if(search.length && search[search.length-1] != '?'
1834  && search[search.length-1] != '&')
1835  search += '&';
1836  url += search + str;
1837  }
1838 
1839  Debug.log("DesktopContent.openNewBrowserTab= " + url);
1840 
1841  window.open(url,'_blank');
1842 } // end openNewBrowserTab()
1843 
1844 //getDesktopWindowTitle ~~
1845 // returns the text in header of the current desktop window
1846 DesktopContent.getDesktopWindowTitle = function() {
1847  return DesktopContent._theWindow.parent.document.getElementById(
1848  "DesktopWindowHeader-" +
1849  DesktopContent._theWindow.name.split('-')[1]).innerHTML;
1850 }
1851 
1852 
1853 
1854 
1855 
1856 
1857