<script>
// Loading Persistence
// https://github.com/SimonLammer/anki-persistence
// 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>
{{#Title}}<h3 id="myH1">{{Title}}</h3>{{/Title}}
{{#Question}}<p>{{Question}}</p>{{/Question}}
<div class="tappable">
<table style="border: 1px solid black" id="qtable"></table>
</div>
<div class="hidden" id="Q_solutions">{{Answers}}</div>
<div class="hidden" id="Card_Type">{{QType (0=kprim,1=mc,2=sc)}}</div>
<div class="hidden" id="Q_1">{{Q_1}}</div>
<div class="hidden" id="Q_2">{{Q_2}}</div>
<div class="hidden" id="Q_3">{{Q_3}}</div>
<div class="hidden" id="Q_4">{{Q_4}}</div>
<div class="hidden" id="Q_5">{{Q_5}}</div>
<script>
// Generate the table depending on the type.
function generateTable() {
// Options are modified according to user's meta.json in the addon's folder
const OPTIONS = {
maxQuestionsToShow: 0
};
var type = document.getElementById("Card_Type").innerHTML;
var table = document.createElement("table");
var tbody = document.createElement("tbody");
if (type == 0) {
tbody.innerHTML = '<tr><th>yes</th><th>no</th><th></th></tr>';
}
stripHtmlTagsFromSolutionString();
let solutions = getCorrectAnswers();
let questionTableHtmlLinesToSolution = []
for (var i = 0; true; i++) {
let questionElement = document.getElementById('Q_' + (i + 1));
if (questionElement && questionElement.innerHTML.trim() !== '') {
var html = [];
let answerText = questionElement.innerHTML;
let labelTag = (type == 0) ? '' : '<label for="inputQuestion' + (i + 1) + '">' + answerText + '</label>';
let textAlign = (type == 0) ? 'center' : 'left';
html.push('<tr>');
var maxColumns = ((type == 0) ? 2 : 1);
for (var j = 0; j < maxColumns; j++) {
let inputTag = '<input id="inputQuestion' + (i + 1) +
'" name="ans_' + ((type != 2) ? (i + 1) : 'A') +
'" type="' + ((type == 1) ? 'checkbox' : 'radio') +
'" value="' + ((j == 0) ? 1 : 0) + '">';
html.push(
'<td onInput="onCheck()" style="text-align: ' + textAlign + '">' + inputTag + labelTag + '</td>');
}
if (type == 0) {
html.push('<td>' + answerText + '</td>');
}
html.push('</tr>');
questionTableHtmlLinesToSolution.push({
html: html.join(""),
solution: solutions[i] || 0 // 解答がない場合は0を設定
});
} else {
console.log('No more questions found. Stopping loop.');
break;
}
}
let shuffledQuestionTableHtmlLinesToSolution = getShuffledQuestionTableHtmlLinesToSolution(
questionTableHtmlLinesToSolution, type, OPTIONS['maxQuestionsToShow']);
let shuffledHtmlLines = shuffledQuestionTableHtmlLinesToSolution
.map(o => o.html)
.join("");
let shuffledSolutions = shuffledQuestionTableHtmlLinesToSolution
.map(o => o.solution);
tbody.innerHTML += shuffledHtmlLines;
table.appendChild(tbody);
document.getElementById('qtable').innerHTML = table.innerHTML;
storeCorrectAnswersInHtml(shuffledSolutions)
onCheck(); // store user answers at least once in case nothing was ticked
}
function stripHtmlTagsFromSolutionString() {
let solutionString = document.getElementById("Q_solutions").innerHTML;
document.getElementById("Q_solutions").innerHTML = solutionString.replace(/(<([^>]+)>)/gi, "");
}
/**
* Returns the shuffled and potentially reduced lines of HTML combined with their solution value
*
* In case of single choice it is guaranteed that the correct answer is shuffled in
* between the wrong ones.
*
* @param {questionTableHtmlLinesToSolution} Array[Object] objects containing the
* properties 'html' and 'solution'
* @param {type} int Card type
* @param {maxQuestionsToShow} int see config options
*/
function getShuffledQuestionTableHtmlLinesToSolution(
questionTableHtmlLinesToSolution, type, maxQuestionsToShow) {
if (type != 2) {
shuffledQuestionTableHtmlLinesToSolution = questionTableHtmlLinesToSolution.sort(
() => Math.random() < 0.5 ? -1 : 1);
if (maxQuestionsToShow > 1) {
return shuffledQuestionTableHtmlLinesToSolution.slice(0, maxQuestionsToShow);
} else {
return shuffledQuestionTableHtmlLinesToSolution;
}
} else {
// To have the single correct answer randomly inserted into the wrong ones
let correctAnswer = questionTableHtmlLinesToSolution.find(o => o.solution == 1);
let wrongAnswers = questionTableHtmlLinesToSolution.filter(o => o.solution == 0);
wrongAnswers.sort(() => Math.random() < 0.5 ? -1 : 1);
if (maxQuestionsToShow > 1) {
wrongAnswers = wrongAnswers.slice(0, maxQuestionsToShow - 1);
}
let randomIndex = Math.floor(Math.random() * (wrongAnswers.length + 1));
wrongAnswers.splice(randomIndex, 0, correctAnswer);
return wrongAnswers;
}
}
/**
* Returns true if the option box/circle is checked.
*
* In case of kprim the second box is used as reference.
*
* @param {HTMLTableRowElement} optionRow Row containing option boxes/circles.
* @param {number} index Index of the option in question.
*/
function isOptionChecked(optionRow, index) {
return optionRow.getElementsByTagName("td")[index].getElementsByTagName("input")[0].checked
}
function getUserAnswers() {
let type = document.getElementById("Card_Type").innerHTML;
let qrows = document.getElementById("qtable").getElementsByTagName('tbody')[0].getElementsByTagName("tr");
let userAnswers = [];
for (let i = 0; i < qrows.length; i++) {
if (type == 0 && i == 0) {
i++; // to skip the first row containing no checkboxes when type is 'kprim'
}
if (type == 0) {
if (isOptionChecked(qrows[i], 0)) {
userAnswers.push(1);
} else if (isOptionChecked(qrows[i], 1)) {
userAnswers.push(0);
} else {
userAnswers.push(2);
}
} else {
if (isOptionChecked(qrows[i], 0)) {
userAnswers.push(1);
} else {
userAnswers.push(0);
}
}
}
return userAnswers
}
/**
* Get the solutions stored in the hidden div with id "Q_solutions" as Array.
*/
function getCorrectAnswers() {
let solutions = document.getElementById("Q_solutions").innerHTML.split(" ").map(string => Number(string));
return solutions;
}
function storeCorrectAnswersInHtml(solutions) {
document.getElementById("Q_solutions").innerHTML = solutions.join(" ");
}
/**
* On checking an option this collects and stores answers in between front/back of the card.
*
* In case of kprim only the first box is looked at, if it isn't checked the second box has to be.
* By default a '1' in the answers stands for 'yes' which is the first option from the left.
*/
function onCheck() {
// Send question table and encoded answers to Persistence along with the provided solutions
if (Persistence.isAvailable()) {
Persistence.clear();
Persistence.setItem('user_answers', getUserAnswers());
Persistence.setItem('Q_solutions', getCorrectAnswers());
Persistence.setItem('qtable', document.getElementById("qtable").innerHTML);
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function tickCheckboxOnNumberKeyDown(event) {
const keyName = event.key;
let tableBody = document.getElementById("qtable").getElementsByTagName('tbody')[0];
var tableRows = tableBody.getElementsByTagName("tr");
if (0 < +keyName && +keyName < 10) {
let tableData = tableRows[+keyName - 1].getElementsByTagName("td")[0];
let tableRow = tableData.getElementsByTagName("input")[0];
tableRow.checked = !tableRow.checked;
onCheck();
}
}
// addCheckboxTickingShortcuts is an easy approach on using only the keyboard to toggle checkboxes in mc/sc.
//
// Naturally the number keys are an intuitive choice here. Unfortunately anki does capture those.
// So the workaround is to hold the (left) 'Alt' key and then type the corresponding number to toggle the row.
function addCheckboxTickingShortcuts() {
document.addEventListener('keydown', tickCheckboxOnNumberKeyDown, false);
}
function isMobile() {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
return true;
} else {
return false;
}
}
function run() {
// for previewing the cards in "Manage Note Type..."
let DEFAULT_CARD_TYPE = 1;
let DEFAULT_SOLUTIONS = "1 0 0 0 0";
if (isNaN(document.getElementById("Card_Type").innerHTML)) {
document.getElementById("Card_Type").innerHTML = DEFAULT_CARD_TYPE;
}
if ('{' + '{Answers}' + '}' == document.getElementById("Q_solutions").innerHTML) {
document.getElementById("Q_solutions").innerHTML = DEFAULT_SOLUTIONS;
}
if (document.getElementById("Card_Type").innerHTML != 0 && !isMobile()) {
addCheckboxTickingShortcuts();
}
setTimeout(generateTable(), 1);
}
async function waitForReadyStateAndRun() {
for (let i = 0; i < 100; i++) {
if (document.readyState === "complete") {
run();
break;
}
console.log("Document not yet fully loaded (readyState: " + document.readyState + "). Retry in 0.1s.");
await sleep(100);
}
}
/*
The following block is inspired by Glutanimate's Cloze Overlapper card template.
The Cloze Overlapper card template is licensed under the CC BY-SA 4.0
license (https://creativecommons.org/licenses/by-sa/4.0/).
*/
if (document.readyState === "complete") {
run();
} else {
waitForReadyStateAndRun();
}
</script>
こうなっていますが、問題を解決できそうでしょうか。