Zum Inhalt springen

MediaWiki:Gadget-CategoryAboveAll.js

aus AufEinWort, der freien Forschung

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();
        });
    }
});