Jump to content

MediaWiki:Common.js

From Erindal Wiki
Revision as of 02:32, 14 September 2026 by Miyokari (talk | contribs) (Fix theme toggle label and load homepage recent changes)

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.
/* ========================================================================
   ERINDAL WIKI - VECTOR 2022.JS v1.0
   Skin-specific enhancements. Common.js continues to own article behaviour.
   ======================================================================== */

( function () {
    'use strict';

    var themeKey = 'erindal-theme';
    var sidebarKey = 'erindal-sidebar';
    var themes = [ 'system', 'light', 'dark' ];

    function onReady( callback ) {
        if ( document.readyState === 'loading' ) {
            document.addEventListener( 'DOMContentLoaded', callback, { once: true } );
        } else {
            callback();
        }
    }

    function readTheme() {
        var value = 'system';

        try {
            value = window.localStorage.getItem( themeKey ) || 'system';
        } catch ( error ) {
            value = 'system';
        }

        return themes.indexOf( value ) === -1 ? 'system' : value;
    }

    function applyTheme( value ) {
        document.documentElement.setAttribute( 'data-ew-theme', value );

        try {
            window.localStorage.setItem( themeKey, value );
        } catch ( error ) {
            /* The selected mode still applies to the current page. */
        }
    }

    function installThemeToggle() {
        var topbar = document.getElementById( 'ew-server-topbar' );
        if ( !topbar || document.getElementById( 'ew-theme-toggle' ) ) {
            return;
        }

        var tools = topbar.querySelector( '.ew-topbar-tools' );
        if ( !tools ) {
            tools = document.createElement( 'div' );
            tools.className = 'ew-topbar-tools';
            topbar.appendChild( tools );
        }

        var button = document.createElement( 'button' );
        button.id = 'ew-theme-toggle';
        button.type = 'button';

        function updateButton() {
            var value = readTheme();
            var labels = {
                system: '\u25d0 Auto',
                light: '\u2600 Light',
                dark: '\u263e Dark'
            };

            button.textContent = labels[ value ];
            button.dataset.ewTheme = value;
            button.setAttribute( 'aria-label', labels[ value ] + ' colour mode. Activate to change mode.' );
            button.title = labels[ value ] + ' colour mode';
        }

        button.addEventListener( 'click', function () {
            var current = readTheme();
            var next = themes[ ( themes.indexOf( current ) + 1 ) % themes.length ];
            applyTheme( next );
            updateButton();
        } );

        tools.appendChild( button );
        applyTheme( readTheme() );
        updateButton();
    }

    function installSidebarToggleFallback() {
        var button = document.getElementById( 'ew-sidebar-toggle' );
        if ( !button || button.dataset.ewVectorBound === '1' || button.getAttribute( 'data-ew-bound' ) === '1' ) {
            return;
        }

        button.dataset.ewVectorBound = '1';

        function updateButton() {
            var collapsed = document.documentElement.classList.contains( 'ew-sidebar-collapsed' );
            button.textContent = collapsed ? '\u203a' : '\u2039';
            button.setAttribute( 'aria-expanded', collapsed ? 'false' : 'true' );
            button.setAttribute( 'aria-label', collapsed ? 'Open sidebar' : 'Close sidebar' );
            button.title = collapsed ? 'Open sidebar' : 'Close sidebar';
        }

        button.addEventListener( 'click', function () {
            var collapsed = document.documentElement.classList.toggle( 'ew-sidebar-collapsed' );

            try {
                window.localStorage.setItem( sidebarKey, collapsed ? 'collapsed' : 'open' );
            } catch ( error ) {
                /* The button still works for the current page. */
            }

            updateButton();
        } );

        updateButton();
    }

    function installTopbarDetails() {
        var topbar = document.getElementById( 'ew-server-topbar' );
        if ( !topbar || topbar.dataset.ewDetailsBound === '1' ) {
            return;
        }

        topbar.dataset.ewDetailsBound = '1';

        Array.prototype.forEach.call( topbar.querySelectorAll( 'details.ew-global-section' ), function ( section ) {
            section.addEventListener( 'toggle', function () {
                if ( !section.open ) {
                    return;
                }

                Array.prototype.forEach.call( topbar.querySelectorAll( 'details.ew-global-section[open]' ), function ( other ) {
                    if ( other !== section ) {
                        other.open = false;
                    }
                } );
            } );
        } );

        document.addEventListener( 'click', function ( event ) {
            if ( topbar.contains( event.target ) ) {
                return;
            }

            Array.prototype.forEach.call( topbar.querySelectorAll( 'details.ew-global-section[open]' ), function ( section ) {
                section.open = false;
            } );
        } );

        document.addEventListener( 'keydown', function ( event ) {
            if ( event.key !== 'Escape' ) {
                return;
            }

            Array.prototype.forEach.call( topbar.querySelectorAll( 'details.ew-global-section[open]' ), function ( section ) {
                section.open = false;
            } );
        } );
    }

    function installRecentChanges() {
        var container = document.querySelector( '.ew-recent .ew-recent-list' );
        if ( !container ) {
            return;
        }

        function showUnavailable() {
            container.textContent = 'Recent changes are temporarily unavailable.';
        }

        mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).then( function () {
            var api = new mw.Api();
            return api.get( {
                action: 'query',
                list: 'recentchanges',
                rcnamespace: 0,
                rcprop: 'title|timestamp',
                rclimit: 5,
                rcshow: '!bot'
            } );
        } ).then( function ( data ) {
            var changes = data && data.query ? data.query.recentchanges : [];

            if ( !changes || !changes.length ) {
                container.textContent = 'No recent changes yet.';
                return;
            }

            container.textContent = '';
            changes.forEach( function ( change ) {
                var row = document.createElement( 'div' );
                var icon = document.createElement( 'span' );
                var details = document.createElement( 'div' );
                var link = document.createElement( 'a' );
                var meta = document.createElement( 'small' );
                var date = new Date( change.timestamp );

                row.className = 'ew-recent-row';
                icon.className = 'ew-recent-icon';
                icon.setAttribute( 'aria-hidden', 'true' );
                icon.textContent = '\u25c6';
                link.href = mw.util.getUrl( change.title );
                link.textContent = change.title;
                meta.textContent = 'Updated ' + date.toLocaleDateString( undefined, {
                    year: 'numeric',
                    month: 'short',
                    day: 'numeric'
                } );

                details.appendChild( link );
                details.appendChild( meta );
                row.appendChild( icon );
                row.appendChild( details );
                container.appendChild( row );
            } );
        }, showUnavailable );
    }

    onReady( function () {
        installThemeToggle();
        installSidebarToggleFallback();
        installTopbarDetails();
        installRecentChanges();
    } );
}() );