[Userscript] WK Anki Mode

Just wanted to say I love this script! I use Anki a ton and never noticed how tedious it is to type on WK. I also have overuse injuries from too much computer use and playing music, so the last thing I want is to make things worse from doing too much WK. Thank you!

3 Likes

This is called RSI, repeated stress injury, or something like that

2 Likes

Hello, I installed this using tampermonkey on googlechrome, but it doesn’t seem to work :confused: (no blue button). Any help ?

Hi, this extension worked perfectly until very recently. Any idea what’s up?

I believe there’s an incompatibility with the Double-Check script that’ll register meanings as incorrect.

2 Likes

Thank you so much for this extension :blush:

1 Like

Trying this out. Very promising, but seems to have some issues.

If I press 1 and the answer has multiple meanings, it’s marked as “incorrect” instead of “correct”… I’m guessing because both meanings were entered into the input field. (perhaps this is the Double-Check script incompatibility?)

Disables other keyboard shortcuts, like “Later Crabigator”

1 Like

Check out [iOS / Android / Web] Juken - Review App for WaniKani if you want to do Anki type reviews.

5 Likes

thanks! I will definitely check it out!

Apologies for bumping an old thread, but I’ve been using this script fine for the past couple of months and today the script stopped working. It won’t allow me to press 1 or 2 to confirm from shortcuts anymore. Is there a way to fix that or another script that does the same thing?

I think you can fix it by searching for the four occurrences of

$("#answer-form form button").click();

in the code and replace them with

$("#answer-form form").submit();
3 Likes

Thanks, that seemed to work!

1 Like

The script stopped working for me today as well, although everything was going fine just a few hours ago. I changed the code like mentioned above, but after marking the item correct or incorrect I can’t seem to press enter to go to the next item :frowning:

Looking at the code, it seems that it was always intended that you also use the keys 1 or 2 to continue to the next review (at least there is the code comment // if answer is shown, press '1' one more time to go to next). That it also worked with Enter until now was probably just an unintentional feature. But if you prefer to use Enter, you can try replacing the code with this modified version:

Modified Script
// ==UserScript==
// @name         Wanikani Anki Mode
// @namespace    mempo
// @version      1.7.2
// @description  Anki mode for Wanikani
// @author       Mempo
// @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 <og402@nyu.edu>

console.log('/// WKAM begin');


// Save the original evaluator
var answerChecker = window.answerChecker;
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();
});

 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;
            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
            });
        }





    } 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
        });
    }

}

 var WKANKIMODE_showAnswer = function () {
    if (!$("#answer-form form fieldset").hasClass("correct") &&
        !$("#answer-form form fieldset").hasClass("incorrect") &&
        !answerShown ) {
        var currentItem = $.jStorage.get("currentItem");
        var questionType = $.jStorage.get("questionType");
        if (questionType === "meaning") {
            var answer = currentItem.en.join(", ");
            if (currentItem.syn.length) {
                answer += " (" + currentItem.syn.join(", ") + ")";
            }
            $("#user-response").val(answer);
        } else { //READING QUESTION
            var i = 0;
            var answer = "";

            if (currentItem.voc) {
                answer += currentItem.kana[0];
            } else if (currentItem.emph == 'kunyomi') {
                answer += currentItem.kun[0];
            } else if (currentItem.emph == 'nanori') {
                answer += currentItem.nanori[0];
            } else {
                answer += currentItem.on[0];
            }
            $("#user-response").val(answer);
        }
        answerShown = true;
    }
};

 var WKANKIMODE_answerYes = function () {
    if (answerShown) {
        answerChecker.evaluate = checkerYes;
        submitAnswer();
        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") ) {
        submitAnswer();
    }

};

var WKANKIMODE_answerNo = function () {
    if (answerShown) {
        answerChecker.evaluate = checkerNo;
        submitAnswer();
        answerShown = false;
        answerChecker.evaluate = originalChecker;
        return;
    }

    if ($("#answer-form form fieldset").hasClass("correct") ||
        $("#answer-form form fieldset").hasClass("incorrect") ) {
        submitAnswer();
    }

};


    /*jshint multistr: true */
    var css = "\
        #WKANKIMODE_anki { \
            background-color: #000099; \
            margin: 0 5px; \
        } \
        #WKANKIMODE_yes { \
            background-color: #009900; \
            margin: 0 0 0 5px; \
        } \
        #WKANKIMODE_no { \
            background-color: #990000; \
        } \
        .WKANKIMODE_button { \
            display: inline-block; \
            font-size: 0.8125em; \
            color: #FFFFFF; \
            cursor: pointer; \
            padding: 10px; \
        } \
        #WKANKIMODE_anki.hidden { \
            display: none; \
        } ";



function addStyle(aCss) {
  var head, style;
  head = document.getElementsByTagName('head')[0];
  if (head) {
    style = document.createElement('style');
    style.setAttribute('type', 'text/css');
    style.textContent = aCss;
    head.appendChild(style);
    return style;
  }
  return null;
}

function submitAnswer() {
    let form = $('#answer-form form');
    let button = $('#answer-form button');
    if ($._data(form[0], 'events').submit) form.submit();
    else if ($._data(button[0], 'events').click) button.click();
}

var addButtons = function () {
    //CHECK AUTOSTART
    autostart = localStorage.getItem('WKANKI_autostart')==="true"?true:false;

    $("<div />", {
                id : "WKANKIMODE_anki",
                title : "Anki Mode",
    })
    .text("Anki Mode Off")
    .addClass("WKANKIMODE_button")
    .on("click", WKANKIMODE_toggle)
    .prependTo("footer");

    // TO-DO
    // add physical buttons to press yes/no/show answer

    // var yesButton = "<div id='WKANKIMODE_yes' class='WKANKIMODE_button' title='Correct' onclick='WKANKIMODE_correct();'>Correct</div>";
    // var noButton = "<div id='WKANKIMODE_no' class='WKANKIMODE_button' title='Incorrect' onclick='WKANKIMODE_incorrect();'>Incorrect</div>";

    // $("footer").prepend($(noButton).hide());
    // $("footer").prepend($(yesButton).hide());

};

var autostartFeature = function() {
    console.log("/// WKAM: 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 (activated && $("#reviews").is(":visible") && !$("*:focus").is("textarea, input"))
            {
                switch (event.keyCode) {
                    case 13:
                        if ($("#answer-form form fieldset").hasClass("correct") || $("#answer-form form fieldset").hasClass("incorrect")) {
                            event.stopPropagation();
                            event.preventDefault();
                            document.querySelector("#answer-form input").disabled = true;
                            submitAnswer();
                        }

                        break;
                    case 32:
                        event.stopPropagation();
                        event.preventDefault();

                        WKANKIMODE_showAnswer();

                        break;
                    case 49:
                        event.stopPropagation();
                        event.preventDefault();

                        WKANKIMODE_answerYes();

                        break;
                    case 50:

                        event.stopPropagation();
                        event.preventDefault();

                        WKANKIMODE_answerNo();

                        break;
                }
            }
        });
};


addStyle(css);
addButtons();
autostartFeature();
bindHotkeys();
4 Likes

Thank you :raised_hands:

1 Like

Yeah it worked like that at first, but with just the 4 lines of code modified as in your first suggestion, pressing 1 one more time either didn’t do anything or randomly marked the item as incorrect :frowning:

Thank you so much for the modified script! I just tried it out and now both pressing Enter or pressing 1 again continue to the next item. Thank you thank you thank you, I can’t imagine Wanikani without Anki Mode!

1 Like

Thank you so much!

1 Like

That worked! Thank you!

1 Like

Sorry for posting it again, but it appears that this script has broken again and now will just reload the reviews page when pressing buttons.

1 Like

It seems that WK has reverted back to the old answer submit method. You can probably just reinstall the original script version from the OP. But I have also updated the modified script in my previous post so that it automatically uses the appropriate method of the two.

7 Likes