AnkiWeb
- Rating
- 2 (π 1 Β· π 1)
- Updated
- 2020-09-01
- Anki versions
- 2.1.41~
- Description language
- en
AnkiWeb addon 1051511270
Persists data between an Anki card's front and back, enabling consistent random values, shuffled elements, or user input, but is deprecated and requires Asset Manager.
Open on AnkiWeb GitHub Ask about alternatives
abandoned
| Min Anki | Max Anki | Updated |
|---|---|---|
| 2.1.31 | 2.1.41+ | 2020-09-01 |
Loadingβ¦
Persists specified localStorage data across Anki restarts by saving it to a media file and reloading it on the first reviewed card, with mobile read-only support.
Adds multiple choice, single choice, and Kprim cards to Anki with answer fields, automatic styling, configurable coloring, and cross-platform review.
Rewrites math-card placeholder variables into visually distinct symbols, storing rendered front/back results in notes and randomizing each note at most once daily for cross-device syncing.
Creates a note type for matching concepts to definitions, with shuffled definitions, numbered dropdown answers, and green/red answer highlighting after Show Answer.
Adds fast two- or three-column matching review mode to Anki, with scheduler/FSRS integration, configurable audio, and separate zero-progress Speedrun Mode for whole-deck challenges.
Keeps the review editor window persistent, obscuring fields on front and revealing them on back, with shortcuts and presentation mode.
Persist data between both sides of an anki flashcard.
While the following example explicitly shows the random number, it could instead be used internally to do many different things:
It could also be used completely different as well. To let the user input something on the frontside and use that same input on the backside for example.
This example shows how anki-persistence can be used to display the same random number on both sides of an Anki flash card. All of these images depict the same card! You can try it out yourself with this exported Anki deck.
| Client | Front | Back |
|---|---|---|
| Web | ![]() |
![]() |
| Android | ![]() |
![]() |
| Android (card preview) | ![]() |
![]() |
| iOS | ![]() |
![]() |
| iOS (card preview) | ![]() |
![]() |
| Mac | ![]() |
![]() |
| Mac (card preview) | ![]() |
![]() |
| Mac (card type editor preview) | ![]() |
![]() |
| Windows | ![]() |
![]() |
| Windows (card preview) | ![]() |
![]() |
| Windows (card type editor preview) | ![]() |
![]() |
| Linux | ![]() |
![]() |
| Linux (card preview) | ![]() |
![]() |
| Linux (card type editor preview) | ![]() |
![]() |
The most powerful feature of this project is that you can check availability of persistence on the front side - there should never be a case where Persistence.isAvailable() returns true on the front- and false on the backside (if there is, please create a bug report, so it can be fixed as soon as possible).
The shown example chooses 0.4 as default value - to be overwritten if Persistence.isAvailable returns true (which is not the case for desktop client previews).
<script>
// v0.5.2 - https://github.com/SimonLammer/anki-persistence/blob/62463a7f63e79ce12f7a622a8ca0beb4c1c5d556/script.js
if(void 0===window.Persistence){var _persistenceKey="github.com/SimonLammer/anki-persistence/",_defaultKey="_default";if(window.Persistence_sessionStorage=function(){var e=!1;try{"object"==typeof window.sessionStorage&&(e=!0,this.clear=function(){for(var e=0;e<sessionStorage.length;e++){var t=sessionStorage.key(e);0==t.indexOf(_persistenceKey)&&(sessionStorage.removeItem(t),e--)}},this.setItem=function(e,t){void 0==t&&(t=e,e=_defaultKey),sessionStorage.setItem(_persistenceKey+e,JSON.stringify(t))},this.getItem=function(e){return void 0==e&&(e=_defaultKey),JSON.parse(sessionStorage.getItem(_persistenceKey+e))},this.removeItem=function(e){void 0==e&&(e=_defaultKey),sessionStorage.removeItem(_persistenceKey+e)})}catch(e){}this.isAvailable=function(){return e}},window.Persistence_windowKey=function(e){var t=window[e],i=!1;"object"==typeof t&&(i=!0,this.clear=function(){t[_persistenceKey]={}},this.setItem=function(e,i){void 0==i&&(i=e,e=_defaultKey),t[_persistenceKey][e]=i},this.getItem=function(e){return void 0==e&&(e=_defaultKey),t[_persistenceKey][e]||null},this.removeItem=function(e){void 0==e&&(e=_defaultKey),delete t[_persistenceKey][e]},void 0==t[_persistenceKey]&&this.clear()),this.isAvailable=function(){return i}},window.Persistence=new Persistence_sessionStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var titleStartIndex=window.location.toString().indexOf("title"),titleContentIndex=window.location.toString().indexOf("main",titleStartIndex);titleStartIndex>0&&titleContentIndex>0&&titleContentIndex-titleStartIndex<10&&(window.Persistence=new Persistence_windowKey("qt"))}}
</script>
{{Front}}
<div id="front"></div>
<script>
var number = 0.4; // Default to 0.4.
if (Persistence.isAvailable()) { // Check whether Persistence works on the client.
number = Persistence.getItem(); // Retrieve a previously stored number and override the default. (In case this is executed on the backside as well by {{FrontSide}})
if (number == null) { // If there was no number stored previously:
number = Math.random(); // 1. Create a random number and override the default.
Persistence.setItem(number); // 2. Store that number
}
}
window.front.appendChild(document.createTextNode(number)); // Print the number.
</script>
<script>
// v0.5.2 - https://github.com/SimonLammer/anki-persistence/blob/62463a7f63e79ce12f7a622a8ca0beb4c1c5d556/script.js
if(void 0===window.Persistence){var _persistenceKey="github.com/SimonLammer/anki-persistence/",_defaultKey="_default";if(window.Persistence_sessionStorage=function(){var e=!1;try{"object"==typeof window.sessionStorage&&(e=!0,this.clear=function(){for(var e=0;e<sessionStorage.length;e++){var t=sessionStorage.key(e);0==t.indexOf(_persistenceKey)&&(sessionStorage.removeItem(t),e--)}},this.setItem=function(e,t){void 0==t&&(t=e,e=_defaultKey),sessionStorage.setItem(_persistenceKey+e,JSON.stringify(t))},this.getItem=function(e){return void 0==e&&(e=_defaultKey),JSON.parse(sessionStorage.getItem(_persistenceKey+e))},this.removeItem=function(e){void 0==e&&(e=_defaultKey),sessionStorage.removeItem(_persistenceKey+e)})}catch(e){}this.isAvailable=function(){return e}},window.Persistence_windowKey=function(e){var t=window[e],i=!1;"object"==typeof t&&(i=!0,this.clear=function(){t[_persistenceKey]={}},this.setItem=function(e,i){void 0==i&&(i=e,e=_defaultKey),t[_persistenceKey][e]=i},this.getItem=function(e){return void 0==e&&(e=_defaultKey),t[_persistenceKey][e]||null},this.removeItem=function(e){void 0==e&&(e=_defaultKey),delete t[_persistenceKey][e]},void 0==t[_persistenceKey]&&this.clear()),this.isAvailable=function(){return i}},window.Persistence=new Persistence_sessionStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var titleStartIndex=window.location.toString().indexOf("title"),titleContentIndex=window.location.toString().indexOf("main",titleStartIndex);titleStartIndex>0&&titleContentIndex>0&&titleContentIndex-titleStartIndex<10&&(window.Persistence=new Persistence_windowKey("qt"))}}
</script>
{{Back}}
<div id="back"></dv>
<script>
var number = 0.4; // Default to 0.4.
if (Persistence.isAvailable()) { // Check whether Persistence works on the client.
number = Persistence.getItem(); // Retrieve the previously stored number and override the default.
Persistence.clear(); // Clear the storage, so a new random number will be created on the next card.
}
window.back.appendChild(document.createTextNode(number)); // Print the number.
</script>
The note has two fields: Front and Back.
These are set to front and back respectively.
To use anki-persistense, follow these steps:
minified.js) is recommended, in order to save space in the anki card type. (A link to the non-minified version is always added to the file, in case someone wants to look at the human-readable code.)<script> and </script>.This can be seen in the example setup.
Anki clients vary in their implementation and JavaScript can behave differently in each one. Therefore, check for availability before using other Persistence methods.
if (Persistence.isAvailable()) {
// do stuff
}
Other methods:
| Name | Description |
|---|---|
Persistence.clear() |
Removes all previously persisted key-value pairs. |
Persistence.getItem(key) |
Retrieves the value associated with the key. If no value is associated to the given key, null is returned. |
Persistence.getItem() |
Retrieves the value associated with a default key. |
Persistence.setItem(key, value) |
Persists the key-value pair. |
Persistence.setItem(value) |
Persists the value using a default key. |
Persistence.removeItem(key) |
Removes the value associated with the key. If no value is associated to the given key, nothing happens. |
Persistence.removeItem() |
Removes the value associated with a default key. |
key may be any string.
Some implementations of Persistence may use JSON.stringify and JSON.parse in the process of persisting and retrieving data. If you plan on persisting a custom object, make sure that obj equals JSON.parse(JSON.stringify(obj)).
Persistence.setItem may persist data across cards, this should be stopped by calling Persistence.clear() at the end of the backside. (If this gets called on the frontside's beginning instead, you cannot use anki's {{FrontSide}} special field in the backside - because doing so would delete the persisted data)
There are two separate internal implementations of Persistence: Persistence_sessionStorage and Persistence_windowKey. The former uses the sessionStorage property, while the latter attaches a new property to an existing persistent (not changing between front- and backside of an anki flashcard) property of the window object and uses that attached property to persist and retrieve data.
Anki's android client has no persistent window properties, so the internal implementation of choice is obviously Persistence_sessionStorage. The desktop clients don't permit the sessionStorage property, so Persistence_windowKey is used.
Additional thought is required for linux and mac 2.1 clients. The window property, which is persistent in review mode, is present - but not persistent - in the preview modes. window.location helps us circumvent this issue, as it contains html, which only specifies title as main webview in review mode.
Huge thanks to