| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
|
saroyanm
2016/11/23 17:44:39
I thought that this code belongs to Aardvark ?
Wha
Wladimir Palant
2016/11/24 14:02:01
Yes, E10S is the reason for this whole change. Any
| |
| 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 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 9 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
| 10 | 10 |
| 11 let messageManager = require("messageManager"); | 11 let messageManager = require("messageManager"); |
| 12 let { | 12 let { |
| 13 createElement, getWindowSize, getParentElement, getElementPosition | 13 createElement, getWindowSize, getParentElement, getElementPosition |
| 14 } = require("./utils"); | 14 } = require("./utils"); |
| 15 | 15 |
| 16 /** | |
| 17 * @typedef State | |
| 18 * @type {Object} | |
| 19 * @property {Window} window | |
| 20 * The top-level window that we are selecting in. | |
| 21 * @property {Element} boxElement | |
| 22 * The element marking the current selection. | |
| 23 * @property {Element} anchorElement | |
| 24 * The element that received the last mouse event. | |
| 25 * @property {Element} selectedElement | |
| 26 * The element currently selected (usually anchorElement or a parent element | |
| 27 * of it). | |
| 28 * @property {boolean} isUserSelected | |
| 29 * Will be true if the user narrowed down the selection to a specific element | |
| 30 * using wider/narrower commands. | |
| 31 * @property {Element} lockedAnchor | |
| 32 * When selection is locked, this property will be updated by mouse events | |
| 33 * instead of anchorElement. | |
| 34 * @property {number} prevSelectionUpdate | |
| 35 * Time of previous selection update, used for rate limiting. | |
| 36 * @property {Object} prevPos | |
| 37 * Position and size of selected element during previous selection update. | |
| 38 */ | |
| 39 | |
| 40 /** | |
| 41 * Current selection state. This object will be empty if no selection is | |
| 42 * currently in progress. | |
| 43 * | |
| 44 * @type {State} | |
| 45 */ | |
| 16 let state = exports.state = {}; | 46 let state = exports.state = {}; |
|
Wladimir Palant
2016/11/17 13:54:48
Original code was storing the selection state as p
saroyanm
2016/11/23 17:44:39
We are setting the properties of state in other fu
Wladimir Palant
2016/11/24 14:02:02
Setting them here doesn't make sense - the definit
| |
| 17 | 47 |
| 18 messageManager.addMessageListener("ElemHideHelper:StartSelection", startSelectio n); | 48 messageManager.addMessageListener("ElemHideHelper:StartSelection", startSelectio n); |
| 19 | 49 |
| 20 onShutdown.add(() => | 50 onShutdown.add(() => |
| 21 { | 51 { |
| 22 messageManager.removeMessageListener("ElemHideHelper:StartSelection", startSel ection); | 52 messageManager.removeMessageListener("ElemHideHelper:StartSelection", startSel ection); |
| 23 | 53 |
| 24 stopSelection(); | 54 stopSelection(); |
| 25 }); | 55 }); |
| 26 | 56 |
| 27 function startSelection(message) | 57 function startSelection(message) |
| 28 { | 58 { |
| 29 stopSelection(); | 59 stopSelection(); |
| 30 | 60 |
| 31 let outerWindowID = message.data; | 61 let outerWindowID = message.data; |
| 32 let wnd = Services.wm.getOuterWindowWithId(outerWindowID); | 62 let wnd = Services.wm.getOuterWindowWithId(outerWindowID); |
| 33 if (!wnd || !canSelect(wnd)) | 63 if (!wnd || !canSelect(wnd)) |
| 34 return; | 64 return; |
| 35 | 65 |
| 36 state.window = wnd; | 66 state.window = wnd; |
| 37 state.id = outerWindowID; | |
| 38 | 67 |
| 39 wnd.addEventListener("click", onMouseClick, true); | 68 wnd.addEventListener("click", onMouseClick, true); |
| 40 wnd.addEventListener("wheel", onMouseScroll, true); | 69 wnd.addEventListener("wheel", onMouseScroll, true); |
|
saroyanm
2016/11/23 17:44:39
It's a deprecated event:
https://developer.mozilla
Wladimir Palant
2016/11/24 14:02:02
That page is about the mousewheel event, not wheel
| |
| 41 wnd.addEventListener("mousemove", onMouseMove, true); | 70 wnd.addEventListener("mousemove", onMouseMove, true); |
| 42 wnd.addEventListener("pagehide", onPageHide, true); | 71 wnd.addEventListener("pagehide", onPageHide, true); |
| 43 | 72 |
| 44 wnd.focus(); | 73 wnd.focus(); |
| 45 | 74 |
| 46 let doc = wnd.document; | 75 let doc = wnd.document; |
| 47 let {elementMarkerClass} = require("info"); | 76 let {elementMarkerClass} = require("info"); |
| 48 state.boxElement = createElement(doc, "div", {"class": elementMarkerClass}, [ | 77 state.boxElement = createElement(doc, "div", {"class": elementMarkerClass}, [ |
| 49 createElement(doc, "div", {"class": "ehh-border"}), | 78 createElement(doc, "div", {"class": "ehh-border"}), |
| 50 createElement(doc, "div", {"class": "ehh-label"}, [ | 79 createElement(doc, "div", {"class": "ehh-label"}, [ |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 76 | 105 |
| 77 for (let key of Object.keys(state)) | 106 for (let key of Object.keys(state)) |
| 78 delete state[key]; | 107 delete state[key]; |
| 79 | 108 |
| 80 messageManager.sendAsyncMessage("ElemHideHelper:SelectionStopped"); | 109 messageManager.sendAsyncMessage("ElemHideHelper:SelectionStopped"); |
| 81 } | 110 } |
| 82 exports.stopSelection = stopSelection; | 111 exports.stopSelection = stopSelection; |
| 83 | 112 |
| 84 function canSelect(wnd) | 113 function canSelect(wnd) |
| 85 { | 114 { |
| 86 let acceptlocalfiles; | 115 let acceptLocalFiles; |
|
saroyanm
2016/11/23 17:44:39
Nit: camelCase is missing
Wladimir Palant
2016/11/24 14:02:02
Done.
| |
| 87 try | 116 try |
| 88 { | 117 { |
| 89 acceptlocalfiles = Services.prefs.getBoolPref("extensions.elemhidehelper.acc eptlocalfiles"); | 118 let pref = "extensions.elemhidehelper.acceptlocalfiles"; |
|
saroyanm
2016/11/23 17:44:39
Nit: exceeding 80 chars.
Wladimir Palant
2016/11/24 14:02:01
Done.
| |
| 119 acceptLocalFiles = Services.prefs.getBoolPref(pref); | |
| 90 } | 120 } |
| 91 catch (e) | 121 catch (e) |
| 92 { | 122 { |
| 93 acceptlocalfiles = false; | 123 acceptLocalFiles = false; |
| 94 } | 124 } |
| 95 | 125 |
| 96 if (!acceptlocalfiles) | 126 if (!acceptLocalFiles) |
| 97 { | 127 { |
| 98 let localSchemes; | 128 let localSchemes; |
| 99 try | 129 try |
| 100 { | 130 { |
| 101 localSchemes = new Set( | 131 localSchemes = new Set( |
| 102 Services.prefs.getCharPref("extensions.adblockplus.whitelistschemes") | 132 Services.prefs.getCharPref("extensions.adblockplus.whitelistschemes") |
| 103 .split(/\s+/) | 133 .split(/\s+/) |
| 104 ); | 134 ); |
|
Wladimir Palant
2016/11/17 13:54:48
This changes the original logic which was simply h
| |
| 105 } | 135 } |
| 106 catch (e) | 136 catch (e) |
| 107 { | 137 { |
| 108 localSchemes = new Set(); | 138 localSchemes = new Set(); |
| 109 } | 139 } |
| 110 | 140 |
| 111 if (localSchemes.has(wnd.location.protocol.replace(/:$/, ""))) | 141 if (localSchemes.has(wnd.location.protocol.replace(/:$/, ""))) |
| 112 return false; | 142 return false; |
| 113 } | 143 } |
| 114 | 144 |
| 115 return true; | 145 return true; |
| 116 } | 146 } |
| 117 | 147 |
| 118 function getElementLabel(elem) | 148 function getElementLabel(elem) |
| 119 { | 149 { |
| 120 let tagName = elem.localName; | 150 let tagName = elem.localName; |
|
saroyanm
2016/11/23 17:44:39
localName is a deprecated property:
https://develo
Wladimir Palant
2016/11/24 14:02:02
That would have been surprising - the docs say tha
| |
| 121 let addition = ""; | 151 let addition = ""; |
| 122 if (elem.id != "") | 152 if (elem.id != "") |
| 123 addition += ", id: " + elem.id; | 153 addition += ", id: " + elem.id; |
| 124 if (elem.className != "") | 154 if (elem.className != "") |
| 125 addition += ", class: " + elem.className; | 155 addition += ", class: " + elem.className; |
| 126 if (elem.style.cssText != "") | 156 if (elem.style.cssText != "") |
| 127 addition += ", style: " + elem.style.cssText; | 157 addition += ", style: " + elem.style.cssText; |
|
saroyanm
2016/11/23 17:44:39
Weak suggestion: What about mentioning that it's n
Wladimir Palant
2016/11/24 14:02:02
Hasn't lead to any confusion so far, we can just a
| |
| 128 | 158 |
| 129 return [tagName, addition]; | 159 return [tagName, addition]; |
| 130 } | 160 } |
| 131 | 161 |
| 132 function setAnchorElement(anchor) | 162 function setAnchorElement(anchor) |
|
saroyanm
2016/11/23 17:44:39
What is the anchor element ? I assume it's not rel
Wladimir Palant
2016/11/24 14:02:01
Nope. I've documented the state properties now, sh
| |
| 133 { | 163 { |
| 134 state.anchorElement = anchor; | 164 state.anchorElement = anchor; |
| 135 | 165 |
| 136 let newSelection = anchor; | 166 let newSelection = anchor; |
| 137 if (state.isUserSelected) | 167 if (state.isUserSelected) |
| 138 { | 168 { |
| 139 // User chose an element via wider/narrower commands, keep the selection if | 169 // User chose an element via wider/narrower commands, keep the selection if |
| 140 // our new anchor is still a child of that element | 170 // our new anchor is still a child of that element |
| 141 let e = newSelection; | 171 let e = newSelection; |
| 142 while (e && e != state.selectedElement) | 172 while (e && e != state.selectedElement) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 159 | 189 |
| 160 let border = state.boxElement.querySelector(".ehh-border"); | 190 let border = state.boxElement.querySelector(".ehh-border"); |
| 161 let label = state.boxElement.querySelector(".ehh-label"); | 191 let label = state.boxElement.querySelector(".ehh-label"); |
| 162 let labelTag = state.boxElement.querySelector(".ehh-labelTag"); | 192 let labelTag = state.boxElement.querySelector(".ehh-labelTag"); |
| 163 let labelAddition = state.boxElement.querySelector(".ehh-labelAddition"); | 193 let labelAddition = state.boxElement.querySelector(".ehh-labelAddition"); |
| 164 | 194 |
| 165 let doc = state.window.document; | 195 let doc = state.window.document; |
| 166 let [wndWidth, wndHeight] = getWindowSize(state.window); | 196 let [wndWidth, wndHeight] = getWindowSize(state.window); |
| 167 | 197 |
| 168 let pos = getElementPosition(elem); | 198 let pos = getElementPosition(elem); |
| 169 state.boxElement.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; | 199 state.boxElement.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; |
|
saroyanm
2016/11/23 17:44:38
Is this approach even working with RTL websites ?
Wladimir Palant
2016/11/24 14:02:01
Well, it works with RTL websites. Our UI is always
saroyanm
2016/11/25 16:18:13
Here you go: #4665
| |
| 170 state.boxElement.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; | 200 state.boxElement.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; |
| 171 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; | 201 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; |
| 172 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; | 202 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; |
| 173 | 203 |
| 174 [labelTag.textContent, labelAddition.textContent] = getElementLabel(elem); | 204 [labelTag.textContent, labelAddition.textContent] = getElementLabel(elem); |
| 175 | 205 |
| 176 // If there is not enough space to show the label move it up a little | 206 // If there is not enough space to show the label move it up a little |
| 177 if (pos.bottom < wndHeight - 25) | 207 if (pos.bottom < wndHeight - 25) |
| 178 label.className = "ehh-label"; | 208 label.className = "ehh-label"; |
| 179 else | 209 else |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 206 | 236 |
| 207 require("./commands").select(); | 237 require("./commands").select(); |
| 208 event.preventDefault(); | 238 event.preventDefault(); |
| 209 } | 239 } |
| 210 | 240 |
| 211 function onMouseScroll(event) | 241 function onMouseScroll(event) |
| 212 { | 242 { |
| 213 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) | 243 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) |
| 214 return; | 244 return; |
| 215 | 245 |
| 216 let delta = event.deltaY || event.deltaX; | 246 let delta = event.deltaY || event.deltaX; |
|
Wladimir Palant
2016/11/17 13:54:48
This was dead code originally, using DOMMouseScrol
saroyanm
2016/11/23 17:44:38
Acknowledged.
| |
| 217 if (!delta) | 247 if (!delta) |
| 218 return; | 248 return; |
| 219 | 249 |
| 220 let commands = require("./commands"); | 250 let commands = require("./commands"); |
|
saroyanm
2016/11/23 17:44:38
Detail: we already loading the module in onMouseCl
Wladimir Palant
2016/11/24 14:02:01
That would create a circular reference.
| |
| 221 if (delta > 0) | 251 if (delta > 0) |
| 222 commands.wider(); | 252 commands.wider(); |
| 223 else | 253 else |
| 224 commands.narrower(); | 254 commands.narrower(); |
| 225 event.preventDefault(); | 255 event.preventDefault(); |
| 226 } | 256 } |
| 227 | 257 |
| 228 function onMouseMove(event) | 258 function onMouseMove(event) |
| 229 { | 259 { |
| 230 hideSelection(); | 260 hideSelection(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 selectElement(state.selectedElement); | 292 selectElement(state.selectedElement); |
| 263 } | 293 } |
| 264 } | 294 } |
| 265 } | 295 } |
| 266 | 296 |
| 267 function onPageHide(event) | 297 function onPageHide(event) |
| 268 { | 298 { |
| 269 stopSelection(); | 299 stopSelection(); |
| 270 } | 300 } |
| 271 | 301 |
| 272 function onAfterPaint(event) | 302 function onAfterPaint(event) |
|
Wladimir Palant
2016/11/17 13:54:48
This code path is untested, I'm not sure whether i
saroyanm
2016/11/23 17:44:39
We do have "onMouseScroll" function, I thought it
Wladimir Palant
2016/11/24 14:02:02
Given that the purpose of this function is selecti
| |
| 273 { | 303 { |
| 274 // Don't update position too often | 304 // Don't update position too often |
| 275 if (state.selectedElement && Date.now() - state.prevSelectionUpdate > 20) | 305 if (state.selectedElement && Date.now() - state.prevSelectionUpdate > 20) |
| 276 { | 306 { |
| 277 let pos = getElementPosition(state.selectedElement); | 307 let pos = getElementPosition(state.selectedElement); |
| 278 if (!state.prevPos || state.prevPos.left != pos.left || | 308 if (!state.prevPos || state.prevPos.left != pos.left || |
| 279 state.prevPos.right != pos.right || state.prevPos.top != pos.top || | 309 state.prevPos.right != pos.right || state.prevPos.top != pos.top || |
| 280 state.prevPos.bottom != pos.bottom) | 310 state.prevPos.bottom != pos.bottom) |
| 281 { | 311 { |
| 282 selectElement(state.selectedElement); | 312 selectElement(state.selectedElement); |
| 283 } | 313 } |
| 284 } | 314 } |
| 285 } | 315 } |
| LEFT | RIGHT |