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 {Prefs} = require("prefs"); | 7 let {Prefs} = require("prefs"); |
8 | 8 |
9 // Make sure to stop selection when we are uninstalled | 9 // Make sure to stop selection when we are uninstalled |
10 onShutdown.add(function() Aardvark.quit()); | 10 onShutdown.add(function() Aardvark.quit()); |
(...skipping 20 matching lines...) Expand all Loading... |
31 commandLabelTimer: null, | 31 commandLabelTimer: null, |
32 viewSourceTimer: null, | 32 viewSourceTimer: null, |
33 boxElem: null, | 33 boxElem: null, |
34 paintNode: null, | 34 paintNode: null, |
35 prevPos: null, | 35 prevPos: null, |
36 | 36 |
37 start: function(wrapper) | 37 start: function(wrapper) |
38 { | 38 { |
39 if (!this.canSelect(wrapper.browser)) | 39 if (!this.canSelect(wrapper.browser)) |
40 return; | 40 return; |
41 | 41 |
42 if (this.browser) | 42 if (this.browser) |
43 this.quit(); | 43 this.quit(); |
44 | 44 |
45 this.window = wrapper.window; | 45 this.window = wrapper.window; |
46 this.browser = wrapper.browser; | 46 this.browser = wrapper.browser; |
47 E = function(id) wrapper.E(id); | 47 E = function(id) wrapper.E(id); |
48 | 48 |
49 this.browser.addEventListener("click", this.onMouseClick, true); | 49 this.browser.addEventListener("click", this.onMouseClick, true); |
50 this.browser.addEventListener("DOMMouseScroll", this.onMouseScroll, true); | 50 this.browser.addEventListener("DOMMouseScroll", this.onMouseScroll, true); |
51 this.browser.addEventListener("keypress", this.onKeyPress, true); | 51 this.browser.addEventListener("keypress", this.onKeyPress, true); |
52 this.browser.addEventListener("mousemove", this.onMouseMove, true); | 52 this.browser.addEventListener("mousemove", this.onMouseMove, true); |
53 this.browser.addEventListener("select", this.quit, false); | 53 this.browser.addEventListener("select", this.quit, false); |
54 this.browser.contentWindow.addEventListener("pagehide", this.onPageHide, tru
e); | 54 this.browser.contentWindow.addEventListener("pagehide", this.onPageHide, tru
e); |
55 | 55 |
56 this.browser.contentWindow.focus(); | 56 this.browser.contentWindow.focus(); |
57 | 57 |
58 let doc = this.browser.contentDocument; | 58 let doc = this.browser.contentDocument; |
59 this.boxElem = doc.importNode(E("ehh-elementmarker").firstElementChild.clone
Node(true), true); | 59 this.boxElem = doc.importNode(E("ehh-elementmarker").firstElementChild.clone
Node(true), true); |
60 | 60 |
61 this.initHelpBox(); | 61 this.initHelpBox(); |
62 | 62 |
63 if (Prefs.showhelp) | 63 if (Prefs.showhelp) |
64 this.showMenu(); | 64 this.showMenu(); |
65 | 65 |
66 // Make sure to select some element immeditely (whichever is in the center o
f the browser window) | 66 // Make sure to select some element immeditely (whichever is in the center o
f the browser window) |
67 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); | 67 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); |
68 this.isUserSelected = false; | 68 this.isUserSelected = false; |
69 this.onMouseMove({clientX: wndWidth / 2, clientY: wndHeight / 2, screenX: -1
, screenY: -1, target: null}); | 69 this.onMouseMove({clientX: wndWidth / 2, clientY: wndHeight / 2, screenX: -1
, screenY: -1, target: null}); |
70 }, | 70 }, |
71 | 71 |
72 canSelect: function(browser) | 72 canSelect: function(browser) |
73 { | 73 { |
74 if (!browser || !browser.contentWindow || | 74 if (!browser || !browser.contentWindow || |
75 !(browser.contentDocument instanceof Ci.nsIDOMHTMLDocument)) | 75 !(browser.contentDocument instanceof Ci.nsIDOMHTMLDocument)) |
76 { | 76 { |
77 return false; | 77 return false; |
78 } | 78 } |
79 | 79 |
80 let location = browser.contentWindow.location; | 80 let location = browser.contentWindow.location; |
81 if (location.href == "about:blank") | 81 if (location.href == "about:blank") |
82 return false; | 82 return false; |
83 | 83 |
84 if (!Prefs.acceptlocalfiles && | 84 if (!Prefs.acceptlocalfiles && |
85 location.hostname == "" && | 85 location.hostname == "" && |
86 location.protocol != "mailbox:" && | 86 location.protocol != "mailbox:" && |
87 location.protocol != "imap:" && | 87 location.protocol != "imap:" && |
88 location.protocol != "news:" && | 88 location.protocol != "news:" && |
89 location.protocol != "snews:") | 89 location.protocol != "snews:") |
90 { | 90 { |
91 return false; | 91 return false; |
92 } | 92 } |
93 | 93 |
94 return true; | 94 return true; |
95 }, | 95 }, |
96 | 96 |
97 doCommand: function(command, event) | 97 doCommand: function(command, event) |
98 { | 98 { |
99 if (this[command](this.selectedElem)) | 99 if (this[command](this.selectedElem)) |
100 { | 100 { |
101 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma
nd + "_altkey"], this.commands[command + "_label"]); | 101 this.showCommandLabel(this.commands[command + "_key"], this.commands[comma
nd + "_altkey"], this.commands[command + "_label"]); |
102 if (event) | 102 if (event) |
103 event.stopPropagation(); | 103 event.stopPropagation(); |
104 } | 104 } |
105 if (event) | 105 if (event) |
106 event.preventDefault(); | 106 event.preventDefault(); |
107 }, | 107 }, |
108 | 108 |
109 showCommandLabel: function(key, alternativeKey, label) | 109 showCommandLabel: function(key, alternativeKey, label) |
110 { | 110 { |
111 if (this.commandLabelTimer) | 111 if (this.commandLabelTimer) |
112 this.commandLabelTimer.cancel(); | 112 this.commandLabelTimer.cancel(); |
113 | 113 |
114 E("ehh-commandlabel-key").textContent = key.toUpperCase(); | 114 E("ehh-commandlabel-key").textContent = key.toUpperCase(); |
115 E("ehh-commandlabel-alternativeKey").textContent = alternativeKey.toUpperCas
e(); | 115 E("ehh-commandlabel-alternativeKey").textContent = alternativeKey.toUpperCas
e(); |
116 E("ehh-commandlabel-label").setAttribute("value", label); | 116 E("ehh-commandlabel-label").setAttribute("value", label); |
117 | 117 |
118 var commandLabel = E("ehh-commandlabel"); | 118 var commandLabel = E("ehh-commandlabel"); |
119 commandLabel.showPopup(this.window.document.documentElement, this.mouseX, th
is.mouseY, "tooltip", "topleft", "topleft"); | 119 commandLabel.showPopup(this.window.document.documentElement, this.mouseX, th
is.mouseY, "tooltip", "topleft", "topleft"); |
120 | 120 |
121 this.commandLabelTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITim
er); | 121 this.commandLabelTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITim
er); |
122 this.commandLabelTimer.initWithCallback(function() | 122 this.commandLabelTimer.initWithCallback(function() |
123 { | 123 { |
124 commandLabel.hidePopup(); | 124 commandLabel.hidePopup(); |
125 Aardvark.commandLabelTimer = null; | 125 Aardvark.commandLabelTimer = null; |
126 }, 400, Ci.nsITimer.TYPE_ONE_SHOT); | 126 }, 400, Ci.nsITimer.TYPE_ONE_SHOT); |
127 }, | 127 }, |
128 | 128 |
129 initHelpBox: function() | 129 initHelpBox: function() |
130 { | 130 { |
131 var helpBoxRows = E("ehh-helpbox-rows"); | 131 var helpBoxRows = E("ehh-helpbox-rows"); |
132 if (helpBoxRows.firstElementChild) | 132 if (helpBoxRows.firstElementChild) |
133 return; | 133 return; |
134 | 134 |
135 // Help box hasn't been filled yet, need to do it now | 135 // Help box hasn't been filled yet, need to do it now |
136 var stringService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsI
StringBundleService); | 136 var stringService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsI
StringBundleService); |
137 var strings = stringService.createBundle("chrome://elemhidehelper/locale/glo
bal.properties"); | 137 var strings = stringService.createBundle("chrome://elemhidehelper/locale/glo
bal.properties"); |
138 | 138 |
139 for (var i = 0; i < this.commands.length; i++) | 139 for (var i = 0; i < this.commands.length; i++) |
140 { | 140 { |
141 var command = this.commands[i]; | 141 var command = this.commands[i]; |
142 var key = strings.GetStringFromName("command." + command + ".key"); | 142 var key = strings.GetStringFromName("command." + command + ".key"); |
143 var alternativeKey = strings.GetStringFromName("command." + command + ".al
ternativeKey"); | 143 var alternativeKey = strings.GetStringFromName("command." + command + ".al
ternativeKey"); |
144 var label = strings.GetStringFromName("command." + command + ".label"); | 144 var label = strings.GetStringFromName("command." + command + ".label"); |
145 this.commands[command + "_key"] = key.toLowerCase(); | 145 this.commands[command + "_key"] = key.toLowerCase(); |
146 this.commands[command + "_altkey"] = alternativeKey.toLowerCase(); | 146 this.commands[command + "_altkey"] = alternativeKey.toLowerCase(); |
147 this.commands[command + "_label"] = label; | 147 this.commands[command + "_label"] = label; |
148 | 148 |
149 var row = this.window.document.createElement("row"); | 149 var row = this.window.document.createElement("row"); |
150 helpBoxRows.appendChild(row); | 150 helpBoxRows.appendChild(row); |
151 | 151 |
152 var element = this.window.document.createElement("description"); | 152 var element = this.window.document.createElement("description"); |
153 element.textContent = key.toUpperCase(); | 153 element.textContent = key.toUpperCase(); |
154 element.className = "key"; | 154 element.className = "key"; |
155 row.appendChild(element); | 155 row.appendChild(element); |
156 | 156 |
157 var element = this.window.document.createElement("description"); | 157 var element = this.window.document.createElement("description"); |
158 element.textContent = alternativeKey.toUpperCase(); | 158 element.textContent = alternativeKey.toUpperCase(); |
159 element.className = "key"; | 159 element.className = "key"; |
160 row.appendChild(element); | 160 row.appendChild(element); |
161 | 161 |
162 element = this.window.document.createElement("description"); | 162 element = this.window.document.createElement("description"); |
163 element.setAttribute("value", label); | 163 element.setAttribute("value", label); |
164 element.className = "label"; | 164 element.className = "label"; |
165 row.appendChild(element); | 165 row.appendChild(element); |
166 } | 166 } |
167 }, | 167 }, |
168 | 168 |
169 hideTooltips: function() | 169 hideTooltips: function() |
170 { | 170 { |
171 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; | 171 let tooltips = ["ehh-helpbox", "ehh-commandlabel", "ehh-viewsource"]; |
172 for (let i = 0; i < tooltips.length; i++) | 172 for (let i = 0; i < tooltips.length; i++) |
173 { | 173 { |
174 let tooltip = E(tooltips[i]); | 174 let tooltip = E(tooltips[i]); |
175 if (tooltip) | 175 if (tooltip) |
176 tooltip.hidePopup(); | 176 tooltip.hidePopup(); |
177 } | 177 } |
178 }, | 178 }, |
179 | 179 |
180 onMouseClick: function(event) | 180 onMouseClick: function(event) |
181 { | 181 { |
182 if (event.button != 0 || event.shiftKey || event.altKey || event.ctrlKey ||
event.metaKey) | 182 if (event.button != 0 || event.shiftKey || event.altKey || event.ctrlKey ||
event.metaKey) |
183 return; | 183 return; |
184 | 184 |
185 this.doCommand("select", event); | 185 this.doCommand("select", event); |
186 }, | 186 }, |
187 | 187 |
188 onMouseScroll: function(event) | 188 onMouseScroll: function(event) |
189 { | 189 { |
190 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) | 190 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) |
191 return; | 191 return; |
192 | 192 |
193 if ("axis" in event && event.axis != event.VERTICAL_AXIS) | 193 if ("axis" in event && event.axis != event.VERTICAL_AXIS) |
194 return; | 194 return; |
195 | 195 |
196 for (let i = 0; i < Math.abs(event.detail); i++) | 196 this.doCommand(event.detail > 0 ? "wider" : "narrower", event); |
197 this.doCommand(event.detail > 0 ? "wider" : "narrower", event); | |
198 }, | 197 }, |
199 | 198 |
200 onKeyPress: function(event) | 199 onKeyPress: function(event) |
201 { | 200 { |
202 if (event.altKey || event.ctrlKey || event.metaKey) | 201 if (event.altKey || event.ctrlKey || event.metaKey) |
203 return; | 202 return; |
204 | 203 |
205 var command = null; | 204 var command = null; |
206 if (event.keyCode == event.DOM_VK_ESCAPE) | 205 if (event.keyCode == event.DOM_VK_ESCAPE) |
207 command = "quit"; | 206 command = "quit"; |
208 else if (event.keyCode == event.DOM_VK_RETURN) | 207 else if (event.keyCode == event.DOM_VK_RETURN) |
209 command = "select"; | 208 command = "select"; |
210 else if (event.charCode) | 209 else if (event.charCode) |
211 { | 210 { |
212 var key = String.fromCharCode(event.charCode).toLowerCase(); | 211 var key = String.fromCharCode(event.charCode).toLowerCase(); |
213 var commands = this.commands; | 212 var commands = this.commands; |
214 for (var i = 0; i < commands.length; i++) | 213 for (var i = 0; i < commands.length; i++) |
215 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al
tkey"] == key) | 214 if (commands[commands[i] + "_key"] == key || commands[commands[i] + "_al
tkey"] == key) |
216 command = commands[i]; | 215 command = commands[i]; |
217 } | 216 } |
218 | 217 |
219 if (command) | 218 if (command) |
220 this.doCommand(command, event); | 219 this.doCommand(command, event); |
221 }, | 220 }, |
222 | 221 |
223 onPageHide: function(event) | 222 onPageHide: function(event) |
224 { | 223 { |
225 this.doCommand("quit", null); | 224 this.doCommand("quit", null); |
226 }, | 225 }, |
227 | 226 |
228 onMouseMove: function(event) | 227 onMouseMove: function(event) |
229 { | 228 { |
230 this.mouseX = event.screenX; | 229 this.mouseX = event.screenX; |
231 this.mouseY = event.screenY; | 230 this.mouseY = event.screenY; |
232 | 231 |
233 this.hideSelection(); | 232 this.hideSelection(); |
234 | 233 |
235 let x = event.clientX; | 234 let x = event.clientX; |
236 let y = event.clientY; | 235 let y = event.clientY; |
237 | 236 |
238 // We might have coordinates relative to a frame, recalculate relative to to
p window | 237 // We might have coordinates relative to a frame, recalculate relative to to
p window |
239 let node = event.target; | 238 let node = event.target; |
240 while (node && node.ownerDocument && node.ownerDocument.defaultView && node.
ownerDocument.defaultView.frameElement) | 239 while (node && node.ownerDocument && node.ownerDocument.defaultView && node.
ownerDocument.defaultView.frameElement) |
241 { | 240 { |
242 node = node.ownerDocument.defaultView.frameElement; | 241 node = node.ownerDocument.defaultView.frameElement; |
243 let rect = node.getBoundingClientRect(); | 242 let rect = node.getBoundingClientRect(); |
244 x += rect.left; | 243 x += rect.left; |
245 y += rect.top; | 244 y += rect.top; |
246 } | 245 } |
247 | 246 |
248 let elem = this.browser.contentDocument.elementFromPoint(x, y); | 247 let elem = this.browser.contentDocument.elementFromPoint(x, y); |
249 while (elem && "contentDocument" in elem && this.canSelect(elem)) | 248 while (elem && "contentDocument" in elem && this.canSelect(elem)) |
250 { | 249 { |
251 let rect = elem.getBoundingClientRect(); | 250 let rect = elem.getBoundingClientRect(); |
252 x -= rect.left; | 251 x -= rect.left; |
253 y -= rect.top; | 252 y -= rect.top; |
254 elem = elem.contentDocument.elementFromPoint(x, y); | 253 elem = elem.contentDocument.elementFromPoint(x, y); |
255 } | 254 } |
256 | 255 |
257 if (elem) | 256 if (elem) |
258 { | 257 { |
259 if (!this.lockedAnchor) | 258 if (!this.lockedAnchor) |
260 this.setAnchorElement(elem); | 259 this.setAnchorElement(elem); |
261 else | 260 else |
262 { | 261 { |
263 this.lockedAnchor = elem; | 262 this.lockedAnchor = elem; |
264 this.selectElement(this.selectedElem); | 263 this.selectElement(this.selectedElem); |
265 } | 264 } |
266 } | 265 } |
267 }, | 266 }, |
268 | 267 |
269 onAfterPaint: function() | 268 onAfterPaint: function() |
270 { | 269 { |
271 // Don't update position too often | 270 // Don't update position too often |
272 if (this.selectedElem && Date.now() - this.prevSelectionUpdate > 20) | 271 if (this.selectedElem && Date.now() - this.prevSelectionUpdate > 20) |
273 { | 272 { |
274 let pos = this.getElementPosition(this.selectedElem); | 273 let pos = this.getElementPosition(this.selectedElem); |
275 if (!this.prevPos || this.prevPos.left != pos.left || this.prevPos.right !
= pos.right | 274 if (!this.prevPos || this.prevPos.left != pos.left || this.prevPos.right !
= pos.right |
276 || this.prevPos.top != pos.top || this.prevPos.bottom !=
pos.bottom) | 275 || this.prevPos.top != pos.top || this.prevPos.bottom !=
pos.bottom) |
277 { | 276 { |
278 this.selectElement(this.selectedElem); | 277 this.selectElement(this.selectedElem); |
279 } | 278 } |
280 } | 279 } |
281 }, | 280 }, |
282 | 281 |
283 setAnchorElement: function(anchor) | 282 setAnchorElement: function(anchor) |
284 { | 283 { |
285 this.anchorElem = anchor; | 284 this.anchorElem = anchor; |
286 | 285 |
287 let newSelection = anchor; | 286 let newSelection = anchor; |
288 if (this.isUserSelected) | 287 if (this.isUserSelected) |
289 { | 288 { |
290 // User chose an element via wider/narrower commands, keep the selection i
f | 289 // User chose an element via wider/narrower commands, keep the selection i
f |
291 // out new anchor is still a child of that element | 290 // out new anchor is still a child of that element |
292 let e = newSelection; | 291 let e = newSelection; |
293 while (e && e != this.selectedElem) | 292 while (e && e != this.selectedElem) |
294 e = this.getParentElement(e); | 293 e = this.getParentElement(e); |
295 | 294 |
296 if (e) | 295 if (e) |
297 newSelection = this.selectedElem; | 296 newSelection = this.selectedElem; |
298 else | 297 else |
299 this.isUserSelected = false; | 298 this.isUserSelected = false; |
300 } | 299 } |
301 | 300 |
302 this.selectElement(newSelection); | 301 this.selectElement(newSelection); |
303 }, | 302 }, |
304 | 303 |
305 appendDescription: function(node, value, className) | 304 appendDescription: function(node, value, className) |
306 { | 305 { |
307 var descr = this.window.document.createElement("description"); | 306 var descr = this.window.document.createElement("description"); |
308 descr.setAttribute("value", value); | 307 descr.setAttribute("value", value); |
309 if (className) | 308 if (className) |
310 descr.setAttribute("class", className); | 309 descr.setAttribute("class", className); |
311 node.appendChild(descr); | 310 node.appendChild(descr); |
312 }, | 311 }, |
313 | 312 |
314 /************************** | 313 /************************** |
315 * Element marker display * | 314 * Element marker display * |
316 **************************/ | 315 **************************/ |
317 | 316 |
318 getElementLabel: function(elem) | 317 getElementLabel: function(elem) |
319 { | 318 { |
320 let tagName = elem.tagName.toLowerCase(); | 319 let tagName = elem.tagName.toLowerCase(); |
321 let addition = ""; | 320 let addition = ""; |
322 if (elem.id != "") | 321 if (elem.id != "") |
323 addition += ", id: " + elem.id; | 322 addition += ", id: " + elem.id; |
324 if (elem.className != "") | 323 if (elem.className != "") |
325 addition += ", class: " + elem.className; | 324 addition += ", class: " + elem.className; |
326 if (elem.style.cssText != "") | 325 if (elem.style.cssText != "") |
327 addition += ", style: " + elem.style.cssText; | 326 addition += ", style: " + elem.style.cssText; |
328 | 327 |
329 return [tagName, addition]; | 328 return [tagName, addition]; |
330 }, | 329 }, |
331 | 330 |
332 selectElement: function(elem) | 331 selectElement: function(elem) |
333 { | 332 { |
334 this.selectedElem = elem; | 333 this.selectedElem = elem; |
335 this.prevSelectionUpdate = Date.now(); | 334 this.prevSelectionUpdate = Date.now(); |
336 | 335 |
337 let border = this.boxElem.getElementsByClassName("ehh-border")[0]; | 336 let border = this.boxElem.getElementsByClassName("ehh-border")[0]; |
338 let label = this.boxElem.getElementsByClassName("ehh-label")[0]; | 337 let label = this.boxElem.getElementsByClassName("ehh-label")[0]; |
339 let labelTag = this.boxElem.getElementsByClassName("ehh-labelTag")[0]; | 338 let labelTag = this.boxElem.getElementsByClassName("ehh-labelTag")[0]; |
340 let labelAddition = this.boxElem.getElementsByClassName("ehh-labelAddition")
[0]; | 339 let labelAddition = this.boxElem.getElementsByClassName("ehh-labelAddition")
[0]; |
341 | 340 |
342 if (this.boxElem.parentNode) | 341 if (this.boxElem.parentNode) |
343 this.boxElem.parentNode.removeChild(this.boxElem); | 342 this.boxElem.parentNode.removeChild(this.boxElem); |
344 | 343 |
345 let doc = this.browser.contentDocument; | 344 let doc = this.browser.contentDocument; |
346 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); | 345 let [wndWidth, wndHeight] = this.getWindowSize(doc.defaultView); |
347 | 346 |
348 let pos = this.getElementPosition(elem); | 347 let pos = this.getElementPosition(elem); |
349 this.boxElem.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; | 348 this.boxElem.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; |
350 this.boxElem.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; | 349 this.boxElem.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; |
351 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; | 350 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; |
352 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; | 351 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; |
353 | 352 |
354 [labelTag.textContent, labelAddition.textContent] = this.getElementLabel(ele
m); | 353 [labelTag.textContent, labelAddition.textContent] = this.getElementLabel(ele
m); |
355 | 354 |
356 // If there is not enough space to show the label move it up a little | 355 // If there is not enough space to show the label move it up a little |
357 if (pos.bottom < wndHeight - 25) | 356 if (pos.bottom < wndHeight - 25) |
358 label.className = "ehh-label"; | 357 label.className = "ehh-label"; |
359 else | 358 else |
360 label.className = "ehh-label onTop"; | 359 label.className = "ehh-label onTop"; |
361 | 360 |
362 doc.documentElement.appendChild(this.boxElem); | 361 doc.documentElement.appendChild(this.boxElem); |
363 | 362 |
364 this.paintNode = doc.defaultView; | 363 this.paintNode = doc.defaultView; |
365 if (this.paintNode) | 364 if (this.paintNode) |
366 { | 365 { |
367 this.prevPos = pos; | 366 this.prevPos = pos; |
368 this.paintNode.addEventListener("MozAfterPaint", this.onAfterPaint, false)
; | 367 this.paintNode.addEventListener("MozAfterPaint", this.onAfterPaint, false)
; |
369 } | 368 } |
370 }, | 369 }, |
371 | 370 |
(...skipping 17 matching lines...) Expand all Loading... |
389 { | 388 { |
390 // Restrict rectangle coordinates by the boundaries of a window's client are
a | 389 // Restrict rectangle coordinates by the boundaries of a window's client are
a |
391 function intersectRect(rect, wnd) | 390 function intersectRect(rect, wnd) |
392 { | 391 { |
393 let [wndWidth, wndHeight] = this.getWindowSize(wnd); | 392 let [wndWidth, wndHeight] = this.getWindowSize(wnd); |
394 rect.left = Math.max(rect.left, 0); | 393 rect.left = Math.max(rect.left, 0); |
395 rect.top = Math.max(rect.top, 0); | 394 rect.top = Math.max(rect.top, 0); |
396 rect.right = Math.min(rect.right, wndWidth); | 395 rect.right = Math.min(rect.right, wndWidth); |
397 rect.bottom = Math.min(rect.bottom, wndHeight); | 396 rect.bottom = Math.min(rect.bottom, wndHeight); |
398 } | 397 } |
399 | 398 |
400 let rect = element.getBoundingClientRect(); | 399 let rect = element.getBoundingClientRect(); |
401 let wnd = element.ownerDocument.defaultView; | 400 let wnd = element.ownerDocument.defaultView; |
402 | 401 |
403 rect = {left: rect.left, top: rect.top, | 402 rect = {left: rect.left, top: rect.top, |
404 right: rect.right, bottom: rect.bottom}; | 403 right: rect.right, bottom: rect.bottom}; |
405 while (true) | 404 while (true) |
406 { | 405 { |
407 intersectRect.call(this, rect, wnd); | 406 intersectRect.call(this, rect, wnd); |
408 | 407 |
409 if (!wnd.frameElement) | 408 if (!wnd.frameElement) |
410 break; | 409 break; |
411 | 410 |
412 // Recalculate coordinates to be relative to frame's parent window | 411 // Recalculate coordinates to be relative to frame's parent window |
413 let frameElement = wnd.frameElement; | 412 let frameElement = wnd.frameElement; |
414 wnd = frameElement.ownerDocument.defaultView; | 413 wnd = frameElement.ownerDocument.defaultView; |
415 | 414 |
416 let frameRect = frameElement.getBoundingClientRect(); | 415 let frameRect = frameElement.getBoundingClientRect(); |
417 let frameStyle = wnd.getComputedStyle(frameElement, null); | 416 let frameStyle = wnd.getComputedStyle(frameElement, null); |
418 let relLeft = frameRect.left + parseFloat(frameStyle.borderLeftWidth) + pa
rseFloat(frameStyle.paddingLeft); | 417 let relLeft = frameRect.left + parseFloat(frameStyle.borderLeftWidth) + pa
rseFloat(frameStyle.paddingLeft); |
419 let relTop = frameRect.top + parseFloat(frameStyle.borderTopWidth) + parse
Float(frameStyle.paddingTop); | 418 let relTop = frameRect.top + parseFloat(frameStyle.borderTopWidth) + parse
Float(frameStyle.paddingTop); |
420 | 419 |
421 rect.left += relLeft; | 420 rect.left += relLeft; |
422 rect.right += relLeft; | 421 rect.right += relLeft; |
423 rect.top += relTop; | 422 rect.top += relTop; |
424 rect.bottom += relTop; | 423 rect.bottom += relTop; |
425 } | 424 } |
426 | 425 |
427 return rect; | 426 return rect; |
428 }, | 427 }, |
429 | 428 |
430 getParentElement: function(elem) | 429 getParentElement: function(elem) |
431 { | 430 { |
432 let result = elem.parentNode; | 431 let result = elem.parentNode; |
433 if (result && result.nodeType == Ci.nsIDOMElement.DOCUMENT_NODE && result.de
faultView && result.defaultView.frameElement) | 432 if (result && result.nodeType == Ci.nsIDOMElement.DOCUMENT_NODE && result.de
faultView && result.defaultView.frameElement) |
434 result = result.defaultView.frameElement; | 433 result = result.defaultView.frameElement; |
435 | 434 |
436 if (result && result.nodeType != Ci.nsIDOMElement.ELEMENT_NODE) | 435 if (result && result.nodeType != Ci.nsIDOMElement.ELEMENT_NODE) |
437 return null; | 436 return null; |
438 | 437 |
439 return result; | 438 return result; |
440 }, | 439 }, |
441 | 440 |
442 /*************************** | 441 /*************************** |
443 * Commands implementation * | 442 * Commands implementation * |
444 ***************************/ | 443 ***************************/ |
445 | 444 |
446 commands: [ | 445 commands: [ |
447 "select", | 446 "select", |
448 "wider", | 447 "wider", |
449 "narrower", | 448 "narrower", |
450 "lock", | 449 "lock", |
451 "quit", | 450 "quit", |
452 "blinkElement", | 451 "blinkElement", |
453 "viewSource", | 452 "viewSource", |
454 "viewSourceWindow", | 453 "viewSourceWindow", |
455 "showMenu" | 454 "showMenu" |
456 ], | 455 ], |
457 | 456 |
458 wider: function(elem) | 457 wider: function(elem) |
459 { | 458 { |
460 if (!elem) | 459 if (!elem) |
461 return false; | 460 return false; |
462 | 461 |
463 let newElem = this.getParentElement(elem); | 462 let newElem = this.getParentElement(elem); |
464 if (!newElem) | 463 if (!newElem) |
465 return false; | 464 return false; |
466 | 465 |
467 this.isUserSelected = true; | 466 this.isUserSelected = true; |
468 this.selectElement(newElem); | 467 this.selectElement(newElem); |
469 return true; | 468 return true; |
470 }, | 469 }, |
471 | 470 |
472 narrower: function(elem) | 471 narrower: function(elem) |
473 { | 472 { |
474 if (elem) | 473 if (elem) |
475 { | 474 { |
476 // Search selected element in the parent chain, starting with the anchor e
lement. | 475 // Search selected element in the parent chain, starting with the anchor e
lement. |
477 // We need to select the element just before the selected one. | 476 // We need to select the element just before the selected one. |
478 let e = this.anchorElem; | 477 let e = this.anchorElem; |
479 let newElem = null; | 478 let newElem = null; |
480 while (e && e != elem) | 479 while (e && e != elem) |
481 { | 480 { |
482 newElem = e; | 481 newElem = e; |
483 e = this.getParentElement(e); | 482 e = this.getParentElement(e); |
484 } | 483 } |
485 | 484 |
486 if (!e || !newElem) | 485 if (!e || !newElem) |
487 return false; | 486 return false; |
488 | 487 |
489 this.isUserSelected = true; | 488 this.isUserSelected = true; |
490 this.selectElement(newElem); | 489 this.selectElement(newElem); |
491 return true; | 490 return true; |
492 } | 491 } |
493 return false; | 492 return false; |
494 }, | 493 }, |
495 | 494 |
496 lock: function(elem) | 495 lock: function(elem) |
497 { | 496 { |
498 if (!elem) | 497 if (!elem) |
499 return false; | 498 return false; |
500 | 499 |
501 if (this.lockedAnchor) | 500 if (this.lockedAnchor) |
502 { | 501 { |
503 this.setAnchorElement(this.lockedAnchor); | 502 this.setAnchorElement(this.lockedAnchor); |
504 this.lockedAnchor = null; | 503 this.lockedAnchor = null; |
505 } | 504 } |
506 else | 505 else |
507 this.lockedAnchor = this.anchorElem; | 506 this.lockedAnchor = this.anchorElem; |
508 | 507 |
509 return true; | 508 return true; |
510 }, | 509 }, |
511 | 510 |
512 quit: function() | 511 quit: function() |
513 { | 512 { |
514 if (!this.browser) | 513 if (!this.browser) |
515 return false; | 514 return false; |
516 | 515 |
517 if ("blinkTimer" in this) | 516 if ("blinkTimer" in this) |
518 this.stopBlinking(); | 517 this.stopBlinking(); |
519 | 518 |
520 if (this.commandLabelTimer) | 519 if (this.commandLabelTimer) |
521 this.commandLabelTimer.cancel(); | 520 this.commandLabelTimer.cancel(); |
522 if (this.viewSourceTimer) | 521 if (this.viewSourceTimer) |
523 this.viewSourceTimer.cancel(); | 522 this.viewSourceTimer.cancel(); |
524 this.commandLabelTimer = null; | 523 this.commandLabelTimer = null; |
525 this.viewSourceTimer = null; | 524 this.viewSourceTimer = null; |
526 | 525 |
527 this.hideSelection(); | 526 this.hideSelection(); |
528 this.hideTooltips(); | 527 this.hideTooltips(); |
529 | 528 |
530 this.browser.removeEventListener("click", this.onMouseClick, true); | 529 this.browser.removeEventListener("click", this.onMouseClick, true); |
531 this.browser.removeEventListener("DOMMouseScroll", this.onMouseScroll, true)
; | 530 this.browser.removeEventListener("DOMMouseScroll", this.onMouseScroll, true)
; |
532 this.browser.removeEventListener("keypress", this.onKeyPress, true); | 531 this.browser.removeEventListener("keypress", this.onKeyPress, true); |
533 this.browser.removeEventListener("mousemove", this.onMouseMove, true); | 532 this.browser.removeEventListener("mousemove", this.onMouseMove, true); |
534 this.browser.removeEventListener("select", this.quit, false); | 533 this.browser.removeEventListener("select", this.quit, false); |
535 this.browser.contentWindow.removeEventListener("pagehide", this.onPageHide,
true); | 534 this.browser.contentWindow.removeEventListener("pagehide", this.onPageHide,
true); |
536 | 535 |
537 this.anchorElem = null; | 536 this.anchorElem = null; |
538 this.selectedElem = null; | 537 this.selectedElem = null; |
539 this.window = null; | 538 this.window = null; |
540 this.browser = null; | 539 this.browser = null; |
541 this.commentElem = null; | 540 this.commentElem = null; |
542 this.lockedAnchor = null; | 541 this.lockedAnchor = null; |
543 this.boxElem = null; | 542 this.boxElem = null; |
544 E = function(id) null; | 543 E = function(id) null; |
545 return false; | 544 return false; |
546 }, | 545 }, |
547 | 546 |
548 select: function(elem) | 547 select: function(elem) |
549 { | 548 { |
550 if (!elem) | 549 if (!elem) |
551 return false; | 550 return false; |
552 | 551 |
553 this.window.openDialog("chrome://elemhidehelper/content/composer.xul", "_bla
nk", | 552 this.window.openDialog("chrome://elemhidehelper/content/composer.xul", "_bla
nk", |
554 "chrome,centerscreen,resizable,dialog=no", elem); | 553 "chrome,centerscreen,resizable,dialog=no", elem); |
555 this.quit(); | 554 this.quit(); |
556 return false; | 555 return false; |
557 }, | 556 }, |
558 | 557 |
559 blinkElement: function(elem) | 558 blinkElement: function(elem) |
560 { | 559 { |
561 if (!elem) | 560 if (!elem) |
562 return false; | 561 return false; |
563 | 562 |
564 if ("blinkTimer" in this) | 563 if ("blinkTimer" in this) |
565 this.stopBlinking(); | 564 this.stopBlinking(); |
566 | 565 |
567 let counter = 0; | 566 let counter = 0; |
568 this.blinkElem = elem; | 567 this.blinkElem = elem; |
569 this.blinkOrigValue = elem.style.visibility; | 568 this.blinkOrigValue = elem.style.visibility; |
570 this.blinkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 569 this.blinkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
571 this.blinkTimer.initWithCallback(function() | 570 this.blinkTimer.initWithCallback(function() |
572 { | 571 { |
573 counter++; | 572 counter++; |
574 elem.style.visibility = (counter % 2 == 0 ? "visible" : "hidden"); | 573 elem.style.visibility = (counter % 2 == 0 ? "visible" : "hidden"); |
575 if (counter == 6) | 574 if (counter == 6) |
576 Aardvark.stopBlinking(); | 575 Aardvark.stopBlinking(); |
577 }, 250, Ci.nsITimer.TYPE_REPEATING_SLACK); | 576 }, 250, Ci.nsITimer.TYPE_REPEATING_SLACK); |
578 | 577 |
579 return true; | 578 return true; |
580 }, | 579 }, |
581 | 580 |
582 stopBlinking: function() | 581 stopBlinking: function() |
583 { | 582 { |
584 this.blinkTimer.cancel(); | 583 this.blinkTimer.cancel(); |
585 this.blinkElem.style.visibility = this.blinkOrigValue; | 584 this.blinkElem.style.visibility = this.blinkOrigValue; |
586 | 585 |
587 delete this.blinkElem; | 586 delete this.blinkElem; |
588 delete this.blinkOrigValue; | 587 delete this.blinkOrigValue; |
589 delete this.blinkTimer; | 588 delete this.blinkTimer; |
590 }, | 589 }, |
591 | 590 |
592 viewSource: function(elem) | 591 viewSource: function(elem) |
593 { | 592 { |
594 if (!elem) | 593 if (!elem) |
595 return false; | 594 return false; |
596 | 595 |
597 var sourceBox = E("ehh-viewsource"); | 596 var sourceBox = E("ehh-viewsource"); |
598 if (sourceBox.state == "open" && this.commentElem == elem) | 597 if (sourceBox.state == "open" && this.commentElem == elem) |
599 { | 598 { |
600 sourceBox.hidePopup(); | 599 sourceBox.hidePopup(); |
601 return true; | 600 return true; |
602 } | 601 } |
603 sourceBox.hidePopup(); | 602 sourceBox.hidePopup(); |
604 | 603 |
605 while (sourceBox.firstElementChild) | 604 while (sourceBox.firstElementChild) |
606 sourceBox.removeChild(sourceBox.firstElementChild); | 605 sourceBox.removeChild(sourceBox.firstElementChild); |
607 this.getOuterHtmlFormatted(elem, sourceBox); | 606 this.getOuterHtmlFormatted(elem, sourceBox); |
608 this.commentElem = elem; | 607 this.commentElem = elem; |
609 | 608 |
610 let anchor = this.window.document.documentElement; | 609 let anchor = this.window.document.documentElement; |
611 let x = this.mouseX; | 610 let x = this.mouseX; |
612 let y = this.mouseY; | 611 let y = this.mouseY; |
613 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer
); | 612 this.viewSourceTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer
); |
614 this.viewSourceTimer.initWithCallback(function() | 613 this.viewSourceTimer.initWithCallback(function() |
615 { | 614 { |
616 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); | 615 sourceBox.showPopup(anchor, x, y, "tooltip", "topleft", "topleft"); |
617 Aardvark.viewSourceTimer = null; | 616 Aardvark.viewSourceTimer = null; |
618 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); | 617 }, 500, Ci.nsITimer.TYPE_ONE_SHOT); |
619 return true; | 618 return true; |
620 }, | 619 }, |
621 | 620 |
622 viewSourceWindow: function(elem) | 621 viewSourceWindow: function(elem) |
623 { | 622 { |
624 if (!elem) | 623 if (!elem) |
625 return false; | 624 return false; |
626 | 625 |
627 var range = elem.ownerDocument.createRange(); | 626 var range = elem.ownerDocument.createRange(); |
628 range.selectNodeContents(elem); | 627 range.selectNodeContents(elem); |
629 var selection = {rangeCount: 1, getRangeAt: function() {return range}}; | 628 var selection = {rangeCount: 1, getRangeAt: function() {return range}}; |
630 | 629 |
631 this.window.openDialog("chrome://global/content/viewPartialSource.xul", "_bl
ank", "scrollbars,resizable,chrome,dialog=no", | 630 this.window.openDialog("chrome://global/content/viewPartialSource.xul", "_bl
ank", "scrollbars,resizable,chrome,dialog=no", |
632 null, null, selection, "selection"); | 631 null, null, selection, "selection"); |
633 return true; | 632 return true; |
634 }, | 633 }, |
635 | 634 |
636 getOuterHtmlFormatted: function(node, container) | 635 getOuterHtmlFormatted: function(node, container) |
637 { | 636 { |
638 var type = null; | 637 var type = null; |
639 switch (node.nodeType) | 638 switch (node.nodeType) |
640 { | 639 { |
641 case node.ELEMENT_NODE: | 640 case node.ELEMENT_NODE: |
642 var box = this.window.document.createElement("vbox"); | 641 var box = this.window.document.createElement("vbox"); |
643 box.className = "elementBox"; | 642 box.className = "elementBox"; |
644 | 643 |
645 var startTag = this.window.document.createElement("hbox"); | 644 var startTag = this.window.document.createElement("hbox"); |
646 startTag.className = "elementStartTag"; | 645 startTag.className = "elementStartTag"; |
647 if (!node.firstElementChild) | 646 if (!node.firstElementChild) |
648 startTag.className += " elementEndTag"; | 647 startTag.className += " elementEndTag"; |
649 | 648 |
650 this.appendDescription(startTag, "<", null); | 649 this.appendDescription(startTag, "<", null); |
651 this.appendDescription(startTag, node.tagName, "tagName"); | 650 this.appendDescription(startTag, node.tagName, "tagName"); |
652 | 651 |
653 for (var i = 0; i < node.attributes.length; i++) | 652 for (var i = 0; i < node.attributes.length; i++) |
654 { | 653 { |
655 var attr = node.attributes[i]; | 654 var attr = node.attributes[i]; |
656 this.appendDescription(startTag, attr.name, "attrName"); | 655 this.appendDescription(startTag, attr.name, "attrName"); |
657 if (attr.value != "") | 656 if (attr.value != "") |
658 { | 657 { |
659 this.appendDescription(startTag, "=", null); | 658 this.appendDescription(startTag, "=", null); |
660 this.appendDescription(startTag, '"' + attr.value.replace(/"/, "&quo
t;") + '"', "attrValue"); | 659 this.appendDescription(startTag, '"' + attr.value.replace(/"/, "&quo
t;") + '"', "attrValue"); |
661 } | 660 } |
662 } | 661 } |
663 | 662 |
664 this.appendDescription(startTag, node.firstElementChild ? ">" : " />", n
ull); | 663 this.appendDescription(startTag, node.firstElementChild ? ">" : " />", n
ull); |
665 box.appendChild(startTag); | 664 box.appendChild(startTag); |
666 | 665 |
667 if (node.firstElementChild) | 666 if (node.firstElementChild) |
668 { | 667 { |
669 for (var child = node.firstElementChild; child; child = child.nextElem
entSibling) | 668 for (var child = node.firstElementChild; child; child = child.nextElem
entSibling) |
670 this.getOuterHtmlFormatted(child, box); | 669 this.getOuterHtmlFormatted(child, box); |
671 | 670 |
672 var endTag = this.window.document.createElement("hbox"); | 671 var endTag = this.window.document.createElement("hbox"); |
673 endTag.className = "elementEndTag"; | 672 endTag.className = "elementEndTag"; |
674 this.appendDescription(endTag, "<", null); | 673 this.appendDescription(endTag, "<", null); |
675 this.appendDescription(endTag, "/" + node.tagName, "tagName"); | 674 this.appendDescription(endTag, "/" + node.tagName, "tagName"); |
676 this.appendDescription(endTag, ">", null); | 675 this.appendDescription(endTag, ">", null); |
677 box.appendChild(endTag); | 676 box.appendChild(endTag); |
678 } | 677 } |
679 container.appendChild(box); | 678 container.appendChild(box); |
680 return; | 679 return; |
681 | 680 |
682 case node.TEXT_NODE: | 681 case node.TEXT_NODE: |
683 type = "text"; | 682 type = "text"; |
684 break; | 683 break; |
685 case node.CDATA_SECTION_NODE: | 684 case node.CDATA_SECTION_NODE: |
686 type = "cdata"; | 685 type = "cdata"; |
687 break; | 686 break; |
688 case node.COMMENT_NODE: | 687 case node.COMMENT_NODE: |
689 type = "comment"; | 688 type = "comment"; |
690 break; | 689 break; |
691 default: | 690 default: |
692 return; | 691 return; |
693 } | 692 } |
694 | 693 |
695 var text = node.nodeValue.replace(/\r/g, '').replace(/^\s+/, '').replace(/\s
+$/, ''); | 694 var text = node.nodeValue.replace(/\r/g, '').replace(/^\s+/, '').replace(/\s
+$/, ''); |
696 if (text == "") | 695 if (text == "") |
697 return; | 696 return; |
698 | 697 |
699 if (type != "cdata") | 698 if (type != "cdata") |
700 { | 699 { |
701 text = text.replace(/&/g, "&") | 700 text = text.replace(/&/g, "&") |
702 .replace(/</g, "<") | 701 .replace(/</g, "<") |
703 .replace(/>/g, ">"); | 702 .replace(/>/g, ">"); |
704 } | 703 } |
705 text = text.replace(/\t/g, " "); | 704 text = text.replace(/\t/g, " "); |
706 if (type == "cdata") | 705 if (type == "cdata") |
707 text = "<![CDATA[" + text + "]]>"; | 706 text = "<![CDATA[" + text + "]]>"; |
708 else if (type == "comment") | 707 else if (type == "comment") |
709 text = "<!--" + text + "-->"; | 708 text = "<!--" + text + "-->"; |
710 | 709 |
711 var lines = text.split("\n"); | 710 var lines = text.split("\n"); |
712 for (var i = 0; i < lines.length; i++) | 711 for (var i = 0; i < lines.length; i++) |
713 this.appendDescription(container, lines[i].replace(/^\s+/, '').replace(/\s
+$/, ''), type); | 712 this.appendDescription(container, lines[i].replace(/^\s+/, '').replace(/\s
+$/, ''), type); |
714 }, | 713 }, |
715 | 714 |
716 showMenu: function() | 715 showMenu: function() |
717 { | 716 { |
718 var helpBox = E("ehh-helpbox"); | 717 var helpBox = E("ehh-helpbox"); |
719 if (helpBox.state == "open") | 718 if (helpBox.state == "open") |
720 { | 719 { |
721 helpBox.hidePopup(); | 720 helpBox.hidePopup(); |
722 return true; | 721 return true; |
723 } | 722 } |
724 | 723 |
725 // Show help box | 724 // Show help box |
726 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); | 725 helpBox.showPopup(this.browser, -1, -1, "tooltip", "topleft", "topleft"); |
727 return true; | 726 return true; |
728 } | 727 } |
729 } | 728 } |
730 | 729 |
731 // Makes sure event handlers like Aardvark.onKeyPress always have the correct | 730 // Makes sure event handlers like Aardvark.onKeyPress always have the correct |
732 // this pointer set. | 731 // this pointer set. |
733 for each (let method in ["onMouseClick", "onMouseScroll", "onKeyPress", "onPageH
ide", "onMouseMove", "onAfterPaint", "quit"]) | 732 for each (let method in ["onMouseClick", "onMouseScroll", "onKeyPress", "onPageH
ide", "onMouseMove", "onAfterPaint", "quit"]) |
734 Aardvark[method] = Aardvark[method].bind(Aardvark); | 733 Aardvark[method] = Aardvark[method].bind(Aardvark); |
OLD | NEW |