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.
/* ============================================================
WIKIPARTNER
THEME + LOGGED-IN 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 */
}
}
/* ========================================================
THEME STATE
======================================================== */
function getCurrentTheme() {
return document.documentElement.classList.contains(
'wp-theme-dark'
)
? DARK
: LIGHT;
}
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
);
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>' +
'<span class="wp-theme-menu-label">' +
(
isDark
? 'Light mode'
: 'Dark mode'
) +
'</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);
var loginItem =
list.querySelector(
'#pt-login'
);
if (loginItem) {
/*
* LOGGED OUT:
*
* Create account | Theme | Log in
*/
list.insertBefore(
item,
loginItem
);
} else {
list.appendChild(
item
);
}
updateThemeButton();
return item;
}
/* ========================================================
HAMBURGER ICON
======================================================== */
function getMenuIcon() {
return [
'<span class="wp-menu-bars" aria-hidden="true">',
'<span></span>',
'<span></span>',
'<span></span>',
'</span>'
].join('');
}
/* ========================================================
LOGGED-IN USER MENU
======================================================== */
function buildLoggedInUserMenu(
list,
themeItem
) {
/*
* #pt-logout exists only when
* MediaWiki sees an authenticated user.
*/
var logoutItem =
list.querySelector(
'#pt-logout'
);
if (!logoutItem) {
/*
* LOGGED OUT
*/
list.classList.remove(
'wp-is-logged-in'
);
list.classList.add(
'wp-is-logged-out'
);
return;
}
/*
* LOGGED IN
*/
list.classList.remove(
'wp-is-logged-out'
);
list.classList.add(
'wp-is-logged-in'
);
/*
* Prevent duplicate hamburger menus.
*/
if (
list.querySelector(
'.wp-user-dropdown'
)
) {
return;
}
/*
* Username stays OUTSIDE.
*/
var usernameItem =
list.querySelector(
'#pt-userpage'
);
/* ====================================================
CREATE DROPDOWN WRAPPER
==================================================== */
var dropdown =
document.createElement('li');
dropdown.className =
'wp-user-dropdown';
/* ====================================================
CREATE 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();
/* ====================================================
CREATE DROPDOWN MENU
==================================================== */
var menu =
document.createElement('ul');
menu.className =
'wp-user-dropdown-menu';
menu.hidden =
true;
/* ====================================================
MOVE USER LINKS
==================================================== */
/*
* ONLY THESE REMAIN OUTSIDE:
*
* Username
* Theme button
*
* Everything else moves inside ☰
*/
Array.prototype
.slice
.call(list.children)
.forEach(
function (item) {
if (
item === usernameItem ||
item === themeItem
) {
return;
}
menu.appendChild(
item
);
}
);
dropdown.appendChild(
trigger
);
dropdown.appendChild(
menu
);
/* ====================================================
FORCE EXACT HEADER ORDER
==================================================== */
/*
* Username | Theme | ☰
*/
if (usernameItem) {
list.appendChild(
usernameItem
);
}
if (themeItem) {
list.appendChild(
themeItem
);
}
list.appendChild(
dropdown
);
/* ====================================================
OPEN / CLOSE FUNCTIONS
==================================================== */
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'
);
}
/* ====================================================
HAMBURGER CLICK
==================================================== */
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 KEY
==================================================== */
document.addEventListener(
'keydown',
function (event) {
if (
event.key === 'Escape' &&
dropdown.classList.contains(
'is-open'
)
) {
closeMenu();
trigger.focus();
}
}
);
}
/* ========================================================
INITIALIZE USER AREA
======================================================== */
function initializeUserArea() {
var list =
document.querySelector(
'.wp-user-menu-list'
);
if (!list) {
return;
}
/*
* First create the theme button.
*/
var themeItem =
createThemeToggle(
list
);
/*
* Then build logged-in dropdown.
*/
buildLoggedInUserMenu(
list,
themeItem
);
updateThemeButton();
}
/* ========================================================
APPLY SAVED THEME
======================================================== */
applyTheme(
getSavedTheme(),
false
);
/* ========================================================
START
======================================================== */
function initialize() {
initializeUserArea();
}
if (
document.readyState ===
'loading'
) {
document.addEventListener(
'DOMContentLoaded',
initialize
);
} else {
initialize();
}
})();