MediaWiki:Common.js: Unterschied zwischen den Versionen

Aus Dokumentation
Wechseln zu:Navigation, Suche
(Die Seite wurde geleert.)
Markierung: Geleert
 
(40 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
  
 +
// Blockieren Rechtsklick Videos
 +
$(document).ready(function () {
 +
  $('video').on('contextmenu', function (e) {
 +
    return false;
 +
  });
 +
});
 +
 +
/* ===== Tandler Wiki - Video-Galerie (zentral) =====
 +
  Wird ueber Platzhalter-Divs eingebunden:
 +
  - <div id="webinare-galerie-slot"></div>              -> zeigt ALLE Webinare, mit Filterleiste + Suche
 +
  - <div id="webinare-galerie-slot-geocpm"></div>        -> zeigt NUR Tag "geocpm", ohne Filterleiste
 +
  - <div id="webinare-galerie-slot-hydraulik"></div>    -> usw. fuer jeden TAGS-Schluessel
 +
  Einfach das Suffix hinter "webinare-galerie-slot-" auf den gewuenschten TAGS-Key setzen.
 +
*/
 +
(function () {
 +
    'use strict';
 +
    var WEBINARE = [
 +
    { titel: 'Neue Hydraulikmenü', datum: '23.09.2026', tag: 'hydraulik', link: 'Hydraulikvariante#Neue_Hydraulikmen.C3.BC_-_Webinar_vom_23.09.2026' },
 +
    { titel: '++SYSTEMS Release V18', datum: '16.09.2026', tag: 'release', link: 'Release_News_Version_18#Release_Webinar_V18' },
 +
        { titel: 'Kanabis Release V11', datum: '28.01.2026', tag: 'kanabis', link: 'Kanabis_Webinare#Release_V11_Webinar_vom_28.01.26' },
 +
        { titel: 'Betriebsfuehrung: Digital & Bedarfsorientiert - Luenen', datum: '17.12.2025', tag: 'togo', link: 'ToGo-Erneuerungen#Betriebsf.C3.BChrung:_Digital_.26_Bedarfsorientiert_-_Webinar_vom_17.12.2025' },
 +
        { titel: 'Automatische Kanalsanierungsplanung / Aquadocs', datum: '12.11.2025', tag: 'kasa', link: 'Automatische_Kanalsanierungsplanung' },
 +
        { titel: 'DWA A 118 / DWA M 119 - Ueberstau & Risikomanagement', datum: '08.10.2025', tag: 'hydraulik', link: 'Schutzkategorien_&_Überflutungsgefährdung#Webinar:_.C3.9Cberstau_.26_Risikomanagment_vom_08.10.2025' },
 +
        { titel: 'V17 - Releasenews', datum: '04.06.2025', tag: 'release', link: 'Release_News_Version_17#Release_Webinar_V17' },
 +
        { titel: 'GeoCPM - Worauf ist bei der Modellierung zu achten?', datum: '09.04.2025', tag: 'geocpm', link: 'GeoCPM_Modellierungsprozess#Worauf_ist_bei_der_Modellierung_zu_achten.3F_Webinar_vom_9.4.2025' },
 +
        { titel: 'GeoCPM - Kommunale Sturzfluten / Risikomanagement', datum: '12.03.2025', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_12.03.2025' },
 +
        { titel: 'MEGAMAP - Die intelligente Leitungsauskunft', datum: '05.03.2025', tag: 'allgemein', link: 'Megamap#Webinar_vom_05.03.2025' },
 +
        { titel: 'AQUA++ - Theorie, Modellierung und Fehlersuche', datum: '19.02.2025', tag: 'aqua', link: 'AQUA++_Webinare#Webinar_vom_19.02.2025' },
 +
        { titel: 'ToGo - Digitalisierung im Kanalbetrieb', datum: '19.12.2024', tag: 'togo', link: 'ToGo-Erneuerungen#Digitalisierung_im_Kanalbetrieb_-_Webinar_vom_19.12.2024' },
 +
        { titel: 'Datenuebernahme aus bestehenden GIS-Systemen', datum: '06.11.2024', tag: 'allgemein', link: 'Datenübernahme_Strakat' },
 +
        { titel: 'KI in der Zustandserfassung', datum: '09.10.2024', tag: 'kasa', link: 'KI_Zustandserfassung' },
 +
        { titel: 'INSIDe-Projekt', datum: '02.10.2024', tag: 'allgemein', link: 'Inside_Forschungsprojekt' },
 +
        { titel: 'V16 - Import Radklim & Beispiele', datum: '03.06.2024', tag: 'geocpm', link: 'Import_RADKLIM' },
 +
        { titel: 'V16 - Zeichentool', datum: '27.06.2024', tag: 'release', link: 'Zeichen-Tool#Webinar_vom_27.06.2024' },
 +
        { titel: 'V16 - Geo3D Erneuerungen', datum: '25.06.2024', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_25.06.2024' },
 +
        { titel: 'V16 - GeoCPM Neuerungen: Durchlaesse, Video', datum: '20.06.2024', tag: 'geocpm', link: 'Durchlass_GeoCPM#Durchl.C3.A4sse_-_Webinar_vom_20.06.2024' },
 +
        { titel: 'V16 - Releasenews', datum: '18.06.2024', tag: 'release', link: 'Release_News#Release_Webinar_vom_18.06.2024' },
 +
        { titel: 'GeoCPM - Tipps & Tricks DGM-Ausduennung', datum: '24.04.2024', tag: 'geocpm', link: 'Optimierung_durch_Ausdünnung#Ausd.C3.BCnnungsalgorithmen_-_Webinar_vom_24.04.2024' },
 +
        { titel: 'Kanabis Release V10', datum: '09.04.2024', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V10_Webinar_vom_09.04.2024' },
 +
        { titel: 'WIKI - Umfrage & Erneuerungen', datum: '20.03.2024', tag: 'allgemein', link: 'Wiki#Webinar_vom_20.03.2024' },
 +
        { titel: 'GeoCPM - Kommunales Sturzflut-Risikomanagement Bayern', datum: '16.11.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_16.11.2023' },
 +
        { titel: 'Flow V15: Neuerungen', datum: '09.11.2023', tag: 'flow', link: 'Bilanzierung_des_Zentralbeckens#Webinar_vom_09.11.2023' },
 +
        { titel: 'GeoCPM Best Practice V15: Strukturen', datum: '02.11.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_02.11.2023' },
 +
        { titel: 'GeoCPM Erneuerungen V15: OBOs', datum: '19.10.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_19.10.2023' },
 +
        { titel: 'Release Version 15: Inn', datum: '18.10.2023', tag: 'release', link: 'Release_News_Version_15#Webinar_vom_18.10.2023' },
 +
        { titel: 'Kanabis Release V9', datum: '09.02.2023', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V9_Webinar_vom_09.02.2023' },
 +
        { titel: 'Neuerungen KASAnova', datum: '01.12.2022', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Kanalzustand_und_Sanierung_am_01.12.2022' },
 +
        { titel: 'Release Version 14.10.00: Main', datum: '24.11.2022', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_24.11.2022' },
 +
        { titel: 'Genauigkeit von Gelaendemodellen & Tipps', datum: '03.05.2022', tag: 'geocpm', link: 'Optimierung_durch_Ausdünnung#Genauigkeit_von_Gel.C3.A4ndemodellen_-_Webinar_vom_03.05.2022' },
 +
        { titel: 'A102 & Flow & Practice', datum: '05.04.2022', tag: 'flow', link: 'DWA_A102#Webinar_-_Flow_.26_DWA_A102_Practice' },
 +
        { titel: 'Radolan Daten fuer GeoCPM', datum: '22.03.2022', tag: 'geocpm', link: 'Aquazis#Webinar_vom_22.03.2022' },
 +
        { titel: 'Release Version 14: Main', datum: '08.02.2022', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_08.02.2022' },
 +
        { titel: 'Kanabis Release Version 8', datum: '09.12.2021', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V8_Webinar_vom_09.12.2021' },
 +
        { titel: 'Geo3D Best-Practice', datum: '24.11.2021', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_24.11.2021' },
 +
        { titel: 'Numerische Simulation', datum: '17.11.2021', tag: 'hydraulik', link: 'Numerische_Simulation' },
 +
        { titel: 'A102 & Flow', datum: '09.11.2021', tag: 'flow', link: 'DWA_A102#Webinar_-_DWA_A102_Erneuerungen_Flow' },
 +
        { titel: '++SYSTEMS Projektdateimanagement 2.0', datum: '27.10.2021', tag: 'allgemein', link: 'Vergleichs-_und_Importkonfiguration#Webinar_vom_27.11.2021' },
 +
        { titel: 'Manueller Laengsschnitt', datum: '06.10.2021', tag: 'hydraulik', link: 'Manueller_Längsschnitt#Webinar_vom_06.10.2021' },
 +
        { titel: 'Starkregen - Kommunales Risikomanagement', datum: '20.10.2021', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_20.10.2021' },
 +
        { titel: 'BIM & Betriebsprozesse', datum: '13.10.2021', tag: 'togo', link: 'ToGo-Erneuerungen#BIM_.26_Betriebsprozesse_-_Webinar_vom_13.10.2021' },
 +
        { titel: 'Version 13 Donau3D Erneuerungen', datum: '20.05.2021', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_20.05.2021' },
 +
        { titel: 'Visualisierung mit dem neuen 3DTool', datum: '22.04.2021', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_21.04.2021' },
 +
        { titel: 'Aufbereitung von Eingangsdaten mit QGIS', datum: '13.04.2021', tag: 'allgemein', link: 'QGIS' },
 +
        { titel: 'Vorstellung der neuen Dokumentationsplattform WIKI', datum: '24.03.2021', tag: 'allgemein', link: 'Wiki' },
 +
        { titel: '++SYSTEMS Kanalzustand und Sanierung', datum: '10.03.2021', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Kanalzustand_und_Sanierung_am_10.03.2021' },
 +
        { titel: 'Multi-User-Plattformen', datum: '03.03.2021', tag: 'allgemein', link: 'Datenbanken#Multi-User-Plattformen-Webinar_vom_03.03.2021' },
 +
        { titel: 'Erneuerungen und Best-Practice', datum: '17.02.2021', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_17.02.2021' },
 +
        { titel: 'Entwurfsplanung', datum: '09.12.2020', tag: 'hydraulik', link: 'Entwurfsplanung_Webinar' },
 +
        { titel: 'GeoCPM Best Practice und Erneuerungen', datum: '03.12.2020', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_03.12.2020' },
 +
        { titel: 'Vom Radar zum Simulationsergebnis I', datum: '02.12.2020', tag: 'geocpm', link: 'Einbinden_von_Radardaten' },
 +
        { titel: 'Vom Radar zum Simulationsergebnis II', datum: '24.11.2020', tag: 'geocpm', link: 'Einbinden_von_Radardaten' },
 +
        { titel: 'Flow - Best Practice', datum: '18.11.2020', tag: 'flow', link: 'Schritt-für-Schritt-Anleitung_Flow#Best-Practice_Webinar' },
 +
        { titel: 'Erneuerungen und Best-Practice Nov 2020', datum: '11.11.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_11.11.2020' },
 +
        { titel: 'GeoCPM Best Practice Mai 2020', datum: '17.05.2020', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_17.05.2020' },
 +
        { titel: 'Bedarfsorientierte Kanalreinigung', datum: '12.05.2020', tag: 'togo', link: 'ToGo-Erneuerungen#Bedarfsorientiere_Kanalreinigung_-_Webinar_vom_12.05.2020' },
 +
        { titel: 'Erneuerungen und Best-Practice Apr 2020', datum: '30.04.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_30.04.2020' },
 +
        { titel: 'Release V12 - Neues Look and Feel', datum: '28.04.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_28.04.2020' },
 +
        { titel: 'Anbindung von Datenbanken', datum: '07.03.2020', tag: 'allgemein', link: 'Datenbanken#Webinar_-_Themenschwerpunkt:_Anbindung_von_Datenbanbanken_vom_07.03.2020' },
 +
        { titel: 'Starkregenrisikomanagement LUBW II', datum: '29.05.2019', tag: 'geocpm', link: 'Vorgehen_Starkregenrisikomangenement_LUBW#Webinar_LUBW_II' },
 +
        { titel: 'Bruchkanten', datum: '22.05.2019', tag: 'geocpm', link: 'Bruchkanten#Vorgehen_Bruchkanten_GeoCPM' },
 +
        { titel: '++SYSTEMS Projektdateimanagement', datum: '15.05.2019', tag: 'allgemein', link: 'Vergleichs-_und_Importkonfiguration#Webinar_vom_15.05.2019' },
 +
        { titel: 'Koordinatentransformation', datum: '30.04.2019', tag: 'allgemein', link: 'Koordinatentransformation#Webinar_vom_30.04.2019' },
 +
        { titel: 'Planausgabe', datum: '10.04.2019', tag: 'allgemein', link: 'Plankonfigurationen#Planausgabe_Webinar_vom_10.04.2018' },
 +
        { titel: 'Release V11', datum: '11.03.2019', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_08.05.2019' },
 +
        { titel: 'Bestandsdaten & Dokumentation 2018', datum: '05.12.2018', tag: 'togo', link: 'ToGo-Erneuerungen#Bestandsdaten.28erfassung.29_und_l.C3.BCckenlose_Dokumentation_-_Webinar_vom_05.12.2018' },
 +
        { titel: 'Funktionale Einheiten - Ergebnislisten', datum: '28.11.2018', tag: 'flow', link: 'Funktionale_Einheiten' },
 +
        { titel: 'KASAnova 2.0 - Sanierungsmodul Version 11', datum: '14.11.2018', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_KASAnova_2.0_-_Sanierungsmodul_Version_11_am_14.11.2018' },
 +
        { titel: 'Release Version 11', datum: '08.11.2018', tag: 'release', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_08.11.2018' },
 +
        { titel: 'KASAnova 2.0 - Sanierungsmodul neu aufgelegt', datum: '18.04.2018', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_KASAnova_2.0_-_Das_Sanierungsmodul_neu_aufgelegt_am_18.04.2018' },
 +
        { titel: 'DYNA - Rechnet nicht', datum: '21.03.2018', tag: 'hydraulik', link: 'DYNA-Fehlerbehebung' },
 +
        { titel: 'Datenbanken', datum: '07.03.2018', tag: 'allgemein', link: 'Datenbanken#Datenbanken-Webinar_vom_07.03.2020' },
 +
        { titel: 'Starkregenrisikomanagement LUBW I', datum: '19.07.2017', tag: 'geocpm', link: 'Vorgehen_Starkregenrisikomangenement_LUBW#Webinar_LUBW_I' },
 +
        { titel: 'Erneuerung mit Flow++', datum: '10.05.2017', tag: 'flow', link: 'Erneuerung_mit_Flow++' },
 +
        { titel: 'Messstellen', datum: '22.03.2017', tag: 'hydraulik', link: 'Messstellen' },
 +
        { titel: 'Import/Export - XML Formate', datum: '15.03.2017', tag: 'allgemein', link: 'Schnittstellen#Import.2FExport-Schnittstellen_Webinar_vom_15.03.2017' },
 +
        { titel: 'Import/Export - DXF und ESRI Shape', datum: '07.12.2016', tag: 'allgemein', link: 'Schnittstellen#Import.2FExport-Schnittstellen_Webinar_vom_07.12.2017' },
 +
        { titel: 'Listengenerator', datum: '23.11.2016', tag: 'allgemein', link: 'Listengenerator#Webinar_vom_23.11.2016' },
 +
        { titel: 'Wasseraustausch - Bi-Direktionale Kopplung', datum: '11.10.2016', tag: 'hydraulik', link: 'Bi-Direktionale_Kopplung#Webinar_-_Themenschwerpunkt:_Bi-Direktionale_Kopplung_vom_11.10.2016' },
 +
        { titel: 'Verteilvorschrift Regenspenden KOSTRA', datum: '22.09.2016', tag: 'hydraulik', link: 'Verteilungsvorschriften_für_extreme_Regenspenden#Webinar_-_Themenschwerpunkt:_Regenerstellung_aus_Verteilungsvorschrift_.28Kostra.29_vom_22.09.2016' },
 +
        { titel: 'Zustandserfassung - Daten-Wellenlaenge', datum: '21.07.2016', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Zustandserfassung_-_der_Befahrer_und_Sie_auf_einer_.22Daten-Wellenl.C3.A4nge.22_am_21.07.2016' },
 +
        { titel: 'Themenplan', datum: '30.06.2016', tag: 'allgemein', link: 'Ansichtskonfiguration#Webinar_vom_30.06.2016' },
 +
        { titel: 'Schluss mit der Zettelwirtschaft', datum: '16.06.2016', tag: 'togo', link: 'ToGo-Erneuerungen#Schluss_mit_der_Zettelwirtschaft_-_Webinar_vom_16.06.2016' },
 +
        { titel: 'Bestandsdaten & Dokumentation 2015', datum: '16.12.2015', tag: 'togo', link: 'ToGo-Erneuerungen#.2B.2BSYSTEMS_togo_-_die_Mobile_Version_-_Webinar_vom_16.12.2015' },
 +
        { titel: 'Einzugsgebietsmanagement', datum: '16.06.2015', tag: 'hydraulik', link: 'Einzugsgebietsmanagement' },
 +
        { titel: 'Integrierte Zustandsbewertung und Sanierungsplanung', datum: '09.05.2015', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Integrierte_Zustandsbewertung_und_Sanierungsplanung_am_9.05.2015' },
 +
        { titel: 'Untersuchungsverwaltung - Zustandsbewertung - Sanierung', datum: '21.10.2014', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Untersuchungsverwaltung_.E2.80.93_Zustandsbewertung_-_Sanierung_am_21.10.2014' },
 +
    ];
 +
    var TAGS = {
 +
        /* Farbsystem nach Corporate Design: Tandler Blau (#372281) fuer die
 +
          Simulations-/Berechnungsmodule, Magenta (#b60e7e) fuer die Asset-/
 +
          Wassermodule, jeweils in Abstufungen. "Alle" nutzt das etablierte
 +
          Blaugrau, Release/Allgemein bleiben neutral grau. */
 +
        alle:      { label: 'Alle',      farbe: '#666699' },
 +
        geocpm:    { label: 'GeoCPM',    farbe: '#372281' },
 +
        hydraulik: { label: 'Hydraulik',  farbe: '#26185A' },
 +
        flow:      { label: 'Flow',      farbe: '#554394' },
 +
        togo:      { label: 'ToGo',      farbe: '#7364A7' },
 +
        kasa:      { label: 'KASAnova',  farbe: '#B60E7E' },
 +
        aqua:      { label: 'AQUA++',    farbe: '#7F0A58' },
 +
        kanabis:  { label: 'Kanabis',    farbe: '#C13291' },
 +
        release:  { label: 'Release',    farbe: '#5F5E5A' },
 +
        allgemein: { label: 'Allgemein',  farbe: '#444441' },
 +
    };
 +
    var ICONS = {
 +
        geocpm:    'GeoCPM.png',
 +
        hydraulik: 'DYNA.png',
 +
        flow:      'Flow.png',
 +
        togo:      'TOGO.png',
 +
        kasa:      'KASANOVA.png',
 +
        aqua:      'Aqua.png',
 +
        kanabis:  'kanabis.png',
 +
        release:  'ppsystems_icon.png',
 +
        allgemein: 'ppsystems_icon.png'
 +
    };
 +
    function injizierCSS() {
 +
        if (document.getElementById('vg-styles')) return;
 +
        var css = [
 +
            '#vg-container { font-family: sans-serif; margin: 1rem 0; }',
 +
            '#vg-controls { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; align-items: center; }',
 +
            '#vg-suche { flex: 1; min-width: 180px; padding: 6px 10px; border: 1px solid #ccc; border-radius: 6px; font-size: 13px; }',
 +
            '.vg-filter-btn { padding: 4px 12px; border-radius: 20px; border: 1px solid #ccc; background: #f8f8f8; font-size: 12px; cursor: pointer; transition: all .15s; }',
 +
            '.vg-filter-btn.aktiv { color: #fff; border-color: transparent; }',
 +
            '.vg-anzahl { font-size: 12px; color: #888; margin-bottom: 8px; }',
 +
            '.vg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; }',
 +
            '.vg-karte { display: block; border: 1px solid #e0e0e0; border-radius: 10px; overflow: hidden; background: #fff; transition: box-shadow .15s, transform .15s; text-decoration: none; color: inherit; }',
 +
            '.vg-karte:hover { box-shadow: 0 4px 16px rgba(0,0,0,.12); transform: translateY(-2px); text-decoration: none; color: inherit; }',
 +
            '.vg-icon-wrap { width: 100%; aspect-ratio: 16/9; background: #f0f0f4; display: flex; align-items: center; justify-content: center; overflow: hidden; }',
 +
            '.vg-icon-img { max-width: 55%; max-height: 55%; object-fit: contain; transition: transform 0.2s ease; }',
 +
            '.vg-karte:hover .vg-icon-img { transform: scale(1.08); }',
 +
            '.vg-badge { display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 12px; color: #fff; font-weight: 500; }',
 +
            '.vg-body { padding: 12px 14px; }',
 +
            '.vg-titel { font-size: 13px; font-weight: 600; color: #222; line-height: 1.4; margin: 6px 0 4px; }',
 +
            '.vg-datum { font-size: 11px; color: #888; }',
 +
            '.vg-leer { text-align: center; padding: 2rem; color: #888; font-size: 14px; grid-column: 1 / -1; }',
 +
        ].join('\n');
 +
        var style = document.createElement('style');
 +
        style.id = 'vg-styles';
 +
        style.textContent = css;
 +
        document.head.appendChild(style);
 +
    }
 +
 +
    function baueGalerie(container, vorauswahl) {
 +
        injizierCSS();
 +
        var nurEinTag = !!vorauswahl && TAGS[vorauswahl];
 +
        var aktuellerTag = nurEinTag ? vorauswahl : 'alle';
 +
 +
        var html = '<div id="vg-container">';
 +
        if (!nurEinTag) {
 +
            html += '<div class="vg-controls">';
 +
            html += '<input class="vg-suche" type="text" placeholder="Webinar suchen..." />';
 +
            Object.keys(TAGS).forEach(function (key) {
 +
                var t = TAGS[key];
 +
                var stil = key === 'alle' ? ' style="background:' + t.farbe + ';color:#fff;border-color:' + t.farbe + ';"' : '';
 +
                html += '<button class="vg-filter-btn' + (key === 'alle' ? ' aktiv' : '') + '" data-tag="' + key + '"' + stil + '>' + t.label + '</button>';
 +
            });
 +
            html += '</div>';
 +
        } else {
 +
            html += '<div class="vg-controls"><input class="vg-suche" type="text" placeholder="Webinar suchen..." /></div>';
 +
        }
 +
        html += '<div class="vg-anzahl"></div>';
 +
        html += '<div class="vg-grid"></div>';
 +
        html += '</div>';
 +
        container.innerHTML = html;
 +
 +
        var suchfeld = container.querySelector('.vg-suche');
 +
        var grid = container.querySelector('.vg-grid');
 +
        var anzahl = container.querySelector('.vg-anzahl');
 +
 +
        function renderKarten() {
 +
            var q = suchfeld.value.toLowerCase().trim();
 +
            var gefiltert = WEBINARE.filter(function (w) {
 +
                var tagOk = aktuellerTag === 'alle' || w.tag === aktuellerTag;
 +
                var suchOk = !q || w.titel.toLowerCase().indexOf(q) > -1;
 +
                return tagOk && suchOk;
 +
            });
 +
            anzahl.textContent = gefiltert.length + ' Webinar' + (gefiltert.length !== 1 ? 'e' : '');
 +
            if (!gefiltert.length) {
 +
                grid.innerHTML = '<p class="vg-leer">Keine Webinare gefunden.</p>';
 +
                return;
 +
            }
 +
            grid.innerHTML = gefiltert.map(function (w) {
 +
                var farbe = TAGS[w.tag] ? TAGS[w.tag].farbe : '#666699';
 +
                var tagLabel = TAGS[w.tag] ? TAGS[w.tag].label : w.tag;
 +
                var iconDatei = ICONS[w.tag] || 'ppsystems_icon.png';
 +
                var url = (typeof mw !== 'undefined') ? mw.util.getUrl(w.link) : ('/index.php?title=' + encodeURIComponent(w.link));
 +
                var iconUrl = (typeof mw !== 'undefined') ? mw.util.getUrl('Special:FilePath/' + iconDatei) : ('/index.php/Special:FilePath/' + encodeURIComponent(iconDatei));
 +
                return [
 +
                    '<a class="vg-karte" href="' + url + '">',
 +
                    '  <div class="vg-icon-wrap"><img class="vg-icon-img" src="' + iconUrl + '" alt="' + tagLabel + '" /></div>',
 +
                    '  <div class="vg-body">',
 +
                    '    <span class="vg-badge" style="background:' + farbe + '">' + tagLabel + '</span>',
 +
                    '    <p class="vg-titel">' + w.titel + '</p>',
 +
                    '    <p class="vg-datum">' + w.datum + '</p>',
 +
                    '  </div>',
 +
                    '</a>',
 +
                ].join('\n');
 +
            }).join('\n');
 +
        }
 +
 +
        if (!nurEinTag) {
 +
            container.querySelectorAll('.vg-filter-btn').forEach(function (btn) {
 +
                btn.addEventListener('click', function () {
 +
                    aktuellerTag = btn.getAttribute('data-tag');
 +
                    container.querySelectorAll('.vg-filter-btn').forEach(function (b) {
 +
                        b.classList.remove('aktiv');
 +
                        b.style.background = '';
 +
                        b.style.color = '';
 +
                        b.style.borderColor = '';
 +
                    });
 +
                    btn.classList.add('aktiv');
 +
                    var farbe = TAGS[aktuellerTag] ? TAGS[aktuellerTag].farbe : '#666699';
 +
                    btn.style.background = farbe;
 +
                    btn.style.color = '#fff';
 +
                    btn.style.borderColor = farbe;
 +
                    renderKarten();
 +
                });
 +
            });
 +
        }
 +
        suchfeld.addEventListener('input', renderKarten);
 +
        renderKarten();
 +
    }
 +
 +
    $(document).ready(function () {
 +
        document.querySelectorAll('[id^="webinare-galerie-slot"]').forEach(function (container) {
 +
            var suffix = container.id.replace('webinare-galerie-slot', '').replace(/^-/, '');
 +
            baueGalerie(container, suffix || null);
 +
        });
 +
    });
 +
})();
 +
 +
 +
/* ===== Tandler Wiki - Projektbaum (zentral, selbstgeschrieben) =====
 +
  Ersetzt {{#tree: extensions=["persist"]|...}} (TreeAndMenu-Erweiterung) durch einen
 +
  selbstgeschriebenen, Datei-Explorer-artigen Baum mit Ordner-/Dokument-Icons.
 +
  Einbindung auf einer Seite: <div id="projektbaum-slot"></div>
 +
  Aufklapp-Zustand wird pro Browser (localStorage) gemerkt, wie bei "extensions=[persist]" vorher.
 +
*/
 +
(function () {
 +
    'use strict';
 +
 +
    var CHEVRON_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
 +
 +
    var ICON_ORDNER = 'pb_icon_ordner.png';
 +
    var ICONS = {
 +
        'Allgemein': 'pb_icon_allgemein.png',
 +
        'Ansicht': 'pb_icon_ansicht.png',
 +
        'Kanalsystem': 'pb_icon_kanalsystem.png',
 +
        'Zustand & Sanierung': 'pb_icon_zustand_sanierung.png',
 +
        'Wasserversorgung': 'pb_icon_wasserversorgung.png',
 +
        'Oberfläche': 'pb_icon_oberflaeche.png',
 +
        'Berechnungsparameter': 'pb_icon_berechnungsparameter.png',
 +
        'Hydraulische Berechnungen': 'pb_icon_hydraulische_berechnungen.png',
 +
        'Auswertung': 'pb_icon_auswertung.png',
 +
        'Schnittstellen': 'pb_icon_schnittstellen.png',
 +
        'Gewässerverwaltung': 'pb_icon_gewaesserverwaltung.png'
 +
    };
 +
 +
    var BAUM = {
 +
        label: 'Projektname', link: null, children: [
 +
            { label: 'Global', link: 'Allgemein', children: [
 +
                { label: 'Gemeinde', link: 'Gemeinde' },
 +
                { label: 'Profile', link: 'Profile' },
 +
                { label: 'Materialien', link: 'Materialien' },
 +
                { label: 'Texte und Spannmasse', link: 'Texte und Spannmasse' },
 +
                { label: 'Dokumente', link: 'Dokumente' },
 +
                { label: 'Marker', link: 'Marker' },
 +
                { label: 'GIS-Punkte', link: 'GIS-Punkte' }
 +
            ]},
 +
            { label: 'Ansicht', link: 'Ansicht', children: [
 +
                { label: 'Ansichtskonfiguration', link: 'Ansichtskonfiguration', children: [
 +
                    { label: 'Zoomkonfiguration', link: 'Zoomkonfiguration' }
 +
                ]},
 +
                { label: 'Farbkonfiguration', link: 'Farbkonfiguration' },
 +
                { label: 'Plangitter', link: 'Plangitter' },
 +
                { label: 'Plankonfigurationen', link: 'Plankonfigurationen' },
 +
                { label: 'Rastergrafiken', link: 'Rastergrafiken' },
 +
                { label: 'Vektorgrafiken', link: 'Vektorgrafiken' },
 +
                { label: 'WMS Grafiken', link: 'WMS Grafiken' },
 +
                { label: 'Symbole', link: 'Symbole' },
 +
                { label: 'Linienarten', link: 'Linienarten' }
 +
            ]},
 +
            { label: 'Kanalsystem', link: 'Kanalsystem', children: [
 +
                { label: 'Knoten', link: 'Knoten' },
 +
                { label: 'Abschnitte', link: 'Abschnitte' }
 +
            ]},
 +
            { label: 'Zustand & Sanierung', link: 'Zustand & Sanierung', children: [
 +
                { label: 'Sanierung', link: 'Sanierung', children: [
 +
                    { label: 'Varianten', link: 'Varianten' },
 +
                    { label: 'Verfahren', link: 'Verfahren (Sanierung)' },
 +
                    { label: 'Sanierungstabellen', link: 'Sanierungstabellen' }
 +
                ]},
 +
                { label: 'Zustand', link: 'Zustand', children: [
 +
                    { label: 'Untersuchungen', link: 'Untersuchungen' },
 +
                    { label: 'Bewertungstabellen', link: 'Bewertungstabellen' },
 +
                    { label: 'Bewertungsvarianten', link: 'Bewertungsvarianten' },
 +
                    { label: 'Bewertungsergebnisse', link: 'Bewertungsergebnisse' }
 +
                ]}
 +
            ]},
 +
            { label: 'Wasserversorgung', link: 'Wasserversorgung', children: [
 +
                { label: 'Wasserleitungen', link: 'Wasserleitungen' },
 +
                { label: 'Wasserknoten', link: 'Wasserknoten' }
 +
            ]},
 +
            { label: 'Oberfläche', link: 'Oberfläche', children: [
 +
                { label: 'Punktmengen', link: 'Punktmengen' },
 +
                { label: 'Bruchkanten', link: 'Bruchkanten' },
 +
                { label: 'Geländemodelle', link: 'Geländemodelle' },
 +
                { label: 'Partitionen', link: 'Partitionen' }
 +
            ]},
 +
            { label: 'Berechnungsparameter', link: 'Berechnungsparameter', children: [
 +
                { label: 'Niederschlag', link: 'Niederschlag', children: [
 +
                    { label: 'Regenmessstationen', link: 'Regenmessstationen' },
 +
                    { label: 'Gebietsniederschlag', link: 'Gebietsniederschlag' },
 +
                    { label: 'Verteilungsvorschriften für extreme Regenspenden', link: 'Verteilungsvorschriften für extreme Regenspenden' }
 +
                ]},
 +
                { label: 'Messstellen', link: 'Messstellen' },
 +
                { label: 'Schlüsselwerte', link: 'Schlüsselwerte', children: [
 +
                    { label: 'Unterschiedliche Schlüsselwerte', link: 'Unterschiedliche Schlüsselwerte' }
 +
                ]},
 +
                { label: 'Kennlinien', link: 'Kennlinien' },
 +
                { label: 'Kurven', link: 'Kurven' },
 +
                { label: 'Ganglinien/Verlauf', link: 'Ganglinien/Verlauf', children: [
 +
                    { label: 'Tagesganglinien/Verlauf', link: 'Tagesganglinien/Verlauf' },
 +
                    { label: 'Wochenganglinien/Verlauf', link: 'Wochenganglinien/Verlauf' },
 +
                    { label: 'Jahresganglinien/Verlauf', link: 'Jahresganglinien/Verlauf' }
 +
                ]},
 +
                { label: 'Schmutzstoffe', link: 'Schmutzstoffe' }
 +
            ]},
 +
            { label: 'Hydraulische Berechnungen', link: 'Hydraulische Berechnungen', children: [
 +
                { label: 'Kanalnetzberechnung', link: 'Kanalnetzberechnung', children: [
 +
                    { label: 'Hydraulikvariante', link: 'Hydraulikvariante', children: [
 +
                        { label: 'Kennlinien', link: 'Kennlinien' },
 +
                        { label: 'Blockregenstaffeln', link: 'Blockregenstaffeln' },
 +
                        { label: 'Natur-/Modellregen', link: 'Natur-/Modellregen' },
 +
                        { label: 'Ergebnislisten', link: 'Ergebnislisten' },
 +
                        { label: 'Längsschnitte', link: 'Längsschnitte' }
 +
                    ]},
 +
                    { label: 'Schmutzfrachtvariante', link: 'Schmutzfrachtvariante', children: [
 +
                        { label: 'Funktionale Einheiten', link: 'Funktionale Einheiten' }
 +
                    ]},
 +
                    { label: 'Steuerungsvarianten', link: 'Steuerungsvarianten' }
 +
                ]},
 +
                { label: 'Oberflächenabflussberechnungen', link: 'Oberflächenabflussberechnungsobjekt', children: [
 +
                    { label: 'Oberflächenabflussberechnungsobjekt', link: 'Oberflächenabflussberechnungsobjekt' }
 +
                ]},
 +
                { label: 'Wassernetzberechnung', link: 'Wassernetzberechnung', children: [
 +
                    { label: 'Berechnungsvariante Wasser-Objekt', link: 'Berechnungsvariante Wasser-Objekt' }
 +
                ]}
 +
            ]},
 +
            { label: 'Auswertung', link: 'Auswertung', children: [
 +
                { label: 'Listengenerator', link: 'Listengenerator' },
 +
                { label: 'Attributname', link: 'Attributname' },
 +
                { label: 'Ausdrücke', link: 'Ausdrücke' },
 +
                { label: 'Eigenschaftslisten', link: 'Eigenschaftslisten' },
 +
                { label: 'Längsschnitte', link: 'Längsschnitte', children: [
 +
                    { label: 'Konfiguration', link: 'Konfiguration' },
 +
                    { label: 'Gespeicherte Längsschnitte', link: 'Gespeicherte Längsschnitte' }
 +
                ]}
 +
            ]},
 +
            { label: 'Schnittstellen', link: 'Schnittstellen', children: [
 +
                { label: 'Vergleichs- und Importkonfiguration', link: 'Vergleichs- und Importkonfiguration' },
 +
                { label: 'Import/Export-Formate', link: 'Import/Export-Formate' },
 +
                { label: 'Datenbankformate', link: 'Datenbankformate' }
 +
            ]},
 +
            { label: 'Gewässerverwaltung', link: 'Gewässerverwaltung', children: [
 +
                { label: 'Gewässer', link: 'Gewässer' },
 +
                { label: 'Gewässerunterhalt', link: 'Gewässerunterhalt', children: [
 +
                    { label: 'Verfahren', link: 'Verfahren (Gewässerunterhalt)' }
 +
                ]}
 +
            ]}
 +
        ]
 +
    };
 +
 +
    function injizierCSS() {
 +
        if (document.getElementById('pb-styles')) return;
 +
        var css = [
 +
            '.pb-liste { list-style: none; margin: 0; padding-left: 20px; }',
 +
            '.pb-wurzel { padding-left: 0; }',
 +
            '.pb-zeile { display: flex; align-items: center; gap: 6px; padding: 4px 2px; cursor: default; }',
 +
            '.pb-toggle { flex: 0 0 16px; width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #372281; cursor: pointer; user-select: none; transition: transform 0.15s ease; transform: rotate(0deg); }',
 +
            '.pb-toggle svg { width: 14px; height: 14px; display: block; }',
 +
            '.pb-toggle.pb-offen { transform: rotate(90deg); }',
 +
            '.pb-toggle.pb-leer { visibility: hidden; }',
 +
            '.pb-icon { flex: 0 0 22px; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; font-size: 16px; line-height: 1; cursor: pointer; }',
 +
            '.pb-icon.pb-kreis { flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%; }',
 +
            '.pb-icon.pb-magenta { background: #b60e7e; }',
 +
            '.pb-icon.pb-blau { background: #372281; }',
 +
            '.pb-icon.pb-kreis img { width: 78%; height: 78%; object-fit: contain; filter: brightness(0) invert(1); }',
 +
            '.pb-icon.pb-punkt { background: none; }',
 +
            '.pb-icon.pb-punkt::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #372281; }',
 +
            '.pb-link { color: #372281; text-decoration: none; font-size: 13px; white-space: nowrap; }',
 +
            '.pb-link:hover { text-decoration: underline; }',
 +
            '.pb-zeile:hover { background: #f5f3fa; border-radius: 4px; }',
 +
            '.pb-wurzel-zeile .pb-link { font-weight: bold; }',
 +
        ].join('\n');
 +
        var style = document.createElement('style');
 +
        style.id = 'pb-styles';
 +
        style.textContent = css;
 +
        document.head.appendChild(style);
 +
    }
 +
 +
    function knotenId(pfad) {
 +
        return 'pb-' + pfad.join('-');
 +
    }
 +
 +
    function iconUrl(datei) {
 +
        return (typeof mw !== 'undefined') ? mw.util.getUrl('Special:FilePath/' + datei) : ('/index.php/Special:FilePath/' + encodeURIComponent(datei));
 +
    }
 +
 +
    function setzeOrdnerIcon(icon, label) {
 +
        icon.classList.add('pb-kreis', 'pb-blau');
 +
        icon.innerHTML = '<img src="' + iconUrl(ICONS[label] || ICON_ORDNER) + '" alt="" />';
 +
    }
 +
 +
    function baueListe(knoten, pfad, ul) {
 +
        knoten.children.forEach(function (kind, i) {
 +
            var eigenerPfad = pfad.concat(i);
 +
            var id = knotenId(eigenerPfad);
 +
            var hatKinder = !!(kind.children && kind.children.length);
 +
 +
            var li = document.createElement('li');
 +
            li.className = 'pb-node';
 +
 +
            var zeile = document.createElement('div');
 +
            zeile.className = 'pb-zeile';
 +
 +
            var toggle = document.createElement('span');
 +
            toggle.className = 'pb-toggle';
 +
            zeile.appendChild(toggle);
 +
 +
            var icon = document.createElement('span');
 +
            icon.className = 'pb-icon';
 +
            zeile.appendChild(icon);
 +
 +
            var link = document.createElement('a');
 +
            link.className = 'pb-link';
 +
            link.href = (typeof mw !== 'undefined') ? mw.util.getUrl(kind.link) : ('/index.php?title=' + encodeURIComponent(kind.link));
 +
            link.textContent = kind.label;
 +
            zeile.appendChild(link);
 +
 +
            li.appendChild(zeile);
 +
 +
            if (hatKinder) {
 +
                toggle.innerHTML = CHEVRON_SVG;
 +
 +
                var ulKind = document.createElement('ul');
 +
                ulKind.className = 'pb-liste';
 +
 +
                var offen = false;
 +
                try { offen = localStorage.getItem(id) === '1'; } catch (e) {}
 +
                ulKind.style.display = offen ? 'block' : 'none';
 +
 +
                if (eigenerPfad.length === 1) {
 +
                    setzeOrdnerIcon(icon, kind.label);
 +
                } else {
 +
                    icon.classList.add('pb-punkt');
 +
                }
 +
 +
                function setSymbole(offenNeu) {
 +
                    toggle.classList.toggle('pb-offen', offenNeu);
 +
                }
 +
                setSymbole(offen);
 +
 +
                function umschalten() {
 +
                    var neuOffen = ulKind.style.display === 'none';
 +
                    ulKind.style.display = neuOffen ? 'block' : 'none';
 +
                    setSymbole(neuOffen);
 +
                    try { localStorage.setItem(id, neuOffen ? '1' : '0'); } catch (e) {}
 +
                }
 +
                toggle.addEventListener('click', umschalten);
 +
                icon.style.cursor = 'pointer';
 +
                icon.addEventListener('click', umschalten);
 +
 +
                baueListe(kind, eigenerPfad, ulKind);
 +
                li.appendChild(ulKind);
 +
            } else {
 +
                toggle.classList.add('pb-leer');
 +
                icon.classList.add('pb-punkt');
 +
                icon.style.cursor = 'default';
 +
            }
 +
 +
            ul.appendChild(li);
 +
        });
 +
    }
 +
 +
    function baueBaum(container) {
 +
        injizierCSS();
 +
        container.innerHTML = '';
 +
 +
        var aeusserUl = document.createElement('ul');
 +
        aeusserUl.className = 'pb-liste pb-wurzel';
 +
 +
        var li = document.createElement('li');
 +
        li.className = 'pb-node';
 +
 +
        var zeile = document.createElement('div');
 +
        zeile.className = 'pb-zeile pb-wurzel-zeile';
 +
 +
        var toggle = document.createElement('span');
 +
        toggle.className = 'pb-toggle';
 +
        toggle.innerHTML = CHEVRON_SVG;
 +
        zeile.appendChild(toggle);
 +
 +
        var icon = document.createElement('span');
 +
        icon.className = 'pb-icon pb-kreis pb-magenta';
 +
        icon.innerHTML = '<img src="' + iconUrl(ICON_ORDNER) + '" alt="" />';
 +
        zeile.appendChild(icon);
 +
 +
        var label = document.createElement('span');
 +
        label.className = 'pb-link';
 +
        label.style.cursor = 'pointer';
 +
        label.textContent = BAUM.label;
 +
        zeile.appendChild(label);
 +
 +
        li.appendChild(zeile);
 +
 +
        var innerUl = document.createElement('ul');
 +
        innerUl.className = 'pb-liste';
 +
 +
        var offen = true;
 +
        try { offen = localStorage.getItem('pb-wurzel') !== '0'; } catch (e) {}
 +
        innerUl.style.display = offen ? 'block' : 'none';
 +
        toggle.classList.toggle('pb-offen', offen);
 +
 +
        function umschaltenWurzel() {
 +
            var neuOffen = innerUl.style.display === 'none';
 +
            innerUl.style.display = neuOffen ? 'block' : 'none';
 +
            toggle.classList.toggle('pb-offen', neuOffen);
 +
            try { localStorage.setItem('pb-wurzel', neuOffen ? '1' : '0'); } catch (e) {}
 +
        }
 +
        toggle.addEventListener('click', umschaltenWurzel);
 +
        label.addEventListener('click', umschaltenWurzel);
 +
        icon.style.cursor = 'pointer';
 +
        icon.addEventListener('click', umschaltenWurzel);
 +
 +
        baueListe(BAUM, [], innerUl);
 +
        li.appendChild(innerUl);
 +
        aeusserUl.appendChild(li);
 +
        container.appendChild(aeusserUl);
 +
    }
 +
 +
    $(document).ready(function () {
 +
        var container = document.getElementById('projektbaum-slot');
 +
        if (container) baueBaum(container);
 +
    });
 +
})();

Aktuelle Version vom 24. September 2026, 10:35 Uhr

// Blockieren Rechtsklick Videos
$(document).ready(function () {
  $('video').on('contextmenu', function (e) {
    return false;
  });
});

/* ===== Tandler Wiki - Video-Galerie (zentral) =====
   Wird ueber Platzhalter-Divs eingebunden:
   - <div id="webinare-galerie-slot"></div>              -> zeigt ALLE Webinare, mit Filterleiste + Suche
   - <div id="webinare-galerie-slot-geocpm"></div>        -> zeigt NUR Tag "geocpm", ohne Filterleiste
   - <div id="webinare-galerie-slot-hydraulik"></div>     -> usw. fuer jeden TAGS-Schluessel
   Einfach das Suffix hinter "webinare-galerie-slot-" auf den gewuenschten TAGS-Key setzen.
*/
(function () {
    'use strict';
    var WEBINARE = [
    	{ titel: 'Neue Hydraulikmenü', datum: '23.09.2026', tag: 'hydraulik', link: 'Hydraulikvariante#Neue_Hydraulikmen.C3.BC_-_Webinar_vom_23.09.2026' },
    	{ titel: '++SYSTEMS Release V18', datum: '16.09.2026', tag: 'release', link: 'Release_News_Version_18#Release_Webinar_V18' },
        { titel: 'Kanabis Release V11', datum: '28.01.2026', tag: 'kanabis', link: 'Kanabis_Webinare#Release_V11_Webinar_vom_28.01.26' },
        { titel: 'Betriebsfuehrung: Digital & Bedarfsorientiert - Luenen', datum: '17.12.2025', tag: 'togo', link: 'ToGo-Erneuerungen#Betriebsf.C3.BChrung:_Digital_.26_Bedarfsorientiert_-_Webinar_vom_17.12.2025' },
        { titel: 'Automatische Kanalsanierungsplanung / Aquadocs', datum: '12.11.2025', tag: 'kasa', link: 'Automatische_Kanalsanierungsplanung' },
        { titel: 'DWA A 118 / DWA M 119 - Ueberstau & Risikomanagement', datum: '08.10.2025', tag: 'hydraulik', link: 'Schutzkategorien_&_Überflutungsgefährdung#Webinar:_.C3.9Cberstau_.26_Risikomanagment_vom_08.10.2025' },
        { titel: 'V17 - Releasenews', datum: '04.06.2025', tag: 'release', link: 'Release_News_Version_17#Release_Webinar_V17' },
        { titel: 'GeoCPM - Worauf ist bei der Modellierung zu achten?', datum: '09.04.2025', tag: 'geocpm', link: 'GeoCPM_Modellierungsprozess#Worauf_ist_bei_der_Modellierung_zu_achten.3F_Webinar_vom_9.4.2025' },
        { titel: 'GeoCPM - Kommunale Sturzfluten / Risikomanagement', datum: '12.03.2025', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_12.03.2025' },
        { titel: 'MEGAMAP - Die intelligente Leitungsauskunft', datum: '05.03.2025', tag: 'allgemein', link: 'Megamap#Webinar_vom_05.03.2025' },
        { titel: 'AQUA++ - Theorie, Modellierung und Fehlersuche', datum: '19.02.2025', tag: 'aqua', link: 'AQUA++_Webinare#Webinar_vom_19.02.2025' },
        { titel: 'ToGo - Digitalisierung im Kanalbetrieb', datum: '19.12.2024', tag: 'togo', link: 'ToGo-Erneuerungen#Digitalisierung_im_Kanalbetrieb_-_Webinar_vom_19.12.2024' },
        { titel: 'Datenuebernahme aus bestehenden GIS-Systemen', datum: '06.11.2024', tag: 'allgemein', link: 'Datenübernahme_Strakat' },
        { titel: 'KI in der Zustandserfassung', datum: '09.10.2024', tag: 'kasa', link: 'KI_Zustandserfassung' },
        { titel: 'INSIDe-Projekt', datum: '02.10.2024', tag: 'allgemein', link: 'Inside_Forschungsprojekt' },
        { titel: 'V16 - Import Radklim & Beispiele', datum: '03.06.2024', tag: 'geocpm', link: 'Import_RADKLIM' },
        { titel: 'V16 - Zeichentool', datum: '27.06.2024', tag: 'release', link: 'Zeichen-Tool#Webinar_vom_27.06.2024' },
        { titel: 'V16 - Geo3D Erneuerungen', datum: '25.06.2024', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_25.06.2024' },
        { titel: 'V16 - GeoCPM Neuerungen: Durchlaesse, Video', datum: '20.06.2024', tag: 'geocpm', link: 'Durchlass_GeoCPM#Durchl.C3.A4sse_-_Webinar_vom_20.06.2024' },
        { titel: 'V16 - Releasenews', datum: '18.06.2024', tag: 'release', link: 'Release_News#Release_Webinar_vom_18.06.2024' },
        { titel: 'GeoCPM - Tipps & Tricks DGM-Ausduennung', datum: '24.04.2024', tag: 'geocpm', link: 'Optimierung_durch_Ausdünnung#Ausd.C3.BCnnungsalgorithmen_-_Webinar_vom_24.04.2024' },
        { titel: 'Kanabis Release V10', datum: '09.04.2024', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V10_Webinar_vom_09.04.2024' },
        { titel: 'WIKI - Umfrage & Erneuerungen', datum: '20.03.2024', tag: 'allgemein', link: 'Wiki#Webinar_vom_20.03.2024' },
        { titel: 'GeoCPM - Kommunales Sturzflut-Risikomanagement Bayern', datum: '16.11.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_16.11.2023' },
        { titel: 'Flow V15: Neuerungen', datum: '09.11.2023', tag: 'flow', link: 'Bilanzierung_des_Zentralbeckens#Webinar_vom_09.11.2023' },
        { titel: 'GeoCPM Best Practice V15: Strukturen', datum: '02.11.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_02.11.2023' },
        { titel: 'GeoCPM Erneuerungen V15: OBOs', datum: '19.10.2023', tag: 'geocpm', link: 'Erneuerungen_GeoCPM#Webinar_vom_19.10.2023' },
        { titel: 'Release Version 15: Inn', datum: '18.10.2023', tag: 'release', link: 'Release_News_Version_15#Webinar_vom_18.10.2023' },
        { titel: 'Kanabis Release V9', datum: '09.02.2023', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V9_Webinar_vom_09.02.2023' },
        { titel: 'Neuerungen KASAnova', datum: '01.12.2022', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Kanalzustand_und_Sanierung_am_01.12.2022' },
        { titel: 'Release Version 14.10.00: Main', datum: '24.11.2022', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_24.11.2022' },
        { titel: 'Genauigkeit von Gelaendemodellen & Tipps', datum: '03.05.2022', tag: 'geocpm', link: 'Optimierung_durch_Ausdünnung#Genauigkeit_von_Gel.C3.A4ndemodellen_-_Webinar_vom_03.05.2022' },
        { titel: 'A102 & Flow & Practice', datum: '05.04.2022', tag: 'flow', link: 'DWA_A102#Webinar_-_Flow_.26_DWA_A102_Practice' },
        { titel: 'Radolan Daten fuer GeoCPM', datum: '22.03.2022', tag: 'geocpm', link: 'Aquazis#Webinar_vom_22.03.2022' },
        { titel: 'Release Version 14: Main', datum: '08.02.2022', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_08.02.2022' },
        { titel: 'Kanabis Release Version 8', datum: '09.12.2021', tag: 'kanabis', link: 'KANABIS-Vergangene_Webinare#Release_V8_Webinar_vom_09.12.2021' },
        { titel: 'Geo3D Best-Practice', datum: '24.11.2021', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_24.11.2021' },
        { titel: 'Numerische Simulation', datum: '17.11.2021', tag: 'hydraulik', link: 'Numerische_Simulation' },
        { titel: 'A102 & Flow', datum: '09.11.2021', tag: 'flow', link: 'DWA_A102#Webinar_-_DWA_A102_Erneuerungen_Flow' },
        { titel: '++SYSTEMS Projektdateimanagement 2.0', datum: '27.10.2021', tag: 'allgemein', link: 'Vergleichs-_und_Importkonfiguration#Webinar_vom_27.11.2021' },
        { titel: 'Manueller Laengsschnitt', datum: '06.10.2021', tag: 'hydraulik', link: 'Manueller_Längsschnitt#Webinar_vom_06.10.2021' },
        { titel: 'Starkregen - Kommunales Risikomanagement', datum: '20.10.2021', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_20.10.2021' },
        { titel: 'BIM & Betriebsprozesse', datum: '13.10.2021', tag: 'togo', link: 'ToGo-Erneuerungen#BIM_.26_Betriebsprozesse_-_Webinar_vom_13.10.2021' },
        { titel: 'Version 13 Donau3D Erneuerungen', datum: '20.05.2021', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_20.05.2021' },
        { titel: 'Visualisierung mit dem neuen 3DTool', datum: '22.04.2021', tag: 'geocpm', link: 'Geo3D-Allgemein#Webinar_vom_21.04.2021' },
        { titel: 'Aufbereitung von Eingangsdaten mit QGIS', datum: '13.04.2021', tag: 'allgemein', link: 'QGIS' },
        { titel: 'Vorstellung der neuen Dokumentationsplattform WIKI', datum: '24.03.2021', tag: 'allgemein', link: 'Wiki' },
        { titel: '++SYSTEMS Kanalzustand und Sanierung', datum: '10.03.2021', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Kanalzustand_und_Sanierung_am_10.03.2021' },
        { titel: 'Multi-User-Plattformen', datum: '03.03.2021', tag: 'allgemein', link: 'Datenbanken#Multi-User-Plattformen-Webinar_vom_03.03.2021' },
        { titel: 'Erneuerungen und Best-Practice', datum: '17.02.2021', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_17.02.2021' },
        { titel: 'Entwurfsplanung', datum: '09.12.2020', tag: 'hydraulik', link: 'Entwurfsplanung_Webinar' },
        { titel: 'GeoCPM Best Practice und Erneuerungen', datum: '03.12.2020', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_03.12.2020' },
        { titel: 'Vom Radar zum Simulationsergebnis I', datum: '02.12.2020', tag: 'geocpm', link: 'Einbinden_von_Radardaten' },
        { titel: 'Vom Radar zum Simulationsergebnis II', datum: '24.11.2020', tag: 'geocpm', link: 'Einbinden_von_Radardaten' },
        { titel: 'Flow - Best Practice', datum: '18.11.2020', tag: 'flow', link: 'Schritt-für-Schritt-Anleitung_Flow#Best-Practice_Webinar' },
        { titel: 'Erneuerungen und Best-Practice Nov 2020', datum: '11.11.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_11.11.2020' },
        { titel: 'GeoCPM Best Practice Mai 2020', datum: '17.05.2020', tag: 'geocpm', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_17.05.2020' },
        { titel: 'Bedarfsorientierte Kanalreinigung', datum: '12.05.2020', tag: 'togo', link: 'ToGo-Erneuerungen#Bedarfsorientiere_Kanalreinigung_-_Webinar_vom_12.05.2020' },
        { titel: 'Erneuerungen und Best-Practice Apr 2020', datum: '30.04.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_30.04.2020' },
        { titel: 'Release V12 - Neues Look and Feel', datum: '28.04.2020', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_28.04.2020' },
        { titel: 'Anbindung von Datenbanken', datum: '07.03.2020', tag: 'allgemein', link: 'Datenbanken#Webinar_-_Themenschwerpunkt:_Anbindung_von_Datenbanbanken_vom_07.03.2020' },
        { titel: 'Starkregenrisikomanagement LUBW II', datum: '29.05.2019', tag: 'geocpm', link: 'Vorgehen_Starkregenrisikomangenement_LUBW#Webinar_LUBW_II' },
        { titel: 'Bruchkanten', datum: '22.05.2019', tag: 'geocpm', link: 'Bruchkanten#Vorgehen_Bruchkanten_GeoCPM' },
        { titel: '++SYSTEMS Projektdateimanagement', datum: '15.05.2019', tag: 'allgemein', link: 'Vergleichs-_und_Importkonfiguration#Webinar_vom_15.05.2019' },
        { titel: 'Koordinatentransformation', datum: '30.04.2019', tag: 'allgemein', link: 'Koordinatentransformation#Webinar_vom_30.04.2019' },
        { titel: 'Planausgabe', datum: '10.04.2019', tag: 'allgemein', link: 'Plankonfigurationen#Planausgabe_Webinar_vom_10.04.2018' },
        { titel: 'Release V11', datum: '11.03.2019', tag: 'release', link: 'Vergangene_Erneuerungen#Webinar_vom_08.05.2019' },
        { titel: 'Bestandsdaten & Dokumentation 2018', datum: '05.12.2018', tag: 'togo', link: 'ToGo-Erneuerungen#Bestandsdaten.28erfassung.29_und_l.C3.BCckenlose_Dokumentation_-_Webinar_vom_05.12.2018' },
        { titel: 'Funktionale Einheiten - Ergebnislisten', datum: '28.11.2018', tag: 'flow', link: 'Funktionale_Einheiten' },
        { titel: 'KASAnova 2.0 - Sanierungsmodul Version 11', datum: '14.11.2018', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_KASAnova_2.0_-_Sanierungsmodul_Version_11_am_14.11.2018' },
        { titel: 'Release Version 11', datum: '08.11.2018', tag: 'release', link: 'GeoCPM_Vergangene_Erneuerungen#Webinar_vom_08.11.2018' },
        { titel: 'KASAnova 2.0 - Sanierungsmodul neu aufgelegt', datum: '18.04.2018', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_KASAnova_2.0_-_Das_Sanierungsmodul_neu_aufgelegt_am_18.04.2018' },
        { titel: 'DYNA - Rechnet nicht', datum: '21.03.2018', tag: 'hydraulik', link: 'DYNA-Fehlerbehebung' },
        { titel: 'Datenbanken', datum: '07.03.2018', tag: 'allgemein', link: 'Datenbanken#Datenbanken-Webinar_vom_07.03.2020' },
        { titel: 'Starkregenrisikomanagement LUBW I', datum: '19.07.2017', tag: 'geocpm', link: 'Vorgehen_Starkregenrisikomangenement_LUBW#Webinar_LUBW_I' },
        { titel: 'Erneuerung mit Flow++', datum: '10.05.2017', tag: 'flow', link: 'Erneuerung_mit_Flow++' },
        { titel: 'Messstellen', datum: '22.03.2017', tag: 'hydraulik', link: 'Messstellen' },
        { titel: 'Import/Export - XML Formate', datum: '15.03.2017', tag: 'allgemein', link: 'Schnittstellen#Import.2FExport-Schnittstellen_Webinar_vom_15.03.2017' },
        { titel: 'Import/Export - DXF und ESRI Shape', datum: '07.12.2016', tag: 'allgemein', link: 'Schnittstellen#Import.2FExport-Schnittstellen_Webinar_vom_07.12.2017' },
        { titel: 'Listengenerator', datum: '23.11.2016', tag: 'allgemein', link: 'Listengenerator#Webinar_vom_23.11.2016' },
        { titel: 'Wasseraustausch - Bi-Direktionale Kopplung', datum: '11.10.2016', tag: 'hydraulik', link: 'Bi-Direktionale_Kopplung#Webinar_-_Themenschwerpunkt:_Bi-Direktionale_Kopplung_vom_11.10.2016' },
        { titel: 'Verteilvorschrift Regenspenden KOSTRA', datum: '22.09.2016', tag: 'hydraulik', link: 'Verteilungsvorschriften_für_extreme_Regenspenden#Webinar_-_Themenschwerpunkt:_Regenerstellung_aus_Verteilungsvorschrift_.28Kostra.29_vom_22.09.2016' },
        { titel: 'Zustandserfassung - Daten-Wellenlaenge', datum: '21.07.2016', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Zustandserfassung_-_der_Befahrer_und_Sie_auf_einer_.22Daten-Wellenl.C3.A4nge.22_am_21.07.2016' },
        { titel: 'Themenplan', datum: '30.06.2016', tag: 'allgemein', link: 'Ansichtskonfiguration#Webinar_vom_30.06.2016' },
        { titel: 'Schluss mit der Zettelwirtschaft', datum: '16.06.2016', tag: 'togo', link: 'ToGo-Erneuerungen#Schluss_mit_der_Zettelwirtschaft_-_Webinar_vom_16.06.2016' },
        { titel: 'Bestandsdaten & Dokumentation 2015', datum: '16.12.2015', tag: 'togo', link: 'ToGo-Erneuerungen#.2B.2BSYSTEMS_togo_-_die_Mobile_Version_-_Webinar_vom_16.12.2015' },
        { titel: 'Einzugsgebietsmanagement', datum: '16.06.2015', tag: 'hydraulik', link: 'Einzugsgebietsmanagement' },
        { titel: 'Integrierte Zustandsbewertung und Sanierungsplanung', datum: '09.05.2015', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Integrierte_Zustandsbewertung_und_Sanierungsplanung_am_9.05.2015' },
        { titel: 'Untersuchungsverwaltung - Zustandsbewertung - Sanierung', datum: '21.10.2014', tag: 'kasa', link: 'Kasanova_Erneuerungen#Webinar:_Untersuchungsverwaltung_.E2.80.93_Zustandsbewertung_-_Sanierung_am_21.10.2014' },
    ];
    var TAGS = {
        /* Farbsystem nach Corporate Design: Tandler Blau (#372281) fuer die
           Simulations-/Berechnungsmodule, Magenta (#b60e7e) fuer die Asset-/
           Wassermodule, jeweils in Abstufungen. "Alle" nutzt das etablierte
           Blaugrau, Release/Allgemein bleiben neutral grau. */
        alle:      { label: 'Alle',       farbe: '#666699' },
        geocpm:    { label: 'GeoCPM',     farbe: '#372281' },
        hydraulik: { label: 'Hydraulik',  farbe: '#26185A' },
        flow:      { label: 'Flow',       farbe: '#554394' },
        togo:      { label: 'ToGo',       farbe: '#7364A7' },
        kasa:      { label: 'KASAnova',   farbe: '#B60E7E' },
        aqua:      { label: 'AQUA++',     farbe: '#7F0A58' },
        kanabis:   { label: 'Kanabis',    farbe: '#C13291' },
        release:   { label: 'Release',    farbe: '#5F5E5A' },
        allgemein: { label: 'Allgemein',  farbe: '#444441' },
    };
    var ICONS = {
        geocpm:    'GeoCPM.png',
        hydraulik: 'DYNA.png',
        flow:      'Flow.png',
        togo:      'TOGO.png',
        kasa:      'KASANOVA.png',
        aqua:      'Aqua.png',
        kanabis:   'kanabis.png',
        release:   'ppsystems_icon.png',
        allgemein: 'ppsystems_icon.png'
    };
    function injizierCSS() {
        if (document.getElementById('vg-styles')) return;
        var css = [
            '#vg-container { font-family: sans-serif; margin: 1rem 0; }',
            '#vg-controls { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; align-items: center; }',
            '#vg-suche { flex: 1; min-width: 180px; padding: 6px 10px; border: 1px solid #ccc; border-radius: 6px; font-size: 13px; }',
            '.vg-filter-btn { padding: 4px 12px; border-radius: 20px; border: 1px solid #ccc; background: #f8f8f8; font-size: 12px; cursor: pointer; transition: all .15s; }',
            '.vg-filter-btn.aktiv { color: #fff; border-color: transparent; }',
            '.vg-anzahl { font-size: 12px; color: #888; margin-bottom: 8px; }',
            '.vg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; }',
            '.vg-karte { display: block; border: 1px solid #e0e0e0; border-radius: 10px; overflow: hidden; background: #fff; transition: box-shadow .15s, transform .15s; text-decoration: none; color: inherit; }',
            '.vg-karte:hover { box-shadow: 0 4px 16px rgba(0,0,0,.12); transform: translateY(-2px); text-decoration: none; color: inherit; }',
            '.vg-icon-wrap { width: 100%; aspect-ratio: 16/9; background: #f0f0f4; display: flex; align-items: center; justify-content: center; overflow: hidden; }',
            '.vg-icon-img { max-width: 55%; max-height: 55%; object-fit: contain; transition: transform 0.2s ease; }',
            '.vg-karte:hover .vg-icon-img { transform: scale(1.08); }',
            '.vg-badge { display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 12px; color: #fff; font-weight: 500; }',
            '.vg-body { padding: 12px 14px; }',
            '.vg-titel { font-size: 13px; font-weight: 600; color: #222; line-height: 1.4; margin: 6px 0 4px; }',
            '.vg-datum { font-size: 11px; color: #888; }',
            '.vg-leer { text-align: center; padding: 2rem; color: #888; font-size: 14px; grid-column: 1 / -1; }',
        ].join('\n');
        var style = document.createElement('style');
        style.id = 'vg-styles';
        style.textContent = css;
        document.head.appendChild(style);
    }

    function baueGalerie(container, vorauswahl) {
        injizierCSS();
        var nurEinTag = !!vorauswahl && TAGS[vorauswahl];
        var aktuellerTag = nurEinTag ? vorauswahl : 'alle';

        var html = '<div id="vg-container">';
        if (!nurEinTag) {
            html += '<div class="vg-controls">';
            html += '<input class="vg-suche" type="text" placeholder="Webinar suchen..." />';
            Object.keys(TAGS).forEach(function (key) {
                var t = TAGS[key];
                var stil = key === 'alle' ? ' style="background:' + t.farbe + ';color:#fff;border-color:' + t.farbe + ';"' : '';
                html += '<button class="vg-filter-btn' + (key === 'alle' ? ' aktiv' : '') + '" data-tag="' + key + '"' + stil + '>' + t.label + '</button>';
            });
            html += '</div>';
        } else {
            html += '<div class="vg-controls"><input class="vg-suche" type="text" placeholder="Webinar suchen..." /></div>';
        }
        html += '<div class="vg-anzahl"></div>';
        html += '<div class="vg-grid"></div>';
        html += '</div>';
        container.innerHTML = html;

        var suchfeld = container.querySelector('.vg-suche');
        var grid = container.querySelector('.vg-grid');
        var anzahl = container.querySelector('.vg-anzahl');

        function renderKarten() {
            var q = suchfeld.value.toLowerCase().trim();
            var gefiltert = WEBINARE.filter(function (w) {
                var tagOk = aktuellerTag === 'alle' || w.tag === aktuellerTag;
                var suchOk = !q || w.titel.toLowerCase().indexOf(q) > -1;
                return tagOk && suchOk;
            });
            anzahl.textContent = gefiltert.length + ' Webinar' + (gefiltert.length !== 1 ? 'e' : '');
            if (!gefiltert.length) {
                grid.innerHTML = '<p class="vg-leer">Keine Webinare gefunden.</p>';
                return;
            }
            grid.innerHTML = gefiltert.map(function (w) {
                var farbe = TAGS[w.tag] ? TAGS[w.tag].farbe : '#666699';
                var tagLabel = TAGS[w.tag] ? TAGS[w.tag].label : w.tag;
                var iconDatei = ICONS[w.tag] || 'ppsystems_icon.png';
                var url = (typeof mw !== 'undefined') ? mw.util.getUrl(w.link) : ('/index.php?title=' + encodeURIComponent(w.link));
                var iconUrl = (typeof mw !== 'undefined') ? mw.util.getUrl('Special:FilePath/' + iconDatei) : ('/index.php/Special:FilePath/' + encodeURIComponent(iconDatei));
                return [
                    '<a class="vg-karte" href="' + url + '">',
                    '  <div class="vg-icon-wrap"><img class="vg-icon-img" src="' + iconUrl + '" alt="' + tagLabel + '" /></div>',
                    '  <div class="vg-body">',
                    '    <span class="vg-badge" style="background:' + farbe + '">' + tagLabel + '</span>',
                    '    <p class="vg-titel">' + w.titel + '</p>',
                    '    <p class="vg-datum">' + w.datum + '</p>',
                    '  </div>',
                    '</a>',
                ].join('\n');
            }).join('\n');
        }

        if (!nurEinTag) {
            container.querySelectorAll('.vg-filter-btn').forEach(function (btn) {
                btn.addEventListener('click', function () {
                    aktuellerTag = btn.getAttribute('data-tag');
                    container.querySelectorAll('.vg-filter-btn').forEach(function (b) {
                        b.classList.remove('aktiv');
                        b.style.background = '';
                        b.style.color = '';
                        b.style.borderColor = '';
                    });
                    btn.classList.add('aktiv');
                    var farbe = TAGS[aktuellerTag] ? TAGS[aktuellerTag].farbe : '#666699';
                    btn.style.background = farbe;
                    btn.style.color = '#fff';
                    btn.style.borderColor = farbe;
                    renderKarten();
                });
            });
        }
        suchfeld.addEventListener('input', renderKarten);
        renderKarten();
    }

    $(document).ready(function () {
        document.querySelectorAll('[id^="webinare-galerie-slot"]').forEach(function (container) {
            var suffix = container.id.replace('webinare-galerie-slot', '').replace(/^-/, '');
            baueGalerie(container, suffix || null);
        });
    });
})();


/* ===== Tandler Wiki - Projektbaum (zentral, selbstgeschrieben) =====
   Ersetzt {{#tree: extensions=["persist"]|...}} (TreeAndMenu-Erweiterung) durch einen
   selbstgeschriebenen, Datei-Explorer-artigen Baum mit Ordner-/Dokument-Icons.
   Einbindung auf einer Seite: <div id="projektbaum-slot"></div>
   Aufklapp-Zustand wird pro Browser (localStorage) gemerkt, wie bei "extensions=[persist]" vorher.
*/
(function () {
    'use strict';

    var CHEVRON_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';

    var ICON_ORDNER = 'pb_icon_ordner.png';
    var ICONS = {
        'Allgemein': 'pb_icon_allgemein.png',
        'Ansicht': 'pb_icon_ansicht.png',
        'Kanalsystem': 'pb_icon_kanalsystem.png',
        'Zustand & Sanierung': 'pb_icon_zustand_sanierung.png',
        'Wasserversorgung': 'pb_icon_wasserversorgung.png',
        'Oberfläche': 'pb_icon_oberflaeche.png',
        'Berechnungsparameter': 'pb_icon_berechnungsparameter.png',
        'Hydraulische Berechnungen': 'pb_icon_hydraulische_berechnungen.png',
        'Auswertung': 'pb_icon_auswertung.png',
        'Schnittstellen': 'pb_icon_schnittstellen.png',
        'Gewässerverwaltung': 'pb_icon_gewaesserverwaltung.png'
    };

    var BAUM = {
        label: 'Projektname', link: null, children: [
            { label: 'Global', link: 'Allgemein', children: [
                { label: 'Gemeinde', link: 'Gemeinde' },
                { label: 'Profile', link: 'Profile' },
                { label: 'Materialien', link: 'Materialien' },
                { label: 'Texte und Spannmasse', link: 'Texte und Spannmasse' },
                { label: 'Dokumente', link: 'Dokumente' },
                { label: 'Marker', link: 'Marker' },
                { label: 'GIS-Punkte', link: 'GIS-Punkte' }
            ]},
            { label: 'Ansicht', link: 'Ansicht', children: [
                { label: 'Ansichtskonfiguration', link: 'Ansichtskonfiguration', children: [
                    { label: 'Zoomkonfiguration', link: 'Zoomkonfiguration' }
                ]},
                { label: 'Farbkonfiguration', link: 'Farbkonfiguration' },
                { label: 'Plangitter', link: 'Plangitter' },
                { label: 'Plankonfigurationen', link: 'Plankonfigurationen' },
                { label: 'Rastergrafiken', link: 'Rastergrafiken' },
                { label: 'Vektorgrafiken', link: 'Vektorgrafiken' },
                { label: 'WMS Grafiken', link: 'WMS Grafiken' },
                { label: 'Symbole', link: 'Symbole' },
                { label: 'Linienarten', link: 'Linienarten' }
            ]},
            { label: 'Kanalsystem', link: 'Kanalsystem', children: [
                { label: 'Knoten', link: 'Knoten' },
                { label: 'Abschnitte', link: 'Abschnitte' }
            ]},
            { label: 'Zustand & Sanierung', link: 'Zustand & Sanierung', children: [
                { label: 'Sanierung', link: 'Sanierung', children: [
                    { label: 'Varianten', link: 'Varianten' },
                    { label: 'Verfahren', link: 'Verfahren (Sanierung)' },
                    { label: 'Sanierungstabellen', link: 'Sanierungstabellen' }
                ]},
                { label: 'Zustand', link: 'Zustand', children: [
                    { label: 'Untersuchungen', link: 'Untersuchungen' },
                    { label: 'Bewertungstabellen', link: 'Bewertungstabellen' },
                    { label: 'Bewertungsvarianten', link: 'Bewertungsvarianten' },
                    { label: 'Bewertungsergebnisse', link: 'Bewertungsergebnisse' }
                ]}
            ]},
            { label: 'Wasserversorgung', link: 'Wasserversorgung', children: [
                { label: 'Wasserleitungen', link: 'Wasserleitungen' },
                { label: 'Wasserknoten', link: 'Wasserknoten' }
            ]},
            { label: 'Oberfläche', link: 'Oberfläche', children: [
                { label: 'Punktmengen', link: 'Punktmengen' },
                { label: 'Bruchkanten', link: 'Bruchkanten' },
                { label: 'Geländemodelle', link: 'Geländemodelle' },
                { label: 'Partitionen', link: 'Partitionen' }
            ]},
            { label: 'Berechnungsparameter', link: 'Berechnungsparameter', children: [
                { label: 'Niederschlag', link: 'Niederschlag', children: [
                    { label: 'Regenmessstationen', link: 'Regenmessstationen' },
                    { label: 'Gebietsniederschlag', link: 'Gebietsniederschlag' },
                    { label: 'Verteilungsvorschriften für extreme Regenspenden', link: 'Verteilungsvorschriften für extreme Regenspenden' }
                ]},
                { label: 'Messstellen', link: 'Messstellen' },
                { label: 'Schlüsselwerte', link: 'Schlüsselwerte', children: [
                    { label: 'Unterschiedliche Schlüsselwerte', link: 'Unterschiedliche Schlüsselwerte' }
                ]},
                { label: 'Kennlinien', link: 'Kennlinien' },
                { label: 'Kurven', link: 'Kurven' },
                { label: 'Ganglinien/Verlauf', link: 'Ganglinien/Verlauf', children: [
                    { label: 'Tagesganglinien/Verlauf', link: 'Tagesganglinien/Verlauf' },
                    { label: 'Wochenganglinien/Verlauf', link: 'Wochenganglinien/Verlauf' },
                    { label: 'Jahresganglinien/Verlauf', link: 'Jahresganglinien/Verlauf' }
                ]},
                { label: 'Schmutzstoffe', link: 'Schmutzstoffe' }
            ]},
            { label: 'Hydraulische Berechnungen', link: 'Hydraulische Berechnungen', children: [
                { label: 'Kanalnetzberechnung', link: 'Kanalnetzberechnung', children: [
                    { label: 'Hydraulikvariante', link: 'Hydraulikvariante', children: [
                        { label: 'Kennlinien', link: 'Kennlinien' },
                        { label: 'Blockregenstaffeln', link: 'Blockregenstaffeln' },
                        { label: 'Natur-/Modellregen', link: 'Natur-/Modellregen' },
                        { label: 'Ergebnislisten', link: 'Ergebnislisten' },
                        { label: 'Längsschnitte', link: 'Längsschnitte' }
                    ]},
                    { label: 'Schmutzfrachtvariante', link: 'Schmutzfrachtvariante', children: [
                        { label: 'Funktionale Einheiten', link: 'Funktionale Einheiten' }
                    ]},
                    { label: 'Steuerungsvarianten', link: 'Steuerungsvarianten' }
                ]},
                { label: 'Oberflächenabflussberechnungen', link: 'Oberflächenabflussberechnungsobjekt', children: [
                    { label: 'Oberflächenabflussberechnungsobjekt', link: 'Oberflächenabflussberechnungsobjekt' }
                ]},
                { label: 'Wassernetzberechnung', link: 'Wassernetzberechnung', children: [
                    { label: 'Berechnungsvariante Wasser-Objekt', link: 'Berechnungsvariante Wasser-Objekt' }
                ]}
            ]},
            { label: 'Auswertung', link: 'Auswertung', children: [
                { label: 'Listengenerator', link: 'Listengenerator' },
                { label: 'Attributname', link: 'Attributname' },
                { label: 'Ausdrücke', link: 'Ausdrücke' },
                { label: 'Eigenschaftslisten', link: 'Eigenschaftslisten' },
                { label: 'Längsschnitte', link: 'Längsschnitte', children: [
                    { label: 'Konfiguration', link: 'Konfiguration' },
                    { label: 'Gespeicherte Längsschnitte', link: 'Gespeicherte Längsschnitte' }
                ]}
            ]},
            { label: 'Schnittstellen', link: 'Schnittstellen', children: [
                { label: 'Vergleichs- und Importkonfiguration', link: 'Vergleichs- und Importkonfiguration' },
                { label: 'Import/Export-Formate', link: 'Import/Export-Formate' },
                { label: 'Datenbankformate', link: 'Datenbankformate' }
            ]},
            { label: 'Gewässerverwaltung', link: 'Gewässerverwaltung', children: [
                { label: 'Gewässer', link: 'Gewässer' },
                { label: 'Gewässerunterhalt', link: 'Gewässerunterhalt', children: [
                    { label: 'Verfahren', link: 'Verfahren (Gewässerunterhalt)' }
                ]}
            ]}
        ]
    };

    function injizierCSS() {
        if (document.getElementById('pb-styles')) return;
        var css = [
            '.pb-liste { list-style: none; margin: 0; padding-left: 20px; }',
            '.pb-wurzel { padding-left: 0; }',
            '.pb-zeile { display: flex; align-items: center; gap: 6px; padding: 4px 2px; cursor: default; }',
            '.pb-toggle { flex: 0 0 16px; width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #372281; cursor: pointer; user-select: none; transition: transform 0.15s ease; transform: rotate(0deg); }',
            '.pb-toggle svg { width: 14px; height: 14px; display: block; }',
            '.pb-toggle.pb-offen { transform: rotate(90deg); }',
            '.pb-toggle.pb-leer { visibility: hidden; }',
            '.pb-icon { flex: 0 0 22px; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; font-size: 16px; line-height: 1; cursor: pointer; }',
            '.pb-icon.pb-kreis { flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%; }',
            '.pb-icon.pb-magenta { background: #b60e7e; }',
            '.pb-icon.pb-blau { background: #372281; }',
            '.pb-icon.pb-kreis img { width: 78%; height: 78%; object-fit: contain; filter: brightness(0) invert(1); }',
            '.pb-icon.pb-punkt { background: none; }',
            '.pb-icon.pb-punkt::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #372281; }',
            '.pb-link { color: #372281; text-decoration: none; font-size: 13px; white-space: nowrap; }',
            '.pb-link:hover { text-decoration: underline; }',
            '.pb-zeile:hover { background: #f5f3fa; border-radius: 4px; }',
            '.pb-wurzel-zeile .pb-link { font-weight: bold; }',
        ].join('\n');
        var style = document.createElement('style');
        style.id = 'pb-styles';
        style.textContent = css;
        document.head.appendChild(style);
    }

    function knotenId(pfad) {
        return 'pb-' + pfad.join('-');
    }

    function iconUrl(datei) {
        return (typeof mw !== 'undefined') ? mw.util.getUrl('Special:FilePath/' + datei) : ('/index.php/Special:FilePath/' + encodeURIComponent(datei));
    }

    function setzeOrdnerIcon(icon, label) {
        icon.classList.add('pb-kreis', 'pb-blau');
        icon.innerHTML = '<img src="' + iconUrl(ICONS[label] || ICON_ORDNER) + '" alt="" />';
    }

    function baueListe(knoten, pfad, ul) {
        knoten.children.forEach(function (kind, i) {
            var eigenerPfad = pfad.concat(i);
            var id = knotenId(eigenerPfad);
            var hatKinder = !!(kind.children && kind.children.length);

            var li = document.createElement('li');
            li.className = 'pb-node';

            var zeile = document.createElement('div');
            zeile.className = 'pb-zeile';

            var toggle = document.createElement('span');
            toggle.className = 'pb-toggle';
            zeile.appendChild(toggle);

            var icon = document.createElement('span');
            icon.className = 'pb-icon';
            zeile.appendChild(icon);

            var link = document.createElement('a');
            link.className = 'pb-link';
            link.href = (typeof mw !== 'undefined') ? mw.util.getUrl(kind.link) : ('/index.php?title=' + encodeURIComponent(kind.link));
            link.textContent = kind.label;
            zeile.appendChild(link);

            li.appendChild(zeile);

            if (hatKinder) {
                toggle.innerHTML = CHEVRON_SVG;

                var ulKind = document.createElement('ul');
                ulKind.className = 'pb-liste';

                var offen = false;
                try { offen = localStorage.getItem(id) === '1'; } catch (e) {}
                ulKind.style.display = offen ? 'block' : 'none';

                if (eigenerPfad.length === 1) {
                    setzeOrdnerIcon(icon, kind.label);
                } else {
                    icon.classList.add('pb-punkt');
                }

                function setSymbole(offenNeu) {
                    toggle.classList.toggle('pb-offen', offenNeu);
                }
                setSymbole(offen);

                function umschalten() {
                    var neuOffen = ulKind.style.display === 'none';
                    ulKind.style.display = neuOffen ? 'block' : 'none';
                    setSymbole(neuOffen);
                    try { localStorage.setItem(id, neuOffen ? '1' : '0'); } catch (e) {}
                }
                toggle.addEventListener('click', umschalten);
                icon.style.cursor = 'pointer';
                icon.addEventListener('click', umschalten);

                baueListe(kind, eigenerPfad, ulKind);
                li.appendChild(ulKind);
            } else {
                toggle.classList.add('pb-leer');
                icon.classList.add('pb-punkt');
                icon.style.cursor = 'default';
            }

            ul.appendChild(li);
        });
    }

    function baueBaum(container) {
        injizierCSS();
        container.innerHTML = '';

        var aeusserUl = document.createElement('ul');
        aeusserUl.className = 'pb-liste pb-wurzel';

        var li = document.createElement('li');
        li.className = 'pb-node';

        var zeile = document.createElement('div');
        zeile.className = 'pb-zeile pb-wurzel-zeile';

        var toggle = document.createElement('span');
        toggle.className = 'pb-toggle';
        toggle.innerHTML = CHEVRON_SVG;
        zeile.appendChild(toggle);

        var icon = document.createElement('span');
        icon.className = 'pb-icon pb-kreis pb-magenta';
        icon.innerHTML = '<img src="' + iconUrl(ICON_ORDNER) + '" alt="" />';
        zeile.appendChild(icon);

        var label = document.createElement('span');
        label.className = 'pb-link';
        label.style.cursor = 'pointer';
        label.textContent = BAUM.label;
        zeile.appendChild(label);

        li.appendChild(zeile);

        var innerUl = document.createElement('ul');
        innerUl.className = 'pb-liste';

        var offen = true;
        try { offen = localStorage.getItem('pb-wurzel') !== '0'; } catch (e) {}
        innerUl.style.display = offen ? 'block' : 'none';
        toggle.classList.toggle('pb-offen', offen);

        function umschaltenWurzel() {
            var neuOffen = innerUl.style.display === 'none';
            innerUl.style.display = neuOffen ? 'block' : 'none';
            toggle.classList.toggle('pb-offen', neuOffen);
            try { localStorage.setItem('pb-wurzel', neuOffen ? '1' : '0'); } catch (e) {}
        }
        toggle.addEventListener('click', umschaltenWurzel);
        label.addEventListener('click', umschaltenWurzel);
        icon.style.cursor = 'pointer';
        icon.addEventListener('click', umschaltenWurzel);

        baueListe(BAUM, [], innerUl);
        li.appendChild(innerUl);
        aeusserUl.appendChild(li);
        container.appendChild(aeusserUl);
    }

    $(document).ready(function () {
        var container = document.getElementById('projektbaum-slot');
        if (container) baueBaum(container);
    });
})();