Setting your cards so that the audio plays if you click anywhere

Hello!

I have a deck of cards consisting entirely of images (it displays one image on the front, and then the back just has another image that is the same size with the answer), and I would like to set it so that it auto-plays an audio file when you show the back, and then if you want to play the audio again, instead of there being a button, you can just click anywhere on the card to replay it.

My HTML/CSS ability is lower intermediate, and I’ve been able to figure out how to style the replay button, but I can’t figure out how to get rid of the button and just make the entire card clickable instead. Is there a way to do this?

You can add a onclick="..." attribute to the img tag, and replace ... with javascript code that triggers the audio play.

1 Like

Thank you! I’ve done very little with javascript, so I don’t know what code to put there.

Well, how did you make your previous button work?

I was able to style the .replay-button in CSS, so I could change the size and colors, even replace it with “:loud_sound:”, without using any javascript. But I haven’t been able to figure out how to get rid of the button entirely and still have a way to click and play the audio.

image

As you can see, Anki’s audio buttons call the function pycmd, which sends a message to the Python side of things (wouldn’t call it backend, but something in-between).

The message consists of three parts: play:context:str_index

  • play: Tells Anki which arguments to expect and which function to call when it receives the message. You can see here how Anki reacts to the command within reviewer.py:
  • context: either q (question) or a (answer)
  • str_index: position of the sound file inside the card

Long story short, all you need to do is send a pycmd to tell Anki which soundfile to play, like this:

<img onclick="pycmd('play:a:0')">

or attach an EventListener to the whole document:

<script>
  if (!globalThis.soundClickListening) {
    document.addEventListener("click", () => pycmd("play:a:0"));
    globalThis.soundClickListening = true;
  }
</script>
4 Likes

Here’s a more general script for anyone using more than one sound:

<script>
  (function cycleSounds() {
    let index = 0;

    const cmds = Array.from(document.querySelectorAll(".soundLink"), (el) =>
      el.getAttribute("onclick").replace(/return.*$/, "")
    );

    if (!globalThis.soundClickListening) {
      document.addEventListener("click", () =>
        eval(cmds[index++ % cmds.length])
      );
      globalThis.soundClickListening = true;
    }
  })();
</script>
2 Likes

Disclaimer: this is desktop-specific code, and may break at any time as it is not a public API.

2 Likes

Thank you so much! This worked perfectly for me!