Wait For Selector

Waits for selectors to match newly added nodes

Per 14-09-2021. Zie de nieuwste versie.

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/432418/970669/Wait%20For%20Selector.js

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Wait For Selector
// @version      0.1.0
// @description  Waits for selectors to match newly added nodes
// @author       Kumirei
// @include      *community.wanikani.com*
// @grant        none
// ==/UserScript==

(function($) {
    // Create new observer on body to monitor all DOM changes
    let observer = new MutationObserver(mutationHandler)
    observer.observe(document.getElementsByTagName('body')[0], {childList: true, subtree: true})

    // Interface for interacting with the library
    let interface = {
        version: GM_info.script.version,
        observer: observer,
        wait: waitForSelector,
        unwait: unwaitID,
        waits: {},
        waitsByID: {},
        nextID: 0
    }

    // Start
    installInterface()

    // Creates a new entry to search for whenever a new element is added to the DOM
    function waitForSelector(preSelector, selector, callback) {
        if (selector.match(`${preSelector}$`) === null) throw ('preSelector must match the end of the selector')
        if (!interface.waits[selector]) interface.waits[selector] = {}
        interface.waits[selector][interface.nextID] = callback
        interface.waits[selector].pre = preSelector
        interface.waitsByID[interface.nextID] = selector
        return interface.nextID++
    }

    // Deletes a previously registered selector
    function unwaitID(ID) {
        delete interface.waits[interface.waitsByID[ID]][ID]
    }

    // Makes sure that the public interface is the newest version and the same as the local one
    function installInterface() {
        let wfs = window.wkfe
        if (!wfs) window.wfs = interface
        else if (wfs.version < interface.version) {
            wfs.version = interface.version
            wfs.observer.disconnect()
            wfs.observer = interface.observer
            wfs.wait = interface.wait
            wfs.unwait = interface.unwait
        }
        interface = wfs || interface
    }

    // Searches the added nodes and matches them with the provided selectors. Calls the callback for every match.
    function mutationHandler(mutations) {
        for (let mutation of mutations) {
            let added = mutation.addedNodes
            for (let node of added) {
                if (node.nodeType === 1) {
                    let sibling = node.previousElementSibling
                    let target = sibling ? sibling : node.parentElement
                    for (let selector in interface.waits) {
                        let query = (sibling?'+ ':'> ')+interface.waits[selector].pre
                        $(target).find(query).each((i, e)=>{
                            $(selector).each((I, E)=>{
                                if (e.isSameNode(E)) {
                                    for (let callback of Object.values(interface.waits[selector])) {
                                        if (typeof callback === "function") callback(E)
                                    }
                                }
                            })
                        })
                    }
                }
            }
        }
    }
})(window.jQuery);