|
|
| Line 1: |
Line 1: |
| /* All JavaScript here will be loaded for users of the Timeless skin */ | | /* All JavaScript here will be loaded for users of the Timeless skin */ |
|
| |
| /**
| |
| * Timeless Light/Dark Mode Toggle
| |
| *
| |
| * Requires the corresponding CSS in MediaWiki:Timeless.css
| |
| */
| |
|
| |
| (function () {
| |
| 'use strict';
| |
|
| |
| var STORAGE_KEY = 'timeless-theme';
| |
|
| |
| /**
| |
| * Get the user's preferred theme.
| |
| * Stored preference takes priority; otherwise use system preference.
| |
| */
| |
| function getPreferredTheme() {
| |
| var stored = localStorage.getItem(STORAGE_KEY);
| |
|
| |
| if (stored === 'dark' || stored === 'light') {
| |
| return stored;
| |
| }
| |
|
| |
| return window.matchMedia &&
| |
| window.matchMedia('(prefers-color-scheme: dark)').matches
| |
| ? 'dark'
| |
| : 'light';
| |
| }
| |
|
| |
| /**
| |
| * Apply the selected theme.
| |
| */
| |
| function applyTheme(theme) {
| |
| document.documentElement.classList.toggle('dark-mode', theme === 'dark');
| |
|
| |
| updateButton(theme);
| |
| }
| |
|
| |
| /**
| |
| * Update the toggle button text and tooltip.
| |
| */
| |
| function updateButton(theme) {
| |
| var button = document.getElementById('timeless-theme-toggle');
| |
|
| |
| if (!button) {
| |
| return;
| |
| }
| |
|
| |
| if (theme === 'dark') {
| |
| button.textContent = '☀️ Light mode';
| |
| button.setAttribute('title', 'Switch to light mode');
| |
| button.setAttribute('aria-label', 'Switch to light mode');
| |
| } else {
| |
| button.textContent = '🌙 Dark mode';
| |
| button.setAttribute('title', 'Switch to dark mode');
| |
| button.setAttribute('aria-label', 'Switch to dark mode');
| |
| }
| |
| }
| |
|
| |
| /**
| |
| * Create the toggle button.
| |
| */
| |
| function createButton() {
| |
| if (document.getElementById('timeless-theme-toggle')) {
| |
| return;
| |
| }
| |
|
| |
| var button = document.createElement('button');
| |
|
| |
| button.id = 'timeless-theme-toggle';
| |
| button.type = 'button';
| |
| button.className = 'timeless-theme-toggle';
| |
| button.addEventListener('click', function () {
| |
| var currentTheme =
| |
| document.documentElement.classList.contains('dark-mode')
| |
| ? 'dark'
| |
| : 'light';
| |
|
| |
| var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
| |
|
| |
| localStorage.setItem(STORAGE_KEY, newTheme);
| |
| applyTheme(newTheme);
| |
| });
| |
|
| |
| /*
| |
| * Timeless has a personal tools/navigation area.
| |
| * Try several possible locations so this works across Timeless versions.
| |
| */
| |
| var locations = [
| |
| '#p-personal',
| |
| '#personal',
| |
| '.personal-tools',
| |
| '#mw-panel'
| |
| ];
| |
|
| |
| var target = null;
| |
|
| |
| for (var i = 0; i < locations.length; i++) {
| |
| target = document.querySelector(locations[i]);
| |
|
| |
| if (target) {
| |
| break;
| |
| }
| |
| }
| |
|
| |
| if (!target) {
| |
| return;
| |
| }
| |
|
| |
| /*
| |
| * If we found a navigation container, put the button in a list item
| |
| * when possible. Otherwise append it directly.
| |
| */
| |
| var list = target.querySelector('ul');
| |
|
| |
| if (list) {
| |
| var listItem = document.createElement('li');
| |
| listItem.id = 'timeless-theme-toggle-container';
| |
|
| |
| listItem.appendChild(button);
| |
| list.appendChild(listItem);
| |
| } else {
| |
| target.appendChild(button);
| |
| }
| |
|
| |
| updateButton(getPreferredTheme());
| |
| }
| |
|
| |
| /**
| |
| * Apply the theme as early as possible.
| |
| */
| |
| applyTheme(getPreferredTheme());
| |
|
| |
| /**
| |
| * Wait for MediaWiki/Timeless to finish constructing the interface.
| |
| */
| |
| mw.loader.using(['mediawiki.util'], function () {
| |
| $(createButton);
| |
| });
| |
|
| |
| /**
| |
| * If the visitor has not manually selected a theme, automatically
| |
| * follow changes to their operating-system color scheme.
| |
| */
| |
| if (window.matchMedia) {
| |
| var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
| |
|
| |
| var systemThemeChanged = function (event) {
| |
| if (!localStorage.getItem(STORAGE_KEY)) {
| |
| applyTheme(event.matches ? 'dark' : 'light');
| |
| }
| |
| };
| |
|
| |
| if (mediaQuery.addEventListener) {
| |
| mediaQuery.addEventListener('change', systemThemeChanged);
| |
| } else if (mediaQuery.addListener) {
| |
| mediaQuery.addListener(systemThemeChanged);
| |
| }
| |
| }
| |
| })();
| |
/* All JavaScript here will be loaded for users of the Timeless skin */