Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * This Source Code is subject to the terms of the Mozilla Public License | 2 * This Source Code is subject to the terms of the Mozilla Public License |
saroyanm
2016/11/23 17:44:37
Irrelevant: Why is this file called Aadvark ?
Wladimir Palant
2016/11/24 14:02:00
The origin of this code is the Aardvark extension
| |
3 * version 2.0 (the "License"). You can obtain a copy of the License at | 3 * version 2.0 (the "License"). You can obtain a copy of the License at |
4 * http://mozilla.org/MPL/2.0/. | 4 * http://mozilla.org/MPL/2.0/. |
5 */ | 5 */ |
6 | 6 |
7 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 7 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
8 | 8 |
9 let {Prefs} = require("prefs"); | 9 let {Prefs} = require("prefs"); |
10 | 10 |
11 // Make sure to stop selection when we are uninstalled | 11 let messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"] |
12 onShutdown.add(() => Aardvark.quit()); | 12 .getService(Ci.nsIMessageListenerManager) |
13 .QueryInterface(Ci.nsIMessageBroadcaster); | |
13 | 14 |
14 // To be replaced when selection starts | 15 // To be replaced when selection starts |
15 function E(id) {return null;} | 16 function E(id) {return null;} |
16 | 17 |
17 let messageCounter = 0; | 18 messageManager.addMessageListener("ElemHideHelper:SelectionStarted", selectionSt arted); |
saroyanm
2016/11/23 17:44:37
Nit: Exceeding 80 chars
Wladimir Palant
2016/11/24 14:02:01
Done.
| |
19 messageManager.addMessageListener("ElemHideHelper:SelectionSucceeded", selection Succeeded); | |
20 messageManager.addMessageListener("ElemHideHelper:SelectionStopped", selectionSt opped); | |
21 onShutdown.add(() => | |
22 { | |
23 messageManager.removeMessageListener("ElemHideHelper:SelectionStarted", select ionStarted); | |
24 messageManager.removeMessageListener("ElemHideHelper:SelectionSucceeded", sele ctionSucceeded); | |
25 messageManager.removeMessageListener("ElemHideHelper:SelectionStopped", select ionStopped); | |
18 | 26 |
19 /********************************* | 27 selectionStopped(); |
20 * Minimal element creation code * | 28 }); |
21 *********************************/ | |
22 | 29 |
23 function createElement(doc, tagName, attrs, children) | 30 function selectionStarted(message) |
24 { | 31 { |
25 let el = doc.createElement(tagName); | 32 Aardvark.selectionStarted(); |
26 if (attrs) | 33 } |
27 for (let key in attrs) | 34 |
28 el.setAttribute(key, attrs[key]); | 35 function selectionSucceeded(message) |
29 if (children) | 36 { |
30 for (let child of children) | 37 Aardvark.selectionSucceeded(message.data); |
31 el.appendChild(child) | 38 } |
32 return el; | 39 |
33 }; | 40 function selectionStopped(message) |
41 { | |
42 Aardvark.selectionStopped(); | |
43 } | |
34 | 44 |
35 /********************************** | 45 /********************************** |
36 * General element selection code * | 46 * General element selection code * |
37 **********************************/ | 47 **********************************/ |
38 | 48 |
39 let Aardvark = exports.Aardvark = | 49 let Aardvark = exports.Aardvark = |
40 { | 50 { |
41 window: null, | 51 window: null, |
42 browser: null, | 52 browser: null, |
43 anchorElem: null, | 53 rememberedWrapper: null, |
saroyanm
2016/11/23 17:44:37
Curious: Why rememberedWrapper, but not just wrapp
Wladimir Palant
2016/11/24 14:02:00
Its a temporary state, a bit of a hack so that we
| |
44 selectedElem: null, | |
45 isUserSelected: false, | |
46 lockedAnchor: null, | |
47 commentElem: null, | |
48 mouseX: -1, | 54 mouseX: -1, |
49 mouseY: -1, | 55 mouseY: -1, |
50 prevSelectionUpdate: -1, | |
51 commandLabelTimer: null, | 56 commandLabelTimer: null, |
52 viewSourceTimer: null, | 57 viewSourceTimer: null, |
53 boxElem: null, | |
54 paintNode: null, | |
55 prevPos: null, | |
56 | 58 |
57 start: function(wrapper) | 59 start: function(wrapper) |
58 { | 60 { |
59 if (!this.canSelect(wrapper.browser)) | 61 this.rememberedWrapper = wrapper; |
60 return; | 62 let browser = wrapper.browser; |
63 if ("selectedBrowser" in browser) | |
saroyanm
2016/11/23 17:44:38
What is "selectedBrowser" property ?
Are we assig
Wladimir Palant
2016/11/24 14:02:01
You need to look at https://developer.mozilla.org/
| |
64 browser = browser.selectedBrowser; | |
65 messageManager.broadcastAsyncMessage( | |
66 "ElemHideHelper:StartSelection", | |
67 browser.outerWindowID | |
68 ); | |
69 }, | |
61 | 70 |
62 if (this.browser) | 71 selectionStarted: function() |
63 this.quit(); | 72 { |
73 let wrapper = this.rememberedWrapper; | |
74 this.rememberedWrapper = null; | |
64 | 75 |
65 this.window = wrapper.window; | 76 this.window = wrapper.window; |
66 this.browser = wrapper.browser; | 77 this.browser = wrapper.browser; |
saroyanm
2016/11/23 17:44:38
We already assigning this.rememberedWrapper value
Wladimir Palant
2016/11/24 14:02:01
No, we are only assigning it to the local browser
| |
67 E = id => wrapper.E(id); | 78 E = id => wrapper.E(id); |
68 | 79 |
69 this.browser.addEventListener("click", this.onMouseClick, true); | |
70 this.browser.addEventListener("DOMMouseScroll", this.onMouseScroll, true); | |
71 this.browser.addEventListener("keypress", this.onKeyPress, true); | 80 this.browser.addEventListener("keypress", this.onKeyPress, true); |
72 this.browser.addEventListener("mousemove", this.onMouseMove, true); | 81 this.browser.addEventListener("mousemove", this.onMouseMove, false); |
73 this.browser.addEventListener("select", this.quit, false); | 82 this.browser.addEventListener("select", this.onTabSelect, false); |
74 this.browser.contentWindow.addEventListener("pagehide", this.onPageHide, tru e); | |
75 | |
76 this.browser.contentWindow.focus(); | |
77 | |
78 let doc = this.browser.contentDocument; | |
79 let {elementMarkerClass} = require("main"); | |
80 this.boxElem = createElement(doc, "div", {"class": elementMarkerClass}, [ | |
81 createElement(doc, "div", {"class": "ehh-border"}), | |
82 createElement(doc, "div", {"class": "ehh-label"}, [ | |
83 createElement(doc, "span", {"class": "ehh-labelTag"}), | |
84 createElement(doc, "span", {"class": "ehh-labelAddition"}) | |
85 ]) | |
86 ]); | |
87 | 83 |
88 this.initHelpBox(); | 84 this.initHelpBox(); |
89 | 85 |
90 if (Prefs.showhelp) | 86 if (Prefs.showhelp) |
91 this.showMenu(); | 87 this.showMenu(); |
92 | |
93 // Make sure to select some element immeditely (whichever is in the center o f the browser window) | |
94 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); | |
95 this.isUserSelected = false; | |
96 this.onMouseMove({clientX: wndWidth / 2, clientY: wndHeight / 2, screenX: -1 , screenY: -1, target: null}); | |
97 }, | 88 }, |
98 | 89 |
99 canSelect: function(browser) | 90 selectionSucceeded: function(nodeInfo) |
100 { | 91 { |
101 if (!browser || !browser.contentWindow || | 92 this.window.openDialog("chrome://elemhidehelper/content/composer.xul", |
saroyanm
2016/11/23 17:44:37
Shouldn't we also remove eventlisteners on selecti
Wladimir Palant
2016/11/24 14:02:01
No, the select command (in lib/child/commands.js)
| |
102 !(browser.contentDocument instanceof Ci.nsIDOMHTMLDocument)) | 93 "_blank", "chrome,centerscreen,resizable,dialog=no", nodeInfo); |
Wladimir Palant
2016/11/17 13:54:47
This function is pretty much what Aardvark.select(
saroyanm
2016/11/23 17:44:38
Acknowledged.
| |
103 { | 94 }, |
104 return false; | |
105 } | |
106 | 95 |
107 let location = browser.contentWindow.location; | 96 selectionStopped: function() |
108 if (location.href == "about:blank") | 97 { |
109 return false; | 98 if (!this.browser) |
99 return; | |
110 | 100 |
111 if (!Prefs.acceptlocalfiles && | 101 if (this.commandLabelTimer) |
112 location.hostname == "" && | 102 this.commandLabelTimer.cancel(); |
113 location.protocol != "mailbox:" && | 103 if (this.viewSourceTimer) |
114 location.protocol != "imap:" && | 104 this.viewSourceTimer.cancel(); |
115 location.protocol != "news:" && | 105 this.commandLabelTimer = null; |
116 location.protocol != "snews:") | 106 this.viewSourceTimer = null; |
117 { | |
118 return false; | |
119 } | |
120 | 107 |
121 return true; | 108 this.hideTooltips(); |
109 | |
110 this.browser.removeEventListener("keypress", this.onKeyPress, true); | |
111 this.browser.removeEventListener("mousemove", this.onMouseMove, false); | |
112 this.browser.removeEventListener("select", this.onTabSelect, false); | |
113 | |
114 this.window = null; | |
115 this.browser = null; | |
116 E = id => null; | |
Wladimir Palant
2016/11/17 13:54:47
This function is what Aardvark.quit() used to be.
saroyanm
2016/11/23 17:44:37
Acknowledged.
| |
122 }, | 117 }, |
123 | 118 |
124 doCommand: function(command, event) | 119 doCommand: function(command, event) |
125 { | 120 { |
126 if (this[command](this.selectedElem)) | 121 let showFeedback; |
122 if (this.hasOwnProperty(command)) | |
123 showFeedback = this[command](); | |
Wladimir Palant
2016/11/17 13:54:47
The command handler no longer gets the selected el
saroyanm
2016/11/23 17:44:38
Acknowledged.
| |
124 else | |
125 { | |
126 showFeedback = (command != "select" && command != "quit"); | |
Wladimir Palant
2016/11/17 13:54:47
This changes behavior slightly - e.g. you will get
saroyanm
2016/11/23 17:44:37
Acknowledged.
| |
127 messageManager.broadcastAsyncMessage("ElemHideHelper:Command", command); | |
128 } | |
129 | |
130 if (showFeedback) | |
127 { | 131 { |
128 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma nd + "_altkey"], this.commands[command + "_label"]); | 132 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma nd + "_altkey"], this.commands[command + "_label"]); |
129 if (event) | 133 if (event) |
130 event.stopPropagation(); | 134 event.stopPropagation(); |
131 } | 135 } |
132 if (event) | 136 if (event) |
133 event.preventDefault(); | 137 event.preventDefault(); |
134 }, | 138 }, |
135 | 139 |
136 showCommandLabel: function(key, alternativeKey, label) | 140 showCommandLabel: function(key, alternativeKey, label) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 { | 201 { |
198 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; | 202 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; |
199 for (let i = 0; i < tooltips.length; i++) | 203 for (let i = 0; i < tooltips.length; i++) |
200 { | 204 { |
201 let tooltip = E(tooltips[i]); | 205 let tooltip = E(tooltips[i]); |
202 if (tooltip) | 206 if (tooltip) |
203 tooltip.hidePopup(); | 207 tooltip.hidePopup(); |
204 } | 208 } |
205 }, | 209 }, |
206 | 210 |
207 onMouseClick: function(event) | |
208 { | |
209 if (event.button != 0 || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) | |
210 return; | |
211 | |
212 this.doCommand("select", event); | |
213 }, | |
214 | |
215 onMouseScroll: function(event) | |
216 { | |
217 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) | |
218 return; | |
219 | |
220 if ("axis" in event && event.axis != event.VERTICAL_AXIS) | |
221 return; | |
222 | |
223 this.doCommand(event.detail > 0 ? "wider" : "narrower", event); | |
224 }, | |
225 | |
226 onKeyPress: function(event) | 211 onKeyPress: function(event) |
227 { | 212 { |
228 if (event.altKey || event.ctrlKey || event.metaKey) | 213 if (event.altKey || event.ctrlKey || event.metaKey) |
229 return; | 214 return; |
230 | 215 |
231 var command = null; | 216 var command = null; |
232 if (event.keyCode == event.DOM_VK_ESCAPE) | 217 if (event.keyCode == event.DOM_VK_ESCAPE) |
saroyanm
2016/11/23 17:44:38
Note: keyCode is a deprecated property.
You want m
Wladimir Palant
2016/11/24 14:02:01
Yes, definitely.
saroyanm
2016/11/25 16:18:13
Done -> #4666
| |
233 command = "quit"; | 218 command = "quit"; |
234 else if (event.keyCode == event.DOM_VK_RETURN) | 219 else if (event.keyCode == event.DOM_VK_RETURN) |
235 command = "select"; | 220 command = "select"; |
236 else if (event.charCode) | 221 else if (event.charCode) |
237 { | 222 { |
238 var key = String.fromCharCode(event.charCode).toLowerCase(); | 223 var key = String.fromCharCode(event.charCode).toLowerCase(); |
239 var commands = this.commands; | 224 var commands = this.commands; |
240 for (var i = 0; i < commands.length; i++) | 225 for (var i = 0; i < commands.length; i++) |
241 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al tkey"] == key) | 226 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al tkey"] == key) |
242 command = commands[i]; | 227 command = commands[i]; |
243 } | 228 } |
244 | 229 |
245 if (command) | 230 if (command) |
246 this.doCommand(command, event); | 231 this.doCommand(command, event); |
247 }, | 232 }, |
248 | 233 |
249 onPageHide: function(event) | |
250 { | |
251 this.doCommand("quit", null); | |
252 }, | |
253 | |
254 onMouseMove: function(event) | 234 onMouseMove: function(event) |
255 { | 235 { |
256 this.mouseX = event.screenX; | 236 this.mouseX = event.screenX; |
257 this.mouseY = event.screenY; | 237 this.mouseY = event.screenY; |
258 | |
259 this.hideSelection(); | |
260 if (!this.browser) | |
261 { | |
262 // hideSelection() called quit() | |
263 return; | |
264 } | |
265 | |
266 let x = event.clientX; | |
267 let y = event.clientY; | |
268 | |
269 // We might have coordinates relative to a frame, recalculate relative to to p window | |
270 let node = event.target; | |
271 while (node && node.ownerDocument && node.ownerDocument.defaultView && node. ownerDocument.defaultView.frameElement) | |
272 { | |
273 node = node.ownerDocument.defaultView.frameElement; | |
274 let rect = node.getBoundingClientRect(); | |
275 x += rect.left; | |
276 y += rect.top; | |
277 } | |
278 | |
279 let elem = this.browser.contentDocument.elementFromPoint(x, y); | |
280 while (elem && "contentDocument" in elem && this.canSelect(elem)) | |
281 { | |
282 let rect = elem.getBoundingClientRect(); | |
283 x -= rect.left; | |
284 y -= rect.top; | |
285 elem = elem.contentDocument.elementFromPoint(x, y); | |
286 } | |
287 | |
288 if (elem) | |
289 { | |
290 if (!this.lockedAnchor) | |
291 this.setAnchorElement(elem); | |
292 else | |
293 { | |
294 this.lockedAnchor = elem; | |
295 this.selectElement(this.selectedElem); | |
296 } | |
297 } | |
298 }, | 238 }, |
299 | 239 |
300 onAfterPaint: function() | 240 onTabSelect: function(event) |
301 { | 241 { |
302 // Don't update position too often | 242 this.doCommand("quit", null); |
303 if (this.selectedElem && Date.now() - this.prevSelectionUpdate > 20) | |
304 { | |
305 let pos = this.getElementPosition(this.selectedElem); | |
306 if (!this.prevPos || this.prevPos.left != pos.left || this.prevPos.right ! = pos.right | |
307 || this.prevPos.top != pos.top || this.prevPos.bottom != pos.bottom) | |
308 { | |
309 this.selectElement(this.selectedElem); | |
310 } | |
311 } | |
312 }, | |
313 | |
314 setAnchorElement: function(anchor) | |
315 { | |
316 this.anchorElem = anchor; | |
317 | |
318 let newSelection = anchor; | |
319 if (this.isUserSelected) | |
320 { | |
321 // User chose an element via wider/narrower commands, keep the selection i f | |
322 // out new anchor is still a child of that element | |
323 let e = newSelection; | |
324 while (e && e != this.selectedElem) | |
325 e = this.getParentElement(e); | |
326 | |
327 if (e) | |
328 newSelection = this.selectedElem; | |
329 else | |
330 this.isUserSelected = false; | |
331 } | |
332 | |
333 this.selectElement(newSelection); | |
334 }, | 243 }, |
335 | 244 |
336 appendDescription: function(node, value, className) | 245 appendDescription: function(node, value, className) |
337 { | 246 { |
338 var descr = this.window.document.createElement("description"); | 247 var descr = this.window.document.createElement("description"); |
339 descr.setAttribute("value", value); | 248 descr.setAttribute("value", value); |
340 if (className) | 249 if (className) |
341 descr.setAttribute("class", className); | 250 descr.setAttribute("class", className); |
342 node.appendChild(descr); | 251 node.appendChild(descr); |
343 }, | 252 }, |
344 | 253 |
345 /************************** | |
346 * Element marker display * | |
347 **************************/ | |
348 | |
349 getElementLabel: function(elem) | |
350 { | |
351 let tagName = elem.tagName.toLowerCase(); | |
352 let addition = ""; | |
353 if (elem.id != "") | |
354 addition += ", id: " + elem.id; | |
355 if (elem.className != "") | |
356 addition += ", class: " + elem.className; | |
357 if (elem.style.cssText != "") | |
358 addition += ", style: " + elem.style.cssText; | |
359 | |
360 return [tagName, addition]; | |
361 }, | |
362 | |
363 selectElement: function(elem) | |
364 { | |
365 this.selectedElem = elem; | |
366 this.prevSelectionUpdate = Date.now(); | |
367 | |
368 let border = this.boxElem.getElementsByClassName("ehh-border")[0]; | |
369 let label = this.boxElem.getElementsByClassName("ehh-label")[0]; | |
370 let labelTag = this.boxElem.getElementsByClassName("ehh-labelTag")[0]; | |
371 let labelAddition = this.boxElem.getElementsByClassName("ehh-labelAddition") [0]; | |
372 | |
373 if (this.boxElem.parentNode) | |
374 this.boxElem.parentNode.removeChild(this.boxElem); | |
375 | |
376 let doc = this.browser.contentDocument; | |
377 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); | |
378 | |
379 let pos = this.getElementPosition(elem); | |
380 this.boxElem.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; | |
381 this.boxElem.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; | |
382 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; | |
383 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; | |
384 | |
385 [labelTag.textContent, labelAddition.textContent] = this.getElementLabel(ele m); | |
386 | |
387 // If there is not enough space to show the label move it up a little | |
388 if (pos.bottom < wndHeight - 25) | |
389 label.className = "ehh-label"; | |
390 else | |
391 label.className = "ehh-label onTop"; | |
392 | |
393 doc.documentElement.appendChild(this.boxElem); | |
394 | |
395 this.paintNode = doc.defaultView; | |
396 if (this.paintNode) | |
397 { | |
398 this.prevPos = pos; | |
399 this.paintNode.addEventListener("MozAfterPaint", this.onAfterPaint, false) ; | |
400 } | |
401 }, | |
402 | |
403 hideSelection: function() | |
404 { | |
405 try | |
406 { | |
407 if (this.boxElem.parentNode) | |
408 this.boxElem.parentNode.removeChild(this.boxElem); | |
409 } | |
410 catch (e) | |
411 { | |
412 // Are we using CPOW whose process is gone? Quit! | |
413 // Clear some variables to prevent recursion (quit will call us again). | |
414 this.boxElem = {}; | |
415 this.paintNode = null; | |
416 this.quit(); | |
417 return; | |
418 } | |
419 | |
420 if (this.paintNode) | |
421 this.paintNode.removeEventListener("MozAfterPaint", this.onAfterPaint, fal se); | |
422 | |
423 this.paintNode = null; | |
424 this.prevPos = null; | |
425 }, | |
426 | |
427 getWindowSize: function(wnd) | |
428 { | |
429 return [wnd.innerWidth, wnd.document.documentElement.clientHeight]; | |
430 }, | |
431 | |
432 getElementPosition: function(element) | |
433 { | |
434 // Restrict rectangle coordinates by the boundaries of a window's client are a | |
435 function intersectRect(rect, wnd) | |
436 { | |
437 let [wndWidth, wndHeight] = this.getWindowSize(wnd); | |
438 rect.left = Math.max(rect.left, 0); | |
439 rect.top = Math.max(rect.top, 0); | |
440 rect.right = Math.min(rect.right, wndWidth); | |
441 rect.bottom = Math.min(rect.bottom, wndHeight); | |
442 } | |
443 | |
444 let rect = element.getBoundingClientRect(); | |
445 let wnd = element.ownerDocument.defaultView; | |
446 | |
447 rect = {left: rect.left, top: rect.top, | |
448 right: rect.right, bottom: rect.bottom}; | |
449 while (true) | |
450 { | |
451 intersectRect.call(this, rect, wnd); | |
452 | |
453 if (!wnd.frameElement) | |
454 break; | |
455 | |
456 // Recalculate coordinates to be relative to frame's parent window | |
457 let frameElement = wnd.frameElement; | |
458 wnd = frameElement.ownerDocument.defaultView; | |
459 | |
460 let frameRect = frameElement.getBoundingClientRect(); | |
461 let frameStyle = wnd.getComputedStyle(frameElement, null); | |
462 let relLeft = frameRect.left + parseFloat(frameStyle.borderLeftWidth) + pa rseFloat(frameStyle.paddingLeft); | |
463 let relTop = frameRect.top + parseFloat(frameStyle.borderTopWidth) + parse Float(frameStyle.paddingTop); | |
464 | |
465 rect.left += relLeft; | |
466 rect.right += relLeft; | |
467 rect.top += relTop; | |
468 rect.bottom += relTop; | |
469 } | |
470 | |
471 return rect; | |
472 }, | |
473 | |
474 getParentElement: function(elem) | |
475 { | |
476 let result = elem.parentNode; | |
477 if (result && result.nodeType == Ci.nsIDOMElement.DOCUMENT_NODE && result.de faultView && result.defaultView.frameElement) | |
478 result = result.defaultView.frameElement; | |
479 | |
480 if (result && result.nodeType != Ci.nsIDOMElement.ELEMENT_NODE) | |
481 return null; | |
482 | |
483 return result; | |
484 }, | |
485 | |
486 /*************************** | 254 /*************************** |
487 * Commands implementation * | 255 * Commands implementation * |
488 ***************************/ | 256 ***************************/ |
489 | 257 |
490 commands: [ | 258 commands: [ |
491 "select", | 259 "select", |
492 "wider", | 260 "wider", |
493 "narrower", | 261 "narrower", |
494 "lock", | 262 "lock", |
495 "quit", | 263 "quit", |
496 "blinkElement", | 264 "blinkElement", |
497 "viewSource", | 265 "viewSource", |
498 "viewSourceWindow", | 266 "viewSourceWindow", |
499 "showMenu" | 267 "showMenu" |
500 ], | 268 ], |
501 | 269 |
502 wider: function(elem) | |
503 { | |
504 if (!elem) | |
505 return false; | |
506 | |
507 let newElem = this.getParentElement(elem); | |
508 if (!newElem) | |
509 return false; | |
510 | |
511 this.isUserSelected = true; | |
512 this.selectElement(newElem); | |
513 return true; | |
514 }, | |
515 | |
516 narrower: function(elem) | |
517 { | |
518 if (elem) | |
519 { | |
520 // Search selected element in the parent chain, starting with the anchor e lement. | |
521 // We need to select the element just before the selected one. | |
522 let e = this.anchorElem; | |
523 let newElem = null; | |
524 while (e && e != elem) | |
525 { | |
526 newElem = e; | |
527 e = this.getParentElement(e); | |
528 } | |
529 | |
530 if (!e || !newElem) | |
531 return false; | |
532 | |
533 this.isUserSelected = true; | |
534 this.selectElement(newElem); | |
535 return true; | |
536 } | |
537 return false; | |
538 }, | |
539 | |
540 lock: function(elem) | |
541 { | |
542 if (!elem) | |
543 return false; | |
544 | |
545 if (this.lockedAnchor) | |
546 { | |
547 this.setAnchorElement(this.lockedAnchor); | |
548 this.lockedAnchor = null; | |
549 } | |
550 else | |
551 this.lockedAnchor = this.anchorElem; | |
552 | |
553 return true; | |
554 }, | |
555 | |
556 quit: function() | |
557 { | |
558 if (!this.browser) | |
559 return false; | |
560 | |
561 if ("blinkTimer" in this) | |
562 this.stopBlinking(); | |
563 | |
564 if (this.commandLabelTimer) | |
565 this.commandLabelTimer.cancel(); | |
566 if (this.viewSourceTimer) | |
567 this.viewSourceTimer.cancel(); | |
568 this.commandLabelTimer = null; | |
569 this.viewSourceTimer = null; | |
570 | |
571 this.hideSelection(); | |
572 this.hideTooltips(); | |
573 | |
574 this.browser.removeEventListener("click", this.onMouseClick, true); | |
575 this.browser.removeEventListener("DOMMouseScroll", this.onMouseScroll, true) ; | |
576 this.browser.removeEventListener("keypress", this.onKeyPress, true); | |
577 this.browser.removeEventListener("mousemove", this.onMouseMove, true); | |
578 this.browser.removeEventListener("select", this.quit, false); | |
579 this.browser.contentWindow.removeEventListener("pagehide", this.onPageHide, true); | |
580 | |
581 this.anchorElem = null; | |
582 this.selectedElem = null; | |
583 this.window = null; | |
584 this.browser = null; | |
585 this.commentElem = null; | |
586 this.lockedAnchor = null; | |
587 this.boxElem = null; | |
588 E = id => null; | |
589 return false; | |
590 }, | |
591 | |
592 select: function(elem) | |
593 { | |
594 if (!elem || !this.window) | |
595 return false; | |
596 | |
597 let messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"] | |
598 .getService(Ci.nsIMessageBroadcaster); | |
599 let messageId = ++messageCounter; | |
600 let callback = (message) => | |
601 { | |
602 let response = message.data; | |
603 if (response.messageId != messageId) | |
604 return; | |
605 | |
606 messageManager.removeMessageListener( | |
607 "ElemHideHelper:GetNodeInfo:Response", | |
608 callback | |
609 ); | |
610 | |
611 if (!response.nodeData) | |
612 return; | |
613 | |
614 this.window.openDialog("chrome://elemhidehelper/content/composer.xul", | |
615 "_blank", "chrome,centerscreen,resizable,dialog=no", response); | |
616 this.quit(); | |
617 }; | |
618 | |
619 messageManager.addMessageListener( | |
620 "ElemHideHelper:GetNodeInfo:Response", | |
621 callback | |
622 ); | |
623 messageManager.broadcastAsyncMessage( | |
624 "ElemHideHelper:GetNodeInfo", | |
625 messageId, | |
626 { | |
627 element: elem | |
628 } | |
629 ); | |
630 return false; | |
631 }, | |
632 | |
633 blinkElement: function(elem) | |
634 { | |
635 if (!elem) | |
636 return false; | |
637 | |
638 if ("blinkTimer" in this) | |
639 this.stopBlinking(); | |
640 | |
641 let counter = 0; | |
642 this.blinkElem = elem; | |
643 this.blinkOrigValue = elem.style.visibility; | |
644 this.blinkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | |
645 this.blinkTimer.initWithCallback(function() | |
646 { | |
647 counter++; | |
648 elem.style.visibility = (counter % 2 == 0 ? "visible" : "hidden"); | |
649 if (counter == 6) | |
650 Aardvark.stopBlinking(); | |
651 }, 250, Ci.nsITimer.TYPE_REPEATING_SLACK); | |
652 | |
653 return true; | |
654 }, | |
655 | |
656 stopBlinking: function() | |
657 { | |
658 this.blinkTimer.cancel(); | |
659 this.blinkElem.style.visibility = this.blinkOrigValue; | |
660 | |
661 delete this.blinkElem; | |
662 delete this.blinkOrigValue; | |
663 delete this.blinkTimer; | |
664 }, | |
665 | |
666 viewSource: function(elem) | 270 viewSource: function(elem) |
667 { | 271 { |
668 if (!elem) | 272 if (!elem) |
669 return false; | 273 return false; |
670 | 274 |
671 var sourceBox = E("ehh-viewsource"); | 275 var sourceBox = E("ehh-viewsource"); |
672 if (sourceBox.state == "open" && this.commentElem == elem) | 276 if (sourceBox.state == "open") |
Wladimir Palant
2016/11/17 13:54:47
This is a behavior change, originally we would onl
| |
673 { | 277 { |
674 sourceBox.hidePopup(); | 278 sourceBox.hidePopup(); |
675 return true; | 279 return true; |
676 } | 280 } |
677 sourceBox.hidePopup(); | 281 sourceBox.hidePopup(); |
678 | 282 |
679 while (sourceBox.firstElementChild) | 283 while (sourceBox.firstElementChild) |
680 sourceBox.removeChild(sourceBox.firstElementChild); | 284 sourceBox.removeChild(sourceBox.firstElementChild); |
681 this.getOuterHtmlFormatted(elem, sourceBox); | 285 this.getOuterHtmlFormatted(elem, sourceBox); |
682 this.commentElem = elem; | |
683 | 286 |
684 let anchor = this.window.document.documentElement; | 287 let anchor = this.window.document.documentElement; |
685 let x = this.mouseX; | 288 let x = this.mouseX; |
686 let y = this.mouseY; | 289 let y = this.mouseY; |
687 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer ); | 290 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer ); |
688 this.viewSourceTimer.initWithCallback(function() | 291 this.viewSourceTimer.initWithCallback(function() |
689 { | 292 { |
690 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); | 293 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); |
691 Aardvark.viewSourceTimer = null; | 294 Aardvark.viewSourceTimer = null; |
692 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); | 295 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
817 } | 420 } |
818 | 421 |
819 // Show help box | 422 // Show help box |
820 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); | 423 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); |
821 return true; | 424 return true; |
822 } | 425 } |
823 } | 426 } |
824 | 427 |
825 // Makes sure event handlers like Aardvark.onKeyPress always have the correct | 428 // Makes sure event handlers like Aardvark.onKeyPress always have the correct |
826 // this pointer set. | 429 // this pointer set. |
827 for (let method of ["onMouseClick", "onMouseScroll", "onKeyPress", "onPageHide", "onMouseMove", "onAfterPaint", "quit"]) | 430 for (let method of ["onKeyPress", "onMouseMove", "onTabSelect"]) |
828 Aardvark[method] = Aardvark[method].bind(Aardvark); | 431 Aardvark[method] = Aardvark[method].bind(Aardvark); |
OLD | NEW |