| 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 |
| 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", |
| 19 selectionStarted); |
| 20 messageManager.addMessageListener("ElemHideHelper:SelectionSucceeded", |
| 21 selectionSucceeded); |
| 22 messageManager.addMessageListener("ElemHideHelper:SelectionStopped", |
| 23 selectionStopped); |
| 24 onShutdown.add(() => |
| 25 { |
| 26 messageManager.removeMessageListener("ElemHideHelper:SelectionStarted", |
| 27 selectionStarted); |
| 28 messageManager.removeMessageListener("ElemHideHelper:SelectionSucceeded", |
| 29 selectionSucceeded); |
| 30 messageManager.removeMessageListener("ElemHideHelper:SelectionStopped", |
| 31 selectionStopped); |
| 18 | 32 |
| 19 /********************************* | 33 selectionStopped(); |
| 20 * Minimal element creation code * | 34 }); |
| 21 *********************************/ | |
| 22 | 35 |
| 23 function createElement(doc, tagName, attrs, children) | 36 function selectionStarted(message) |
| 24 { | 37 { |
| 25 let el = doc.createElement(tagName); | 38 Aardvark.selectionStarted(); |
| 26 if (attrs) | 39 } |
| 27 for (let key in attrs) | 40 |
| 28 el.setAttribute(key, attrs[key]); | 41 function selectionSucceeded(message) |
| 29 if (children) | 42 { |
| 30 for (let child of children) | 43 Aardvark.selectionSucceeded(message.data); |
| 31 el.appendChild(child) | 44 } |
| 32 return el; | 45 |
| 33 }; | 46 function selectionStopped(message) |
| 47 { |
| 48 Aardvark.selectionStopped(); |
| 49 } |
| 34 | 50 |
| 35 /********************************** | 51 /********************************** |
| 36 * General element selection code * | 52 * General element selection code * |
| 37 **********************************/ | 53 **********************************/ |
| 38 | 54 |
| 39 let Aardvark = exports.Aardvark = | 55 let Aardvark = exports.Aardvark = |
| 40 { | 56 { |
| 41 window: null, | 57 window: null, |
| 42 browser: null, | 58 browser: null, |
| 43 anchorElem: null, | 59 rememberedWrapper: null, |
| 44 selectedElem: null, | |
| 45 isUserSelected: false, | |
| 46 lockedAnchor: null, | |
| 47 commentElem: null, | |
| 48 mouseX: -1, | 60 mouseX: -1, |
| 49 mouseY: -1, | 61 mouseY: -1, |
| 50 prevSelectionUpdate: -1, | |
| 51 commandLabelTimer: null, | 62 commandLabelTimer: null, |
| 52 viewSourceTimer: null, | 63 viewSourceTimer: null, |
| 53 boxElem: null, | |
| 54 paintNode: null, | |
| 55 prevPos: null, | |
| 56 | 64 |
| 57 start: function(wrapper) | 65 start: function(wrapper) |
| 58 { | 66 { |
| 59 if (!this.canSelect(wrapper.browser)) | 67 this.rememberedWrapper = wrapper; |
| 60 return; | 68 let browser = wrapper.browser; |
| 69 if ("selectedBrowser" in browser) |
| 70 browser = browser.selectedBrowser; |
| 71 messageManager.broadcastAsyncMessage( |
| 72 "ElemHideHelper:StartSelection", |
| 73 browser.outerWindowID |
| 74 ); |
| 75 }, |
| 61 | 76 |
| 62 if (this.browser) | 77 selectionStarted: function() |
| 63 this.quit(); | 78 { |
| 79 let wrapper = this.rememberedWrapper; |
| 80 this.rememberedWrapper = null; |
| 64 | 81 |
| 65 this.window = wrapper.window; | 82 this.window = wrapper.window; |
| 66 this.browser = wrapper.browser; | 83 this.browser = wrapper.browser; |
| 67 E = id => wrapper.E(id); | 84 E = id => wrapper.E(id); |
| 68 | 85 |
| 69 this.browser.addEventListener("click", this.onMouseClick, true); | |
| 70 this.browser.addEventListener("DOMMouseScroll", this.onMouseScroll, true); | |
| 71 this.browser.addEventListener("keypress", this.onKeyPress, true); | 86 this.browser.addEventListener("keypress", this.onKeyPress, true); |
| 72 this.browser.addEventListener("mousemove", this.onMouseMove, true); | 87 this.browser.addEventListener("mousemove", this.onMouseMove, false); |
| 73 this.browser.addEventListener("select", this.quit, false); | 88 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 | 89 |
| 88 this.initHelpBox(); | 90 this.initHelpBox(); |
| 89 | 91 |
| 90 if (Prefs.showhelp) | 92 if (Prefs.showhelp) |
| 91 this.showMenu(); | 93 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 }, | 94 }, |
| 98 | 95 |
| 99 canSelect: function(browser) | 96 selectionSucceeded: function(nodeInfo) |
| 100 { | 97 { |
| 101 if (!browser || !browser.contentWindow || | 98 this.window.openDialog("chrome://elemhidehelper/content/composer.xul", |
| 102 !(browser.contentDocument instanceof Ci.nsIDOMHTMLDocument)) | 99 "_blank", "chrome,centerscreen,resizable,dialog=no", nodeInfo); |
| 103 { | 100 }, |
| 104 return false; | |
| 105 } | |
| 106 | 101 |
| 107 let location = browser.contentWindow.location; | 102 selectionStopped: function() |
| 108 if (location.href == "about:blank") | 103 { |
| 109 return false; | 104 if (!this.browser) |
| 105 return; |
| 110 | 106 |
| 111 if (!Prefs.acceptlocalfiles && | 107 if (this.commandLabelTimer) |
| 112 location.hostname == "" && | 108 this.commandLabelTimer.cancel(); |
| 113 location.protocol != "mailbox:" && | 109 if (this.viewSourceTimer) |
| 114 location.protocol != "imap:" && | 110 this.viewSourceTimer.cancel(); |
| 115 location.protocol != "news:" && | 111 this.commandLabelTimer = null; |
| 116 location.protocol != "snews:") | 112 this.viewSourceTimer = null; |
| 117 { | |
| 118 return false; | |
| 119 } | |
| 120 | 113 |
| 121 return true; | 114 this.hideTooltips(); |
| 115 |
| 116 this.browser.removeEventListener("keypress", this.onKeyPress, true); |
| 117 this.browser.removeEventListener("mousemove", this.onMouseMove, false); |
| 118 this.browser.removeEventListener("select", this.onTabSelect, false); |
| 119 |
| 120 this.window = null; |
| 121 this.browser = null; |
| 122 E = id => null; |
| 122 }, | 123 }, |
| 123 | 124 |
| 124 doCommand: function(command, event) | 125 doCommand: function(command, event) |
| 125 { | 126 { |
| 126 if (this[command](this.selectedElem)) | 127 let showFeedback; |
| 128 if (this.hasOwnProperty(command)) |
| 129 showFeedback = this[command](); |
| 130 else |
| 131 { |
| 132 showFeedback = (command != "select" && command != "quit"); |
| 133 messageManager.broadcastAsyncMessage("ElemHideHelper:Command", command); |
| 134 } |
| 135 |
| 136 if (showFeedback) |
| 127 { | 137 { |
| 128 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma
nd + "_altkey"], this.commands[command + "_label"]); | 138 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma
nd + "_altkey"], this.commands[command + "_label"]); |
| 129 if (event) | 139 if (event) |
| 130 event.stopPropagation(); | 140 event.stopPropagation(); |
| 131 } | 141 } |
| 132 if (event) | 142 if (event) |
| 133 event.preventDefault(); | 143 event.preventDefault(); |
| 134 }, | 144 }, |
| 135 | 145 |
| 136 showCommandLabel: function(key, alternativeKey, label) | 146 showCommandLabel: function(key, alternativeKey, label) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 { | 207 { |
| 198 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; | 208 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; |
| 199 for (let i = 0; i < tooltips.length; i++) | 209 for (let i = 0; i < tooltips.length; i++) |
| 200 { | 210 { |
| 201 let tooltip = E(tooltips[i]); | 211 let tooltip = E(tooltips[i]); |
| 202 if (tooltip) | 212 if (tooltip) |
| 203 tooltip.hidePopup(); | 213 tooltip.hidePopup(); |
| 204 } | 214 } |
| 205 }, | 215 }, |
| 206 | 216 |
| 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) | 217 onKeyPress: function(event) |
| 227 { | 218 { |
| 228 if (event.altKey || event.ctrlKey || event.metaKey) | 219 if (event.altKey || event.ctrlKey || event.metaKey) |
| 229 return; | 220 return; |
| 230 | 221 |
| 231 var command = null; | 222 var command = null; |
| 232 if (event.keyCode == event.DOM_VK_ESCAPE) | 223 if (event.keyCode == event.DOM_VK_ESCAPE) |
| 233 command = "quit"; | 224 command = "quit"; |
| 234 else if (event.keyCode == event.DOM_VK_RETURN) | 225 else if (event.keyCode == event.DOM_VK_RETURN) |
| 235 command = "select"; | 226 command = "select"; |
| 236 else if (event.charCode) | 227 else if (event.charCode) |
| 237 { | 228 { |
| 238 var key = String.fromCharCode(event.charCode).toLowerCase(); | 229 var key = String.fromCharCode(event.charCode).toLowerCase(); |
| 239 var commands = this.commands; | 230 var commands = this.commands; |
| 240 for (var i = 0; i < commands.length; i++) | 231 for (var i = 0; i < commands.length; i++) |
| 241 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al
tkey"] == key) | 232 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al
tkey"] == key) |
| 242 command = commands[i]; | 233 command = commands[i]; |
| 243 } | 234 } |
| 244 | 235 |
| 245 if (command) | 236 if (command) |
| 246 this.doCommand(command, event); | 237 this.doCommand(command, event); |
| 247 }, | 238 }, |
| 248 | 239 |
| 249 onPageHide: function(event) | |
| 250 { | |
| 251 this.doCommand("quit", null); | |
| 252 }, | |
| 253 | |
| 254 onMouseMove: function(event) | 240 onMouseMove: function(event) |
| 255 { | 241 { |
| 256 this.mouseX = event.screenX; | 242 this.mouseX = event.screenX; |
| 257 this.mouseY = event.screenY; | 243 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 }, | 244 }, |
| 299 | 245 |
| 300 onAfterPaint: function() | 246 onTabSelect: function(event) |
| 301 { | 247 { |
| 302 // Don't update position too often | 248 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 }, | 249 }, |
| 335 | 250 |
| 336 appendDescription: function(node, value, className) | 251 appendDescription: function(node, value, className) |
| 337 { | 252 { |
| 338 var descr = this.window.document.createElement("description"); | 253 var descr = this.window.document.createElement("description"); |
| 339 descr.setAttribute("value", value); | 254 descr.setAttribute("value", value); |
| 340 if (className) | 255 if (className) |
| 341 descr.setAttribute("class", className); | 256 descr.setAttribute("class", className); |
| 342 node.appendChild(descr); | 257 node.appendChild(descr); |
| 343 }, | 258 }, |
| 344 | 259 |
| 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 /*************************** | 260 /*************************** |
| 487 * Commands implementation * | 261 * Commands implementation * |
| 488 ***************************/ | 262 ***************************/ |
| 489 | 263 |
| 490 commands: [ | 264 commands: [ |
| 491 "select", | 265 "select", |
| 492 "wider", | 266 "wider", |
| 493 "narrower", | 267 "narrower", |
| 494 "lock", | 268 "lock", |
| 495 "quit", | 269 "quit", |
| 496 "blinkElement", | 270 "blinkElement", |
| 497 "viewSource", | 271 "viewSource", |
| 498 "viewSourceWindow", | 272 "viewSourceWindow", |
| 499 "showMenu" | 273 "showMenu" |
| 500 ], | 274 ], |
| 501 | 275 |
| 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) | 276 viewSource: function(elem) |
| 667 { | 277 { |
| 668 if (!elem) | 278 if (!elem) |
| 669 return false; | 279 return false; |
| 670 | 280 |
| 671 var sourceBox = E("ehh-viewsource"); | 281 var sourceBox = E("ehh-viewsource"); |
| 672 if (sourceBox.state == "open" && this.commentElem == elem) | 282 if (sourceBox.state == "open") |
| 673 { | 283 { |
| 674 sourceBox.hidePopup(); | 284 sourceBox.hidePopup(); |
| 675 return true; | 285 return true; |
| 676 } | 286 } |
| 677 sourceBox.hidePopup(); | 287 sourceBox.hidePopup(); |
| 678 | 288 |
| 679 while (sourceBox.firstElementChild) | 289 while (sourceBox.firstElementChild) |
| 680 sourceBox.removeChild(sourceBox.firstElementChild); | 290 sourceBox.removeChild(sourceBox.firstElementChild); |
| 681 this.getOuterHtmlFormatted(elem, sourceBox); | 291 this.getOuterHtmlFormatted(elem, sourceBox); |
| 682 this.commentElem = elem; | |
| 683 | 292 |
| 684 let anchor = this.window.document.documentElement; | 293 let anchor = this.window.document.documentElement; |
| 685 let x = this.mouseX; | 294 let x = this.mouseX; |
| 686 let y = this.mouseY; | 295 let y = this.mouseY; |
| 687 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer
); | 296 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer
); |
| 688 this.viewSourceTimer.initWithCallback(function() | 297 this.viewSourceTimer.initWithCallback(function() |
| 689 { | 298 { |
| 690 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); | 299 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); |
| 691 Aardvark.viewSourceTimer = null; | 300 Aardvark.viewSourceTimer = null; |
| 692 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); | 301 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 } | 426 } |
| 818 | 427 |
| 819 // Show help box | 428 // Show help box |
| 820 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); | 429 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); |
| 821 return true; | 430 return true; |
| 822 } | 431 } |
| 823 } | 432 } |
| 824 | 433 |
| 825 // Makes sure event handlers like Aardvark.onKeyPress always have the correct | 434 // Makes sure event handlers like Aardvark.onKeyPress always have the correct |
| 826 // this pointer set. | 435 // this pointer set. |
| 827 for (let method of ["onMouseClick", "onMouseScroll", "onKeyPress", "onPageHide",
"onMouseMove", "onAfterPaint", "quit"]) | 436 for (let method of ["onKeyPress", "onMouseMove", "onTabSelect"]) |
| 828 Aardvark[method] = Aardvark[method].bind(Aardvark); | 437 Aardvark[method] = Aardvark[method].bind(Aardvark); |
| OLD | NEW |