MediaWiki:Common.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Any JavaScript here will be loaded for all users on every page load. */
/* ==========================================================================
DEV VANIQUOTES - VECTOR 2022 COMMON.JS
Adapted from the working dev Vanisource Common.js.
========================================================================== */
// SIDEBAR ACCORDION - STRICT LEFT-COLUMN ISOLATION & TRUE ACCORDION
(function() {
function tagSidebarMenus() {
var allMenus = document.querySelectorAll('.vector-menu');
for (var i = 0; i < allMenus.length; i++) {
var menu = allMenus[i];
// Only menus inside the modern or legacy left sidebar containers
if (menu.closest('#vector-main-menu, #mw-panel, #mw-navigation')) {
menu.classList.add('vanipedia-sidebar-menu');
if (menu.querySelector('.vector-menu-heading') && !menu.classList.contains('vanipedia-collapsed')) {
menu.classList.add('vanipedia-collapsed');
}
}
}
}
tagSidebarMenus();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', tagSidebarMenus);
}
// Inject CSS targeted strictly at our tagged sidebar menus
var style = document.createElement('style');
style.textContent =
'.vanipedia-sidebar-menu { width: 185px !important; } ' +
'.vanipedia-sidebar-menu.vanipedia-collapsed .vector-menu-content { display: none !important; } ' +
'.vanipedia-sidebar-menu .vector-menu-heading { ' +
' cursor: pointer !important; ' +
' background-color: #2c4c50 !important; ' +
' border: 1px solid #1b3033 !important; ' +
' border-radius: 4px !important; ' +
' margin-bottom: 4px !important; ' +
' padding: 10px 12px !important; ' +
' font-weight: 600 !important; ' +
' color: #ffffff !important; ' +
' display: flex !important; ' +
' justify-content: space-between !important; ' +
' align-items: center !important; ' +
' gap: 10px !important; ' +
' transition: all 0.2s ease; ' +
'} ' +
'.vanipedia-sidebar-menu:not(.vanipedia-collapsed) .vector-menu-heading { ' +
' border-radius: 4px 4px 0 0 !important; ' +
' margin-bottom: 0 !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-heading:hover { ' +
' background-color: #385e63 !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-heading::after { ' +
' content: "▼"; ' +
' font-size: 0.75em; ' +
' color: #ffffff !important; ' +
' transition: transform 0.2s ease; ' +
'} ' +
'.vanipedia-sidebar-menu.vanipedia-collapsed .vector-menu-heading::after { ' +
' transform: rotate(-90deg); ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-content { ' +
' background-color: #eaeff0 !important; ' +
' border: 1px solid #2c4c50 !important; ' +
' border-top: none !important; ' +
' border-radius: 0 0 4px 4px !important; ' +
' padding: 0 0 4px 0 !important; ' +
' margin-bottom: 6px !important; ' +
' box-shadow: 0 3px 6px rgba(0,0,0,0.15) !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-content ul { ' +
' list-style: none !important; ' +
' margin: 0 !important; ' +
' padding: 0 !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-content li a { ' +
' display: block !important; ' +
' padding: 8px 12px 8px 16px !important; ' +
' color: #1b3033 !important; ' +
' text-decoration: none !important; ' +
' border-left: 3px solid transparent !important; ' +
' border-bottom: 1px solid rgba(44, 76, 80, 0.1) !important; ' +
' transition: all 0.15s ease !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-content li:last-child a { ' +
' border-bottom: none !important; ' +
'} ' +
'.vanipedia-sidebar-menu .vector-menu-content li a:hover { ' +
' background-color: #dbe4e6 !important; ' +
' border-left: 3px solid #2c4c50 !important; ' +
' color: #000000 !important; ' +
'} ';
document.head.appendChild(style);
function collapseAllSidebarMenus() {
var menus = document.querySelectorAll('.vanipedia-sidebar-menu');
for (var i = 0; i < menus.length; i++) {
menus[i].classList.add('vanipedia-collapsed');
}
}
document.addEventListener('click', function(e) {
var heading = e.target.closest('.vector-menu-heading');
if (!heading) return;
var navContainer = heading.closest('.vanipedia-sidebar-menu');
if (navContainer) {
var isAlreadyOpen = !navContainer.classList.contains('vanipedia-collapsed');
collapseAllSidebarMenus();
if (!isAlreadyOpen) {
navContainer.classList.remove('vanipedia-collapsed');
}
e.stopPropagation();
e.preventDefault();
}
}, true);
})();
// RESTRICT ADMINISTRATIVE UI BY USER GROUP
mw.loader.using('mediawiki.user').then(function() {
var userGroups = mw.config.get('wgUserGroups') || [];
var isAuthorized =
userGroups.includes('sysop') ||
userGroups.includes('interface-admin') ||
userGroups.includes('Editor');
if (!isAuthorized) {
document.body.classList.add('restricted-ui');
}
});
// OPEN ACCORDIONS FROM TABLE OF CONTENTS
mw.hook('wikipage.content').add(function() {
function handleAccordionTOC(hash) {
if (!hash || hash === '#') return false;
try {
var targetId = hash.substring(1);
var targetElement =
document.getElementById(targetId) ||
document.getElementById(decodeURIComponent(targetId));
if (!targetElement) return false;
var $target = $(targetElement);
var $heading = $target.is('h2, h3') ? $target : $target.closest('h2, h3');
if (!$heading.length) return false;
var $accordion = $heading.next('.book-accordion');
var $parentAccordions = $heading.parents('.book-accordion');
if (!$accordion.length && !$parentAccordions.length) return false;
// Open all ancestor accordions
$parentAccordions.each(function() {
var $parentCollapsible = $(this).children('.mw-collapsible');
if ($parentCollapsible.length && $parentCollapsible.hasClass('mw-collapsed')) {
var pId = $parentCollapsible.attr('id');
if (pId) {
var pToggleClass = pId.replace(
'mw-customcollapsible-',
'mw-customtoggle-'
);
$('.' + pToggleClass).first().click();
}
}
});
// Open accordion immediately following heading
if ($accordion.length) {
var $collapsible = $accordion.children(
'.mw-collapsible, .mw-collapsible-content'
).first();
if (!$collapsible.length) {
$collapsible = $accordion.find('.mw-collapsible');
}
if ($collapsible.length && $collapsible.hasClass('mw-collapsed')) {
var collapsibleId = $collapsible.attr('id');
if (collapsibleId) {
var toggleClass = collapsibleId.replace(
'mw-customcollapsible-',
'mw-customtoggle-'
);
$('.' + toggleClass).first().click();
}
}
}
var $scrollTarget = $accordion.length ? $accordion : $heading;
setTimeout(function() {
$('html, body').animate({
scrollTop: $scrollTarget.offset().top - 75
}, 300);
}, 100);
return true;
} catch (e) {
console.error('TOC Accordion script error:', e);
return false;
}
}
$(document)
.off('click.tocAccordion')
.on('click.tocAccordion', 'a[href^="#"]', function(e) {
if ($(this).closest('#toc, .toc, .vector-toc').length > 0) {
var href = $(this).attr('href');
var isAccordion = handleAccordionTOC(href);
if (isAccordion) {
e.preventDefault();
if (history.pushState) {
history.pushState(null, null, href);
} else {
window.location.hash = href;
}
}
}
});
if (window.location.hash) {
setTimeout(function() {
handleAccordionTOC(window.location.hash);
}, 500);
}
});
// STICKY BURGER MENU - PURE FLOATING DROPDOWN
(function() {
let isMenuOpen = false;
function forceUnpinSidebar() {
document.documentElement.classList.remove(
'vector-feature-main-menu-pinned-enabled',
'vector-feature-main-menu-pinned-clientpref-1'
);
document.documentElement.classList.add(
'vector-feature-main-menu-pinned-disabled',
'vector-feature-main-menu-pinned-clientpref-0'
);
if (document.body) {
document.body.classList.remove(
'vector-feature-main-menu-pinned-enabled',
'vector-feature-main-menu-pinned-clientpref-1'
);
document.body.classList.add(
'vector-feature-main-menu-pinned-disabled',
'vector-feature-main-menu-pinned-clientpref-0'
);
}
document.cookie = 'vector-feature-main-menu-pinned=0; path=/; max-age=31536000';
try {
localStorage.setItem('vector-feature-main-menu-pinned', '0');
} catch(e) {}
var mainMenu = document.getElementById('vector-main-menu');
var unpinnedContainer =
document.getElementById('vector-main-menu-unpinned-container') ||
document.querySelector('#vector-main-menu-dropdown .vector-dropdown-content');
var pinnedContainer =
document.getElementById('vector-main-menu-pinned-container');
if (
mainMenu &&
unpinnedContainer &&
pinnedContainer &&
pinnedContainer.contains(mainMenu)
) {
unpinnedContainer.appendChild(mainMenu);
}
}
function getDropdownElement() {
return (
document.querySelector('#vector-main-menu-dropdown .vector-dropdown-content') ||
document.getElementById('vector-main-menu-dropdown-content') ||
document.getElementById('vector-main-menu-unpinned-container') ||
document.getElementById('vector-main-menu')
);
}
function openMenu(menuBtn) {
forceUnpinSidebar();
var checkbox = document.getElementById('vector-main-menu-dropdown-checkbox');
var dropdown = getDropdownElement();
if (!dropdown) return;
if (checkbox) {
checkbox.checked = true;
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
}
var rect = menuBtn.getBoundingClientRect();
dropdown.style.setProperty('position', 'fixed', 'important');
dropdown.style.setProperty('top', rect.bottom + 'px', 'important');
dropdown.style.setProperty('left', rect.left + 'px', 'important');
dropdown.style.setProperty('z-index', '99999', 'important');
dropdown.style.setProperty(
'max-height',
(window.innerHeight - rect.bottom - 16) + 'px',
'important'
);
dropdown.style.setProperty('overflow-y', 'auto', 'important');
dropdown.style.setProperty('display', 'block', 'important');
dropdown.style.setProperty('visibility', 'visible', 'important');
dropdown.style.setProperty('opacity', '1', 'important');
dropdown.style.setProperty(
'background-color',
'var(--background-color-base, #ffffff)',
'important'
);
dropdown.style.setProperty(
'box-shadow',
'0 4px 16px rgba(0, 0, 0, 0.2)',
'important'
);
dropdown.style.setProperty('border-radius', '4px', 'important');
isMenuOpen = true;
}
function closeMenu() {
var checkbox = document.getElementById('vector-main-menu-dropdown-checkbox');
var dropdown = getDropdownElement();
if (!dropdown) return;
if (checkbox) {
checkbox.checked = false;
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
}
dropdown.style.removeProperty('position');
dropdown.style.removeProperty('top');
dropdown.style.removeProperty('left');
dropdown.style.removeProperty('z-index');
dropdown.style.removeProperty('max-height');
dropdown.style.removeProperty('overflow-y');
dropdown.style.removeProperty('background-color');
dropdown.style.removeProperty('box-shadow');
dropdown.style.removeProperty('border-radius');
dropdown.style.setProperty('display', 'none', 'important');
dropdown.style.setProperty('visibility', 'hidden', 'important');
dropdown.style.setProperty('opacity', '0', 'important');
isMenuOpen = false;
}
function initStickyBurger() {
forceUnpinSidebar();
var stickyHeader = document.getElementById('vector-sticky-header');
if (!stickyHeader) return false;
if (document.getElementById('vanipedia-sticky-main-menu')) {
return true;
}
var menuBtn = document.createElement('div');
menuBtn.id = 'vanipedia-sticky-main-menu';
menuBtn.title = 'Main menu';
menuBtn.style.cursor = 'pointer';
menuBtn.className =
'vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--icon-only';
var iconSpan = document.createElement('span');
iconSpan.className =
'vector-icon mw-ui-icon-menu mw-ui-icon-wikimedia-menu';
menuBtn.appendChild(iconSpan);
menuBtn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (isMenuOpen) {
closeMenu();
} else {
openMenu(menuBtn);
}
});
var startContainer = stickyHeader.querySelector(
'.vector-sticky-header-start'
);
if (!startContainer) {
startContainer = document.createElement('div');
startContainer.className = 'vector-sticky-header-start';
stickyHeader.insertBefore(startContainer, stickyHeader.firstChild);
}
startContainer.insertBefore(menuBtn, startContainer.firstChild);
return true;
}
// Close menu when clicking outside
document.addEventListener('click', function(e) {
if (!isMenuOpen) return;
var menuBtn = document.getElementById('vanipedia-sticky-main-menu');
var dropdown = getDropdownElement();
if (
dropdown &&
menuBtn &&
!menuBtn.contains(e.target) &&
!dropdown.contains(e.target)
) {
closeMenu();
}
});
// Bootstrap initializer
if (!initStickyBurger()) {
var checkTimer = setInterval(function() {
if (initStickyBurger()) {
clearInterval(checkTimer);
}
}, 100);
setTimeout(function() {
clearInterval(checkTimer);
}, 4000);
}
mw.hook('wikipage.content').add(initStickyBurger);
$(initStickyBurger);
})();
// FLOATING "BACK TO TOP" BUTTON
(function() {
function initBackToTop() {
if (document.getElementById('vanipedia-back-to-top')) return;
var btn = document.createElement('button');
btn.id = 'vanipedia-back-to-top';
btn.title = 'Back to top';
btn.setAttribute('aria-label', 'Back to top');
btn.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" ' +
'width="22" height="22" viewBox="0 0 24 24" ' +
'fill="none" stroke="currentColor" stroke-width="2.5" ' +
'stroke-linecap="round" stroke-linejoin="round">' +
'<polyline points="18 15 12 9 6 15"></polyline>' +
'</svg>';
btn.addEventListener('click', function(e) {
e.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
function toggleVisibility() {
if (window.scrollY > 300) {
btn.classList.add('visible');
} else {
btn.classList.remove('visible');
}
}
window.addEventListener('scroll', toggleVisibility, { passive: true });
toggleVisibility();
document.body.appendChild(btn);
}
$(initBackToTop);
mw.hook('wikipage.content').add(initBackToTop);
})();