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