MediaWiki:Common.js

From Mona Mahall / Asli Serbest
Revision as of 08:25, 26 July 2026 by Cmfiy (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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.
/* =========================================================================
   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 );
}() );