// ==UserScript== // @name WaniKani Quick Info KT // @namespace https://www.wanikani.com // @description Shows available information while waiting for the server response. Originally by Ethan, Modified. // @version 0.1.4 // @include http*://www.wanikani.com/review/session* // @run-at document-end // @grant none // @downloadURL https://update.greasyfork.icu/scripts/10063/WaniKani%20Quick%20Info%20KT.user.js // @updateURL https://update.greasyfork.icu/scripts/10063/WaniKani%20Quick%20Info%20KT.meta.js // ==/UserScript== /*global $, console, additionalContent, Notes, UserSynonyms, setTimeout*/ /*jslint plusplus: true */ (function () { 'use strict'; additionalContent.itemInfo = function () { return; }; // replace with empty function. will prevent execute on firefox, do nothing on chrome. function newItemInfo() { // takes in a string and returns an array containing only the kanji characters in the string. function getComponents(vocab) { var c, components = []; for (c = 0; c < vocab.length; c++) { if (/^[\u4e00-\u9faf]+$/.test(vocab[c])) { components.push(vocab[c]); } } return components; } function regex(key) { switch (key) { case "radical": return (/\[(?:radical)\]/gi); case "kanji": return (/\[(?:kanji)\]/gi); case "vocabulary": return (/\[(?:vocabulary)\]/gi); case "meaning": return (/\[(?:meaning)\]/gi); case "reading": return (/\[(?:reading)\]/gi); case "ja": return (/\[(?:ja)\]/gi); case "closeTagSpan": return (/\[\/(?:radical|kanji|vocabulary|meaning|reading|ja)\]/gi); } } function htmlify(str) { var i, keys; str = str.replace("\r\n", "

"); keys = [ "radical", "kanji", "vocabulary", "meaning", "reading", "ja", "closeTagSpan" ]; function filter(str, key) { switch (key) { case "ja": return str.replace(regex(key), ''); case "closeTagSpan": return str.replace(regex(key), ""); default: return str.replace(regex(key), ''); } } for (i = 0; i < keys.length; i++) { str = filter(str, keys[i]); } return str; } function getRkvId(item) { var rkvType = item.rad ? "r" : item.kan ? "k" : item.voc ? "v" : undefined; return (rkvType + item.id); } function checkCurItem(readMeanType1, rkvId1) { var readMeanType2, rkvId2; readMeanType2 = $.jStorage.get("questionType"); rkvId2 = getRkvId($.jStorage.get("currentItem")); return (readMeanType1 === readMeanType2 && rkvId1 === rkvId2); } // normal meaning/name always start with a Capital letter, but injected synonyms are always lowercase only // answerChecker injects cur.syn into cur.en when validating a 'meaning' question function meaningSynFilterFmt(meaningList) { return $.grep(meaningList, function (str) { return str.toLowerCase() !== str; }).join(", "); } $("#option-item-info").off("click"); // delete all click handlers for this element $("#option-item-info").click(function () { // replace the main button toggler code if ($("#option-item-info").hasClass("active")) { // if info button .active $("#additional-content li").removeClass("active"); // deactivate all buttons $("#information").hide().children().hide(); // hide "#information" and child "#item-info" $("html, body").animate({ scrollTop: 0 }, 200); // scroll up } else if ($("#user-response").is(":disabled")) { // info button NOT .active and not waiting for answer $("#information").show().children().hide(); // show "#information" and hide any visible children $("html, body").animate({ scrollTop: $("#user-response").offset().top - 10 }, 200); // scroll down $("#additional-content li").removeClass("active"); // deactivate all buttons $("#option-item-info").addClass("active"); // make info button active $("#item-info").fadeIn(300); // show #item-info } // this replaces another click handler that we deleted if ($("#user-response").is(":disabled")) { $("#answer-exception").remove(); } var rkvId, itemInfoCol1, itemInfoCol2, cur, readMeanType, itemInfo, loading; itemInfo = $("#item-info"); cur = $.jStorage.get("currentItem"); readMeanType = $.jStorage.get("questionType"); rkvId = getRkvId(cur); if (itemInfo.is(":visible") && (itemInfo.data("question-type") !== readMeanType || itemInfo.data("id") !== rkvId)) { itemInfoCol1 = $("#item-info-col1"); itemInfoCol2 = $("#item-info-col2"); itemInfoCol1.empty(); itemInfoCol2.empty(); loading = ''; //put crabigator here if (cur.rad) { itemInfoCol1.html('

Name

' + meaningSynFilterFmt(cur.en) + '

User Synonyms

'); itemInfoCol2.html('

Mnemonics

' + loading + '
'); UserSynonyms.load("radical", cur.syn, cur.id, true); $("#all-info").hide(); $.getJSON("/json/radical/" + cur.id, function (radJSON) { if (!checkCurItem(readMeanType, rkvId)) { return; // item has since changed, ignore this data. } radJSON.mnemonic = htmlify(radJSON.mnemonic); itemInfoCol1.find("section#item-info-name").html("

Name

" + radJSON.en); itemInfoCol2.find("section#item-info-mnemonic").html("

Mnemonics

" + radJSON.mnemonic); itemInfoCol2.find("section#note-meaning").html("

Name Note

"); Notes.add("radical", "meaning", cur.id, radJSON.meaning_note, itemInfoCol2.find("section#note-meaning")); itemInfo.data("id", rkvId); itemInfo.data("question-type", readMeanType); }).fail(function () { $("#information-offline").show(); }); } else if (cur.kan) { (function () { var emphReading; emphReading = cur.emph === "onyomi" ? cur.on : cur.kun; itemInfoCol1.html('

Meanings

' + meaningSynFilterFmt(cur.en) + '

User Synonyms

Important Readings (' + cur.emph + ")

" + emphReading + '
"); itemInfoCol2.html('

Meaning Mnemonic

' + loading + '

Reading Mnemonic

' + loading + '
'); UserSynonyms.load("kanji", cur.syn, cur.id, true); if (readMeanType === "meaning") { $("#item-info-reading, #item-info-reading-mnemonic, #note-reading").hide(); } else { $("#item-info-meaning, #item-info-meaning-mnemonic, #note-meaning, .user-synonyms").hide(); } $("#all-info").show(); }()); $.getJSON("/json/kanji/" + cur.id, function (kanJSON) { if (!checkCurItem(readMeanType, rkvId)) { return; // item has since changed, ignore this data. } var relatedRadChar, relatedRad, i, relatedRadStr, relatedRadList; kanJSON.meaning_mnemonic = htmlify(kanJSON.meaning_mnemonic); kanJSON.reading_mnemonic = htmlify(kanJSON.reading_mnemonic); kanJSON.meaning_hint = htmlify(kanJSON.meaning_hint); kanJSON.reading_hint = htmlify(kanJSON.reading_hint); relatedRadStr = ""; relatedRadList = kanJSON.related; for (i = 0; i < relatedRadList.length; i++) { relatedRad = relatedRadList[i]; if (relatedRad.custom_font_name) { relatedRadChar = ''; } else if (/\.png/i.test(relatedRad.rad)) { relatedRadChar = ''; } else { relatedRadChar = relatedRad.rad; } relatedRadStr += '
  • ' + relatedRadChar + " " + relatedRad.en.split(",")[0] + "
  • "; } itemInfoCol1.find("section#item-info-meaning").html("

    Meanings

    " + kanJSON.en); itemInfoCol1.find("section#related-items").html('

    Radical Combination

    "); itemInfoCol2.find("section#item-info-meaning-mnemonic").html('

    Meaning Mnemonic

    ' + kanJSON.meaning_mnemonic + '

    HINT

    ' + kanJSON.meaning_hint + '
    '); itemInfoCol2.find("section#item-info-reading-mnemonic").html('

    Reading Mnemonic

    ' + kanJSON.reading_mnemonic + '

    HINT

    ' + kanJSON.reading_hint + '
    '); itemInfoCol2.find("section#note-meaning").html("

    Meaning Note

    "); Notes.add("kanji", "meaning", cur.id, kanJSON.meaning_note, itemInfoCol2.find("section#note-meaning")); itemInfoCol2.find("section#note-reading").html("

    Reading Note

    "); Notes.add("kanji", "reading", cur.id, kanJSON.reading_note, itemInfoCol2.find("section#note-reading")); itemInfo.data("id", rkvId); itemInfo.data("question-type", readMeanType); }).fail(function () { $("#information-offline").show(); }); } else if (cur.voc) { (function () { var i, relatedKanStr, relatedKanList, relatedKan; relatedKanStr = ""; relatedKanList = getComponents(cur.voc); for (i = 0; i < relatedKanList.length; i++) { relatedKan = relatedKanList[i]; relatedKanStr += '
  • ' + relatedKan + "
  • "; } itemInfoCol1.html('

    Meanings

    ' + meaningSynFilterFmt(cur.en) + '

    User Synonyms

    Reading

    ' + cur.kana.join(", ") + '

    Part of Speech

    ' + loading + '
    "); itemInfoCol2.html('

    Meaning Explanation

    ' + loading + '

    Reading Explanation

    ' + loading + '

    Context Sentence

    ' + loading + "
    "); UserSynonyms.load("vocabulary", cur.syn, cur.id, true); if (readMeanType === "meaning") { $("#item-info-reading, #item-info-reading-mnemonic, #note-reading").hide(); } else { $("#item-info-meaning, #item-info-meaning-mnemonic, #note-meaning, .user-synonyms").hide(); } $("#all-info").show(); }()); $.getJSON("/json/vocabulary/" + cur.id, function (vocJSON) { if (!checkCurItem(readMeanType, rkvId)) { return; // item has since changed, ignore this data. } var sentenceStr, relatedKan, i, relatedKanStr, relatedKanList; vocJSON.meaning_explanation = htmlify(vocJSON.meaning_explanation); vocJSON.reading_explanation = htmlify(vocJSON.reading_explanation); relatedKanStr = ""; relatedKanList = vocJSON.related; for (i = 0; i < relatedKanList.length; i++) { relatedKan = relatedKanList[i]; relatedKanStr += '
  • ' + relatedKan.kan + " " + relatedKan.en + "
  • "; } if (vocJSON.sentences.length === 0) { sentenceStr = "

    N/A

    "; } else { sentenceStr = "

    " + vocJSON.sentences[0][0] + "

    " + vocJSON.sentences[0][1] + "

    "; } itemInfoCol1.find("section#item-info-meaning").html("

    Meanings

    " + vocJSON.en); itemInfoCol1.find("section#item-info-reading").html("

    Reading

    " + vocJSON.kana); itemInfoCol1.find("section#part-of-speech").html("

    Part of Speech

    " + vocJSON.part_of_speech); itemInfoCol1.find("section#related-items").html('

    Related Kanji

    "); itemInfoCol2.find("section#item-info-meaning-mnemonic").html('

    Meaning Explanation

    ' + vocJSON.meaning_explanation); itemInfoCol2.find("section#item-info-reading-mnemonic").html('

    Reading Explanation

    ' + vocJSON.reading_explanation); itemInfoCol2.find("section#note-meaning").html("

    Meaning Note

    "); Notes.add("vocabulary", "meaning", cur.id, vocJSON.meaning_note, itemInfoCol2.find("section#note-meaning")); itemInfoCol2.find("section#note-reading").html("

    Reading Note

    "); Notes.add("vocabulary", "reading", cur.id, vocJSON.reading_note, itemInfoCol2.find("section#note-reading")); itemInfoCol2.find("section#item-info-context-sentences").html("

    Context Sentence

    " + sentenceStr); itemInfo.data("id", rkvId); itemInfo.data("question-type", readMeanType); }).fail(function () { $("#information-offline").show(); }); } } }); } // delayed load to make sure this loads after (and so can replace) the original setTimeout(function () { additionalContent.itemInfo = newItemInfo; // replace empty function with new function additionalContent.itemInfo(); // execute it console.log('WaniKani Quick Info KT: loaded replacement function'); }, 100); console.log('WaniKani Quick Info KT: script load end'); }());