Issue with keyup Event Handler Being Called Multiple Times in Anki Flashcards

Hello,

I’m working on a custom script for Anki flashcards that involves using hotkeys to reveal parts of a card. The script listens for keyup events and reveals the next cloze deletion or all cloze deletions on the card, depending on which key is pressed. However, I’m encountering an issue where, after using the hotkeys for a while during the same study session, as I progress through the deck, the event handler starts being called multiple times for a single key press, leading to unexpected behavior.

Script Summary:

The script uses document.addEventListener('keyup', function(e) {...}) to listen for key presses. When a specific key (e.g., ‘.’) is pressed, it should reveal the next cloze deletion. Another key (e.g., ‘+’) reveals all cloze deletions. Initially, the script works as expected, but after some time or after several cards, a single press of the hotkey triggers the event handler multiple times.

What I’ve Tried:

  1. Ensuring the event listener is added only once using a flag.
  2. Implementing debouncing and throttling within the event handler.
  3. Manually resetting the event listener before adding it again.

Despite these efforts, the problem persists, seemingly becoming more pronounced the further I get into the deck.

Question:

How can I prevent the keyup event handler from being triggered multiple times after a single key press, especially as I continue to review more cards during a single study session in Anki? Is there something specific about the Anki environment that I should account for, or is there a more effective way to manage event listeners in this context?

Any insights or suggestions would be greatly appreciated. Below is a simplified version of my code for reference:

var hotkey = '.';
var revealAllKey = '+';
var lastHotkeyPress = 0;
const debounceTime = 1000; // 1000ms = 1 second debounce time

document.addEventListener('keyup', function(e) {
    var currentTime = Date.now();
        if (currentTime - lastHotkeyPress < debounceTime) {
            return; // Too soon since the last execution, so we skip this event
        }
    if (e.key === hotkey) {
        // Logic to reveal next cloze
        console.log("Next cloze revealed.");
    } else if (e.key === revealAllKey) {
        // Logic to reveal all clozes
        console.log("All clozes revealed.");
    }
});

Thank you in advance for your help!

I’d expect these workarounds to work but since you’ve not shown the relevant code, I’ll give a simple working solution.

Anki uses the same webview throughout the review session so you need to ensure you’re not running document.addEventListener() unconditionally in template code.
The simplest solution is assigning a flag to the global object (window / globalThis) and checking for its existence to avoid registering it multiple times.

Example:


if(!globalThis.myKeyupHandler) {
    document.addEventListener("keyup", handler);
    globalThis.myKeyupHandler = handler;
}

I recommend writing a helper function like in this example if you have many events to handle:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.