DOM + DocumentUtil merge (#727)
* Add DOM functions to DocumentUtil * Use DocumentUtil instead of DOM * Remove DOM * Move document-util.js into mixed
This commit is contained in:
parent
9f8f83508e
commit
2a86d66092
@ -42,12 +42,11 @@
|
|||||||
"mixed/js/core.js",
|
"mixed/js/core.js",
|
||||||
"mixed/js/yomichan.js",
|
"mixed/js/yomichan.js",
|
||||||
"mixed/js/comm.js",
|
"mixed/js/comm.js",
|
||||||
"mixed/js/dom.js",
|
|
||||||
"mixed/js/api.js",
|
"mixed/js/api.js",
|
||||||
"mixed/js/dynamic-loader.js",
|
"mixed/js/dynamic-loader.js",
|
||||||
"mixed/js/frame-client.js",
|
"mixed/js/frame-client.js",
|
||||||
"mixed/js/text-scanner.js",
|
"mixed/js/text-scanner.js",
|
||||||
"fg/js/document-util.js",
|
"mixed/js/document-util.js",
|
||||||
"fg/js/dom-text-scanner.js",
|
"fg/js/dom-text-scanner.js",
|
||||||
"fg/js/popup.js",
|
"fg/js/popup.js",
|
||||||
"fg/js/source.js",
|
"fg/js/source.js",
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* ClipboardMonitor
|
* ClipboardMonitor
|
||||||
* DOM
|
|
||||||
* Display
|
* Display
|
||||||
|
* DocumentUtil
|
||||||
* api
|
* api
|
||||||
* wanakana
|
* wanakana
|
||||||
*/
|
*/
|
||||||
@ -104,7 +104,7 @@ class DisplaySearch extends Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
const key = DOM.getKeyFromEvent(e);
|
const key = DocumentUtil.getKeyFromEvent(e);
|
||||||
const ignoreKeys = this._onKeyDownIgnoreKeys;
|
const ignoreKeys = this._onKeyDownIgnoreKeys;
|
||||||
|
|
||||||
const activeModifierMap = new Map([
|
const activeModifierMap = new Map([
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DOM
|
* DocumentUtil
|
||||||
* conditionsNormalizeOptionValue
|
* conditionsNormalizeOptionValue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ ConditionsUI.Condition = class Condition {
|
|||||||
const pressedKeyIndices = new Set();
|
const pressedKeyIndices = new Set();
|
||||||
|
|
||||||
const onKeyDown = ({originalEvent}) => {
|
const onKeyDown = ({originalEvent}) => {
|
||||||
const pressedKeyEventName = DOM.getKeyFromEvent(originalEvent);
|
const pressedKeyEventName = DocumentUtil.getKeyFromEvent(originalEvent);
|
||||||
if (pressedKeyEventName === 'Escape' || pressedKeyEventName === 'Backspace') {
|
if (pressedKeyEventName === 'Escape' || pressedKeyEventName === 'Backspace') {
|
||||||
pressedKeyIndices.clear();
|
pressedKeyIndices.clear();
|
||||||
inputInner.val('');
|
inputInner.val('');
|
||||||
@ -331,7 +331,7 @@ ConditionsUI.Condition = class Condition {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pressedModifiers = DOM.getActiveModifiers(originalEvent);
|
const pressedModifiers = DocumentUtil.getActiveModifiers(originalEvent);
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey
|
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey
|
||||||
// https://askubuntu.com/questions/567731/why-is-shift-alt-being-mapped-to-meta
|
// 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
|
// It works with mouse events on some platforms, so try to determine if metaKey is pressed
|
||||||
|
@ -73,12 +73,11 @@
|
|||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
<script src="/mixed/js/yomichan.js"></script>
|
<script src="/mixed/js/yomichan.js"></script>
|
||||||
<script src="/mixed/js/comm.js"></script>
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
|
|
||||||
<script src="/bg/js/handlebars.js"></script>
|
<script src="/bg/js/handlebars.js"></script>
|
||||||
<script src="/fg/js/document-util.js"></script>
|
<script src="/mixed/js/document-util.js"></script>
|
||||||
<script src="/fg/js/dom-text-scanner.js"></script>
|
<script src="/fg/js/dom-text-scanner.js"></script>
|
||||||
<script src="/fg/js/source.js"></script>
|
<script src="/fg/js/source.js"></script>
|
||||||
<script src="/mixed/js/audio-system.js"></script>
|
<script src="/mixed/js/audio-system.js"></script>
|
||||||
|
@ -121,13 +121,12 @@
|
|||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
<script src="/mixed/js/yomichan.js"></script>
|
<script src="/mixed/js/yomichan.js"></script>
|
||||||
<script src="/mixed/js/comm.js"></script>
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/dynamic-loader.js"></script>
|
<script src="/mixed/js/dynamic-loader.js"></script>
|
||||||
<script src="/mixed/js/frame-client.js"></script>
|
<script src="/mixed/js/frame-client.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
|
|
||||||
<script src="/fg/js/document-util.js"></script>
|
<script src="/mixed/js/document-util.js"></script>
|
||||||
<script src="/fg/js/dom-text-scanner.js"></script>
|
<script src="/fg/js/dom-text-scanner.js"></script>
|
||||||
<script src="/fg/js/popup.js"></script>
|
<script src="/fg/js/popup.js"></script>
|
||||||
<script src="/fg/js/source.js"></script>
|
<script src="/fg/js/source.js"></script>
|
||||||
|
@ -1135,7 +1135,6 @@
|
|||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
<script src="/mixed/js/yomichan.js"></script>
|
<script src="/mixed/js/yomichan.js"></script>
|
||||||
<script src="/mixed/js/comm.js"></script>
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
|
||||||
<script src="/mixed/js/environment.js"></script>
|
<script src="/mixed/js/environment.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
@ -1148,6 +1147,7 @@
|
|||||||
<script src="/bg/js/profile-conditions.js"></script>
|
<script src="/bg/js/profile-conditions.js"></script>
|
||||||
<script src="/bg/js/util.js"></script>
|
<script src="/bg/js/util.js"></script>
|
||||||
<script src="/mixed/js/audio-system.js"></script>
|
<script src="/mixed/js/audio-system.js"></script>
|
||||||
|
<script src="/mixed/js/document-util.js"></script>
|
||||||
|
|
||||||
<script src="/bg/js/settings/anki.js"></script>
|
<script src="/bg/js/settings/anki.js"></script>
|
||||||
<script src="/bg/js/settings/anki-templates.js"></script>
|
<script src="/bg/js/settings/anki-templates.js"></script>
|
||||||
|
@ -47,11 +47,10 @@
|
|||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
<script src="/mixed/js/yomichan.js"></script>
|
<script src="/mixed/js/yomichan.js"></script>
|
||||||
<script src="/mixed/js/comm.js"></script>
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
|
|
||||||
<script src="/fg/js/document-util.js"></script>
|
<script src="/mixed/js/document-util.js"></script>
|
||||||
<script src="/fg/js/dom-text-scanner.js"></script>
|
<script src="/fg/js/dom-text-scanner.js"></script>
|
||||||
<script src="/fg/js/source.js"></script>
|
<script src="/fg/js/source.js"></script>
|
||||||
<script src="/mixed/js/audio-system.js"></script>
|
<script src="/mixed/js/audio-system.js"></script>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DOM
|
|
||||||
* DocumentUtil
|
* DocumentUtil
|
||||||
* FrameOffsetForwarder
|
* FrameOffsetForwarder
|
||||||
* PopupProxy
|
* PopupProxy
|
||||||
@ -98,7 +97,7 @@ class Frontend {
|
|||||||
this._textScanner.prepare();
|
this._textScanner.prepare();
|
||||||
|
|
||||||
window.addEventListener('resize', this._onResize.bind(this), false);
|
window.addEventListener('resize', this._onResize.bind(this), false);
|
||||||
DOM.addFullscreenChangeEventListener(this._updatePopup.bind(this));
|
DocumentUtil.addFullscreenChangeEventListener(this._updatePopup.bind(this));
|
||||||
|
|
||||||
const visualViewport = window.visualViewport;
|
const visualViewport = window.visualViewport;
|
||||||
if (visualViewport !== null && typeof visualViewport === 'object') {
|
if (visualViewport !== null && typeof visualViewport === 'object') {
|
||||||
@ -274,7 +273,7 @@ class Frontend {
|
|||||||
if (
|
if (
|
||||||
isIframe &&
|
isIframe &&
|
||||||
showIframePopupsInRootFrame &&
|
showIframePopupsInRootFrame &&
|
||||||
DOM.getFullscreenElement() === null &&
|
DocumentUtil.getFullscreenElement() === null &&
|
||||||
this._allowRootFramePopupProxy
|
this._allowRootFramePopupProxy
|
||||||
) {
|
) {
|
||||||
popupPromise = this._popupCache.get('iframe');
|
popupPromise = this._popupCache.get('iframe');
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DOM
|
* DocumentUtil
|
||||||
* FrameClient
|
* FrameClient
|
||||||
* api
|
* api
|
||||||
* dynamicLoader
|
* dynamicLoader
|
||||||
@ -349,7 +349,7 @@ class Popup {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOM.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners);
|
DocumentUtil.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFullscreenChanged() {
|
_onFullscreenChanged() {
|
||||||
@ -475,7 +475,7 @@ class Popup {
|
|||||||
|
|
||||||
_getFrameParentElement() {
|
_getFrameParentElement() {
|
||||||
const defaultParent = document.body;
|
const defaultParent = document.body;
|
||||||
const fullscreenElement = DOM.getFullscreenElement();
|
const fullscreenElement = DocumentUtil.getFullscreenElement();
|
||||||
if (
|
if (
|
||||||
fullscreenElement === null ||
|
fullscreenElement === null ||
|
||||||
fullscreenElement.shadowRoot ||
|
fullscreenElement.shadowRoot ||
|
||||||
|
@ -41,12 +41,11 @@
|
|||||||
"mixed/js/core.js",
|
"mixed/js/core.js",
|
||||||
"mixed/js/yomichan.js",
|
"mixed/js/yomichan.js",
|
||||||
"mixed/js/comm.js",
|
"mixed/js/comm.js",
|
||||||
"mixed/js/dom.js",
|
|
||||||
"mixed/js/api.js",
|
"mixed/js/api.js",
|
||||||
"mixed/js/dynamic-loader.js",
|
"mixed/js/dynamic-loader.js",
|
||||||
"mixed/js/frame-client.js",
|
"mixed/js/frame-client.js",
|
||||||
"mixed/js/text-scanner.js",
|
"mixed/js/text-scanner.js",
|
||||||
"fg/js/document-util.js",
|
"mixed/js/document-util.js",
|
||||||
"fg/js/dom-text-scanner.js",
|
"fg/js/dom-text-scanner.js",
|
||||||
"fg/js/popup.js",
|
"fg/js/popup.js",
|
||||||
"fg/js/source.js",
|
"fg/js/source.js",
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* AudioSystem
|
* AudioSystem
|
||||||
* DOM
|
|
||||||
* DisplayGenerator
|
* DisplayGenerator
|
||||||
* DisplayHistory
|
* DisplayHistory
|
||||||
* DocumentUtil
|
* DocumentUtil
|
||||||
@ -186,11 +185,11 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
const key = DOM.getKeyFromEvent(e);
|
const key = DocumentUtil.getKeyFromEvent(e);
|
||||||
const handlers = this._hotkeys.get(key);
|
const handlers = this._hotkeys.get(key);
|
||||||
if (typeof handlers === 'undefined') { return false; }
|
if (typeof handlers === 'undefined') { return false; }
|
||||||
|
|
||||||
const eventModifiers = DOM.getActiveModifiers(e);
|
const eventModifiers = DocumentUtil.getActiveModifiers(e);
|
||||||
for (const {modifiers, action} of handlers) {
|
for (const {modifiers, action} of handlers) {
|
||||||
if (getSetDifference(modifiers, eventModifiers).size !== 0) { continue; }
|
if (getSetDifference(modifiers, eventModifiers).size !== 0) { continue; }
|
||||||
|
|
||||||
@ -558,7 +557,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onGlossaryMouseDown(e) {
|
_onGlossaryMouseDown(e) {
|
||||||
if (DOM.isMouseButtonPressed(e, 'primary')) {
|
if (DocumentUtil.isMouseButtonPressed(e, 'primary')) {
|
||||||
this._clickScanPrevent = false;
|
this._clickScanPrevent = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -568,7 +567,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onGlossaryMouseUp(e) {
|
_onGlossaryMouseUp(e) {
|
||||||
if (!this._clickScanPrevent && DOM.isMouseButtonPressed(e, 'primary')) {
|
if (!this._clickScanPrevent && DocumentUtil.isMouseButtonPressed(e, 'primary')) {
|
||||||
try {
|
try {
|
||||||
this._onTermLookup(e);
|
this._onTermLookup(e);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DOM
|
|
||||||
* DOMTextScanner
|
* DOMTextScanner
|
||||||
* TextSourceElement
|
* TextSourceElement
|
||||||
* TextSourceRange
|
* 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
|
// Private
|
||||||
|
|
||||||
_setImposterStyle(style, propertyName, value) {
|
_setImposterStyle(style, propertyName, value) {
|
||||||
@ -240,7 +365,7 @@ class DocumentUtil {
|
|||||||
const {node, offset, content} = new DOMTextScanner(range.endContainer, range.endOffset, true, false).seek(1);
|
const {node, offset, content} = new DOMTextScanner(range.endContainer, range.endOffset, true, false).seek(1);
|
||||||
range.setEnd(node, offset);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -251,7 +376,7 @@ class DocumentUtil {
|
|||||||
const {node, offset, content} = new DOMTextScanner(range.startContainer, range.startOffset, true, false).seek(-1);
|
const {node, offset, content} = new DOMTextScanner(range.startContainer, range.startOffset, true, false).seek(-1);
|
||||||
range.setStart(node, offset);
|
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.
|
// This purposefully leaves the starting offset as modified and sets the range length to 0.
|
||||||
range.setEnd(node, offset);
|
range.setEnd(node, offset);
|
||||||
return true;
|
return true;
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DOM
|
* DocumentUtil
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TextScanner extends EventDispatcher {
|
class TextScanner extends EventDispatcher {
|
||||||
@ -155,8 +155,8 @@ class TextScanner extends EventDispatcher {
|
|||||||
if (this._ignoreNodes !== null && clonedTextSource.range) {
|
if (this._ignoreNodes !== null && clonedTextSource.range) {
|
||||||
length = clonedTextSource.text().length;
|
length = clonedTextSource.text().length;
|
||||||
while (clonedTextSource.range && length > 0) {
|
while (clonedTextSource.range && length > 0) {
|
||||||
const nodes = DOM.getNodesInRange(clonedTextSource.range);
|
const nodes = DocumentUtil.getNodesInRange(clonedTextSource.range);
|
||||||
if (!DOM.anyNodeMatchesSelector(nodes, this._ignoreNodes)) {
|
if (!DocumentUtil.anyNodeMatchesSelector(nodes, this._ignoreNodes)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--length;
|
--length;
|
||||||
@ -204,16 +204,16 @@ class TextScanner extends EventDispatcher {
|
|||||||
_onMouseMove(e) {
|
_onMouseMove(e) {
|
||||||
this._scanTimerClear();
|
this._scanTimerClear();
|
||||||
|
|
||||||
if (this._pendingLookup || DOM.isMouseButtonDown(e, 'primary')) {
|
if (this._pendingLookup || DocumentUtil.isMouseButtonDown(e, 'primary')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifiers = DOM.getActiveModifiers(e);
|
const modifiers = DocumentUtil.getActiveModifiers(e);
|
||||||
this.trigger('activeModifiersChanged', {modifiers});
|
this.trigger('activeModifiersChanged', {modifiers});
|
||||||
|
|
||||||
if (!(
|
if (!(
|
||||||
this._isScanningModifierPressed(this._modifier, e) ||
|
this._isScanningModifierPressed(this._modifier, e) ||
|
||||||
(this._useMiddleMouse && DOM.isMouseButtonDown(e, 'auxiliary'))
|
(this._useMiddleMouse && DocumentUtil.isMouseButtonDown(e, 'auxiliary'))
|
||||||
)) {
|
)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DOM.isMouseButtonDown(e, 'primary')) {
|
if (DocumentUtil.isMouseButtonDown(e, 'primary')) {
|
||||||
this._scanTimerClear();
|
this._scanTimerClear();
|
||||||
this.clearSelection(false);
|
this.clearSelection(false);
|
||||||
}
|
}
|
||||||
@ -284,7 +284,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
this._preventNextClick = false;
|
this._preventNextClick = false;
|
||||||
|
|
||||||
const primaryTouch = e.changedTouches[0];
|
const primaryTouch = e.changedTouches[0];
|
||||||
if (DOM.isPointInSelection(primaryTouch.clientX, primaryTouch.clientY, window.getSelection())) {
|
if (DocumentUtil.isPointInSelection(primaryTouch.clientX, primaryTouch.clientY, window.getSelection())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +93,9 @@ async function testDocument1() {
|
|||||||
|
|
||||||
const vm = new VM({document, window, Range, Node});
|
const vm = new VM({document, window, Range, Node});
|
||||||
vm.execute([
|
vm.execute([
|
||||||
'mixed/js/dom.js',
|
|
||||||
'fg/js/dom-text-scanner.js',
|
'fg/js/dom-text-scanner.js',
|
||||||
'fg/js/source.js',
|
'fg/js/source.js',
|
||||||
'fg/js/document-util.js'
|
'mixed/js/document-util.js'
|
||||||
]);
|
]);
|
||||||
const [DOMTextScanner, TextSourceRange, TextSourceElement, DocumentUtil] = vm.get([
|
const [DOMTextScanner, TextSourceRange, TextSourceElement, DocumentUtil] = vm.get([
|
||||||
'DOMTextScanner',
|
'DOMTextScanner',
|
||||||
|
Loading…
Reference in New Issue
Block a user