Wanikani: Skip to Quiz

Enables the quiz button without having to go through any of the lessons.

目前為 2021-01-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Wanikani: Skip to Quiz
// @namespace    http://tampermonkey.net/
// @version      1.1.0
// @description  Enables the quiz button without having to go through any of the lessons.
// @author       Kumirei
// @match        https://www.wanikani.com/lesson/session
// @match        https://preview.wanikani.com/lesson/session
// @grant        none
// ==/UserScript==
/*global $, wkof */
/*jshint esversion: 9 */

(function() {
    // Make quiz button look clickable
    add_css('#lesson #batch-items ul li[data-index="quiz"] span {background-color: #004fdd; cursor: pointer !important;}','skip-to-quiz-css');

    // Enable clicking quiz button by adding class that the existing click handler
    // checks for before it fires
    onEachElementReady('li[data-index="quiz"]', null, function(e) {
        e = $(e);
        bindFirst(e,'click', function() {
            e.addClass('active-quiz');
        });
    });

    // Library Functions

    // Adds CSS to document
    // Does not escape its input
    function add_css(css, id="") {
        document.getElementsByTagName('head')[0].insertAdjacentHTML('beforeend', `<style id="${id}">${css}</style>`);
    }

    // Calls callback once on each element matching selector that is added
    // to the DOM, including existing elements at the time the function is first called.
    // options is options for the MutationObserver (optional, is merged with default options  {childList: true, subtree: true})
    function onEachElementReady(selector, options, callback) {
        if (!options) options = {};

        let els_found = new Set();
        function check_available() {
            for (const el of document.querySelectorAll(selector)) {
                if (!els_found.has(el)) {
                    els_found.add(el);
                    callback(el);
                }
            }
        }

        queueMicrotask(check_available);

        let mo = new MutationObserver(check_available);
        mo.observe(document.documentElement, {
            childList: true,
            subtree: true,
            ...options,
        });
    }

    // Adds a jQuery event listener that runs before all ones added so far
    // Based on https://stackoverflow.com/questions/2360655/jquery-event-handlers-always-execute-in-order-they-were-bound-any-way-around-t
    // [name] is the name of the event "click", "mouseover", ..
    // same as you'd pass it to bind()
    // [fn] is the handler function
    let bindFirst = function(jqel, name, fn) {
        // bind as you normally would
        // don't want to miss out on any jQuery magic
        jqel.on(name, fn);

        // Thanks to a comment by @Martin, adding support for
        // namespaced events too.
        jqel.each(function() {
            var handlers = $._data(this, 'events')[name.split('.')[0]];
            // take out the handler we just inserted from the end
            var handler = handlers.pop();
            // move it at the beginning
            handlers.splice(0, 0, handler);
        });
    };
})();