[Userscript] WK Anki Mode

I’m using Chrome.
This is what I get when I do inspect
Active resource loading counts reached a per-frame limit while the tab was in background. Network requests will be delayed until a previous loading finishes, or the tab is brought to the foreground. See https://www.chromestatus.com/feature/5527160148197376 for more details
application-ad22670f636ed2b126016bb87aa69fb8a2e303e03c794926cac203bbeeddb70a.js:2 [Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://fonts.gstatic.com/s/sourcesanspro/v11/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2
userscript.html?id=44f3e9f4-0f6b-44ec-8494-4d83d4cd7d37:125 WKO: loaded
userscript.html?id=815ec36c-40b1-45e3-a969-614aa0ff93a9:19 /// Start of Wanikani Anki Mode
userscript.html?id=815ec36c-40b1-45e3-a969-614aa0ff93a9:25 ƒ (e,t){var n,i,r,a,o,s,u,c,l,d,f,p,h,m,g,y;if(r=,u=,o=.jStorage.get("currentItem"),n=!1,d=!1,l=!1,s=!1,t=.trim(t),“reading”===e&&(t=t.replace(/n/g,"\u3093").replace(/\s/g,"")),$("#user-response"…
userscript.html?id=815ec36c-40b1-45e3-a969-614aa0ff93a9:237 ///////////// AUTOSTART: false
application-ad22670f636ed2b126016bb87aa69fb8a2e303e03c794926cac203bbeeddb70a.js:3 [Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://maxcdn.bootstrapcdn.com/font-awesome/3.2.1/font/fontawesome-webfont.woff?v=3.2.1
application-ad22670f636ed2b126016bb87aa69fb8a2e303e03c794926cac203bbeeddb70a.js:3 [Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://fonts.gstatic.com/s/sourcesanspro/v11/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdu.woff2
css-hits-counter.js:153 [Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://fonts.gstatic.com/s/sourcesanspro/v11/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2
userscript.html?id=44f3e9f4-0f6b-44ec-8494-4d83d4cd7d37:125 WKO: k665
userscript.html?id=44f3e9f4-0f6b-44ec-8494-4d83d4cd7d37:125

unfortunately that doesn’t tell me anything except that you have slow internet. The only other thing you might try is reinstalling the script, but otherwise I have no idea what is going on.

EDIT: posted an update with a minor change to the script. Did that fix it by any chance?

Doesn’t seem to, but it may just be an issue with tampermonkey since I tried downloading another script that used shortcuts just to see and those shortcuts don’t work either. I assume that’s also what is causing the slow internet error because every other window tampermonkey can’t access doesn’t have that on the console tab and shows up like normal. Thanks for trying to help!

maybe there’s a faulty script that slows everything down. Something that includes external libraries like jQuery might do that.

1 Like

Very cool script! As a big Anki user, this helps me a lot. Typing is pretty slow and error prone for me. And in Anki mode, I force myself to pronounce the meanings and readings, which I think helps the memorizing process (for me at least).

One tiny suggestion: is it at all possible to have the audio play as soon as we press space bar, and then press correct or incorrect? Being able to read the hiragana while hearing it might help me consolidate my hiranaga skills :slight_smile:

Thanks for the good work!

Hey all,

I’ve been using this script for a while (shout out to doing reviews at work via anki mode :wink: ) and I wanted to change the keyboard shortcuts so I can sit a bit more comfy. Couldn’t find anything about it in the thread so I did some digging; I’m not a programmer

Around line 250 you’ll find bindHotkeys

You can change the javascript character code accordingly!

4 Likes

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