Jump to content

MediaWiki:Common.js

From Roovet Data
Revision as of 20:24, 20 July 2026 by Maintenance script (talk | contribs) (Remove non-Main header DOM grouping and restore native structure v2T)

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.
/* RV_DATA_MAIN_PAGE_VIEWPORT_CENTER_V2D_START */
(function () {
    "use strict";

    if (
        !document.body ||
        !document.body.classList.contains(
            "page-Main_Page"
        )
    ) {
        return;
    }

    var animationFrame = 0;
    var resizeTimer = 0;

    function setImportant(element, property, value) {
        if (!element) {
            return;
        }

        element.style.setProperty(
            property,
            value,
            "important"
        );
    }

    function releaseAncestorClipping(home) {
        var current = home.parentElement;

        while (
            current &&
            current !== document.body
        ) {
            setImportant(
                current,
                "overflow-x",
                "visible"
            );

            current = current.parentElement;
        }

        setImportant(
            document.body,
            "overflow-x",
            "hidden"
        );

        setImportant(
            document.documentElement,
            "overflow-x",
            "hidden"
        );
    }

    function centerHomepage() {
        var home = document.querySelector(
            ".rdx-home"
        );

        if (!home) {
            return;
        }

        releaseAncestorClipping(home);

        var viewportWidth =
            document.documentElement.clientWidth ||
            window.innerWidth ||
            0;

        if (!viewportWidth) {
            return;
        }

        var gutter;

        if (viewportWidth <= 700) {
            gutter = 0;
        } else if (viewportWidth <= 1100) {
            gutter = 16;
        } else {
            gutter = 32;
        }

        var availableWidth =
            viewportWidth - (gutter * 2);

        var targetWidth = Math.min(
            1180,
            availableWidth
        );

        targetWidth = Math.max(
            320,
            targetWidth
        );

        /*
         * Reset all earlier CSS positioning before
         * measuring the element's natural browser
         * location.
         */
        setImportant(
            home,
            "position",
            "relative"
        );

        setImportant(
            home,
            "left",
            "0"
        );

        setImportant(
            home,
            "right",
            "auto"
        );

        setImportant(
            home,
            "width",
            targetWidth + "px"
        );

        setImportant(
            home,
            "max-width",
            "none"
        );

        setImportant(
            home,
            "margin-left",
            "0"
        );

        setImportant(
            home,
            "margin-right",
            "0"
        );

        setImportant(
            home,
            "transform",
            "none"
        );

        /*
         * Force layout calculation after removing
         * all previous transforms.
         */
        void home.offsetWidth;

        var rectangle =
            home.getBoundingClientRect();

        var desiredLeft = Math.round(
            (viewportWidth - targetWidth) / 2
        );

        var correction = Math.round(
            desiredLeft - rectangle.left
        );

        setImportant(
            home,
            "transform",
            "translate3d(" +
                correction +
                "px, 0, 0)"
        );

        home.setAttribute(
            "data-rdx-viewport-centered",
            "true"
        );

        home.setAttribute(
            "data-rdx-viewport-width",
            String(viewportWidth)
        );

        home.setAttribute(
            "data-rdx-target-width",
            String(targetWidth)
        );

        home.setAttribute(
            "data-rdx-original-left",
            String(
                Math.round(rectangle.left)
            )
        );

        home.setAttribute(
            "data-rdx-correction",
            String(correction)
        );

        /*
         * Verify the rendered result and perform one
         * final adjustment for sub-pixel browser
         * rounding or delayed Vector layout changes.
         */
        window.requestAnimationFrame(
            function () {
                var finalRectangle =
                    home.getBoundingClientRect();

                var remainingDifference =
                    Math.round(
                        desiredLeft -
                        finalRectangle.left
                    );

                if (
                    Math.abs(
                        remainingDifference
                    ) > 1
                ) {
                    correction +=
                        remainingDifference;

                    setImportant(
                        home,
                        "transform",
                        "translate3d(" +
                            correction +
                            "px, 0, 0)"
                    );

                    home.setAttribute(
                        "data-rdx-correction",
                        String(correction)
                    );
                }

                home.setAttribute(
                    "data-rdx-final-left",
                    String(
                        Math.round(
                            home
                                .getBoundingClientRect()
                                .left
                        )
                    )
                );
            }
        );
    }

    function queueCentering() {
        if (animationFrame) {
            window.cancelAnimationFrame(
                animationFrame
            );
        }

        animationFrame =
            window.requestAnimationFrame(
                function () {
                    animationFrame =
                        window.requestAnimationFrame(
                            centerHomepage
                        );
                }
            );
    }

    function delayedCentering() {
        window.clearTimeout(
            resizeTimer
        );

        resizeTimer = window.setTimeout(
            queueCentering,
            80
        );
    }

    if (
        document.readyState === "loading"
    ) {
        document.addEventListener(
            "DOMContentLoaded",
            queueCentering,
            {
                once: true
            }
        );
    } else {
        queueCentering();
    }

    window.addEventListener(
        "load",
        queueCentering
    );

    window.addEventListener(
        "resize",
        delayedCentering
    );

    if (window.visualViewport) {
        window.visualViewport.addEventListener(
            "resize",
            delayedCentering
        );
    }

    /*
     * Vector and ResourceLoader can finish portions
     * of their layout after DOM ready. Recheck after
     * those delayed changes.
     */
    window.setTimeout(
        queueCentering,
        250
    );

    window.setTimeout(
        queueCentering,
        750
    );

    window.setTimeout(
        queueCentering,
        1500
    );
}());
/* RV_DATA_MAIN_PAGE_VIEWPORT_CENTER_V2D_END */

/* RV_DATA_HEADER_CLICK_FIX_V2O_START */
(function () {
    "use strict";

    if (
        !document.body ||
        !document.body.classList.contains(
            "page-Main_Page"
        )
    ) {
        return;
    }

    function important(
        element,
        property,
        value
    ) {
        if (!element) {
            return;
        }

        element.style.setProperty(
            property,
            value,
            "important"
        );
    }

    function moveToolsOnce() {
        var views =
            document.getElementById(
                "p-views"
            );

        var tools =
            document.getElementById(
                "vector-page-tools-dropdown"
            )
            ||
            document.querySelector(
                ".vector-page-tools-landmark"
            );

        if (
            !views ||
            !tools ||
            !views.parentNode
        ) {
            return;
        }

        if (
            tools.parentNode !==
            views.parentNode
            ||
            tools.previousElementSibling !==
            views
        ) {
            views.parentNode.insertBefore(
                tools,
                views.nextSibling
            );
        }

        tools.classList.add(
            "rv-tools-inline"
        );

        tools.setAttribute(
            "data-rv-tools-inline",
            "2o"
        );
    }

    function getHeaderTargets() {
        var selectors = [
            "#vector-appearance-dropdown > .vector-dropdown-label",
            "#vector-appearance-dropdown button",
            "#pt-createaccount-2 > a",
            "#pt-createaccount > a",
            "#pt-login-2 > a",
            "#pt-login > a",
            "#vector-user-links-dropdown > .vector-dropdown-label",
            "#vector-user-links-dropdown button"
        ];

        var targets = [];

        selectors.forEach(
            function (selector) {
                document
                    .querySelectorAll(selector)
                    .forEach(
                        function (element) {
                            if (
                                targets.indexOf(
                                    element
                                ) === -1
                            ) {
                                targets.push(
                                    element
                                );
                            }
                        }
                    );
            }
        );

        return targets;
    }

    function raiseHeaderControls() {
        var headerContainer =
            document.querySelector(
                ".vector-header-container"
            );

        var header =
            document.querySelector(
                ".vector-header"
            );

        var headerEnd =
            document.querySelector(
                ".vector-header-end"
            );

        important(
            headerContainer,
            "position",
            "relative"
        );

        important(
            headerContainer,
            "z-index",
            "2147482000"
        );

        important(
            headerContainer,
            "overflow",
            "visible"
        );

        important(
            headerContainer,
            "pointer-events",
            "auto"
        );

        important(
            header,
            "position",
            "relative"
        );

        important(
            header,
            "z-index",
            "1"
        );

        important(
            header,
            "overflow",
            "visible"
        );

        important(
            header,
            "pointer-events",
            "auto"
        );

        important(
            headerEnd,
            "position",
            "relative"
        );

        important(
            headerEnd,
            "z-index",
            "100"
        );

        important(
            headerEnd,
            "overflow",
            "visible"
        );

        important(
            headerEnd,
            "pointer-events",
            "auto"
        );

        getHeaderTargets().forEach(
            function (target) {
                important(
                    target,
                    "position",
                    "relative"
                );

                important(
                    target,
                    "z-index",
                    "110"
                );

                important(
                    target,
                    "pointer-events",
                    "auto"
                );

                important(
                    target,
                    "touch-action",
                    "manipulation"
                );

                target.setAttribute(
                    "data-rv-click-ready",
                    "2o"
                );
            }
        );
    }

    function auditHeaderTargets() {
        var report = [];

        getHeaderTargets().forEach(
            function (target) {
                var rectangle =
                    target.getBoundingClientRect();

                if (
                    rectangle.width <= 0
                    ||
                    rectangle.height <= 0
                ) {
                    return;
                }

                var x =
                    Math.round(
                        rectangle.left
                        +
                        rectangle.width / 2
                    );

                var y =
                    Math.round(
                        rectangle.top
                        +
                        rectangle.height / 2
                    );

                var topElement =
                    document.elementFromPoint(
                        x,
                        y
                    );

                var related = Boolean(
                    topElement
                    &&
                    (
                        topElement === target
                        ||
                        target.contains(
                            topElement
                        )
                        ||
                        topElement.contains(
                            target
                        )
                    )
                );

                report.push({
                    target:
                        target.id
                        ||
                        target.className
                        ||
                        target.tagName,

                    text:
                        (
                            target.textContent
                            ||
                            target.getAttribute(
                                "aria-label"
                            )
                            ||
                            ""
                        ).trim(),

                    clickable: related,

                    topElement:
                        topElement
                        ?
                        (
                            topElement.id
                            ||
                            topElement.className
                            ||
                            topElement.tagName
                        )
                        :
                        null
                });
            }
        );

        window.roovetHeaderClickAudit =
            report;

        document.body.setAttribute(
            "data-rv-header-click-ready",
            "2o"
        );

        document.body.setAttribute(
            "data-rv-header-target-count",
            String(report.length)
        );

        document.body.setAttribute(
            "data-rv-header-clickable-count",
            String(
                report.filter(
                    function (entry) {
                        return entry.clickable;
                    }
                ).length
            )
        );
    }

    function initialize() {
        moveToolsOnce();
        raiseHeaderControls();

        window.requestAnimationFrame(
            function () {
                raiseHeaderControls();
                auditHeaderTargets();
            }
        );
    }

    if (
        document.readyState ===
        "loading"
    ) {
        document.addEventListener(
            "DOMContentLoaded",
            initialize,
            {
                once: true
            }
        );
    } else {
        initialize();
    }

    window.addEventListener(
        "load",
        initialize,
        {
            once: true
        }
    );

    /*
     * Vector and ResourceLoader may finish individual
     * controls shortly after page load.
     */
    window.setTimeout(
        initialize,
        150
    );

    window.setTimeout(
        initialize,
        500
    );

    window.setTimeout(
        initialize,
        1200
    );
}());
/* RV_DATA_HEADER_CLICK_FIX_V2O_END */

/* RV_DATA_NATIVE_NONMAIN_HEADER_V2T_START */
(function () {
    "use strict";

    if (
        !document.body
        ||
        document.body.classList.contains(
            "page-Main_Page"
        )
        ||
        !document.body.classList.contains(
            "skin-vector-2022"
        )
    ) {
        return;
    }

    function restoreNativeUserLinks() {
        var host =
            document.getElementById(
                "rv-universal-user-row"
            );

        if (!host) {
            document.body.setAttribute(
                "data-rv-native-user-row",
                "2t"
            );

            return;
        }

        var userLinks =
            host.parentNode;

        if (!userLinks) {
            return;
        }

        /*
         * Restore the original logical order:
         *
         * Appearance
         * Create account / Log in
         * Personal tools
         */
        while (host.firstChild) {
            userLinks.insertBefore(
                host.firstChild,
                host
            );
        }

        host.parentNode.removeChild(
            host
        );

        document.body.setAttribute(
            "data-rv-native-user-row",
            "2t"
        );
    }

    function initialize() {
        window.requestAnimationFrame(
            function () {
                window.requestAnimationFrame(
                    restoreNativeUserLinks
                );
            }
        );
    }

    if (
        document.readyState === "loading"
    ) {
        document.addEventListener(
            "DOMContentLoaded",
            initialize,
            {
                once: true
            }
        );
    } else {
        initialize();
    }

    window.addEventListener(
        "load",
        initialize,
        {
            once: true
        }
    );

    window.setTimeout(
        initialize,
        150
    );

    window.setTimeout(
        initialize,
        500
    );

    window.setTimeout(
        initialize,
        1200
    );
}());
/* RV_DATA_NATIVE_NONMAIN_HEADER_V2T_END */