Cloze one by one uncovering

thanks, worked like a charm :+1:

I see, so {{c1::}} is taken by anki and run in first so you get empty string from it when you wanting to run some JavaScript on it, can it be done by running javascript that connect with sqlite database to get the content of {{c1::}} from the field with the same note id and run the JavaScript code after anki action done and replace the value with the new one?
(I don’t know if it’s possible to send calls to anki sqlite database by JavaScript but maybe? :sweat_smile:)

That would over-complicate things :relaxed:
Like mentioned above, the easiest thing would be to parse the raw cloze syntax myself. That is, write a JS algorithm that takes the innerHTML of an element and creates more useful cloze spans out of the raw field input than what Anki does natively.

Then I can use the front side for the incremental reveal and make users click “Show Answer” on the last cloze.


As a side note: I do not use clozes myself, because I personally prefer Q&A style cards, but helping you guys out with this is very gratifying for me, so I’ll continue to do it in my free time :grinning_face_with_smiling_eyes:
Massive and Incremental Cloze are two nice side projects that many people seem to be interested in, so I might create a more robust, general-use Cloze+ note type one day that takes the best of both worlds.

Thanks for the inspiration and feedback to all of you!

2 Likes

Thanks for your help,
By the way, if you interest in Q&A cards more I have a note type that is useful for you maybe, the main purpose of it that when you have two information that related to each other but if you put the questions all along you will spoil the first answer like that so it’s small nested questions and to reveal all press show answer,like this:
16-00-31-ezgif-7-98abd8aa1631
And the input is easy and user friendly:


It’s formating needs a little adjustment, if you want I can send you sample template

@MmZ1, I’d like to see it. It seems like it would help me with certain types of cards, that I’d been handling using nested <details> tags until now.

1 Like

Here is it:
http://dl.tiapp.ga/179164296963809200085979252/Nested_Q_As-20211002152245.apkg
I didn’t find how to send files in this forum so i use telegram Direct link generator bot to send the file with the link above but seems that the link will expire in 24h,
I made some modifications to the code to fix some viewing errors and it is support night mode now for both background and text colors,and mobile class for font size,


If you know how we can benefit from this with different things you may share it with us, for now I use this script to show nested Q&As

2 Likes

@shallash
Sorry there are a small error in styling:
in night mode after question 3 the button color go white, to fix this go to front template and replace all id=‘b2,b3,b4,b5,b6,b7,b8,b9;b10’ with ‘b12’ (not id=1,2,3…etc)
And in style remove extra b2,3,4 and keep only b12 in the same line in both light and night lines
I update the link above you can instantly copy it

1 Like

Hi all, I wanted to know if there’s any way I can flip the card to the back, once all of my incremental clozes are uncovered. (I’m using the closet incremental clozes)

Thanks for sharing this. But I just want to have multiple cloze in one cards (like c1, c2 in one card), is there a way (or javascript hints) that I can make it? Thanks.

Just name them all c1. Or use the Ctrl+Alt/Option+C shortcut.

Yeah but I want to use multiple clozes (c1 c2 c3…) in one card so that I could choose to reveal one by one or reveal all ( one card, not random) or use with input (fill the blank). At that time, I need to fill all the blank to reveal them instead of one by one.

I’m really struggling to make heads and tails of how to implement this code into my card templates to make them work. Where do I paste these? On which template? Everything I tried has made the clozes stop being blurred or doesn’t work for me and I’m really confused. I don’t have any javascript knowledge so that’s not helping either. Any help would be appreciated

@kleinerpirat Is it possible to implement the Cloze one by one into the Ankiphil v2 Card template?

Ankili got it working on the v1 template, but I struggle to replicate it in v2.
I managed to get it working on Windows by copy pasting as I saw fit, but couldn’t really replicate that.
It also did not work on AnkiDroid.

We established an Anki work group at the Medical Faculty in Halle and could really use a cloze-one-by-one to upgrade existing cards for OSCEs and the learning of Standart operating procedures and Algorithms.

We are also planning to rework the German M2 Deck in collaboration with Göttingen and these type of cards could come in very handy.

Front-Side

<!-- ##############  HEADER  ############## -->
<div class="header">
    
    <!-- TIMER -->
    <span class="timer" id="timer"></span>
    <script>
      //############## TIMER CONFIGURATION START ##############
      //Set Timer Length

        var minutes = 0
        var seconds = 15
        
      //############## TIMER CONFIGURATION END ##############

      function countdown( elementName, minutes, seconds )
      {
        var element, endTime, hours, mins, msLeft, time;
        function twoDigits( n )
        {
            return (n <= 9 ? "0" + n : n); 
        }
        function updateTimer()
        {
            msLeft = endTime - (+new Date);
            //USER CUSTOMIZATION - you can edit color and text of the 'time expired' readout under the element.innerHTML
            if ( msLeft < 1000 ) {
                element.innerHTML = "<span style='color:#CC5B5B; font-weight:bold; margin-right: 5px;'>! ! !</span>";
            } else {
                time = new Date( msLeft );
                hours = time.getUTCHours();
                mins = time.getUTCMinutes();
                element.innerHTML = (hours ? hours + ':' + twoDigits( mins ) : mins) + ':' + twoDigits( time.getUTCSeconds() );
                setTimeout( updateTimer, time.getUTCMilliseconds() + 500 );
            }
        }
        element = document.getElementById( elementName );
        endTime = (+new Date) + 1000 * (60*minutes + seconds) + 500;
        updateTimer();
      }
        countdown("timer", minutes, seconds ); //2nd value is the minute, 3rd is the seconds
    </script>

    <div class="head-flex-mid">
        <!-- TAGS FIELD -->
        <div class="headhov">{{#Tags}}<button class="button-tags" onclick="myFunction('button-tags', 'hint-tags', 'button-tags')" title="Öffne/Schließe&#10;(⌥/Alt+T)"><strong>Tags</strong></button>{{/Tags}}</div>
            <div class="headhov"><div id="button-tags" class="generalclass" style="display:none;">
            {{Tags}}</div></div> | 
        
        <!-- SOURCE FIELD -->
        <div class="headhov"><strong>{{Source}}</strong></div> | 

        <!-- NOTE ID FIELD -->
        <div class="headhov">{{#Note ID}}<button class="button-nid" onclick="myFunction('button-nid', 'hint-nid', 'button-nid')" title="Öffne/Schließe&#10;(⌥/Alt+N)"><strong>Note ID</strong></button>{{/Note ID}}</div>
            <div class="headhov"><div id="button-nid" class="generalclass" style="display:none;">
            {{Note ID}}</div></div>
    </div>
    
    <!-- DATE STAMP FIELD -->
    <div class="head-flex-right"><div class="headhov"><span style="margin-left: -3px;"><strong>{{Date Stamp}}</strong></span></div></div>
</div><hr>


<div class="cloze-container" id="cloze">{{edit:cloze:Text}}</div>


<br><br>


<script>
  // ##############  BUTTON REVEAL SHORTCUTS  ##############
  // Visit https://keycode.info/ to get the number/letter for the key you want to assign
  // The shortcuts are  Alt  +  the number/letter below
  // All shortcuts will also open with "H" if using the Hint Hotkeys add-on

  var tags = '84'
  var nid = '78'
  var errata = '69'

  var ScrollToHint = true;
</script>


<script>
  function myFunction(divid, id, divid) {
    var x = document.getElementById(divid), y = document.getElementById(id), z = document.getElementById(divid);
    if (x.style.display == "none") 
    {
    x.style.display = "block"; y.style.display = "none"; z.scrollToId;
    } 
        else {
         x.style.display = "none"; y.style.display = "inline-block";
        }
    if (ScrollToHint){
        z.scrollIntoView({
         behavior: "smooth", //"auto" for instant scrolling
         block: "start",
         inline: "nearest"
    });}
    }
    document.onkeydown = function(evt) {
    evt = evt || window.event;
        if (evt.altKey && evt.keyCode == tags) {
            myFunction('button-tags', 'hint-tags', 'button-tags')}
        if (evt.altKey && evt.keyCode == nid) {
            myFunction('button-nid', 'hint-nid', 'button-nid')}
        if (evt.altKey && evt.keyCode == errata) {
            document.getElementById('button-errata').click(); document.getElementById('button-errata').style.display = "inline-block";}
    }
</script>

Back-Side

<!-- ##############  HEADER  ############## -->
<div class="header">
    
    <!-- TIMER -->
    <span class="timer" id="timer"></span>
    <script>
      //############## TIMER CONFIGURATION START ##############
      //Set Timer Length

        var minutes = 0
        var seconds = 15
        
      //############## TIMER CONFIGURATION END ##############

      function countdown( elementName, minutes, seconds )
      {
        var element, endTime, hours, mins, msLeft, time;
        function twoDigits( n )
        {
            return (n <= 9 ? "0" + n : n); 
        }
        function updateTimer()
        {
            msLeft = endTime - (+new Date);
            //USER CUSTOMIZATION - you can edit color and text of the 'time expired' readout under the element.innerHTML
            if ( msLeft < 1000 ) {
                element.innerHTML = "<span style='color:#CC5B5B; font-weight:bold; margin-right: 5px;'>! ! !</span>";
            } else {
                time = new Date( msLeft );
                hours = time.getUTCHours();
                mins = time.getUTCMinutes();
                element.innerHTML = (hours ? hours + ':' + twoDigits( mins ) : mins) + ':' + twoDigits( time.getUTCSeconds() );
                setTimeout( updateTimer, time.getUTCMilliseconds() + 500 );
            }
        }
        element = document.getElementById( elementName );
        endTime = (+new Date) + 1000 * (60*minutes + seconds) + 500;
        updateTimer();
      }
        countdown("timer", minutes, seconds ); //2nd value is the minute, 3rd is the seconds
    </script>

    <div class="head-flex-mid">
        <!-- TAGS FIELD -->
        <div class="headhov">{{#Tags}}<button class="button-tags" onclick="myFunction('button-tags', 'hint-tags', 'button-tags')" title="Öffne/Schließe&#10;(⌥/Alt+T)"><strong>Tags</strong></button>{{/Tags}}</div>
            <div class="headhov"><div id="button-tags" class="generalclass" style="display:none;">
            {{Tags}}</div></div> | 
        
        <!-- SOURCE FIELD -->
        <div class="headhov"><strong>{{Source}}</strong></div> | 

        <!-- NOTE ID FIELD -->
        <div class="headhov">{{#Note ID}}<button class="button-nid" onclick="myFunction('button-nid', 'hint-nid', 'button-nid')" title="Öffne/Schließe&#10;(⌥/Alt+N)"><strong>Note ID</strong></button>{{/Note ID}}</div>
            <div class="headhov"><div id="button-nid" class="generalclass" style="display:none;">
            {{Note ID}}</div></div>
    </div>
    
    <!-- DATE STAMP FIELD -->
    <div class="head-flex-right"><div class="headhov"><span style="margin-left: -3px;"><strong>{{Date Stamp}}</strong></span></div></div>
</div><hr>


<div class="cloze-container" id="cloze">{{edit:cloze:Text}}</div>


<br><br>


<!-- EXTRA FIELD -->
    {{#Extra}}<div class="extra" id="extra">{{edit:Extra}}</div><br>{{/Extra}}


<script>
  // ##############  BUTTON REVEAL SHORTCUTS  ##############
  // Visit https://keycode.info/ to get the number/letter for the key you want to assign
  // The shortcuts are  Alt  +  the number/letter below
  // All shortcuts will also open with "H" if using the Hint Hotkeys add-on

  var tags = '84'
  var nid = '78'
  var errata = '69'

  var amboss_link = '49'
  var zusatz = '50'
  var hammer = '51'
  var meditricks = '52'
  var klinik = '53'
  var histo = '54'
  var image = '55'

  var OpenCloseAll = '56'

  var ScrollToHint = true;
</script>


<!-- ##############  SHOW FIELDS AUTOMATICALLY  ##############
For instructions on how to show a field automatically, visit www.ankingmed.com/faq and search for "show hint" or watch the video on YouTube -->

<!-- HAMMER FIELD -->
<div id="button-hammer" class="generalclass" style="display:none;">
	{{#Hammer}}<div class="hammer"><button class="button-hammer" onclick="document.getElementById('hint-hammer').style.display='inline-block'; myFunction('button-hammer', 'hint-hammer', 'button-hammer')" title="Schließe Hammer&#10;(⌥/Alt+3)" style="margin: 2.5px;"><img src="_amboss-hammer.icon_v2.png">Hammer</button><br>
	<div id="hammer">{{edit:Hammer}}</div></div><br>
	{{/Hammer}}</div>

<!-- IMAGE FIELD -->
<div id="button-img" class="generalclass">
	{{#Image}}<div class="image" id="image">{{edit:Image}}</div><br>{{/Image}}</div>

<!-- AMBOSS-LINK -->
{{#AMBOSS-Link}}<a href="{{AMBOSS-Link}}"><button class="button-amboss" id="button-amboss" title="Zum AMBOSS-Kapitel&#10;(⌥/Alt+1)"><img src="_amboss-icon_16x16.png">AMBOSS</button></a>{{/AMBOSS-Link}}

<!-- ZUSATZINFOS / HAMMER / MEDITRICKS / KLINIK / HISTO / IMAGE BUTTON -->
{{#Zusatzinfos}}<a href="#" class="hint" id="hint-zusatz" onclick="this.style.display='none'; myFunction('button-zusatz', 'hint-zusatz', 'button-zusatz'); return false;">
	<button class="button-zusatz" title="Öffne Zusatzinfos&#10;(⌥/Alt+2)"><img src="_amboss-zusatz.icon_v2.png"> Zusatzinfos</button></a>{{/Zusatzinfos}}

{{#Hammer}}<a href="#" class="hint" id="hint-hammer" onclick="this.style.display='none'; myFunction('button-hammer', 'hint-hammer', 'button-hammer'); return false;">
	<button class="button-hammer" title="Öffne Hammer&#10;(⌥/Alt+3)"><img src="_amboss-hammer.icon_v2.png">Hammer</button></a>{{/Hammer}}

{{#Meditricks}}<a href="#" class="hint" id="hint-meditricks" onclick="this.style.display='inline-block'; myFunction('button-meditricks', 'hint-meditricks', 'button-meditricks'); return false;">
    <button class="button-meditricks" title="Öffne Meditricks&#10;(⌥/Alt+4)"><img src="_meditricks.icon_v1.png"> <img src="_meditricks_v1.png"></button></a>{{/Meditricks}}
    
{{#Klinik}}<a href="#" class="hint" id="hint-klinik" onclick="this.style.display='none'; myFunction('button-klinik', 'hint-klinik', 'button-klinik'); return false;">
    <button class="button-klinik" title="Öffne Klinik&#10;(⌥/Alt+5)"><img src="_amboss-stethoskop.icon_v2.png">Klinik</button></a>{{/Klinik}}

{{#Präparat}}<a href="#" class="hint" id="hint-histo" onclick="this.style.display='none'; myFunction('button-histo', 'hint-histo', 'button-histo'); return false;">
	<button class="button-histo" title="Öffne Präparat&#10;(⌥/Alt+6)"><img src="_amboss-microscope.icon_v3.png">Präparat</button></a>{{/Präparat}}

{{#Image}}<a href="#" class="hint" id="hint-image" onclick="this.style.display='inline-block'; myFunction('button-img', 'hint-img', 'button-img'); return false;">
	<button class="button-img" title="Öffne/Schließe&#10;(⌥/Alt+7)"><img src="_amboss-abb.icon_v2.png">Abbildung</button></a>{{/Image}}

<br><br>

<!-- ZUSATZINFOS FIELD -->
<div id="button-zusatz" class="generalclass" style="display:none;">
    {{#Zusatzinfos}}<div class="zusatz"><button class="button-zusatz" onclick="document.getElementById('hint-zusatz').style.display='inline-block'; myFunction('button-zusatz', 'hint-zusatz', 'button-zusatz')" title="Schließe Zusatzinfos&#10;(⌥/Alt+2)" style="margin: 2.5px;"><img src="_amboss-zusatz.icon_v2.png"> Zusatzinfos</button><br>
    <div id="zusatz">{{edit:Zusatzinfos}}</div></div><br>
	{{/Zusatzinfos}}</div>

<!-- MEDITRICKS FIELD -->
<div id="button-meditricks" class="generalclass" style="display:none;">
	{{#Meditricks}}<div class="image"><button class="button-meditricks" onclick="document.getElementById('hint-meditricks').style.display='inline-block'; myFunction('button-meditricks', 'hint-meditricks', 'button-meditricks')" title="Schließe Meditricks&#10;(⌥/Alt+4)" style="width: 50%; max-width: 375px; margin: 2.5px;"><img src="_meditricks.icon_v1.png"> <img src="_meditricks_v1.png"></button><br>
    <div id="meditricks">{{edit:Meditricks}}</div></div><br>
    {{/Meditricks}}</div>

<!-- KLINIK FIELD -->
<div id="button-klinik" class="generalclass" style="display:none;">
	{{#Klinik}}<div class="klinik"><button class="button-klinik" onclick="document.getElementById('hint-klinik').style.display='inline-block'; myFunction('button-klinik', 'hint-klinik', 'button-klinik')" title="Schließe Klinik&#10;(⌥/Alt+5)" style="margin: 2.5px;"><img src="_amboss-stethoskop.icon_v2.png">Klinik</button><br>
	<div id="klinik">{{edit:Klinik}}</div></div><br>
	{{/Klinik}}</div>

<!-- HISTO FIELD -->
<div id="button-histo" class="generalclass" style="display:none;">
    {{#Präparat}}<div class="histo"><button class="button-histo" onclick="document.getElementById('hint-histo').style.display='inline-block'; myFunction('button-histo', 'hint-histo', 'button-histo')" title="Schließe Präparat&#10;(⌥/Alt+6)" style="margin: 2.5px;"><img src="_amboss-microscope.icon_v3.png">Präparat</button><br>
    <div id="histo">{{edit:Präparat}}</div></div><br>
	{{/Präparat}}</div>


<script>
  function myFunction(divid, id, divid) {
    var x = document.getElementById(divid), y = document.getElementById(id), z = document.getElementById(divid);
    if (x.style.display == "none") 
    {
    x.style.display = "block"; y.style.display = "none"; z.scrollToId;
    } 
        else {
         x.style.display = "none"; y.style.display = "inline-block";
        }
    if (ScrollToHint){
        z.scrollIntoView({
         behavior: "smooth", //"auto" for instant scrolling
         block: "start",
         inline: "nearest"
    });}
    }
    document.onkeydown = function(evt) {
    evt = evt || window.event;
        if (evt.altKey && evt.keyCode == tags) {
            myFunction('button-tags', 'hint-tags', 'button-tags')}
        if (evt.altKey && evt.keyCode == nid) {
            myFunction('button-nid', 'hint-nid', 'button-nid')}
        if (evt.altKey && evt.keyCode == errata) {
            document.getElementById('button-errata').click(); document.getElementById('button-errata').style.display = "inline-block";}
        if (evt.altKey && evt.keyCode == amboss_link) {
            document.getElementById('button-amboss').click(); document.getElementById('button-amboss').style.display = "inline-block";}
        if (evt.altKey && evt.keyCode == zusatz) {
            myFunction('button-zusatz', 'hint-zusatz', 'button-zusatz')}
        if (evt.altKey && evt.keyCode == hammer) {
            myFunction('button-hammer', 'hint-hammer', 'button-hammer')}
        if (evt.altKey && evt.keyCode == meditricks) {
            myFunction('button-meditricks', 'hint-meditricks', 'button-meditricks')}
        if (evt.altKey && evt.keyCode == klinik) {
            myFunction('button-klinik', 'hint-klinik', 'button-klinik')}
        if (evt.altKey && evt.keyCode == histo) {
            myFunction('button-histo', 'hint-histo', 'button-histo')}
        if (evt.altKey && evt.keyCode == image) {
            myFunction('button-img', 'hint-img', 'button-img')}
        
        if (evt.altKey && evt.keyCode == OpenCloseAll) {
        try{myFunction('button-img', 'hint-img', 'button-img')}
        finally{try{myFunction('button-histo', 'hint-histo', 'button-histo')}
        finally{try{myFunction('button-klinik', 'hint-klinik', 'button-klinik')}
        finally{try{myFunction('button-meditricks', 'hint-meditricks', 'button-meditricks')}
        finally{try{myFunction('button-zusatz', 'hint-zusatz', 'button-zusatz')}
        finally{myFunction('button-hammer', 'hint-hammer', 'button-hammer')}}}}}
        }
    }
</script>

I just took a brief look at the Ankiphil deck and saw that there are some notes with clozed enumerations, like this one:

Just to make sure I understood correctly: You want to be able to incrementally reveal the clozes of an individual card by clicking on them or via shortcut (in this case, the three red clozes)?

Currently, I’m a bit busy with uni, but I might be able to take a look at it this weekend (if not, then next weekend :D).

Hi, your template is wonderful!
And I found a way to get current cloze id and their answer in front card. (a regex trick)
In addition, my js code add every cloze span a onclick event to show/hide content.
Finally, I found a way from an unsigned template to automatically turn to the back after all clozes show the answer(AnkiMobile, PC, AnkiDroid).
I think we can merge our template into a perfect template.
My code is simple in front.html : front.html

1 Like

I did it! :grinning: AnkiWeb share code: 457099967
Source code is in my github

mathjax_in_anki

All in the front side.

3 Likes

Gave it a quick try and it looks awesome! This is surely going to be of interest to many users. Thanks for sharing @ruin1990! :clap:

I forgot to remove the line

(only wrapped equations, no AnkiDroid support)

in the original template. You can remove it from your shared note, since it isn’t true anymore.

:grin: Okay, I changed it.

I personally think the best thing about my template is the smooth transition from the original Cloze.
Just replace the front template simply.

I want to share with you a very interesting model.
All credit goes to GitHub - thiswillbeyourgithub/Clozolkor: enhancing "cloze one by one" script by iTraveller.
I made my modifications and added a few things.

Animação

1 Like

first, @kleinerpirat and @kleinerpirat congratulations on the card, it was excellent!

When we add a Hint in cloze, that Hint remains after the reveal (in the Kleinerpirati version this didn’t happen):

Animação

I want to give a suggestion that exists in the model I posted above:

  • Have a hotkey to show letter by letter
    Animação2
1 Like