Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/aardvark.js

Issue 29363476: Issue 2879 - Move element selection into the content process (Closed) Base URL: https://hg.adblockplus.org/elemhidehelper
Patch Set: Created Nov. 17, 2016, 1:17 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/child/commands.js » ('j') | lib/child/commands.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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);
OLDNEW
« no previous file with comments | « no previous file | lib/child/commands.js » ('j') | lib/child/commands.js » ('J')

Powered by Google App Engine
This is Rietveld