How to put a random field inside a div with a script?

Hello.
I have 5 fields with different sentences called Sentece1, Sentece2, Sentece3, Sentece4 and Sentece5.

I need to write a script that displays only one random field inside the div with id="sentence" based on the randomly generated number (from 1 to 5).

<div id="sentence"></div>

Neither of these scripts works:

<script>
	number = 2; //some random number
	sentence = `{{Sentence${number}}}`;
	document.getElementById('sentence').innerHTML = sentence;
</script>
<script>
	number = 2; //some random number
	sentence = '{{Sentence' + number + '}}';
	document.getElementById('sentence').innerHTML = sentence;
</script>

How to fix it? Am I doing something wrong?

I reckon the problem with your script is that Anki tries to replace the expression in brackets with a field value before the javascript is run. Thus, the field doesn’t exist (yet). But I’m still new to js and very hazy on the internals of Anki as well, so there may well be a better solution.

I don’t see any reason why the following shouldn’t work for you, but I’d be interested in using a more elegant solution myself as well.

<div class="sentence" hidden>{{Sentence1}}</div>
<div class="sentence" hidden>{{Sentence2}}</div>
<div class="sentence" hidden>{{Sentence3}}</div>

<script>

	const fields = [...document.querySelectorAll(".sentence")];

	function randomInt(max) {
		return Math.floor(Math.random() * max);
	}		
	rand = randomInt(fields.length)

	fields[rand].hidden = false;

</script>

 

Do you need to show the same random sentence on both sides of the card? It’s possible but obviously less straightforward than the code above.

3 Likes

Thanks. But for some reason, I can’t make your script to run on the back of the card. None of the hidden fields are being revealed with any number I try to use. Your script works only on the front side of the card but not on the back. Does it work for you on both sides?

At first glance I don’t know why it wouldn’t, I can have a look tomorrow.

In the meantime, it could help if you posted your complete html for front and back. Maybe something else is causing the issue.

1 Like

The code for the front and back sides are absolutely the same:

{{type:Word}}
{{Definition}}

<br><br>

<div class="sentence" hidden>{{Sentence1}}</div>
<div class="sentence" hidden>{{Sentence2}}</div>
<div class="sentence" hidden>{{Sentence3}}</div>
<div class="sentence" hidden>{{Sentence4}}</div>
<div class="sentence" hidden>{{Sentence5}}</div>

<script>
	const fields = document.querySelectorAll(".sentence");
	fields[3].hidden = false;
</script>

In this case, Sentence4 is being revealed on the front but not on the back.

You see, it’s because I’m a bit of plank. Wrap your script in curly brackets, then it should reload every time.

1 Like

Thanks a lot. It helped. But why do we need to use curly braces there?

Unfortunately, this is key… but if I find out I’ll let you know. I have a hunch, but I don’t want to spread misinformation.

I see @kleinerpirat has been lurking. Maybe has a better technical explanation^^

The issue is the const keyword. Because the document persists between cards, using const outside of functions (outermost scope) causes a SyntaxError.

Use the keyword var instead or enclose the script in an IIFE, like:

(() => {
  const fields = document.querySelectorAll(".sentence");
  fields[3].hidden = false;
})();
4 Likes

Right into my “HTF does JS work” deck it goes.

1 Like

Thanks a lot!

Just wondering if you got this to work and what it actually looks like on your flashcard. I think this is a great idea. You can have the flashcard display a random sentence every time you see it? That’s great.

Yes.
Everything works great. The cards look like this:

https://youtu.be/6LRGZHowZsI

That’s awesome. Your cards look great! I have a system that’s a bit different but I like your ideas. I explain how my flashcards work on this page:

https://ankimaster.com/the-ankimaster-system-how-to-study-your-cards/

What I describe there I believe is the optimal way to study Anki flashcards for learning languages.

2 Likes