Jpdb percentage bar

Adds a progress bar during jpdb reviews

目前为 2022-09-09 提交的版本。查看 最新版本

// ==UserScript==
// @name         Jpdb percentage bar
// @namespace    http://tampermonkey.net/
// @version      0.3.7
// @description  Adds a progress bar during jpdb reviews
// @author       Calonca
// @match        https://jpdb.io/review
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @license GPLv2
// @namespace https://gf.qytechs.cn/users/956173-calonca
// ==/UserScript==

let styleSheet = `
    .innerBar {
    width: 10%;
    height: 30px;
    background-color: #7baee9;
    text-align: center; /* To center it horizontally (if you want) */
    line-height: 30px; /* To center it vertically */
    color: white;
    }
    .outerBar {
    width: 100%;
    background-color: #a2a2a2;
    text-align: center; /* To center it horizontally (if you want) */
    }
    `;

const doneNumKey = "revsDone";
let s = document.createElement("style");
s.type = "text/css";
s.innerHTML = styleSheet;
(document.head || document.documentElement).appendChild(s);

(function() {
    'use strict';
    if (GM_getValue(doneNumKey)==null){
        //Set values in first script usage
        GM_setValue(doneNumKey,0)
    }

    function getPercentage(done, remaining){
        //return (((done+remaining)));
        return (100*(done/(Number(done)+Number(remaining)))).toFixed(2)+"%";
    }

    function getDoneAndRemainingString(done, remaining){
        return "&nbspdone:&nbsp"+done+"&nbsp|&nbsp"+"remaining:&nbsp"+remaining;
    }

    //Progress bar
    let outerBar = document.createElement("div");
    outerBar.className = "outerBar";

    let innerBar = document.createElement("div");
    innerBar.className = "innerBar";
    outerBar.appendChild(innerBar);

    function updateBar(){
        let percentage = getPercentage(GM_getValue(doneNumKey),revNum);
        innerBar.style.width = percentage;
        innerBar.innerHTML = getDoneAndRemainingString(GM_getValue(doneNumKey),revNum)+"&nbsp|&nbsp"+percentage;
    }

    let learnNavItem = document.querySelectorAll(".nav-item")[0]
    let span = learnNavItem.childNodes[1];
    let revNum = span.textContent;

    function onReset() {
        if (confirm("Do you want to reset the Progress Bar?")) {
            GM_setValue(doneNumKey,0);
            updateBar();
        }
    }

    outerBar.onclick = onReset;

    //Increase done review count on button click
    function increaseDone() {
        GM_setValue(doneNumKey,GM_getValue(doneNumKey)+1);
    }
    function afterShowingGradeButtons(){
        outerBar.onclick = null;
        document.getElementById("grade-3").addEventListener ("click", increaseDone , false);
        document.getElementById("grade-4").addEventListener ("click", increaseDone , false);
        document.getElementById("grade-5").addEventListener ("click", increaseDone , false);
    }

    let showAnswerButton = document.getElementById("show-answer");
    if (showAnswerButton){
        waitForKeyElements (
            "#grade-3"
            , afterShowingGradeButtons
        );
    }

    //Add elements to the document
    updateBar();

    let elementAfter = document.getElementsByClassName("main-row")[0];
    if (elementAfter){//Doing review
        elementAfter.parentElement.insertBefore(outerBar,elementAfter);
    }else {//Continue or finish screen
        let parent = document.getElementsByClassName("container bugfix")[0];
        let importantText = document.getElementsByTagName('h5')[0]
        if (importantText.innerHTML == "Good job! You've finished all of your due cards!"){//Finish screen
            let resetText = document.createElement("h5");
            resetText.innerHTML = "Progress bar has been reset";
            parent.insertBefore(resetText,parent.childNodes[1]);
            GM_setValue(doneNumKey,0);
        }
    }
})();


//Put the function here instead of requires due to GreasyFolk rules, original can be found at https://gist.github.com/BrockA/2625891
/*--- waitForKeyElements():  A utility function, for Greasemonkey scripts,
    that detects and handles AJAXed content.

    Usage example:

        waitForKeyElements (
            "div.comments"
            , commentCallbackFunction
        );

        //--- Page-specific function to do what we want when the node is found.
        function commentCallbackFunction (jNode) {
            jNode.text ("This comment changed by waitForKeyElements().");
        }

    IMPORTANT: This function requires your script to have loaded jQuery.
*/
function waitForKeyElements (
    selectorTxt,    /* Required: The jQuery selector string that
                        specifies the desired element(s).
                    */
    actionFunction, /* Required: The code to run when elements are
                        found. It is passed a jNode to the matched
                        element.
                    */
    bWaitOnce,      /* Optional: If false, will continue to scan for
                        new elements even after the first match is
                        found.
                    */
    iframeSelector  /* Optional: If set, identifies the iframe to
                        search.
                    */
) {
    var targetNodes, btargetsFound;

    if (typeof iframeSelector == "undefined")
        targetNodes     = $(selectorTxt);
    else
        targetNodes     = $(iframeSelector).contents ()
                                           .find (selectorTxt);

    if (targetNodes  &&  targetNodes.length > 0) {
        btargetsFound   = true;
        /*--- Found target node(s).  Go through each and act if they
            are new.
        */
        targetNodes.each ( function () {
            var jThis        = $(this);
            var alreadyFound = jThis.data ('alreadyFound')  ||  false;

            if (!alreadyFound) {
                //--- Call the payload function.
                var cancelFound     = actionFunction (jThis);
                if (cancelFound)
                    btargetsFound   = false;
                else
                    jThis.data ('alreadyFound', true);
            }
        } );
    }
    else {
        btargetsFound   = false;
    }

    //--- Get the timer-control variable for this selector.
    var controlObj      = waitForKeyElements.controlObj  ||  {};
    var controlKey      = selectorTxt.replace (/[^\w]/g, "_");
    var timeControl     = controlObj [controlKey];

    //--- Now set or clear the timer as appropriate.
    if (btargetsFound  &&  bWaitOnce  &&  timeControl) {
        //--- The only condition where we need to clear the timer.
        clearInterval (timeControl);
        delete controlObj [controlKey]
    }
    else {
        //--- Set a timer, if needed.
        if ( ! timeControl) {
            timeControl = setInterval ( function () {
                    waitForKeyElements (    selectorTxt,
                                            actionFunction,
                                            bWaitOnce,
                                            iframeSelector
                                        );
                },
                300
            );
            controlObj [controlKey] = timeControl;
        }
    }
    waitForKeyElements.controlObj   = controlObj;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址