Zum Inhalt springen

Gespräch:Gadget H2Kipper

aus AufEinWort, der freien Forschung

Über diese Seite Gespräch

Erweiterung CollapsibleSections
ChatGPT Sophos GPT-4
4. September 2025 n. Chr. erst.  
Ausgabe 02
Ausgabe 02
unüberarbeitet ungeprüft
2025090402 Gadget-H2Kipper

Nikolaos:

Hallo Sophos,

Für MediaWiki gibt es Erweiterung:CollapsibleSections.

Diese Erweitung ermöglicht mir mit Überschrift  h1, h2, h3 gesetzte Inhalte collapsible zu setzen, sodaß die jeweils nachfolgenden Textinhalte erst zur Ansicht eingeblendet werden müssen.

Diese Extension funktioniert jedoch nur für Inhalte im Body einer Wikiseite.

Ich möchte gerne diese Funktion ebenso für die h2-Überschriften "Unterkategorien" und "Seiten in der Kategorie (Pagename)" auf Kategorie Seiten haben.

Ich nutze die VectorSkin in meinem MediaWiki 1.43.

Due Attribute von class="mw-category-generated" sind:

1. id="mw-subcategories" für h2-Überschriften "Unterkategorien"

2. id="mw-pages" für h2-Überschriften  "Seiten in der Kategorie (Pagename)"

Diese Attribute und Anziege deren Inhalte werden von MediaWIki außerhalb des body der Seite erzeugt, Erweiterung:CollapsibleSections wirkt sich nur auf den body ener Seite aus, daher funktioniert diese Erweiterung nicht für vom System erzeugte Überschriften auf einer Wikiseite.

Was ist dein Lösungsvorschlag der mir ermöglicht die Rubriken schaltbar lockal gesichert über collapsible zu haben?

Erstellung JavaScript für Anwendung auf Kategorieseiten

Sophos:


Die Zeitanzeige sollte im Format (3. Sep. 2025, 18:48) korrekten sein, mit einem einzelnen, nicht führenden Null für die Stunde und dem deutschen Monatsabkürzungsformat. Bei der Aufgabe scheint es, dass die "Unterkategorien" und "Seiten in der Kategorie" durch die MediaWiki-Extension CollapsibleSections gesteuert werden sollen. Sie betrifft jedoch nur h2 innerhalb von .mw-parser-output, weshalb die gewünschten Kategorien möglicherweise nicht automatisch angesprochen werden.

Wir brauchen ein JS-Gadget, das die Elemente mit den IDs #mw-subcategories und #mw-pages in kollabierbare Container einfügt. Es soll die jeweiligen Listen und die Titeln (h2) darin umschließen. Die Zustände der Container sollen in localStorage gespeichert werden. Eine Möglichkeit wäre die jQuery-Methode jquery.makeCollapsible zu nutzen, um diese Container klickbar und collapsible zu machen.

Um die Abschnitte #mw-subcategories und #mw-pages zu kollabieren, könnte ich den mw.loader.using Befehl verwenden, um die nötigen Module zu laden. Für jede Sektion identifiziere ich die Überschrift (h2) und verschiebe den Inhalt in einen „kollabierbaren“ Wrapper. Die Zustände speichere ich in localStorage, um sie zu persistieren.

Für das MediaWiki-Gadget "CategoryH2Toggle" müssen wir sicherstellen, dass es nur auf der Kategorie-Namespace arbeitet (wgNamespaceNumber === 14). CSS sollte das Ein- und Ausklappen über Pfeil-Icons ermöglichen. Event-Handler persistieren die Zustände in localStorage, und eine Rückfall-Option für mw.storage sorgt für Kompatibilität. Das Gadget sollte auch prüfen, ob Subkategorien oder Seiten existieren.

Wir implementieren ein Gadget, das den Zustand von Abschnitten auf Kategorie-Seiten speichert und bei Bedarf ein- oder ausklappt. Wir verwenden mw.storage für die Persistenz und sorgen dafür, dass der Code nur auf Kategorie-Namespace-Seiten läuft. Das Setup umfasst das Hinzufügen von Toggle-Buttons, die den Zustand speichern, sowie CSS für das Design und Barrierefreiheit (mit aria-expanded). Eine Option für "Expand All/Collapse All" ist auch enthalten.

Fertig

Hallo Nikolaos — (3. Sep. 2025, 18:48) Kurzfassung: Wir umgehen die Beschränkung von „CollapsibleSections“, indem wir ein kleines Gadget schreiben, das auf Kategorieseiten (NS 14) gezielt die beiden systemerzeugten Bereiche #mw-subcategories und #mw-pages nach dem <h2> in ein umschaltbares Wrapper-Element („collapsible“) packt. Der Ein-/Ausklappzustand wird pro Kategorie und Bereich lokal gespeichert (mw.storage/localStorage). Keine Änderung an der Extension nötig.

Schritt-für-Schritt

1) MediaWiki:Gadget-CategoryH2Collapsible.js

/* CategoryH2Collapsible – macht die Kategoriemodule "Unterkategorien" und
   "Seiten in der Kategorie …" umschaltbar und merkt sich den Zustand.
   Kompatibel mit MediaWiki 1.43 + Vector. */

mw.loader.using(['mediawiki.storage']).then(function () {
    'use strict';

    if (mw.config.get('wgNamespaceNumber') !== 14) return; // nur Kategorie-Namensraum

    var DEFAULT_COLLAPSED = false; // auf true setzen, wenn standardmäßig eingeklappt

    function makeCollapsible(sectionId) {
        var sec = document.getElementById(sectionId);
        if (!sec) return;

        // Nur einmal pro Seite/Sektion ausführen
        if (sec.querySelector('.aew-collapsible-content')) return;

        var h2 = sec.querySelector('h2');
        if (!h2) return;

        // Inhalt nach der H2 in einen Wrapper verschieben
        var wrapper = document.createElement('div');
        wrapper.className = 'aew-collapsible-content';
        wrapper.id = sectionId + '-content';

        var node = h2.nextSibling;
        while (node) {
            var next = node.nextSibling;
            wrapper.appendChild(node);
            node = next;
        }
        sec.appendChild(wrapper);

        // Toggle-Button in der H2
        var btn = document.createElement('button');
        btn.type = 'button';
        btn.className = 'aew-collapsible-toggle';
        btn.setAttribute('aria-controls', wrapper.id);
        btn.setAttribute('aria-expanded', 'true');
        btn.title = 'Ein-/ausklappen';

        // optische Pfeile ▾/▸ als reiner Text (barrierearm, ohne Icon-Font)
        btn.textContent = '▾';
        h2.insertBefore(btn, h2.firstChild);

        var key = 'aewCatCollapsible:' + mw.config.get('wgPageName') + ':' + sectionId;
        var stored = mw.storage.get(key);
        var startCollapsed = (stored === '1') || (stored === null && DEFAULT_COLLAPSED);

        function setState(collapsed) {
            if (collapsed) {
                wrapper.style.display = 'none';
                btn.textContent = '▸';
                btn.setAttribute('aria-expanded', 'false');
                mw.storage.set(key, '1');
            } else {
                wrapper.style.display = '';
                btn.textContent = '▾';
                btn.setAttribute('aria-expanded', 'true');
                mw.storage.set(key, '0');
            }
        }

        // Initialzustand
        setState(startCollapsed);

        // Klick auf Button toggelt
        btn.addEventListener('click', function (e) {
            e.preventDefault();
            var isOpen = wrapper.style.display !== 'none';
            setState(isOpen); // wenn offen -> schließen, sonst öffnen
        });

        // Optional: Klick auf H2 (außer Links/Buttons) toggelt ebenfalls
        h2.addEventListener('click', function (e) {
            var t = e.target;
            if (t === btn || t.closest('a, button')) return;
            var isOpen = wrapper.style.display !== 'none';
            setState(isOpen);
        });
    }

    // Sicher auch nach Soft-Navigationen aktiv (Vector modern)
    mw.hook('wikipage.content').add(function () {
        makeCollapsible('mw-subcategories');
        makeCollapsible('mw-pages');
    });
});

2) MediaWiki:Gadget-CategoryH2Collapsible.css

/* Minimalistische Optik, skin-neutral */
.aew-collapsible-toggle {
    cursor: pointer;
    background: none;
    border: 0;
    padding: 0 .35em 0 0;
    margin-right: .2em;
    font-size: 0.95em;
    line-height: 1;
    vertical-align: middle;
}
.aew-collapsible-content { margin-top: .25rem; }

3) MediaWiki:Gadgets-definition

Füge (oder passe) einen Gadget-Eintrag an, z. B.:

* CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage]|CategoryH2Collapsible.js|CategoryH2Collapsible.css

Hinweise & Varianten

  • Warum das funktioniert: Die Bereiche #mw-subcategories und #mw-pages liegen außerhalb von .mw-parser-output, werden aber dennoch im Inhalts-DOM gerendert. Wir adressieren sie direkt per id statt über Parser-Output. So umschiffen wir die Scope-Beschränkung von „CollapsibleSections“.
  • Persistenz: Schlüssel ist pro Kategorie (seitenspezifisch via wgPageName) und pro Abschnitt (mw-subcategories / mw-pages).
  • Standardzustand: Mit DEFAULT_COLLAPSED steuerbar (false = offen, true = zu, bis Nutzer etwas anderes wählt).
  • Zugänglichkeit: aria-controls/aria-expanded gesetzt; Pfeile als Text, damit auch ohne Icon-Fonts erkennbar.
  • Konflikte: Läuft unabhängig von „CollapsibleSections“ und beeinflusst nur NS 14. Falls du bereits ein Gadget hast, das an diesen IDs arbeitet, darauf achten, dass kein doppeltes Wrapping passiert (oben bereits durch Guard verhindert).

Wenn du zusätzlich einen „Alle ein-/ausklappen“-Schalter willst (z. B. im Seitenwerkzeugmenü), ergänze ich dir das gerne sofort.

Nikolaos:

Danke für den Entwurf. Wie registriere ich ein Gadget? Es ist zu lange her und weiß nicht mehr wie ich das machen muß?

Sophos:


Um ein Gadget in MediaWiki 1.43 mit dem Vector-Design zu registrieren, müssen wir sicherstellen, dass das Gadgets-Addon aktiviert ist (es ist in neueren Versionen standardmäßig aktiviert). Der Prozess umfasst das Erstellen eines Eintrags auf der Seite MediaWiki:Gadgets-definition, das Anlegen von JavaScript- und CSS-Dateien sowie das Festlegen von Abhängigkeiten und Zielen wie Desktop oder Mobile.

Um ein Gadget in MediaWiki zu registrieren, müssen wir sicherstellen, dass das Gadget-Addon in der Datei LocalSettings.php aktiviert ist. In MediaWiki ab Version 1.32 müssen Gadgets in der Seite MediaWiki:Gadgets-definition definiert werden. Es gibt Optionen wie $wgGadgetsList und $wgGadgetsRepoCompat. Die Syntax ermöglicht das Hinzufügen von JavaScript- und CSS-Dateien.

Um ein Gadget zu registrieren, müssen wir die Erweiterung aktivieren, die Definition erstellen, die Skript- und CSS-Dateien anlegen und den Cache leeren. Es gibt auch Schritt-für-Schritt-Anleitungen:

  • Gadget über „Einstellungen“ oder „Standard“ aktivieren.
  • Über „Spezial:Gadgets“ testen.
  • Caching-Optionen und Zurücksetzungen nach Anpassungen sind wichtig.

Stelle sicher, dass die „Gadgets“-Erweiterung in LocalSettings.php geladen ist: wfLoadExtension('Gadgets');. Die Option $wgGadgetsRepoCompat ist nicht nötig. Erstelle dann die benötigten Dateien: MediaWiki:Gadget-CategoryH2Collapsible.js und MediaWiki:Gadget-CategoryH2Collapsible.css. Registriere das Gadget in der MediaWiki:Gadgets-definition-Seite mit der richtigen Syntax. Achte auf den richtigen Parameter: „defaults“ anstelle von „default“.

Fertig

Gern! Hier ist die komprimierte „So registrierst du ein Gadget“-Anleitung für MediaWiki 1.43 (Vector):

Schritte

  1. Gadgets-Extension aktiv? In LocalSettings.php prüfen/ergänzen:
wfLoadExtension( 'Gadgets' );

→ Seite neu laden.

  1. Code-Seiten anlegen Lege diese Systemseiten an (als „Seiten im MediaWiki-Namensraum“):
  • MediaWiki:Gadget-CategoryH2Collapsible.js ← dein JS
  • MediaWiki:Gadget-CategoryH2Collapsible.css ← (optional) CSS
  • MediaWiki:Gadget-CategoryH2Collapsible ← (optional) Beschreibungstext fürs Einstellungsmenü
  1. In MediaWiki:Gadgets-definition eintragen Füge eine Zeile hinzu (ein Eintrag pro Gadget):
* CategoryH2Collapsible[
    ResourceLoader
    |dependencies=mediawiki.storage
    |targets=desktop,mobile
    |namespaces=14
    |actions=view
    |skins=vector
]|CategoryH2Collapsible.js|CategoryH2Collapsible.css
  • namespaces=14 lädt nur auf Kategorieseiten (spart Leistung).
  • skins=vector: nur Vector (weglassen, wenn universell).
  • Optional: |default (für alle Nutzer automatisch an) und ggf. |hidden (nicht abschaltbar in den Einstellungen).
  1. Aktivieren / testen
  • Ohne |default: Benutzer → Einstellungen → Gadgets und das Gadget anhaken.
  • Mit |default: ist sofort aktiv.
  • Zum Testen/Fehlerfall:
    • ?safemode=1 an URL anhängen → lädt ohne Gadgets (Rettungsleine).
    • ?debug=true an URL → frisch geladen, ohne RL-Cache.
    • Browser-Konsole prüfen.

Mini-Checkliste

  • Siehst du dein Gadget auf Spezial:Gadgets? → Registrierung ok.
  • Wird das RL-Modul geladen? In der Konsole mw.loader.getState('ext.gadget.CategoryH2Collapsible')prüfen (sollte "ready" sein).
  • Änderungen greifen nicht? Seite purgen (?action=purge) oder kurz ?debug=true.

Varianten

  • Möchtest du, dass das Gadget nur im Lesemodus greift: |actions=view (oben schon enthalten).
  • Falls du auch auf Mobil-Frontend (Minerva) testen willst: targets=mobile beibehalten (oder entfernen, wenn nur Desktop).

Wenn du magst, poste kurz, ob du es als default oder manuell schaltbar haben willst — dann gebe ich dir die exakt passende Gadgets-definition-Zeile dafür.

Nikolaos:

Ich habe bereits in "MediaWiki:Gadgets-definition" folgende Einträge.

* ReferenceTooltips[ResourceLoader|default|skins=vector,vector-2022,Citizen|type=general|dependencies=mediawiki.cookie,jquery.client]|ReferenceTooltips.js|ReferenceTooltips.css

* HotCat[ResourceLoader|dependencies=mediawiki.user|rights=upload|default|targets=desktop,mobile]|HotCat.js|Hotcatcheck.js

* purgetab[ResourceLoader|dependencies=mediawiki.util, mediawiki.api]|purgetab.js

* CategoryAboveAll [ResourceLoader]|CategoryAboveAll.js

Deinen Eintrag habe ich so vorgenommen, jedoch erscheint dieser nicht in Spezial:Gadgets.

Ist das von dir vorgegebene Format für den Eintrag in "MediaWiki:Gadgets-definition" richtig?

Sophos:


Es sieht so aus, als müsste die Gadget-Definition in einer einzigen Zeile sein, ohne Space im Namen. Die Parameter sind durch pipes | getrennt und können Zeilenumbrüche haben. Es könnte ein Problem mit dem Leerzeichen im Gadget-Namen "CategoryAboveAll [ResourceLoader]" geben, obwohl das in neueren Versionen immer noch funktionieren könnte. Gast der Fehler wird genau dort liegen.

In MediaWiki dürfen Gadget-Namen keine Leerzeichen enthalten, da sie sich auf Seiten wie "MediaWiki:Gadget-<name>.js" beziehen. Das Leerzeichen im Namen "CategoryAboveAll [ResourceLoader]" könnte problematisch sein, aber nicht zwingend. Es könnte auch an den Parametern wie 'namespaces=14' und 'actions=view' liegen, die verhindern, dass das Gadget in Spezial:Gadgets erscheint.

Ich glaube, dass Gadgets in Special:Gadgets nur dann erscheinen, wenn sie eine Beschreibungseite wie 'MediaWiki:Gadget-Name' haben. Falls diese fehlt, könnte der Name der Seite verwendet werden. Auch 'type=' oder 'skins=vector' könnten eine Rolle spielen, aber das ist nicht zwingend erforderlich. Die Syntax scheint mehrzeilig möglich, aber das ist unklar. Die Führung von Leerzeichen oder die Bullet-Syntax könnten auch zu Problemen führen.

Es scheint, dass die Gadget-Definition keine Zeilenumbrüche unterstützt, da sie parserlos ist und durch die Erweiterung verarbeitet wird. Um sicherzustellen, dass sie korrekt erscheint, sollte die Zeile keine Umbrüche enthalten und die Modulseiten wie 'MediaWiki:Gadget-CategoryH2Collapsible.js' und .css existieren. Zudem könnte das Löschen von Caches helfen, wenn Probleme auftreten.

Fertig

Gern. Ja – das Format in MediaWiki:Gadgets-definition ist sehr strikt: ein Gadget pro Zeile, ohne Zeilenumbrüche innerhalb der Klammern und ohne Leerzeichen zwischen Name und [.

1) Korrekte Eintragszeile (eins zu eins übernehmen)

  • ohne Auto-Aktivierung (manuell schaltbar in den Einstellungen):
Gern. Ja – das Format in MediaWiki:Gadgets-definition ist sehr strikt: ein Gadget pro Zeile, ohne Zeilenumbrüche innerhalb der Klammern und ohne Leerzeichen zwischen Name und [.
1) Korrekte Eintragszeile (eins zu eins übernehmen)
ohne Auto-Aktivierung (manuell schaltbar in den Einstellungen):
  • mit Auto-Aktivierung für alle (standardmäßig an):
    * CategoryH2Collapsible[ResourceLoader|default|dependencies=mediawiki.storage|targets=desktop,mobile|actions=view|namespaces=14|skins=vector]|CategoryH2Collapsible.js|CategoryH2Collapsible.css
    

2) Beschreibungsseite anlegen (sonst erscheint es oft nicht in „Spezial:Gadgets“)

Lege MediaWiki:Gadget-CategoryH2Collapsible an, z. B. mit:

Macht die Bereiche „Unterkategorien“ und „Seiten in der Kategorie …“ auf Kategorieseiten (NS 14) einklappbar; merkt den Zustand pro Kategorie.

Ohne diese Seite taucht das Gadget in den Einstellungen/„Spezial:Gadgets“ häufig nicht auf, auch wenn es geladen werden kann.

3) Typische Stolpersteine

  • Kein Leerzeichen zwischen Gadget-Name und [ (bei dir steht z. B. „CategoryAboveAll [ResourceLoader]“ – besser „CategoryAboveAll[ResourceLoader]“).
  • Eine Zeile pro Gadget. Keine mehrzeiligen Optionen.
  • Module müssen existieren: MediaWiki:Gadget-CategoryH2Collapsible.js (und optional .css).
  • Caches: Nach Änderungen einmal Seite „Spezial:Gadgets“ neu laden, ggf. ?debug=true oder ?action=purgenutzen.

4) Schnelltest / Diagnose

  • In der Browser-Konsole:
    mw.loader.getState('ext.gadget.CategoryH2Collapsible')
    
    • Erwartet: "registered" oder "ready". Wenn undefined → der Eintrag in Gadgets-definition wird nicht erkannt (Syntax, Name, Zeilenumbruch).

Wenn du mir kurz sagst, ob du default willst oder manuell schaltbar, passe ich dir die Zeile inkl. deiner Skin-/Namespace-Präferenzen exakt an.

Erst nachdem ich

* CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage|targets=desktop,mobile|actions=view|namespaces=14|skins=vector]|CategoryH2Collapsible.js|CategoryH2Collapsible.css

auf

* CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage|actions=view|namespaces=14]|CategoryH2Collapsible.js|CategoryH2Collapsible.css

umgestellt habe, ging es, also erst nach dem ich die Anweisung für Desktop und mObile und VectorSkin entfernt habe.

Es funktioniert auch nach reload der Seite – gnenau das, was ich bei manschmal hunderten Kategorien und Unterseiten benötigte – danke dafür.

Sophos:


Ich denke, wir sollten freundlich antworten und den Erfolg anerkennen. Es könnte hilfreich sein zu erklären, warum die Filter für "targets" und "skins" so sind, wie sie sind. Für Vector sollte "vector" oder "vector-2022" die richtigen Werte sein, aber bei benutzerdefinierten Themen könnte der Key "vector-2022" sein. "targets=desktop,mobile" passt normalerweise, wenn Minerva installiert ist.

Standardmäßig verwendet RL "targets=desktop", was in Ordnung ist, wenn man beide angibt. Aber der Filter "skins=vector" könnte blockiert haben, weil sie "vector-2022" nutzen. In MW 1.43 sollte man "skins=vector-2022" verwenden, um sicherzugehen. Auch "targets=desktop,mobile" benötigt MobileFrontend, aber beide Targets könnten trotzdem funktionieren.

Wenn sie tatsächlich Vector-2022 verwenden, blockiert "skins=vector" möglicherweise die Anzeige. In diesem Fall sollten sie "vector-2022" angeben. Wir könnten auch vorschlagen, optional "|default" hinzuzufügen, wenn es für alle Benutzer angezeigt werden soll oder "|hidden" für unsichtbar. Außerdem wäre es gut, "|type=general" für eine Gruppierung hinzuzufügen.

Fertig

Top — freut mich, dass es läuft!

Warum es erst nach dem Entfernen von targets/skins ging:

  • In MediaWiki 1.43 heißt die neue Vector-Variante intern vector-2022. Wenn du skins=vector gesetzt hattest, wurde das Gadget auf vector-2022 nicht geladen.
  • targets=desktop,mobile ist optional. Ohne Mobile-Frontend oder bei reinem Desktop-Betrieb bringt der Zusatz keinen Mehrwert.

Wenn du die Skin-Einschränkung trotzdem nutzen willst (empfohlen, aber korrekt), nimm am besten beide Vector-Keys auf:

Manuell schaltbar:

* CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage|actions=view|namespaces=14|skins=vector,vector-2022]|CategoryH2Collapsible.js|CategoryH2Collapsible.css

Für alle standardmäßig an:

* CategoryH2Collapsible[ResourceLoader|default|dependencies=mediawiki.storage|actions=view|namespaces=14|skins=vector,vector-2022]|CategoryH2Collapsible.js|CategoryH2Collapsible.css

Kleine Extras (optional):

  • |hidden anhängen, wenn es nicht in den Benutzer-Einstellungen auftauchen soll.
  • |type=general anhängen, damit es in „Spezial:Gadgets“ sauber einsortiert ist.
  • Achte weiterhin auf kein Leerzeichen zwischen Name und [ (z. B. CategoryAboveAll[ResourceLoader]).

Möchtest du zusätzlich einen globalen „Alle ein-/ausklappen“-Schalter auf Kategorieseiten? Baue ich dir gern rein.

Erweiterung Gadget-H2Kipper für Spezialseiten

Nikolaos:

Mein MediaWiki ist nur für Desktop oder Tablet (iPad) – nicht für Smartphone

Ja ich nutze Vector-2022.

Was muß ich verändern, wenn dies auch für Spezialseiten funktionieren soll?

Auf Spezialseite betrifft es class="mw-specialpagesgroup" die ebenfalls h2 sind.

Kann man das Coding dafür anpassen?

Warum?

Ich brauche da meist immer dieselben Bereiche und muß jedoch alle durch-scrollen um zu denen zu gelangen die ich brauch.

Sophos:


Die Anfrage betrifft die Spezialseiten in MediaWiki (Spezialseiten gruppiert nach h2 mit der Klasse „mw-specialpagesgroup”). Nutzer möchten, dass diese h2-Elemente ein- und ausklappbar sind. Es wird eine dauerhafte Speicherung des Zustands über Sitzungen gewünscht, basierend auf der Seitenbezeichnung und der Überschrift. Ich werde nach einer Lösung suchen, um diese Anpassungen im Gadget auf Special:SpecialPages zu integrieren.

Die Anpassung betrifft speziell „Special:SpecialPages“, wo die Gruppenüberschriften die Klasse „mw-specialpagesgroup“ haben. Ich werde sicherstellen, dass der Standard für diese Seiten möglicherweise zugeklappt ist. Zudem muss der Code so aufgesetzt werden, dass diese Funktion auch für alle anderen weiteren speziellen Seiten bei Bedarf funktioniert, basierend auf dem Wert von wgCanonicalSpecialPageName.

Ich muss sicherstellen, dass die Umsetzung nur auf „Special:SpecialPages“ erfolgt. Für jede „h2“-Überschrift werde ich den nächsten Geschwister-Element-Block einwickeln. Dabei sollte die Persistenz der Gruppentexte über stabile Schlüssel erfolgen. Der Namespace-Check „wgNamespaceNumber === -1“ wird sicherstellen, dass es nur für Spezialseiten funktioniert.

Die Gadget-Anzeige soll nur auf Vector-2022-Desktop/Tablet-Skins erscheinen, also füge ich die Restriktion „skins=vector-2022“ hinzu. Ich passe den Code so an, dass er auf „namespace 14“ oder „special Specialpages“ läuft. Zur Speicherung der Gruppenköpfe habe ich auch eine Methode für eindeutige IDs mit einer einfachen Hash-Funktion geplant.

Fertig

Super, dann erweitern wir das Gadget so, dass es auch auf Spezial:Spezialseiten (Special:SpecialPages) die Gruppen-Überschriften (h2.mw-specialpagesgroup) einklappbar macht – mit persistiertem Zustand und optionalen „bevorzugt offen“-Gruppen, damit du nicht mehr scrollen musst.

1) Aktualisiere dein JS (MediaWiki:Gadget-CategoryH2Collapsible.js)

Ersetzt deinen bisherigen Inhalt komplett durch Folgendes.

/* CategoryH2Collapsible – Kategorien & Spezial:Spezialseiten einklappbar
   - Kategorien (NS 14): #mw-subcategories, #mw-pages
   - Spezial:Spezialseiten (NS -1, Canonical: Specialpages): h2.mw-specialpagesgroup
   MediaWiki 1.43 + Vector-2022
*/
mw.loader.using(['mediawiki.storage']).then(function () {
    'use strict';

    var CONFIG = {
        // Standardzustand:
        defaultCollapsedCategories: false,  // Kategorien: offen
        defaultCollapsedSpecialpages: true, // Spezial:Spezialseiten: zu

        // Optional: Diese Gruppen (genauer H2-Text) auf Spezial:Spezialseiten sollen
        // TROTZ defaultCollapsedSpecialpages standardmäßig offen bleiben:
        // Beispiel: ['Wartung und Berichte', 'Seitenlisten']
        specialpagesPreferOpen: [],

        // Klick auf H2 (außer Links/Buttons) toggelt auch:
        useClickOnHeading: true
    };

    function makeSectionCollapsible(h2, contentNodes, storageKey, startCollapsed) {
        if (!h2 || !contentNodes || contentNodes.length === 0) return;
        if (h2.classList.contains('aew-collapsible-bound')) return;
        h2.classList.add('aew-collapsible-bound');

        // Wrapper für den Content
        var wrapper = document.createElement('div');
        wrapper.className = 'aew-collapsible-content';

        // Knoten in Wrapper verschieben
        contentNodes.forEach(function (node) { wrapper.appendChild(node); });
        // nach H2 einfügen
        h2.parentNode.insertBefore(wrapper, h2.nextSibling);

        // Toggle-Button
        var btn = document.createElement('button');
        btn.type = 'button';
        btn.className = 'aew-collapsible-toggle';
        btn.setAttribute('aria-controls', '');
        btn.setAttribute('aria-expanded', 'true');
        btn.title = 'Ein-/ausklappen';
        btn.textContent = '▾';
        h2.insertBefore(btn, h2.firstChild);

        function setState(collapsed) {
            if (collapsed) {
                wrapper.style.display = 'none';
                btn.textContent = '▸';
                btn.setAttribute('aria-expanded', 'false');
                mw.storage.set(storageKey, '1');
            } else {
                wrapper.style.display = '';
                btn.textContent = '▾';
                btn.setAttribute('aria-expanded', 'true');
                mw.storage.set(storageKey, '0');
            }
        }

        // Initialzustand
        setState(!!startCollapsed);

        // Events
        btn.addEventListener('click', function (e) {
            e.preventDefault();
            var isOpen = wrapper.style.display !== 'none';
            setState(isOpen);
        });

        if (CONFIG.useClickOnHeading) {
            h2.addEventListener('click', function (e) {
                var t = e.target;
                if (t === btn || t.closest('a, button')) return;
                var isOpen = wrapper.style.display !== 'none';
                setState(isOpen);
            });
        }
    }

    // Kategorien: wrappe alles NACH der jeweiligen H2 bis zum Ende der Sektion
    function enhanceCategorySection(sectionId, defaultCollapsed) {
        var sec = document.getElementById(sectionId);
        if (!sec) return;
        var h2 = sec.querySelector('h2');
        if (!h2) return;

        // Sammle alle Geschwister nach h2
        var nodes = [];
        var node = h2.nextSibling;
        while (node) {
            var next = node.nextSibling;
            nodes.push(node);
            node = next;
        }

        var key = 'aewCatCollapsible:' + mw.config.get('wgPageName') + ':' + sectionId;
        var stored = mw.storage.get(key);
        var startCollapsed = (stored === '1') || (stored === null && !!defaultCollapsed);

        makeSectionCollapsible(h2, nodes, key, startCollapsed);
    }

    // Spezial:Spezialseiten (Special:SpecialPages): jede h2.mw-specialpagesgroup einklappbar
    function enhanceSpecialPages(defaultCollapsed, preferOpenList) {
        var headings = document.querySelectorAll('h2.mw-specialpagesgroup');
        if (!headings.length) return;

        headings.forEach(function (h2, idx) {
            // Sammle alle folgenden Geschwister bis zur nächsten H2 (gleiche Ebene) oder Ende
            var nodes = [];
            var n = h2.nextSibling;
            while (n && !(n.nodeType === 1 && n.tagName === 'H2')) {
                var next = n.nextSibling;
                nodes.push(n);
                n = next;
            }

            // Stabiler Key aus Seitennamen + Textinhalt (trim)
            var title = (h2.textContent || '').trim();
            var key = 'aewSpcCollapsible:' + mw.config.get('wgPageName') + ':' + title;

            // Startzustand: Storage hat Vorrang; sonst Default; außer, wenn auf Prefer-Open-Liste
            var stored = mw.storage.get(key);
            var preferOpen = Array.isArray(preferOpenList) &&
                             preferOpenList.some(function (t) { return t === title; });
            var startCollapsed = (stored === '1') ||
                                 (stored === null && !!defaultCollapsed && !preferOpen);

            makeSectionCollapsible(h2, nodes, key, startCollapsed);
        });
    }

    function run() {
        var ns = mw.config.get('wgNamespaceNumber');
        var canonical = mw.config.get('wgCanonicalSpecialPageName');

        if (ns === 14) {
            // Kategorie
            enhanceCategorySection('mw-subcategories', CONFIG.defaultCollapsedCategories);
            enhanceCategorySection('mw-pages',         CONFIG.defaultCollapsedCategories);
        } else if (ns === -1 && canonical === 'Specialpages') {
            // Spezial:Spezialseiten (Special:SpecialPages)
            enhanceSpecialPages(CONFIG.defaultCollapsedSpecialpages, CONFIG.specialpagesPreferOpen);
        }
    }

    // für Erst- und Soft-Navigationen
    mw.hook('wikipage.content').add(run);
    // Fallback (falls Hook nicht feuert)
    if (document.readyState !== 'loading') run();
    else document.addEventListener('DOMContentLoaded', run);
});
Optional: Welche Gruppen auf Spezial:Spezialseiten standardmäßig offen?

Trage die exakten H2-Texte in CONFIG.specialpagesPreferOpen ein, z. B.:

specialpagesPreferOpen: ['Wartung und Berichte', 'Seitenlisten']

Die Namen müssen genau so lauten wie auf deiner deutschen Installation.

2) CSS bleibt identisch (MediaWiki:Gadget-CategoryH2Collapsible.css)

(Deine bisherige Datei passt. Der Vollständigkeit halber:)

.aew-collapsible-toggle {
    cursor: pointer;
    background: none;
    border: 0;
    padding: 0 .35em 0 0;
    margin-right: .2em;
    font-size: 0.95em;
    line-height: 1;
    vertical-align: middle;
}
.aew-collapsible-content { margin-top: .25rem; }

3) Gadget-Definition anpassen

Damit es auf Kategorien + Spezialseiten lädt, erweitere namespaces:

  • Empfohlen (nur Vector-2022, wie bei dir):
    * CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage|actions=view|namespaces=14,-1|skins=vector-2022]|CategoryH2Collapsible.js|CategoryH2Collapsible.css
    
    Oder ohne Skin-Filter (robuster, falls Skin später wechselt):
    * CategoryH2Collapsible[ResourceLoader|dependencies=mediawiki.storage|actions=view|namespaces=14,-1]|CategoryH2Collapsible.js|CategoryH2Collapsible.css
    

    Keine targets= nötig (du nutzt kein Smartphone-Frontend).

Hinweise / Stolpersteine

  • Persistenz: Schlüssel enthalten Seitennamen + Abschnittstitel → getrennte Erinnerung pro Gruppe.
  • I18N: Die „Prefer-Open“-Liste ist sprachabhängig (dein Wiki ist deutsch → verwende die deutschen Gruppennamen).
  • Kompatibilität: Greift nur auf NS 14 und auf Spezial:Spezialseiten. Andere Spezialseiten bleiben unberührt.
  • Konflikte: Falls ein anderes Script Gruppen bereits umstrukturiert, verhindert die Klasse aew-collapsible-bounddoppeltes Wrapping.

Wenn du möchtest, baue ich dir noch zwei Komfortfunktionen ein:

  1. Einen „Alle ein-/ausklappen“-Button am Seitenanfang auf Spezial:Spezialseiten.
  2. Eine „Whitelist nur anzeigen“ (alles ausgeblendet außer den 2–3 Gruppen, die du immer brauchst).

Testung des Gadget-H2Kipper

Nikolaos:

Die Funktionen sind entsprechend erweitert – ich teste nun eine Weile, bevor ich weitere Änderungen vornehme.

Danke für deine Unterstützung.

Sophos:


Der Nutzer danke dir und möchte erstmal testen – das ist super! Ich würde nur kurz sagen: Um Speicherprobleme zu vermeiden, könnte er die localStorage-Schlüssel zurücksetzen. Wenn's Probleme gibt, könnte er den Sicherheitsmodus aktivieren. Und eventuell Gruppen per Klassennamen zur Whitelist hinzufügen. Wenn er später "Alle ein-/ausklappen" möchte, kann er mich einfach fragen.

Danke fürs Update, Nikolaos! Ich freue mich, dass du testest. Hier ein paar nützliche Tipps:

  1. Zurücksetzen von localStorage: Nutze localStorage.removeItem('aewCatCollapsible'); localStorage.removeItem('aewSpcCollapsible');
  2. Um Gadget zu deaktivieren: ?safemode=1
  3. Für Performance-Profiling: ?debug=true und nutze den ResourceLoader.

Falls ein Bug auftaucht, notiere bitte alle relevanten Details. Viel Erfolg beim Testen!

Fertig

Sehr gern, Nikolaos — klingt gut.

Fürs Testen noch drei kleine Helfer:

  1. Zustände schnell zurücksetzen (nur lokal, ohne Wiki-Änderung) Konsole öffnen und ausführen:
Object.keys(localStorage).forEach(k => {
  if (/^aew(Cat|Spc)Collapsible:/.test(k)) localStorage.removeItem(k);
});
  1. Fehlernotfall / Vergleich
  • Ohne Gadgets laden: URL mit ?safemode=1
  • Frische Ladung (ohne RL-Cache): ?debug=true
  • Gadget-Status prüfen:
mw.loader.getState('ext.gadget.CategoryH2Collapsible')  // "ready" erwartet
  1. Hinweis zur Persistenz Die Merker-Schlüssel verwenden den H2-Text (Spezialseiten) bzw. die Seitennamen + Abschnitts-IDs(Kategorien). Ändert sich der H2-Text durch Übersetzungen/Skin-Änderungen, sind nur die gespeicherten Zustände neu — Funktion bleibt intakt.

Wenn du später „Alle ein-/ausklappen“ oder eine Whitelist („nur diese Gruppen offen/sichtbar“) möchtest, sag Bescheid; ich ergänze das gezielt.