1 function printProp(x) { |
1 var cm_TheContextMenu; |
2 window.app.debug(x + ":"); |
|
3 for (property in x) { |
|
4 window.chrome.alert(" " + property + ": " + x[property]); |
|
5 } |
|
6 } |
|
7 |
|
8 function historyViewContextEvent(e) { |
|
9 window.chrome.alert("history context: " + e + " " + e.itemIndex + |
|
10 " x=" + e.pos.x + " y=" + e.pos.y); |
|
11 printProp(e); |
|
12 } |
|
13 |
|
14 window.chrome.chromeComplete.connect(chromeLoadComplete); |
|
15 |
|
16 |
|
17 function chromeLoadComplete() { |
|
18 |
|
19 window.snippets.ContextMenuId.externalMouseEvent.connect( |
|
20 function(type, name, description) { |
|
21 |
|
22 if ((name == "QGraphicsSceneMouseReleaseEvent") || (name == "QGraphicsSceneResizeEvent")){ |
|
23 window.snippets.ContextMenuId.hide(); |
|
24 window.snippets.ContextMenuId.dontShow = true; |
|
25 setTimeout ( 'window.snippets.ContextMenuId.dontShow = false', 500 ); // reset the flag in 0.5 sec. |
|
26 } |
|
27 } |
|
28 ); |
|
29 } |
|
30 |
|
31 function ContextMenu() |
|
32 { |
|
33 // attach internal funcs |
|
34 this.write = writeContextMenu; |
|
35 |
|
36 // do setup |
|
37 this.write(); |
|
38 } |
|
39 //// |
|
40 |
|
41 function showBookmarkView() |
|
42 { |
|
43 if(window.views.WebView.BookmarkTreeView == undefined) { |
|
44 window.views.WebView.createSuperPage("BookmarkTreeView", true); |
|
45 } |
|
46 window.views.WebView.BookmarkTreeView.load(chrome.baseDirectory + "bookmarkview.superpage/BookmarkView.html"); |
|
47 |
|
48 // Show it. |
|
49 window.views.WebView.zoomFactor = 1.0; |
|
50 window.views.WebView.showSuperPage("BookmarkTreeView"); |
|
51 } |
|
52 |
|
53 function showSettingsView() |
|
54 { |
|
55 if(window.views.WebView.SettingsView == undefined) { |
|
56 window.views.WebView.createSuperPage("SettingsView", true); |
|
57 } |
|
58 window.views.WebView.SettingsView.load(chrome.baseDirectory + "settingsview.superpage/SettingsView.html"); |
|
59 |
|
60 // Show it. |
|
61 window.views.WebView.zoomFactor = 1.0; |
|
62 window.views.WebView.showSuperPage("SettingsView"); |
|
63 } |
|
64 |
|
65 function showHistoryView() |
|
66 { |
|
67 if(window.views.WebView.BookmarkHistoryView == undefined) { |
|
68 window.views.WebView.createSuperPage("BookmarkHistoryView", true); |
|
69 } |
|
70 window.views.WebView.BookmarkHistoryView.load(chrome.baseDirectory + "historyview.superpage/historyView.html"); |
|
71 |
|
72 // Show it. |
|
73 window.views.WebView.zoomFactor = 1.0; |
|
74 window.views.WebView.showSuperPage("BookmarkHistoryView"); |
|
75 } |
|
76 |
|
77 function goToRecentUrlView () { |
|
78 showHistoryView(); |
|
79 window.ViewStack.switchView("BookmarkHistoryView", "WebView"); |
|
80 } |
|
81 |
|
82 function goToBookmarkView () { |
|
83 showBookmarkView(); |
|
84 window.ViewStack.switchView("BookmarkTreeView", "WebView"); |
|
85 } |
|
86 |
2 |
87 function goToSettingsView () { |
3 function ContextMenu(snippetId, contentView) { |
88 showSettingsView(); |
4 this.snippetId = snippetId; |
89 window.ViewStack.switchView("SettingsView", "WebView"); |
5 this.mainDiv = undefined; |
90 //window.snippets.UrlSearchChromeId.hide(false); |
6 this.tailEl = undefined; |
91 } |
7 this.contentView = contentView; |
92 |
8 this.showTimeoutId = 0; |
93 // "Private" methods |
9 // Width of a tab with no text, just the icon. Icons must all be the same width. |
94 function writeContextMenu() { |
10 // Update this if icon size or tab border width etc. changes -- or better yet, determine it dynamically. |
95 var html = |
11 this.normalTabWidth = 64; |
96 '<div class="loadImagesTop">'+ |
12 |
97 '</div>'+ |
13 // ContextMenu is a singleton to avoid problems with scope-chaining in some of the |
98 '<div class="loadImagesCenter">'+ |
14 // callbacks that it uses. See handleTabActivate. |
99 '</div>'+ |
15 if (cm_TheContextMenu != undefined) app.debug("ERROR: cm_TheContextMenu must be a singleton"); |
100 '<div class="loadImagesBottom">'+ |
16 cm_TheContextMenu = this; |
101 '</div>'+ |
17 |
|
18 // Create tabs and their corresponding menus based on JSON data. |
|
19 this.createTabsElement = function(data) { |
|
20 this.mainDiv = document.createElement("div"); |
|
21 this.mainDiv.setAttribute("class", "ContextMenuDiv"); |
|
22 this.mainDiv.setAttribute("id", "cm_mainDivId"); |
|
23 |
|
24 var tabsDiv = document.createElement("div"); |
|
25 tabsDiv.setAttribute("class", "TabsDiv"); |
|
26 tabsDiv.setAttribute("id", "cm_tabsDivId"); |
|
27 |
|
28 var menuDiv = document.createElement("div"); |
|
29 menuDiv.setAttribute("class", "MenuDiv"); |
|
30 menuDiv.setAttribute("id", "cm_menuDivId"); |
|
31 |
|
32 var tabsUl = document.createElement("ul"); |
|
33 tabsUl.setAttribute("class", "TabsUl"); |
|
34 tabsUl.setAttribute("id", "cm_tabsUlId"); |
|
35 tabsDiv.appendChild(tabsUl); |
|
36 |
|
37 var currentTabFound = false; |
|
38 |
|
39 // Iterate through the list of tabs. |
|
40 for (var i=0; i < data.tabs.length; i++) { |
|
41 var tab = data.tabs[i]; |
|
42 if (tab.visible != undefined) { |
|
43 if (!tab.visible()) { |
|
44 continue; |
|
45 } |
|
46 } |
|
47 |
|
48 // Create the tab. |
|
49 var tabEl = document.createElement("li"); |
|
50 tabsUl.appendChild(tabEl); |
|
51 |
|
52 var tabDiv = document.createElement("div"); |
|
53 tabEl.appendChild(tabDiv); |
|
54 |
|
55 var iconEl = undefined; |
|
56 var iconHighlightedEl = undefined; |
|
57 |
|
58 // Create the tab's icons. |
|
59 if (tab.icon != undefined) { |
|
60 iconEl = document.createElement("img"); |
|
61 iconEl.setAttribute("id", "icon"); |
|
62 iconEl.setAttribute("src", tab.icon); |
|
63 tabDiv.appendChild(iconEl); |
|
64 } |
|
65 if (tab.iconHighlighted != undefined) { |
|
66 iconHighlightedEl = document.createElement("img"); |
|
67 iconHighlightedEl.setAttribute("id", "iconHighlighted"); |
|
68 iconHighlightedEl.setAttribute("src", tab.iconHighlighted); |
|
69 tabDiv.appendChild(iconHighlightedEl); |
|
70 } |
|
71 |
|
72 // Create the tab's text. |
|
73 if (tab.text != undefined) { |
|
74 var anchorEl = document.createElement("a"); |
|
75 tabDiv.appendChild(anchorEl); |
|
76 var textEl = document.createTextNode(tab.text); |
|
77 anchorEl.appendChild(textEl); |
|
78 } |
|
79 |
|
80 // Create the menu for this tab. |
|
81 var menuEl = this.createMenuElement(tab); |
|
82 menuDiv.appendChild(menuEl); |
|
83 |
|
84 var tabClassName; |
|
85 if (tab.current == "true") { |
|
86 // This is the current, or selected, tab. |
|
87 tabClassName = "ViewContext_HighlightedTab"; |
|
88 tabDiv.className = "ViewContext_HighlightedTabDiv"; |
|
89 if(iconEl != undefined) { |
|
90 iconEl.setAttribute("style", "display: none;"); |
|
91 } |
|
92 currentTabFound = true; |
|
93 } |
|
94 else { |
|
95 // Not selected. |
|
96 tabClassName = "ViewContext_NormalTab"; |
|
97 tabDiv.className = "ViewContext_NormalTabDiv"; |
|
98 if(iconHighlightedEl != undefined) { |
|
99 iconHighlightedEl.setAttribute("style", "display: none;"); |
|
100 } |
|
101 |
|
102 // Hide its menu. |
|
103 menuEl.style.display = "none"; |
|
104 } |
|
105 |
|
106 if (tab.disabled == "true") { |
|
107 // The tab is disabled, add the appropriate CSS class to it. |
|
108 tabClassName += " ViewContext_DisabledTab"; |
|
109 } |
|
110 |
|
111 tabEl.className = tabClassName; |
|
112 |
|
113 // Set up callback to show the menu that corresponds to this tab. |
|
114 tabEl.onmouseup = this.handleTabActivate; |
|
115 tabEl.cm_menu = menuEl; |
|
116 |
|
117 // Remember that this tab is disabled. |
|
118 tabEl.cm_disabled = tab.disabled == "true"; |
|
119 } |
|
120 |
|
121 // If a "current" tab was not specified, highlight the first tab and display its menu. |
|
122 if (!currentTabFound) { |
|
123 var firstTabEl = tabsUl.firstChild; |
|
124 firstTabEl.className = "ViewContext_HighlightedTab"; |
|
125 firstTabEl.firstChild.className = "ViewContext_HighlightedTabDiv"; |
|
126 firstTabEl.cm_menu.style.display = ""; |
|
127 } |
|
128 |
|
129 // this.tailEl = document.createElement("img"); |
|
130 // this.mainDiv.appendChild(this.tailEl); |
|
131 // this.tailEl.setAttribute("id", "cm_tailId"); |
|
132 // this.tailEl.setAttribute("src", "contextmenu.snippet/icons/menu_tail.png"); |
|
133 |
|
134 this.mainDiv.appendChild(tabsDiv); |
|
135 this.mainDiv.appendChild(menuDiv); |
|
136 return this.mainDiv; |
|
137 } |
|
138 |
|
139 // Create a single menu based on the given data structure. |
|
140 this.createMenuElement = function(data) { |
|
141 // Create menu list. |
|
142 var menuUl = document.createElement("ul"); |
|
143 menuUl.setAttribute("class", "MenuUl"); |
|
144 |
|
145 for (var i=0; i < data.menuItems.length; i++) { |
|
146 var menuItem = data.menuItems[i]; |
|
147 |
|
148 // Create the item. |
|
149 var itemLi = document.createElement("li"); |
|
150 itemLi.setAttribute("class", "MenuLi"); |
|
151 var itemSpan = document.createElement("div"); |
|
152 |
|
153 // Is it a row if items? enumerate that as a ul inside of this outer li |
|
154 if(menuItem.menuRow != undefined) { |
|
155 var menuRowUl = document.createElement("ul"); |
|
156 menuRowUl.setAttribute("class", "MenuRowUl"); |
|
157 itemSpan.appendChild(menuRowUl); |
|
158 |
|
159 for(var j=0; j < menuItem.menuRow.length; j++) |
|
160 { |
|
161 var menuRowItem = menuItem.menuRow[j]; |
|
162 |
|
163 var rowItemLi = document.createElement("li"); |
|
164 rowItemLi.setAttribute("class", "MenuRowLi"); |
|
165 menuRowUl.appendChild(rowItemLi); |
|
166 |
|
167 // bind to mouseup |
|
168 rowItemLi.onmouseup = (function(handler) { |
|
169 return function() { |
|
170 if (handler != undefined) |
|
171 handler(); |
|
172 this.hide(); |
|
173 }.bind(this) |
|
174 }.bind(this))(menuRowItem.onclick); |
|
175 |
|
176 if (menuRowItem.text != undefined) { |
|
177 var textEl = document.createTextNode(menuRowItem.text); |
|
178 rowItemLi.appendChild(textEl); |
|
179 } |
|
180 } |
|
181 } |
|
182 else { |
|
183 itemLi.className += " RegularMenuLi"; |
|
184 if (menuItem.disabled == "true" || data.disabled == "true") { |
|
185 // Disabled item. |
|
186 itemLi.className += " ViewContext_DisabledMenuItem"; |
|
187 } |
|
188 else { |
|
189 // Enabled item. Set up the onmouseup handler. |
|
190 itemLi.onmouseup = (function(handler) { |
|
191 return function() { |
|
192 if (handler != undefined) |
|
193 handler(); |
|
194 this.hide(); |
|
195 }.bind(this) |
|
196 }.bind(this))(menuItem.onclick); |
|
197 } |
|
198 |
|
199 // Create the item's icon. |
|
200 if (menuItem.icon != undefined) { |
|
201 var iconEl = document.createElement("img"); |
|
202 itemSpan.appendChild(iconEl); |
|
203 iconEl.setAttribute("src", menuItem.icon); |
|
204 } |
|
205 |
|
206 // Create the item's text. |
|
207 if (menuItem.text != undefined) { |
|
208 var anchorEl = document.createElement("a"); |
|
209 itemSpan.appendChild(anchorEl); |
|
210 var textEl = document.createTextNode(menuItem.text); |
|
211 anchorEl.appendChild(textEl); |
|
212 } |
|
213 } |
|
214 |
|
215 menuUl.appendChild(itemLi); |
|
216 itemLi.appendChild(itemSpan); |
|
217 } |
|
218 return menuUl; |
|
219 } |
102 |
220 |
103 '<div class="menuItem menuTop">'+ |
221 // Handle mouse clicks on tab elements. |
104 '<div class="menuItemContents" onmouseup="goToBookmarkView(); window.snippets.ContextMenuId.hide()">'+ |
222 // Note: "this" refers to the element that was clicked on, ie. the tab item. |
105 '<img STYLE="vertical-align: middle; padding-left: 20px; padding-right: 15px;" src="contextmenu.snippet/icons/menu_icon_bookmarks.png">'+ |
223 this.handleTabActivate = function() { |
106 '<span class="menuItemLabel">'+ |
224 var tabsDivChildren = document.getElementById("cm_tabsUlId").childNodes; |
107 window.localeDelegate.translateText("content_view_menu_bookmarks")+ |
225 var otherTabsWidth = 0; |
108 '</span>'+ |
226 // Set the class for each tab. |
109 '</div>'+ |
227 for (var i = 0; i < tabsDivChildren.length; i++) { |
110 '</div>'+ |
228 var tabEl = tabsDivChildren[i]; |
111 |
229 var iconHighlighted = getChildById(tabEl, "iconHighlighted"); |
112 '<div class="menuItem menuBot">'+ |
230 var icon = getChildById(tabEl, "icon"); |
113 '<div class="menuItemContents" onmouseup="goToRecentUrlView();window.snippets.ContextMenuId.hide()">'+ |
231 if (tabEl == this) { |
114 '<img STYLE="vertical-align: middle; padding-left: 20px; padding-right: 15px;" src="contextmenu.snippet/icons/menu_icon_settings.png">'+ |
232 // Activate the tab. |
115 '<span class="menuItemLabel">'+ |
233 tabEl.className = "ViewContext_HighlightedTab"; |
116 window.localeDelegate.translateText("content_view_menu_history")+ |
234 //tabEl.firstChild.className = "ViewContext_HighlightedTabDiv"; |
117 '</span>'+ |
235 |
118 '</div>'+ |
236 // Show the highlighted icon, if one exists. |
119 '</div>'; |
237 if(iconHighlighted != undefined) { |
120 |
238 iconHighlighted.style.display = ""; |
121 document.write(html); |
239 |
122 } |
240 // Hide the normal icon. |
123 |
241 if (icon != undefined) { |
124 |
242 icon.style.display = "none"; |
125 |
243 } |
|
244 } |
|
245 } |
|
246 else { |
|
247 // Deactivate the tab. |
|
248 tabEl.className = "ViewContext_NormalTab"; |
|
249 //tabEl.firstChildclassName = "ViewContext_NormalTabDiv"; |
|
250 |
|
251 // If a highlighted icon exists, switch to the normal one, otherwise leave |
|
252 // the normal one alone. |
|
253 if(iconHighlighted != undefined) { |
|
254 iconHighlighted.style.display = "none"; |
|
255 if (icon != undefined) { |
|
256 icon.style.display = ""; |
|
257 } |
|
258 } |
|
259 } |
|
260 if (tabEl.cm_disabled) { |
|
261 tabEl.className += " ViewContext_DisabledTab"; |
|
262 //tabEl.firstClassName += " ViewContext_DisabledTabDiv"; |
|
263 } |
|
264 } |
|
265 |
|
266 // Show the menu of the tab that was just clicked. |
|
267 var menuDivChildren = document.getElementById("cm_menuDivId").childNodes; |
|
268 for (var i = 0; i < menuDivChildren.length; i++) { |
|
269 var menuEl = menuDivChildren[i]; |
|
270 if (menuEl == this.cm_menu) { |
|
271 menuDivChildren[i].style.display = ""; |
|
272 } |
|
273 else { |
|
274 menuDivChildren[i].style.display = "none"; |
|
275 } |
|
276 } |
|
277 //cm_TheContextMenu.positionTail(); |
|
278 //document.getElementById(this.snippetId).clientHeight = this.mainDiv.clientHeight; |
|
279 //document.getElementById("ContextMenuId").setAttribute("style", "height: " + document.getElementById("cm_mainDivId").clientHeight + "px;") |
|
280 |
|
281 cm_TheContextMenu.updateTabSizes(); |
|
282 snippets[cm_TheContextMenu.snippetId].updateOwnerArea(); |
|
283 } |
|
284 |
|
285 // Return the width of the "non-content" part of the element box, ie. thickness of |
|
286 // the padding, the border and the margin. |
|
287 this.getNonContentWidth = function(element) { |
|
288 var tabStyle = document.defaultView.getComputedStyle(element, null); |
|
289 return parseInt(tabStyle["margin-left"]) + parseInt(tabStyle["margin-right"]) + |
|
290 parseInt(tabStyle["padding-left"]) + parseInt(tabStyle["padding-right"]) + |
|
291 parseInt(tabStyle["border-left-width"]) + parseInt(tabStyle["border-right-width"]); |
|
292 } |
|
293 |
|
294 // Update the tab widths. Expand the highlighted tab to its maximum width and shrink the |
|
295 // normal tabs to their minimum widths. Note: it would be preferable to have this done |
|
296 // by CSS. |
|
297 this.updateTabSizes = function() { |
|
298 var tabsUl = document.getElementById("cm_tabsUlId"); |
|
299 var tabsDivChildren = tabsUl.childNodes; |
|
300 var otherTabsWidth = 0; |
|
301 var highlightedTab; |
|
302 for (var i = 0; i < tabsDivChildren.length; i++) { |
|
303 var tabEl = tabsDivChildren[i]; |
|
304 if (tabEl.className.indexOf("ViewContext_HighlightedTab") != -1) { |
|
305 highlightedTab = tabEl; |
|
306 } |
|
307 else { |
|
308 var newTabWidth = cm_TheContextMenu.normalTabWidth - cm_TheContextMenu.getNonContentWidth(tabEl); |
|
309 tabEl.style.width = newTabWidth; |
|
310 otherTabsWidth += tabEl.offsetWidth; |
|
311 } |
|
312 } |
|
313 if (highlightedTab != undefined) { |
|
314 var newWidth = tabsUl.offsetWidth - otherTabsWidth; |
|
315 newWidth -= cm_TheContextMenu.getNonContentWidth(highlightedTab) + 2; |
|
316 highlightedTab.style.width = newWidth; |
|
317 } |
|
318 } |
|
319 |
|
320 this.positionTail = function() { |
|
321 // Move the "tail" into position. |
|
322 var tailEl = document.getElementById("cm_tailId"); |
|
323 if (tailEl != undefined) { |
|
324 //var mainDiv = document.getElementById("cm_mainDivId"); |
|
325 var tailX = (this.mainDiv.clientWidth - tailEl.clientWidth) / 2; |
|
326 var tailY = this.mainDiv.clientHeight; |
|
327 tailEl.setAttribute("style", "position:absolute; top: " + tailY + "px; left: " + tailX); |
|
328 } |
|
329 } |
|
330 |
|
331 // Create all the DOM elements of the window. |
|
332 this.create = function(menuData) { |
|
333 var snippetEl = document.getElementById(this.snippetId); |
|
334 var el = this.createTabsElement(menuData); |
|
335 snippetEl.appendChild(el); |
|
336 } |
|
337 |
|
338 // Show the content menu. The menuData must contain an object tree describing the structure of the |
|
339 // tabs and sub-menus. |
|
340 // |
|
341 // Example menu data in JSON format: |
|
342 // var MenuData = { |
|
343 // "tabs": [ { |
|
344 // "text": "Tab 1", |
|
345 // "icon": "tab1.png", |
|
346 // "current": "true", |
|
347 // "menuItems": [ { |
|
348 // "text": Menu item 1, |
|
349 // "onclick": handleMenu1, |
|
350 // "icon": "menu1.png", |
|
351 // }, |
|
352 // { |
|
353 // "text": Menu item 2, |
|
354 // "onclick": function() { alert("hello"); }, |
|
355 // "icon": "menu2.png", |
|
356 // }, |
|
357 // ], |
|
358 // }, |
|
359 // { |
|
360 // "text": "Tab 2", |
|
361 // "icon": "tab2.png", |
|
362 // "menuItems": [ { |
|
363 // "text": Menu item 1, |
|
364 // "onclick": handleMenu21, |
|
365 // }, |
|
366 // { |
|
367 // "text": Menu item 2, |
|
368 // "onclick": handleMenu22, |
|
369 // }, |
|
370 // ], |
|
371 // }, |
|
372 // ] |
|
373 // }; |
|
374 // |
|
375 |
|
376 this.cancel = function() { |
|
377 //app.debug("CM: cancel " + this.showTimeoutId); |
|
378 clearTimeout(this.showTimeoutId); |
|
379 this.showTimeoutId = 0; |
|
380 this.cleanUp(); |
|
381 } |
|
382 |
|
383 this.show = function(menuData) { |
|
384 this.cleanUp(); |
|
385 this.create(menuData); |
|
386 this.showTimeoutId = setTimeout('cm_TheContextMenu.showIt()', 10); |
|
387 } |
|
388 |
|
389 this.cleanUp = function() { |
|
390 // Remove elements from DOM to save memory. |
|
391 var oldEl = document.getElementById("cm_mainDivId"); |
|
392 if (oldEl) { |
|
393 var snippetEl = document.getElementById(cm_TheContextMenu.snippetId); |
|
394 snippetEl.removeChild(oldEl); |
|
395 } |
|
396 } |
|
397 |
|
398 // Hide this window. |
|
399 this.hide = function() { |
|
400 snippets[cm_TheContextMenu.snippetId].hide(); |
|
401 } |
|
402 |
|
403 this.onHide = function() { |
|
404 this.cleanUp(); |
|
405 } |
|
406 |
|
407 this.showIt = function() { |
|
408 cm_TheContextMenu.updateTabSizes(); |
|
409 // Use a timer to actually show the window to allow the page re-layout |
|
410 // to finish. We don't know when this really happens but 50ms seems to |
|
411 // be enough on the N97. Without this delay the bottom of the window |
|
412 // often gets clipped. |
|
413 setTimeout("cm_TheContextMenu.showIt2()", 50); |
|
414 } |
|
415 |
|
416 this.showIt2 = function() { |
|
417 var snippet = snippets[cm_TheContextMenu.snippetId]; |
|
418 |
|
419 snippet.updateOwnerArea(); |
|
420 snippet.setZValue(2); |
|
421 |
|
422 centerSnippet(snippet); |
|
423 |
|
424 // if (showTail) { |
|
425 // cm_TheContextMenu.positionTail(); |
|
426 // } |
|
427 |
|
428 snippet.show(); |
|
429 } |
|
430 |
|
431 chrome.chromeComplete.connect(createDelegate(this, |
|
432 function() { |
|
433 var snippet = snippets[this.snippetId]; |
|
434 |
|
435 chrome.aspectChanged.connect(createDelegate(this, |
|
436 function(a) { |
|
437 centerSnippet(snippets[this.snippetId]); |
|
438 })); |
|
439 |
|
440 snippet.hidden.connect(createDelegate(this, this.onHide)); |
|
441 |
|
442 })); |
|
443 } // End ContextMenu class |