Make Space Bar NOT flip card immediately

Hi everyone,

I’m aware this is a bit of a weird one - I’m curious if this could be done somehow, but if it can’t, no big deal either.
 

I have a note type that takes FEN notation for chess like so:

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR,
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR,
rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR

and turns it into a clickable sequence of chess positions:
Open Sicilian Anki

 

In addition to the mouse click, I’d like the template to cycle through the positions by clicking the space bar. The following works in the card editor, but obviously doesn’t work on the review screen. There, space just flips the card (as it should):

<script>
document.body.onkeyup = function(e) {
  if (e.key == " " || e.code == "Space" || e.keyCode == 32      )
    showNext(); 
}
</script>

 

Is there a way to achieve the following behavior:

"Space" // First FEN position
"Space" // Second FEN position
"Space" // Third FEN position
"Space" // Last FEN position
"Space" // Flip Card
"Space" // Rate Card Good

 
Thanks so much in advance!

2 Likes

I’m just gonna go ahead and say probably not. Looks like you have some advanced use case that Anki probably isn’t the best tool for. Alternatively, you could try some other character instead of space no?

@ODeer thanks for that great explanation of your use case!

Anki only flips to the back when no text input is focused. This hack makes use of this with a dummy input and some focus handling:

<script>
  (() => {
    /**
     * Anki script: delay answer on spacebar
     * @author Matthias Metelka | @kleinerpirat
     */

    const dummy = document.createElement("div");
    dummy.id = "dummyInput";
    dummy.contentEditable = true;
    document.getElementById("qa").appendChild(dummy);
    dummy.focus();

    /* count for demo condition */
    let count = 0;

    if (!globalThis.spaceListening) {
      document.addEventListener("click", () => dummy.focus());
      document.addEventListener("keydown", (e) => {
        dummy.blur();
        if (e.code == "Space") {
          /* replace this with your condition */
          if (count++ < 3) {
            dummy.focus();
            /* place your function call here - e.g. showNext(); */
            console.log("pressed space!");
          }
        } else {
          setTimeout(() => dummy.focus());
        }
      });
      globalThis.spaceListening = true;
    }
  })();
</script>

CSS

#dummyInput {
  caret-color: transparent;
}

If not Anki, what else? :smiley: Use cases like this are the sole reason I’m using Anki over more polished flashcard software. It’s basically a programmer’s playground :nerd_face:

7 Likes

Yeah you’re right. I didn’t have a solution so I just gave what I knew. But your method is a solution!

1 Like

That’s the sort of mad genius stuff I was hoping for!

I’ve changed the code to the following:

<script>
  (() => {
    /**
     * Anki script: delay answer on spacebar
     * @author Matthias Metelka | @kleinerpirat
     */

    const dummy = document.createElement("div");
    dummy.id = "dummyInput";
    dummy.contentEditable = true;
    document.getElementById("qa").appendChild(dummy);
    dummy.focus();

    /* Stuff I added - I'll change it to use the same counter as ShowNext() later
				but I want to find the error here first
				Side note: I want this more implicit - but for illustration
		*/
		source = document.getElementById("source");
		var source_arr = source.textContent.split(",");
		var no_of_steps = source_arr.length;

    /* count for demo condition */		
		let count = 0;

    if (!globalThis.spaceListening) {
      document.addEventListener("click", () => dummy.focus());
      document.addEventListener("keydown", (e) => {
        dummy.blur();
        if (e.code == "Space") {
          if (count++ < no_of_steps - 1) {
            dummy.focus();
            showNext();
          }
        } else {
          setTimeout(() => dummy.focus());
        }
      });
      globalThis.spaceListening = true;
    }
  })();
</script>

 

It works quite beautifully… but only for one card at a time. For the first card, it works exactly as I wanted:

Position1 - Position2 - ... - Last Position - Flip - RateGood

But for the next cards, the focus stays on the dummy, and enters the spaces there - but doesn’t trigger the script nor flips the card - clicking still works, so it’s not an issue within ShowNext().

A gif to illustrate:

Ruy Lopez Anki

 
Any idea what’s happening? As you may notice, web dev isn’t really my strong suit - I’ve only ever dabbled with it for Anki.

Merce bis hierher!