This project provides a template-based cloze implementation that:
This is achieved purely through JavaScript in the card template and a novel application of Anki's built-in (awesome) Selective Card Generation feature. The big benefit of this is that you can generate cloze cards from existing notes, for which you may already have cards. It has no dependency on Anki's Cloze note type nor any other note types, which means you don't have to migrate your cards to a new note type. It is compatible with Anki Desktop, AnkiMobile, and AnkiDroid.
Getting started is easy. You can either download the shared deck or follow the instructions for setting up the templates manually.
Replicating Anki functionality with JavaScript and card templates is not the goal however. The goal is endless flexibility. You can add cloze cards to any existing note type ("cloze anything") simply by adding new fields and card templates based on the instructions found here. You can also modify the templates completely, using them simply as a guide.
With the default settings this replicates Anki's cloze functionality. However the template is highly configurable and lets you do things you can't otherwise easily do. Below is a summary of some useful features of the templates and this approach.
[...]
or [hint]
in the case of a hint. The templates let you customize this. For example, you could use underscores and have the format be ___
. Or you could always include the hint, as in ___ [hint]
. Also instead of a fixed number of 3 characters you could have each non-space character replaced. So you could have ((c1::ab cdef::hint))
become __ ____ [hint]
.((c1::`a`bc `d`ef))
could be rendered as a__ d__
. You can selectively reveal any part of the content, not just at the beginning. Note that you could also do a((c1::bc)) d((c1::ef))
, however the backtick syntax may be more convenient.An optional plugin is also provided that automates some of the otherwise (minimal) manual work that would be required when following this approach.
There are two options for getting started:
Installing the plugin is also recommended to make it easier for you to edit the cloze cards, but it isn't required.
Similar to Anki's Cloze Templates, you need a field to contain the cloze content. Out of convention it's a good idea to have the field name end in Cloze in case you want to use the plugin later. Suppose you name it ExpressionCloze
, as suggested in the instructions. Cloze content is entered in this field in a similar way as with Anki's Cloze Templates. The only difference is that instead of the format {{c1::text}}
you use ((c1::text))
. You then need fields to enable each of the cloze cards. So, suppose you want to support three clozes. You would add fields ExpressionCloze1
, ExpressionCloze2
, and ExpressionCloze3
. You enter any text you want into these fields to enable the corresponding cloze card. Out of convention the plugin uses 1
.
For example, suppose you want to create cloze cards for each of the words in the expression Ik heb honger. You would write the fields like so:
For an HTML rendering of this example, see front and back card examples.
Because each of the cloze fields has a non-empty value of 1
, a card will be generated for each of c1
through c3
. If you deleted the 1
from ExpressionCloze3
then a card will be generated for c1
and c2
only.
Let's dig into how this all works. The instructions referenced earlier have the following template for the first cloze card. Notice that the entire content of the front of the card is surrounded by conditional tags based on ExpressionCloze
and ExpressionCloze1
. This means that both fields must be non-empty for the card to be created, due to the way Anki card generation works. So if either of these fields is empty, the corresponding card isn't generated. The ommitted script simply looks at the number the value for data-card
ends with and then updates the content within the cloze <div>
accordingly. So if the value of data-card
is ExpressionCloze2
then it knows to hide the ((c2::text))
and show the others.
{{#ExpressionCloze}}
{{#ExpressionCloze1}}
<div id="cloze" data-card="{{Card}}" data-cloze-show-before="all" data-cloze-show-after="all">
{{ExpressionCloze}}
</div>
{{Meaning}}
<script>
// .. ommitted ...
</script>
{{/ExpressionCloze1}}
{{/ExpressionCloze}}
The templates also support hints in the cloze deletions, as in Anki's system. For example, for the example below, heb
would be replaced with [verb]
instead of [...]
.
((c1::Ik)) ((c2::heb::verb)) ((c3::honger)).
For the full details on how to set up your card templates manually, see the instructions. Alternatively, you can use the shared deck as a starting point and use the instructions as reference in how to modify it to meet your needs.
The template has several settings for controlling how the cloze deletions are rendered. See Configuration for details.
The plugin does two things to make it easier for you to edit cloze deletions when following this approach:
[...]
button in the editor so that you can use it on other notes besides those based on Anki's Cloze type.ExpressionCloze
field (or similarly named field) to the other fields ExpressionCloze1
, ExpressionCloze2
, etc. that enable the corresponding cloze cards.The [...]
button behaves the same when used on one of the note types based on Anki's Cloze type. Otherwise however, if the field name ends in Cloze, like ExpressionCloze
, then it will wrap the selected text, such as in ((c1::text))
. This is the same as Anki's normal behavior with clozes except it uses parentheses instead of curly braces.
The [...]
button has an additonal useful feature where if you press it while an empty field ending in Cloze has focus, it will copy the text from another field with the same name minus the Cloze suffix. For example, if you click the button while focusing on ExpressionCloze
then it will copy the text from Expression
.
You can also modify the cloze field without using the [...]
button. The plugin monitors changes and identifies patterns like ((c1::text))
. It makes the corresponding cloze fields to be either empty or contain 1
depending on the presence of cloze deletions. For example, if you fill in ExpressionCloze
with ((c1::Ik)) ((c2::heb)) ((c3::honger)).
then it will fill in 1
for each of ExpressionCloze1
, ExpressionCloze2
, and ExpressionCloze3
. If you edit it to become ((c1::Ik)) ((c2::heb)) honger.
then it will make ExpressionCloze3
empty.
The plugin adds two actions in the browser under Edit -> Cloze Anything. Both of them operate on whatever notes are selected in the browser.
This automatically makes a cloze from an entire field. For example, suppose you have a field named ExpressionCloze
and Expression
. If ExpressionCloze
is empty, then this action causes the content of Expression
to be copied to ExpressionCloze
and made into a cloze like ((c1::content))
. It also updates ExpressionCloze1
to cause the cloze card to be generated. This is useful when you have a lot of notes with short content where you want to cloze the entire content. It's much more efficient to cloze these in bulk than one by one.
Note that this essentially is using cloze to make a Production card (i.e. given the meaning in your native language, produce the expression in the language you are learning). So why not just make a Production card template instead of using cloze? In some cases this may be more effective than using cloze. However there are a couple reasons why cloze could be useful:
This basically just makes sure the Cloze field is in sync with the corresponding fields responsible for card generation. For example, if ExpressionCloze
has ((c1::Ik)) ((c2::heb)) ((c3::honger)).
then this would ensure ExpressionCloze1
, ExpressionCloze2
, and ExpressionCloze3
are each filled in with a 1
. But ExpressionCloze4
would be made blank, if it exists. This action isn't generally necessary to use while using the plugin because the plugin ensures that these fields are updated as you change content. But if you do an import or if you edit notes before using the plugin, this can be used to fix up the fields to be in sync.
Anki already has built-in support for Cloze. So why use Cloze Anything?
Pros:
Cons:
type:
prefix to enable type in the answer is not supported.The card templates are compatible with Anki Desktop, AnkiMobile, and AnkiDroid.
The plugin works with Anki Desktop 2.1. I have no plans to add 2.0 support.
I have not yet tested interactions of the plugin with other cloze plugins such as Cloze (Hide All) and Cloze Overlapper. If you encounter a problem please file an issue and I will do my best to fix it.
The following plugins have been reported as having compatibility issues with this plugin:
In addition to inspiration drawn from Anki's cloze system itself, there are a couple related Anki cloze plugins that provided some inspiration for features found here. Thanks to all authors for the thought put into Anki and these plugins that have helped develop new ideas.
Copyright 2019-2021 Matthew Hayes
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.