From 2a86d6609210a586ec32c48a99904c9b64744d04 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 9 Aug 2020 21:07:11 -0400 Subject: [PATCH] DOM + DocumentUtil merge (#727) * Add DOM functions to DocumentUtil * Use DocumentUtil instead of DOM * Remove DOM * Move document-util.js into mixed --- dev/data/manifest-variants.json | 3 +- ext/bg/js/search.js | 4 +- ext/bg/js/settings/conditions-ui.js | 6 +- ext/bg/search.html | 3 +- ext/bg/settings-popup-preview.html | 3 +- ext/bg/settings.html | 2 +- ext/fg/float.html | 3 +- ext/fg/js/frontend.js | 5 +- ext/fg/js/popup.js | 6 +- ext/manifest.json | 3 +- ext/mixed/js/display.js | 9 +- ext/{fg => mixed}/js/document-util.js | 131 ++++++++++++++++++++++- ext/mixed/js/dom.js | 145 -------------------------- ext/mixed/js/text-scanner.js | 16 +-- test/test-document-util.js | 3 +- 15 files changed, 157 insertions(+), 185 deletions(-) rename ext/{fg => mixed}/js/document-util.js (76%) delete mode 100644 ext/mixed/js/dom.js diff --git a/dev/data/manifest-variants.json b/dev/data/manifest-variants.json index c8135baf..fd11c5c2 100644 --- a/dev/data/manifest-variants.json +++ b/dev/data/manifest-variants.json @@ -42,12 +42,11 @@ "mixed/js/core.js", "mixed/js/yomichan.js", "mixed/js/comm.js", - "mixed/js/dom.js", "mixed/js/api.js", "mixed/js/dynamic-loader.js", "mixed/js/frame-client.js", "mixed/js/text-scanner.js", - "fg/js/document-util.js", + "mixed/js/document-util.js", "fg/js/dom-text-scanner.js", "fg/js/popup.js", "fg/js/source.js", diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 7cad2671..0a0699a9 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -17,8 +17,8 @@ /* global * ClipboardMonitor - * DOM * Display + * DocumentUtil * api * wanakana */ @@ -104,7 +104,7 @@ class DisplaySearch extends Display { } onKeyDown(e) { - const key = DOM.getKeyFromEvent(e); + const key = DocumentUtil.getKeyFromEvent(e); const ignoreKeys = this._onKeyDownIgnoreKeys; const activeModifierMap = new Map([ diff --git a/ext/bg/js/settings/conditions-ui.js b/ext/bg/js/settings/conditions-ui.js index 031689a7..98b3d432 100644 --- a/ext/bg/js/settings/conditions-ui.js +++ b/ext/bg/js/settings/conditions-ui.js @@ -16,7 +16,7 @@ */ /* global - * DOM + * DocumentUtil * conditionsNormalizeOptionValue */ @@ -323,7 +323,7 @@ ConditionsUI.Condition = class Condition { const pressedKeyIndices = new Set(); const onKeyDown = ({originalEvent}) => { - const pressedKeyEventName = DOM.getKeyFromEvent(originalEvent); + const pressedKeyEventName = DocumentUtil.getKeyFromEvent(originalEvent); if (pressedKeyEventName === 'Escape' || pressedKeyEventName === 'Backspace') { pressedKeyIndices.clear(); inputInner.val(''); @@ -331,7 +331,7 @@ ConditionsUI.Condition = class Condition { return; } - const pressedModifiers = DOM.getActiveModifiers(originalEvent); + const pressedModifiers = DocumentUtil.getActiveModifiers(originalEvent); // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey // https://askubuntu.com/questions/567731/why-is-shift-alt-being-mapped-to-meta // It works with mouse events on some platforms, so try to determine if metaKey is pressed diff --git a/ext/bg/search.html b/ext/bg/search.html index 9556a1a1..6f7e04c9 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -73,12 +73,11 @@ - - + diff --git a/ext/bg/settings-popup-preview.html b/ext/bg/settings-popup-preview.html index 3479efa4..59924a27 100644 --- a/ext/bg/settings-popup-preview.html +++ b/ext/bg/settings-popup-preview.html @@ -121,13 +121,12 @@ - - + diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 8326a65c..f6025f55 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -1135,7 +1135,6 @@ - @@ -1148,6 +1147,7 @@ + diff --git a/ext/fg/float.html b/ext/fg/float.html index 51aa2350..bd2508e6 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -47,11 +47,10 @@ - - + diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index ccffbab6..0c18fb2a 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -16,7 +16,6 @@ */ /* global - * DOM * DocumentUtil * FrameOffsetForwarder * PopupProxy @@ -98,7 +97,7 @@ class Frontend { this._textScanner.prepare(); window.addEventListener('resize', this._onResize.bind(this), false); - DOM.addFullscreenChangeEventListener(this._updatePopup.bind(this)); + DocumentUtil.addFullscreenChangeEventListener(this._updatePopup.bind(this)); const visualViewport = window.visualViewport; if (visualViewport !== null && typeof visualViewport === 'object') { @@ -274,7 +273,7 @@ class Frontend { if ( isIframe && showIframePopupsInRootFrame && - DOM.getFullscreenElement() === null && + DocumentUtil.getFullscreenElement() === null && this._allowRootFramePopupProxy ) { popupPromise = this._popupCache.get('iframe'); diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 22672706..8ea1afd0 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -16,7 +16,7 @@ */ /* global - * DOM + * DocumentUtil * FrameClient * api * dynamicLoader @@ -349,7 +349,7 @@ class Popup { return; } - DOM.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners); + DocumentUtil.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners); } _onFullscreenChanged() { @@ -475,7 +475,7 @@ class Popup { _getFrameParentElement() { const defaultParent = document.body; - const fullscreenElement = DOM.getFullscreenElement(); + const fullscreenElement = DocumentUtil.getFullscreenElement(); if ( fullscreenElement === null || fullscreenElement.shadowRoot || diff --git a/ext/manifest.json b/ext/manifest.json index b22e75c6..12286c40 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -41,12 +41,11 @@ "mixed/js/core.js", "mixed/js/yomichan.js", "mixed/js/comm.js", - "mixed/js/dom.js", "mixed/js/api.js", "mixed/js/dynamic-loader.js", "mixed/js/frame-client.js", "mixed/js/text-scanner.js", - "fg/js/document-util.js", + "mixed/js/document-util.js", "fg/js/dom-text-scanner.js", "fg/js/popup.js", "fg/js/source.js", diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 170b9d23..08ececc7 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -17,7 +17,6 @@ /* global * AudioSystem - * DOM * DisplayGenerator * DisplayHistory * DocumentUtil @@ -186,11 +185,11 @@ class Display extends EventDispatcher { } onKeyDown(e) { - const key = DOM.getKeyFromEvent(e); + const key = DocumentUtil.getKeyFromEvent(e); const handlers = this._hotkeys.get(key); if (typeof handlers === 'undefined') { return false; } - const eventModifiers = DOM.getActiveModifiers(e); + const eventModifiers = DocumentUtil.getActiveModifiers(e); for (const {modifiers, action} of handlers) { if (getSetDifference(modifiers, eventModifiers).size !== 0) { continue; } @@ -558,7 +557,7 @@ class Display extends EventDispatcher { } _onGlossaryMouseDown(e) { - if (DOM.isMouseButtonPressed(e, 'primary')) { + if (DocumentUtil.isMouseButtonPressed(e, 'primary')) { this._clickScanPrevent = false; } } @@ -568,7 +567,7 @@ class Display extends EventDispatcher { } _onGlossaryMouseUp(e) { - if (!this._clickScanPrevent && DOM.isMouseButtonPressed(e, 'primary')) { + if (!this._clickScanPrevent && DocumentUtil.isMouseButtonPressed(e, 'primary')) { try { this._onTermLookup(e); } catch (error) { diff --git a/ext/fg/js/document-util.js b/ext/mixed/js/document-util.js similarity index 76% rename from ext/fg/js/document-util.js rename to ext/mixed/js/document-util.js index d3bba30f..ba39942d 100644 --- a/ext/fg/js/document-util.js +++ b/ext/mixed/js/document-util.js @@ -16,7 +16,6 @@ */ /* global - * DOM * DOMTextScanner * TextSourceElement * TextSourceRange @@ -134,6 +133,132 @@ class DocumentUtil { }; } + static isPointInRect(x, y, rect) { + return ( + x >= rect.left && x < rect.right && + y >= rect.top && y < rect.bottom + ); + } + + static isPointInAnyRect(x, y, rects) { + for (const rect of rects) { + if (this.isPointInRect(x, y, rect)) { + return true; + } + } + return false; + } + + static isPointInSelection(x, y, selection) { + for (let i = 0; i < selection.rangeCount; ++i) { + const range = selection.getRangeAt(i); + if (this.isPointInAnyRect(x, y, range.getClientRects())) { + return true; + } + } + return false; + } + + static isMouseButtonPressed(mouseEvent, button) { + const mouseEventButton = mouseEvent.button; + switch (button) { + case 'primary': return mouseEventButton === 0; + case 'secondary': return mouseEventButton === 2; + case 'auxiliary': return mouseEventButton === 1; + default: return false; + } + } + + static isMouseButtonDown(mouseEvent, button) { + const mouseEventButtons = mouseEvent.buttons; + switch (button) { + case 'primary': return (mouseEventButtons & 0x1) !== 0x0; + case 'secondary': return (mouseEventButtons & 0x2) !== 0x0; + case 'auxiliary': return (mouseEventButtons & 0x4) !== 0x0; + default: return false; + } + } + + static getActiveModifiers(event) { + const modifiers = new Set(); + if (event.altKey) { modifiers.add('alt'); } + if (event.ctrlKey) { modifiers.add('ctrl'); } + if (event.metaKey) { modifiers.add('meta'); } + if (event.shiftKey) { modifiers.add('shift'); } + return modifiers; + } + + static getKeyFromEvent(event) { + const key = event.key; + return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : ''); + } + + static addFullscreenChangeEventListener(onFullscreenChanged, eventListenerCollection=null) { + const target = document; + const options = false; + const fullscreenEventNames = [ + 'fullscreenchange', + 'MSFullscreenChange', + 'mozfullscreenchange', + 'webkitfullscreenchange' + ]; + for (const eventName of fullscreenEventNames) { + if (eventListenerCollection === null) { + target.addEventListener(eventName, onFullscreenChanged, options); + } else { + eventListenerCollection.addEventListener(target, eventName, onFullscreenChanged, options); + } + } + } + + static getFullscreenElement() { + return ( + document.fullscreenElement || + document.msFullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement || + null + ); + } + + static getNodesInRange(range) { + const end = range.endContainer; + const nodes = []; + for (let node = range.startContainer; node !== null; node = this.getNextNode(node)) { + nodes.push(node); + if (node === end) { break; } + } + return nodes; + } + + static getNextNode(node) { + let next = node.firstChild; + if (next === null) { + while (true) { + next = node.nextSibling; + if (next !== null) { break; } + + next = node.parentNode; + if (next === null) { break; } + + node = next; + } + } + return next; + } + + static anyNodeMatchesSelector(nodes, selector) { + const ELEMENT_NODE = Node.ELEMENT_NODE; + for (let node of nodes) { + for (; node !== null; node = node.parentNode) { + if (node.nodeType !== ELEMENT_NODE) { continue; } + if (node.matches(selector)) { return true; } + break; + } + } + return false; + } + // Private _setImposterStyle(style, propertyName, value) { @@ -240,7 +365,7 @@ class DocumentUtil { const {node, offset, content} = new DOMTextScanner(range.endContainer, range.endOffset, true, false).seek(1); range.setEnd(node, offset); - if (!this._isWhitespace(content) && DOM.isPointInAnyRect(x, y, range.getClientRects())) { + if (!this._isWhitespace(content) && DocumentUtil.isPointInAnyRect(x, y, range.getClientRects())) { return true; } } finally { @@ -251,7 +376,7 @@ class DocumentUtil { const {node, offset, content} = new DOMTextScanner(range.startContainer, range.startOffset, true, false).seek(-1); range.setStart(node, offset); - if (!this._isWhitespace(content) && DOM.isPointInAnyRect(x, y, range.getClientRects())) { + if (!this._isWhitespace(content) && DocumentUtil.isPointInAnyRect(x, y, range.getClientRects())) { // This purposefully leaves the starting offset as modified and sets the range length to 0. range.setEnd(node, offset); return true; diff --git a/ext/mixed/js/dom.js b/ext/mixed/js/dom.js deleted file mode 100644 index 59fea9f6..00000000 --- a/ext/mixed/js/dom.js +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2019-2020 Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class DOM { - static isPointInRect(x, y, rect) { - return ( - x >= rect.left && x < rect.right && - y >= rect.top && y < rect.bottom - ); - } - - static isPointInAnyRect(x, y, rects) { - for (const rect of rects) { - if (DOM.isPointInRect(x, y, rect)) { - return true; - } - } - return false; - } - - static isPointInSelection(x, y, selection) { - for (let i = 0; i < selection.rangeCount; ++i) { - const range = selection.getRangeAt(i); - if (DOM.isPointInAnyRect(x, y, range.getClientRects())) { - return true; - } - } - return false; - } - - static isMouseButtonPressed(mouseEvent, button) { - const mouseEventButton = mouseEvent.button; - switch (button) { - case 'primary': return mouseEventButton === 0; - case 'secondary': return mouseEventButton === 2; - case 'auxiliary': return mouseEventButton === 1; - default: return false; - } - } - - static isMouseButtonDown(mouseEvent, button) { - const mouseEventButtons = mouseEvent.buttons; - switch (button) { - case 'primary': return (mouseEventButtons & 0x1) !== 0x0; - case 'secondary': return (mouseEventButtons & 0x2) !== 0x0; - case 'auxiliary': return (mouseEventButtons & 0x4) !== 0x0; - default: return false; - } - } - - static getActiveModifiers(event) { - const modifiers = new Set(); - if (event.altKey) { modifiers.add('alt'); } - if (event.ctrlKey) { modifiers.add('ctrl'); } - if (event.metaKey) { modifiers.add('meta'); } - if (event.shiftKey) { modifiers.add('shift'); } - return modifiers; - } - - static getKeyFromEvent(event) { - const key = event.key; - return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : ''); - } - - static addFullscreenChangeEventListener(onFullscreenChanged, eventListenerCollection=null) { - const target = document; - const options = false; - const fullscreenEventNames = [ - 'fullscreenchange', - 'MSFullscreenChange', - 'mozfullscreenchange', - 'webkitfullscreenchange' - ]; - for (const eventName of fullscreenEventNames) { - if (eventListenerCollection === null) { - target.addEventListener(eventName, onFullscreenChanged, options); - } else { - eventListenerCollection.addEventListener(target, eventName, onFullscreenChanged, options); - } - } - } - - static getFullscreenElement() { - return ( - document.fullscreenElement || - document.msFullscreenElement || - document.mozFullScreenElement || - document.webkitFullscreenElement || - null - ); - } - - static getNodesInRange(range) { - const end = range.endContainer; - const nodes = []; - for (let node = range.startContainer; node !== null; node = DOM.getNextNode(node)) { - nodes.push(node); - if (node === end) { break; } - } - return nodes; - } - - static getNextNode(node) { - let next = node.firstChild; - if (next === null) { - while (true) { - next = node.nextSibling; - if (next !== null) { break; } - - next = node.parentNode; - if (next === null) { break; } - - node = next; - } - } - return next; - } - - static anyNodeMatchesSelector(nodes, selector) { - const ELEMENT_NODE = Node.ELEMENT_NODE; - for (let node of nodes) { - for (; node !== null; node = node.parentNode) { - if (node.nodeType !== ELEMENT_NODE) { continue; } - if (node.matches(selector)) { return true; } - break; - } - } - return false; - } -} diff --git a/ext/mixed/js/text-scanner.js b/ext/mixed/js/text-scanner.js index 923784b3..d0256b1e 100644 --- a/ext/mixed/js/text-scanner.js +++ b/ext/mixed/js/text-scanner.js @@ -16,7 +16,7 @@ */ /* global - * DOM + * DocumentUtil */ class TextScanner extends EventDispatcher { @@ -155,8 +155,8 @@ class TextScanner extends EventDispatcher { if (this._ignoreNodes !== null && clonedTextSource.range) { length = clonedTextSource.text().length; while (clonedTextSource.range && length > 0) { - const nodes = DOM.getNodesInRange(clonedTextSource.range); - if (!DOM.anyNodeMatchesSelector(nodes, this._ignoreNodes)) { + const nodes = DocumentUtil.getNodesInRange(clonedTextSource.range); + if (!DocumentUtil.anyNodeMatchesSelector(nodes, this._ignoreNodes)) { break; } --length; @@ -204,16 +204,16 @@ class TextScanner extends EventDispatcher { _onMouseMove(e) { this._scanTimerClear(); - if (this._pendingLookup || DOM.isMouseButtonDown(e, 'primary')) { + if (this._pendingLookup || DocumentUtil.isMouseButtonDown(e, 'primary')) { return; } - const modifiers = DOM.getActiveModifiers(e); + const modifiers = DocumentUtil.getActiveModifiers(e); this.trigger('activeModifiersChanged', {modifiers}); if (!( this._isScanningModifierPressed(this._modifier, e) || - (this._useMiddleMouse && DOM.isMouseButtonDown(e, 'auxiliary')) + (this._useMiddleMouse && DocumentUtil.isMouseButtonDown(e, 'auxiliary')) )) { return; } @@ -241,7 +241,7 @@ class TextScanner extends EventDispatcher { return false; } - if (DOM.isMouseButtonDown(e, 'primary')) { + if (DocumentUtil.isMouseButtonDown(e, 'primary')) { this._scanTimerClear(); this.clearSelection(false); } @@ -284,7 +284,7 @@ class TextScanner extends EventDispatcher { this._preventNextClick = false; const primaryTouch = e.changedTouches[0]; - if (DOM.isPointInSelection(primaryTouch.clientX, primaryTouch.clientY, window.getSelection())) { + if (DocumentUtil.isPointInSelection(primaryTouch.clientX, primaryTouch.clientY, window.getSelection())) { return; } diff --git a/test/test-document-util.js b/test/test-document-util.js index 40b65ed1..4ff380ec 100644 --- a/test/test-document-util.js +++ b/test/test-document-util.js @@ -93,10 +93,9 @@ async function testDocument1() { const vm = new VM({document, window, Range, Node}); vm.execute([ - 'mixed/js/dom.js', 'fg/js/dom-text-scanner.js', 'fg/js/source.js', - 'fg/js/document-util.js' + 'mixed/js/document-util.js' ]); const [DOMTextScanner, TextSourceRange, TextSourceElement, DocumentUtil] = vm.get([ 'DOMTextScanner',