MediaWiki:Common.js: Difference between revisions
Replaced content with "→Any JavaScript here will be loaded for all users on every page load.: " Tags: Replaced Manual revert |
No edit summary |
||
| Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | |||
/** | |||
* Night Mode Toggle for Minerva Neue | |||
* Theme is applied early via LocalSettings.php hook to prevent FOUC | |||
* This script just adds the toggle button | |||
*/ | |||
(function () { | |||
'use strict'; | |||
var STORAGE_KEY = 'minerva-night-mode'; | |||
// SVG icons (20x20) | |||
var MOON_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>'; | |||
var SUN_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'; | |||
/** | |||
* Detect OS color scheme preference | |||
*/ | |||
function getOSPreference() { | |||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { | |||
return 'night'; | |||
} | |||
return 'day'; | |||
} | |||
/** | |||
* Get saved theme, or detect from OS on first visit | |||
*/ | |||
function getSavedTheme() { | |||
try { | |||
var saved = localStorage.getItem(STORAGE_KEY); | |||
if (saved) { | |||
return saved; | |||
} | |||
// First visit: detect OS preference and save it | |||
var osPreference = getOSPreference(); | |||
localStorage.setItem(STORAGE_KEY, osPreference); | |||
return osPreference; | |||
} catch (e) { | |||
return getOSPreference(); | |||
} | |||
} | |||
function saveTheme(theme) { | |||
try { | |||
localStorage.setItem(STORAGE_KEY, theme); | |||
} catch (e) {} | |||
} | |||
function applyTheme(theme) { | |||
var html = document.documentElement; | |||
html.classList.remove('skin-theme-clientpref-day', 'skin-theme-clientpref-night'); | |||
html.classList.add('skin-theme-clientpref-' + theme); | |||
} | |||
function updateButtonState(button, theme) { | |||
var icon = button.querySelector('.nightmode-icon'); | |||
if (theme === 'night') { | |||
icon.innerHTML = SUN_SVG; | |||
button.setAttribute('title', 'Switch to light mode'); | |||
} else { | |||
icon.innerHTML = MOON_SVG; | |||
button.setAttribute('title', 'Switch to dark mode'); | |||
} | |||
} | |||
function createToggleButton() { | |||
var currentTheme = getSavedTheme(); | |||
var li = document.createElement('li'); | |||
var button = document.createElement('a'); | |||
button.setAttribute('role', 'button'); | |||
button.setAttribute('href', '#'); | |||
button.id = 'ca-nightmode'; | |||
button.className = 'cdx-button cdx-button--size-large cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--icon-only cdx-button--weight-quiet'; | |||
button.style.cursor = 'pointer'; | |||
var icon = document.createElement('span'); | |||
icon.className = 'nightmode-icon'; | |||
icon.style.cssText = 'display:flex;align-items:center;justify-content:center;width:20px;height:20px;'; | |||
var label = document.createElement('span'); | |||
label.className = 'sr-only'; | |||
label.style.cssText = 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0;'; | |||
label.textContent = currentTheme === 'night' ? 'Light mode' : 'Dark mode'; | |||
button.appendChild(icon); | |||
button.appendChild(label); | |||
li.appendChild(button); | |||
updateButtonState(button, currentTheme); | |||
button.addEventListener('click', function (e) { | |||
e.preventDefault(); | |||
var newTheme = getSavedTheme() === 'night' ? 'day' : 'night'; | |||
saveTheme(newTheme); | |||
applyTheme(newTheme); | |||
updateButtonState(button, newTheme); | |||
}); | |||
return li; | |||
} | |||
function insertButton() { | |||
var notificationsList = document.querySelector('.minerva-notifications ul'); | |||
if (notificationsList) { | |||
notificationsList.appendChild(createToggleButton()); | |||
} else { | |||
var userNav = document.querySelector('.minerva-user-navigation'); | |||
if (userNav) { | |||
var container = document.createElement('div'); | |||
container.className = 'minerva-notifications'; | |||
var ul = document.createElement('ul'); | |||
ul.appendChild(createToggleButton()); | |||
container.appendChild(ul); | |||
userNav.insertBefore(container, userNav.firstChild); | |||
} | |||
} | |||
} | |||
// Insert button when DOM is ready | |||
if (document.readyState === 'loading') { | |||
document.addEventListener('DOMContentLoaded', insertButton); | |||
} else { | |||
insertButton(); | |||
} | |||
})(); | |||