Wanikani JLPT Indicator

Show which JLPT level the kanji or vocabulary word is in (if at all) according to Jonathan Waller‘s JLPT Resources page http://www.tanos.co.uk/jlpt/. The code is based on dtwigs "WaniKani Common Vocab Indicator" script. This code is at https://github.com/NicoleRauch/WaniKaniJLPT

当前为 2019-02-21 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Wanikani JLPT Indicator
// @namespace   nicolerauch
// @author      nicolerauch & myria
// @description Show which JLPT level the kanji or vocabulary word is in (if at all) according to Jonathan Waller‘s JLPT Resources page http://www.tanos.co.uk/jlpt/. The code is based on dtwigs "WaniKani Common Vocab Indicator" script. This code is at https://github.com/NicoleRauch/WaniKaniJLPT
// @run-at      document-end
// @include     *://www.wanikani.com/review/session*
// @include     *://www.wanikani.com/lesson/session*
// @version     0.2.0
// @run-at      document-end
// @grant       GM_xmlhttpRequest
// @connect     wanikanijlpt.herokuapp.com
// ==/UserScript==

(function () {
    'use strict';

    var jlptApiUrl = "https://wanikanijlpt.herokuapp.com/api/";

    console.log('/// Start of WK Kanji & Vocab JLPT Indicator');


    var css =
        '.jlpt-indicator-item {' +
        '    position: absolute;' +
        '    padding: 0px 5px 2px;' +
        '    top: 68px;' +
        '    left: 20px;' +
        '    -webkit-border-radius: 3px;' +
        '    -moz-border-radius: 3px;' +
        '    border-radius: 3px;' +
        '    z-index: 100;' +
        '    letter-spacing: 0;' +
        '    opacity: 0.8;' +
        '    text-decoration: none;' +
        '}' +
        '.jlpt-indicator-item.hide {' +
        '    background-color: transparent;' +
        '    color: transparent;' +
        '}' +
        '.jlpt-indicator-item.fetching {' +
        '    background-color: transparent;' +
        '    color: white;' +
        '    opacity: 0.5;' +
        '}' +
        '.jlpt-indicator-item.jlpt {' +
        '    background-color: white;' +
        '    color: #a100f1;' +
        '}' +
        '.jlpt-indicator-item.nojlpt {' +
        '    background-color: transparent;' +
        '    color: white;' +
        '    opacity: 0.5;' +
        '}';

    var allClasses = {
        hide: {
            klass: 'hide',
            text: ''
        },
        fetching: {
            klass: 'fetching',
            text: '...'
        },
        jlptn5: {
            klass: 'jlpt',
            text: 'JLPT N5'
        },
        jlptn4: {
            klass: 'jlpt',
            text: 'JLPT N4'
        },
        jlptn3: {
            klass: 'jlpt',
            text: 'JLPT N3'
        },
        jlptn2: {
            klass: 'jlpt',
            text: 'JLPT N2'
        },
        jlptn1: {
            klass: 'jlpt',
            text: 'JLPT N1'
        },
        nojlpt: {
            klass: 'nojlpt',
            text: 'no JLPT word'
        }
    };

    addStyle(css);

    $('#question').append('<div id="jlpt-indicator" class="jlpt-indicator-item"></div>');
    $('#lessons').append('<div id="jlpt-indicator" class="jlpt-indicator-item"></div>');

//every time item changes, look up vocabulary word
    $.jStorage.listenKeyChange('currentItem', function () {
        handleJLPT($.jStorage.get('currentItem'));
    });

    $.jStorage.listenKeyChange('l/currentLesson', function () {
        handleJLPT($.jStorage.get('l/currentLesson'));
    });

    $.jStorage.listenKeyChange('l/currentQuizItem', function () {
        handleJLPT($.jStorage.get('l/currentQuizItem'));
    });

    $.jStorage.listenKeyChange('l/overlayStartQuiz', function () {
        setJLPTIndicator("hide"); // remove indicator during quiz start overlay screen
    });

    $.jStorage.listenKeyChange('l/overlayStartLesson', function () {
        setJLPTIndicator("hide"); // remove indicator during lesson start overlay screen
    });

    function handleJLPT(currentItem) {
        var kanji = currentItem.kan;
        var vocab = currentItem.voc;
        var readings = currentItem.kana;

        // also query kanji from the backend because we need the hide information from the backend
        // due to race conditions with the reorder script
        fetchJLPTData(kanji, vocab, readings || []);
    }

    function fetchJLPTData(kanji, vocab, kana) {
        setClassAndText(allClasses.fetching);
        GM_xmlhttpRequest({
            method: 'get',
            url: jlptApiUrl + (
                kanji ? encodeURIComponent(kanji) :
                    vocab ? (encodeURIComponent(vocab.replace(/する$|〜/,'')) + "/" +
                        kana.map(function(k){return k.replace(/する$/,'')}).map(encodeURIComponent).join("/")) :
                        "noword"),
            responseType: 'text',
            onload: function (response) {
                setJLPTIndicator(response.response);
            },
            onerror: function (error) {
                console.log('JLPT API error: ', error);
            }
        });
    }

    function setJLPTIndicator(level) {
        setClassAndText(allClasses[level]);
    }

    function setClassAndText(aObj) {
        var $wrapper = $('#jlpt-indicator');
        for (var entry in allClasses) {
            $wrapper.removeClass(allClasses[entry].klass);
        }

        $wrapper.text(aObj.text).addClass(aObj.klass);
    }

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

})();