JavaScript работает в версии 2.0 Anki, но не в версии 2.1
Я использую Анки, чтобы помочь сыну 5-го класса изучать математику. Мой сын достиг того момента, когда ему нужно проанализировать, как подходить к конкретным проблемам, а не просто запомнить факты.
Например, представьте, что вы пытаетесь научиться умножать дроби... .45 X .61 =?
Мне нужен был способ поместить случайные математические вопросы в карту Anki. Это означает, что однажды карта отобразит.45 X.61 =? В следующий раз, когда карта будет отображаться, вопрос может быть.. .34 X .12 =?
Поискав в интернете, я смог найти статью, которая объясняет, как это сделать...
https://yingtongli.me/blog/2015/03/15/random-question-generator-on-anki-using.html
Я не разработчик JavaScript, но я смог заставить эту технику работать после того, как в течение недели бился головой о клавиатуру.
Позвольте мне объяснить, как вы это делаете, а затем я объясню, где проблема.
Установите версию Анки 2.0.
Откройте Anki и создайте новую колоду.
Добавьте новую карту в колоду.
Откроется диалоговое окно добавления карты. В самом верху две длинные кнопки... "Тип" и "Палуба". Нажмите на кнопку "Тип" слева.
Откроется диалоговое окно "Выбор типа заметки".
Нажмите на кнопку "Управление" в нижней части диалогового окна.
Выберите основной тип заметки и нажмите кнопку "Добавить" слева.
Первый вариант должен быть "Добавить базовый". Нажмите кнопку "ОК" в нижней части диалогового окна.
Назовите новый тип заметки. "Тип заметки со сценарием", затем нажмите "ОК"
Хит бежать.
Теперь выберите новый тип заметки ("Тип заметки со сценарием") и нажмите "Выбрать".
Теперь мы хотим добавить дополнительное поле. По умолчанию этот тип заметки имеет поля с именами "Front" и "Back". Мы хотим добавить третье поле с именем "Скрипт".
Вверху слева есть кнопка с надписью "Поля". Нажмите на эту кнопку.
Появится другое диалоговое окно. Слева находится кнопка Добавить. Нажмите на это.
Введите Script в появившемся диалоговом окне и нажмите кнопку "ОК".
Теперь закройте текущее диалоговое окно, нажав кнопку закрытия рядом с кнопкой в правой части.
Давайте настроим наши карты сейчас. В левом верхнем углу текущего экрана находятся две кнопки. Кнопка справа обозначена надписью "Карты". Нажмите эту кнопку.
Здесь мы настраиваем шаблон карты. Одна часть кода JavaScript входит в шаблон Front. Здесь должен быть следующий текст...
{{Фронт}}
Удалите все и вставьте следующий код.
<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(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); //Replace special symbols.
eval(code);
</script>
<div id="front">{{Front}}</div>
Этот JavaScript берет код JavaScrippt, который мы поместим в поле "Сценарий", и выполняет его с помощью оператора eval.
Обратите внимание на то, что в этом коде функция постоянства поддерживает постоянные значения между лицевой и обратной сторонами карты Anki. Моя проблема связана с этой сохраняющейся функцией.
В нижней трети экрана находится "Задний шаблон". Удалите все и вставьте следующий код...
{{FrontSide}}
<hr id=answer>
<div id="back">{{Back}}</div>
В правом нижнем углу нажмите кнопку "Закрыть".
Теперь нам нужно заполнить поля. Значения спереди и сзади не имеют значения. Я поставил "Фронт" спереди и "Назад" сзади.
Для поля "Сценарий" мы хотим добавить некоторый код. Нам нужно открыть представление HTML, прежде чем вставлять код. Убедитесь, что ваш курсор находится в полях Script.
В версии 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);
Это работает в версии 2.0 Anki.
Вот вопрос
И вот ответ...
Мы сгенерировали случайное число в JavaScript, и это значение сохраняется между передней и задней частью карты Anki. Это открывает множество возможностей для карт математики и естественных наук Анки, использующих случайные числа.
Тем не менее, не все хорошо в Whoville.
Когда вы запускаете этот код на версии 2.1 Anki, он не работает.
Сценарий обходится, и отображаются статические значения полей Front и Back.
JavaScript все еще выполняется. Я мог бы поставить предупреждение в поле "Сценарий", и оно работает.
Проблема в персистентной функции. Новая версия Anki не нравится в функции Persist.
Может кто-то указать мне верное направление.
3 ответа
Проверить https://github.com/SimonLammer/anki-persistence Для достижения постоянства используются разные подходы.
Но среда Anki несколько непредсказуема, и вам нужно проверить, успешно ли инициализирован код.
Я понял...
Проблема в том, что Anki 2.1 исключил возможность хранить постоянные данные в объекте window.py.
Теперь вы можете спросить (как и я), что такое объект window.py? Я не уверен на 100%, но я считаю, что это внутренний объект Python, который допускает некоторые взаимодействия между JavaScript и Python. Анки написана на Python.
В любом случае window.py больше не доступен в Anki 2.1, что означает, что метод, который я описал в моем вопросе (см. Выше), больше не работает в Anki 2.1.
К счастью, автор статьи (ссылка на которую приведена выше в вопросе) упомянул, что объект window является общим для вызовов вопроса и ответа карты Anki.
Я начал играть с объектом окна в Javascript, и я смог получить постоянство данных, работая в Anki 2.1 (это также работает в Anki 2.0)
В приведенном выше вопросе я углубляюсь в эту технику, чтобы генерировать постоянные случайные значения в ваших картах Anki. Это означает, что вы генерируете случайное число в вопросе, и те же значения доступны в ответе. Я не буду вдаваться в подробности здесь, но обратитесь к вопросу выше для более подробной информации.
В "Front Template" есть код.
<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(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); //Replace special symbols.
eval(code);
</script>
<div id="front">{{Front}}</div>
Это тот же код из статьи. Я просто удалил код, который больше не работает.
Вот код скрипта карты...
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);
Этот код работает только на рабочем столе Anki 2.1. Я также проверил iOS, и она работает там же.
Я надеюсь, что это помогает кому-то еще.
Рад слышать, что вы нашли решение, codingguy.
Для получения дополнительной информации, я хочу добавить, что в 2014 году у меня была та же идея. Я заставил ее работать, используя JavaScript и Cookies в своих шаблонах заметок.
Для этого мне пришлось модифицировать Anki с помощью плагина (для создания обезьяны-патча в Qt Web View), которым я поделился как плагин Anki 2.0 JS Booster. Адаптированный для Anki 2.1, другой разработчик опубликовал то же самое решение здесь, плагин Anki 2.1 Cookie Monster.