summaryrefslogtreecommitdiff
path: root/ext/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js')
-rw-r--r--ext/js/accessibility/google-docs-util.js6
-rw-r--r--ext/js/app/frontend.js6
-rw-r--r--ext/js/app/popup.js10
-rw-r--r--ext/js/dom/document-util.js798
-rw-r--r--ext/js/dom/dom-data-binder.js4
-rw-r--r--ext/js/dom/text-source-element.js4
-rw-r--r--ext/js/dom/text-source-generator.js8
-rw-r--r--ext/js/dom/text-source-range.js16
-rw-r--r--ext/js/input/hotkey-handler.js6
-rw-r--r--ext/js/language/text-scanner.js16
-rw-r--r--ext/js/pages/settings/generic-setting-controller.js4
-rw-r--r--ext/js/pages/settings/keyboard-mouse-input-field.js8
-rw-r--r--ext/js/pages/settings/keyboard-shortcuts-controller.js6
-rw-r--r--ext/js/pages/settings/nested-popups-controller.js4
-rw-r--r--ext/js/pages/settings/profile-conditions-ui.js4
-rw-r--r--ext/js/pages/settings/scan-inputs-controller.js4
-rw-r--r--ext/js/pages/settings/settings-display-controller.js4
17 files changed, 454 insertions, 454 deletions
diff --git a/ext/js/accessibility/google-docs-util.js b/ext/js/accessibility/google-docs-util.js
index 31ae5982..f3f800fd 100644
--- a/ext/js/accessibility/google-docs-util.js
+++ b/ext/js/accessibility/google-docs-util.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {DocumentUtil} from '../dom/document-util.js';
+import {computeZoomScale, isPointInAnyRect} from '../dom/document-util.js';
import {TextSourceRange} from '../dom/text-source-range.js';
/**
@@ -126,7 +126,7 @@ export class GoogleDocsUtil {
*/
_getRangeWithPoint(textNode, x, y, normalizeCssZoom) {
if (normalizeCssZoom) {
- const scale = DocumentUtil.computeZoomScale(textNode);
+ const scale = computeZoomScale(textNode);
x /= scale;
y /= scale;
}
@@ -137,7 +137,7 @@ export class GoogleDocsUtil {
const mid = Math.floor((start + end) / 2);
range.setStart(textNode, mid);
range.setEnd(textNode, end);
- if (DocumentUtil.isPointInAnyRect(x, y, range.getClientRects())) {
+ if (isPointInAnyRect(x, y, range.getClientRects())) {
start = mid;
} else {
end = mid;
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index 9c4778cc..04f8673f 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -20,7 +20,7 @@ import {createApiMap, invokeApiMapHandler} from '../core/api-map.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {log} from '../core/log.js';
import {promiseAnimationFrame} from '../core/promise-animation-frame.js';
-import {DocumentUtil} from '../dom/document-util.js';
+import {addFullscreenChangeEventListener, getFullscreenElement} from '../dom/document-util.js';
import {TextSourceElement} from '../dom/text-source-element.js';
import {TextSourceGenerator} from '../dom/text-source-generator.js';
import {TextSourceRange} from '../dom/text-source-range.js';
@@ -163,7 +163,7 @@ export class Frontend {
this._textScanner.prepare();
window.addEventListener('resize', this._onResize.bind(this), false);
- DocumentUtil.addFullscreenChangeEventListener(this._updatePopup.bind(this));
+ addFullscreenChangeEventListener(this._updatePopup.bind(this));
const {visualViewport} = window;
if (typeof visualViewport !== 'undefined' && visualViewport !== null) {
@@ -523,7 +523,7 @@ export class Frontend {
} else if (
isIframe &&
showIframePopupsInRootFrame &&
- DocumentUtil.getFullscreenElement() === null &&
+ getFullscreenElement() === null &&
this._allowRootFramePopupProxy
) {
popupPromise = this._popupCache.get('iframe');
diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js
index 103a5468..c9011932 100644
--- a/ext/js/app/popup.js
+++ b/ext/js/app/popup.js
@@ -22,7 +22,7 @@ import {EventDispatcher} from '../core/event-dispatcher.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {ExtensionError} from '../core/extension-error.js';
import {deepEqual} from '../core/utilities.js';
-import {DocumentUtil} from '../dom/document-util.js';
+import {addFullscreenChangeEventListener, computeZoomScale, convertRectZoomCoordinates, getFullscreenElement} from '../dom/document-util.js';
import {loadStyle} from '../dom/style-util.js';
import {ThemeController} from './theme-controller.js';
@@ -594,7 +594,7 @@ export class Popup extends EventDispatcher {
return;
}
- DocumentUtil.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners);
+ addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners);
}
/**
@@ -748,7 +748,7 @@ export class Popup extends EventDispatcher {
if (defaultParent !== null && defaultParent.tagName.toLowerCase() === 'frameset') {
defaultParent = document.documentElement;
}
- const fullscreenElement = DocumentUtil.getFullscreenElement();
+ const fullscreenElement = getFullscreenElement();
if (
fullscreenElement === null ||
fullscreenElement.shadowRoot ||
@@ -1091,7 +1091,7 @@ export class Popup extends EventDispatcher {
* @returns {DOMRect} The rectangle of the frame.
*/
_getFrameBoundingClientRect() {
- return DocumentUtil.convertRectZoomCoordinates(this._frame.getBoundingClientRect(), this._container);
+ return convertRectZoomCoordinates(this._frame.getBoundingClientRect(), this._container);
}
/**
@@ -1100,7 +1100,7 @@ export class Popup extends EventDispatcher {
* @returns {import('popup').Rect[]} Either an updated list of rectangles, or `sourceRects` if no change is required.
*/
_convertSourceRectsCoordinateSpace(sourceRects) {
- let scale = DocumentUtil.computeZoomScale(this._container);
+ let scale = computeZoomScale(this._container);
if (scale === 1) { return sourceRects; }
scale = 1 / scale;
const sourceRects2 = [];
diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js
index a98bfe86..bf11f421 100644
--- a/ext/js/dom/document-util.js
+++ b/ext/js/dom/document-util.js
@@ -15,466 +15,466 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-
/**
- * This class contains utility functions related to the HTML document.
- * TODO : This class should be made non-static
+ * This variable is stateful, but it is only used to do feature detection,
+ * and its value should be constant for the lifetime of the extension.
+ * @type {?boolean}
*/
-// eslint-disable-next-line unicorn/no-static-only-class
-export class DocumentUtil {
- /** @type {?boolean} */
- static _cssZoomSupported = null;
+let cssZoomSupported = null;
- /**
- * Computes the scaling adjustment that is necessary for client space coordinates based on the
- * CSS zoom level.
- * @param {?Node} node A node in the document.
- * @returns {number} The scaling factor.
- */
- static computeZoomScale(node) {
- if (this._cssZoomSupported === null) {
- this._cssZoomSupported = this._computeCssZoomSupported();
- }
- if (!this._cssZoomSupported) { return 1; }
- // documentElement must be excluded because the computer style of its zoom property is inconsistent.
- // * If CSS `:root{zoom:X;}` is specified, the computed zoom will always report `X`.
- // * If CSS `:root{zoom:X;}` is not specified, the computed zoom report the browser's zoom level.
- // Therefor, if CSS root zoom is specified as a value other than 1, the adjusted {x, y} values
- // would be incorrect, which is not new behaviour.
- let scale = 1;
- const {ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE} = Node;
- const {documentElement} = document;
- for (; node !== null && node !== documentElement; node = node.parentNode) {
- const {nodeType} = node;
- if (nodeType === DOCUMENT_FRAGMENT_NODE) {
- const {host} = /** @type {ShadowRoot} */ (node);
- if (typeof host !== 'undefined') {
- node = host;
- }
- continue;
- } else if (nodeType !== ELEMENT_NODE) {
- continue;
+/**
+ * Computes the scaling adjustment that is necessary for client space coordinates based on the
+ * CSS zoom level.
+ * @param {?Node} node A node in the document.
+ * @returns {number} The scaling factor.
+ */
+export function computeZoomScale(node) {
+ if (cssZoomSupported === null) {
+ cssZoomSupported = computeCssZoomSupported();
+ }
+ if (!cssZoomSupported) { return 1; }
+ // documentElement must be excluded because the computer style of its zoom property is inconsistent.
+ // * If CSS `:root{zoom:X;}` is specified, the computed zoom will always report `X`.
+ // * If CSS `:root{zoom:X;}` is not specified, the computed zoom report the browser's zoom level.
+ // Therefor, if CSS root zoom is specified as a value other than 1, the adjusted {x, y} values
+ // would be incorrect, which is not new behaviour.
+ let scale = 1;
+ const {ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE} = Node;
+ const {documentElement} = document;
+ for (; node !== null && node !== documentElement; node = node.parentNode) {
+ const {nodeType} = node;
+ if (nodeType === DOCUMENT_FRAGMENT_NODE) {
+ const {host} = /** @type {ShadowRoot} */ (node);
+ if (typeof host !== 'undefined') {
+ node = host;
}
- const zoomString = getComputedStyle(/** @type {HTMLElement} */ (node)).getPropertyValue('zoom');
- if (typeof zoomString !== 'string' || zoomString.length === 0) { continue; }
- const zoom = Number.parseFloat(zoomString);
- if (!Number.isFinite(zoom) || zoom === 0) { continue; }
- scale *= zoom;
+ continue;
+ } else if (nodeType !== ELEMENT_NODE) {
+ continue;
}
- return scale;
+ const zoomString = getComputedStyle(/** @type {HTMLElement} */ (node)).getPropertyValue('zoom');
+ if (typeof zoomString !== 'string' || zoomString.length === 0) { continue; }
+ const zoom = Number.parseFloat(zoomString);
+ if (!Number.isFinite(zoom) || zoom === 0) { continue; }
+ scale *= zoom;
}
+ return scale;
+}
- /**
- * Converts a rect based on the CSS zoom scaling for a given node.
- * @param {DOMRect} rect The rect to convert.
- * @param {Node} node The node to compute the zoom from.
- * @returns {DOMRect} The updated rect, or the same rect if no change is needed.
- */
- static convertRectZoomCoordinates(rect, node) {
- const scale = this.computeZoomScale(node);
- return (scale === 1 ? rect : new DOMRect(rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale));
- }
+/**
+ * Converts a rect based on the CSS zoom scaling for a given node.
+ * @param {DOMRect} rect The rect to convert.
+ * @param {Node} node The node to compute the zoom from.
+ * @returns {DOMRect} The updated rect, or the same rect if no change is needed.
+ */
+export function convertRectZoomCoordinates(rect, node) {
+ const scale = computeZoomScale(node);
+ return (scale === 1 ? rect : new DOMRect(rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale));
+}
- /**
- * Converts multiple rects based on the CSS zoom scaling for a given node.
- * @param {DOMRect[]|DOMRectList} rects The rects to convert.
- * @param {Node} node The node to compute the zoom from.
- * @returns {DOMRect[]} The updated rects, or the same rects array if no change is needed.
- */
- static convertMultipleRectZoomCoordinates(rects, node) {
- const scale = this.computeZoomScale(node);
- if (scale === 1) { return [...rects]; }
- const results = [];
- for (const rect of rects) {
- results.push(new DOMRect(rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale));
- }
- return results;
+/**
+ * Converts multiple rects based on the CSS zoom scaling for a given node.
+ * @param {DOMRect[]|DOMRectList} rects The rects to convert.
+ * @param {Node} node The node to compute the zoom from.
+ * @returns {DOMRect[]} The updated rects, or the same rects array if no change is needed.
+ */
+export function convertMultipleRectZoomCoordinates(rects, node) {
+ const scale = computeZoomScale(node);
+ if (scale === 1) { return [...rects]; }
+ const results = [];
+ for (const rect of rects) {
+ results.push(new DOMRect(rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale));
}
+ return results;
+}
- /**
- * Checks whether a given point is contained within a rect.
- * @param {number} x The horizontal coordinate.
- * @param {number} y The vertical coordinate.
- * @param {DOMRect} rect The rect to check.
- * @returns {boolean} `true` if the point is inside the rect, `false` otherwise.
- */
- static isPointInRect(x, y, rect) {
- return (
- x >= rect.left && x < rect.right &&
- y >= rect.top && y < rect.bottom
- );
- }
+/**
+ * Checks whether a given point is contained within a rect.
+ * @param {number} x The horizontal coordinate.
+ * @param {number} y The vertical coordinate.
+ * @param {DOMRect} rect The rect to check.
+ * @returns {boolean} `true` if the point is inside the rect, `false` otherwise.
+ */
+export function isPointInRect(x, y, rect) {
+ return (
+ x >= rect.left && x < rect.right &&
+ y >= rect.top && y < rect.bottom
+ );
+}
- /**
- * Checks whether a given point is contained within any rect in a list.
- * @param {number} x The horizontal coordinate.
- * @param {number} y The vertical coordinate.
- * @param {DOMRect[]|DOMRectList} rects The rect to check.
- * @returns {boolean} `true` if the point is inside any of the rects, `false` otherwise.
- */
- static isPointInAnyRect(x, y, rects) {
- for (const rect of rects) {
- if (this.isPointInRect(x, y, rect)) {
- return true;
- }
+/**
+ * Checks whether a given point is contained within any rect in a list.
+ * @param {number} x The horizontal coordinate.
+ * @param {number} y The vertical coordinate.
+ * @param {DOMRect[]|DOMRectList} rects The rect to check.
+ * @returns {boolean} `true` if the point is inside any of the rects, `false` otherwise.
+ */
+export function isPointInAnyRect(x, y, rects) {
+ for (const rect of rects) {
+ if (isPointInRect(x, y, rect)) {
+ return true;
}
- return false;
}
+ return false;
+}
- /**
- * Checks whether a given point is contained within a selection range.
- * @param {number} x The horizontal coordinate.
- * @param {number} y The vertical coordinate.
- * @param {Selection} selection The selection to check.
- * @returns {boolean} `true` if the point is inside the selection, `false` otherwise.
- */
- 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;
- }
+/**
+ * Checks whether a given point is contained within a selection range.
+ * @param {number} x The horizontal coordinate.
+ * @param {number} y The vertical coordinate.
+ * @param {Selection} selection The selection to check.
+ * @returns {boolean} `true` if the point is inside the selection, `false` otherwise.
+ */
+export function isPointInSelection(x, y, selection) {
+ for (let i = 0; i < selection.rangeCount; ++i) {
+ const range = selection.getRangeAt(i);
+ if (isPointInAnyRect(x, y, range.getClientRects())) {
+ return true;
}
- return false;
}
+ return false;
+}
- /**
- * Gets an array of the active modifier keys.
- * @param {KeyboardEvent|MouseEvent|TouchEvent} event The event to check.
- * @returns {import('input').ModifierKey[]} An array of modifiers.
- */
- static getActiveModifiers(event) {
- /** @type {import('input').ModifierKey[]} */
- const modifiers = [];
- if (event.altKey) { modifiers.push('alt'); }
- if (event.ctrlKey) { modifiers.push('ctrl'); }
- if (event.metaKey) { modifiers.push('meta'); }
- if (event.shiftKey) { modifiers.push('shift'); }
- return modifiers;
- }
+/**
+ * Gets an array of the active modifier keys.
+ * @param {KeyboardEvent|MouseEvent|TouchEvent} event The event to check.
+ * @returns {import('input').ModifierKey[]} An array of modifiers.
+ */
+export function getActiveModifiers(event) {
+ /** @type {import('input').ModifierKey[]} */
+ const modifiers = [];
+ if (event.altKey) { modifiers.push('alt'); }
+ if (event.ctrlKey) { modifiers.push('ctrl'); }
+ if (event.metaKey) { modifiers.push('meta'); }
+ if (event.shiftKey) { modifiers.push('shift'); }
+ return modifiers;
+}
- /**
- * Gets an array of the active modifier keys and buttons.
- * @param {KeyboardEvent|MouseEvent|TouchEvent} event The event to check.
- * @returns {import('input').Modifier[]} An array of modifiers and buttons.
- */
- static getActiveModifiersAndButtons(event) {
- /** @type {import('input').Modifier[]} */
- const modifiers = this.getActiveModifiers(event);
- if (event instanceof MouseEvent) {
- this._getActiveButtons(event, modifiers);
- }
- return modifiers;
+/**
+ * Gets an array of the active modifier keys and buttons.
+ * @param {KeyboardEvent|MouseEvent|TouchEvent} event The event to check.
+ * @returns {import('input').Modifier[]} An array of modifiers and buttons.
+ */
+export function getActiveModifiersAndButtons(event) {
+ /** @type {import('input').Modifier[]} */
+ const modifiers = getActiveModifiers(event);
+ if (event instanceof MouseEvent) {
+ getActiveButtonsInternal(event, modifiers);
}
+ return modifiers;
+}
- /**
- * Gets an array of the active buttons.
- * @param {MouseEvent} event The event to check.
- * @returns {import('input').ModifierMouseButton[]} An array of modifiers and buttons.
- */
- static getActiveButtons(event) {
- /** @type {import('input').ModifierMouseButton[]} */
- const buttons = [];
- this._getActiveButtons(event, buttons);
- return buttons;
- }
+/**
+ * Gets an array of the active buttons.
+ * @param {MouseEvent} event The event to check.
+ * @returns {import('input').ModifierMouseButton[]} An array of modifiers and buttons.
+ */
+export function getActiveButtons(event) {
+ /** @type {import('input').ModifierMouseButton[]} */
+ const buttons = [];
+ getActiveButtonsInternal(event, buttons);
+ return buttons;
+}
- /**
- * Adds a fullscreen change event listener. This function handles all of the browser-specific variants.
- * @param {EventListener} onFullscreenChanged The event callback.
- * @param {?import('../core/event-listener-collection.js').EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to.
- */
- 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);
- }
+/**
+ * Adds a fullscreen change event listener. This function handles all of the browser-specific variants.
+ * @param {EventListener} onFullscreenChanged The event callback.
+ * @param {?import('../core/event-listener-collection.js').EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to.
+ */
+export function 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);
}
}
+}
- /**
- * Returns the current fullscreen element. This function handles all of the browser-specific variants.
- * @returns {?Element} The current fullscreen element, or `null` if the window is not fullscreen.
- */
- static getFullscreenElement() {
- return (
- document.fullscreenElement ||
- // @ts-expect-error - vendor prefix
- document.msFullscreenElement ||
- // @ts-expect-error - vendor prefix
- document.mozFullScreenElement ||
- // @ts-expect-error - vendor prefix
- document.webkitFullscreenElement ||
- null
- );
- }
+/**
+ * Returns the current fullscreen element. This function handles all of the browser-specific variants.
+ * @returns {?Element} The current fullscreen element, or `null` if the window is not fullscreen.
+ */
+export function getFullscreenElement() {
+ return (
+ document.fullscreenElement ||
+ // @ts-expect-error - vendor prefix
+ document.msFullscreenElement ||
+ // @ts-expect-error - vendor prefix
+ document.mozFullScreenElement ||
+ // @ts-expect-error - vendor prefix
+ document.webkitFullscreenElement ||
+ null
+ );
+}
- /**
- * Gets all of the nodes within a `Range`.
- * @param {Range} range The range to check.
- * @returns {Node[]} The list of nodes.
- */
- static getNodesInRange(range) {
- const end = range.endContainer;
- const nodes = [];
- for (let node = /** @type {?Node} */ (range.startContainer); node !== null; node = this.getNextNode(node)) {
- nodes.push(node);
- if (node === end) { break; }
- }
- return nodes;
+/**
+ * Gets all of the nodes within a `Range`.
+ * @param {Range} range The range to check.
+ * @returns {Node[]} The list of nodes.
+ */
+export function getNodesInRange(range) {
+ const end = range.endContainer;
+ const nodes = [];
+ for (let node = /** @type {?Node} */ (range.startContainer); node !== null; node = getNextNode(node)) {
+ nodes.push(node);
+ if (node === end) { break; }
}
+ return nodes;
+}
- /**
- * Gets the next node after a specified node. This traverses the DOM in its logical order.
- * @param {Node} node The node to start at.
- * @returns {?Node} The next node, or `null` if there is no next node.
- */
- static getNextNode(node) {
- let next = /** @type {?Node} */ (node.firstChild);
- if (next === null) {
- while (true) {
- next = node.nextSibling;
- if (next !== null) { break; }
+/**
+ * Gets the next node after a specified node. This traverses the DOM in its logical order.
+ * @param {Node} node The node to start at.
+ * @returns {?Node} The next node, or `null` if there is no next node.
+ */
+export function getNextNode(node) {
+ let next = /** @type {?Node} */ (node.firstChild);
+ if (next === null) {
+ while (true) {
+ next = node.nextSibling;
+ if (next !== null) { break; }
- next = node.parentNode;
- if (next === null) { break; }
+ next = node.parentNode;
+ if (next === null) { break; }
- node = next;
- }
+ node = next;
}
- return next;
}
+ return next;
+}
- /**
- * Checks whether any node in a list of nodes matches a selector.
- * @param {Node[]} nodes The list of ndoes to check.
- * @param {string} selector The selector to test.
- * @returns {boolean} `true` if any element node matches the selector, `false` otherwise.
- */
- static anyNodeMatchesSelector(nodes, selector) {
- const ELEMENT_NODE = Node.ELEMENT_NODE;
- // This is a rather ugly way of getting the "node" variable to be a nullable
- for (let node of /** @type {(?Node)[]} */ (nodes)) {
- while (node !== null) {
- if (node.nodeType !== ELEMENT_NODE) {
- node = node.parentNode;
- continue;
- }
- if (/** @type {HTMLElement} */ (node).matches(selector)) { return true; }
- break;
+/**
+ * Checks whether any node in a list of nodes matches a selector.
+ * @param {Node[]} nodes The list of ndoes to check.
+ * @param {string} selector The selector to test.
+ * @returns {boolean} `true` if any element node matches the selector, `false` otherwise.
+ */
+export function anyNodeMatchesSelector(nodes, selector) {
+ const ELEMENT_NODE = Node.ELEMENT_NODE;
+ // This is a rather ugly way of getting the "node" variable to be a nullable
+ for (let node of /** @type {(?Node)[]} */ (nodes)) {
+ while (node !== null) {
+ if (node.nodeType !== ELEMENT_NODE) {
+ node = node.parentNode;
+ continue;
}
+ if (/** @type {HTMLElement} */ (node).matches(selector)) { return true; }
+ break;
}
- return false;
}
+ return false;
+}
- /**
- * Checks whether every node in a list of nodes matches a selector.
- * @param {Node[]} nodes The list of ndoes to check.
- * @param {string} selector The selector to test.
- * @returns {boolean} `true` if every element node matches the selector, `false` otherwise.
- */
- static everyNodeMatchesSelector(nodes, selector) {
- const ELEMENT_NODE = Node.ELEMENT_NODE;
- // This is a rather ugly way of getting the "node" variable to be a nullable
- for (let node of /** @type {(?Node)[]} */ (nodes)) {
- while (true) {
- if (node === null) { return false; }
- if (node.nodeType === ELEMENT_NODE && /** @type {HTMLElement} */ (node).matches(selector)) { break; }
- node = node.parentNode;
- }
+/**
+ * Checks whether every node in a list of nodes matches a selector.
+ * @param {Node[]} nodes The list of ndoes to check.
+ * @param {string} selector The selector to test.
+ * @returns {boolean} `true` if every element node matches the selector, `false` otherwise.
+ */
+export function everyNodeMatchesSelector(nodes, selector) {
+ const ELEMENT_NODE = Node.ELEMENT_NODE;
+ // This is a rather ugly way of getting the "node" variable to be a nullable
+ for (let node of /** @type {(?Node)[]} */ (nodes)) {
+ while (true) {
+ if (node === null) { return false; }
+ if (node.nodeType === ELEMENT_NODE && /** @type {HTMLElement} */ (node).matches(selector)) { break; }
+ node = node.parentNode;
}
- return true;
}
+ return true;
+}
- /**
- * Checks whether the meta key is supported in the browser on the specified operating system.
- * @param {string} os The operating system to check.
- * @param {string} browser The browser to check.
- * @returns {boolean} `true` if supported, `false` otherwise.
- */
- static isMetaKeySupported(os, browser) {
- return !(browser === 'firefox' || browser === 'firefox-mobile') || os === 'mac';
- }
+/**
+ * Checks whether the meta key is supported in the browser on the specified operating system.
+ * @param {string} os The operating system to check.
+ * @param {string} browser The browser to check.
+ * @returns {boolean} `true` if supported, `false` otherwise.
+ */
+export function isMetaKeySupported(os, browser) {
+ return !(browser === 'firefox' || browser === 'firefox-mobile') || os === 'mac';
+}
- /**
- * Checks whether an element on the page that can accept input is focused.
- * @returns {boolean} `true` if an input element is focused, `false` otherwise.
- */
- static isInputElementFocused() {
- const element = document.activeElement;
- if (element === null) { return false; }
- const type = element.nodeName.toUpperCase();
- switch (type) {
- case 'INPUT':
- case 'TEXTAREA':
- case 'SELECT':
- return true;
- default:
- return element instanceof HTMLElement && element.isContentEditable;
- }
+/**
+ * Checks whether an element on the page that can accept input is focused.
+ * @returns {boolean} `true` if an input element is focused, `false` otherwise.
+ */
+export function isInputElementFocused() {
+ const element = document.activeElement;
+ if (element === null) { return false; }
+ const type = element.nodeName.toUpperCase();
+ switch (type) {
+ case 'INPUT':
+ case 'TEXTAREA':
+ case 'SELECT':
+ return true;
+ default:
+ return element instanceof HTMLElement && element.isContentEditable;
}
+}
- /**
- * Offsets an array of DOMRects by a given amount.
- * @param {DOMRect[]} rects The DOMRects to offset.
- * @param {number} x The horizontal offset amount.
- * @param {number} y The vertical offset amount.
- * @returns {DOMRect[]} The DOMRects with the offset applied.
- */
- static offsetDOMRects(rects, x, y) {
- const results = [];
- for (const rect of rects) {
- results.push(new DOMRect(rect.left + x, rect.top + y, rect.width, rect.height));
- }
- return results;
+/**
+ * Offsets an array of DOMRects by a given amount.
+ * @param {DOMRect[]} rects The DOMRects to offset.
+ * @param {number} x The horizontal offset amount.
+ * @param {number} y The vertical offset amount.
+ * @returns {DOMRect[]} The DOMRects with the offset applied.
+ */
+export function offsetDOMRects(rects, x, y) {
+ const results = [];
+ for (const rect of rects) {
+ results.push(new DOMRect(rect.left + x, rect.top + y, rect.width, rect.height));
}
+ return results;
+}
- /**
- * Gets the parent writing mode of an element.
- * See: https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode.
- * @param {?Element} element The HTML element to check.
- * @returns {import('document-util').NormalizedWritingMode} The writing mode.
- */
- static getElementWritingMode(element) {
- if (element !== null) {
- const {writingMode} = getComputedStyle(element);
- if (typeof writingMode === 'string') {
- return this.normalizeWritingMode(writingMode);
- }
+/**
+ * Gets the parent writing mode of an element.
+ * See: https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode.
+ * @param {?Element} element The HTML element to check.
+ * @returns {import('document-util').NormalizedWritingMode} The writing mode.
+ */
+export function getElementWritingMode(element) {
+ if (element !== null) {
+ const {writingMode} = getComputedStyle(element);
+ if (typeof writingMode === 'string') {
+ return normalizeWritingMode(writingMode);
}
- return 'horizontal-tb';
}
+ return 'horizontal-tb';
+}
- /**
- * Normalizes a CSS writing mode value by converting non-standard and deprecated values
- * into their corresponding standard vaules.
- * @param {string} writingMode The writing mode to normalize.
- * @returns {import('document-util').NormalizedWritingMode} The normalized writing mode.
- */
- static normalizeWritingMode(writingMode) {
- switch (writingMode) {
- case 'tb':
- return 'vertical-lr';
- case 'tb-rl':
- return 'vertical-rl';
- case 'horizontal-tb':
- case 'vertical-rl':
- case 'vertical-lr':
- case 'sideways-rl':
- case 'sideways-lr':
- return writingMode;
- default: // 'lr', 'lr-tb', 'rl'
- return 'horizontal-tb';
- }
+/**
+ * Normalizes a CSS writing mode value by converting non-standard and deprecated values
+ * into their corresponding standard vaules.
+ * @param {string} writingMode The writing mode to normalize.
+ * @returns {import('document-util').NormalizedWritingMode} The normalized writing mode.
+ */
+export function normalizeWritingMode(writingMode) {
+ switch (writingMode) {
+ case 'tb':
+ return 'vertical-lr';
+ case 'tb-rl':
+ return 'vertical-rl';
+ case 'horizontal-tb':
+ case 'vertical-rl':
+ case 'vertical-lr':
+ case 'sideways-rl':
+ case 'sideways-lr':
+ return writingMode;
+ default: // 'lr', 'lr-tb', 'rl'
+ return 'horizontal-tb';
}
+}
- /**
- * Converts a value from an element to a number.
- * @param {string} valueString A string representation of a number.
- * @param {import('document-util').ToNumberConstraints} constraints An object which might contain `min`, `max`, and `step` fields which are used to constrain the value.
- * @returns {number} The parsed and constrained number.
- */
- static convertElementValueToNumber(valueString, constraints) {
- let value = Number.parseFloat(valueString);
- if (!Number.isFinite(value)) { value = 0; }
+/**
+ * Converts a value from an element to a number.
+ * @param {string} valueString A string representation of a number.
+ * @param {import('document-util').ToNumberConstraints} constraints An object which might contain `min`, `max`, and `step` fields which are used to constrain the value.
+ * @returns {number} The parsed and constrained number.
+ */
+export function convertElementValueToNumber(valueString, constraints) {
+ let value = Number.parseFloat(valueString);
+ if (!Number.isFinite(value)) { value = 0; }
- const min = this._convertToNumberOrNull(constraints.min);
- const max = this._convertToNumberOrNull(constraints.max);
- const step = this._convertToNumberOrNull(constraints.step);
- if (typeof min === 'number') { value = Math.max(value, min); }
- if (typeof max === 'number') { value = Math.min(value, max); }
- if (typeof step === 'number' && step !== 0) { value = Math.round(value / step) * step; }
- return value;
- }
+ const min = convertToNumberOrNull(constraints.min);
+ const max = convertToNumberOrNull(constraints.max);
+ const step = convertToNumberOrNull(constraints.step);
+ if (typeof min === 'number') { value = Math.max(value, min); }
+ if (typeof max === 'number') { value = Math.min(value, max); }
+ if (typeof step === 'number' && step !== 0) { value = Math.round(value / step) * step; }
+ return value;
+}
- /**
- * @param {string} value
- * @returns {?import('input').Modifier}
- */
- static normalizeModifier(value) {
- switch (value) {
- case 'alt':
- case 'ctrl':
- case 'meta':
- case 'shift':
- case 'mouse0':
- case 'mouse1':
- case 'mouse2':
- case 'mouse3':
- case 'mouse4':
- case 'mouse5':
- return value;
- default:
- return null;
- }
+/**
+ * @param {string} value
+ * @returns {?import('input').Modifier}
+ */
+export function normalizeModifier(value) {
+ switch (value) {
+ case 'alt':
+ case 'ctrl':
+ case 'meta':
+ case 'shift':
+ case 'mouse0':
+ case 'mouse1':
+ case 'mouse2':
+ case 'mouse3':
+ case 'mouse4':
+ case 'mouse5':
+ return value;
+ default:
+ return null;
}
+}
- /**
- * @param {string} value
- * @returns {?import('input').ModifierKey}
- */
- static normalizeModifierKey(value) {
- switch (value) {
- case 'alt':
- case 'ctrl':
- case 'meta':
- case 'shift':
- return value;
- default:
- return null;
- }
+/**
+ * @param {string} value
+ * @returns {?import('input').ModifierKey}
+ */
+export function normalizeModifierKey(value) {
+ switch (value) {
+ case 'alt':
+ case 'ctrl':
+ case 'meta':
+ case 'shift':
+ return value;
+ default:
+ return null;
}
+}
- /**
- * @param {MouseEvent} event The event to check.
- * @param {import('input').ModifierMouseButton[]|import('input').Modifier[]} array
- */
- static _getActiveButtons(event, array) {
- let {buttons} = event;
- if (typeof buttons === 'number' && buttons > 0) {
- for (let i = 0; i < 6; ++i) {
- const buttonFlag = (1 << i);
- if ((buttons & buttonFlag) !== 0) {
- array.push(/** @type {import('input').ModifierMouseButton} */ (`mouse${i}`));
- buttons &= ~buttonFlag;
- if (buttons === 0) { break; }
- }
+/**
+ * @param {MouseEvent} event The event to check.
+ * @param {import('input').ModifierMouseButton[]|import('input').Modifier[]} array
+ */
+function getActiveButtonsInternal(event, array) {
+ let {buttons} = event;
+ if (typeof buttons === 'number' && buttons > 0) {
+ for (let i = 0; i < 6; ++i) {
+ const buttonFlag = (1 << i);
+ if ((buttons & buttonFlag) !== 0) {
+ array.push(/** @type {import('input').ModifierMouseButton} */ (`mouse${i}`));
+ buttons &= ~buttonFlag;
+ if (buttons === 0) { break; }
}
}
}
+}
- /**
- * @param {string|number|undefined} value
- * @returns {?number}
- */
- static _convertToNumberOrNull(value) {
- if (typeof value !== 'number') {
- if (typeof value !== 'string' || value.length === 0) {
- return null;
- }
- value = Number.parseFloat(value);
+/**
+ * @param {string|number|undefined} value
+ * @returns {?number}
+ */
+function convertToNumberOrNull(value) {
+ if (typeof value !== 'number') {
+ if (typeof value !== 'string' || value.length === 0) {
+ return null;
}
- return !Number.isNaN(value) ? value : null;
+ value = Number.parseFloat(value);
}
+ return !Number.isNaN(value) ? value : null;
+}
- /**
- * Computes whether or not this browser and document supports CSS zoom, which is primarily a legacy Chromium feature.
- * @returns {boolean}
- */
- static _computeCssZoomSupported() {
- // 'style' can be undefined in certain contexts, such as when document is an SVG document.
- const {style} = document.createElement('div');
+/**
+ * Computes whether or not this browser and document supports CSS zoom, which is primarily a legacy Chromium feature.
+ * @returns {boolean}
+ */
+function computeCssZoomSupported() {
+ // 'style' can be undefined in certain contexts, such as when document is an SVG document.
+ const {style} = document.createElement('div');
+ return (
+ typeof style === 'object' &&
+ style !== null &&
// @ts-expect-error - zoom is a non-standard property.
- return (typeof style === 'object' && style !== null && typeof style.zoom === 'string');
- }
+ typeof style.zoom === 'string'
+ );
}
diff --git a/ext/js/dom/dom-data-binder.js b/ext/js/dom/dom-data-binder.js
index 7523e434..be5633d7 100644
--- a/ext/js/dom/dom-data-binder.js
+++ b/ext/js/dom/dom-data-binder.js
@@ -17,7 +17,7 @@
*/
import {TaskAccumulator} from '../general/task-accumulator.js';
-import {DocumentUtil} from './document-util.js';
+import {convertElementValueToNumber} from './document-util.js';
import {SelectorObserver} from './selector-observer.js';
/**
@@ -264,7 +264,7 @@ export class DOMDataBinder {
case 'text':
return `${/** @type {HTMLInputElement} */ (element).value}`;
case 'number':
- return DocumentUtil.convertElementValueToNumber(/** @type {HTMLInputElement} */ (element).value, /** @type {HTMLInputElement} */ (element));
+ return convertElementValueToNumber(/** @type {HTMLInputElement} */ (element).value, /** @type {HTMLInputElement} */ (element));
case 'textarea':
return /** @type {HTMLTextAreaElement} */ (element).value;
case 'select':
diff --git a/ext/js/dom/text-source-element.js b/ext/js/dom/text-source-element.js
index 927783d1..b2829e75 100644
--- a/ext/js/dom/text-source-element.js
+++ b/ext/js/dom/text-source-element.js
@@ -17,7 +17,7 @@
*/
import {readCodePointsBackward, readCodePointsForward} from '../data/sandbox/string-util.js';
-import {DocumentUtil} from './document-util.js';
+import {convertMultipleRectZoomCoordinates} from './document-util.js';
/**
* This class represents a text source that is attached to a HTML element, such as an <img>
@@ -145,7 +145,7 @@ export class TextSourceElement {
* @returns {DOMRect[]} The rects.
*/
getRects() {
- return DocumentUtil.convertMultipleRectZoomCoordinates(this._element.getClientRects(), this._element);
+ return convertMultipleRectZoomCoordinates(this._element.getClientRects(), this._element);
}
/**
diff --git a/ext/js/dom/text-source-generator.js b/ext/js/dom/text-source-generator.js
index 83c7271c..68bf036a 100644
--- a/ext/js/dom/text-source-generator.js
+++ b/ext/js/dom/text-source-generator.js
@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {DocumentUtil} from './document-util.js';
+import {computeZoomScale, isPointInAnyRect} from './document-util.js';
import {DOMTextScanner} from './dom-text-scanner.js';
import {TextSourceElement} from './text-source-element.js';
import {TextSourceRange} from './text-source-range.js';
@@ -358,7 +358,7 @@ export class TextSourceGenerator {
// Convert CSS zoom coordinates
if (normalizeCssZoom) {
- const scale = DocumentUtil.computeZoomScale(startContainer);
+ const scale = computeZoomScale(startContainer);
x /= scale;
y /= scale;
}
@@ -370,7 +370,7 @@ export class TextSourceGenerator {
const {node, offset, content} = new DOMTextScanner(nodePre, offsetPre, true, false).seek(1);
range.setEnd(node, offset);
- if (!this._isWhitespace(content) && DocumentUtil.isPointInAnyRect(x, y, range.getClientRects())) {
+ if (!this._isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects())) {
return true;
}
} finally {
@@ -381,7 +381,7 @@ export class TextSourceGenerator {
const {node, offset, content} = new DOMTextScanner(startContainer, range.startOffset, true, false).seek(-1);
range.setStart(node, offset);
- if (!this._isWhitespace(content) && DocumentUtil.isPointInAnyRect(x, y, range.getClientRects())) {
+ if (!this._isWhitespace(content) && 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/js/dom/text-source-range.js b/ext/js/dom/text-source-range.js
index 05e7b6fb..2012af7a 100644
--- a/ext/js/dom/text-source-range.js
+++ b/ext/js/dom/text-source-range.js
@@ -17,7 +17,7 @@
*/
import {toError} from '../core/to-error.js';
-import {DocumentUtil} from './document-util.js';
+import {convertMultipleRectZoomCoordinates, convertRectZoomCoordinates, getElementWritingMode, getNodesInRange, offsetDOMRects} from './document-util.js';
import {DOMTextScanner} from './dom-text-scanner.js';
/**
@@ -170,7 +170,7 @@ export class TextSourceRange {
*/
getRects() {
if (this._isImposterDisconnected()) { return this._getCachedRects(); }
- return DocumentUtil.convertMultipleRectZoomCoordinates(this._range.getClientRects(), this._range.startContainer);
+ return convertMultipleRectZoomCoordinates(this._range.getClientRects(), this._range.startContainer);
}
/**
@@ -181,7 +181,7 @@ export class TextSourceRange {
getWritingMode() {
let node = this._isImposterDisconnected() ? this._imposterSourceElement : this._range.startContainer;
if (node !== null && node.nodeType !== Node.ELEMENT_NODE) { node = node.parentElement; }
- return DocumentUtil.getElementWritingMode(/** @type {?Element} */ (node));
+ return getElementWritingMode(/** @type {?Element} */ (node));
}
/**
@@ -243,7 +243,7 @@ export class TextSourceRange {
* @returns {Node[]} The nodes in the range.
*/
getNodesInRange() {
- return DocumentUtil.getNodesInRange(this._range);
+ return getNodesInRange(this._range);
}
/**
@@ -263,8 +263,8 @@ export class TextSourceRange {
* @returns {TextSourceRange} A new instance of the class corresponding to the range.
*/
static createFromImposter(range, imposterElement, imposterSourceElement) {
- const cachedRects = DocumentUtil.convertMultipleRectZoomCoordinates(range.getClientRects(), range.startContainer);
- const cachedSourceRect = DocumentUtil.convertRectZoomCoordinates(imposterSourceElement.getBoundingClientRect(), imposterSourceElement);
+ const cachedRects = convertMultipleRectZoomCoordinates(range.getClientRects(), range.startContainer);
+ const cachedSourceRect = convertRectZoomCoordinates(imposterSourceElement.getBoundingClientRect(), imposterSourceElement);
return new TextSourceRange(range, range.startOffset, range.toString(), imposterElement, imposterSourceElement, cachedRects, cachedSourceRect);
}
@@ -289,8 +289,8 @@ export class TextSourceRange {
) {
throw new Error('Cached rects not valid for this instance');
}
- const sourceRect = DocumentUtil.convertRectZoomCoordinates(this._imposterSourceElement.getBoundingClientRect(), this._imposterSourceElement);
- return DocumentUtil.offsetDOMRects(
+ const sourceRect = convertRectZoomCoordinates(this._imposterSourceElement.getBoundingClientRect(), this._imposterSourceElement);
+ return offsetDOMRects(
this._cachedRects,
sourceRect.left - this._cachedSourceRect.left,
sourceRect.top - this._cachedSourceRect.top
diff --git a/ext/js/input/hotkey-handler.js b/ext/js/input/hotkey-handler.js
index 6d7d3d7a..818c0155 100644
--- a/ext/js/input/hotkey-handler.js
+++ b/ext/js/input/hotkey-handler.js
@@ -18,7 +18,7 @@
import {EventDispatcher} from '../core/event-dispatcher.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
-import {DocumentUtil} from '../dom/document-util.js';
+import {getActiveModifiers, isInputElementFocused} from '../dom/document-util.js';
/**
* Class which handles hotkey events and actions.
@@ -173,7 +173,7 @@ export class HotkeyHandler extends EventDispatcher {
_onKeyDown(event) {
const hotkeyInfo = this._hotkeys.get(event.code);
if (typeof hotkeyInfo !== 'undefined') {
- const eventModifiers = DocumentUtil.getActiveModifiers(event);
+ const eventModifiers = getActiveModifiers(event);
if (this._invokeHandlers(eventModifiers, hotkeyInfo, event.key)) {
event.preventDefault();
return;
@@ -269,7 +269,7 @@ export class HotkeyHandler extends EventDispatcher {
_isHotkeyPermitted(modifiers, key) {
return !(
(modifiers.length === 0 || (modifiers.length === 1 && modifiers[0] === 'shift')) &&
- DocumentUtil.isInputElementFocused() &&
+ isInputElementFocused() &&
this._isKeyCharacterInput(key)
);
}
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index 697e2b4d..d4caa643 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -20,7 +20,7 @@ import {EventDispatcher} from '../core/event-dispatcher.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {log} from '../core/log.js';
import {clone} from '../core/utilities.js';
-import {DocumentUtil} from '../dom/document-util.js';
+import {anyNodeMatchesSelector, everyNodeMatchesSelector, getActiveModifiers, getActiveModifiersAndButtons, isPointInSelection} from '../dom/document-util.js';
import {TextSourceElement} from '../dom/text-source-element.js';
/**
@@ -609,8 +609,8 @@ export class TextScanner extends EventDispatcher {
if (preventNextClickScan) { return; }
- const modifiers = DocumentUtil.getActiveModifiersAndButtons(e);
- const modifierKeys = DocumentUtil.getActiveModifiers(e);
+ const modifiers = getActiveModifiersAndButtons(e);
+ const modifierKeys = getActiveModifiers(e);
const inputInfo = this._createInputInfo(null, 'mouse', 'click', false, modifiers, modifierKeys);
this._searchAt(e.clientX, e.clientY, inputInfo);
}
@@ -658,7 +658,7 @@ export class TextScanner extends EventDispatcher {
this._preventNextClick = false;
const selection = window.getSelection();
- if (selection !== null && DocumentUtil.isPointInSelection(x, y, selection)) {
+ if (selection !== null && isPointInSelection(x, y, selection)) {
return;
}
@@ -1393,8 +1393,8 @@ export class TextScanner extends EventDispatcher {
* @returns {?import('text-scanner').InputInfo}
*/
_getMatchingInputGroupFromEvent(pointerType, eventType, event) {
- const modifiers = DocumentUtil.getActiveModifiersAndButtons(event);
- const modifierKeys = DocumentUtil.getActiveModifiers(event);
+ const modifiers = getActiveModifiersAndButtons(event);
+ const modifierKeys = getActiveModifiers(event);
return this._getMatchingInputGroup(pointerType, eventType, modifiers, modifierKeys);
}
@@ -1534,8 +1534,8 @@ export class TextScanner extends EventDispatcher {
while (length > 0) {
const nodes = textSource.getNodesInRange();
if (
- (includeSelector !== null && !DocumentUtil.everyNodeMatchesSelector(nodes, includeSelector)) ||
- (excludeSelector !== null && DocumentUtil.anyNodeMatchesSelector(nodes, excludeSelector))
+ (includeSelector !== null && !everyNodeMatchesSelector(nodes, includeSelector)) ||
+ (excludeSelector !== null && anyNodeMatchesSelector(nodes, excludeSelector))
) {
--length;
textSource.setEndOffset(length, false, layoutAwareScan);
diff --git a/ext/js/pages/settings/generic-setting-controller.js b/ext/js/pages/settings/generic-setting-controller.js
index 12db2ab7..7c082a96 100644
--- a/ext/js/pages/settings/generic-setting-controller.js
+++ b/ext/js/pages/settings/generic-setting-controller.js
@@ -18,7 +18,7 @@
import {ExtensionError} from '../../core/extension-error.js';
import {parseJson} from '../../core/json.js';
-import {DocumentUtil} from '../../dom/document-util.js';
+import {convertElementValueToNumber} from '../../dom/document-util.js';
import {DOMDataBinder} from '../../dom/dom-data-binder.js';
export class GenericSettingController {
@@ -328,7 +328,7 @@ export class GenericSettingController {
_toNumber(value, data) {
/** @type {import('document-util').ToNumberConstraints} */
const constraints = typeof data.constraints === 'object' && data.constraints !== null ? data.constraints : {};
- return typeof value === 'string' ? DocumentUtil.convertElementValueToNumber(value, constraints) : 0;
+ return typeof value === 'string' ? convertElementValueToNumber(value, constraints) : 0;
}
/**
diff --git a/ext/js/pages/settings/keyboard-mouse-input-field.js b/ext/js/pages/settings/keyboard-mouse-input-field.js
index 310cbb19..0c45d4bb 100644
--- a/ext/js/pages/settings/keyboard-mouse-input-field.js
+++ b/ext/js/pages/settings/keyboard-mouse-input-field.js
@@ -18,7 +18,7 @@
import {EventDispatcher} from '../../core/event-dispatcher.js';
import {EventListenerCollection} from '../../core/event-listener-collection.js';
-import {DocumentUtil} from '../../dom/document-util.js';
+import {getActiveButtons, getActiveModifiers} from '../../dom/document-util.js';
import {HotkeyUtil} from '../../input/hotkey-util.js';
/**
@@ -139,7 +139,7 @@ export class KeyboardMouseInputField extends EventDispatcher {
* @returns {Set<import('input').ModifierKey>}
*/
_getModifierKeys(e) {
- const modifiers = new Set(DocumentUtil.getActiveModifiers(e));
+ const modifiers = new Set(getActiveModifiers(e));
// 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.
@@ -216,7 +216,7 @@ export class KeyboardMouseInputField extends EventDispatcher {
*/
_onMouseButtonMouseDown(e) {
e.preventDefault();
- this._addModifiers(DocumentUtil.getActiveButtons(e));
+ this._addModifiers(getActiveButtons(e));
}
/**
@@ -236,7 +236,7 @@ export class KeyboardMouseInputField extends EventDispatcher {
return;
}
e.preventDefault();
- this._addModifiers(DocumentUtil.getActiveButtons(e));
+ this._addModifiers(getActiveButtons(e));
}
/**
diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js
index 907cf4a1..0a01b836 100644
--- a/ext/js/pages/settings/keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js
@@ -17,7 +17,7 @@
*/
import {EventListenerCollection} from '../../core/event-listener-collection.js';
-import {DocumentUtil} from '../../dom/document-util.js';
+import {convertElementValueToNumber, normalizeModifierKey} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {ObjectPropertyAccessor} from '../../general/object-property-accessor.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
@@ -400,7 +400,7 @@ class KeyboardShortcutHotkeyEntry {
/** @type {import('input').ModifierKey[]} */
const modifiers2 = [];
for (const modifier of modifiers) {
- const modifier2 = DocumentUtil.normalizeModifierKey(modifier);
+ const modifier2 = normalizeModifierKey(modifier);
if (modifier2 === null) { continue; }
modifiers2.push(modifier2);
}
@@ -435,7 +435,7 @@ class KeyboardShortcutHotkeyEntry {
let value = this._getArgumentInputValue(node);
switch (template) {
case 'hotkey-argument-move-offset':
- value = `${DocumentUtil.convertElementValueToNumber(value, node)}`;
+ value = `${convertElementValueToNumber(value, node)}`;
break;
}
this._setArgument(value);
diff --git a/ext/js/pages/settings/nested-popups-controller.js b/ext/js/pages/settings/nested-popups-controller.js
index ccdc3c9c..077b1a66 100644
--- a/ext/js/pages/settings/nested-popups-controller.js
+++ b/ext/js/pages/settings/nested-popups-controller.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {DocumentUtil} from '../../dom/document-util.js';
+import {convertElementValueToNumber} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
export class NestedPopupsController {
@@ -71,7 +71,7 @@ export class NestedPopupsController {
*/
_onNestedPopupsCountChange(e) {
const node = /** @type {HTMLInputElement} */ (e.currentTarget);
- const value = Math.max(1, DocumentUtil.convertElementValueToNumber(node.value, node));
+ const value = Math.max(1, convertElementValueToNumber(node.value, node));
this._setPopupNestingMaxDepth(value);
}
diff --git a/ext/js/pages/settings/profile-conditions-ui.js b/ext/js/pages/settings/profile-conditions-ui.js
index 5801af17..d2bf03bf 100644
--- a/ext/js/pages/settings/profile-conditions-ui.js
+++ b/ext/js/pages/settings/profile-conditions-ui.js
@@ -18,7 +18,7 @@
import {EventDispatcher} from '../../core/event-dispatcher.js';
import {EventListenerCollection} from '../../core/event-listener-collection.js';
-import {DocumentUtil} from '../../dom/document-util.js';
+import {normalizeModifier} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
@@ -941,7 +941,7 @@ class ProfileConditionUI {
/** @type {import('input').Modifier[]} */
const results = [];
for (const item of modifiersString.split(/[,;\s]+/)) {
- const modifier = DocumentUtil.normalizeModifier(item.trim().toLowerCase());
+ const modifier = normalizeModifier(item.trim().toLowerCase());
if (modifier !== null) { results.push(modifier); }
}
return results;
diff --git a/ext/js/pages/settings/scan-inputs-controller.js b/ext/js/pages/settings/scan-inputs-controller.js
index f1547fe4..144eae9f 100644
--- a/ext/js/pages/settings/scan-inputs-controller.js
+++ b/ext/js/pages/settings/scan-inputs-controller.js
@@ -17,7 +17,7 @@
*/
import {EventListenerCollection} from '../../core/event-listener-collection.js';
-import {DocumentUtil} from '../../dom/document-util.js';
+import {normalizeModifier} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
@@ -417,7 +417,7 @@ class ScanInputField {
/** @type {import('input').Modifier[]} */
const results = [];
for (const modifier of modifiersString.split(/[,;\s]+/)) {
- const modifier2 = DocumentUtil.normalizeModifier(modifier.trim().toLowerCase());
+ const modifier2 = normalizeModifier(modifier.trim().toLowerCase());
if (modifier2 === null) { continue; }
results.push(modifier2);
}
diff --git a/ext/js/pages/settings/settings-display-controller.js b/ext/js/pages/settings/settings-display-controller.js
index 47aa9c9c..6e740e13 100644
--- a/ext/js/pages/settings/settings-display-controller.js
+++ b/ext/js/pages/settings/settings-display-controller.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {DocumentUtil} from '../../dom/document-util.js';
+import {isInputElementFocused} from '../../dom/document-util.js';
import {PopupMenu} from '../../dom/popup-menu.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {SelectorObserver} from '../../dom/selector-observer.js';
@@ -184,7 +184,7 @@ export class SettingsDisplayController {
_onKeyDown(e) {
switch (e.code) {
case 'Escape':
- if (!DocumentUtil.isInputElementFocused()) {
+ if (!isInputElementFocused()) {
this._closeTopMenuOrModal();
e.preventDefault();
}