From a39a1fa9e4700d1189dfc5073b5fcb2557965671 Mon Sep 17 00:00:00 2001 From: toasted-nutbread <toasted-nutbread@users.noreply.github.com> Date: Thu, 22 Aug 2019 19:44:31 -0400 Subject: Add support for Edge browser --- ext/mixed/js/extension.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 ext/mixed/js/extension.js (limited to 'ext/mixed') diff --git a/ext/mixed/js/extension.js b/ext/mixed/js/extension.js new file mode 100644 index 00000000..d7085e5b --- /dev/null +++ b/ext/mixed/js/extension.js @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +function toIterable(value) { + if (typeof Symbol !== 'undefined' && typeof value[Symbol.iterator] !== 'undefined') { + return value; + } + + const array = JSON.parse(JSON.stringify(value)); + return Array.isArray(array) ? array : []; +} + +function extensionHasChrome() { + try { + return typeof chrome === 'object' && chrome !== null; + } catch (e) { + return false; + } +} + +function extensionHasBrowser() { + try { + return typeof browser === 'object' && browser !== null; + } catch (e) { + return false; + } +} + +const EXTENSION_IS_BROWSER_EDGE = ( + extensionHasBrowser() && + (!extensionHasChrome() || (typeof chrome.runtime === 'undefined' && typeof browser.runtime !== 'undefined')) +); + +if (EXTENSION_IS_BROWSER_EDGE) { + // Edge does not have chrome defined. + chrome = browser; +} -- cgit v1.2.3 From ad0dca7bb12d13545b559e9c738fcc0767ba20d5 Mon Sep 17 00:00:00 2001 From: toasted-nutbread <toasted-nutbread@users.noreply.github.com> Date: Sat, 31 Aug 2019 14:57:24 -0400 Subject: Make the imposter element tracked using TextSourceRange --- ext/fg/js/document.js | 22 +++++++++++----------- ext/fg/js/frontend.js | 6 +++--- ext/fg/js/source.js | 15 +++++++++++++-- ext/mixed/js/display.js | 20 +++++++++++++------- 4 files changed, 40 insertions(+), 23 deletions(-) (limited to 'ext/mixed') 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,16 +84,22 @@ 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); - textSource.setEndOffset(length); + ({definitions, length} = await apiTermsFind(textSource.text())); + if (definitions.length === 0) { + return false; + } - const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + textSource.setEndOffset(length); + + sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + } finally { + textSource.cleanup(); + } const context = { source: { -- cgit v1.2.3 From 171e3f1097a86b993ba1e16c07c4ad6d5bff75ee Mon Sep 17 00:00:00 2001 From: toasted-nutbread <toasted-nutbread@users.noreply.github.com> Date: Sat, 31 Aug 2019 22:12:21 -0400 Subject: Add option for enabling deep scanning --- ext/bg/js/options.js | 3 ++- ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 4 ++++ ext/fg/js/document.js | 4 ++-- ext/fg/js/frontend.js | 2 +- ext/mixed/js/display.js | 2 +- 6 files changed, 12 insertions(+), 5 deletions(-) (limited to 'ext/mixed') diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index c76525b9..7d993987 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -218,7 +218,8 @@ function optionsSetDefaults(options) { autoHideResults: false, delay: 20, length: 10, - modifier: 'shift' + modifier: 'shift', + deepDomScan: false }, dictionaries: {}, diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index c4eb4842..f5d669b2 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -47,6 +47,7 @@ async function formRead() { optionsNew.scanning.selectText = $('#select-matched-text').prop('checked'); optionsNew.scanning.alphanumeric = $('#search-alphanumeric').prop('checked'); optionsNew.scanning.autoHideResults = $('#auto-hide-results').prop('checked'); + optionsNew.scanning.deepDomScan = $('#deep-dom-scan').prop('checked'); optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10); optionsNew.scanning.length = parseInt($('#scan-length').val(), 10); optionsNew.scanning.modifier = $('#scan-modifier-key').val(); @@ -187,6 +188,7 @@ async function onReady() { $('#select-matched-text').prop('checked', options.scanning.selectText); $('#search-alphanumeric').prop('checked', options.scanning.alphanumeric); $('#auto-hide-results').prop('checked', options.scanning.autoHideResults); + $('#deep-dom-scan').prop('checked', options.scanning.deepDomScan); $('#scan-delay').val(options.scanning.delay); $('#scan-length').val(options.scanning.length); $('#scan-modifier-key').val(options.scanning.modifier); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 778dcee0..cc140023 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -192,6 +192,10 @@ <label><input type="checkbox" id="auto-hide-results"> Automatically hide results</label> </div> + <div class="checkbox options-advanced"> + <label><input type="checkbox" id="deep-dom-scan"> Deep DOM scan</label> + </div> + <div class="form-group options-advanced"> <label for="scan-delay">Scan delay (in milliseconds)</label> <input type="number" min="1" id="scan-delay" class="form-control"> diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js index 8bb857e7..727bc5d2 100644 --- a/ext/fg/js/document.js +++ b/ext/fg/js/document.js @@ -89,7 +89,7 @@ function docImposterCreate(element, isTextarea) { return [imposter, container]; } -function docRangeFromPoint({x, y}) { +function docRangeFromPoint({x, y}, options) { const elements = document.elementsFromPoint(x, y); let imposter = null; let imposterContainer = null; @@ -108,7 +108,7 @@ function docRangeFromPoint({x, y}) { } } - const range = caretRangeFromPointExt(x, y, elements); + const range = caretRangeFromPointExt(x, y, options.scanning.deepDomScan ? elements : []); if (range !== null) { if (imposter !== null) { docSetImposterStyle(imposterContainer.style, 'z-index', '-2147483646'); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 5a8d18c1..8a5c48d0 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -285,7 +285,7 @@ class Frontend { return; } - const textSource = docRangeFromPoint(point); + const textSource = docRangeFromPoint(point, this.options); let hideResults = !textSource || !textSource.containsPoint(point); let searched = false; let success = false; diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 4620e198..ebf56897 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -80,7 +80,7 @@ class Display { const {docRangeFromPoint, docSentenceExtract} = this.dependencies; const clickedElement = $(e.target); - const textSource = docRangeFromPoint({x: e.clientX, y: e.clientY}); + const textSource = docRangeFromPoint({x: e.clientX, y: e.clientY}, this.options); if (textSource === null) { return false; } -- cgit v1.2.3