MediaWiki:Common.js
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.
( function () {
'use strict';
function ensureThemeStylesLoaded() {
try {
if ( !window.mw || !mw.loader || !mw.config ) {
return;
}
const skin = mw.config.get( 'skin' ) || 'vector';
const moduleName = 'themeloader.skins.' + skin + '.default';
if ( typeof mw.loader.getState === 'function' ) {
const state = mw.loader.getState( moduleName );
if ( state === null ) {
return;
}
if ( state === 'ready' || state === 'loading' ) {
return;
}
}
mw.loader.load( moduleName );
} catch ( e ) {
// Ignore error
}
}
function getSavedTheme() {
try {
return localStorage.getItem( 'mw-theme' ) || 'default';
} catch ( e ) {
return 'default';
}
}
// Define available themes matching christmas.css roots
const themes = [
{ name: 'Pink', id: 'default' },
{ name: 'Dark', id: 'dark-neutral' },
{ name: 'Christmas', id: 'christmas' },
{ name: 'Power Light', id: 'power-light' },
{ name: 'Magic Light', id: 'magic-light' },
{ name: 'Sense Light', id: 'sense-light' },
{ name: 'Charm Light', id: 'charm-light' },
{ name: 'Power Dark', id: 'power-dark' },
{ name: 'Charm Dark', id: 'charm-dark' },
{ name: 'Magic Dark', id: 'dark-lightBlue' },
{ name: 'Sense Dark', id: 'dark-purple' },
];
// Function to apply theme
function applyTheme( themeId ) {
ensureThemeStylesLoaded();
try {
localStorage.setItem( 'mw-theme', themeId );
} catch ( e ) {
// Ignore error
}
if ( themeId === 'default' ) {
document.documentElement.removeAttribute( 'data-theme' );
} else {
document.documentElement.setAttribute( 'data-theme', themeId );
}
}
// Initialize theme immediately
ensureThemeStylesLoaded();
applyTheme( getSavedTheme() );
// Wait for DOM
const domReady = function ( callback ) {
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', callback );
} else {
setTimeout( callback, 0 );
}
};
domReady( function () {
// Prevent duplicate injection
if ( document.getElementById( 'mw-theme-floating' ) ) {
return;
}
// Create Floating Container
// ID matches CSS: #mw-theme-floating
const container = document.createElement( 'div' );
container.id = 'mw-theme-floating';
// Create Inner Wrapper
// Class matches CSS: .themeMenu
const themeMenuDiv = document.createElement( 'div' );
themeMenuDiv.className = 'themeMenu';
// Create Toggle Button
// Class matches CSS: .themeMenu-toggle
const btn = document.createElement( 'button' );
btn.className = 'themeMenu-toggle';
btn.textContent = 'Appearence';
btn.title = 'Change appearence';
btn.type = 'button';
// Create Dropdown List
// Class matches CSS: .themeMenu-dropdown
const dropdown = document.createElement( 'ul' );
dropdown.className = 'themeMenu-dropdown';
// Populate Items
themes.forEach( function ( theme ) {
// Item Wrapper
// CSS doesn't strictly require this wrapper for floating,
// but theme-menu.css might use .themeMenu-itemWrap
const itemWrap = document.createElement( 'li' );
itemWrap.className = 'themeMenu-itemWrap';
const themeLink = document.createElement( 'a' );
themeLink.className = 'themeMenu-item';
themeLink.href = '#';
themeLink.textContent = theme.name;
themeLink.dataset.themeId = theme.id;
// Highlight current
const currentTheme = getSavedTheme();
if ( theme.id === currentTheme ) {
themeLink.classList.add( 'is-current' );
}
themeLink.addEventListener( 'click', function ( e ) {
e.preventDefault();
ensureThemeStylesLoaded();
applyTheme( theme.id );
// Update highlighting
dropdown.querySelectorAll( '.themeMenu-item' ).forEach( function ( link ) {
link.classList.remove( 'is-current' );
} );
themeLink.classList.add( 'is-current' );
// Close menu
themeMenuDiv.classList.remove( 'is-open' );
} );
itemWrap.appendChild( themeLink );
dropdown.appendChild( itemWrap );
} );
// Toggle Logic
// CSS uses .themeMenu.is-open .themeMenu-dropdown { display: block }
btn.addEventListener( 'click', function ( e ) {
e.preventDefault();
e.stopPropagation();
themeMenuDiv.classList.toggle( 'is-open' );
} );
// Click Outside Logic
document.addEventListener( 'click', function ( e ) {
if ( !themeMenuDiv.contains( e.target ) ) {
themeMenuDiv.classList.remove( 'is-open' );
}
} );
// Assemble
themeMenuDiv.appendChild( btn );
themeMenuDiv.appendChild( dropdown );
container.appendChild( themeMenuDiv );
// Inject into Body
document.body.appendChild( container );
} );
}() );