From 1a9348ec27b903af47511da11306f884a82cf353 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 17 Aug 2019 19:32:58 -0400 Subject: Add option for maximum nested popup depth --- ext/bg/js/settings.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ext/bg/js/settings.js') diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index f5d669b2..de1616f3 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -51,6 +51,7 @@ async function formRead() { optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10); optionsNew.scanning.length = parseInt($('#scan-length').val(), 10); optionsNew.scanning.modifier = $('#scan-modifier-key').val(); + optionsNew.scanning.popupNestingMaxDepth = parseInt($('#popup-nesting-max-depth').val(), 10); optionsNew.anki.enable = $('#anki-enable').prop('checked'); optionsNew.anki.tags = $('#card-tags').val().split(/[,; ]+/); @@ -192,6 +193,7 @@ async function onReady() { $('#scan-delay').val(options.scanning.delay); $('#scan-length').val(options.scanning.length); $('#scan-modifier-key').val(options.scanning.modifier); + $('#popup-nesting-max-depth').val(options.scanning.popupNestingMaxDepth); $('#dict-purge-link').click(utilAsync(onDictionaryPurge)); $('#dict-file').change(utilAsync(onDictionaryImport)); -- cgit v1.2.3 From 42ec3e2a43dfd9ac0748ca7c364cef2b44f625a2 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 18 Aug 2019 16:48:18 -0400 Subject: Add support for popup on the search page --- ext/bg/js/options.js | 3 ++- ext/bg/js/search-frontend.js | 51 ++++++++++++++++++++++++++++++++++++++++++++ ext/bg/js/settings.js | 2 ++ ext/bg/search.html | 1 + ext/bg/settings.html | 4 ++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 ext/bg/js/search-frontend.js (limited to 'ext/bg/js/settings.js') diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 2197c72c..1b2d5e1a 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -220,7 +220,8 @@ function optionsSetDefaults(options) { length: 10, modifier: 'shift', deepDomScan: false, - popupNestingMaxDepth: 0 + popupNestingMaxDepth: 0, + enableOnSearchPage: true }, dictionaries: {}, diff --git a/ext/bg/js/search-frontend.js b/ext/bg/js/search-frontend.js new file mode 100644 index 00000000..77aa4052 --- /dev/null +++ b/ext/bg/js/search-frontend.js @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 Alex Yatskov + * Author: Alex Yatskov + * + * 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 . + */ + + +async function searchFrontendSetup() { + const options = await apiOptionsGet(); + if (!options.scanning.enableOnSearchPage) { return; } + + const scriptSrcs = [ + '/fg/js/api.js', + '/fg/js/frontend-api-receiver.js', + '/fg/js/popup.js', + '/fg/js/popup-proxy-host.js', + '/fg/js/util.js', + '/fg/js/frontend.js' + ]; + for (const src of scriptSrcs) { + const script = document.createElement('script'); + script.async = false; + script.src = src; + document.body.appendChild(script); + } + + const styleSrcs = [ + '/fg/css/client.css' + ]; + for (const src of styleSrcs) { + const style = document.createElement('link'); + style.rel = 'stylesheet'; + style.type = 'text/css'; + style.href = src; + document.head.appendChild(style); + } +} + +searchFrontendSetup(); diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index de1616f3..5472c7bd 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -48,6 +48,7 @@ async function formRead() { 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.enableOnSearchPage = $('#enable-scanning-on-search-page').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(); @@ -190,6 +191,7 @@ async function onReady() { $('#search-alphanumeric').prop('checked', options.scanning.alphanumeric); $('#auto-hide-results').prop('checked', options.scanning.autoHideResults); $('#deep-dom-scan').prop('checked', options.scanning.deepDomScan); + $('#enable-scanning-on-search-page').prop('checked', options.scanning.enableOnSearchPage); $('#scan-delay').val(options.scanning.delay); $('#scan-length').val(options.scanning.length); $('#scan-modifier-key').val(options.scanning.modifier); diff --git a/ext/bg/search.html b/ext/bg/search.html index 05c0daab..38c5a4e9 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -51,5 +51,6 @@ + diff --git a/ext/bg/settings.html b/ext/bg/settings.html index a0d08ec5..0005efa6 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -192,6 +192,10 @@ +
+ +
+
-- cgit v1.2.3 From 71471d08e56f1a2431e67d0439724cc52a1ea73e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 25 Aug 2019 21:13:17 -0400 Subject: Add option to enable/disable scanning of source expressions in popups --- ext/bg/js/options.js | 1 + ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 4 +++ ext/fg/js/frontend.js | 86 +++++++++++++++++++++++++++++++++++++++++++---- ext/fg/js/popup-nested.js | 4 ++- 5 files changed, 89 insertions(+), 8 deletions(-) (limited to 'ext/bg/js/settings.js') diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 1b2d5e1a..df95aae9 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -221,6 +221,7 @@ function optionsSetDefaults(options) { modifier: 'shift', deepDomScan: false, popupNestingMaxDepth: 0, + enableOnPopupExpressions: false, enableOnSearchPage: true }, diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 5472c7bd..83f4528c 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -48,6 +48,7 @@ async function formRead() { 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.enableOnPopupExpressions = $('#enable-scanning-of-popup-expressions').prop('checked'); optionsNew.scanning.enableOnSearchPage = $('#enable-scanning-on-search-page').prop('checked'); optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10); optionsNew.scanning.length = parseInt($('#scan-length').val(), 10); @@ -191,6 +192,7 @@ async function onReady() { $('#search-alphanumeric').prop('checked', options.scanning.alphanumeric); $('#auto-hide-results').prop('checked', options.scanning.autoHideResults); $('#deep-dom-scan').prop('checked', options.scanning.deepDomScan); + $('#enable-scanning-of-popup-expressions').prop('checked', options.scanning.enableOnPopupExpressions); $('#enable-scanning-on-search-page').prop('checked', options.scanning.enableOnSearchPage); $('#scan-delay').val(options.scanning.delay); $('#scan-length').val(options.scanning.length); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 0005efa6..85b7ee5f 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -192,6 +192,10 @@ +
+ +
+
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 3605dffd..f59ea318 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -18,7 +18,7 @@ class Frontend { - constructor(popup) { + constructor(popup, ignoreNodes) { this.popup = popup; this.popupTimer = null; this.mouseDownLeft = false; @@ -26,6 +26,7 @@ class Frontend { this.textSourceLast = null; this.pendingLookup = false; this.options = null; + this.ignoreNodes = (Array.isArray(ignoreNodes) && ignoreNodes.length > 0 ? ignoreNodes.join(',') : null); this.primaryTouchIdentifier = null; this.contextMenuChecking = false; @@ -39,10 +40,10 @@ class Frontend { static create() { const initializationData = window.frontendInitializationData; const isNested = (initializationData !== null && typeof initializationData === 'object'); - const {id, parentFrameId} = initializationData || {}; + const {id, parentFrameId, ignoreNodes} = isNested ? initializationData : {}; const popup = isNested ? new PopupProxy(id, parentFrameId) : PopupProxyHost.instance.createPopup(null); - const frontend = new Frontend(popup); + const frontend = new Frontend(popup, ignoreNodes); frontend.prepare(); return frontend; } @@ -337,9 +338,14 @@ class Frontend { } async searchTerms(textSource, focus) { - textSource.setEndOffset(this.options.scanning.length); + this.setTextSourceScanLength(textSource, this.options.scanning.length); - const {definitions, length} = await apiTermsFind(textSource.text()); + const searchText = textSource.text(); + if (searchText.length === 0) { + return; + } + + const {definitions, length} = await apiTermsFind(searchText); if (definitions.length === 0) { return false; } @@ -365,9 +371,14 @@ class Frontend { } async searchKanji(textSource, focus) { - textSource.setEndOffset(1); + this.setTextSourceScanLength(textSource, 1); - const definitions = await apiKanjiFind(textSource.text()); + const searchText = textSource.text(); + if (searchText.length === 0) { + return; + } + + const definitions = await apiKanjiFind(searchText); if (definitions.length === 0) { return false; } @@ -493,6 +504,67 @@ class Frontend { } return false; } + + setTextSourceScanLength(textSource, length) { + textSource.setEndOffset(length); + if (this.ignoreNodes === null || !textSource.range) { + return; + } + + length = textSource.text().length; + while (textSource.range && length > 0) { + const nodes = Frontend.getNodesInRange(textSource.range); + if (Frontend.isValidScanningNodeList(nodes, this.ignoreNodes)) { + break; + } + --length; + textSource.setEndOffset(length); + } + } + + static getNodesInRange(range) { + const end = range.endContainer; + const nodes = []; + for (let node = range.startContainer; node !== null; node = Frontend.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 (node === null) { break; } + + node = next; + } + } + return next; + } + + static isValidScanningNodeList(nodeList, selector) { + for (const node of nodeList) { + if (!Frontend.isValidScanningNode(node, selector)) { + return false; + } + } + return true; + } + + static isValidScanningNode(node, selector) { + for (; node !== null; node = node.parentNode) { + if (node.nodeType === Node.ELEMENT_NODE) { + return !node.matches(selector); + } + } + return true; + } } window.yomichan_frontend = Frontend.create(); diff --git a/ext/fg/js/popup-nested.js b/ext/fg/js/popup-nested.js index ad235cc6..e0376bb2 100644 --- a/ext/fg/js/popup-nested.js +++ b/ext/fg/js/popup-nested.js @@ -32,7 +32,9 @@ async function popupNestedInitialize(id, depth, parentFrameId) { return; } - window.frontendInitializationData = {id, depth, parentFrameId}; + const ignoreNodes = options.scanning.enableOnPopupExpressions ? [] : [ '.expression', '.expression *' ]; + + window.frontendInitializationData = {id, depth, parentFrameId, ignoreNodes}; const scriptSrcs = [ '/fg/js/frontend-api-sender.js', -- cgit v1.2.3