MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
Created page with "→Any JavaScript here will be loaded for all users on every page load.: /* ========================================================================= aslimona.xyz — inline lightbox for gallery / thumbnail images Paste this ENTIRE file into: Special:MyLanguage/MediaWiki:Common.js (as an admin: go to https://aslimona.xyz/index.php/MediaWiki:Common.js click "Edit", paste, save.) Fixes the "click image -> File page -> back -> click next" problem: click..." |
No edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/* ========================================================================= | /* ========================================================================= | ||
aslimona.xyz — inline lightbox for gallery / thumbnail images | aslimona.xyz — inline lightbox for gallery / thumbnail images | ||
| Line 222: | Line 221: | ||
} ); | } ); | ||
} ); | } ); | ||
}() ); | |||
/* ========================================================================= | |||
CRAZY VERSION — per-page color scheme picker. | |||
Works together with the CRAZY VERSION block in MediaWiki:Common.css. | |||
Reads the current page name and picks ONE of 10 schemes | |||
(.crazy-scheme-0 … .crazy-scheme-9). Deterministic: the same page | |||
ALWAYS gets the same look, but different pages (Digital Twin, Homes of | |||
the Internet, Köçek Pisti …) look completely different from each other. | |||
To turn the crazy version off: delete this block AND the CRAZY VERSION | |||
block in MediaWiki:Common.css. The lightbox code above is unaffected. | |||
========================================================================= */ | |||
( function () { | |||
'use strict'; | |||
var SCHEMES = 10; | |||
function pageName() { | |||
if ( window.mw && mw.config && mw.config.get ) { | |||
var n = mw.config.get( 'wgPageName' ); | |||
if ( n ) { | |||
return n; | |||
} | |||
} | |||
return document.title || 'Main_Page'; | |||
} | |||
// reveal the (briefly hidden) content once the theme class is set, | |||
// so you don't see the plain dark layout flash before the colors. | |||
function reveal() { | |||
document.documentElement.classList.add( 'crazy-ready' ); | |||
} | |||
function apply() { | |||
try { | |||
var name = pageName(); | |||
var h = 0; | |||
for ( var i = 0; i < name.length; i++ ) { | |||
h = ( h * 31 + name.charCodeAt( i ) ) >>> 0; | |||
} | |||
var scheme = h % SCHEMES; | |||
// One of 12 background images, picked at RANDOM on every page load. | |||
var bg = Math.floor( Math.random() * 12 ); | |||
document.documentElement.classList.add( 'crazy-scheme-' + scheme, 'crazy-bg-' + bg ); | |||
if ( document.body ) { | |||
document.body.classList.add( 'crazy-scheme-' + scheme, 'crazy-bg-' + bg ); | |||
} | |||
} finally { | |||
// always reveal, even if something above failed | |||
reveal(); | |||
} | |||
} | |||
if ( document.readyState !== 'loading' ) { | |||
apply(); | |||
} else { | |||
document.addEventListener( 'DOMContentLoaded', apply ); | |||
} | |||
// hard safety net: never leave the page hidden for more than 1.5s | |||
setTimeout( reveal, 1500 ); | |||
}() ); | }() ); | ||
Latest revision as of 08:25, 26 July 2026
/* =========================================================================
aslimona.xyz — inline lightbox for gallery / thumbnail images
Paste this ENTIRE file into: Special:MyLanguage/MediaWiki:Common.js
(as an admin: go to https://aslimona.xyz/index.php/MediaWiki:Common.js
click "Edit", paste, save.)
Fixes the "click image -> File page -> back -> click next" problem:
clicking any gallery or thumbnail image now opens a big in-page viewer
with Prev/Next arrows and keyboard navigation, on every article,
automatically. No per-page changes needed.
========================================================================= */
( function () {
'use strict';
function onReady( fn ) {
if ( document.readyState !== 'loading' ) {
fn();
} else {
document.addEventListener( 'DOMContentLoaded', fn );
}
}
// Convert a MediaWiki thumbnail URL to the full-resolution original URL.
// e.g. .../images/a/a1/Foo.jpg/800px-Foo.jpg -> .../images/a/a1/Foo.jpg
// .../images/thumb/a/a1/Foo.jpg/800px-Foo.jpg -> .../images/a/a1/Foo.jpg
function originalFromThumb( src ) {
var m = src.match( /^(.*\/thumb\/([0-9a-f])\/([0-9a-f]{2})\/([^\/]+))\/\d+px-[^\/]+$/i );
if ( m ) {
return src.replace( '/thumb/', '/' ).replace( /\/\d+px-[^\/]+$/, '' );
}
var m2 = src.match( /^(.*\/[0-9a-f]\/[0-9a-f]{2}\/[^\/]+)\/\d+px-[^\/]+$/i );
if ( m2 ) {
return m2[ 1 ];
}
return src;
}
function injectStyles() {
var css = [
'.aslimona-lb-overlay{position:fixed;inset:0;background:rgba(6,6,7,0.94);',
'z-index:100000;display:flex;flex-direction:column;align-items:center;',
'justify-content:center;padding:4vh 4vw;box-sizing:border-box;}',
'.aslimona-lb-overlay[hidden]{display:none;}',
'.aslimona-lb-img{max-width:92vw;max-height:80vh;object-fit:contain;',
'border:1px solid #3a372f;background:#111;}',
'.aslimona-lb-caption{color:#a89f8c;font-family:"IBM Plex Mono","Courier New",monospace;',
'font-size:0.8rem;margin-top:14px;text-align:center;max-width:80vw;}',
'.aslimona-lb-counter{color:#6e6858;font-family:"IBM Plex Mono","Courier New",monospace;',
'font-size:0.7rem;margin-top:4px;letter-spacing:0.08em;}',
'.aslimona-lb-close,.aslimona-lb-prev,.aslimona-lb-next{position:fixed;',
'background:transparent;border:1px solid #3a372f;color:#e9e4d8;',
'font-family:Georgia,serif;cursor:pointer;transition:background .2s,color .2s;}',
'.aslimona-lb-close:hover,.aslimona-lb-prev:hover,.aslimona-lb-next:hover{',
'background:#c9a15a;color:#0c0c0d;}',
'.aslimona-lb-close{top:24px;right:24px;width:40px;height:40px;font-size:20px;',
'line-height:38px;text-align:center;}',
'.aslimona-lb-prev,.aslimona-lb-next{top:50%;transform:translateY(-50%);',
'width:48px;height:64px;font-size:22px;}',
'.aslimona-lb-prev{left:16px;}',
'.aslimona-lb-next{right:16px;}',
'@media (max-width:600px){',
'.aslimona-lb-prev,.aslimona-lb-next{width:36px;height:52px;font-size:18px;}',
'.aslimona-lb-close{width:34px;height:34px;font-size:17px;line-height:32px;}',
'}'
].join( '' );
var style = document.createElement( 'style' );
style.textContent = css;
document.head.appendChild( style );
}
function buildOverlay() {
var overlay = document.createElement( 'div' );
overlay.className = 'aslimona-lb-overlay';
overlay.hidden = true;
var img = document.createElement( 'img' );
img.className = 'aslimona-lb-img';
overlay.appendChild( img );
var caption = document.createElement( 'div' );
caption.className = 'aslimona-lb-caption';
overlay.appendChild( caption );
var counter = document.createElement( 'div' );
counter.className = 'aslimona-lb-counter';
overlay.appendChild( counter );
var closeBtn = document.createElement( 'button' );
closeBtn.className = 'aslimona-lb-close';
closeBtn.setAttribute( 'aria-label', 'Close' );
closeBtn.textContent = '×';
overlay.appendChild( closeBtn );
var prevBtn = document.createElement( 'button' );
prevBtn.className = 'aslimona-lb-prev';
prevBtn.setAttribute( 'aria-label', 'Previous image' );
prevBtn.textContent = '‹';
overlay.appendChild( prevBtn );
var nextBtn = document.createElement( 'button' );
nextBtn.className = 'aslimona-lb-next';
nextBtn.setAttribute( 'aria-label', 'Next image' );
nextBtn.textContent = '›';
overlay.appendChild( nextBtn );
document.body.appendChild( overlay );
return {
overlay: overlay,
img: img,
caption: caption,
counter: counter,
closeBtn: closeBtn,
prevBtn: prevBtn,
nextBtn: nextBtn
};
}
onReady( function () {
var content = document.querySelector( '.mw-parser-output' );
if ( !content ) {
return;
}
// Collect every lightbox-able image link on the page, in document order:
// - <gallery> thumbnails: li.gallerybox a.image
// - inline [[File:x|thumb]]: div.thumb a.image
var links = Array.prototype.slice.call(
content.querySelectorAll( 'li.gallerybox a.image, div.thumb a.image, a.image' )
);
if ( !links.length ) {
return;
}
// de-duplicate while preserving order
var seen = {};
links = links.filter( function ( a ) {
if ( seen[ a.href ] ) {
return false;
}
seen[ a.href ] = true;
return true;
} );
var items = links.map( function ( a ) {
var thumbImg = a.querySelector( 'img' );
var full = thumbImg ? originalFromThumb( thumbImg.src ) : a.href;
var captionEl = null;
var gallerytext = a.closest( 'li.gallerybox' );
if ( gallerytext ) {
captionEl = gallerytext.querySelector( '.gallerytext' );
} else {
var thumbinner = a.closest( '.thumbinner' );
if ( thumbinner ) {
captionEl = thumbinner.querySelector( '.thumbcaption' );
}
}
return {
full: full,
caption: captionEl ? captionEl.textContent.trim() : ( thumbImg ? thumbImg.alt : '' ),
link: a
};
} );
injectStyles();
var ui = buildOverlay();
var currentIndex = 0;
function show( index ) {
currentIndex = ( index + items.length ) % items.length;
var item = items[ currentIndex ];
ui.img.src = item.full;
ui.caption.textContent = item.caption || '';
ui.counter.textContent = ( currentIndex + 1 ) + ' / ' + items.length;
}
function open( index ) {
show( index );
ui.overlay.hidden = false;
document.body.style.overflow = 'hidden';
}
function close() {
ui.overlay.hidden = true;
document.body.style.overflow = '';
}
items.forEach( function ( item, index ) {
item.link.addEventListener( 'click', function ( ev ) {
// let ctrl/cmd/shift/middle-clicks behave normally (open in new tab etc.)
if ( ev.ctrlKey || ev.metaKey || ev.shiftKey || ev.button === 1 ) {
return;
}
ev.preventDefault();
open( index );
} );
} );
ui.closeBtn.addEventListener( 'click', close );
ui.prevBtn.addEventListener( 'click', function () {
show( currentIndex - 1 );
} );
ui.nextBtn.addEventListener( 'click', function () {
show( currentIndex + 1 );
} );
ui.overlay.addEventListener( 'click', function ( ev ) {
if ( ev.target === ui.overlay ) {
close();
}
} );
document.addEventListener( 'keydown', function ( ev ) {
if ( ui.overlay.hidden ) {
return;
}
if ( ev.key === 'Escape' ) {
close();
} else if ( ev.key === 'ArrowLeft' ) {
show( currentIndex - 1 );
} else if ( ev.key === 'ArrowRight' ) {
show( currentIndex + 1 );
}
} );
} );
}() );
/* =========================================================================
CRAZY VERSION — per-page color scheme picker.
Works together with the CRAZY VERSION block in MediaWiki:Common.css.
Reads the current page name and picks ONE of 10 schemes
(.crazy-scheme-0 … .crazy-scheme-9). Deterministic: the same page
ALWAYS gets the same look, but different pages (Digital Twin, Homes of
the Internet, Köçek Pisti …) look completely different from each other.
To turn the crazy version off: delete this block AND the CRAZY VERSION
block in MediaWiki:Common.css. The lightbox code above is unaffected.
========================================================================= */
( function () {
'use strict';
var SCHEMES = 10;
function pageName() {
if ( window.mw && mw.config && mw.config.get ) {
var n = mw.config.get( 'wgPageName' );
if ( n ) {
return n;
}
}
return document.title || 'Main_Page';
}
// reveal the (briefly hidden) content once the theme class is set,
// so you don't see the plain dark layout flash before the colors.
function reveal() {
document.documentElement.classList.add( 'crazy-ready' );
}
function apply() {
try {
var name = pageName();
var h = 0;
for ( var i = 0; i < name.length; i++ ) {
h = ( h * 31 + name.charCodeAt( i ) ) >>> 0;
}
var scheme = h % SCHEMES;
// One of 12 background images, picked at RANDOM on every page load.
var bg = Math.floor( Math.random() * 12 );
document.documentElement.classList.add( 'crazy-scheme-' + scheme, 'crazy-bg-' + bg );
if ( document.body ) {
document.body.classList.add( 'crazy-scheme-' + scheme, 'crazy-bg-' + bg );
}
} finally {
// always reveal, even if something above failed
reveal();
}
}
if ( document.readyState !== 'loading' ) {
apply();
} else {
document.addEventListener( 'DOMContentLoaded', apply );
}
// hard safety net: never leave the page hidden for more than 1.5s
setTimeout( reveal, 1500 );
}() );