MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
| Line 1: | Line 1: | ||
/* ===================================================== | |||
EARLY THEME APPLICATION (Prevents FOUC as much as possible) | |||
===================================================== */ | |||
(function() { | (function () { | ||
try { | |||
const savedTheme = localStorage.getItem('lt-theme'); | |||
if (savedTheme === 'red') { | |||
document.documentElement.classList.add('theme-red'); | |||
} else if (savedTheme === 'blue') { | |||
document.documentElement.classList.add('theme-blue'); | |||
} | |||
} catch (e) {} | |||
})(); | })(); | ||
localStorage.setItem(' | console.log("Theme system loaded"); | ||
/* ===================================================== | |||
MAIN LOGIC | |||
===================================================== */ | |||
mw.loader.using(['mediawiki.util']).then(function () { | |||
console.log("mw loader ready"); | |||
/* ====================== | |||
APPLY THEME | |||
====================== */ | |||
function applyTheme(theme, skipSave) { | |||
document.documentElement.classList.remove('theme-red', 'theme-blue'); | |||
if (theme === 'red') { | |||
document.documentElement.classList.add('theme-red'); | |||
} | |||
if (theme === 'blue') { | |||
document.documentElement.classList.add('theme-blue'); | |||
} | |||
if (!skipSave) { | |||
localStorage.setItem('lt-theme', theme); | |||
} | |||
updateThemeSelection(theme); | |||
} | |||
/* ====================== | |||
UPDATE BUTTON STATE | |||
====================== */ | |||
function updateThemeSelection(theme) { | |||
const buttons = document.querySelectorAll('.lt-theme-button'); | |||
buttons.forEach(function (btn) { | |||
btn.classList.remove('is-active'); | |||
}); | |||
const active = document.querySelector('[data-theme="' + theme + '"]'); | |||
if (active) { | |||
active.classList.add('is-active'); | |||
} | |||
} | |||
/* ====================== | |||
INJECT MENU | |||
====================== */ | |||
function injectThemeControls(container) { | |||
if (document.getElementById('custom-theme-menu')) return; | |||
const wrapper = document.createElement('div'); | |||
wrapper.id = 'custom-theme-menu'; | |||
wrapper.className = 'mw-portlet citizen-menu'; | |||
const heading = document.createElement('div'); | |||
heading.className = 'citizen-menu__heading'; | |||
heading.textContent = 'Theme'; | |||
const content = document.createElement('div'); | |||
content.className = 'citizen-menu__content'; | |||
const list = document.createElement('ul'); | |||
list.className = 'citizen-menu__content-list'; | |||
const item = document.createElement('li'); | |||
item.className = 'mw-list-item mw-list-item-js'; | |||
const inner = document.createElement('div'); | |||
function createButton(label, theme) { | |||
const btn = document.createElement('button'); | |||
btn.className = 'lt-theme-button'; | |||
btn.textContent = label; | |||
btn.dataset.theme = theme; | |||
btn.addEventListener('click', function () { | |||
applyTheme(theme); | |||
}); | |||
return btn; | |||
} | |||
inner.appendChild(createButton('Velvet Room', 'default')); | |||
inner.appendChild(createButton('Courtroom', 'red')); | |||
inner.appendChild(createButton('Mementos', 'blue')); | |||
item.appendChild(inner); | |||
list.appendChild(item); | |||
content.appendChild(list); | |||
wrapper.appendChild(heading); | |||
wrapper.appendChild(content); | |||
container.appendChild(wrapper); | |||
const currentTheme = localStorage.getItem('lt-theme') || 'default'; | |||
updateThemeSelection(currentTheme); | |||
} | |||
/* ====================== | |||
WATCH FOR MENU LOAD | |||
====================== */ | |||
const observer = new MutationObserver(function () { | |||
const container = document.querySelector('.citizen-preferences-content'); | |||
if (container) { | |||
injectThemeControls(container); | |||
} | |||
}); | |||
observer.observe(document.body, { childList: true, subtree: true }); | |||
}); | |||
Revision as of 16:27, 20 February 2026
/* =====================================================
EARLY THEME APPLICATION (Prevents FOUC as much as possible)
===================================================== */
(function () {
try {
const savedTheme = localStorage.getItem('lt-theme');
if (savedTheme === 'red') {
document.documentElement.classList.add('theme-red');
} else if (savedTheme === 'blue') {
document.documentElement.classList.add('theme-blue');
}
} catch (e) {}
})();
console.log("Theme system loaded");
/* =====================================================
MAIN LOGIC
===================================================== */
mw.loader.using(['mediawiki.util']).then(function () {
console.log("mw loader ready");
/* ======================
APPLY THEME
====================== */
function applyTheme(theme, skipSave) {
document.documentElement.classList.remove('theme-red', 'theme-blue');
if (theme === 'red') {
document.documentElement.classList.add('theme-red');
}
if (theme === 'blue') {
document.documentElement.classList.add('theme-blue');
}
if (!skipSave) {
localStorage.setItem('lt-theme', theme);
}
updateThemeSelection(theme);
}
/* ======================
UPDATE BUTTON STATE
====================== */
function updateThemeSelection(theme) {
const buttons = document.querySelectorAll('.lt-theme-button');
buttons.forEach(function (btn) {
btn.classList.remove('is-active');
});
const active = document.querySelector('[data-theme="' + theme + '"]');
if (active) {
active.classList.add('is-active');
}
}
/* ======================
INJECT MENU
====================== */
function injectThemeControls(container) {
if (document.getElementById('custom-theme-menu')) return;
const wrapper = document.createElement('div');
wrapper.id = 'custom-theme-menu';
wrapper.className = 'mw-portlet citizen-menu';
const heading = document.createElement('div');
heading.className = 'citizen-menu__heading';
heading.textContent = 'Theme';
const content = document.createElement('div');
content.className = 'citizen-menu__content';
const list = document.createElement('ul');
list.className = 'citizen-menu__content-list';
const item = document.createElement('li');
item.className = 'mw-list-item mw-list-item-js';
const inner = document.createElement('div');
function createButton(label, theme) {
const btn = document.createElement('button');
btn.className = 'lt-theme-button';
btn.textContent = label;
btn.dataset.theme = theme;
btn.addEventListener('click', function () {
applyTheme(theme);
});
return btn;
}
inner.appendChild(createButton('Velvet Room', 'default'));
inner.appendChild(createButton('Courtroom', 'red'));
inner.appendChild(createButton('Mementos', 'blue'));
item.appendChild(inner);
list.appendChild(item);
content.appendChild(list);
wrapper.appendChild(heading);
wrapper.appendChild(content);
container.appendChild(wrapper);
const currentTheme = localStorage.getItem('lt-theme') || 'default';
updateThemeSelection(currentTheme);
}
/* ======================
WATCH FOR MENU LOAD
====================== */
const observer = new MutationObserver(function () {
const container = document.querySelector('.citizen-preferences-content');
if (container) {
injectThemeControls(container);
}
});
observer.observe(document.body, { childList: true, subtree: true });
});