Skip to content

Instantly share code, notes, and snippets.

@flavluc
Last active August 14, 2019 18:26
Show Gist options
  • Save flavluc/96fd41cca9457bd73909c3ef016ee3bc to your computer and use it in GitHub Desktop.
Save flavluc/96fd41cca9457bd73909c3ef016ee3bc to your computer and use it in GitHub Desktop.
wanikani script to simulate anki with mobile support
// ==UserScript==
// @name Wanikani Anki Mode (mobile support)
// @namespace zen
// @version 0.0.1
// @description Anki mode for Wanikani with mobile support
// @author Zen
// @match https://www.wanikani.com/review/session*
// @match http://www.wanikani.com/review/session*
// @grant none
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==
const ANKI_MODE = "WANKIMODE";
const CORRECT_ANS = { accurate: !0, passed: !0 };
const WRONG_ANS = { accurate: !0, passed: 0 };
const originalChecker = answerChecker.evaluate;
const originalValidator = answerChecker.isNonKanaPresent;
let answerShown = false;
let answerChecked = false;
function toggleAnkiMode() {
if (localStorage.getItem(ANKI_MODE) === "true") {
$("#anki-toggle").text("Anki Off");
$("#user-response").off("focus");
$("#user-response").focus();
$("#answer-form form button").attr("disabled", false);
toggleButtons();
answerChecker.evaluate = originalChecker;
answerShown = false;
localStorage.setItem(ANKI_MODE, false);
} else {
$("#anki-toggle").text("Anki On");
$("#user-response").on("focus", function() {
$("#user-response").blur();
});
$("#answer-form form button").attr("disabled", true);
toggleButtons({ show: true });
localStorage.setItem(ANKI_MODE, true);
}
}
function showAnswer() {
if (!answerShown) {
const currentItem = $.jStorage.get("currentItem");
if ($.jStorage.get("questionType") === "meaning") {
let ans = currentItem.en.join(", ");
if (currentItem.syn.length) {
ans += " (" + currentItem.syn.join(", ") + ")";
}
$("#user-response").val(ans);
} else {
let i = 0;
let ans = "";
if (currentItem.voc) {
for (i = 0; i < currentItem.kana.length - 1; i++) {
ans += currentItem.kana[i] + ", ";
}
ans += currentItem.kana[currentItem.kana.length - 1];
} else if (currentItem.emph == "kunyomi") {
for (i = 0; i < currentItem.kun.length - 1; i++) {
ans += currentItem.kun[i] + ", ";
}
ans += currentItem.kun[currentItem.kun.length - 1];
} else if (currentItem.emph == "nanori") {
for (i = 0; i < currentItem.nanori.length - 1; i++) {
ans += currentItem.nanori[i] + ", ";
}
ans += currentItem.nanori[currentItem.nanori.length - 1];
} else {
for (i = 0; i < currentItem.on.length - 1; i++) {
ans += currentItem.on[i] + ", ";
}
ans += currentItem.on[currentItem.on.length - 1];
}
$("#user-response").val(ans);
}
answerShown = true;
toggleButtons({ correct: true, incorrect: true });
}
}
function answer(evaluate) {
if (answerShown) {
if (!answerChecked) {
answerChecker.evaluate = () => evaluate;
answerChecker.isNonKanaPresent = () => false;
$("#answer-form form button").click();
answerChecker.evaluate = originalChecker;
answerChecker.isNonKanaPresent = originalValidator;
answerChecked = true;
} else {
$("#answer-form form button").click();
toggleButtons({ show: true });
answerChecked = false;
answerShown = false;
}
}
}
function addStyle(css) {
$("footer")
.css("display", "flex")
.css("width", "100%")
.css("height", "55px");
const head = document.getElementsByTagName("head")[0];
if (head) {
const style = document.createElement("style");
style.setAttribute("type", "text/css");
style.textContent = css;
head.appendChild(style);
}
}
function createToggle(activated) {
$("<a />", {
id: "anki-toggle"
})
.text(`Anki ${activated ? "On" : "Off"}`)
.on("click", toggleAnkiMode)
.addClass("anki-toggle")
.prependTo("#summary-button");
}
function createButton({ id, texts, backgroundColor, onClick }) {
$("<div />", {
id
})
.html(texts.reduce((a, i) => a + `<p class="p-text">${i}</p>`, ""))
.addClass("anki-button")
.css("background-color", backgroundColor)
.on("click", onClick)
.prependTo("footer")
.hide();
}
function bindHotkeys() {
$(document).on("keydown.reviewScreen", function(event) {
if (event.keyCode === 27) {
return toggleAnkiMode();
}
if (
localStorage.getItem(ANKI_MODE) === "true" &&
[13, 32, 49, 50].includes(event.keyCode)
) {
switch (event.keyCode) {
case 32:
return showAnswer();
case 49:
return answer(WRONG_ANS);
case 13:
case 50:
return answer(CORRECT_ANS);
}
}
});
}
function toggleButtons({ show, correct, incorrect } = {}) {
$("#anki-show-button")[show ? "show" : "hide"]();
$("#anki-correct-button")[correct ? "show" : "hide"]();
$("#anki-incorrect-button")[incorrect ? "show" : "hide"]();
}
const css = `
.p-text {
padding: 0;
margin: 0;
}
.anki-toggle {
cursor: pointer;
}
.anki-button {
display: flex;
flex-direction: column;
font-size: 0.8125em;
color: #FFFFFF;
cursor: pointer;
padding: 10px;
width: 100%;
align-items: center;
justify-content: center;
}
`;
function main() {
addStyle(css);
createToggle(localStorage.getItem(ANKI_MODE) === "true");
createButton({
id: "anki-show-button",
texts: ["Show answer", "(space)"],
backgroundColor: "#0277BD",
onClick: showAnswer
});
createButton({
id: "anki-correct-button",
texts: ["Know", "(2)"],
backgroundColor: "#2F7D32",
onClick: () => answer(CORRECT_ANS)
});
createButton({
id: "anki-incorrect-button",
texts: ["Don't know", "(1)"],
backgroundColor: "#C62827",
onClick: () => answer(WRONG_ANS)
});
if (localStorage.getItem(ANKI_MODE) === "true") {
$("#answer-form form button").attr("disabled", true);
$("#user-response").on("focus", function() {
$("#user-response").blur();
});
}
toggleButtons({
show: true
});
bindHotkeys();
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment