MediaWiki:Gadget-CollapseAllButton.js

From Space Station 14 Wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/** Class name of an element that holds a collapse all button. */
const collapseAllButtonContainerClass = "collapsible-toggle-container";

/** Class name of an actual collapse all button. */
const collapseAllButtonClass = "mw-collapsible-toggle";

/** Data attribute on the collapse all button container element, 
 * that specifies a class name for a collapsable elements container that the collapse all button shall target. */
const collapsibleContainerDataAttr = "data-target-class";

/** The initial part of a custom toggle class name. */
const customToggleClassPrefix = "mw-customtoggle";

/** Class name for collapsible elements. */
const collapsibleClass = "mw-collapsible";

/** Class name for collapsed elements. */
const collapsedClass = "mw-collapsed";

const logPrefix = "Gadget-ExpandAllReagents"

// ===========

mw.hook('wikipage.content').add((content) => {
    /** @type {HTMLElement} */
    const contentEl = content[0];

    // small timeout to prevent race condition with underlying jquery
    // that works the collapsible magic.
    setTimeout(() => {
        for (const collapseAllButtonContainerEl of contentEl.getElementsByClassName(collapseAllButtonContainerClass)) {
            const collapseAllButton = collapseAllButtonContainerEl.getElementsByClassName(collapseAllButtonClass)[0];
            if (!collapseAllButton) {
                logWarn("failed to find a collapse all button inside a collapse all button container element");
                console.warn({
                    collapseAllButtonContainerEl
                })
                continue;
            }

            const collapsibleContainerClass = collapseAllButtonContainerEl.getAttribute(collapsibleContainerDataAttr);
            if (!collapsibleContainerClass) {
                logWarn("collapsible container data attribute not found on the collapse all button container element");
                console.warn({
                    collapseAllButtonContainerEl
                })
                continue;
            }

            let toggleEls = new Set();
            /** Whether the initial querying of the toggle elements has been done. */
            let initialized = false;

            collapseAllButton.addEventListener('click', () => {
                if (!initialized) {
                    const collapsibleContainerEls = contentEl.getElementsByClassName(collapsibleContainerClass);

                    for (const collapsibleContainerEl of collapsibleContainerEls) {
                        for (const toggleEl of collapsibleContainerEl.querySelectorAll(`[class*='${customToggleClassPrefix}']`)) {
                            toggleEls.add(toggleEl);
                        }
                    }

                    initialized = true;
                }

                toggleEls.forEach(el => el.click());
            });
        }
    }, 250)
});

// ===========

function joinLogPrefixWithMessage(msg) {
    return logPrefix + " " + msg;
}

function logWarn(msg) {
    console.warn(joinLogPrefixWithMessage(msg));
}

function throwErr(msg) {
    throw new Error(joinLogPrefixWithMessage(msg));
}