MediaWiki:Common.js
MediaWiki interface page
More actions
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. */
/**
* eve.wiki — MediaWiki:Common.js
* EVE-specific JS for Citizen skin
* No external dependencies — vanilla JS only
*/
( function () {
'use strict';
/* ============================================================
1. WAVE ACCORDION
Finds all .evewiki-wave elements and wires up click toggles.
To use in wikitext: wrap content in <div class="evewiki-wave">
<div class="evewiki-wave-header">...</div>
<div class="evewiki-wave-body">...</div>
</div>
============================================================ */
function initWaveAccordions() {
var waves = document.querySelectorAll( '.evewiki-wave' );
waves.forEach( function ( wave ) {
var header = wave.querySelector( '.evewiki-wave-header' );
if ( !header ) return;
// Open first wave by default
if ( wave === waves[ 0 ] ) {
wave.classList.add( 'is-open' );
}
header.addEventListener( 'click', function () {
wave.classList.toggle( 'is-open' );
} );
// Keyboard support
header.setAttribute( 'tabindex', '0' );
header.setAttribute( 'role', 'button' );
header.addEventListener( 'keydown', function ( e ) {
if ( e.key === 'Enter' || e.key === ' ' ) {
e.preventDefault();
wave.classList.toggle( 'is-open' );
}
} );
} );
}
/* ============================================================
2. SEARCH HOTKEY
Press / to focus search (standard wiki UX pattern)
============================================================ */
function initSearchHotkey() {
var searchInput = document.querySelector(
'#searchInput, .citizen-search__input, input[name="search"]'
);
if ( !searchInput ) return;
document.addEventListener( 'keydown', function ( e ) {
var tag = document.activeElement ? document.activeElement.tagName : '';
if ( e.key === '/' && tag !== 'INPUT' && tag !== 'TEXTAREA' ) {
e.preventDefault();
searchInput.focus();
searchInput.select();
}
if ( e.key === 'Escape' && document.activeElement === searchInput ) {
searchInput.blur();
}
} );
}
/* ============================================================
3. ACTIVE NAV HIGHLIGHT
Adds .evewiki-nav-active to sidebar links matching current page path
============================================================ */
function initActiveNav() {
var path = window.location.pathname;
var links = document.querySelectorAll(
'.citizen-nav a, #citizen-sidebar a, .citizen-sidebar a'
);
links.forEach( function ( link ) {
var href = link.getAttribute( 'href' );
if ( href && href !== '/' && path.indexOf( href ) === 0 ) {
link.closest( 'li' )?.classList.add( 'citizen-nav__item--active' );
}
} );
}
/* ============================================================
4. INFOBOX IMAGE LAZY EXPAND
Click on infobox portrait to open full-size in overlay
============================================================ */
function initInfoboxPortrait() {
var portraits = document.querySelectorAll( '.infobox img, .evewiki-portrait img' );
portraits.forEach( function ( img ) {
img.style.cursor = 'zoom-in';
img.addEventListener( 'click', function () {
var overlay = document.createElement( 'div' );
overlay.style.cssText = [
'position:fixed', 'inset:0', 'z-index:99999',
'background:rgba(0,0,0,.85)',
'display:flex', 'align-items:center', 'justify-content:center',
'cursor:zoom-out'
].join(';');
var full = document.createElement( 'img' );
full.src = img.src;
full.style.cssText = 'max-width:90vw;max-height:90vh;object-fit:contain;border:1px solid #233042;';
overlay.appendChild( full );
document.body.appendChild( overlay );
overlay.addEventListener( 'click', function () {
document.body.removeChild( overlay );
} );
document.addEventListener( 'keydown', function esc( e ) {
if ( e.key === 'Escape' ) {
if ( document.body.contains( overlay ) ) {
document.body.removeChild( overlay );
}
document.removeEventListener( 'keydown', esc );
}
} );
} );
} );
}
/* ============================================================
5. SORTABLE TABLE ENHANCEMENTS
Adds row hover highlight class for wikitables
============================================================ */
function initTableEnhancements() {
var tables = document.querySelectorAll( '.wikitable, .evewiki-table' );
tables.forEach( function ( table ) {
var rows = table.querySelectorAll( 'tbody tr' );
rows.forEach( function ( row ) {
row.addEventListener( 'mouseenter', function () {
row.style.background = '#1c2230';
} );
row.addEventListener( 'mouseleave', function () {
row.style.background = '';
} );
} );
} );
}
/* ============================================================
6. COPY-TO-CLIPBOARD FOR CODE BLOCKS
Adds a small copy button to <pre> blocks
============================================================ */
function initCodeCopy() {
var pres = document.querySelectorAll( '.mw-parser-output pre' );
pres.forEach( function ( pre ) {
pre.style.position = 'relative';
var btn = document.createElement( 'button' );
btn.textContent = 'Copy';
btn.style.cssText = [
'position:absolute', 'top:6px', 'right:6px',
'background:#131720', 'border:1px solid #233042',
'color:#93a4b5', 'font-family:Rajdhani,sans-serif',
'font-size:10px', 'font-weight:600', 'letter-spacing:1px',
'text-transform:uppercase', 'padding:3px 8px',
'cursor:pointer', 'transition:color .12s,border-color .12s'
].join(';');
btn.addEventListener( 'mouseenter', function () {
btn.style.color = '#4fc3e8';
btn.style.borderColor = '#4fc3e8';
} );
btn.addEventListener( 'mouseleave', function () {
btn.style.color = '#93a4b5';
btn.style.borderColor = '#233042';
} );
btn.addEventListener( 'click', function () {
navigator.clipboard.writeText( pre.textContent.trim() ).then( function () {
btn.textContent = 'Copied!';
btn.style.color = '#3acc7a';
setTimeout( function () {
btn.textContent = 'Copy';
btn.style.color = '#93a4b5';
}, 2000 );
} );
} );
pre.appendChild( btn );
} );
}
/* ============================================================
7. HOMEPAGE-ONLY: CATEGORY CARD HOVER GLOW
Only runs on Main_Page
============================================================ */
function initHomepageEffects() {
if ( mw.config.get( 'wgPageName' ) !== 'Main_Page' ) return;
var cards = document.querySelectorAll( '.evewiki-hp-card' );
cards.forEach( function ( card ) {
card.addEventListener( 'mouseenter', function () {
card.style.borderTopColor = '#4fc3e8';
card.style.boxShadow = '0 0 20px rgba(79,195,232,.08)';
} );
card.addEventListener( 'mouseleave', function () {
card.style.borderTopColor = '';
card.style.boxShadow = '';
} );
} );
}
/* ============================================================
INIT — run after DOM ready
============================================================ */
function init() {
initWaveAccordions();
initSearchHotkey();
initActiveNav();
initInfoboxPortrait();
initTableEnhancements();
initCodeCopy();
initHomepageEffects();
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', init );
} else {
init();
}
}() );