diff options
Diffstat (limited to 'ext/fg/js')
-rw-r--r-- | ext/fg/js/driver.js | 21 | ||||
-rw-r--r-- | ext/fg/js/source-element.js | 33 | ||||
-rw-r--r-- | ext/fg/js/source-range.js | 90 | ||||
-rw-r--r-- | ext/fg/js/util.js | 22 |
4 files changed, 102 insertions, 64 deletions
diff --git a/ext/fg/js/driver.js b/ext/fg/js/driver.js index e94a4ac2..b0cc4613 100644 --- a/ext/fg/js/driver.js +++ b/ext/fg/js/driver.js @@ -70,15 +70,22 @@ window.driver = new class { return; } - if (this.options.scanning.requireShift && !e.shiftKey && !(this.mouseDownMiddle && this.options.scanning.middleMouse)) { + const mouseScan = this.mouseDownMiddle && this.options.scanning.middleMouse; + const keyScan = + this.options.scanning.modifier === 'alt' && e.altKey || + this.options.scanning.modifier === 'ctrl' && e.ctrlKey || + this.options.scanning.modifier === 'shift' && e.shiftKey || + this.options.scanning.modifier === 'none'; + + if (!keyScan && !mouseScan) { return; } const searchFunc = () => this.searchAt(this.lastMousePos); - if (this.options.scanning.requireShift) { - searchFunc(); - } else { + if (this.options.scanning.modifier === 'none') { this.popupTimerSet(searchFunc); + } else { + searchFunc(); } } @@ -142,8 +149,9 @@ window.driver = new class { return; } - const textSource = docRangeFromPoint(point, this.options.scanning.imposter); + const textSource = docRangeFromPoint(point); if (!textSource || !textSource.containsPoint(point)) { + docImposterDestroy(); return; } @@ -159,6 +167,7 @@ window.driver = new class { }).catch(error => { this.handleError(error, textSource); }).then(() => { + docImposterDestroy(); this.pendingLookup = false; }); } @@ -230,7 +239,7 @@ window.driver = new class { handleError(error, textSource) { if (window.orphaned) { - if (textSource && this.options.scanning.requireShift) { + if (textSource && this.options.scanning.modifier !== 'none') { this.popup.showOrphaned(textSource.getRect(), this.options); } } else { diff --git a/ext/fg/js/source-element.js b/ext/fg/js/source-element.js index 69fbc5ab..a8101382 100644 --- a/ext/fg/js/source-element.js +++ b/ext/fg/js/source-element.js @@ -18,41 +18,42 @@ class TextSourceElement { - constructor(element, length=-1) { + constructor(element, content='') { this.element = element; - this.length = length; + this.content = content; } clone() { - return new TextSourceElement(this.element, this.length); + return new TextSourceElement(this.element, this.content); } text() { - const text = this.textRaw(); - return this.length < 0 ? text : text.substring(0, this.length); + return this.content; } - textRaw() { + setEndOffset(length) { switch (this.element.nodeName) { case 'BUTTON': - return this.element.innerHTML; + this.content = this.element.innerHTML; + break; case 'IMG': - return this.element.getAttribute('alt'); + this.content = this.element.getAttribute('alt'); + break; default: - return this.element.value || ''; + this.content = this.element.value; + break; } + + this.content = this.content || ''; + this.content = this.content.substring(0, length); + + return this.content.length; } setStartOffset(length) { - // NOP return 0; } - setEndOffset(length) { - this.length = length; - return length; - } - containsPoint(point) { const rect = this.getRect(); return point.x >= rect.left && point.x <= rect.right; @@ -71,6 +72,6 @@ class TextSourceElement { } equals(other) { - return other.element && other.textRaw() === this.textRaw(); + return other.element === this.element && other.content === this.content; } } diff --git a/ext/fg/js/source-range.js b/ext/fg/js/source-range.js index 6d445f54..fa73b0a4 100644 --- a/ext/fg/js/source-range.js +++ b/ext/fg/js/source-range.js @@ -18,30 +18,31 @@ class TextSourceRange { - constructor(range) { - this.rng = range; + constructor(range, content='') { + this.range = range; + this.content = content; } clone() { - return new TextSourceRange(this.rng.cloneRange()); + return new TextSourceRange(this.range.cloneRange(), this.content); } text() { - return this.rng.toString(); + return this.content; } setEndOffset(length) { - const lengthAdj = length + this.rng.startOffset; - const state = TextSourceRange.seekForward(this.rng.startContainer, lengthAdj); - this.rng.setEnd(state.node, state.offset); - return length - state.length; + const state = TextSourceRange.seekForward(this.range.startContainer, this.range.startOffset, length); + this.range.setEnd(state.node, state.offset); + this.content = state.content; + return length - state.remainder; } setStartOffset(length) { - const lengthAdj = length + (this.rng.startContainer.length - this.rng.startOffset); - const state = TextSourceRange.seekBackward(this.rng.startContainer, lengthAdj); - this.rng.setStart(state.node, state.offset); - return length - state.length; + const state = TextSourceRange.seekBackward(this.range.startContainer, this.range.startOffset, length); + this.range.setStart(state.node, state.offset); + this.content = state.content; + return length - state.remainder; } containsPoint(point) { @@ -50,11 +51,11 @@ class TextSourceRange { } getRect() { - return this.rng.getBoundingClientRect(); + return this.range.getBoundingClientRect(); } getPaddedRect() { - const range = this.rng.cloneRange(); + const range = this.range.cloneRange(); const startOffset = range.startOffset; const endOffset = range.endOffset; const node = range.startContainer; @@ -68,7 +69,7 @@ class TextSourceRange { select() { const selection = window.getSelection(); selection.removeAllRanges(); - selection.addRange(this.rng); + selection.addRange(this.range); } deselect() { @@ -77,11 +78,30 @@ class TextSourceRange { } equals(other) { - return other.rng && other.rng.compareBoundaryPoints(Range.START_TO_START, this.rng) === 0; + return other.range && other.range.compareBoundaryPoints(Range.START_TO_START, this.range) === 0; } - static seekForward(node, length) { - const state = {node, length, offset: 0}; + static shouldEnter(node) { + if (node.nodeType !== 1) { + return false; + } + + const skip = ['RT', 'SCRIPT', 'STYLE']; + if (skip.includes(node.nodeName)) { + return false; + } + + const style = window.getComputedStyle(node); + const hidden = + style.visibility === 'hidden' || + style.display === 'none' || + parseFloat(style.fontSize) === 0; + + return !hidden; + } + + static seekForward(node, offset, length) { + const state = {node, offset, remainder: length, content: ''}; if (!TextSourceRange.seekForwardHelper(node, state)) { return state; } @@ -98,12 +118,15 @@ class TextSourceRange { } static seekForwardHelper(node, state) { - if (node.nodeType === 3) { - const consumed = Math.min(node.length, state.length); + if (node.nodeType === 3 && node.parentElement && TextSourceRange.shouldEnter(node.parentElement)) { + const offset = state.node === node ? state.offset : 0; + const remaining = node.length - offset; + const consumed = Math.min(remaining, state.remainder); + state.content = state.content + node.nodeValue.substring(offset, offset + consumed); state.node = node; - state.offset = consumed; - state.length -= consumed; - } else { + state.offset = offset + consumed; + state.remainder -= consumed; + } else if (TextSourceRange.shouldEnter(node)) { for (let i = 0; i < node.childNodes.length; ++i) { if (!TextSourceRange.seekForwardHelper(node.childNodes[i], state)) { break; @@ -111,11 +134,11 @@ class TextSourceRange { } } - return state.length > 0; + return state.remainder > 0; } - static seekBackward(node, length) { - const state = {node, length, offset: node.length}; + static seekBackward(node, offset, length) { + const state = {node, offset, remainder: length, content: ''}; if (!TextSourceRange.seekBackwardHelper(node, state)) { return state; } @@ -132,12 +155,15 @@ class TextSourceRange { } static seekBackwardHelper(node, state) { - if (node.nodeType === 3) { - const consumed = Math.min(node.length, state.length); + if (node.nodeType === 3 && node.parentElement && TextSourceRange.shouldEnter(node.parentElement)) { + const offset = state.node === node ? state.offset : node.length; + const remaining = offset; + const consumed = Math.min(remaining, state.remainder); + state.content = node.nodeValue.substring(offset - consumed, offset) + state.content; state.node = node; - state.offset = node.length - consumed; - state.length -= consumed; - } else { + state.offset = offset - consumed; + state.remainder -= consumed; + } else if (TextSourceRange.shouldEnter(node)) { for (let i = node.childNodes.length - 1; i >= 0; --i) { if (!TextSourceRange.seekBackwardHelper(node.childNodes[i], state)) { break; @@ -145,6 +171,6 @@ class TextSourceRange { } } - return state.length > 0; + return state.remainder > 0; } } diff --git a/ext/fg/js/util.js b/ext/fg/js/util.js index e5705ffd..c6270ce6 100644 --- a/ext/fg/js/util.js +++ b/ext/fg/js/util.js @@ -112,18 +112,12 @@ function docImposterDestroy() { } } -function docImposterHide() { - for (const element of document.getElementsByClassName('yomichan-imposter')) { - element.style.visibility = 'hidden'; - } -} - -function docRangeFromPoint(point, imposter) { +function docRangeFromPoint(point) { const element = document.elementFromPoint(point.x, point.y); if (element !== null) { if (element.nodeName === 'IMG' || element.nodeName === 'BUTTON') { return new TextSourceElement(element); - } else if (imposter && (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')) { + } else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { docImposterCreate(element); } } @@ -144,11 +138,9 @@ function docRangeFromPoint(point, imposter) { const range = document.caretRangeFromPoint(point.x, point.y); if (range !== null) { - docImposterHide(); return new TextSourceRange(range); } - docImposterDestroy(); return null; } @@ -168,6 +160,11 @@ function docSentenceExtract(source, extent) { for (let i = position; i >= startPos; --i) { const c = content[i]; + if (c === '\n') { + startPos = i + 1; + break; + } + if (quoteStack.length === 0 && (terminators.includes(c) || c in quotesFwd)) { startPos = i + 1; break; @@ -186,6 +183,11 @@ function docSentenceExtract(source, extent) { for (let i = position; i <= endPos; ++i) { const c = content[i]; + if (c === '\n') { + endPos = i + 1; + break; + } + if (quoteStack.length === 0) { if (terminators.includes(c)) { endPos = i + 1; |