Skip to content

Instantly share code, notes, and snippets.

@silas
Created June 20, 2019 15:15
Show Gist options
  • Save silas/3d28414a3ef27890603fc9c26348cf2f to your computer and use it in GitHub Desktop.
Save silas/3d28414a3ef27890603fc9c26348cf2f to your computer and use it in GitHub Desktop.
Anki JavaScript Cards

Anki JavaScript Cards

This demonstrates one method for creating JavaScript based Anki cards.

Tested on

Instructions

  1. Ensure you have synchronized all your Anki clients
  2. Open Anki for desktop computers
  3. Click Create Deck
  4. Enter Test for the desk name and click OK
  5. Click the Test deck
  6. Click Add
  7. Click the Type button
  8. Click ManageAdd
  9. Select Clone: Basic and click OK
  10. Enter Script for Name and click OK
  11. Close the window
  12. Select Script and click Choose
  13. Click Cards...
  14. Enter the following for Front Template:
    <div id="front" class="card">Loading front...</div>
    
    <script>
    var code = (function () {/* {{Front}} */}).toString();
    code = code.slice(16, code.length - 4);
    eval(new DOMParser().parseFromString(code, "text/html").documentElement.textContent);
    </script>
    NOTE: You can ignore the "Invalid HTML on card: ReferenceError: Front is not defined" error.
  15. Enter the following for Back Template (ignore the "Invalid HTML on card: ReferenceError: Back is not defined" error):
    <div id="back" class="card">Loading back...</div>
    
    <script>
    var code = (function () {/* {{Back}} */}).toString();
    code = code.slice(16, code.length - 4);
    eval(new DOMParser().parseFromString(code, "text/html").documentElement.textContent);
    </script>
    NOTE: You can ignore the "Invalid HTML on card: ReferenceError: Back is not defined" error.
  16. Click Close
  17. Enter the following for Front:
    window.now = new Date();
    
    document.getElementById('front').innerHTML = 'What is the current year?';
  18. Enter the following for Back:
    document.getElementById('back').innerHTML = 'Current year: ' + window.now.getFullYear();
  19. Click Add
  20. Click Close
  21. Click Study NowShow Answer
@williamblair333
Copy link

williamblair333 commented Jul 23, 2022

For new people like me, here is how you do it:
On the Front Template do this:

<script>
  var code = (function () {/* {{Front}} */}).toString();
  code = code.slice(16, code.length - 4);
  eval(new DOMParser().parseFromString(code, "text/html").documentElement.textContent);
</script>

{{#Front}}
 <div id="front" class="card">Loading front...</div>
{{/Front}}

On the Back Template do this:

{{FrontSide}}

<hr id=answer>

<script>
  var code = (function () {/* {{Back}} */}).toString();
  code = code.slice(16, code.length - 4);
  eval(new DOMParser().parseFromString(code, "text/html").documentElement.textContent);
</script>

{{#Back}}
  <div id="back" class="card">Loading back...</div>
{{/Back}}

@samishal1998
Copy link

samishal1998 commented Apr 7, 2023

Even though this method works it seems kinda weird, given that the html+js framework already has many methods for passing data.

  1. You could escape the text and pass it in attributes, which could be retrieved later.
<div id="front" class="card" data="{{Front}}">Loading front...</div>

<script>
  var code =  unescape(document.getElementById("front").getAttribute("data"));
  eval(code);
</script>
  1. You could use the script tag with any type other than js to pass text
<div id="front" class="card" >Loading front...</div>

<script id="code" type="text">
{{Front}}
</script>

<script>
  var code = document.getElementById("code").innerText;
  eval(code);
</script>
  1. You could even use a random tag given that you make it hidden
<div id="front" class="card" >Loading front...</div>

<data id="code" style="display:none;">
{{Front}}
</data>

<script>
  var code = document.getElementById("code").innerText;
  eval(code);
</script>

This is especially beneficial with JSON data. Lately, I've been making cards that require some fields to be arrays, and Anki doesn't support arrays (not that I know of).
** You could also use jQuery depending on the platform.

@ogallagher
Copy link

ogallagher commented Feb 3, 2024

For the the content of the <script> tag in the card template, I was unable to use variable declaration keywords (ex. var, let) without wrapping the script body in a function to nest in scope.

<script>
// nest in scope by executing anonymous function
(function () {
  var code = document.getElementById('code').innerText
  eval(code)
})()
</script>

@samishal1998
Copy link

For the the content of the <script> tag in the card template, I was unable to use variable declaration keywords (ex. var, let) without wrapping the script body in a function to nest in scope.

<script>
// nest in scope by executing anonymous function
(function () {
  var code = document.getElementById('code').innerText
  eval(code)
})()
</script>

That's weird it worked fine on my side. anyways, using an IIFE is a good solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment