How to have instant type:answer feedback?

Thanks @BlackBeans for caring about my digital wellbeing, but I don’t really mind the pinging :wink: It’s an honor some people reach out to me for help - altough I don’t always find the time for it.


@huyvanphan, try this script for your front template of “Basic (type in the answer)”:

<script>
  (() => {
  /**
   * Type-in-the-answer live feedback for Anki
   * @author Matthias Metelka | @kleinerpirat
   */
    /* Helper functions to keep caret position while typing */
    const getCaretPosition = (contenteditable) => {
      contenteditable.focus();
      let _range = document.getSelection().getRangeAt(0);
      let range = _range.cloneRange();
      range.selectNodeContents(contenteditable);
      range.setEnd(_range.endContainer, _range.endOffset);
      return range.toString().length;
    };
    const setCaretPosition = (contenteditable, pos) => {
      contenteditable.focus();
      document.getSelection().collapse(contenteditable, pos);
    };

    /* Replace input with contenteditable div */
    const input = document.getElementById("typeans");
    const editable = document.createElement("div");
    editable.contentEditable = true;
    editable.id = "typeans";
    editable.innerHTML = input.value;
    input.replaceWith(editable);

    editable.addEventListener("input", () => {
      const pos = getCaretPosition(editable);
      /* Anki uses value attribute to compare answer */
      editable.value = editable.innerText;

      editable.innerHTML = (() => {
        const letters = editable.innerText.split("");
        const word = "{{Answer}}";
        let html = "";
        letters.forEach((letter, i) => {
          html += `<span class="${
            letter == word[i] ? "typeGood" : "typeBad"
          }">${letter}</span>`;
        });
        return html;
      })();
      setCaretPosition(editable, pos);
    });
  })();
</script>

CSS

[contenteditable]#typeans {
  border: thin solid var(--border);
  background: var(--frame-bg);
}

Explanation

Anki uses an input element for its answer box, which cannot contain HTML, only plain text - so it can’t be styled. My script replaces that input element with a contenteditable (the same kind of element that’s used for the fields in Anki’s note editor).

I wrap each letter in its own <span>, using Anki’s classes “typeGood” and “typeBad” for color-coding.

There’s some overhead because updating the inner HTML of such an element moves the caret position to the start.