(Solved) Specific answer boxes for each cloze region (type-in answer)

Perhaps you have seen many exercises like this, and there seems to be no feasible way to create flashcards other than using the type-in answer format. The default type-in answer format of Anki has a weakness in that when the answers are written as a long text string, users find it difficult to remember which answers have been entered and it is very difficult to edit them (especially for exercises that contain about 50 - 60 words on various tenses).

I have created a draft with the function of replacing cloze regions with input fields, and the data entered will be passed to the original input fields. At this point, the original input fields will serve as a reference for users to know which answers they have entered.

The front:

The back:

It seems to be working well, just missing a few functions such as decoration, improving answers, adjust the size of type boxes and adding spacing between answers, right?I haven’t completed those functions yet because there is still a bigger issue. The issue seems to be that your code only works on 1st card, and when you switch to 2nd card (whilel reviewing), the Javascript code disappears. Interestingly, this issue only occurs on Windows, while it works normally on AnkiDroid.

I truly do not know what caused this error, but I think that if it can be fixed, this template will be a new way to build decks with complex answers (or if someone has already made this template, please let me know where I went wrong). Please let me know your thoughts!

-------------------------------------- Link and codes ----------------------------------------

My two notes for example: type in answer.apkg - Google Drive

Front card:

{{cloze:Question}}
{{type:cloze:Question}}

<script>
const clozeElements = document.getElementsByClassName("cloze");
for (let i = clozeElements.length - 1; i >= 0; i--) {
  const cloze = clozeElements[i];
  const ordinal = cloze.dataset.ordinal;
  const input = document.createElement("input");
  input.type = "text";
  input.classList.add("cloze-input");
  input.dataset.ordinal = ordinal;
  cloze.parentNode.insertBefore(input, cloze);
  cloze.parentNode.removeChild(cloze);
}

const clozeInputs = document.getElementsByClassName("cloze-input");
const mainInput = document.getElementById("typeans");

for (let i = 0; i < clozeInputs.length; i++) {
  const clozeInput = clozeInputs[i];
  clozeInput.addEventListener("input", function(event) {
    let values = [];
    for (let j = 0; j < clozeInputs.length; j++) {
      values.push(clozeInputs[j].value);
    }
    mainInput.value = values.join(" ");
  });
}
</script>

Back card

{{type:cloze:Question}}<br>

{{Note}}

It is unlikely that the JS disappears, but it probably throws a syntax error:

1 Like

The javascript code definitely didn’t disappear, I just don’t know which word to use to describe that it’s not working because I’m not very familiar with the code. But I will try again with your method, thank you very much.
p/s: But do you know why this error only occurs on the PC version and not on mobile? Many of my other decks that use JavaScript to play videos, extract text, or play audio also encounter similar issues

It’s because AnkiDroid rebuilds the document on each card flip, whereas Anki Desktop persists the document.

var can be redeclared, but const or let cannot. That means as soon as you flip the card, there will be an error if a variable is already defined with one of these keywords.

Here’s a more detailed explanation (the statement about 2.1.41 is wrong, as Damien commented below):

2 Likes

I apologize for the delay in responding, you know, the time zone difference.
Thank you so much, today I learned something new. It’s really difficult for someone like me who doesn’t have a good understanding of code to find a thread discussing my issue, let alone a constructive comment like yours. The code snippet now works perfectly on both mobile and desktop devices (for now), for those who are interested, the code snippet is as follows:

Front

{{cloze:Question}}
{{type:cloze:Question}}

<script>
(() => {
  const clozeElements = document.getElementsByClassName("cloze");
  for (let i = clozeElements.length - 1; i >= 0; i--) {
    const cloze = clozeElements[i];
    const ordinal = cloze.dataset.ordinal;
    const input = document.createElement("input");
    input.type = "text";
    input.classList.add("cloze-input");
    input.dataset.ordinal = ordinal;
    cloze.parentNode.insertBefore(input, cloze);
    cloze.parentNode.removeChild(cloze);
  }

  const clozeInputs = document.getElementsByClassName("cloze-input");
  const mainInput = document.getElementById("typeans");

  for (let i = 0; i < clozeInputs.length; i++) {
    const clozeInput = clozeInputs[i];
    clozeInput.addEventListener("input", function(event) {
      let values = [];
      for (let j = 0; j < clozeInputs.length; j++) {
        values.push(clozeInputs[j].value);
      }
      mainInput.value = values.join(" ");
    });
  }
})();
</script>

Back

{{type:cloze:Question}}<br>

{{Note}}
2 Likes

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