From 72f6b936fcce2eb5f2b54cc6dfdd274690aa0b5b Mon Sep 17 00:00:00 2001 From: iamllama <100429699+iamllama@users.noreply.github.com> Date: Wed, 4 Dec 2024 05:44:10 +0800 Subject: [PATCH] Replace findText with a js impl, remove blink --- generate_grid.py | 48 +++++++++++++++++++++++++++++------------------- webview_util.py | 15 ++++----------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/generate_grid.py b/generate_grid.py index e82142c..d7f9d9f 100644 --- a/generate_grid.py +++ b/generate_grid.py @@ -45,8 +45,8 @@ def kanjitile(char, bgcolor, count = 0, avg_interval = 0): if config.onclickaction == "copy": result_html += "" if not export: - result_html += f"" - result_html += f"" + result_html += f"" + result_html += f"" result_html += "\n" result_html += "\n" result_html += "
Kanji Grid - %s
\n" % deckname @@ -224,32 +224,42 @@ def kanjigrid(mw, config): util.addUnitData(units, ch, i, card, config.kanjionly) return units -SEARCH_BLINK_CSS_SNIPPET = """ -.blink { - animation: blink 0.2s ease-in-out; - animation-iteration-count: 3; -} - -@keyframes blink { - 0% { opacity: 1; } - 50% { opacity: 0; } - 100% { opacity: 1; } +SEARCH_CSS_SNIPPET = """ +a.highlight { + background: black; + color: white !important; } """.strip() -SEARCH_BLINK_JS_SNIPPET = """ -function blinkChar(char) { +SEARCH_JS_SNIPPET = """ +function findChar(char) { + /* for styling the match */ + const HIGHLIGHT_CLASS = "highlight" + + /* clear the previous match's highlight (if any) */ + const prevMatchingElem = document.querySelector(`.${HIGHLIGHT_CLASS}`); + if (prevMatchingElem !== null) + prevMatchingElem.classList.remove(HIGHLIGHT_CLASS); + /* https://stackoverflow.com/questions/3813294/how-to-get-element-by-innertext */ const xpath = "//a[text()='" + char + "']"; + /* this only considers the first matching element, so it assumes the grid kanji are unique */ const matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if (matchingElement === null) return false; - matchingElement.classList.add("blink"); - /* cleanup anim class */ - matchingElement.addEventListener("animationend", function() { - matchingElement.classList.remove("blink"); - }, { once: true }); + + /* we need to open the enclosing
block first (if any), or scrollIntoView won't work */ + let parentDetailsElem = matchingElement.closest('details'); + if (parentDetailsElem !== null) + parentDetailsElem.open = true; + + matchingElement.classList.add(HIGHLIGHT_CLASS); + + /* scroll to match */ + matchingElement.scrollIntoView({ behavior: "smooth", block: "center" }); + + /* ret value indicates whether a match was found */ return true; } """.strip() diff --git a/webview_util.py b/webview_util.py index 105f551..903e476 100644 --- a/webview_util.py +++ b/webview_util.py @@ -43,18 +43,11 @@ def on_find_cmd(wv: AnkiWebView): return def findTextCallback(found): - if found: - # doesn't seem to be a way to style the text highlighting - # and it be hard to spot, so make the target blink - wv.eval(f"blinkChar('{char}');") - else: - tooltip(f"\"{char}\" not found in grid.") + if not found: + tooltip(f"\"{char}\" not found in grid.") - # qt handles scrolling to, scrollbar indicator and opening the
block - # there's an issue with findText where it sometimes doesn't scroll up when the kanji is found upwards/backwards - # calling findText twice, although hacky, makes it reliably scroll up - wv.findText(char) - wv.findText(char, resultCallback=findTextCallback) + # qt's findText impl is bugged and inconvenient, so we use our own + wv.evalWithCallback(f"findChar('{char}');", findTextCallback) def add_webview_context_menu_items(wv, expected_wv, menu, config, deckname, char): # hook is active while kanjigrid is open, and right clicking on the main window (deck list) will also trigger this, so check wv