How to make a certain part of the field as type in?

I want Anki to check my answers for certain cards after I type them in.

However, I don’t want to create a separate field for the answer because I often create forward + backward cards and that too with proper sentences (to help retain the context) and putting the answer into a separate field would make it difficult to create the backward cards.

I also don’t want to use cloze deletions because then I tend to remember the card rather than the answer.

A possible solution would be to wrap the answer with some HTML, probably something like the following:

This is an example of an <span class="type">answer</span>.

The above example is different from a cloze in that this whole text is on the back side on the card. The front side has a different text which serves as the question. The text that I want Anki to match is the part that is contained within the span element.

But, I don’t know how to get it working, if it is even possible. I would appreciate some help in this regard. Thanks!

Typing in specific parts of a sentence is exactly what {{type:cloze:fieldName}} is meant for, so i think you will most likely have to use it. The way you use “type” as a class name will not work.

However, you can use some CSS styling to hide parts of the enclozed text on the front, so you don’t “remember the card”, as you have described.

Create a note-type with one field named “Text”. Insert the following HTML into that field.

<div class="question_text">
  Example Question Sentence..?
</div>
<div class="cloze_text">
  Unenclosed part, hidden on the front ‒ {{c1::enclosed part to be typed}}
</div>

For the note-type, use the following HTML and CSS:

Front Template

<style>
	.question_text {
		display: block;
	}
	.cloze_text {
		display: none;
	}
</style>

<div>{{cloze:Text}}</div>

<div>{{type:cloze:Text}}</div>

Back Template

<style>
	.cloze_text {
		display: block;
	}
	.question_text {
		display: block;
	}
</style>

<div>{{cloze:Text}}</div>

<div>{{type:cloze:Text}}</div>

Styling

.card {
 font-family: arial;
 font-size: 20px;
 text-align: block;
 color: black;
 background-color: white;
}

.cloze {
 font-weight: bold;
 color: blue;
}

.cloze-inactive {
	color: yellow;
}

div {
	padding: 0.5rem;
}

In my opinion, this could be more elegant, if you would separate the question text and the text to be partially enclozed into two fields. But i stuck with your approach of keeping the question text and the text to be enclozed in one field.

Thanks for taking out the time to help. But I couldn’t understand how to adapt your approach for myself.

First of all, it is not clear how to use it with forward and backward cards. That is, how do I use different questions for the forward and the backward cards?

Another important thing is that I prefer all my cards to have the same note type. This makes creating cards easier and also allows changing their format later without forcing a full sync.

Let me share some examples of how I want the cards to look.

Example 1:

Front:

What is "term"?

Back:

It refers to ....

Term?

For the forward card, I don’t want the typing box (though there should be not much problem if it has to be there).

For the backward card, I want Anki to match only the “term”. However, I have no major issue if the question stem much be displayed. I just want that only the term should be matched.

Example 2:

Front:

Which instrument is used to .... ?

Back:

What is .... used for?

For the forward card, I want Anki to match only the name of the instrument.

For the backward card, I don’t want the typing box (though there should be not much problem if it has to be there).

Example 3:

Front:

What is another term for .... ?

Back:

What is another term for .... ?

Here, I want Anki to match the term in both forward and reverse cards.

Example 4:

Front:

What is the mechanism of .... ?

Back:

Mechanism

Here, I don’t want to create a backward card. Also, I don’t want Anki to match anything here.

I am not sure how convincing the above explanation is, but I do require a “super” note type that can

  • use different questions for the forward and backward cards
  • control whether the backward card is generated or not
  • control if the “type in the answer” box is displayed or not (depending on whether the answer has such an element or not)
  • match only the specified part of the answer, if typing is enabled for that answer.

The Basic (with optional reversed card) note type is able to fulfill my first two requirements. But, I am looking for a solution to fulfill the other two requirements in the same note type.

Yeah i realized that i didn’t included a way to display multiple different questions.

Change the HTML content to the following:

<section>
  <div class="question_text">Example Question Sentence..?
  </div>
  <div class="cloze_text">
    Unenclosed part, hidden on the front ‒ {{c1::enclosed part to be typed}}</div>
</section>
<section>
  <div class="question_text">
    Second example Question Sentence..?
  </div>
  <div class="cloze_text">Second sentence, hidden on the front ‒ {{c2::third part to be enclozed}}</div>
</section>
<section>
  <div class="question_text">
    Third example Question Sentence..?
  </div>
  <div class="cloze_text">Third sentence, hidden on the front ‒ {{c3::third part to be enclozed}}</div>
</section>

In the styling section of the note-type, add the following:

section:has(.cloze-inactive){
	display: none;
}

You don’t have to change the Front Template or the Back Template for this to work.

This is close to a good solution. But, the problem is that it makes the HTML code for each card too long.

I can put the front question in one field, the back question in another field. But I can’t make one field for the cloze because the cloze in each section must have only one deletion (c1 or c2 but not both) for the above code to work.

Also, because the answer is usually contained within the question of the opposite side, it would mean that I have to duplicate the content (to put it into the cloze_text).

I feel that the best way to solve this problem is the one I proposed in my original post. Anki should recognize a special class like “type_answer” and use it for matching the answer. However, I am not skilled enough to implement this myself (in JS) if it is even possible to do so using JS in the note type.

Another option would be that Anki natively supports using such a class for this purpose in the Basic and the other related note types. I am willing to wait for the next release, if the developers plan to implement it.

Having said that, i think there are other ways, in which you could approach this, which would each have their own advantages and drawbacks.

My idea with the {{type:cloze:fieldName}} cards was to fulfill your requirement of having only part of a sentence being checked. The disadvantages are, that you need some special HTML in the field content, which you have to copy each time when adding new cards. In addition, the cloze note-type in Anki does not allow for additional card types, which makes fulfilling your other requirements harder.

Another approach might be to stick to generic {{type:fieldName}} cards. This would require you to come up with a generic question or prompt, which you can include in the Front Template. The advantage would be, that you can create multiple card types (for Front-to-Back and Back-to-Front), and use the {{type:fieldName}} only on one card type. This would fulfill your requirement of being prompted to type in the answer only in one direction.

However, this approach goes against your requirements of having only on Field, since with {{type:fieldName}} the whole filed content will be checked by Anki, so you cannot include the question in the same field. And you will either have to include some JavaScript to determine the type of data you ask about, and change to question accordingly, or you will have to create different note-types for each type of data.

I think you will have to make some compromises, depending on which requirements are more important to you. I personally would prefer the second approach, and try to come up with generic questions or prompts, and i would create a couple of different note types for each of the data that i want to learn. But if it’s important to you that you only have one field, and that you have a large variety of question sentences, then the approach i first outlined might be preferable.

Firstly, I don’t want my note to have a single field. When I said that I don’t want to put the answer in a separate field, I meant that I don’t want to create a field just for the answer.

Secondly, it looks like I got an idea to solve the problem. However, I need some help with the JS required to implement it.

My idea:

Front Template:

{{Front}}
<div id="type">{{type:Back}}</div>

Back Template:

{{Front}}
<hr id=answer>
<div id="back">{{Back}}</div>
<div id='type'>{{type:Back}}</div>

Now,

  • If the {{Back}} field doesn’t have any element with the class “type_answer”, the divs with the id “type” should be hidden.
  • If the {{Back}} field has an element with the class “type_answer”, the div with the id “back” should be hidden. Also, the part of the {{Back}} field that is not contained within the element with the class “type_answer” should be hidden (and thus not matched).

The implementation of these two rules requires JS, which, unfortunately, I don’t have much experience in. So, I would appreciate any help to write the JS code to implement this.

Yeah, i agree that you will need JavaScript for this. Unfortunately i don’t know too much about it, so i would have to do some reading before attempting this.

You might want to change the subject of the post to “Card Design”, so more people who are interested / knowledgeable in JavaScript will see this.

1 Like

Maybe something like this

Front

{{Front}}

<div id="type">{{type:Back}}</div>
<div id="back" hidden>{{Back}}</div>

<script>
var typeElement = document.getElementById("type");
var backElement = document.getElementById("back");
var backContent = backElement.innerHTML;
var regex = /\btype_answer\b/;

if (!regex.test(backContent)) {
 typeElement.style.display = "none";
}
</script>

Back

{{Front}}

<hr id=answer>
<hr id="no_type_hr" hidden>

<div id="type">{{type:Back}}</div>
<div id="back">{{Back}}</div>

<script>
var typeElement = document.getElementById("type");
var backElement = document.getElementById("back");
var backContent = backElement.innerHTML;
var regex = /\btype_answer\b/;

if (!regex.test(backContent)) {
 typeElement.style.display = "none";
 document.getElementById("no_type_hr").style.display = "block";
} else {
 backElement.style.display = "none";
}
</script>
1 Like

@jcznk, that was very close to what I wanted. Thanks!

But if you could implement the following, it would meet my requirements exactly.

If the {{Back}} field has an element with the class “type_answer”, the part of the {{Back}} field that is not contained within the element with the class “type_answer” should be hidden (and thus not matched by Anki).

For example, here only the word “answer” should be matched.

It is probably possible, maybe with some regex, but it would require quite a more complex solution I’m afraid.

Maybe you could try the following workaround:

Front template:

{{Front}}

<div id="type">{{type:Back}}</div>
<div id="back" hidden>{{Back}}</div>

<script>
var typeElement = document.querySelector("#type");
var backElement = document.querySelector("#back");
var backContent = backElement.innerHTML;
var regex = /\btype_answer\b/;

if (!regex.test(backContent)) {
   typeElement.style.display = "none";
} 
</script>

<script>
  (() => {
   /**
   * Type-in-the-answer live feedback for Anki (vague variant)
   * @author Matthias Metelka | @kleinerpirat
   */
    const input = document.querySelector("#typeans");
    const answer = document.querySelector('.type_answer').innerText;
    if (input) {
      input.addEventListener("input", () => {
        input.classList.add("typed");
        input.classList.toggle(
          "goodsofar",
          input.value == answer.substring(0, input.value.length)
        );
        input.classList.toggle(
          "correct",
          input.value == answer
        );
      });
    }
  })();
</script>

Back template:

<span class="BackSide">

{{Front}}

<hr id=answer>

<div id="back">{{Back}}</div>

</span>

Styling section:

#typeans {
  color: black;
}
#typeans.typed {
  background-color: #ff9999;
}
#typeans.typed.goodsofar {
  background-color: #ffff7f;
}
#typeans.typed.correct {
  background-color: #99ff99;
}
.BackSide .type_answer {
  font-weight: bold; 
  color: blue;
}

Basically, instead of using Anki’s default code for evaluating type input, I inserted a slightly modified version of the code found in this topic to have instant type answer feedback.
I also removed most of the type_answer code from the Back template.
The purpose of the class BackSide and this CSS .BackSide .type_answer { font-weight: bold; color: blue; } is to highlight the content of the .type_answer span, to still have some sort of visual feedback.

I like this solution. Thank you very much for all the time you invested in finding a solution for me.

However, I have decided to use a slightly modified version of your JS & CSS.

I changed

const answer = document.querySelector('.type_answer').innerText;

to

    const answer = document.querySelector('.type_answer').innerText + '  ';

This will ensure that I will not immediately know that my answer is correct, and I will still have to press the spacebar twice before I get the confirmation.

For similar reasons, I removed the following from the CSS:

#typeans.typed {
  background-color: #ff9999;
}
#typeans.typed.goodsofar {
  background-color: #ffff7f;
}

Also, I found a major issue with the above approach (but I managed to solve it).
Because I make both forward and reverse cards, I will usually have “type_answer” on both front and back fields. But, the answer should be matched only from the back field. So, I changed

    const answer = document.querySelector('.type_answer').innerText + '  ';

to

    const answer = document.querySelector('#back .type_answer').innerText + '  ';

For similar reasons, I changed

#BackSide .type_answer {
	font-weight: bold;
  color: lightblue;
}

to

#BackSide #back .type_answer {
	font-weight: bold;
  color: lightblue;
}
1 Like

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