MediaWiki:Gadget-CategoryAboveAll.js
Erscheinungsbild
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
// Gadget: CategoryAboveAll — Kategorienblock nach oben verschieben + Zustand merken
// Gestaltung: MediaWiki:Gadget-CategoryAboveAll.css
//siehe weitere Angaben unter Hilfe:Gadget-CategoryAboveAll.js
$(function () {
var KEY = 'CategoryAboveAll:expanded'; // "1" = geöffnet, "0" = geschlossen
function isExpanded() {
try { return localStorage.getItem(KEY) === '1'; } catch (e) { return false; }
}
function setExpanded(on) {
try { localStorage.setItem(KEY, on ? '1' : '0'); } catch (e) {}
}
function moveCats() {
var ns = mw.config.get('wgNamespaceNumber');
if (ns === -1) return; // Spezialseiten auslassen
var bc = document.getElementById('mw-content-text') || document.getElementById('bodyContent');
var catlinks = document.getElementById('catlinks');
if (!bc || !catlinks) return;
if (!catlinks.innerHTML.trim()) return;
// Vor der Rückkehr prüfen: Inhalt kann später dynamisch hinzukommen.
var oberordnung = document.getElementById('seitenordnung-oberordnung');
if (oberordnung && oberordnung.parentNode !== catlinks) {
catlinks.appendChild(oberordnung);
}
if (oberordnung) {
var kopfzeile = oberordnung.querySelector('.seitenordnung-kopfzeile');
var quellen = kopfzeile && kopfzeile.querySelector('.seitenordnung-quellen');
if (quellen) {
// Wie bisher nur den ersten Quellenkopf verschieben.
// Weitere Quellenangaben bleiben bei ihrem Textabschnitt.
var quellenkopf = document.getElementById('seitenordnung-kopf') ||
bc.querySelector('span.seitenordnung');
if (quellenkopf && quellenkopf.parentNode !== quellen) {
quellen.appendChild(quellenkopf);
}
// Auch SMW-Links in zusätzlichen Hüll-Elementen berücksichtigen.
var allLinks = $(quellen).find('a');
// Auch zuvor gesetzte Markierungen in Hinweisen entfernen.
allLinks.removeClass('seitenordnung-link-getrennt');
var links = allLinks.filter(function () {
return this.textContent.trim() !== '' &&
!$(this).closest('.seitenordnung-hinweis').length;
});
links.slice(1).addClass('seitenordnung-link-getrennt');
}
if (oberordnung.dataset.kategoriestufenLazy !== '1' &&
oberordnung.dataset.categoryAboveAllToggle !== '1') {
oberordnung.dataset.categoryAboveAllToggle = '1';
mw.loader.using('jquery.makeCollapsible').then(function () {
// Bereits initialisierte Blöcke behalten ihren Zustand.
$(oberordnung).makeCollapsible();
$(oberordnung).find('.mw-collapsible-toggle').attr({
title: 'ein-/ausklappen',
'aria-label': 'Kategoriestufen ein-/ausklappen'
});
});
}
}
if (catlinks.dataset.movedByCategoryAboveAll === '1') return;
catlinks.dataset.movedByCategoryAboveAll = '1';
// Nach oben versetzen
$(bc).prepend(catlinks);
// Toggle-Button
var $btn = $('<button id="kat-toggle-button" class="kat-toggle-button" type="button">Kategorien</button>');
$(catlinks).before($btn);
// Persistenten Zustand anwenden
var expanded = isExpanded();
if (expanded) {
$(catlinks).show();
$btn.attr('aria-expanded', 'true');
} else {
$(catlinks).hide();
$btn.attr('aria-expanded', 'false');
}
// Klick: anzeigen/verbergen + Zustand speichern
$btn.on('click', function () {
var willExpand = !$(catlinks).is(':visible');
setExpanded(willExpand);
$btn.attr('aria-expanded', willExpand ? 'true' : 'false');
$(catlinks).slideToggle();
});
}
function bindLazyTree(tree) {
if (tree.dataset.kategoriestufenLazy !== '1' || tree.dataset.lazyBound === '1') return;
tree.dataset.lazyBound = '1';
var placeholder = tree.querySelector('.kategoriestufen-laden');
if (!placeholder) throw new Error('Kategoriestufen: Schalter fehlt in der Kopfzeile.');
// Wikitext erlaubt kein button-Element; erst im Browser erzeugen.
var button = document.createElement('button');
button.type = 'button';
button.className = 'kategoriestufen-laden';
button.title = 'ein-/ausklappen';
button.setAttribute('aria-label', 'Kategoriestufen ein-/ausklappen');
button.setAttribute('aria-expanded', 'false');
button.setAttribute('aria-controls', 'kategoriestufen-inhalt');
button.textContent = '⎇';
placeholder.parentNode.replaceChild(button, placeholder);
var content = tree.querySelector('.kategoriestufen-inhalt');
var count = tree.querySelector('.seitenordnung-anzahl');
var expanded = false;
var generation = 0;
var pending = null;
button.addEventListener('click', function () {
expanded = !expanded;
var current = ++generation;
button.setAttribute('aria-expanded', expanded ? 'true' : 'false');
button.textContent = expanded ? '⌥' : '⎇';
content.hidden = !expanded;
if (!expanded) {
if (pending && pending.abort) pending.abort();
content.textContent = '';
count.textContent = '';
return;
}
content.textContent = 'Kategoriestufen werden geladen …';
mw.loader.using('mediawiki.api').then(function () {
if (!expanded || current !== generation) return;
pending = new mw.Api().post({
action: 'parse', formatversion: 2,
title: mw.config.get('wgPageName'), contentmodel: 'wikitext',
text: '{{#invoke:Kategoriestufen|anzeige}}',
prop: 'text|modules', disablelimitreport: true
});
return pending;
}).then(function (data) {
if (!data || !expanded || current !== generation) return;
var holder = document.createElement('div');
$(holder).append($.parseHTML(data.parse.text, document, false));
var result = holder.querySelector('#seitenordnung-oberordnung');
var body = result && result.querySelector('.mw-collapsible-content');
if (!body) {
var error = holder.querySelector('.error');
content.textContent = error ? error.textContent :
'Keine Kategoriestufen verfügbar.';
return;
}
content.textContent = '';
while (body.firstChild) content.appendChild(body.firstChild);
var resultCount = result.querySelector('.seitenordnung-anzahl');
count.textContent = resultCount ? resultCount.textContent : '';
if (data.parse.modules && data.parse.modules.length) mw.loader.load(data.parse.modules);
mw.hook('wikipage.content').fire($(content));
}).catch(function () {
if (expanded && current === generation) {
content.textContent = 'Laden fehlgeschlagen. Zum erneuten Versuch zu- und wieder aufklappen.';
}
});
});
}
var automaticRequested = false;
function loadAutomaticTree() {
var cats = document.getElementById('catlinks');
if (automaticRequested || document.getElementById('seitenordnung-oberordnung') ||
!cats || !cats.querySelector('.mw-normal-catlinks li, .mw-hidden-catlinks li') ||
mw.config.get('wgNamespaceNumber') < 0 ||
mw.config.get('wgAction') !== 'view' || !mw.config.get('wgArticleId')) return;
automaticRequested = true;
mw.loader.using('mediawiki.api').then(function () {
return new mw.Api().post({
action: 'parse', formatversion: 2,
title: mw.config.get('wgPageName'), contentmodel: 'wikitext',
text: '{{#invoke:Kategoriestufen|kopf}}',
prop: 'text|modules', disablelimitreport: true
});
}).then(function (data) {
// Eine vorhandene Vorlage hat Vorrang, auch nach dynamischen Änderungen.
if (document.getElementById('seitenordnung-oberordnung')) return;
var parsed = data.parse;
var holder = document.createElement('div');
$(holder).append($.parseHTML(parsed.text, document, false));
var tree = holder.querySelector('#seitenordnung-oberordnung');
if (!tree) {
var error = holder.querySelector('.error');
if (error) {
var note = document.createElement('div');
note.className = 'error';
note.textContent = error.textContent;
cats.appendChild(note);
}
return; // Nicht freigegebener Namensraum liefert leere Ausgabe.
}
if (parsed.modules && parsed.modules.length) mw.loader.load(parsed.modules);
cats.appendChild(tree);
bindLazyTree(tree);
moveCats();
mw.hook('wikipage.content').fire($(tree));
}).catch(function () {
var note = document.createElement('div');
note.className = 'error';
note.textContent = 'Kategoriestufen konnten nicht geladen werden. Bitte die Seite neu laden.';
cats.appendChild(note);
});
}
// Initial
moveCats();
loadAutomaticTree();
// Auch nach dynamischen Inhaltswechseln (z. B. VE / Ajax)
if (mw && mw.hook) {
mw.hook('wikipage.content').add(function () {
moveCats();
loadAutomaticTree();
});
}
});