Image occlusion and cloze not working together (in one note)

I’d like to combine ‘image occlusion’ and ‘cloze’ in the following way; have clozes and image occlusions on one single note, where each count for a card. This seemed like it should work, since image occlusion seems to use “clozes” for occlusions. The problem is, that it produces brackets “{{c1:: }}” in the answer.

Look at the cloze in the previewer, where it says "{{c1:: }}.
The below thing emerges in actual cards as well, not just this viewer:


All the code, except for the following CSS, is contained in the above pictures:

#image-occlusion-canvas {
    --inactive-shape-color: #ffeba2;
    --active-shape-color: #92c3fa;
    --inactive-shape-border: 1px #212121;
    --active-shape-border: 1px #212121;
}

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

.photo-container {
            margin: 5px;
            border: 2px solid white;
            padding: 5px;
}

I would also like to understand, but have yet to finde this anywhere:

  1. Why are the ‘Header’ and ‘Back Extra’ fields necessary for the card?
  2. How can I remove them if they are not – does it make a difference if I write something in them?

In advance, thanks for any help—it is appreciated:) The above text is not very cordial, but I was trying to be short.

If it is any help, here is the code, from the two pictures:

{{Media}}
<div class="photo-container">
{{#Header}}<div>{{Header}}</div>{{/Header}}
<div style="display: none">{{cloze:Occlusion}}</div>
<div id="err"></div>
<div id="image-occlusion-container">
    {{Image}}
    <canvas id="image-occlusion-canvas"></canvas>
</div>
<script>
try {
    anki.imageOcclusion.setup();
} catch (exc) {
    document.getElementById("err").innerHTML = `Error loading image occlusion. Is your Anki version up to date?<br><br>${exc}`;
}
</script>
</div>
{{cloze::Back}}
{{#Back Extra}}<div>{{Back Extra}}</div>{{/Back Extra}}
{{Tags}}
{{Media}}
<div class="photo-container">
{{#Header}}<div>{{Header}}</div>{{/Header}}
<div style="display: none">{{cloze:Occlusion}}</div>
<div id="err"></div>
<div id="image-occlusion-container">
    {{Image}}
    <canvas id="image-occlusion-canvas"></canvas>
</div>
<script>
try {
    anki.imageOcclusion.setup();
} catch (exc) {
    document.getElementById("err").innerHTML = `Error loading image occlusion. Is your Anki version up to date?<br><br>${exc}`;
}
</script>
</div>
{{Back}}
{{#Back Extra}}<div>{{Back Extra}}</div>{{/Back Extra}}
{{Tags}}
<div><button id="toggle">Toggle Masks</button></div>

Someone else will have to explain to you exactly why it is so, but – you can only use c1/c2/… cloze notation on the Cloze note type. I understand what you’re saying about IO seeming like cloze in many ways, but it’s just not implemented that way.

However, it seems to me though that you don’t gain anything by blending these 2 notes into a single type, so just use them as separate types.

I’m not sure what you mean by “necessary”? The template actually uses them with Conditional Replacement – Card Generation - Anki Manual – so they are pretty specifically not necessary. If there’s nothing in that field of the note, they won’t be displayed on the card at all.

Remove them from where? This is a special note type, so I don’t think you can remove the fields. You can remove them from the card templates, I suppose – but since there’s no harm in leaving them there, and you might find a purpose for them some day, I’d encourage you to leave them alone.

1 Like

Firstly, I do gain something from blending the two types of notes; quickly, I want to have a figure and an accompanying description/code block. I then want to be able both to cloze parts of the image (the figure, e.g. of a graph) and cloze parts of the description and/or code block (e.g. with code that produces the graph, or explains it). My motivation for blending is legitimate.

Secondly, I tried to remove both of those fields (delete the fields), and Anki told me, that it was not a possibility, as they were “necessary”. This is all I meant by the second part. I do not understand what it is supposed to mean, and therefore I just inferred that they were “necessary” for the structure of the image occlusion.

A caveat, I could principally make an image including both the aforementioned code block and description, however the size of the occlusion reveals unnecessary information about the back-side (since the occlusion would be within a line). And it would require a great deal from me to fix mistakes post-creation of the note.

I wasn’t doubting your motivation. I’m just not sure that a combined note type is the only way to accomplish what you’re wanting. If it ends up not being possible at all, other avenues might be worth considering.

Ah, that was the part I answered later – correct, you can’t delete the fields.

1 Like

It looks like your back template is missing cloze syntax. Try replacing {{Back}} with {{cloze:Back}}.

Also, you might want to add some cloze-related CSS to the styling section, for example:

.cloze {
  font-weight: bold;
  color: red;
}
1 Like

Thanks, this solved the “{{c1:: }}” problem:) Much appreciated! :heart:
I can see however, that the field does not display on the card, where there is an image occlusion (I’ve noticed this now, but it does not seem to have anything to do with the new code).
The code is the same as above, with the exact edits you’ve suggested. I am probably going to make this another post on the forum, if you do not have suggestion.

The problem (there is one note, and two cards – which display in the way below):



Now, the card, that is the problem (the whole field “Back” is not displayed).

I think there might be no easy way to achieve that.

By design, cloze fields (e.g., {{text:Field}}) are only displayed when the current card number matches that of at least one of their cloze deletions.
For example: if card 1 corresponds to an image occlusion mask, and your {{cloze:Back}} field does not contain {{c1::some text}}, then, when Anki shows you card number 1, the {{cloze:Back}} field will not be included.

The following is a hacky workaround which employs javascript to selectively show the content of the {{Back}} field, depending on whether or not an image occlusion is currently being displayed.

It seems to work fine on my computer (Anki 24.02 beta1 for Windows10). I have not tested it on AnkiDroid or AnkiMobile. The first script might not work correctly if you use nested cloze deletions (e.g., {{c1::This is {{c2::an}} example}}).

<div id="originalBackContent" style="display: none;">{{Back}}</div>
<div id="backOutput"></div>
<div id="backCloze">{{cloze:Back}}</div>

<script>
    // This script retrieves the original content from an element with the id "originalBackContent",
    // removes any cloze syntax, and displays the modified content in an element with the id "backOutput".

    var originalContent = document.getElementById("originalBackContent").innerHTML;
    var unclozedContent = originalContent.replace(/\{\{c(\d+)::(.*?)(::(.*?))?\}\}/g, function(match, p1, p2, p3, p4) {
        return p2;
    });
    document.getElementById("backOutput").innerHTML = unclozedContent; 
</script>

<script>
    // This script checks if an element with the class "cloze" exists.
    // If such an element exists and it doesn't have a data attribute called "data-shape",
    // it hides the element with the id "backOutput".

    var clozeElement = document.querySelector('.cloze');
    if (clozeElement) {
        var clozeOcclusionInactive = clozeElement.getAttribute('data-shape');   
        if (!clozeOcclusionInactive) {
            document.getElementById("backOutput").style.display = "none";
        }
    }
</script>

2 Likes

I can confirm, that this works for the current iOS version of Anki (for iPhone – I have yet to test on iPad). This is wonderful! It works exactly like I wanted it to.

This is the result, if I use nested clozes (for context)–mind the “{{c3 N}}” is the result:


The text was supposed to say “arrival process N” (“process” was clozed and is now gone).
I don’t expect you to work any longer on this–you have already been a huge help to me, thank you:)

One last question; can I use this code mutatis mutandis with other fields (e.g. both with another field name, and if there are multiple cloze fields beside the “Back” field)?

Hi :slight_smile: Sorry for the late answer.

  1. Regarding nested cloze deletions, I’m afraid I can’t think of any “good” solution. Maybe you could try some workaround. Here are some ideas off the top of my head:
  • Remove the first script: This way, when showing an image occlusion card, Anki will display the literal content of the {{Back}} field, without removing any cloze syntax. It’s not the prettiest solution, but it avoids any loss of data or artifacts.

  • Add empty cloze deletions: Alternatively, you could add some additional “empty” cloze deletions (e.g., {{c1::-}}, {{c2::-}}) to the {{Back}} field, one for each image occlusion mask. This way, each “image occlusion” mask will have the same number as at least one text cloze deletion, and the {{cloze:Back}} field will always be shown, even without using any of the two scripts I posted. It’s a bit clunky, but quite effective.

  • Simplified version of the first script: Lastly, you could use a simplified version of the first script, which does not employ capture groups when removing cloze syntax. Pros: it should have better compatibility with nested cloze deletions. Cons: it will remove {{c1-9:: and }} even when they are not being used as cloze deletion syntax.

<script>
    var originalContent = document.getElementById("originalBackContent").innerHTML;
    var unclozedContent = originalContent.replace(/\{\{c\d+::/g, '').replace(/\}\}/g, '');
    document.getElementById("backOutput").innerHTML = unclozedContent; 
</script>
  1. Re “can I use this code with other fields”: Sure! I don’t see why not. Do you have anything specific in mind?