MediaWiki:Minerva.js: Unterschied zwischen den Versionen

Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
 
(7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 3: Zeile 3:
/* Weitere Menüs für MobileFrontend & MinervaNeue (Mobile Ansicht) */
/* Weitere Menüs für MobileFrontend & MinervaNeue (Mobile Ansicht) */
(function () {
(function () {
  // Nur Mobile-Skin (Minerva)
   if (mw.config.get('skin') !== 'minerva') return;
   if (mw.config.get('skin') !== 'minerva') return;
  const BLOCK_ID = 'ados-custom-links';


   // --- KONFIG: Label + Seitentitel (werden mit mw.util.getUrl() sicher verlinkt)
   // --- KONFIG: Label + Seitentitel (werden mit mw.util.getUrl() sicher verlinkt)
  // Header/Sektionen haben title = null
  // WICHTIG: "📊 Diagramm / Statistik" steht ganz oben
   const LINKS = [
   const LINKS = [
     ['Hauptkategorien', null], // Header/Toggle, kein Link
     ['📊 Diagramm / Statistik', null],
    ['Abfüllungen pro Jahr', 'Abfüllungen_pro_Jahr'],
    // optional:
    // ['Top 5 – Community', 'Top_5'],
 
    ['Hauptkategorien', null],
     ['Alle A Dream of Scotland Abfüllungen', 'Kategorie:Alle A Dream of Scotland Abfüllungen'],
     ['Alle A Dream of Scotland Abfüllungen', 'Kategorie:Alle A Dream of Scotland Abfüllungen'],
     ['Alle A Dream of Ireland Abfüllungen', 'Kategorie:Alle A Dream of Ireland Abfüllungen'],
     ['Alle A Dream of Ireland Abfüllungen', 'Kategorie:Alle A Dream of Ireland Abfüllungen'],
     ['Alle A Dream of... – Der Rest der Welt', 'Kategorie:Alle A Dream of... – Der Rest der Welt Abfüllungen'],
     ['Alle A Dream of... – Der Rest der Welt', 'Kategorie:Alle A Dream of... – Der Rest der Welt Abfüllungen'],
     ['Cigar Malt Übersicht', 'Kategorie:Cigar Malt Übersicht'],
     ['Cigar Malt Übersicht', 'Kategorie:Cigar Malt Übersicht'],
Zeile 19: Zeile 29:
     ['The Fine Art of Whisky Abfüllungen', 'Kategorie:The Fine Art of Whisky Abfüllungen'],
     ['The Fine Art of Whisky Abfüllungen', 'Kategorie:The Fine Art of Whisky Abfüllungen'],
     ['The Forbidden Kingdom', 'Kategorie:The Forbidden Kingdom'],
     ['The Forbidden Kingdom', 'Kategorie:The Forbidden Kingdom'],
     ['Sonderabfüllungen', 'Kategorie:Sonderabfüllungen'] // <— NEU
     ['Sonderabfüllungen', 'Kategorie:Sonderabfüllungen']
   ];
   ];
  const BLOCK_ID = 'ados-custom-links';


   function findMenuList() {
   function findMenuList() {
Zeile 32: Zeile 40:
       document.querySelector('.menu')
       document.querySelector('.menu')
     );
     );
  }
  function buildSectionsFromLinks(links) {
    const sections = [];
    let current = null;
    for (const [label, title] of links) {
      if (title === null) {
        current = { header: label, items: [] };
        sections.push(current);
      } else if (current) {
        current.items.push({ label, title });
      }
    }
    return sections;
   }
   }


Zeile 37: Zeile 60:
     const host = findMenuList();
     const host = findMenuList();
     if (!host) return false;
     if (!host) return false;
    if (document.getElementById(BLOCK_ID)) return true; // schon eingebaut


     // äußerer Block
     // schon eingebaut?
     const outer = document.createElement('ul');
    if (document.getElementById(BLOCK_ID)) return true;
     outer.id = BLOCK_ID;
 
     outer.className = 'toggle-list__list';
    const sections = buildSectionsFromLinks(LINKS);
    if (!sections.length) return false;
 
    // Container für alle Sektionen
     const container = document.createElement('div');
     container.id = BLOCK_ID;
 
     sections.forEach((sec, idx) => {
      const secId = `${BLOCK_ID}-sec-${idx}`;
 
      // äußerer Block je Sektion
      const outer = document.createElement('ul');
      outer.className = 'toggle-list__list';
 
      // Header mit Icon + Toggle
      const headerLi = document.createElement('li');
      headerLi.className = 'toggle-list-item';
 
      const headerBtn = document.createElement('button');
      headerBtn.type = 'button';
      headerBtn.className = 'toggle-list-item__anchor';
      headerBtn.setAttribute('aria-expanded', 'true');
      headerBtn.innerHTML =
        '<span class="minerva-icon minerva-icon--listBullet"></span>' +
        `<span class="toggle-list-item__label">${sec.header}</span>`;
 
      headerLi.appendChild(headerBtn);
      outer.appendChild(headerLi);


    // Header mit Icon + Toggle
      // Unterpunkte-Liste (ohne Icons)
    const [headerLabel] = LINKS[0];
      const inner = document.createElement('ul');
    const headerLi = document.createElement('li');
      inner.className = 'toggle-list__list';
    headerLi.className = 'toggle-list-item';
      inner.style.marginLeft = '10px';


    const headerBtn = document.createElement('button');
      sec.items.forEach(({ label, title }) => {
    headerBtn.type = 'button';
        const li = document.createElement('li');
    headerBtn.className = 'toggle-list-item__anchor';
        li.className = 'toggle-list-item';
    headerBtn.setAttribute('aria-expanded', 'true');
    headerBtn.innerHTML =
      '<span class="minerva-icon minerva-icon--listBullet"></span>' +
      `<span class="toggle-list-item__label">${headerLabel}</span>`;


    headerLi.appendChild(headerBtn);
        const a = document.createElement('a');
    outer.appendChild(headerLi);
        a.className = 'toggle-list-item__anchor';
        a.textContent = label;
        a.href = mw.util.getUrl(title);


    // Unterpunkte-Liste (ohne Icons)
        li.appendChild(a);
    const inner = document.createElement('ul');
        inner.appendChild(li);
    inner.className = 'toggle-list__list';
      });
    inner.style.marginLeft = '10px';


    for (let i = 1; i < LINKS.length; i++) {
       outer.appendChild(inner);
      const [label, title] = LINKS[i];
       const li = document.createElement('li');
      li.className = 'toggle-list-item';


       const a = document.createElement('a');
       // Toggle-Logik pro Sektion
      a.className = 'toggle-list-item__anchor';
      headerBtn.addEventListener('click', function () {
      a.textContent = label;
        const expanded = this.getAttribute('aria-expanded') === 'true';
      a.href = title ? mw.util.getUrl(title) : '#';
        this.setAttribute('aria-expanded', String(!expanded));
        inner.style.display = expanded ? 'none' : '';
        try { localStorage.setItem(secId + ':collapsed', expanded ? '1' : '0'); } catch (e) {}
      });


       // KEIN Icon bei Unterpunkten
       // Zustand wiederherstellen
       li.appendChild(a);
       try {
      inner.appendChild(li);
        if (localStorage.getItem(secId + ':collapsed') === '1') {
    }
          headerBtn.setAttribute('aria-expanded', 'false');
    outer.appendChild(inner);
          inner.style.display = 'none';
        }
      } catch (e) {}


    // Toggle-Logik
       container.appendChild(outer);
    headerBtn.addEventListener('click', function () {
      const expanded = this.getAttribute('aria-expanded') === 'true';
      this.setAttribute('aria-expanded', String(!expanded));
       inner.style.display = expanded ? 'none' : '';
      try { localStorage.setItem(BLOCK_ID + ':collapsed', expanded ? '1' : '0'); } catch (e) {}
     });
     });
    // Zustand wiederherstellen
    try {
      if (localStorage.getItem(BLOCK_ID + ':collapsed') === '1') {
        headerBtn.setAttribute('aria-expanded', 'false');
        inner.style.display = 'none';
      }
    } catch (e) {}


     // nach der ersten vorhandenen UL einfügen (direkt unter Start/Zufällige Seite)
     // nach der ersten vorhandenen UL einfügen (direkt unter Start/Zufällige Seite)
     const firstUl = host.querySelector('ul') || host;
     const firstUl = host.querySelector('ul') || host;
     (firstUl.parentNode || host).insertBefore(outer, firstUl.nextSibling);
     (firstUl.parentNode || host).insertBefore(container, firstUl.nextSibling);


     return true;
     return true;
Zeile 106: Zeile 141:
   // beim Laden probieren …
   // beim Laden probieren …
   document.addEventListener('DOMContentLoaded', () => setTimeout(build, 0));
   document.addEventListener('DOMContentLoaded', () => setTimeout(build, 0));
   // … und wenn das Burger-Menü dynamisch aufgebaut wird, nochmal
   // … und wenn das Burger-Menü dynamisch aufgebaut wird, nochmal
   document.addEventListener('click', (e) => {
   document.addEventListener('click', (e) => {
Zeile 115: Zeile 151:
     }
     }
   });
   });
   // Fallback: Observer für lazy DOM
   // Fallback: Observer für lazy DOM
   const obs = new MutationObserver(() => { if (build()) obs.disconnect(); });
   const obs = new MutationObserver(() => { if (build()) obs.disconnect(); });
Zeile 123: Zeile 160:
// ----------Abschnitte Geöffnet-----------
// ----------Abschnitte Geöffnet-----------


// Alle Abschnitte in Minerva automatisch ausklappen
/* Minerva: Alle Abschnitte automatisch ausklappen */
(function () {
(function () {
   if (!window.mw) return;
   if (!window.mw) return;
  // Nur im Minerva-Skin (MobileFrontend)
   if (mw.config.get('skin') !== 'minerva') return;
   if (mw.config.get('skin') !== 'minerva') return;


   function expandAll() {
   function expandAll() {
     // Minerva nutzt Buttons mit .section-toggle zum Auf/Zu-klappen
     // 1) Alle Toggle-Buttons, die noch "zu" sind, anklicken
     document.querySelectorAll('button.section-toggle[aria-expanded="false"]').forEach(function (btn) {
     document.querySelectorAll('button.section-toggle[aria-expanded="false"], [data-event-name="section-toggle"][aria-expanded="false"]').forEach(function (btn) {
       btn.click();
       try { btn.click(); } catch(e) {}
    });
 
    // 2) Sicherheitsgurt: typische Inhalts-Container sichtbar erzwingen
    document.querySelectorAll('.collapsible-block, .mf-section-contents, .section-content').forEach(function (el) {
      el.style.display = 'block';
      el.hidden = false;
      el.classList.add('open-block');
      el.classList.remove('collapsed');
     });
     });
   }
   }


   // Beim Rendern der Seite
   // Beim Rendern und bei dynamischen Änderungen erneut ausführen
   if (mw.hook) {
  function init() {
     mw.hook('wikipage.content').add(function () {
    expandAll();
       expandAll();
    // Nochmal kurz nach Seitenaufbau und nach spätem JS
    setTimeout(expandAll, 50);
    setTimeout(expandAll, 400);
  }
 
   if (mw.loader && mw.loader.using) {
     mw.loader.using(['mobile.init']).always(function () {
      if (mw.hook) mw.hook('wikipage.content').add(init);
       init();
     });
     });
   } else {
   } else {
     document.addEventListener('DOMContentLoaded', expandAll);
     document.addEventListener('DOMContentLoaded', init);
  }
 
  // Falls Inhalte nachträglich geladen/umgebaut werden (Vorschau, Spoiler etc.)
  if (window.MutationObserver) {
    var obs = new MutationObserver(function () { expandAll(); });
    obs.observe(document.body, { childList: true, subtree: true });
   }
   }
})();
})();