MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
No edit summary |
No edit summary |
||
| Line 179: | Line 179: | ||
span.style.transform = | span.style.transform = | ||
`rotate(${randomRotate}deg) translateY(${randomY}px) scale(${randomSize})`; | `rotate(${randomRotate}deg) translateY(${randomY}px) scale(${randomSize})`; | ||
// --- Box logic --- | |||
const chance = Math.random(); | |||
if (chance < 0.05) { | |||
span.classList.add('box-white'); | |||
} else if (chance < 0.20) { | |||
span.classList.add('box-black'); | |||
} | |||
el.appendChild(span); | el.appendChild(span); | ||
Revision as of 20:18, 20 February 2026
(function () {
const theme = localStorage.getItem('lt-theme') || 'lt-theme-default';
document.documentElement.classList.add(theme);
})();
mw.loader.using(['mediawiki.util']).then(function () {
function injectThemeOption(container) {
function createRadio(id, label) {
const radioWrapper = document.createElement('div');
radioWrapper.className = 'citizen-client-prefs-radio';
const input = document.createElement('input');
input.type = 'radio';
input.name = 'lt-theme-group';
input.id = id;
input.className = 'citizen-client-prefs-radio__input';
const icon = document.createElement('span');
icon.className = 'citizen-client-prefs-radio__icon';
const labelEl = document.createElement('label');
labelEl.className = 'citizen-client-prefs-radio__label';
labelEl.htmlFor = id;
labelEl.textContent = label;
radioWrapper.appendChild(input);
radioWrapper.appendChild(icon);
radioWrapper.appendChild(labelEl);
return radioWrapper;
}
if (document.getElementById('lt-theme-test')) return;
// Portlet wrapper
const wrapper = document.createElement('div');
wrapper.id = 'lt-theme-test';
wrapper.className = 'mw-portlet citizen-menu';
// Heading
const heading = document.createElement('div');
heading.className = 'citizen-menu__heading';
heading.textContent = 'Theme';
// Content wrapper
const content = document.createElement('div');
content.className = 'citizen-menu__content';
// UL
const list = document.createElement('ul');
list.className = 'citizen-menu__content-list';
// LI
const item = document.createElement('li');
item.className = 'mw-list-item mw-list-item-js';
// Inner div (matches Citizen structure)
const innerDiv = document.createElement('div');
// FORM (this is important for spacing)
const form = document.createElement('form');
form.appendChild(createRadio('lt-theme-default', '🎭 Velvet'));
form.appendChild(createRadio('lt-theme-red', '🚇 Meta'));
form.appendChild(createRadio('lt-theme-blue', '⚖️ Justice'));
// === Persistence Logic ===
// Check if theme exists
let savedTheme = localStorage.getItem('lt-theme');
if (!savedTheme) {
// First-time visitor → set default explicitly
savedTheme = 'lt-theme-default';
localStorage.setItem('lt-theme', savedTheme);
}
// Select the saved radio
const savedInput = form.querySelector('#' + savedTheme);
if (savedInput) {
savedInput.checked = true;
}
form.addEventListener('change', function (e) {
if (e.target && e.target.matches('.citizen-client-prefs-radio__input')) {
const newTheme = e.target.id;
// Remove all theme classes first
document.documentElement.classList.remove(
'lt-theme-default',
'lt-theme-red',
'lt-theme-blue'
);
// Add the selected one
document.documentElement.classList.add(newTheme);
// Persist it
localStorage.setItem('lt-theme', newTheme);
}
});
// Assemble hierarchy
innerDiv.appendChild(form);
item.appendChild(innerDiv);
list.appendChild(item);
content.appendChild(list);
wrapper.appendChild(heading);
wrapper.appendChild(content);
container.appendChild(wrapper);
}
const observer = new MutationObserver(function () {
const container = document.querySelector('.citizen-preferences-content');
if (container) {
injectThemeOption(container);
}
});
observer.observe(document.body, { childList: true, subtree: true });
function floatWordmark() {
const wordmarks = document.querySelectorAll('.mw-logo-wordmark');
wordmarks.forEach(function (el) {
if (el.dataset.floatingApplied) return;
const text = el.textContent;
el.textContent = '';
text.split('').forEach(function (char, index) {
const span = document.createElement('span');
span.textContent = char === ' ' ? '\u00A0' : char;
span.style.animationDelay = (index * 0.08) + 's';
span.className = 'velvet-letter';
el.appendChild(span);
});
el.dataset.floatingApplied = "true";
});
}
floatWordmark();
function applyRansomEffect(selector) {
if (!document.documentElement.classList.contains('lt-theme-red')) return;
const elements = document.querySelectorAll(selector);
const fonts = [
"'Anton', sans-serif",
"'Bebas Neue', sans-serif",
"'Archivo Black', sans-serif",
"'Oswald', sans-serif"
];
elements.forEach(function (el) {
if (el.dataset.scrapbookApplied) return;
const text = el.textContent;
el.textContent = '';
text.split('').forEach(function (char) {
const span = document.createElement('span');
span.textContent = char === ' ' ? '\u00A0' : char;
span.classList.add('scrapbook-letter');
const randomFont = fonts[Math.floor(Math.random() * fonts.length)];
const randomRotate = (Math.random() * 6 - 3);
const randomSize = 1 + (Math.random() * 0.15 - 0.075);
const randomY = (Math.random() * 6 - 3);
span.style.fontFamily = randomFont;
span.style.transform =
`rotate(${randomRotate}deg) translateY(${randomY}px) scale(${randomSize})`;
// --- Box logic ---
const chance = Math.random();
if (chance < 0.05) {
span.classList.add('box-white');
} else if (chance < 0.20) {
span.classList.add('box-black');
}
el.appendChild(span);
});
el.dataset.scrapbookApplied = "true";
});
}
applyRansomEffect('.lt-infobox-title');
applyRansomEffect('.mw-page-title-main');
applyRansomEffect('h2');
});