How to create a script that modifies the content of the fields?

Hello. I need to create a script that takes a word from the first field of the card, modifies the sentence from the second field, and displays the modified result.
The script on the front side should replace the word with underscores. On the back, it should wrap the word in <b></b> tags to make it bold. Example:

Word: weather
Sentence: The weather yesterday was good.

Front side output: The ___ yesterday was good.
Back side output: The weather yesterday was good. (The <b>weather</b> yesterday was good)

I wrote some code that works well in browsers, but it doesn’t work in the Anki app. Could somebody, please, help me to understand why it doesn’t work?

Front side:

<div>Front</div><hr><br>

<div class="word" style="display:none">{{Word}}</div>
<div class="sentence" style="display:none">{{Sentence}}</div>

<div class="output1"></div>

<script>

      let word = document.querySelector(".word").textContent;
      let sentence = document.querySelector(".sentence").textContent;

      document.querySelector(".output1").textContent = sentence.replace(word, "___");

</script>

Back side:

<div>Back</div><hr><br>

<div class="word" style="display:none">{{Word}}</div>
<div class="sentence" style="display:none">{{Sentence}}</div>

<div class="output2"></div>

<script>

      let word = document.querySelector(".word").textContent;
      let sentence = document.querySelector(".sentence").textContent;

      document.querySelector(".output2").innerHTML = sentence.replace(word, "<b>" + word + "</b>");

</script>

By deleting “let” your script seems to work fine for me:

Front script:

<script>

      word = document.querySelector(".word").textContent;
      sentence = document.querySelector(".sentence").textContent;

      document.querySelector(".output1").textContent = sentence.replace(word, "___");

</script>

Back script:

<script>

      word = document.querySelector(".word").textContent;
      sentence = document.querySelector(".sentence").textContent;

      document.querySelector(".output2").innerHTML = sentence.replace(word, "<b>" + word + "</b>");

</script>
2 Likes

It works indeed! Thanks!
But how the hell do these variables work without declarative words (let, const, var)?

A new problem has arisen. Replacing replace() method with replaceAll() makes the code broken. Is there any way to make the replaceAll() method work properly?

(Disclaimer: I am not a programmer, so my knowledge on the subject is limited and what I say might not be correct)

About the first question: as far as I know, it is not strictly necessary to use declarative words, but you are always advised to, as sometimes problems might happen if you do not. Neither let or const seem to work with your script, while var seems to work fine.
From https://www.w3schools.com/js/js_variables.asp :

Always declare JavaScript variables with var , let , or const .
The var keyword is used in all JavaScript code from 1995 to 2015.
The let and const keywords were added to JavaScript in 2015.
If you want your code to run in older browser, you must use var

That said, I personally have some scripts in which const is used and they all function fine. So I do not know what might be the issue in this case.

About the replace() vs replaceAll() part: I don’t think replaceAll() is needed to accomplish what you’re trying to, you can use RegEx with the g (global) modifier. See my reply in your other topic

1 Like

Now you might ask: “What is the issue with using block scoped variables at the top level of a <script> tag, i.e. why is const and let working inside functions, but not outside?”

A variable with the same name must not be declared multiple times in the same scope using the let or const keywords.

Consider this script:

let num = 1
let num = 42

The second line will throw the following error:

Uncaught SyntaxError: Identifier 'num' has already been declared.

Say you used let/const at the top-level of a <script> tag, which is the outermost scope. When Anki executes that script twice in the same context (i.e. when switching to a new card), it will throw that error.

This wasn’t an issue before Anki switched to persisting its webview during review. Before 2.1.41, the whole document was refreshed with each card, so you could use let/const/var interchangeably.

Now, you’ll need to use var at the outermost scope.

3 Likes

(for the record, older Anki versions used a persistent webview too; I believe the change in behaviour was when we moved away from using jquery to update the HTML)

1 Like