JavaScript 在 Anki 2.0 版本中有效,但在 2.1 版本中无效

cod*_*000 2 javascript anki

我正在使用 Anki 帮助我 5 年级的儿子学习数学。我的儿子已经到了需要回顾如何解决具体问题而不是简单地记住事实的地步。

例如,假设您正在尝试学习如何乘以分数... .45 X .61 = ?

我需要一种将随机数学问题放入 Anki 卡片的方法。这意味着有一天卡片会显示 0.45 X .61 = ? 下次显示卡片时,问题可能是... .34 X .12 = ?

在网上搜索之后,我找到了一篇解释如何做到这一点的文章......

https://yingtongli.me/blog/2015/03/15/random-question-generator-on-anki-using.html
Run Code Online (Sandbox Code Playgroud)

我不是 JavaScript 开发人员,但在我的头敲击键盘一周后,我能够使这项技术发挥作用。

让我解释你如何做到这一点,然后我会解释问题出在哪里。

安装 Anki 2.0 版本。

打开 Anki 并创建一个新牌组。

将一张新卡添加到牌组中。

出现添加卡片对话框。最顶部是两个长按钮......“类型”和“甲板”。单击左侧的“类型”按钮。

出现选择笔记类型对话框。

单击对话框底部的“管理”按钮。

选择基本笔记类型,然后单击左侧的“添加”按钮。

第一个选项应该是“添加基本”。单击对话框底部的“确定”按钮。

命名您的新笔记类型..“脚本笔记类型”,然后单击“确定”

命中逃生。

现在选择您的新笔记类型(“脚本笔记类型”),然后单击“选择”。

现在我们要添加一个额外的字段。默认情况下,此笔记类型具有名为“前”和“后”的字段。我们要添加名为“Script”的第三个字段。

左上角附近有一个标记为“字段”的按钮。单击此按钮。

出现另一个对话框。左侧是添加按钮。点击它。

在出现的对话框中输入脚本,然后单击“确定”按钮。

现在通过单击右侧按钮附近的关闭按钮关闭当前对话框。

现在让我们设置我们的卡片。当前屏幕左上角附近有两个按钮。右侧的按钮标有“卡片”。单击此按钮。

这是我们设置卡片模板的地方。JavaScript 代码的一部分进入前端模板。目前这里应该有以下文字...

{{正面}}

删除所有内容并粘贴以下代码。

<script>

function persist(cb) {
    window.setTimeout(function() {
        // Determine whether to use Anki's Bridge object (Desktop) or sessionStorage (AnkiDroid) to store data across sides.
        var dummy = {};

        var mode = "dummy";
        if (typeof(py) !== "undefined") {
            mode = "py";
            py.data = py.data || {};
        } else if (typeof(sessionStorage) !== "undefined") {
            mode = "sessionStorage";
        }

        var dataObj = {
            setItem: function(key, val) {
                if (mode === "dummy") {
                    dummy[key] = val;
                } else if (mode === "py") {
                    py.data[key] = val;
                } else if (mode === "sessionStorage") {
                    sessionStorage.setItem(key, val);
                }
            },
            getItem: function(key, def) {
                var val = undefined;
                if (mode === "dummy") {
                    val = dummy[key];
                } else if (mode === "py") {
                    val = py.data[key];
                } else if (mode === "sessionStorage") {
                    val = sessionStorage.getItem(key);
                }
                if (val == null) {
                    return def;
                } else {
                    return val;
                }
            },
            tryItem: function(key, val) {
                var currVal = dataObj.getItem(key, undefined);
                if (currVal == null) {
                    dataObj.setItem(key, val);
                    return val;
                } else {
                    return currVal;
                }
            },
            clear: function() {
                if (mode === "dummy") {
                    dummy = {};
                } else if (mode === "py") {
                    window.py.data = {};
                } else if (mode === "sessionStorage") {
                    sessionStorage.clear();
                }
            }
        };

        if (!document.getElementById("back")) {
            dataObj.clear();
        }

        cb(dataObj);
    }, 0); //Execute after Anki has loaded its Bridge object.
}

</script>

<script>

var code = (function () {/* {{Script}} */}).toString();
code = code.replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, ""); //Strip beginning/ending comments.
code = code.replace(/<div>/g, "\n").replace(/<\/div>/g, "\n").replace(/<br \/>/g, "\n"); //Strip HTML.
code = code.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&"); //Replace special symbols.
eval(code);
</script>

<div id="front">{{Front}}</div>
Run Code Online (Sandbox Code Playgroud)

该 JavaScript 获取我们将放置在“脚本”字段中的 JavaScrippt 代码,并使用 eval 语句执行它。

注意这段代码中的 persist 函数,它使 Anki 卡的正面和背面的值保持一致。我的问题与此持久功能有关。

屏幕底部三分之一是“背景模板”。删除所有内容并粘贴以下代码...

  {{FrontSide}}

<hr id=answer>

<div id="back">{{Back}}</div>
Run Code Online (Sandbox Code Playgroud)

单击右下角的“关闭”按钮。

现在我们需要填写字段。前面和后面的值无关紧要。我把“前面”放在前面,把“后面”放在后面。

对于 Script 字段,我们要添加一些代码。在粘贴代码之前,我们需要打开 HTML 视图。确保您的光标位于脚本字段中。

在 Anki 2.0 版本中,屏幕右上方有一个带有向下箭头图片的按钮。2.1 版本有“...”而不是向下箭头按钮。

单击此箭头,将出现一个菜单。选择“编辑 HTML”菜单选项。

粘贴以下代码...

window.setTimeout(function(){

persist(function(data) {


var num1 = data.tryItem("num1",Math.random());


document.getElementById("front").innerHTML = num1; 
document.getElementById("back").innerHTML = num1;
});

},0);
Run Code Online (Sandbox Code Playgroud)

这适用于 Anki 2.0 版本。

这是问题

问题

这是答案......

答案

我们在 JavaScript 中生成了一个随机数,并且该值保留在 Anki Card 的正面和背面之间。这为使用随机数的数学和科学 Anki 卡开辟了可能性世界。

然而,Whoville 的情况并不好。

当您在 Anki 2.1 版本上运行此代码时,它不起作用。

Anki 2.1 错误

该脚本被绕过,并显示 Front 和 Back 字段的静态值。

JavaScript 仍在执行中。我可以在 Script 字段中放置一个警报语句并且它可以工作。

问题出在 Persist 函数中。较新版本的 Anki 不喜欢 Persist 功能。

任何人都可以指出我正确的方向。

cod*_*000 7

我想到了...

问题在于 Anki 2.1 消除了在 window.py 对象中存储持久数据的能力。

现在你可能会问(和我一样)window.py 对象是什么?我不是 100% 确定,但我相信它是一个内部 Python 对象,允许 JavaScript 和 Python 之间进行一些交互。Anki 是用 Python 编写的。

在任何情况下,window.py 在 Anki 2.1 中都不再可用,这意味着我在我的问题(见上文)中描述的技术在 Anki 2.1 中不再适用。

幸运的是,文章作者(在上面的问题中引用)提到,窗口对象在 Anki 卡片问答的调用之间共享。

我开始在 Javascript 中使用 window 对象,并且能够在 Anki 2.1 中获得数据持久性(这也适用于 Anki 2.0)

在上面的问题中,我深入研究了这种在 Anki 卡中生成持久随机值的技术。这意味着您在问题中生成了一个随机数,并且答案中提供了相同的值。我不会在这里详细介绍,但请参阅上面的问题以获取更多详细信息。

在“前模板”中,这里是代码。

    <script>    
        var code = (function () {/* {{Script}} */}).toString();    
        code = code.replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, ""); //Strip beginning/ending comments.

        code = code.replace(/<div>/g, "\n").replace(/<\/div>/g, "\n").replace(/<br \/>/g, "\n"); //Strip HTML.

        code = code.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&"); //Replace special symbols.

        eval(code);

    </script>    
<div id="front">{{Front}}</div>
Run Code Online (Sandbox Code Playgroud)

这与文章中的代码相同。我只是删除了一些不再有效的代码。

这是卡片脚本代码...

window.setTimeout(function(){     

var windowsref = window; //Set a reference to the window object     

if ((("num1" in windowsref) == false) || windowsref.cnt != 1) {

            windowsref.num1 = Math.random();

            windowsref.cnt = 0;

   }      

windowsref.cnt++;

document.getElementById("front").innerHTML = windowsref.num1;

document.getElementById("back").innerHTML = windowsref.num1;     

},0);
Run Code Online (Sandbox Code Playgroud)

此代码仅适用于 Anki 2.1 桌面。我还测试了 iOS,它也可以在那里工作。

我希望这对其他人有帮助。