Adding prefix as (A) (B) (C) (D) each fixed position with randomized Javascript code


<div class="shuffle">{{Opt1}}</div>
<div class="shuffle">{{Opt2}}</div>
<div class="shuffle">{{Opt3}}</div>
<div class="shuffle">{{Opt4}}</div>
<div id="container"></div>

<script>
    // https://stackoverflow.com/a/12646864
    function shuffleArray(array) {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
    }

    setTimeout(() => {
        const fields = [...document.querySelectorAll(".shuffle")];
        shuffleArray(fields);
        fields.forEach((fld) => document.getElementById("container").appendChild(fld));
},0);
</script>```

https://ankiweb.net/shared/info/1050625176

1 Like

It’s the best, but I really need to formulate the above code as it becomes easier for my case. Thanks.

In the loop where the shuffled options are re-added to the container you can also modify their textContent. I assume your remplate already has a way to communicate the shuffled order to the card back?

fields.forEach((fld, index) = {
  // Add (a), (b), (c) or (d) to the option content
  const prefix = String.fromCharCode(97 + index);
  fld.textContent =  prefix + ") " + fld.textContent;
  document.getElementById("container").appendChild(fld);
})

Editing innerHTML instead would let you add styling to the prefix, if you like. If the content within the Opt1, Opt2 etc fields has html, then this approach is better though also more likely to break stuff.

fields.forEach((fld, index) = {
  // Add (a), (b), (c) or (d) to the option content
  const prefix = String.fromCharCode(97 + index);
  fld.innerHTML =  `<span class="option-prefix">${prefix})</span> ${fld.innerHTML}`;
  document.getElementById("container").appendChild(fld);
})

And then add some css targeting the option-prefix classs in the card styling.


<div class="shuffle">{{Opt1}}</div>
<div class="shuffle">{{Opt2}}</div>
<div class="shuffle">{{Opt3}}</div>
<div class="shuffle">{{Opt4}}</div>
<div id="container"></div>

<script>
    // https://stackoverflow.com/a/12646864
    function shuffleArray(array) {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
    }

    setTimeout(() => {
        const fields = [...document.querySelectorAll(".shuffle")];
        shuffleArray(fields);
        fields.forEach((fld, index) = { // Add (a), (b), (c) or (d) to the option content const prefix = String.fromCharCode(97 + index); fld.textContent = prefix + ") " + fld.textContent; document.getElementById("container").appendChild(fld));
    }, 0);
</script>```[quote="jhhr, post:4, topic:46274, full:true"]
In the loop where the shuffled options are re-added to the container you can also modify their `textContent`. I assume your remplate already has a way to communicate the shuffled order to the card back?

fields.forEach((fld, index) = {
// Add (a), (b), (c) or (d) to the option content
const prefix = String.fromCharCode(97 + index);
fld.textContent = prefix + ") " + fld.textContent;
document.getElementById(“container”).appendChild(fld);
})


[/quote]

I tried too much though it breaks the shuffling too and gives original output without randomization.
![Screenshot_2024-06-22-01-39-37-157_com.ichi2.anki|312x500]

Is the code you posted above what you tried in your template? The entire part inside the loop is commented out because the linebreaks were apparently turned into spaces. I imagine this is easy to miss when looking at the code in the Anki editor where there’s no syntax highlighting.

You have:

// Add (a), (b), (c) or (d) to the option content const prefix = String.fromCharCode(97 + index); fld.textContent = prefix + ") " + fld.textContent; document.getElementById("container").appendChild(fld));

Should be:

// Add (a), (b), (c) or (d) to the option content
const prefix = String.fromCharCode(97 + index);
fld.textContent = prefix + ") " + fld.textContent;
document.getElementById("container").appendChild(fld));

Thank you so much sir, Finally succeeded.

1 Like

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