Contents

MediaWiki:Common.js: Difference between revisions

No edit summary
No edit summary
Line 1: Line 1:
/* ============================================================
/* ============================================================
   WIKIPARTNER
   WIKIPARTNER
   THEME + LOGGED-IN USER MENU
   THEME + USER MENU
============================================================ */
============================================================ */


Line 18: Line 18:
     function getSavedTheme() {
     function getSavedTheme() {
         try {
         try {
             var saved = window.localStorage.getItem(STORAGE_KEY);
             var saved = window.localStorage.getItem(
                STORAGE_KEY
            );


             if (saved === LIGHT || saved === DARK) {
             if (
                saved === LIGHT ||
                saved === DARK
            ) {
                 return saved;
                 return saved;
             }
             }
Line 33: Line 38:
     function saveTheme(theme) {
     function saveTheme(theme) {
         try {
         try {
             window.localStorage.setItem(STORAGE_KEY, theme);
             window.localStorage.setItem(
                STORAGE_KEY,
                theme
            );
         } catch (e) {
         } catch (e) {
             /* localStorage unavailable */
             /* localStorage unavailable */
Line 41: Line 49:


     /* ========================================================
     /* ========================================================
       THEME STATE
       CURRENT THEME
     ======================================================== */
     ======================================================== */


     function getCurrentTheme() {
     function getCurrentTheme() {
         return document.documentElement.classList.contains(
         return document.documentElement
            'wp-theme-dark'
            .classList.contains(
        )
                'wp-theme-dark'
            )
             ? DARK
             ? DARK
             : LIGHT;
             : LIGHT;
     }
     }


    /* ========================================================
      APPLY THEME
    ======================================================== */


     function applyTheme(theme, shouldSave) {
     function applyTheme(theme, shouldSave) {
         var html = document.documentElement;
         var html =
         var isDark = theme === DARK;
            document.documentElement;
 
         var isDark =
            theme === DARK;
 


         html.classList.toggle(
         html.classList.toggle(
Line 67: Line 84:
         );
         );


        /*
        * Keep MediaWiki-compatible theme classes too.
        */
         html.classList.remove(
         html.classList.remove(
             'skin-theme-clientpref-day',
             'skin-theme-clientpref-day',
Line 72: Line 93:
             'skin-theme-clientpref-os'
             'skin-theme-clientpref-os'
         );
         );


         html.classList.add(
         html.classList.add(
Line 78: Line 100:
                 : 'skin-theme-clientpref-day'
                 : 'skin-theme-clientpref-day'
         );
         );


         html.setAttribute(
         html.setAttribute(
             'data-wikipartner-theme',
             'data-wikipartner-theme',
             isDark ? DARK : LIGHT
             isDark
                ? DARK
                : LIGHT
         );
         );


         if (shouldSave !== false) {
         if (shouldSave !== false) {
             saveTheme(theme);
             saveTheme(theme);
         }
         }


         updateThemeButton();
         updateThemeButton();
Line 137: Line 164:


     function updateThemeButton() {
     function updateThemeButton() {
         var button = document.getElementById(
         var button =
            'wikipartner-theme-toggle'
            document.getElementById(
        );
                'wikipartner-theme-toggle'
            );
 


         if (!button) {
         if (!button) {
             return;
             return;
         }
         }


         var isDark =
         var isDark =
             getCurrentTheme() === DARK;
             getCurrentTheme() === DARK;


         button.innerHTML =
         button.innerHTML =
Line 155: Line 186:
                         : getMoonIcon()
                         : getMoonIcon()
                 ) +
                 ) +
             '</span>' +
             '</span>';


            '<span class="wp-theme-menu-label">' +
                (
                    isDark
                        ? 'Light mode'
                        : 'Dark mode'
                ) +
            '</span>';


         button.setAttribute(
         button.setAttribute(
Line 171: Line 195:
                 : 'Switch to dark mode'
                 : 'Switch to dark mode'
         );
         );


         button.setAttribute(
         button.setAttribute(
Line 190: Line 215:
                 'wikipartner-theme-item'
                 'wikipartner-theme-item'
             );
             );


         if (existing) {
         if (existing) {
Line 198: Line 224:
         var item =
         var item =
             document.createElement('li');
             document.createElement('li');


         item.id =
         item.id =
             'wikipartner-theme-item';
             'wikipartner-theme-item';


         item.className =
         item.className =
             'mw-list-item wikipartner-theme-item';
             'mw-list-item ' +
            'wikipartner-theme-item';




         var button =
         var button =
             document.createElement('button');
             document.createElement(
                'button'
            );
 


         button.id =
         button.id =
             'wikipartner-theme-toggle';
             'wikipartner-theme-toggle';


         button.className =
         button.className =
             'wikipartner-theme-toggle';
             'wikipartner-theme-toggle';


         button.type = 'button';
 
         button.type =
            'button';




Line 226: Line 261:
                         ? LIGHT
                         ? LIGHT
                         : DARK;
                         : DARK;


                 applyTheme(
                 applyTheme(
Line 235: Line 271:




         item.appendChild(button);
         item.appendChild(
            button
        );




         var loginItem =
         updateThemeButton();
            list.querySelector(
                '#pt-login'
            );
 
 
        if (loginItem) {
 
            /*
            * LOGGED OUT:
            *
            * Create account | Theme | Log in
            */


            list.insertBefore(
                item,
                loginItem
            );
        } else {
            list.appendChild(
                item
            );
        }
        updateThemeButton();


         return item;
         return item;
Line 288: Line 299:


     /* ========================================================
     /* ========================================================
       LOGGED-IN USER MENU
      FIND / CLEAN USERNAME
    ======================================================== */
 
    function cleanUsernameDuplicates(
        primary,
        list
    ) {
        var username =
            mw.config.get(
                'wgUserName'
            );
 
 
        if (!username) {
            return;
        }
 
 
        /*
        * MediaWiki's data-user-page already puts
        * the username in .wp-user-primary.
        *
        * Some personal-menu configurations can
        * also provide another user-page link.
        * Remove that duplicate from the menu.
        */
 
        var items =
            Array.prototype.slice.call(
                list.children
            );
 
 
        items.forEach(
            function (item) {
 
                var link =
                    item.querySelector('a');
 
 
                var linkText =
                    link
                        ? link.textContent.trim()
                        : '';
 
 
                var isUserPageId =
                    item.id === 'pt-userpage' ||
                    item.id === 'pt-userpage-2';
 
 
                var isUsername =
                    linkText === username;
 
 
                if (
                    isUserPageId ||
                    isUsername
                ) {
 
                    /*
                    * If primary somehow has no username,
                    * move this one there instead.
                    */
                    if (
                        primary &&
                        !primary.querySelector('li')
                    ) {
 
                        primary.appendChild(
                            item
                        );
 
                    } else {
 
                        item.remove();
 
                    }
                }
            }
        );
    }
 
 
    /* ========================================================
       LOGGED OUT LAYOUT
     ======================================================== */
     ======================================================== */


     function buildLoggedInUserMenu(
     function buildLoggedOutLayout(
         list,
         list,
         themeItem
         themeItem
     ) {
     ) {
        list.classList.remove(
            'wp-is-logged-in'
        );
        list.classList.add(
            'wp-is-logged-out'
        );


        /*
        * #pt-logout exists only when
        * MediaWiki sees an authenticated user.
        */


         var logoutItem =
         var loginItem =
             list.querySelector(
             list.querySelector(
                 '#pt-logout'
                 '#pt-login'
             );
             );




         if (!logoutItem) {
         /*
        * Desired layout:
        *
        * Create account | Theme | Log in
        */


            /*
        if (loginItem) {
            * LOGGED OUT
            */


             list.classList.remove(
             list.insertBefore(
                 'wp-is-logged-in'
                 themeItem,
                loginItem
             );
             );


             list.classList.add(
        } else {
                 'wp-is-logged-out'
 
             list.appendChild(
                 themeItem
             );
             );


            return;
         }
         }
    }




        /*
    /* ========================================================
        * LOGGED IN
      LOGGED IN LAYOUT
        */
    ======================================================== */


    function buildLoggedInLayout(
        primary,
        list,
        themeItem
    ) {
         list.classList.remove(
         list.classList.remove(
             'wp-is-logged-out'
             'wp-is-logged-out'
Line 335: Line 444:
         list.classList.add(
         list.classList.add(
             'wp-is-logged-in'
             'wp-is-logged-in'
        );
        cleanUsernameDuplicates(
            primary,
            list
         );
         );




         /*
         /*
         * Prevent duplicate hamburger menus.
         * Remove an old dropdown if ResourceLoader
        * initialization somehow runs again.
         */
         */


         if (
         var oldDropdown =
             list.querySelector(
             list.querySelector(
                 '.wp-user-dropdown'
                 '.wp-user-dropdown'
             )
             );
         ) {
 
 
         if (oldDropdown) {
             return;
             return;
         }
         }
        /*
        * Username stays OUTSIDE.
        */
        var usernameItem =
            list.querySelector(
                '#pt-userpage'
            );




         /* ====================================================
         /* ====================================================
           CREATE DROPDOWN WRAPPER
           CREATE HAMBURGER WRAPPER
         ==================================================== */
         ==================================================== */


         var dropdown =
         var dropdown =
             document.createElement('li');
             document.createElement('li');


         dropdown.className =
         dropdown.className =
Line 373: Line 482:


         /* ====================================================
         /* ====================================================
           CREATE HAMBURGER BUTTON
           HAMBURGER BUTTON
         ==================================================== */
         ==================================================== */


Line 380: Line 489:
                 'button'
                 'button'
             );
             );


         trigger.type =
         trigger.type =
             'button';
             'button';


         trigger.className =
         trigger.className =
             'wp-user-menu-trigger';
             'wp-user-menu-trigger';


         trigger.setAttribute(
         trigger.setAttribute(
Line 391: Line 503:
             'Open user menu'
             'Open user menu'
         );
         );


         trigger.setAttribute(
         trigger.setAttribute(
Line 396: Line 509:
             'User menu'
             'User menu'
         );
         );


         trigger.setAttribute(
         trigger.setAttribute(
Line 401: Line 515:
             'false'
             'false'
         );
         );


         trigger.innerHTML =
         trigger.innerHTML =
Line 407: Line 522:


         /* ====================================================
         /* ====================================================
           CREATE DROPDOWN MENU
           DROPDOWN CONTENT
         ==================================================== */
         ==================================================== */


         var menu =
         var menu =
             document.createElement('ul');
             document.createElement('ul');


         menu.className =
         menu.className =
             'wp-user-dropdown-menu';
             'wp-user-dropdown-menu';


         menu.hidden =
         menu.hidden =
             true;
             true;


        /* ====================================================
          MOVE USER LINKS
        ==================================================== */


         /*
         /*
         * ONLY THESE REMAIN OUTSIDE:
         * Move every existing menu item
        * into ☰.
         *
         *
         * Username
         * Username is NOT in this list anymore.
         * Theme button
         * Theme is not inserted yet.
        *
        * Everything else moves inside ☰
         */
         */


         Array.prototype
         Array.prototype
             .slice
             .slice.call(
            .call(list.children)
                list.children
            )
             .forEach(
             .forEach(
                 function (item) {
                 function (item) {


                     if (
                     if (
                         item === usernameItem ||
                         item !== themeItem &&
                         item === themeItem
                         item !== dropdown
                     ) {
                     ) {
                         return;
 
                         menu.appendChild(
                            item
                        );
                     }
                     }
                    menu.appendChild(
                        item
                    );
                 }
                 }
             );
             );
Line 456: Line 568:
             trigger
             trigger
         );
         );


         dropdown.appendChild(
         dropdown.appendChild(
Line 461: Line 574:
         );
         );


        /* ====================================================
          FORCE EXACT HEADER ORDER
        ==================================================== */


         /*
         /*
        * Exact layout:
        *
         * Username | Theme | ☰
         * Username | Theme | ☰
        *
        * Username lives in .wp-user-primary,
        * while theme and hamburger live here.
         */
         */


 
         list.appendChild(
         if (usernameItem) {
             themeItem
 
         );
            list.appendChild(
                usernameItem
             );
 
        }
 
 
         if (themeItem) {
 
            list.appendChild(
                themeItem
            );
 
        }




Line 495: Line 595:


         /* ====================================================
         /* ====================================================
           OPEN / CLOSE FUNCTIONS
           OPEN / CLOSE
         ==================================================== */
         ==================================================== */


         function closeMenu() {
         function closeMenu() {
             dropdown.classList.remove(
             dropdown.classList.remove(
                 'is-open'
                 'is-open'
             );
             );


             menu.hidden =
             menu.hidden =
                 true;
                 true;


             trigger.setAttribute(
             trigger.setAttribute(
Line 511: Line 612:
                 'false'
                 'false'
             );
             );
         }
         }




         function openMenu() {
         function openMenu() {
             dropdown.classList.add(
             dropdown.classList.add(
                 'is-open'
                 'is-open'
             );
             );


             menu.hidden =
             menu.hidden =
                 false;
                 false;


             trigger.setAttribute(
             trigger.setAttribute(
Line 528: Line 629:
                 'true'
                 'true'
             );
             );
         }
         }




         /* ====================================================
         /* ====================================================
           HAMBURGER CLICK
           CLICK HAMBURGER
         ==================================================== */
         ==================================================== */


Line 541: Line 641:


                 event.preventDefault();
                 event.preventDefault();
                 event.stopPropagation();
                 event.stopPropagation();


Line 558: Line 657:


                 }
                 }
             }
             }
         );
         );
Line 594: Line 692:


                 }
                 }
             }
             }
         );
         );
Line 600: Line 697:


         /* ====================================================
         /* ====================================================
           ESCAPE KEY
           ESCAPE
         ==================================================== */
         ==================================================== */


Line 617: Line 714:


                     trigger.focus();
                     trigger.focus();
                 }
                 }
             }
             }
         );
         );
Line 626: Line 721:


     /* ========================================================
     /* ========================================================
       INITIALIZE USER AREA
       INITIALIZE ACCOUNT AREA
     ======================================================== */
     ======================================================== */


     function initializeUserArea() {
     function initializeUserArea() {
        var primary =
            document.querySelector(
                '.wp-user-primary'
            );


         var list =
         var list =
Line 643: Line 743:


         /*
         /*
         * First create the theme button.
         * Empty username container should not
        * take up space for anonymous users.
         */
         */
        if (
            primary &&
            !primary.querySelector('li')
        ) {
            primary.classList.add(
                'is-empty'
            );
        }


         var themeItem =
         var themeItem =
Line 652: Line 764:




         /*
         var username =
        * Then build logged-in dropdown.
            mw.config.get(
        */
                'wgUserName'
            );
 
 
        if (username) {
 
            buildLoggedInLayout(
                primary,
                list,
                themeItem
            );
 
        } else {


        buildLoggedInUserMenu(
            buildLoggedOutLayout(
            list,
                list,
            themeItem
                themeItem
        );
            );
        }




Line 681: Line 806:


     function initialize() {
     function initialize() {
         initializeUserArea();
         initializeUserArea();
     }
     }



Revision as of 23:50, 19 August 2026

/* ============================================================
   WIKIPARTNER
   THEME + USER MENU
============================================================ */

(function () {
    'use strict';

    var STORAGE_KEY = 'wikipartner-theme';
    var LIGHT = 'light';
    var DARK = 'dark';


    /* ========================================================
       THEME STORAGE
    ======================================================== */

    function getSavedTheme() {
        try {
            var saved = window.localStorage.getItem(
                STORAGE_KEY
            );

            if (
                saved === LIGHT ||
                saved === DARK
            ) {
                return saved;
            }
        } catch (e) {
            /* localStorage unavailable */
        }

        return LIGHT;
    }


    function saveTheme(theme) {
        try {
            window.localStorage.setItem(
                STORAGE_KEY,
                theme
            );
        } catch (e) {
            /* localStorage unavailable */
        }
    }


    /* ========================================================
       CURRENT THEME
    ======================================================== */

    function getCurrentTheme() {
        return document.documentElement
            .classList.contains(
                'wp-theme-dark'
            )
            ? DARK
            : LIGHT;
    }


    /* ========================================================
       APPLY THEME
    ======================================================== */

    function applyTheme(theme, shouldSave) {
        var html =
            document.documentElement;

        var isDark =
            theme === DARK;


        html.classList.toggle(
            'wp-theme-dark',
            isDark
        );

        html.classList.toggle(
            'wp-theme-light',
            !isDark
        );


        /*
         * Keep MediaWiki-compatible theme classes too.
         */
        html.classList.remove(
            'skin-theme-clientpref-day',
            'skin-theme-clientpref-night',
            'skin-theme-clientpref-os'
        );


        html.classList.add(
            isDark
                ? 'skin-theme-clientpref-night'
                : 'skin-theme-clientpref-day'
        );


        html.setAttribute(
            'data-wikipartner-theme',
            isDark
                ? DARK
                : LIGHT
        );


        if (shouldSave !== false) {
            saveTheme(theme);
        }


        updateThemeButton();
    }


    /* ========================================================
       THEME ICONS
    ======================================================== */

    function getMoonIcon() {
        return [
            '<svg viewBox="0 0 24 24" aria-hidden="true">',

                '<path d="M20.3 15.2A8.4 8.4 0 0 1 8.8 3.7 8.5 8.5 0 1 0 11.5 11.5Z"></path>',

                '<path class="wp-theme-star" d="M17.5 4v3M16 5.5h3"></path>',

            '</svg>'
        ].join('');
    }


    function getSunIcon() {
        return [
            '<svg viewBox="0 0 24 24" aria-hidden="true">',

                '<circle cx="12" cy="12" r="3.8"></circle>',

                '<path d="M12 2.3v2.1"></path>',
                '<path d="M12 19.6v2.1"></path>',

                '<path d="M4.93 4.93l1.5 1.5"></path>',
                '<path d="M17.57 17.57l1.5 1.5"></path>',

                '<path d="M2.3 12h2.1"></path>',
                '<path d="M19.6 12h2.1"></path>',

                '<path d="M4.93 19.07l1.5-1.5"></path>',
                '<path d="M17.57 6.43l1.5-1.5"></path>',

            '</svg>'
        ].join('');
    }


    /* ========================================================
       UPDATE THEME BUTTON
    ======================================================== */

    function updateThemeButton() {
        var button =
            document.getElementById(
                'wikipartner-theme-toggle'
            );


        if (!button) {
            return;
        }


        var isDark =
            getCurrentTheme() === DARK;


        button.innerHTML =
            '<span class="wp-theme-icon">' +
                (
                    isDark
                        ? getSunIcon()
                        : getMoonIcon()
                ) +
            '</span>';


        button.setAttribute(
            'aria-label',
            isDark
                ? 'Switch to light mode'
                : 'Switch to dark mode'
        );


        button.setAttribute(
            'title',
            isDark
                ? 'Light mode'
                : 'Dark mode'
        );
    }


    /* ========================================================
       CREATE THEME BUTTON
    ======================================================== */

    function createThemeToggle(list) {
        var existing =
            document.getElementById(
                'wikipartner-theme-item'
            );


        if (existing) {
            return existing;
        }


        var item =
            document.createElement('li');


        item.id =
            'wikipartner-theme-item';


        item.className =
            'mw-list-item ' +
            'wikipartner-theme-item';


        var button =
            document.createElement(
                'button'
            );


        button.id =
            'wikipartner-theme-toggle';


        button.className =
            'wikipartner-theme-toggle';


        button.type =
            'button';


        button.addEventListener(
            'click',
            function () {

                var nextTheme =
                    getCurrentTheme() === DARK
                        ? LIGHT
                        : DARK;


                applyTheme(
                    nextTheme,
                    true
                );
            }
        );


        item.appendChild(
            button
        );


        updateThemeButton();


        return item;
    }


    /* ========================================================
       HAMBURGER ICON
    ======================================================== */

    function getMenuIcon() {
        return [
            '<span class="wp-menu-bars" aria-hidden="true">',
                '<span></span>',
                '<span></span>',
                '<span></span>',
            '</span>'
        ].join('');
    }


    /* ========================================================
       FIND / CLEAN USERNAME
    ======================================================== */

    function cleanUsernameDuplicates(
        primary,
        list
    ) {
        var username =
            mw.config.get(
                'wgUserName'
            );


        if (!username) {
            return;
        }


        /*
         * MediaWiki's data-user-page already puts
         * the username in .wp-user-primary.
         *
         * Some personal-menu configurations can
         * also provide another user-page link.
         * Remove that duplicate from the menu.
         */

        var items =
            Array.prototype.slice.call(
                list.children
            );


        items.forEach(
            function (item) {

                var link =
                    item.querySelector('a');


                var linkText =
                    link
                        ? link.textContent.trim()
                        : '';


                var isUserPageId =
                    item.id === 'pt-userpage' ||
                    item.id === 'pt-userpage-2';


                var isUsername =
                    linkText === username;


                if (
                    isUserPageId ||
                    isUsername
                ) {

                    /*
                     * If primary somehow has no username,
                     * move this one there instead.
                     */
                    if (
                        primary &&
                        !primary.querySelector('li')
                    ) {

                        primary.appendChild(
                            item
                        );

                    } else {

                        item.remove();

                    }
                }
            }
        );
    }


    /* ========================================================
       LOGGED OUT LAYOUT
    ======================================================== */

    function buildLoggedOutLayout(
        list,
        themeItem
    ) {
        list.classList.remove(
            'wp-is-logged-in'
        );

        list.classList.add(
            'wp-is-logged-out'
        );


        var loginItem =
            list.querySelector(
                '#pt-login'
            );


        /*
         * Desired layout:
         *
         * Create account | Theme | Log in
         */

        if (loginItem) {

            list.insertBefore(
                themeItem,
                loginItem
            );

        } else {

            list.appendChild(
                themeItem
            );

        }
    }


    /* ========================================================
       LOGGED IN LAYOUT
    ======================================================== */

    function buildLoggedInLayout(
        primary,
        list,
        themeItem
    ) {
        list.classList.remove(
            'wp-is-logged-out'
        );

        list.classList.add(
            'wp-is-logged-in'
        );


        cleanUsernameDuplicates(
            primary,
            list
        );


        /*
         * Remove an old dropdown if ResourceLoader
         * initialization somehow runs again.
         */

        var oldDropdown =
            list.querySelector(
                '.wp-user-dropdown'
            );


        if (oldDropdown) {
            return;
        }


        /* ====================================================
           CREATE HAMBURGER WRAPPER
        ==================================================== */

        var dropdown =
            document.createElement('li');


        dropdown.className =
            'wp-user-dropdown';


        /* ====================================================
           HAMBURGER BUTTON
        ==================================================== */

        var trigger =
            document.createElement(
                'button'
            );


        trigger.type =
            'button';


        trigger.className =
            'wp-user-menu-trigger';


        trigger.setAttribute(
            'aria-label',
            'Open user menu'
        );


        trigger.setAttribute(
            'title',
            'User menu'
        );


        trigger.setAttribute(
            'aria-expanded',
            'false'
        );


        trigger.innerHTML =
            getMenuIcon();


        /* ====================================================
           DROPDOWN CONTENT
        ==================================================== */

        var menu =
            document.createElement('ul');


        menu.className =
            'wp-user-dropdown-menu';


        menu.hidden =
            true;


        /*
         * Move every existing menu item
         * into ☰.
         *
         * Username is NOT in this list anymore.
         * Theme is not inserted yet.
         */

        Array.prototype
            .slice.call(
                list.children
            )
            .forEach(
                function (item) {

                    if (
                        item !== themeItem &&
                        item !== dropdown
                    ) {

                        menu.appendChild(
                            item
                        );
                    }
                }
            );


        dropdown.appendChild(
            trigger
        );


        dropdown.appendChild(
            menu
        );


        /*
         * Exact layout:
         *
         * Username | Theme | ☰
         *
         * Username lives in .wp-user-primary,
         * while theme and hamburger live here.
         */

        list.appendChild(
            themeItem
        );


        list.appendChild(
            dropdown
        );


        /* ====================================================
           OPEN / CLOSE
        ==================================================== */

        function closeMenu() {
            dropdown.classList.remove(
                'is-open'
            );


            menu.hidden =
                true;


            trigger.setAttribute(
                'aria-expanded',
                'false'
            );
        }


        function openMenu() {
            dropdown.classList.add(
                'is-open'
            );


            menu.hidden =
                false;


            trigger.setAttribute(
                'aria-expanded',
                'true'
            );
        }


        /* ====================================================
           CLICK HAMBURGER
        ==================================================== */

        trigger.addEventListener(
            'click',
            function (event) {

                event.preventDefault();
                event.stopPropagation();


                if (
                    dropdown.classList.contains(
                        'is-open'
                    )
                ) {

                    closeMenu();

                } else {

                    openMenu();

                }
            }
        );


        /* ====================================================
           CLICK INSIDE MENU
        ==================================================== */

        menu.addEventListener(
            'click',
            function (event) {

                event.stopPropagation();

            }
        );


        /* ====================================================
           CLICK OUTSIDE
        ==================================================== */

        document.addEventListener(
            'click',
            function (event) {

                if (
                    !dropdown.contains(
                        event.target
                    )
                ) {

                    closeMenu();

                }
            }
        );


        /* ====================================================
           ESCAPE
        ==================================================== */

        document.addEventListener(
            'keydown',
            function (event) {

                if (
                    event.key === 'Escape' &&
                    dropdown.classList.contains(
                        'is-open'
                    )
                ) {

                    closeMenu();

                    trigger.focus();
                }
            }
        );
    }


    /* ========================================================
       INITIALIZE ACCOUNT AREA
    ======================================================== */

    function initializeUserArea() {
        var primary =
            document.querySelector(
                '.wp-user-primary'
            );


        var list =
            document.querySelector(
                '.wp-user-menu-list'
            );


        if (!list) {
            return;
        }


        /*
         * Empty username container should not
         * take up space for anonymous users.
         */

        if (
            primary &&
            !primary.querySelector('li')
        ) {

            primary.classList.add(
                'is-empty'
            );
        }


        var themeItem =
            createThemeToggle(
                list
            );


        var username =
            mw.config.get(
                'wgUserName'
            );


        if (username) {

            buildLoggedInLayout(
                primary,
                list,
                themeItem
            );

        } else {

            buildLoggedOutLayout(
                list,
                themeItem
            );
        }


        updateThemeButton();
    }


    /* ========================================================
       APPLY SAVED THEME
    ======================================================== */

    applyTheme(
        getSavedTheme(),
        false
    );


    /* ========================================================
       START
    ======================================================== */

    function initialize() {
        initializeUserArea();
    }


    if (
        document.readyState ===
        'loading'
    ) {

        document.addEventListener(
            'DOMContentLoaded',
            initialize
        );

    } else {

        initialize();

    }

})();