// ==UserScript==
// @name Wanikani Anki Mode
// @namespace ckarisch
// @version 1.10.4
// @description Anki mode for Wanikani
// @author Christof Karisch
// @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==
//Original author: Oleg Grishin <[email protected]>, Mempo (edited the original script)
(function(global) {
'use strict';
//===================================================================
// Initialization of the Wanikani Open Framework.
//-------------------------------------------------------------------
var script_name = 'Wanikani Anki Mode';
var wkof_version_needed = '1.0.27';
if (!window.wkof) {
if (confirm(script_name + ' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?'))
window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
return;
}
if (wkof.version.compare_to(wkof_version_needed) === 'older') {
if (confirm(script_name + ' requires Wanikani Open Framework version ' + wkof_version_needed + '.\nDo you want to be forwarded to the update page?'))
window.location.href = 'https://greasyfork.org/en/scripts/38582-wanikani-open-framework';
return;
}
wkof.include('ItemData, Settings');
wkof.ready('document,ItemData,Settings').then(startup);
//===================================================================
console.log('/// Start of Wanikani Anki Mode');
let buttonOffsetTopTimeout;
// Save the original evaluator
var originalChecker = answerChecker.evaluate;
var checkerYes = function(itemType, correctValue) {
return {
accurate: !0,
passed: !0
};
}
var checkerNo = function(itemType, correctValue) {
return {
accurate: !0,
passed: 0
};
}
var activated = false;
var answerShown = false;
//AUTOSTART
var autostart = false;
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
$("#user-response").blur();
});
//========================================================================
// Startup
//-------------------------------------------------------------------
function startup() {
wkof.load_css("https://raw.githubusercontent.com/ckarisch/wk-anki-mode/master/styles.css", true);
addButtons();
addAnswerOverlay();
autostartFeature();
bindHotkeys();
bindMove();
}
var WKANKIMODE_toggle = function() {
if (activated) {
if (autostart) {
//DISABLE ANKI MODE
$("#WKANKIMODE_anki").text("Anki Mode Off");
$("#answer-form form button").prop("disabled", false);
$("#user-response").off("focus");
$("#user-response").focus();
answerChecker.evaluate = originalChecker;
observer.disconnect();
localStorage.setItem("WKANKI_autostart", false);
activated = false;
autostart = false;
$("#WKANKIMODE_anki_answer").addClass("hidden");
console.log("back to #1");
} else {
//ENABLE AUTOSTART
activated = true;
autostart = true;
localStorage.setItem("WKANKI_autostart", true);
$("#WKANKIMODE_anki").text("Anki Mode Auto Start");
// start observer to force blur
observer.observe(document.getElementById("answer-form"), {
childList: true,
subtree: true,
attributes: true,
characterData: false
});
$("#WKANKIMODE_anki_answer").removeClass("hidden");
}
} else {
//ENABLE ANKI MODE
$("#WKANKIMODE_anki").text("Anki Mode On");
$("#answer-form form button").prop("disabled", true);
$("#user-response").on("focus", function() {
$("#user-response").blur();
});
activated = true;
autostart = false;
// start observer to force blur
observer.observe(document.getElementById("answer-form"), {
childList: true,
subtree: true,
attributes: true,
characterData: false
});
$("#WKANKIMODE_anki_answer").removeClass("hidden");
}
}
var WKANKIMODE_showAnswer = function() {
if (!$("#answer-form form fieldset").hasClass("correct") &&
!$("#answer-form form fieldset").hasClass("incorrect") &&
!answerShown) {
var i = 0;
var answerArray = [];
var answerArraySyn = [];
var currentItem = $.jStorage.get("currentItem");
var questionType = $.jStorage.get("questionType");
if (questionType === "meaning") {
answerArray = currentItem.en;
answerArraySyn = currentItem.syn;
$("#user-response").val(answerArray[0]);
$("#WKANKIMODE_anki_answer").val(answerArray.join(", ") +
(answerArraySyn.length > 0 ? " (" + answerArraySyn.join(", ") + ")" : ""));
} else { //READING QUESTION
if (currentItem.voc) {
for (i = 0; i < (currentItem.kana.length); i++) {
answerArray.push(currentItem.kana[i]);
}
} else if (currentItem.emph == 'kunyomi') {
for (i = 0; i < (currentItem.kun.length); i++) {
answerArray.push(currentItem.kun[i]);
}
} else if (currentItem.emph == 'nanori') {
for (i = 0; i < (currentItem.nanori.length); i++) {
answerArray.push(currentItem.nanori[i]);
}
} else {
for (i = 0; i < (currentItem.on.length); i++) {
answerArray.push(currentItem.on[i]);
}
}
$("#user-response").val(answerArray[0]);
$("#WKANKIMODE_anki_answer").val(answerArray.join(", "));
}
answerShown = true;
}
};
var WKANKIMODE_answerYes = function() {
if (answerShown) {
answerChecker.evaluate = checkerYes;
$("#answer-form form button").click();
answerShown = false;
answerChecker.evaluate = originalChecker;
return;
}
// if answer is shown, press '1' one more time to go to next
if ($("#answer-form form fieldset").hasClass("correct") ||
$("#answer-form form fieldset").hasClass("incorrect")) {
$("#answer-form form button").click();
$("#WKANKIMODE_anki_answer").val("");
}
};
var WKANKIMODE_answerNo = function() {
if (answerShown) {
answerChecker.evaluate = checkerNo;
$("#answer-form form button").click();
answerShown = false;
answerChecker.evaluate = originalChecker;
return;
}
if ($("#answer-form form fieldset").hasClass("correct") ||
$("#answer-form form fieldset").hasClass("incorrect")) {
$("#answer-form form button").click();
$("#WKANKIMODE_anki_answer").val("");
}
};
var addButtons = function() {
//CHECK AUTOSTART
autostart = localStorage.getItem('WKANKI_autostart') === "true" ? true : false;
let buttonTop = "margin-top: " + (localStorage.getItem("buttonOffsetTop") ? localStorage.getItem("buttonOffsetTop") + "px;" : "calc(50% - 63px);");
$("<div />", {
id: "WKANKIMODE_anki",
title: "Anki Mode",
})
.text("Anki Mode Off")
.addClass("WKANKIMODE_button")
.on("click", WKANKIMODE_toggle)
.prependTo("footer");
$("<div />", {
id: "WKANKIMODE_anki_buttongroup",
})
.prependTo(".pure-u-1");
$("<div />", {
id: "WKANKIMODE_anki_incorrect",
title: "No",
style: buttonTop,
})
.text("Don't know")
.addClass("WKANKIMODE_button incorrect")
.on("click", WKANKIMODE_answerNo)
.prependTo("#WKANKIMODE_anki_buttongroup");
$("<div />", {
id: "WKANKIMODE_anki_show",
title: "Show",
style: buttonTop,
})
.text("Show")
.addClass("WKANKIMODE_button show")
.on("click", WKANKIMODE_showAnswer)
.prependTo("#WKANKIMODE_anki_buttongroup");
$("<div />", {
id: "WKANKIMODE_anki_correct",
title: "Yes",
style: buttonTop,
})
.text("Know")
.addClass("WKANKIMODE_button correct")
.on("click", WKANKIMODE_answerYes)
.prependTo("#WKANKIMODE_anki_buttongroup");
$("#WKANKIMODE_anki_buttongroup div").each(function() {
$(this).css("margin-top", localStorage.getItem("buttonOffsetTop"));
});
};
var addAnswerOverlay = function() {
$("<input />", {
id: "WKANKIMODE_anki_answer",
type: "text",
readonly: "readonly",
})
.addClass("WKANKIMODE_answer")
.appendTo("#answer-form fieldset");
};
var autostartFeature = function() {
console.log("///////////// AUTOSTART: " + autostart);
if (autostart) {
$("#WKANKIMODE_anki").text("Anki Mode Auto Start");
$("#answer-form form button").prop("disabled", true);
$("#user-response").on("focus", function() {
$("#user-response").blur();
});
activated = true;
// start observer to force blur
observer.observe(document.getElementById("answer-form"), {
childList: true,
subtree: true,
attributes: true,
characterData: false
});
}
}
var bindHotkeys = function() {
$(document).on("keydown.reviewScreen", function(event) {
if ($("#reviews").is(":visible") && !$("*:focus").is("textarea, input")) {
switch (event.keyCode) {
case 32:
event.stopPropagation();
event.preventDefault();
if (activated)
WKANKIMODE_showAnswer();
break;
case 49:
event.stopPropagation();
event.preventDefault();
if (activated)
WKANKIMODE_answerYes();
break;
case 50:
event.stopPropagation();
event.preventDefault();
if (activated)
WKANKIMODE_answerNo();
break;
}
}
});
};
let getPoint = function(event) {
let point = {};
if (event.changedTouches) {
point.y = event.changedTouches[0].pageY;
point.x = event.changedTouches[0].pageX;
} else {
point.y = event.clientY;
point.x = event.clientX;
}
return point;
}
var bindMove = function() {
let thumb = document.querySelector('#WKANKIMODE_anki_buttongroup');
let divs = $('#WKANKIMODE_anki_buttongroup div');
//console.log(localStorage.getItem("buttonOffsetTop"));
let touchfunction = function(event) {
let point = getPoint(event);
//event.preventDefault(); // prevent selection start (browser action)
let shiftY = point.y - divs.get(0).getBoundingClientRect().top;
// shiftY not needed, the thumb moves only horizontally
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
document.addEventListener('touchmove', onMouseMove);
document.addEventListener('touchend', onMouseUp);
function onMouseMove(event) {
let point = getPoint(event);
let newTop = point.y - shiftY - thumb.getBoundingClientRect().top;
// the pointer is out of slider => lock the thumb within the bounaries
if (newTop < 0) {
newTop = 0;
}
let bottomEdge = thumb.offsetHeight - divs.get(0).offsetHeight;
if (newTop > bottomEdge) {
newTop = bottomEdge;
}
divs.each(function() {
$(this).css("margin-top", newTop);
});
clearTimeout(buttonOffsetTopTimeout);
buttonOffsetTopTimeout = setTimeout(function() {
localStorage.setItem("buttonOffsetTop", newTop);
}, 300);
}
function onMouseUp() {
document.removeEventListener('mouseup', onMouseUp);
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('touchend', onMouseUp);
document.removeEventListener('touchmove', onMouseMove);
}
};
thumb.onmousedown = touchfunction;
thumb.ontouchstart = touchfunction;
thumb.ondragstart = function() {
return false;
};
};
})(window);