MediaWiki:Common.js: Difference between revisions
Appearance
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
| Line 118: | Line 118: | ||
if (sp !== 'FormEdit' && sp !== 'FormStart') return; | if (sp !== 'FormEdit' && sp !== 'FormStart') return; | ||
const IMG_SELECTOR = 'input[name^="Relic[img"]'; | |||
let | let activeId = null; | ||
let baseline = new Map(); | |||
let timer = null; | |||
function snapshot() { | |||
baseline.clear(); | |||
$content.find(IMG_SELECTOR).each(function () { | |||
baseline.set(this, this.value || ''); | |||
}); | |||
} | |||
function enforce() { | |||
if (!activeId) return; | |||
if (! | |||
$content.find(IMG_SELECTOR).each(function () { | |||
const el = this; | |||
const prev = baseline.get(el) ?? ''; | |||
const now = el.value || ''; | |||
// Only allow the active input to change; lock all others | |||
if (el.id === activeId) { | |||
// Update baseline for active field only | |||
baseline.set(el, now); | |||
} else { | |||
if (now !== prev) { | |||
el.value = prev; | |||
} | |||
} | |||
}); | }); | ||
} | } | ||
// When user clicks PF upload link, set the active input and lock others for 20 seconds | |||
$content.on('mousedown click', 'a.pf_uploadable', function () { | |||
activeId = this.getAttribute('data-inputid'); // e.g. input_8 | |||
if (!activeId) return; | |||
snapshot(); | |||
// Focus the correct field | |||
const target = document.getElementById(activeId); | |||
if (target) { target.focus(); target.click(); } | |||
// Start enforcement loop | |||
if (timer) clearInterval(timer); | |||
timer = setInterval(enforce, 150); | |||
// Stop after 20 seconds | |||
setTimeout(function () { | |||
if (timer) clearInterval(timer); | |||
timer = null; | |||
activeId = null; | |||
}, 20000); | |||
}); | |||
// Also enforce on any input/change events | |||
$content.on('input change', IMG_SELECTOR, function () { | |||
enforce(); | |||
}); | |||
}); | }); | ||
Revision as of 15:13, 25 December 2025
/* Any JavaScript here will be loaded for all users on every page load. */
// Vector 2022: pin main menu for logged-out users on desktop
if (!mw.config.get('wgUserName') && window.matchMedia('(min-width: 1120px)').matches) {
const observer = new MutationObserver((_, obs) => {
if (document.documentElement.classList.contains('vector-animations-ready')) {
const pin = document.querySelector('[data-event-name="pinnable-header.vector-main-menu.pin"]');
if (pin) pin.click();
obs.disconnect();
}
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
}
// Remove "Main menu" headings/labels injected by Vector/Vector 2022 (works across variants)
(function () {
function killMainMenuText(root = document) {
// Look for common heading/label elements
const candidates = root.querySelectorAll(
'#vector-main-menu, #vector-main-menu-pinned-container, #mw-panel, nav.vector-main-menu, #vector-main-menu-dropdown'
);
candidates.forEach(container => {
// Remove elements whose visible text is exactly "Main menu"
container.querySelectorAll('*').forEach(el => {
const txt = (el.textContent || '').trim();
if (txt === 'Main menu') {
el.style.display = 'none';
}
// Also catch the longer hint text variants
if (txt.toLowerCase().includes('main menu has moved here')) {
el.style.display = 'none';
}
});
});
}
// Run now, on load, and after Vector finishes UI init
killMainMenuText();
window.addEventListener('load', () => killMainMenuText());
const obs = new MutationObserver(() => killMainMenuText());
obs.observe(document.documentElement, { childList: true, subtree: true });
})();
// DOOM ARCHIVES header: inject above your Doom Titles links (guaranteed)
(function () {
const HEADER_CLASS = 'doom-archives-header';
function styleHeader(header) {
header.style.display = 'block';
header.style.width = '100%';
header.style.boxSizing = 'border-box';
header.style.margin = '10px 0 10px';
header.style.padding = '12px 14px';
header.style.background = 'rgba(0,0,0,0.75)';
header.style.border = '1px solid #3a0000';
header.style.borderRadius = '12px';
header.style.boxShadow = 'inset 0 0 20px rgba(180,0,0,0.30), 0 0 8px rgba(0,0,0,0.8)';
header.style.color = '#f5c542';
header.style.fontWeight = '900';
header.style.letterSpacing = '0.22em';
header.style.textTransform = 'uppercase';
header.style.textAlign = 'center';
header.style.fontFamily = "'Bebas Neue', Arial, sans-serif";
header.style.textShadow = '0 0 3px rgba(245,197,66,0.35)';
header.style.fontSize = '22px';
}
function findAnchor() {
// Use a link you KNOW exists in your sidebar
return (
document.querySelector('a[href*="Category:Doom_(1993)"]') ||
document.querySelector('a[href*="Category:Doom_II"]') ||
document.querySelector('a[href*="Category:Doom_3"]') ||
document.querySelector('a[href*="Category:Doom_Eternal"]')
);
}
function ensureHeader() {
const a = findAnchor();
if (!a) return;
// Find the menu content container that holds the link list
const menuContent =
a.closest('.vector-menu-content') ||
a.closest('ul') ||
a.parentElement;
if (!menuContent) return;
// Avoid duplicates
if (menuContent.querySelector('.' + HEADER_CLASS)) return;
const header = document.createElement('div');
header.className = HEADER_CLASS;
header.textContent = 'DOOM RELICS';
styleHeader(header);
// Insert header before the first list item / first link area
menuContent.insertBefore(header, menuContent.firstChild);
}
function run() {
ensureHeader();
setTimeout(ensureHeader, 150);
setTimeout(ensureHeader, 600);
setTimeout(ensureHeader, 1200);
}
// Run now + keep alive if Vector re-renders
run();
window.addEventListener('load', run);
const obs = new MutationObserver(() => ensureHeader());
obs.observe(document.documentElement, { childList: true, subtree: true });
})();
mw.hook('wikipage.content').add(function ($content) {
const sp = mw.config.get('wgCanonicalSpecialPageName');
if (sp !== 'FormEdit' && sp !== 'FormStart') return;
const IMG_SELECTOR = 'input[name^="Relic[img"]';
let activeId = null;
let baseline = new Map();
let timer = null;
function snapshot() {
baseline.clear();
$content.find(IMG_SELECTOR).each(function () {
baseline.set(this, this.value || '');
});
}
function enforce() {
if (!activeId) return;
$content.find(IMG_SELECTOR).each(function () {
const el = this;
const prev = baseline.get(el) ?? '';
const now = el.value || '';
// Only allow the active input to change; lock all others
if (el.id === activeId) {
// Update baseline for active field only
baseline.set(el, now);
} else {
if (now !== prev) {
el.value = prev;
}
}
});
}
// When user clicks PF upload link, set the active input and lock others for 20 seconds
$content.on('mousedown click', 'a.pf_uploadable', function () {
activeId = this.getAttribute('data-inputid'); // e.g. input_8
if (!activeId) return;
snapshot();
// Focus the correct field
const target = document.getElementById(activeId);
if (target) { target.focus(); target.click(); }
// Start enforcement loop
if (timer) clearInterval(timer);
timer = setInterval(enforce, 150);
// Stop after 20 seconds
setTimeout(function () {
if (timer) clearInterval(timer);
timer = null;
activeId = null;
}, 20000);
});
// Also enforce on any input/change events
$content.on('input change', IMG_SELECTOR, function () {
enforce();
});
});