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