MediaWiki:Minerva.js: Unterschied zwischen den Versionen

Keine Bearbeitungszusammenfassung
Markierung: Zurückgesetzt
Keine Bearbeitungszusammenfassung
 
(Eine dazwischenliegende Version desselben Benutzers wird 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)
const LINKS = [
  // Header/Sektionen haben title = null
  ['Hauptkategorien', null],
   // WICHTIG: "📊 Diagramm / Statistik" steht ganz oben
   ['Alle A Dream of Scotland Abfüllungen', 'Kategorie:Alle A Dream of Scotland Abfüllungen'],
   const LINKS = [
  ['Alle A Dream of Ireland Abfüllungen',  'Kategorie:Alle A Dream of Ireland Abfüllungen'],
    ['📊 Diagramm / Statistik', null],
   ['Alle A Dream of... – Der Rest der Welt', 'Kategorie:Alle A Dream of... – Der Rest der Welt Abfüllungen'],
    ['Abfüllungen pro Jahr', 'Abfüllungen_pro_Jahr'],
  ['Cigar Malt Übersicht', 'Kategorie:Cigar Malt Übersicht'],
    // optional:
  ['Alle Rumbastic Abfüllungen', 'Kategorie:Alle Rumbastic Abfüllungen'],
    // ['Top 5 – Community', 'Top_5'],
  ['The Tasteful 8', 'Kategorie:The Tasteful 8'],
  ['Còmhlan Abfüllungen', 'Kategorie:Còmhlan Abfüllungen'],
  ['Friendly Mr. Z Whiskytainment Abfüllungen', 'Kategorie:Friendly Mr. Z Whiskytainment Abfüllungen'],
  ['Die Whisky Elfen Abfüllungen', 'Kategorie:Die Whisky Elfen Abfüllungen'],
  ['The Fine Art of Whisky Abfüllungen', 'Kategorie:The Fine Art of Whisky Abfüllungen'],
  ['The Forbidden Kingdom', 'Kategorie:The Forbidden Kingdom'],
  ['Sonderabfüllungen', 'Kategorie:Sonderabfüllungen'],


  // --- NEUER REITER / SEKTION ---
    ['Hauptkategorien', null],
  ['📊 Diagramm / Statistik', null],
    ['Alle A Dream of Scotland Abfüllungen', 'Kategorie:Alle A Dream of Scotland Abfüllungen'],
  ['Abfüllungen pro Jahr', 'Abfüllungen_pro_Jahr'],
    ['Alle A Dream of Ireland Abfüllungen', 'Kategorie:Alle A Dream of Ireland Abfüllungen'],
  // optional später:
    ['Alle A Dream of... – Der Rest der Welt', 'Kategorie:Alle A Dream of... Der Rest der Welt Abfüllungen'],
  // ['Top 5 Community', 'Top_5'],
    ['Cigar Malt Übersicht', 'Kategorie:Cigar Malt Übersicht'],
];
    ['Alle Rumbastic Abfüllungen', 'Kategorie:Alle Rumbastic Abfüllungen'],
 
    ['The Tasteful 8', 'Kategorie:The Tasteful 8'],
  const BLOCK_ID = 'ados-custom-links';
    ['Còmhlan Abfüllungen', 'Kategorie:Còmhlan Abfüllungen'],
    ['Friendly Mr. Z Whiskytainment Abfüllungen', 'Kategorie:Friendly Mr. Z Whiskytainment Abfüllungen'],
    ['Die Whisky Elfen Abfüllungen', 'Kategorie:Die Whisky Elfen Abfüllungen'],
    ['The Fine Art of Whisky Abfüllungen', 'Kategorie:The Fine Art of Whisky Abfüllungen'],
    ['The Forbidden Kingdom', 'Kategorie:The Forbidden Kingdom'],
    ['Sonderabfüllungen', 'Kategorie:Sonderabfüllungen']
  ];


   function findMenuList() {
   function findMenuList() {
Zeile 40: Zeile 42:
   }
   }


function build() {
  function buildSectionsFromLinks(links) {
  const host = findMenuList();
    const sections = [];
  if (!host) return false;
    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;
  }
 
  function build() {
    const host = findMenuList();
    if (!host) return false;


  // Block schon eingebaut?
    // schon eingebaut?
  if (document.getElementById(BLOCK_ID)) return true;
    if (document.getElementById(BLOCK_ID)) return true;


  // Container für alle Sektionen
    const sections = buildSectionsFromLinks(LINKS);
  const container = document.createElement('div');
    if (!sections.length) return false;
  container.id = BLOCK_ID;


  // LINKS in Sektionen aufteilen: jeder Header (title=null) startet neue Sektion
    // Container für alle Sektionen
  const sections = [];
    const container = document.createElement('div');
  let current = null;
    container.id = BLOCK_ID;


  for (const [label, title] of LINKS) {
    sections.forEach((sec, idx) => {
    if (title === null) {
      const secId = `${BLOCK_ID}-sec-${idx}`;
       current = { header: label, items: [] };
 
       sections.push(current);
      // äußerer Block je Sektion
    } else if (current) {
      const outer = document.createElement('ul');
       current.items.push({ label, title });
       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>`;


  // Sektionen bauen
      headerLi.appendChild(headerBtn);
  sections.forEach((sec, idx) => {
      outer.appendChild(headerLi);
    const secId = `${BLOCK_ID}-sec-${idx}`;


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


    // Header
      sec.items.forEach(({ label, title }) => {
    const headerLi = document.createElement('li');
        const li = document.createElement('li');
    headerLi.className = 'toggle-list-item';
        li.className = 'toggle-list-item';


    const headerBtn = document.createElement('button');
        const a = document.createElement('a');
    headerBtn.type = 'button';
        a.className = 'toggle-list-item__anchor';
    headerBtn.className = 'toggle-list-item__anchor';
        a.textContent = label;
    headerBtn.setAttribute('aria-expanded', 'true');
        a.href = mw.util.getUrl(title);
    headerBtn.innerHTML =
      '<span class="minerva-icon minerva-icon--listBullet"></span>' +
      `<span class="toggle-list-item__label">${sec.header}</span>`;


    headerLi.appendChild(headerBtn);
        li.appendChild(a);
    outer.appendChild(headerLi);
        inner.appendChild(li);
      });


    // Inner list
      outer.appendChild(inner);
    const inner = document.createElement('ul');
    inner.className = 'toggle-list__list';
    inner.style.marginLeft = '10px';


    sec.items.forEach(({ label, title }) => {
      // Toggle-Logik pro Sektion
      const li = document.createElement('li');
      headerBtn.addEventListener('click', function () {
      li.className = 'toggle-list-item';
        const expanded = this.getAttribute('aria-expanded') === 'true';
        this.setAttribute('aria-expanded', String(!expanded));
        inner.style.display = expanded ? 'none' : '';
        try { localStorage.setItem(secId + ':collapsed', expanded ? '1' : '0'); } catch (e) {}
      });


       const a = document.createElement('a');
       // Zustand wiederherstellen
      a.className = 'toggle-list-item__anchor';
      try {
      a.textContent = label;
        if (localStorage.getItem(secId + ':collapsed') === '1') {
       a.href = mw.util.getUrl(title);
          headerBtn.setAttribute('aria-expanded', 'false');
          inner.style.display = 'none';
        }
       } catch (e) {}


       li.appendChild(a);
       container.appendChild(outer);
      inner.appendChild(li);
     });
     });


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


     // Toggle-Logik pro Sektion
     return true;
    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(secId + ':collapsed', expanded ? '1' : '0'); } catch (e) {}
    });


    // Zustand wiederherstellen
  // beim Laden probieren …
    try {
  document.addEventListener('DOMContentLoaded', () => setTimeout(build, 0));
      if (localStorage.getItem(secId + ':collapsed') === '1') {
        headerBtn.setAttribute('aria-expanded', 'false');
        inner.style.display = 'none';
      }
    } catch (e) {}


     container.appendChild(outer);
  // … und wenn das Burger-Menü dynamisch aufgebaut wird, nochmal
  document.addEventListener('click', (e) => {
    const btn = e.target.closest('button, a');
    if (!btn) return;
    const s = (btn.className + ' ' + btn.id).toLowerCase();
     if (s.includes('menu') || s.includes('hamburger') || s.includes('main-menu')) {
      setTimeout(build, 250);
    }
   });
   });


   // Einfügen (wie bei dir: direkt nach erster UL)
   // Fallback: Observer für lazy DOM
   const firstUl = host.querySelector('ul') || host;
   const obs = new MutationObserver(() => { if (build()) obs.disconnect(); });
  (firstUl.parentNode || host).insertBefore(container, firstUl.nextSibling);
   obs.observe(document.documentElement, { childList: true, subtree: true });
 
})();
   return true;
}