diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js index a017a0a6..e6a16bd5 100644 --- a/ext/fg/js/document.js +++ b/ext/fg/js/document.js @@ -70,12 +70,6 @@ function docImposterCreate(element) { return imposter; } -function docImposterDestroy() { - for (const element of document.getElementsByClassName('yomichan-imposter')) { - element.parentNode.removeChild(element); - } -} - function docRangeFromPoint(point) { const element = document.elementFromPoint(point.x, point.y); let imposter = null; @@ -92,12 +86,18 @@ function docRangeFromPoint(point) { } const range = document.caretRangeFromPoint(point.x, point.y); - if (imposter !== null) { - imposter.style.zIndex = -2147483646; - imposter.style.pointerEvents = 'none'; + if (range !== null && isPointInRange(point, range)) { + if (imposter !== null) { + imposter.style.zIndex = -2147483646; + imposter.style.pointerEvents = 'none'; + } + return new TextSourceRange(range, '', imposter); + } else { + if (imposter !== null) { + imposter.parentNode.removeChild(imposter); + } + return null; } - - return range !== null && isPointInRange(point, range) ? new TextSourceRange(range) : null; } function docSentenceExtract(source, extent) { diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 3c5f2ac8..ebff768e 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -307,10 +307,11 @@ class Frontend { this.onError(e); } } finally { + if (textSource !== null) { + textSource.cleanup(); + } if (hideResults && this.options.scanning.autoHideResults) { this.searchClear(); - } else { - docImposterDestroy(); } this.pendingLookup = false; @@ -371,7 +372,6 @@ class Frontend { } searchClear() { - docImposterDestroy(); this.popup.hide(); this.popup.clearAutoPlayTimer(); diff --git a/ext/fg/js/source.js b/ext/fg/js/source.js index a360b331..409e81aa 100644 --- a/ext/fg/js/source.js +++ b/ext/fg/js/source.js @@ -25,13 +25,20 @@ const IGNORE_TEXT_PATTERN = /\u200c/; */ class TextSourceRange { - constructor(range, content='') { + constructor(range, content, imposter) { this.range = range; this.content = content; + this.imposter = imposter; } clone() { - return new TextSourceRange(this.range.cloneRange(), this.content); + return new TextSourceRange(this.range.cloneRange(), this.content, this.imposter); + } + + cleanup() { + if (this.imposter !== null && this.imposter.parentNode !== null) { + this.imposter.parentNode.removeChild(this.imposter); + } } text() { @@ -221,6 +228,10 @@ class TextSourceElement { return new TextSourceElement(this.element, this.content); } + cleanup() { + // NOP + } + text() { return this.content; } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index a2707bd0..4620e198 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -84,17 +84,23 @@ class Display { if (textSource === null) { return false; } - textSource.setEndOffset(this.options.scanning.length); - const {definitions, length} = await apiTermsFind(textSource.text()); - if (definitions.length === 0) { - return false; + let definitions, length, sentence; + try { + textSource.setEndOffset(this.options.scanning.length); + + ({definitions, length} = await apiTermsFind(textSource.text())); + if (definitions.length === 0) { + return false; + } + + textSource.setEndOffset(length); + + sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + } finally { + textSource.cleanup(); } - textSource.setEndOffset(length); - - const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); - const context = { source: { definitions: this.definitions,