MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
/** | /** | ||
* eve.wiki — MediaWiki:Common.js | * eve.wiki — MediaWiki:Common.js | ||
* | * Clean rewrite — no syntax errors | ||
*/ | */ | ||
| Line 11: | Line 9: | ||
/* ============================================================ | /* ============================================================ | ||
1. WAVE ACCORDION | 1. WAVE ACCORDION | ||
============================================================ */ | ============================================================ */ | ||
function initWaveAccordions() { | function initWaveAccordions() { | ||
var waves = document.querySelectorAll( '.evewiki-wave' ); | var waves = document.querySelectorAll( '.evewiki-wave' ); | ||
waves.forEach( function ( wave ) { | if ( !waves.length ) return; | ||
waves.forEach( function ( wave, i ) { | |||
var header = wave.querySelector( '.evewiki-wave-header' ); | var header = wave.querySelector( '.evewiki-wave-header' ); | ||
if ( !header ) return; | if ( !header ) return; | ||
if ( i === 0 ) { | |||
if ( | |||
wave.classList.add( 'is-open' ); | wave.classList.add( 'is-open' ); | ||
} | } | ||
header.setAttribute( 'tabindex', '0' ); | |||
header.setAttribute( 'role', 'button' ); | |||
header.addEventListener( 'click', function () { | header.addEventListener( 'click', function () { | ||
| Line 32: | Line 29: | ||
} ); | } ); | ||
header.addEventListener( 'keydown', function ( e ) { | header.addEventListener( 'keydown', function ( e ) { | ||
if ( e.key === 'Enter' || e.key === ' ' ) { | if ( e.key === 'Enter' || e.key === ' ' ) { | ||
| Line 45: | Line 39: | ||
/* ============================================================ | /* ============================================================ | ||
2. SEARCH HOTKEY | 2. SEARCH HOTKEY — / to focus search | ||
============================================================ */ | ============================================================ */ | ||
function initSearchHotkey() { | function initSearchHotkey() { | ||
document.addEventListener( 'keydown', function ( e ) { | document.addEventListener( 'keydown', function ( e ) { | ||
var tag = document.activeElement ? document.activeElement.tagName : ''; | var tag = document.activeElement ? document.activeElement.tagName : ''; | ||
if ( e.key === '/' && tag !== 'INPUT' && tag !== 'TEXTAREA' ) { | if ( e.key === '/' && tag !== 'INPUT' && tag !== 'TEXTAREA' ) { | ||
e.preventDefault(); | e.preventDefault(); | ||
searchInput.focus(); | var input = document.querySelector( | ||
'#evewiki-search-input, .mw-inputbox-input, input.mw-searchInput, .citizen-search__input' | |||
); | |||
if ( input ) { | |||
input.focus(); | |||
input.select(); | |||
} | |||
} | } | ||
if ( e.key === ' | } ); | ||
} | |||
/* ============================================================ | |||
3. HOMEPAGE SEARCH — Enter key handler | |||
============================================================ */ | |||
function initHomepageSearch() { | |||
var input = document.querySelector( '.evewiki-hp-search .mw-inputbox-input' ); | |||
if ( !input ) return; | |||
input.addEventListener( 'keydown', function ( e ) { | |||
if ( e.key === 'Enter' ) { | |||
var q = input.value.trim(); | |||
if ( q ) { | |||
window.location = mw.util.getUrl( 'Special:Search' ) + '?search=' + encodeURIComponent( q ) + '&fulltext=1'; | |||
} | |||
} | } | ||
} ); | } ); | ||
| Line 68: | Line 75: | ||
/* ============================================================ | /* ============================================================ | ||
4. ACTIVE NAV HIGHLIGHT | |||
============================================================ */ | ============================================================ */ | ||
function initActiveNav() { | function initActiveNav() { | ||
var path = window.location.pathname; | var path = window.location.pathname; | ||
var links = document.querySelectorAll( | var links = document.querySelectorAll( '.citizen-nav a, #citizen-sidebar a' ); | ||
links.forEach( function ( link ) { | links.forEach( function ( link ) { | ||
var href = link.getAttribute( 'href' ); | var href = link.getAttribute( 'href' ); | ||
if ( href && href !== '/' && path.indexOf( href ) === 0 ) { | if ( href && href !== '/' && path.indexOf( href ) === 0 ) { | ||
link.closest( 'li' ) | var li = link.closest( 'li' ); | ||
if ( li ) { | |||
li.classList.add( 'citizen-nav__item--active' ); | |||
} | |||
} | } | ||
} ); | } ); | ||
| Line 85: | Line 92: | ||
/* ============================================================ | /* ============================================================ | ||
5. INFOBOX IMAGE ZOOM | |||
============================================================ */ | ============================================================ */ | ||
function | function initInfoboxZoom() { | ||
var | var imgs = document.querySelectorAll( '.infobox img, .evewiki-portrait img' ); | ||
imgs.forEach( function ( img ) { | |||
img.style.cursor = 'zoom-in'; | img.style.cursor = 'zoom-in'; | ||
img.addEventListener( 'click', function () { | img.addEventListener( 'click', function () { | ||
var overlay = document.createElement( 'div' ); | var overlay = document.createElement( 'div' ); | ||
overlay.style.cssText = | 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'; | ||
var full = document.createElement( 'img' ); | var full = document.createElement( 'img' ); | ||
full.src = img.src; | full.src = img.src; | ||
full.style.cssText = 'max-width:90vw;max-height:90vh;object-fit:contain;border:1px solid #233042 | full.style.cssText = 'max-width:90vw;max-height:90vh;object-fit:contain;border:1px solid #233042'; | ||
overlay.appendChild( full ); | overlay.appendChild( full ); | ||
| Line 109: | Line 110: | ||
overlay.addEventListener( 'click', function () { | overlay.addEventListener( 'click', function () { | ||
document.body.removeChild( overlay ); | if ( document.body.contains( overlay ) ) { | ||
document.body.removeChild( overlay ); | |||
} | |||
} ); | } ); | ||
document.addEventListener( 'keydown', function | document.addEventListener( 'keydown', function escHandler( e ) { | ||
if ( e.key === 'Escape' ) { | if ( e.key === 'Escape' ) { | ||
if ( document.body.contains( overlay ) ) { | if ( document.body.contains( overlay ) ) { | ||
document.body.removeChild( overlay ); | document.body.removeChild( overlay ); | ||
} | } | ||
document.removeEventListener( 'keydown', | document.removeEventListener( 'keydown', escHandler ); | ||
} | } | ||
} ); | } ); | ||
| Line 125: | Line 128: | ||
/* ============================================================ | /* ============================================================ | ||
6. CODE BLOCK COPY BUTTON | |||
6. COPY | |||
============================================================ */ | ============================================================ */ | ||
function initCodeCopy() { | function initCodeCopy() { | ||
| Line 154: | Line 137: | ||
var btn = document.createElement( 'button' ); | var btn = document.createElement( 'button' ); | ||
btn.textContent = 'Copy'; | btn.textContent = 'Copy'; | ||
btn.style.cssText = | 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'; | ||
btn.addEventListener( 'click', function () { | btn.addEventListener( 'click', function () { | ||
var text = pre.textContent.trim(); | |||
if ( navigator.clipboard ) { | |||
navigator.clipboard.writeText( text ).then( function () { | |||
btn.textContent = 'Copied!'; | |||
btn.style.color = '#3acc7a'; | |||
setTimeout( function () { | |||
btn.textContent = 'Copy'; | |||
btn.style.color = '#93a4b5'; | |||
}, 2000 ); | |||
} ); | |||
} | |||
} ); | } ); | ||
| Line 188: | Line 158: | ||
/* ============================================================ | /* ============================================================ | ||
INIT | |||
INIT | |||
============================================================ */ | ============================================================ */ | ||
function init() { | function init() { | ||
initWaveAccordions(); | initWaveAccordions(); | ||
initSearchHotkey(); | initSearchHotkey(); | ||
initHomepageSearch(); | |||
initActiveNav(); | initActiveNav(); | ||
initInfoboxZoom(); | |||
initCodeCopy(); | initCodeCopy(); | ||
} | } | ||
| Line 226: | Line 175: | ||
} | } | ||
}() ); | }() ); | ||
Latest revision as of 23:47, 13 April 2026
/**
* eve.wiki — MediaWiki:Common.js
* Clean rewrite — no syntax errors
*/
( function () {
'use strict';
/* ============================================================
1. WAVE ACCORDION
============================================================ */
function initWaveAccordions() {
var waves = document.querySelectorAll( '.evewiki-wave' );
if ( !waves.length ) return;
waves.forEach( function ( wave, i ) {
var header = wave.querySelector( '.evewiki-wave-header' );
if ( !header ) return;
if ( i === 0 ) {
wave.classList.add( 'is-open' );
}
header.setAttribute( 'tabindex', '0' );
header.setAttribute( 'role', 'button' );
header.addEventListener( 'click', function () {
wave.classList.toggle( 'is-open' );
} );
header.addEventListener( 'keydown', function ( e ) {
if ( e.key === 'Enter' || e.key === ' ' ) {
e.preventDefault();
wave.classList.toggle( 'is-open' );
}
} );
} );
}
/* ============================================================
2. SEARCH HOTKEY — / to focus search
============================================================ */
function initSearchHotkey() {
document.addEventListener( 'keydown', function ( e ) {
var tag = document.activeElement ? document.activeElement.tagName : '';
if ( e.key === '/' && tag !== 'INPUT' && tag !== 'TEXTAREA' ) {
e.preventDefault();
var input = document.querySelector(
'#evewiki-search-input, .mw-inputbox-input, input.mw-searchInput, .citizen-search__input'
);
if ( input ) {
input.focus();
input.select();
}
}
} );
}
/* ============================================================
3. HOMEPAGE SEARCH — Enter key handler
============================================================ */
function initHomepageSearch() {
var input = document.querySelector( '.evewiki-hp-search .mw-inputbox-input' );
if ( !input ) return;
input.addEventListener( 'keydown', function ( e ) {
if ( e.key === 'Enter' ) {
var q = input.value.trim();
if ( q ) {
window.location = mw.util.getUrl( 'Special:Search' ) + '?search=' + encodeURIComponent( q ) + '&fulltext=1';
}
}
} );
}
/* ============================================================
4. ACTIVE NAV HIGHLIGHT
============================================================ */
function initActiveNav() {
var path = window.location.pathname;
var links = document.querySelectorAll( '.citizen-nav a, #citizen-sidebar a' );
links.forEach( function ( link ) {
var href = link.getAttribute( 'href' );
if ( href && href !== '/' && path.indexOf( href ) === 0 ) {
var li = link.closest( 'li' );
if ( li ) {
li.classList.add( 'citizen-nav__item--active' );
}
}
} );
}
/* ============================================================
5. INFOBOX IMAGE ZOOM
============================================================ */
function initInfoboxZoom() {
var imgs = document.querySelectorAll( '.infobox img, .evewiki-portrait img' );
imgs.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';
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 () {
if ( document.body.contains( overlay ) ) {
document.body.removeChild( overlay );
}
} );
document.addEventListener( 'keydown', function escHandler( e ) {
if ( e.key === 'Escape' ) {
if ( document.body.contains( overlay ) ) {
document.body.removeChild( overlay );
}
document.removeEventListener( 'keydown', escHandler );
}
} );
} );
} );
}
/* ============================================================
6. CODE BLOCK COPY BUTTON
============================================================ */
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';
btn.addEventListener( 'click', function () {
var text = pre.textContent.trim();
if ( navigator.clipboard ) {
navigator.clipboard.writeText( text ).then( function () {
btn.textContent = 'Copied!';
btn.style.color = '#3acc7a';
setTimeout( function () {
btn.textContent = 'Copy';
btn.style.color = '#93a4b5';
}, 2000 );
} );
}
} );
pre.appendChild( btn );
} );
}
/* ============================================================
INIT
============================================================ */
function init() {
initWaveAccordions();
initSearchHotkey();
initHomepageSearch();
initActiveNav();
initInfoboxZoom();
initCodeCopy();
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', init );
} else {
init();
}
}() );