MediaWiki:Common.js

Aus CK-Wissen
Version vom 8. Oktober 2026, 21:56 Uhr von Cezary (Diskussion | Beiträge) (Helfer nachladen: Notfallkarte und Schmerz-Regler dazu)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
/* CK-Wissen (seit 25.09.2026): Nachtmodus.
   Ohne Wahl richtet sich die Seite nach der Einstellung von Handy oder Rechner – das macht MediaWiki:Common.css allein
   (Block B, ohne Skript und ohne Aufblitzen). Dieses Skript zeigt den Schalter „Automatisch · Hell · Dunkel“
   (Rechner: oben rechts, Handy: oben im Menü ☰) und merkt sich eine Wahl an zwei Stellen:
   - im Browser-Speicher (localStorage „ckw-farbe“) – bleibt, solange niemand die Website-Daten löscht;
   - im Cookie von MediaWiki („…mwclientpreferences“, Eintrag ckw-farbe-clientpref-hell/-dunkel, 30 Tage, wird bei jedem
     Besuch erneuert). Dieses Cookie liest MediaWiki schon beim Laden und tauscht am <html> die Grundklasse
     ckw-farbe-clientpref-auto gegen die Wahl aus, bevor etwas zu sehen ist – ohne Aufblitzen. Die Grundklasse gibt der
     Server aus (LocalSettings.php, Block ckw-nachtmodus-2026), beim Bearbeiten nicht.
   Fehlt die Grundklasse, setzt dieses Skript wie bisher die Klassen ckw-nacht / ckw-hell (dann blitzt es kurz).
   Beim Bearbeiten bleibt die Seite hell. Alte Testlinks (&nachtmodus=test / aus) funktionieren weiter. */
( function () {
	'use strict';
	var SCHLUESSEL = 'ckw-farbe';
	var KEKS = 'mwclientpreferences'; // mw.cookie ergänzt den Namen des Wikis davor
	var WERTE = [ 'auto', 'hell', 'dunkel' ];
	var html = document.documentElement;
	var bearbeiten = [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1;

	function gueltig( w ) { return WERTE.indexOf( w ) !== -1; }
	// Wert der Klasse ckw-farbe-clientpref-… am <html> (null, wenn der Server die Grundklasse nicht ausgibt)
	function klassenwert() {
		var m = html.className.match( /(?:^|\s)ckw-farbe-clientpref-(\w+)(?=\s|$)/ );
		return m ? m[ 1 ] : null;
	}
	function lesen() {
		var w = null;
		try { w = localStorage.getItem( SCHLUESSEL ); } catch ( e ) {}
		if ( gueltig( w ) ) { return w; }
		w = klassenwert();
		return gueltig( w ) ? w : 'auto';
	}
	// Cookie für MediaWiki: Einträge anderer Funktionen bleiben erhalten; „auto“ = kein Eintrag
	function keks( w ) {
		mw.loader.using( 'mediawiki.cookie' ).then( function () {
			var alt = mw.cookie.get( KEKS ) || '';
			var teile = alt.split( ',' ).filter( function ( t ) {
				return /^[\w-]+-clientpref-\w+$/.test( t ) && t.indexOf( SCHLUESSEL + '-clientpref-' ) !== 0;
			} );
			if ( w !== 'auto' ) { teile.push( SCHLUESSEL + '-clientpref-' + w ); }
			var neu = teile.join( ',' );
			if ( neu !== alt || w !== 'auto' ) { mw.cookie.set( KEKS, neu || null ); }
		} );
	}
	function merken( w ) {
		try { localStorage.setItem( SCHLUESSEL, w ); } catch ( e ) {}
		keks( w );
	}
	function anwenden( w ) {
		var k = klassenwert();
		if ( k !== null && k !== w ) {
			html.classList.remove( 'ckw-farbe-clientpref-' + k );
			html.classList.add( 'ckw-farbe-clientpref-' + w );
		}
		html.classList.toggle( 'ckw-nacht', w === 'dunkel' && !bearbeiten );
		html.classList.toggle( 'ckw-hell', w === 'hell' );
		Array.prototype.forEach.call( document.querySelectorAll( '.ckw-farbe button' ), function ( knopf ) {
			knopf.setAttribute( 'aria-pressed', knopf.value === w ? 'true' : 'false' );
		} );
	}

	// Aus der Testphase: Testlink und gemerkter Test-Schalter
	var wert = null;
	try { wert = new URLSearchParams( location.search ).get( 'nachtmodus' ); } catch ( e ) {}
	if ( wert !== null ) {
		if ( wert === 'test' || wert === 'an' ) { merken( 'dunkel' ); }
		if ( wert === 'aus' ) { merken( 'auto' ); }
		try {
			var sauber = new URL( location.href );
			sauber.searchParams.delete( 'nachtmodus' );
			history.replaceState( history.state, '', sauber.toString() );
		} catch ( e ) {}
	}
	try {
		if ( localStorage.getItem( 'ckw-nachtmodus-test' ) !== null ) {
			localStorage.removeItem( 'ckw-nachtmodus-test' );
			if ( localStorage.getItem( SCHLUESSEL ) === null ) { localStorage.setItem( SCHLUESSEL, 'dunkel' ); }
		}
	} catch ( e ) {}
	var jetzt = lesen();
	anwenden( jetzt );
	keks( jetzt ); // Cookie anlegen, angleichen oder um 30 Tage verlängern

	function schalter( lang ) {
		var gruppe = document.createElement( 'div' );
		gruppe.className = 'ckw-farbe';
		gruppe.setAttribute( 'role', 'group' );
		gruppe.setAttribute( 'aria-label', 'Darstellung' );
		[
			[ 'auto', lang ? 'Automatisch' : 'Auto', 'Wie am Gerät eingestellt' ],
			[ 'hell', 'Hell', 'Immer hell' ],
			[ 'dunkel', 'Dunkel', 'Immer dunkel (Nachtmodus)' ]
		].forEach( function ( o ) {
			var knopf = document.createElement( 'button' );
			knopf.type = 'button';
			knopf.value = o[ 0 ];
			knopf.textContent = o[ 1 ];
			knopf.title = o[ 2 ];
			knopf.addEventListener( 'click', function () { merken( o[ 0 ] ); anwenden( o[ 0 ] ); } );
			gruppe.appendChild( knopf );
		} );
		return gruppe;
	}

	$( function () {
		if ( mw.config.get( 'skin' ) === 'minerva' ) {
			var menue = document.getElementById( 'mw-mf-page-left' );
			if ( menue && !menue.querySelector( '.ckw-farbe-menue' ) ) {
				var box = document.createElement( 'div' );
				box.className = 'ckw-farbe-menue';
				var kopf = document.createElement( 'div' );
				kopf.className = 'ckw-farbe-kopf';
				kopf.textContent = 'Darstellung';
				box.appendChild( kopf );
				box.appendChild( schalter( true ) );
				var nav = menue.querySelector( '#p-navigation' );
				if ( nav ) { nav.parentNode.insertBefore( box, nav ); } else { menue.insertBefore( box, menue.firstChild ); }
			}
		} else {
			var liste = document.querySelector( '#p-personal ul' );
			if ( liste && !document.getElementById( 'pt-ckw-farbe' ) ) {
				var li = document.createElement( 'li' );
				li.id = 'pt-ckw-farbe';
				li.className = 'mw-list-item';
				li.appendChild( schalter( false ) );
				liste.insertBefore( li, liste.firstChild );
			}
		}
		anwenden( lesen() );
	} );

	// Wahl in einem anderen Tab geändert
	window.addEventListener( 'storage', function ( e ) {
		if ( e.key === SCHLUESSEL ) { anwenden( lesen() ); }
	} );
}() );

/* CK-Wissen (seit 24.09.2026): linke Leiste zum Aufklappen, „Auf dieser Seite“ rechts neben dem Text,
   Kleinigkeiten für die Lesespalte. Gestaltung dazu am Ende von MediaWiki:Common.css.
   Ohne Skript bleibt alles sichtbar (die Leiste geht nach 4 Sekunden von selbst auf). */
( function () {
	'use strict';

	var each = function ( liste, fn ) { Array.prototype.forEach.call( liste, fn ); };

	function titelAus( href ) {
		if ( !href ) { return null; }
		// nur einfache Seitenlinks (ohne &action=…, &oldid=… usw.)
		var m = href.match( /^[^?#]*\?title=([^&#]+)$/ ) || href.match( /\/index\.php\/([^?#]+)$/ );
		if ( !m ) { return null; }
		try { return decodeURIComponent( m[ 1 ] ).replace( / /g, '_' ); } catch ( e ) { return null; }
	}

	/* ---------- Linke Leiste ---------- */
	function leiste() {
		var panel = document.getElementById( 'mw-panel' );
		if ( !panel ) { return; }
		var hier = mw.config.get( 'wgPageName' );
		var SPEICHER = 'ckw-leiste';
		var gemerkt = {};
		try { gemerkt = JSON.parse( localStorage.getItem( SPEICHER ) || '{}' ) || {}; } catch ( e ) { gemerkt = {}; }
		var immerOffen = { 'p-navigation': true, 'p-Gegen_die_Attacke': true };

		each( panel.querySelectorAll( '.vector-menu-portal' ), function ( portal ) {
			var hatHier = false;
			each( portal.querySelectorAll( 'li > a' ), function ( a ) {
				if ( titelAus( a.getAttribute( 'href' ) ) === hier ) {
					a.parentNode.classList.add( 'ckw-hier' );
					a.setAttribute( 'aria-current', 'page' );
					hatHier = true;
				}
			} );
			if ( immerOffen[ portal.id ] ) { return; }
			var kopf = portal.querySelector( '.vector-menu-heading' );
			var inhalt = portal.querySelector( '.vector-menu-content' );
			if ( !kopf || !inhalt ) { return; }

			var anzahl = inhalt.querySelectorAll( 'li:not(#feedlinks)' ).length; // „Atom“ ist ausgeblendet (Common.css)
			if ( !inhalt.id ) { inhalt.id = portal.id + '-inhalt'; }
			var knopf = document.createElement( 'button' );
			knopf.type = 'button';
			knopf.className = 'ckw-klapp';
			knopf.setAttribute( 'aria-controls', inhalt.id );
			var text = document.createElement( 'span' );
			text.className = 'ckw-klapp-text';
			text.textContent = kopf.textContent.trim();
			var zahl = document.createElement( 'span' );
			zahl.className = 'ckw-klapp-zahl';
			zahl.textContent = String( anzahl );
			zahl.setAttribute( 'aria-hidden', 'true' );
			knopf.appendChild( text );
			knopf.appendChild( zahl );
			kopf.textContent = '';
			kopf.appendChild( knopf );

			var setze = function ( offen ) {
				knopf.setAttribute( 'aria-expanded', offen ? 'true' : 'false' );
				knopf.title = ( offen ? 'Zuklappen' : 'Aufklappen' ) + ' (' + anzahl + ' Seiten)';
				portal.classList.toggle( 'ckw-zu', !offen );
			};
			setze( hatHier || gemerkt[ portal.id ] === true );
			knopf.addEventListener( 'click', function () {
				var offen = knopf.getAttribute( 'aria-expanded' ) !== 'true';
				setze( offen );
				gemerkt[ portal.id ] = offen;
				try { localStorage.setItem( SPEICHER, JSON.stringify( gemerkt ) ); } catch ( e ) {}
			} );
		} );
		document.documentElement.classList.add( 'ckw-leiste-bereit' );
	}

	/* ---------- Lesespalte ---------- */
	function istLeseseite() {
		return mw.config.get( 'skin' ) === 'vector' &&
			mw.config.get( 'wgAction' ) === 'view' &&
			!mw.config.get( 'wgIsMainPage' ) &&
			[ 0, 1, 4, 5, 12 ].indexOf( mw.config.get( 'wgNamespaceNumber' ) ) !== -1;
	}

	function lesespalte( spalte ) {
		// Einleitung: erster Absatz vor der ersten Zwischenüberschrift, wenn er nicht zu lang ist
		var ersterAbsatz = null, kind = spalte.firstElementChild;
		while ( kind && kind.tagName !== 'H2' ) {
			if ( kind.tagName === 'P' && kind.textContent.trim().length > 40 ) { ersterAbsatz = kind; break; }
			kind = kind.nextElementSibling;
		}
		if ( ersterAbsatz && ersterAbsatz.textContent.length <= 650 ) { ersterAbsatz.classList.add( 'ckw-einleitung' ); }

		// Zu breite Tabellen seitlich schiebbar machen (nicht bei umflossenen Tabellen)
		each( spalte.querySelectorAll( 'table.wikitable' ), function ( t ) {
			if ( t.parentNode.classList.contains( 'ckw-tabelle' ) ) { return; }
			if ( window.getComputedStyle( t ).cssFloat !== 'none' ) { return; }
			var huelle = document.createElement( 'div' );
			huelle.className = 'ckw-tabelle';
			t.parentNode.insertBefore( huelle, t );
			huelle.appendChild( t );
		} );
	}

	/* ---------- „Auf dieser Seite“ ---------- */
	function seitennav( spalte ) {
		var toc = document.getElementById( 'toc' );
		var inhalt = document.getElementById( 'mw-content-text' );
		if ( !toc || !inhalt || !toc.querySelector( 'li.toclevel-1' ) ) { return; }

		var eintraege = [];
		var baue = function ( ul, ebene ) {
			var ol = document.createElement( 'ol' );
			each( ul.children, function ( li ) {
				var a = li.querySelector( ':scope > a' );
				if ( !a ) { return; }
				var neuLi = document.createElement( 'li' );
				var neuA = document.createElement( 'a' );
				neuA.href = a.getAttribute( 'href' );
				var t = a.querySelector( '.toctext' );
				neuA.textContent = ( t || a ).textContent;
				neuLi.appendChild( neuA );
				var ziel = null;
				try { ziel = document.getElementById( decodeURIComponent( neuA.hash.slice( 1 ) ) ); } catch ( e ) {}
				if ( ziel ) { eintraege.push( { a: neuA, li: neuLi, ziel: ziel.closest( 'h2, h3, h4' ) || ziel, ebene: ebene } ); }
				var unter = li.querySelector( ':scope > ul' );
				if ( unter && ebene < 2 ) { neuLi.appendChild( baue( unter, ebene + 1 ) ); }
				ol.appendChild( neuLi );
			} );
			return ol;
		};

		var nav = document.createElement( 'nav' );
		nav.className = 'ckw-seitennav';
		nav.setAttribute( 'aria-label', 'Auf dieser Seite' );
		var titel = document.createElement( 'div' );
		titel.className = 'ckw-seitennav-titel';
		titel.textContent = 'Auf dieser Seite';
		nav.appendChild( titel );
		nav.appendChild( baue( toc.querySelector( 'ul' ), 1 ) );
		var hoch = document.createElement( 'a' );
		hoch.href = '#top';
		hoch.className = 'ckw-nach-oben';
		hoch.textContent = 'Nach oben';
		nav.appendChild( hoch );
		inhalt.appendChild( nav );
		document.body.classList.add( 'ckw-mit-seitennav' );

		// Mitlaufende Markierung: welcher Abschnitt ist gerade zu sehen?
		var aktiv = null, geplant = false;
		var markiere = function () {
			geplant = false;
			if ( window.getComputedStyle( nav ).display === 'none' ) { return; }
			var neu = null;
			for ( var i = 0; i < eintraege.length; i++ ) {
				if ( eintraege[ i ].ziel.getBoundingClientRect().top <= 120 ) { neu = eintraege[ i ]; } else { break; }
			}
			if ( neu === aktiv ) { return; }
			each( nav.querySelectorAll( '.ckw-aktiv' ), function ( x ) { x.classList.remove( 'ckw-aktiv' ); } );
			each( nav.querySelectorAll( '.ckw-offen' ), function ( x ) { x.classList.remove( 'ckw-offen' ); } );
			aktiv = neu;
			if ( !neu ) { return; }
			neu.a.classList.add( 'ckw-aktiv' );
			var li = neu.li;
			while ( li && li !== nav ) {
				if ( li.tagName === 'LI' ) { li.classList.add( 'ckw-offen' ); }
				li = li.parentNode;
			}
			// Markierten Eintrag in der Liste sichtbar halten, ohne die Seite zu verschieben
			var oben = neu.a.offsetTop, unten = oben + neu.a.offsetHeight;
			if ( oben < nav.scrollTop + 40 ) { nav.scrollTop = Math.max( 0, oben - 60 ); }
			else if ( unten > nav.scrollTop + nav.clientHeight - 40 ) { nav.scrollTop = unten - nav.clientHeight + 60; }
		};
		var plane = function () {
			if ( !geplant ) { geplant = true; window.requestAnimationFrame( markiere ); }
		};
		window.addEventListener( 'scroll', plane, { passive: true } );
		window.addEventListener( 'resize', plane );
		markiere();
	}

	$( function () {
		// Themen der Leiste für „Weiter im Thema“ melden (vor dem Umbau der Überschriften)
		try {
			var panel = document.getElementById( 'mw-panel' ), gruppen = [];
			each( panel ? panel.querySelectorAll( '.vector-menu-portal' ) : [], function ( p ) {
				if ( p.id === 'p-tb' ) { return; }
				var kopf = p.querySelector( '.vector-menu-heading' ), links = [];
				each( p.querySelectorAll( 'li > a' ), function ( a ) {
					var text = a.textContent.trim(), href = a.getAttribute( 'href' );
					if ( text && href ) { links.push( [ text, href ] ); }
				} );
				if ( links.length ) { gruppen.push( { id: p.id, label: kopf ? kopf.textContent.trim() : '', links: links } ); }
			} );
			if ( gruppen.length ) { mw.hook( 'ckw.themen' ).fire( gruppen ); }
		} catch ( e ) { mw.log.warn( 'CK-Wissen Themen:', e ); }
		try { leiste(); } catch ( e ) {
			document.documentElement.classList.add( 'ckw-leiste-offen' );
			mw.log.warn( 'CK-Wissen Leiste:', e );
		}
		if ( !istLeseseite() ) { return; }
		var spalte = document.querySelector( '#mw-content-text > .mw-parser-output' );
		if ( !spalte ) { return; }
		try { lesespalte( spalte ); } catch ( e ) { mw.log.warn( 'CK-Wissen Lesespalte:', e ); }
		try { seitennav( spalte ); } catch ( e ) { mw.log.warn( 'CK-Wissen Seitennavigation:', e ); }
	} );
}() );

/* CK-Wissen (seit 24.09.2026): Handy-Ansicht – alle Themen der linken Leiste im Menü (☰) und unten auf jeder Seite,
   „Gegen die Attacke“ dort aufgeklappt gleich nach „Start“. Oben auf den Seiten steht seit 25.09.2026 kein
   Akut-Kasten mehr: In einer Attacke kann man kaum lesen, oben soll zuerst der Text der Seite kommen.
   Die Themen kommen automatisch aus MediaWiki:Sidebar: Das Skript liest die Desktop-Leiste einer
   leeren Seite und merkt sie sich im Browser für 12 Stunden. Gestaltung am Ende von MediaWiki:Common.css. */
( function () {
	'use strict';
	if ( mw.config.get( 'skin' ) !== 'minerva' ) { return; }

	var SPEICHER = 'ckw-themen-v2'; // v2 seit 25.09.2026: neue Gruppennamen der Leiste sofort zeigen
	try { localStorage.removeItem( 'ckw-themen-v1' ); } catch ( e ) {}
	var HALTBAR = 12 * 60 * 60 * 1000;
	var skript = mw.config.get( 'wgScript' );
	var hier = mw.config.get( 'wgPageName' );
	var istInhalt = mw.config.get( 'wgAction' ) === 'view' &&
		mw.config.get( 'wgNamespaceNumber' ) >= 0 &&
		!mw.config.get( 'wgIsMainPage' );

	function titelAus( href ) {
		if ( !href ) { return null; }
		var m = href.match( /^[^?#]*\?title=([^&#]+)$/ ) || href.match( /\/index\.php\/([^?#]+)$/ );
		if ( !m ) { return null; }
		try { return decodeURIComponent( m[ 1 ] ).replace( / /g, '_' ); } catch ( e ) { return null; }
	}

	function el( tag, klasse, text ) {
		var e = document.createElement( tag );
		if ( klasse ) { e.className = klasse; }
		if ( text ) { e.textContent = text; }
		return e;
	}

	function verweis( paar ) {
		var a = el( 'a', null, paar[ 0 ] );
		a.href = paar[ 1 ];
		if ( titelAus( paar[ 1 ] ) === hier ) {
			a.className = 'ckw-hier';
			a.setAttribute( 'aria-current', 'page' );
		}
		return a;
	}

	function gruppenBlock( gruppen, klasse ) {
		var box = el( 'div', klasse );
		gruppen.forEach( function ( g ) {
			var liste = el( 'ul' ), hatHier = false;
			g.links.forEach( function ( paar ) {
				var li = el( 'li' );
				var a = verweis( paar );
				if ( a.className === 'ckw-hier' ) { hatHier = true; }
				li.appendChild( a );
				liste.appendChild( li );
			} );
			if ( g.id === 'p-navigation' ) {
				var start = el( 'div', 'ckw-gruppe ckw-gruppe-start' );
				start.appendChild( liste );
				box.appendChild( start );
				return;
			}
			var akut = g.id === 'p-Gegen_die_Attacke';
			var d = el( 'details', 'ckw-gruppe' + ( akut ? ' ckw-gruppe-akut' : '' ) );
			d.open = akut || hatHier;
			var s = el( 'summary' );
			s.appendChild( el( 'span', 'ckw-gruppe-name', g.label ) );
			var zahl = el( 'span', 'ckw-gruppe-zahl', String( g.links.length ) );
			zahl.setAttribute( 'aria-hidden', 'true' );
			s.appendChild( zahl );
			d.appendChild( s );
			d.appendChild( liste );
			box.appendChild( d );
		} );
		return box;
	}

	function zeigen( gruppen ) {
		// Menü (☰): Themen nach „Start“ und „Zufällige Seite“
		var menue = document.getElementById( 'mw-mf-page-left' );
		if ( menue ) {
			var altM = menue.querySelector( '.ckw-menue-themen' );
			if ( altM ) { altM.parentNode.removeChild( altM ); }
			var themenM = gruppenBlock( gruppen.filter( function ( g ) { return g.id !== 'p-navigation'; } ), 'ckw-menue-themen' );
			var nav = menue.querySelector( '#p-navigation' );
			if ( nav ) { nav.parentNode.insertBefore( themenM, nav.nextSibling ); } else { menue.appendChild( themenM ); }
		}

		// Unten auf der Seite: alle Themen
		var haupt = document.getElementById( 'content' );
		if ( istInhalt && haupt ) {
			var altU = document.querySelector( '.ckw-mobil-themen' );
			if ( altU ) { altU.parentNode.removeChild( altU ); }
			var unten = el( 'nav', 'ckw-mobil-themen' );
			unten.setAttribute( 'aria-labelledby', 'ckw-mobil-themen-titel' );
			var h = el( 'h2', 'ckw-mobil-themen-titel', 'Themen' );
			h.id = 'ckw-mobil-themen-titel';
			unten.appendChild( h );
			unten.appendChild( gruppenBlock( gruppen, 'ckw-mobil-themen-liste' ) );
			haupt.appendChild( unten );
		}
		mw.hook( 'ckw.themen' ).fire( gruppen );
	}

	function ausLeiste( html ) {
		var doc = new DOMParser().parseFromString( html, 'text/html' );
		var gruppen = [];
		Array.prototype.forEach.call( doc.querySelectorAll( '#mw-panel .vector-menu-portal' ), function ( p ) {
			if ( p.id === 'p-tb' ) { return; }
			var kopf = p.querySelector( '.vector-menu-heading' );
			var links = [];
			Array.prototype.forEach.call( p.querySelectorAll( 'li > a' ), function ( a ) {
				var text = a.textContent.trim(), href = a.getAttribute( 'href' );
				if ( text && href ) { links.push( [ text, href ] ); }
			} );
			if ( links.length ) { gruppen.push( { id: p.id, label: kopf ? kopf.textContent.trim() : '', links: links } ); }
		} );
		return gruppen;
	}

	$( function () {
		try {
			var gemerkt = null;
			try { gemerkt = JSON.parse( localStorage.getItem( SPEICHER ) || 'null' ); } catch ( e ) {}
			if ( gemerkt && gemerkt.gruppen && Date.now() - gemerkt.zeit < HALTBAR ) {
				zeigen( gemerkt.gruppen );
				return;
			}
			fetch( skript + '?title=Special:BlankPage&useskin=vector&useformat=desktop', { credentials: 'omit' } )
				.then( function ( r ) { return r.ok ? r.text() : Promise.reject( r.status ); } )
				.then( function ( html ) {
					var gruppen = ausLeiste( html );
					if ( !gruppen.length ) { return; }
					try { localStorage.setItem( SPEICHER, JSON.stringify( { zeit: Date.now(), gruppen: gruppen } ) ); } catch ( e ) {}
					zeigen( gruppen );
				} )
				.catch( function () {
					if ( gemerkt && gemerkt.gruppen ) { zeigen( gemerkt.gruppen ); }
				} );
		} catch ( e ) {
			mw.log.warn( 'CK-Wissen Handy-Navigation:', e );
		}
	} );
}() );

/* CK-Wissen (seit 25.09.2026): „Weiter im Thema“ am Ende jedes Artikels – vorherige und nächste Seite
   aus derselben Gruppe der linken Leiste (MediaWiki:Sidebar), am Rechner und auf dem Handy.
   Steht vor „Siehe auch“, „Literatur“, „Weblinks“ bzw. „Einzelnachweise“, sonst am Ende des Textes. */
( function () {
	'use strict';
	var ENDE = /^(Siehe auch|Literatur|Weblinks|Externe Links|Einzelnachweise|Quellen|Belege|Referenzen|Fußnoten|Anmerkungen)\b/i;

	function titelAus( href ) {
		if ( !href ) { return null; }
		var m = href.match( /^[^?#]*\?title=([^&#]+)$/ ) || href.match( /\/index\.php\/([^?#]+)$/ );
		if ( !m ) { return null; }
		try { return decodeURIComponent( m[ 1 ] ).replace( / /g, '_' ); } catch ( e ) { return null; }
	}

	function el( tag, klasse, text ) {
		var e = document.createElement( tag );
		if ( klasse ) { e.className = klasse; }
		if ( text ) { e.textContent = text; }
		return e;
	}

	function karte( paar, richtung, klasse ) {
		var a = el( 'a', 'ckw-weiter-karte ' + klasse );
		a.href = paar[ 1 ];
		a.appendChild( el( 'span', 'ckw-weiter-richtung', richtung ) );
		a.appendChild( el( 'span', 'ckw-weiter-titel', paar[ 0 ] ) );
		return a;
	}

	function weiter( gruppen ) {
		if ( mw.config.get( 'wgAction' ) !== 'view' || mw.config.get( 'wgIsMainPage' ) ||
			mw.config.get( 'wgNamespaceNumber' ) < 0 ||
			mw.config.get( 'wgRevisionId' ) !== mw.config.get( 'wgCurRevisionId' ) ) { return; }
		var namen = [ mw.config.get( 'wgPageName' ) ];
		if ( mw.config.get( 'wgRedirectedFrom' ) ) { namen.push( String( mw.config.get( 'wgRedirectedFrom' ) ).replace( / /g, '_' ) ); }
		var spalte = document.querySelector( '#mw-content-text > .mw-parser-output' );
		if ( !spalte ) { return; }

		var gruppe = null, liste = null, stelle = -1;
		gruppen.some( function ( g ) {
			if ( g.id === 'p-navigation' ) { return false; }
			var seiten = g.links.filter( function ( p ) {
				var t = titelAus( p[ 1 ] );
				return t && !/^(Spezial|Special):/.test( t );
			} );
			for ( var i = 0; i < seiten.length; i++ ) {
				if ( namen.indexOf( titelAus( seiten[ i ][ 1 ] ) ) !== -1 ) { gruppe = g; liste = seiten; stelle = i; return true; }
			}
			return false;
		} );
		if ( !gruppe || liste.length < 2 ) { return; }

		var alt = spalte.querySelector( '.ckw-weiter' );
		if ( alt ) { alt.parentNode.removeChild( alt ); }
		var nav = el( 'nav', 'ckw-weiter' );
		nav.setAttribute( 'aria-label', 'Weiter im Thema ' + gruppe.label );
		var kopf = el( 'div', 'ckw-weiter-kopf', 'Weiter im Thema ' );
		kopf.appendChild( el( 'b', null, gruppe.label ) );
		kopf.appendChild( document.createTextNode( ' ' ) );
		kopf.appendChild( el( 'span', 'ckw-weiter-stelle', '· Seite ' + ( stelle + 1 ) + ' von ' + liste.length ) );
		nav.appendChild( kopf );
		var karten = el( 'div', 'ckw-weiter-karten' );
		if ( stelle > 0 ) { karten.appendChild( karte( liste[ stelle - 1 ], '← Zurück', 'ckw-weiter-zurueck' ) ); }
		if ( stelle < liste.length - 1 ) { karten.appendChild( karte( liste[ stelle + 1 ], 'Weiter →', 'ckw-weiter-vor' ) ); }
		else if ( stelle >= 2 ) { karten.appendChild( karte( liste[ 0 ], 'Zum Anfang des Themas ↺', 'ckw-weiter-vor' ) ); }
		nav.appendChild( karten );

		// Vor „Siehe auch“, „Literatur“, „Einzelnachweise“ … einsetzen, sonst ans Ende
		var ziel = null;
		Array.prototype.some.call( spalte.querySelectorAll( 'h2' ), function ( h ) {
			if ( h.parentNode !== spalte ) { return false; }
			var t = ( h.querySelector( '.mw-headline' ) || h ).textContent.trim();
			if ( ENDE.test( t ) ) { ziel = h; return true; }
			return false;
		} );
		if ( ziel ) { spalte.insertBefore( nav, ziel ); } else { spalte.appendChild( nav ); }
	}

	mw.hook( 'ckw.themen' ).add( function ( gruppen ) {
		try { weiter( gruppen ); } catch ( e ) { mw.log.warn( 'CK-Wissen Weiter im Thema:', e ); }
	} );
}() );

/* CK-Wissen (seit 25.09.2026): Tabellen, die nicht in die Seitenbreite passen, werden als Karten gezeigt.
   Jede Zeile wird eine Karte, die Spaltenüberschriften stehen als kleine Beschriftung über jedem Wert.
   Passt die Tabelle in die Breite, bleibt sie eine Tabelle. Gilt am Rechner und am Handy und prüft neu,
   wenn sich die Breite ändert oder ein zugeklappter Abschnitt aufgeht. Nur für einfache Tabellen mit
   Kopfzeile und ohne zusammengefasste Zellen (Zwischenüberschriften über die ganze Breite gehen). Abschalten für eine Tabelle: class="wikitable ckw-nie-karten".
   Die Gestaltung steht in MediaWiki:Common.css unter „Zu breite Tabellen als Karten“. */
( function () {
	'use strict';
	if ( mw.config.get( 'wgAction' ) !== 'view' ) { return; }

	function geeignet( t ) {
		if ( t.classList.contains( 'ckw-nie-karten' ) || t.classList.contains( 'ckw-karten-bereit' ) ) { return false; }
		if ( t.querySelector( 'table' ) || ( t.parentElement && t.parentElement.closest( 'table' ) ) ) { return false; }
		var zeilen = t.rows;
		if ( zeilen.length < 2 ) { return false; }
		var kopf = zeilen[ 0 ].cells;
		if ( kopf.length < 2 ) { return false; }
		for ( var i = 0; i < kopf.length; i++ ) {
			if ( kopf[ i ].tagName !== 'TH' || kopf[ i ].colSpan > 1 || kopf[ i ].rowSpan > 1 ) { return false; }
		}
		for ( var z = 1; z < zeilen.length; z++ ) {
			var zellen = zeilen[ z ].cells;
			// Zwischenüberschrift über die ganze Breite: wird in der Kartenansicht zur Überschrift
			if ( zellen.length === 1 && zellen[ 0 ].colSpan === kopf.length && zellen[ 0 ].rowSpan === 1 ) { continue; }
			if ( zellen.length !== kopf.length ) { return false; }
			for ( var k = 0; k < zellen.length; k++ ) {
				if ( zellen[ k ].colSpan > 1 || zellen[ k ].rowSpan > 1 ) { return false; }
			}
		}
		return true;
	}

	function beschrifte( t ) {
		var kopf = t.rows[ 0 ].cells;
		t.rows[ 0 ].classList.add( 'ckw-karten-kopf' );
		for ( var z = 1; z < t.rows.length; z++ ) {
			var zellen = t.rows[ z ].cells;
			if ( zellen.length === 1 && zellen[ 0 ].colSpan > 1 ) { t.rows[ z ].classList.add( 'ckw-karten-gruppe' ); continue; }
			for ( var k = 0; k < zellen.length; k++ ) {
				var name = kopf[ k ].textContent.replace( /\[\d+\]/g, '' ).replace( /\s+/g, ' ' ).trim();
				zellen[ k ].setAttribute( 'data-ckw-spalte', name );
				if ( !zellen[ k ].textContent.trim() && !zellen[ k ].querySelector( 'img' ) ) { zellen[ k ].classList.add( 'ckw-karten-leer' ); }
			}
		}
		t.classList.add( 'ckw-karten-bereit' );
	}

	function pruefe( t ) {
		var huelle = t.parentElement;
		if ( !huelle ) { return; }
		var platz = huelle.clientWidth;
		if ( !platz ) { return; } // unsichtbar, etwa in einem zugeklappten Abschnitt
		var war = t.classList.contains( 'ckw-karten' );
		if ( war ) { t.classList.remove( 'ckw-karten' ); }
		var zuBreit = t.scrollWidth > platz + 2;
		if ( zuBreit ) { t.classList.add( 'ckw-karten' ); }
		if ( huelle.classList.contains( 'ckw-tabelle' ) ) { huelle.classList.toggle( 'ckw-tabelle-karten', zuBreit ); }
	}

	function einrichten( wurzel ) {
		var tabellen = [];
		var liste = wurzel.querySelectorAll( '.mw-parser-output table.wikitable' );
		for ( var i = 0; i < liste.length; i++ ) {
			if ( geeignet( liste[ i ] ) ) { beschrifte( liste[ i ] ); tabellen.push( liste[ i ] ); }
		}
		if ( !tabellen.length ) { return; }
		var alle = function () { tabellen.forEach( pruefe ); };
		alle();
		if ( window.ResizeObserver ) {
			var breiten = new Map();
			var ro = new ResizeObserver( function ( eintraege ) {
				eintraege.forEach( function ( e ) {
					var b = Math.round( e.contentRect.width );
					if ( breiten.get( e.target ) === b ) { return; }
					breiten.set( e.target, b );
					tabellen.forEach( function ( t ) { if ( t.parentElement === e.target ) { pruefe( t ); } } );
				} );
			} );
			tabellen.forEach( function ( t ) { if ( t.parentElement ) { ro.observe( t.parentElement ); } } );
		} else {
			var warte;
			window.addEventListener( 'resize', function () { clearTimeout( warte ); warte = setTimeout( alle, 200 ); } );
		}
	}

	window.ckwTabellenAlsKarten = einrichten;
	// Immer die ganze Seite prüfen: Andere Skripte melden über denselben Haken auch kleine eingefügte Teile,
	// und ein später angemeldeter Empfänger bekommt nur die letzte Meldung. Bereits erledigte Tabellen werden übersprungen.
	var spaeter = function () { setTimeout( function () { einrichten( document ); }, 0 ); };
	mw.hook( 'wikipage.content' ).add( spaeter );
	$( spaeter );
}() );

/* CK-Wissen (seit 25.09.2026): Druckansicht – Zwischenüberschriften, unter denen nur Nicht-zu-Druckendes steht
   (<div class="noprint">…, etwa Weblinks oder Videos), beim Drucken weglassen. Setzt die Klasse ckw-druck-leer;
   die Gestaltung steht in MediaWiki:Common.css im Abschnitt „Druckansicht“. Der Gesundheitshinweis (ckw-hinweis)
   zählt dabei nicht als Inhalt des letzten Abschnitts. */
( function () {
	'use strict';
	function ebene( el ) {
		var m = /^H([1-6])$/.exec( el.tagName );
		if ( m ) { return Number( m[ 1 ] ); }
		m = el.classList.contains( 'mw-heading' ) && /(?:^|\s)mw-heading(\d)(?:\s|$)/.exec( el.className );
		return m ? Number( m[ 1 ] ) : 0;
	}
	function weg( el ) {
		return el.classList.contains( 'noprint' ) || el.classList.contains( 'ckw-druck-leer' ) || el.classList.contains( 'ckw-hinweis' ) ||
			/^(LINK|META|STYLE|SCRIPT)$/.test( el.tagName );
	}
	// Steht in el etwas, das gedruckt wird? (Text oder Bild/Tabelle außerhalb von noprint)
	function druckbar( el ) {
		if ( weg( el ) ) { return false; }
		var gang = document.createTreeWalker( el, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, { acceptNode: function ( n ) {
			if ( n.nodeType === 1 ) {
				if ( weg( n ) ) { return NodeFilter.FILTER_REJECT; }
				return /^(IMG|TABLE)$/.test( n.tagName ) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
			}
			return n.textContent.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
		} } );
		return gang.nextNode() !== null;
	}
	function markiere( spalte ) {
		var kopf = Array.prototype.filter.call( spalte.children, function ( el ) { return ebene( el ) >= 2; } );
		// von hinten nach vorn: Unterabschnitte zuerst, dann weiß der Oberabschnitt, ob unter ihm noch etwas steht
		for ( var i = kopf.length - 1; i >= 0; i-- ) {
			var h = kopf[ i ], e = ebene( h ), leer = true, el = h.nextElementSibling;
			while ( el && !( ebene( el ) && ebene( el ) <= e ) ) {
				if ( druckbar( el ) ) { leer = false; break; }
				el = el.nextElementSibling;
			}
			h.classList.toggle( 'ckw-druck-leer', leer );
		}
	}
	mw.hook( 'wikipage.content' ).add( function ( $inhalt ) {
		var wurzel = $inhalt && $inhalt[ 0 ];
		if ( !wurzel ) { return; }
		var spalte = wurzel.classList.contains( 'mw-parser-output' ) ? wurzel : wurzel.querySelector( '.mw-parser-output' );
		if ( !spalte ) { return; }
		// Handy-Ansicht: Abschnitte stecken in <section>; die inneren zuerst
		var behaelter = Array.prototype.slice.call( spalte.querySelectorAll( 'section' ) ).reverse();
		behaelter.push( spalte );
		behaelter.forEach( markiere );
	} );
}() );

/* CK-Wissen (seit 26.09.2026): YouTube-Videos laden erst nach einem Klick (Vorlage:YouTube).
   Beim Öffnen der Seite wird nichts von YouTube oder Google geladen, auch kein Vorschaubild. Erst der Klick auf
   „Video abspielen“ setzt den Player von youtube-nocookie.com ein; der Klick ist die Einwilligung
   (§ 25 Abs. 1 TDDDG, Art. 6 Abs. 1 lit. a DSGVO, siehe CK-Wissen:Datenschutz). Gemerkt wird nichts:
   Auf jeder Seite und bei jedem Besuch fragt die Fläche neu. Ohne Skript bleibt der Link „Direkt auf YouTube ansehen“. */
( function () {
	'use strict';
	var ID = /^[A-Za-z0-9_-]{11}$/;
	function abspielen( box, flaeche, id, titel ) {
		var rahmen = document.createElement( 'iframe' );
		rahmen.src = 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0';
		rahmen.title = titel ? 'Video: ' + titel : 'YouTube-Video';
		rahmen.setAttribute( 'allow', 'autoplay; encrypted-media; picture-in-picture; fullscreen' );
		rahmen.setAttribute( 'allowfullscreen', '' );
		rahmen.setAttribute( 'referrerpolicy', 'strict-origin-when-cross-origin' );
		flaeche.textContent = '';
		flaeche.appendChild( rahmen );
		box.classList.add( 'ckw-video-an' );
		rahmen.focus();
	}
	function einrichten( wurzel ) {
		Array.prototype.forEach.call( wurzel.querySelectorAll( '.ckw-video[data-ckw-video]' ), function ( box ) {
			var id = box.getAttribute( 'data-ckw-video' );
			var flaeche = box.querySelector( '.ckw-video-flaeche' );
			if ( !ID.test( id ) || !flaeche || box.classList.contains( 'ckw-video-an' ) || flaeche.querySelector( '.ckw-video-start' ) ) { return; }
			var t = flaeche.querySelector( '.ckw-video-titel' );
			var titel = t ? t.textContent.trim() : '';
			var knopf = document.createElement( 'button' );
			knopf.type = 'button';
			knopf.className = 'ckw-video-start';
			knopf.setAttribute( 'aria-label', 'Video abspielen' + ( titel ? ': ' + titel : '' ) + ' (wird von YouTube geladen)' );
			var dreieck = document.createElement( 'span' );
			dreieck.className = 'ckw-video-play';
			dreieck.setAttribute( 'aria-hidden', 'true' );
			knopf.appendChild( dreieck );
			knopf.appendChild( document.createTextNode( 'Video abspielen' ) );
			knopf.addEventListener( 'click', function () { abspielen( box, flaeche, id, titel ); } );
			flaeche.appendChild( knopf );
		} );
	}
	mw.hook( 'wikipage.content' ).add( function ( $inhalt ) {
		if ( $inhalt && $inhalt[ 0 ] ) { einrichten( $inhalt[ 0 ] ); }
	} );
}() );

/* CK-Wissen (seit 27.09.2026): Kopfzeile – in schmalen Fenstern am Rechner (etwa Tablet hochkant) rutschen
   die Reiter („Lesen“, „Versionsgeschichte“ …) und die Suche in eine zweite Zeile und lagen dann über der
   Seitenüberschrift. Jetzt rückt der Seiteninhalt um diese Zeile nach unten. Gilt nur für die Rechner-Ansicht. */
( function () {
	'use strict';
	var basis = document.getElementById( 'mw-head-base' );
	var rechts = document.getElementById( 'right-navigation' );
	if ( !basis || !rechts || !document.body.classList.contains( 'skin-vector-legacy' ) ) { return; }
	function pruefen() {
		basis.style.marginBottom = '';
		var mehr = Math.ceil( rechts.getBoundingClientRect().bottom - basis.getBoundingClientRect().bottom );
		// nur bei einer echten zweiten Zeile (rund 40 Pixel), nicht bei Rundungsresten von 1–2 Pixeln
		if ( mehr > 10 ) {
			basis.style.marginBottom = ( mehr + 6 ) + 'px';
		}
	}
	pruefen();
	var warten;
	window.addEventListener( 'resize', function () {
		clearTimeout( warten );
		warten = setTimeout( pruefen, 120 );
	} );
	if ( document.fonts && document.fonts.ready ) { document.fonts.ready.then( pruefen ); }
}() );

/* CK-Wissen (seit 10.2026): kleine Helfer auf einzelnen Seiten.
   GdB-Seite: Regler „Was bringt welcher GdB?“ und Antrags-Helfer. Sauerstoffflasche: Rechner „Wie lange reicht meine Flasche?“.
   Ärzte und Kliniken: Suche nach Ort, Postleitzahl oder Name. Notaufnahme: Notfallkarte zum Ausfüllen.
   Schmerzskala: Regler „Wo liegt Ihr stärkster Schmerz?“.
   Programm und Aussehen liegen in eigenen Seiten (MediaWiki:CKW-GdB-Helfer, MediaWiki:CKW-O2-Rechner, MediaWiki:CKW-Arztsuche,
   MediaWiki:CKW-Notfallkarte, MediaWiki:CKW-Schmerzskala, jeweils .js und .css).
   Hier wird nur nachgeladen, und nur auf Seiten, in denen der passende Kasten steht.
   Browser merken sich die Helfer einen Tag lang. Nach einer Änderung an einem Helfer „stand“ um eins erhöhen,
   dann holen alle Browser gleich die neue Fassung. */
( function () {
	'use strict';
	var stand = 2, helfer = [
		[ '.ckw-gdb-stufen, .ckw-antragshelfer', 'CKW-GdB-Helfer' ],
		[ '.ckw-o2-rechner', 'CKW-O2-Rechner' ],
		[ '.ckw-arztsuche', 'CKW-Arztsuche' ],
		[ '.ckw-notfallkarte', 'CKW-Notfallkarte' ],
		[ '.ckw-schmerzskala', 'CKW-Schmerzskala' ]
	], geladen = {};
	mw.hook( 'wikipage.content' ).add( function ( $inhalt ) {
		var wurzel = $inhalt && $inhalt[ 0 ];
		if ( !wurzel || !wurzel.querySelector ) { return; }
		helfer.forEach( function ( h ) {
			if ( geladen[ h[ 1 ] ] || !wurzel.querySelector( h[ 0 ] ) ) { return; }
			geladen[ h[ 1 ] ] = true;
			var seite = mw.config.get( 'wgScript' ) + '?title=MediaWiki:' + h[ 1 ];
			mw.loader.load( seite + '.css&action=raw&ctype=text/css&maxage=86400&smaxage=86400&v=' + stand, 'text/css' );
			mw.loader.load( seite + '.js&action=raw&ctype=text/javascript&maxage=86400&smaxage=86400&v=' + stand );
		} );
	} );
}() );