WK Overlay

Overlays component information on reviews when show info is pressed.

当前为 2017-03-15 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         WK Overlay
// @namespace    wkoverlay
// @version      0.2.1
// @description  Overlays component information on reviews when show info is pressed.
// @author       Ethan
// @match        https://www.wanikani.com/review/session*
// @grant        none
// ==/UserScript==

// TODO if kanji or radical follows vocab, overlay is not removed

var isKanji = function(ch){
    return /^[\u4e00-\u9faf]+$/.test(ch);
};
/** Gets the Kanji characters in a given string.
	* @param {string} vocabString -
	* @return {Array.<string>} An array of the kanji components in the given string
	*/
var getComponents = function(vocabString){
    return Array.prototype.filter.call(vocabString, function(ch){
        return isKanji(ch);
    }, this);
};

var addStyleTag = function(){
        /* Non-Javascript determined (to be put in style tag)*/
        var styleText =
        ".wkOverlay {\r\n" +
            "display: block;\r\n" +
            "position: absolute;\r\n" +
            "}\r\n" +
            ".infoSpan {\r\n" +
            "position: absolute;\r\n" +
            "backgroundColor: black;\r\n" +
            "color: #fff;\r\n" +
            "textAlign: center;\r\n" +
            "padding: 5px 10px;\r\n" +
            "borderRadius: 6px;\r\n" +
            "display: inline-block;\r\n" +
            "fontSize: 10pt;\r\n" +
            "}\r\n" +
            ".infoTop::after{\r\n" +
            "content: '';\r\n" +
            "position: absolute;\r\n" +
            "top: 100%;\r\n" +
            "left:20px;\r\n" +
            "margin-left: -10px;\r\n" +
            "border-width: 10px;\r\n" +
            "border-style: solid;\r\n" +
            "border-color: black transparent transparent transparent\r\n" +
            "}\r\n" +
            ".infoBottom::after{\r\n" +
            "content: '';\r\n" +
            "position: absolute;\r\n" +
            "bottom: 100%;\r\n" +
            "left:20px;\r\n" +
            "margin-left: -10px;\r\n" +
            "border-width: 10px;\r\n" +
            "border-style: solid;\r\n" +
            "border-color: transparent transparent black transparent\r\n" +
            "} \r\n";
        var styleElem = document.createElement('style');
        styleElem.appendChild(document.createTextNode(styleText));
        document.head.appendChild(styleElem);
};

(function() {
    'use strict';

    //salt this event so future scripts don't throw multiple events and confuse the script
    var hideEvent = "hide"+Math.trunc(Math.random()*1000000);
    var showEvent = "show"+Math.trunc(Math.random()*1000000);
//---------------------------
    var oldHide = $.fn.hide;
    $.fn.hide = function(){this.trigger(new jQuery.Event(hideEvent)); return oldHide.apply(this, arguments);};
    var oldShow = $.fn.show;
    $.fn.show = function(){this.trigger(new jQuery.Event(showEvent)); return oldShow.apply(this, arguments);};
//--------------------------
    
    addStyleTag();
    
    var parentElement = $("#question");
    var overlay = document.createElement('div');
    overlay.style.display = 'none';
    var descOverlay = document.createElement('div');
    
    var respComps = {};
    var prompt;
    parentElement[0].appendChild(overlay);

    $.jStorage.listenKeyChange('currentItem', function(){
        while (overlay.firstChild){
            overlay.removeChild(overlay.firstChild);
        }
        // Runs after span is changed, but is this guaranteed?
        prompt = $.jStorage.get('currentItem');
        if (prompt.voc){
            for (var ch in prompt.voc){
                var chSpan = document.createElement('span');

                chSpan.innerText = prompt.voc[ch];

                chSpan.style.fontSize = document.defaultView.getComputedStyle($("#character")[0], "").fontSize;
            }
        }
    });

    // Show overlay when info is being shown.
    $("#item-info").on(showEvent, function(){
        // Clear array of nodelists
        while (overlay.firstChild){
            overlay.removeChild(overlay.firstChild);
        }
        $("#related-items .kanji a").each(function(i, comp){
            console.log(comp);

            respComps[comp.childNodes[0].textContent] = comp.childNodes[1].textContent;
        });

        overlay.className = "wkOverlay";
        overlay.style.display = 'block';

//      while (descOverlay.firstChild){
//          descOverlay.removeChild(descOverlay.firstChild);
  //    }

        if (prompt.voc){
            var flipTopBottom = false; //true: top, false: bottom
            // Position absolute needs negative margins to react to number of characters
            var marginLeftPercentage = (-100/prompt.voc.length) + "%";
            var marginRightPercentage = "2%";
            for (var ch in prompt.voc){
                flipTopBottom = !flipTopBottom;
                var chSpan = document.createElement('span');
                chSpan.className = "wkOverlayChar";

                var comp = document.createElement('span');
                comp.innerText = prompt.voc[ch];
                comp.style.opacity = 0;
                chSpan.appendChild(comp);

                console.info(respComps, prompt.voc[ch], respComps[prompt.voc[ch]]);
                chSpan.style.fontSize = document.defaultView.getComputedStyle($("#character")[0], "").fontSize; // and lineHeight

                // Javascript determined values.
                overlay.style.height = $("#character span").height() + 'px';
                overlay.style.top = $("#character span").position().top + 'px';
                overlay.style.left = $("#character span").position().left + 'px';
                overlay.setAttribute('lang', "ja");
//                overlay.style.position = "absolute";

                //overlay.style.display = 'none';
                overlay.style.height = $("#character span").height() + 'px';

                overlay.appendChild(chSpan);
                
                // Pretty sure it does nothing ----
                if (!isKanji(prompt.voc[ch])){
                    chSpan.style.visibility = 'hidden';
                }
                else{
                //    chSpan.style.backgroundColor = "cyan";
                }
                //---------------------


                if (respComps[prompt.voc[ch]]){
                    var spInf = document.createElement('span');
                    spInf.innerText = respComps[prompt.voc[ch]];

                    chSpan.appendChild(spInf);
                    spInf.style.marginLeft = marginLeftPercentage;
                    spInf.style.marginRight = marginRightPercentage;
                    if(flipTopBottom){
                        spInf.className = "infoSpan infoTop";
                        spInf.style.bottom = "100%";
                    }
                    else{
                        spInf.className = "infoSpan infoBottom";
                        spInf.style.top = "100%";
                    }
                    spInf.style.position ="absolute";
                    spInf.style.backgroundColor = "black";
                    spInf.style.color = "#fff";
                    spInf.style.textAlign = "center";
                    spInf.style.padding = "5px 10px";
                    spInf.style.borderRadius = "6px";
                    spInf.style.display = "inline-block";
                    spInf.style.fontSize = "10pt";
                }
            }
        }
//      descOverlay.style.display = 'block';
        //console.log($("#character span"));
    });

    $("#item-info").on(hideEvent, function(){
        overlay.style.display = 'none';
//      descOverlay.style.display = 'none';
    });
})();