otsdaq_utilities  v2_05_02_indev
SimpleContextMenu.js
1 //=====================================================================================
2 //
3 // Created Nov, 2016
4 // by Ryan Rivera ((rrivera at fnal.gov))
5 //
6 // SimpleContextMenu.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/DesktopContent.js"></script>
14 // <script type="text/JavaScript" src="/WebPath/js/js_lib/SimpleContextMenu.js"></script>
15 //
16 // ...anywhere inside the <head></head> tag of a window content html page
17 // 2. for proper functionality certain handlers are used:
18 // cannot overwrite handlers for window: onfocus, onscroll, onblur, onmousemove
19 // (if you must overwrite, try to call the DesktopContent handlers from your handlers)
20 //
21 // Recommendations:
22 // 1. use Debug to output status and errors, e.g.:
23 // Debug.log("this is my status",Debug.LOW_PRIORITY); //LOW_PRIORITY, MED_PRIORITY, INFO_PRIORITY, WARN_PRIORITY, HIGH_PRIORITY
24 // 2. call window.focus() to bring your window to the front of the Desktop
25 //
26 // The code of Requirement #1 should be inserted in the header of each page that will be
27 // the content of a window in the ots desktop.
28 //
29 // This code handles bringing the window to the front when the content
30 // is clicked or scrolled.
31 //
32 // Example usage: /WebPath/html/SimpleContextMenuTest.html
33 //
34 //=====================================================================================
35 
36 var SimpleContextMenu = SimpleContextMenu || {}; //define SimpleContextMenu namespace
37 
38 if (typeof Debug == 'undefined')
39  alert('ERROR: Debug is undefined! Must include Debug.js before SimpleContextMenu.js');
40 if (typeof Globals == 'undefined')
41  alert('ERROR: Globals is undefined! Must include Globals.js before SimpleContextMenu.js');
42 if (typeof DesktopContent == 'undefined' &&
43  typeof Desktop == 'undefined')
44  alert('ERROR: DesktopContent is undefined! Must include DesktopContent.js before SimpleContextMenu.js');
45 
46 
47 //"public" function list:
48 // SimpleContextMenu.createMenu(menuItems,menuItemHandlers,popupID,topLeftX,topLeftY, primaryColor, secondaryColor, useDefaultHighlightColors)
49 // SimpleContextMenu.createMenuCallAsString(menuItems,menuItemHandlers,popupID,topLeftX,topLeftY, primaryColor, secondaryColor, useDefaultHighlightColors)
50 
51 //"private" function list:
52 // SimpleContextMenu.mouseMoveHandler(event)
53 // SimpleContextMenu.callMenuItemHandler(event,index)
54 // SimpleContextMenu.handleMouseOverMenuItem(event,index)
55 
56 //"private" members:
57 SimpleContextMenu._popUpEl = 0;
58 SimpleContextMenu._menuItemHandlers = [];
59 SimpleContextMenu._primaryColor = "";
60 SimpleContextMenu._secondaryColor = "";
61 
62 SimpleContextMenu._styleEl = 0;
63 
64 //=====================================================================================
65 //SimpleContextMenu.createMenu
66 // if from event, for left and top use, e.g event.pageX-1,event.pageY-1
67 SimpleContextMenu.createMenu = function(menuItems,menuItemHandlers,
68  popupID,topLeftX,topLeftY, primaryColor, secondaryColor, useDefaultHighlightColors)
69 {
70 
71  // Debug.log("Creating SimpleContextMenu...");
72  // Debug.log("menuItems=" + menuItems);
73  // Debug.log("menuItemHandlers=" + menuItemHandlers);
74  // Debug.log("popupID=" + popupID);
75  // Debug.log("topLeftX=" + topLeftX);
76  // Debug.log("topLeftY=" + topLeftY);
77  // Debug.log("primaryColor=" + primaryColor);
78  // Debug.log("secondaryColor=" + secondaryColor);
79 
80  SimpleContextMenu._menuItemHandlers = menuItemHandlers;
81  SimpleContextMenu._primaryColor = primaryColor;
82  SimpleContextMenu._secondaryColor = secondaryColor;
83  SimpleContextMenu._useDefaultHighlightColors = useDefaultHighlightColors;
84 
85  var body = document.getElementsByTagName("BODY")[0];
86  var el = SimpleContextMenu._popUpEl;
87  if(el)
88  {
89  Debug.log("Can not create SimpleContextMenu if one already exists",
90  Debug.MED_PRIORITY);
91  return;
92  }
93 
95  //create the element
96  el = document.createElement("div");
97  el.setAttribute("id", popupID);
98  el.style.display = "none";
99  el.onmousemove = function(e){e.cancelBubble = true;};
100  body.appendChild(el); //add element to body of page
101 
102 
104  //add style for error to page HEAD tag
105  var css = "";
106 
107  css += "#clearDiv {" +
108  "clear: both;" +
109  "}\n\n";
110 
111  //error close link style
112  css += "#" + popupID + "" +
113  "{" +
114  "position:absolute;" +
115  "left:" + topLeftX + "px;" +
116  "top:" + topLeftY + "px;" +
117  "z-index: 1000000;" + //one million!
118  "background-color: " + primaryColor + ";" +
119  //"border: 0px solid " + secondaryColor + ";" +
120  "padding: 8px 0 8px 0;" +
121  "border-radius: 2px;" +
122  "box-shadow: inset rgba(255,254,255,0.6) 0 0 0 /*top-bottom glow*/," +
123  " inset rgba(0,0,0,0.35) 0 0 3px /* inner shadow */, " +
124  " rgb(150,150,150) 0 0 3px /* outer glow */," +
125  " rgb(175,175,175) 0 0 3px /* color border */," +
126  " rgba(0,0,0,0.7) -5px 5px 5px /* drop shadow */; " +
127  "}\n\n";
128  css += "#" + popupID + " div" +
129  "{" +
130  "padding: 0 10px 0 10px;" +
131  "color: " + secondaryColor + ";" +
132  "-webkit-user-select: none;" +
133  "-moz-user-select: none;" +
134  "user-select: none;" +
135  "}\n\n";
136  css += "#" + popupID + " div:hover" +
137  "{" +
138  "background-color: " + (useDefaultHighlightColors?"rgb(91,148,240)":secondaryColor) + ";" +
139  "color: " + (useDefaultHighlightColors?"white":primaryColor) + ";" +
140  "cursor: pointer;" +
141  "}\n\n";
142  css += "#" + popupID + " *" +
143  "{" +
144  "font-size: 14px;" +
145  "font: arial;" +
146  "}\n\n";
147 
148  //add style element to HEAD tag
149  var style = document.createElement('style');
150 
151  if (style.styleSheet) {
152  style.styleSheet.cssText = css;
153  } else {
154  style.appendChild(document.createTextNode(css));
155  }
156 
157  document.getElementsByTagName('head')[0].appendChild(style);
158 
159  SimpleContextMenu._styleEl = style;
160 
161 
163  //add menu items to element
164  var str = "";
165  for(var i=0;i<menuItems.length;++i)
166  {
167  str +=
168  "<div class='SimpleContextMenu-menuItem' " +
169  "id='SimpleContextMenu-menuItem-" + i + "' " +
170  "onmousemove='SimpleContextMenu.handleMouseOverMenuItem(event," + i + ");' " +
171  "onmousedown='event.stopPropagation();' " +
172  "onmouseup='SimpleContextMenu.callMenuItemHandler(event," + i + ");' " +
173  ">" +
174  menuItems[i] +
175  "</div>";
176  str += "<div id='clearDiv'></div>";
177  }
178 
179  el.innerHTML = str;
180  el.style.display = "block";
181 
182  SimpleContextMenu._popUpEl = el;
183 } //end createMenu()
184 
185 //=====================================================================================
186 //SimpleContextMenu.createMenuCallAsString
187 // create string version of call to SimpleContextMenu.createMenu(...)
188 // this string can be put into an event handler string
189 // e.g. "onmousedown='" + createTreeLinkContextMenuString(...) + "'"
190 SimpleContextMenu.createMenuCallAsString = function(menuItems,menuItemHandlers,
191  popupID, primaryColor, secondaryColor, useDefaultHighlightColors) {
192 
193  var str = "";
194  str += "SimpleContextMenu.createMenu([";
195 
196  //output item strings
197  for(j=0;j<menuItems.length;++j)
198  {
199  if(j)
200  str += ",";
201  str += "\"" + menuItems[j] + "\"";
202  }
203 
204  str += "]," +//end items and open array for item handlers
205  "[";
206 
207  for(j=0;j<menuItemHandlers.length;++j)
208  {
209  //Debug.log("menuItemHandlers[j]= " + menuItemHandlers[j]);
210  //need to escape all quotes by one more level
211  menuItemHandlers[j] = menuItemHandlers[j].replace(/\\\"/g, "AAAAA");
212  menuItemHandlers[j] = menuItemHandlers[j].replace(/"/g, "\\\"");
213  menuItemHandlers[j] = menuItemHandlers[j].replace(/AAAAA/g, "\\\\\\\"");
214  //Debug.log("menuItemHandlers[j]= " + menuItemHandlers[j]);
215  //Debug.log("this works= " + "Debug.log(\\\"hi\\\");");
216  //THIS WORKS: treeViewHandlerStr_ += "\"" + "Debug.log(\\\"hi\\\");" + "\"";
217  str += "\"" + menuItemHandlers[j] + "\"";
218  if(j != menuItemHandlers.length-1)
219  str += ",";
220  }
221  str += "]" + //end menuItemHandlers array
222  ",\"" + popupID + "\",event.pageX-1,event.pageY-1, " +
223  "\"" + primaryColor +
224  "\", \"" + secondaryColor +
225  "\", " + (useDefaultHighlightColors?1:0) + ");";
226 
227  return str;
228 } //end createMenuCallAsString()
229 
230 SimpleContextMenu._removePopupTimer = 0;
231 
232 //=====================================================================================
233 //SimpleContextMenu.mouseMoveHandler
234 // subscribe the mouse move handler to DesktopContent.mouseMoveSubscriber
235 // OR if (typeof DesktopContent == 'undefined' then subscribe to Desktop
236 SimpleContextMenu.mouseMoveHandler = function(e)
237 {
238  //Debug.log("moving " + e.pageX + "-" + e.pageY);
239  if(SimpleContextMenu._popUpEl && !SimpleContextMenu._removePopupTimer) //delete popup
240  {
241  //Debug.log("Starting timer to remove SimpleContextMenu");
242  SimpleContextMenu._removePopupTimer = window.setTimeout(
243  function()
244  {
245  SimpleContextMenu._removePopupTimer = 0; //clear timer variable
246 
247  //Debug.log("Removing SimpleContextMenu");
248  SimpleContextMenu._popUpEl.parentNode.removeChild(SimpleContextMenu._popUpEl);
249  SimpleContextMenu._popUpEl = 0;
250 
251  if(SimpleContextMenu._styleEl)
252  {
253  SimpleContextMenu._styleEl.parentNode.removeChild(SimpleContextMenu._styleEl);
254  SimpleContextMenu._styleEl = 0;
255  }
256  }, //end mouse move remove popup handler
257  1000 /*in milliseconds*/);
258  }
259  else if(!SimpleContextMenu._popUpEl) SimpleContextMenu._removePopupTimer = 0; //clear if popup gone
260 } //end mouseMoveHandler
261 //subscribe the mouse move handler (if desktop content or part of actual desktop)
262 if(typeof DesktopContent == 'undefined')
263  Desktop.mouseMoveSubscriber(SimpleContextMenu.mouseMoveHandler);
264 else
265  DesktopContent.mouseMoveSubscriber(SimpleContextMenu.mouseMoveHandler);
266 
267 
268 //=====================================================================================
269 SimpleContextMenu.callMenuItemHandler = function(event,index)
270 {
271  var handler = SimpleContextMenu._menuItemHandlers[index];
272 
273  Debug.log("Removing SimpleContextMenu");
274  SimpleContextMenu._popUpEl.parentNode.removeChild(SimpleContextMenu._popUpEl);
275  SimpleContextMenu._popUpEl = 0;
276 
277  if(SimpleContextMenu._styleEl)
278  {
279  SimpleContextMenu._styleEl.parentNode.removeChild(SimpleContextMenu._styleEl);
280  SimpleContextMenu._styleEl = 0;
281  }
282 
283  event.cancelBubble = true;
284  event.preventDefault();
285  event.stopPropagation();
286 
287  //Debug.log("SimpleContextMenu.callMenuItemHandler " + handler);
288  if(handler && (typeof handler) == "string") //if handler supplied as string
289  {
290  Debug.log("evaluateJS = " + handler);
291  eval(handler);
292  return false;
293  }
294  else //assume it is a function
295  {
296  handler(event, index);
297  return false;
298  }
299 } //end callMenuItemHandler()
300 
301 //=====================================================================================
302 //SimpleContextMenu.handleMouseOverMenuItem
303 SimpleContextMenu.handleMouseOverMenuItem = function(event,index)
304 {
305  event.cancelBubble = true;
306 
307  //kill the popup removal, if user still interested
308  if(SimpleContextMenu._removePopupTimer)
309  {
310  window.clearTimeout(SimpleContextMenu._removePopupTimer);
311  SimpleContextMenu._removePopupTimer = 0;
312  }
313 
314  //Debug.log(index);
315  //set colors properly for mouse over
316 
317  var el;
318  for(var i=0;i<SimpleContextMenu._menuItemHandlers.length;++i)
319  {
320  el = document.getElementById("SimpleContextMenu-menuItem-" + i);
321  if(i == index) //hovered one
322  {
323  el.style.backgroundColor = (SimpleContextMenu._useDefaultHighlightColors?"rgb(91,148,240)":SimpleContextMenu._secondaryColor);
324  el.style.color = (SimpleContextMenu._useDefaultHighlightColors?"white" :SimpleContextMenu._primaryColor);
325  }
326  else
327  {
328  el.style.backgroundColor = SimpleContextMenu._primaryColor;
329  el.style.color = SimpleContextMenu._secondaryColor;
330  }
331  }
332 } //end handleMouseOverMenuItem
333 
334 
335 
336 
337 
338 
339 
340 
341 
342 
343 
344 
345