Menü aufrufen
Toggle preferences menu
Persönliches Menü aufrufen
Nicht angemeldet
Ihre IP-Adresse wird öffentlich sichtbar sein, wenn Sie Änderungen vornehmen.

MediaWiki:Common.js: Unterschied zwischen den Versionen

MediaWiki-Schnittstellenseite
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
 
(56 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 8: Zeile 8:
         section.hidden = 'until-found';
         section.hidden = 'until-found';
     });
     });
});
//Anker aufklappen und Spoiler aufklappen bei Suchen
$(document).ready(function() {
    setTimeout(function() {
        var hash = window.location.hash;
        var ref = document.referrer;
        var searchMatch = ref.match(/[?&]search=([^&]+)/);
       
        // Anker-Link: entsprechenden Abschnitt aufklappen
        if (hash) {
            var target = document.getElementById(hash.substring(1));
            if (target) {
                var h2 = target.closest('h2') ||
                        (target.tagName === 'H2' ? target : null);
                if (!h2) {
                    var section = target.closest('.citizen-section');
                    if (section) h2 = section.previousElementSibling;
                }
                if (h2 && h2.classList.contains('citizen-section-heading')) {
                    var indicator = h2.querySelector('.citizen-section-indicator');
                    if (indicator) indicator.click();
                    setTimeout(function() { target.scrollIntoView(); }, 100);
                }
            }
        }
        // Suche: ersten Abschnitt + verschachtelte Spoiler aufklappen
        if (!searchMatch) return;
        var term = decodeURIComponent(searchMatch[1]).toLowerCase();
        var sections = document.querySelectorAll('.citizen-section');
        for (var i = 0; i < sections.length; i++) {
            if (sections[i].textContent.toLowerCase().includes(term)) {
                var h2 = sections[i].previousElementSibling;
                if (h2 && h2.classList.contains('citizen-section-heading')) {
                    var indicator = h2.querySelector('.citizen-section-indicator');
                    if (indicator) indicator.click();
                }
                // Verschachtelte mw-collapsible aufklappen die den Begriff enthalten
                setTimeout(function(sec) {
                    var collapsibles = sec.querySelectorAll('.mw-collapsible.mw-collapsed');
                    collapsibles.forEach(function(col) {
                        if (col.textContent.toLowerCase().includes(term)) {
                            var toggle = col.querySelector('.mw-collapsible-toggle');
                            if (toggle) toggle.click();
                        }
                    });
                    h2.scrollIntoView();
                }, 200, sections[i]);
                break;
            }
        }
    }, 500);
});
//Hauptseite Grid Ausrichtung
$(document).ready(function() {
    setTimeout(function() {
        document.querySelectorAll('.wiki-overview-grid').forEach(function(grid) {
            var cols = grid.querySelectorAll('.wiki-overview-col');
            var firstHeaders = [];
            cols.forEach(function(col) {
                var h = col.querySelector('h4');
                if (h) firstHeaders.push(h);
            });
           
            // Natürliche Höhen vor minHeight messen
            var naturalHeights = firstHeaders.map(function(h) { return h.offsetHeight; });
            var maxH = Math.max.apply(null, naturalHeights);
            var minH = Math.min.apply(null, naturalHeights);
           
            firstHeaders.forEach(function(h) {
                h.style.minHeight = maxH + 'px';
                h.style.display = 'flex';
                h.style.alignItems = 'flex-end';
                h.style.justifyContent = 'center';
            });
            // Grid um den Leerraum nach oben verschieben
            if (maxH > minH) {
                grid.style.marginTop = '-' + (maxH - minH) + 'px';
            }
        });
    }, 300);
});
// Ausklappen des ersten Abschnitts bei fehlendem Einleitungstext
$(document).ready(function() {
    setTimeout(function() {
        var content = document.querySelector('.mw-parser-output');
        if (!content) return;
        var children = Array.from(content.children);
        // Prüfen ob die erste Section Text enthält (= Einleitungstext)
        var firstSection = children.find(function(el) {
            return el.classList.contains('citizen-section');
        });
        if (firstSection && firstSection.textContent.trim() !== '') return;
        // Erste H2 aufklappen
        var firstH2 = children.find(function(el) {
            return el.tagName === 'H2' && el.classList.contains('citizen-section-heading');
        });
        if (firstH2) {
            var indicator = firstH2.querySelector('.citizen-section-indicator');
            if (indicator) indicator.click();
        }
    }, 500);
});
});


// Social Icons in Sidebar ersetzen
// Social Icons in Sidebar ersetzen
$(function() {
$(function() {
    $('#n-sidebar-label-contactus').closest('ul').addClass('sgpggb-external-menu');
     var icons = {
     var icons = {
         'n-Discord':    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36" width="20" height="20" fill="currentColor"><path d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></svg>',
         'n-Discord':    'fab fa-discord',
         'n-Facebook':  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" width="20" height="20" fill="currentColor"><path d="M279.14 288l14.22-92.66h-88.91v-60.13c0-25.35 12.42-50.06 52.24-50.06h40.42V6.26S260.43 0 225.36 0c-73.22 0-121.08 44.38-121.08 124.72v70.62H22.89V288h81.39v224h100.17V288z"/></svg>',
         'n-Facebook':  'fab fa-facebook-f',
         'n-Instagram':  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="20" height="20" fill="currentColor"><path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"/></svg>',
         'n-Instagram':  'fab fa-instagram',
         'n-X':          '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20" height="20" fill="currentColor"><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"/></svg>',
         'n-X':          'fab fa-x-twitter',
         'n-YouTube':    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="20" height="20" fill="currentColor"><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>',
         'n-YouTube':    'fab fa-youtube',
         'n-Twitch':    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20" height="20" fill="currentColor"><path d="M391.17,103.47H352.54v109.7h38.63ZM285,103H246.37V212.75H285ZM120.83,0,24.31,91.42V420.58H140.14V512l96.53-91.42h77.25L487.69,256V0ZM449.07,237.75l-77.22,73.12H294.61l-67.6,64v-64H140.14V36.58H449.07Z"/></svg>',
         'n-Twitch':    'fab fa-twitch',
         'n-E-Mail':    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20" height="20" fill="currentColor"><path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"/></svg>',
         'n-E-Mail':    'fas fa-envelope',
         'n-Support-us': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20" height="20" fill="currentColor"><path d="M47.6 300.4L228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6 0 115.2 0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg>'
         'n-Support-us': 'fas fa-heart'
     };
     };


     $.each(icons, function(id, svg) {
     $.each(icons, function(id, cls) {
         $('#' + id + ' a').html(svg);
         $('#' + id + ' a').html('<i class="' + cls + '"></i>');
     });
     });
});
});
var tagline = document.getElementById('footer-tagline');
if (tagline) {
    var original = tagline.innerHTML;
    var shown = localStorage.getItem('footer_gender_dismissed');
    if (!shown) {
        tagline.innerHTML = 'Aus Gründen der besseren Lesbarkeit wird auf diesem Wiki überwiegend das generische Maskulinum verwendet. Es sind stets alle Geschlechter gleichermaßen gemeint. <button id="footer-gender-dismiss" style="background:none; border:none; cursor:pointer; font-size:0.9em; opacity:0.6; padding:0 4px;" title="Verstanden">✕</button>';
        document.getElementById('footer-gender-dismiss').addEventListener('click', function() {
            tagline.innerHTML = original;
            localStorage.setItem('footer_gender_dismissed', '1');
        });
    }
}
// mw-anon Klasse für nicht angemeldete User setzen
if ( !mw.config.get('wgUserId') ) {
    document.documentElement.classList.add('mw-anon');
}
/**
* Forum-News-Ticker
* ------------------
* Zeigt die neuesten Themen aus einem phpBB-Forum (via Atom-Feed) als
* rotierendes Text-Karussell im Notice-Box-Stil an.
*
* VORAUSSETZUNG: In phpBB muss ACP -> Allgemein -> Feed-Einstellungen
* aktiviert sein, und das Zielforum muss fuer Gaeste lesbar sein.
*
* EINBAU:
* 1. Diesen Code an das Ende von MediaWiki:Common.js anhaengen.
* 2. An der Stelle, wo die News-Box erscheinen soll, folgendes HTML
*    einbauen (z.B. ueber eine Vorlage:NewsTicker):
*
*      <div id="forum-news-ticker" class="mw-message-box mw-message-box-notice"></div>
*
* 3. Konfiguration unten (FEED_URL, MAX_AGE_HOURS, etc.) anpassen.
*/
( function () {
'use strict';
// ---- Konfiguration ----
// Direkter Zugriff auf phpBB scheitert an CORS (andere Subdomain),
// deshalb ueber einen same-origin Proxy auf dem Wiki-Server selbst
// (siehe news-proxy.php).
var FEED_URL = '/wiki/news-proxy.php';
var TARGET_FORUM_ID = '22';
var MAX_AGE_HOURS = 168; // 7 Tage
var MIN_ITEMS = 3; // falls weniger als 7 Tage alt: trotzdem so viele zeigen
var MAX_ITEMS = 5; // wie viele Themen maximal im Karussell landen
var CACHE_MINUTES = 10; // wie lange der Feed lokal zwischengespeichert wird
var ROTATE_MS = 6000; // Anzeigedauer je Eintrag
var CACHE_KEY = 'forumNewsTickerCache_v1';
function getContainer() {
return document.getElementById( 'forum-news-ticker' );
}
function loadFromCache() {
try {
var raw = localStorage.getItem( CACHE_KEY );
if ( !raw ) {
return null;
}
var parsed = JSON.parse( raw );
var ageMinutes = ( Date.now() - parsed.fetchedAt ) / ( 1000 * 60 );
if ( ageMinutes > CACHE_MINUTES ) {
return null;
}
return parsed.items;
} catch ( e ) {
return null;
}
}
function saveToCache( items ) {
try {
localStorage.setItem( CACHE_KEY, JSON.stringify( {
fetchedAt: Date.now(),
items: items
} ) );
} catch ( e ) {
// localStorage evtl. voll oder deaktiviert - einfach ignorieren
}
}
function fetchFeed() {
return fetch( FEED_URL )
.then( function ( response ) {
if ( !response.ok ) {
throw new Error( 'Feed nicht erreichbar: ' + response.status );
}
return response.text();
} )
.then( function ( xmlText ) {
var xml = new DOMParser().parseFromString( xmlText, 'application/xml' );
if ( xml.querySelector( 'parsererror' ) ) {
throw new Error( 'Feed-XML konnte nicht geparst werden' );
}
var now = Date.now();
var entries = Array.prototype.slice.call( xml.querySelectorAll( 'entry' ) );
var items = entries.map( function ( entry ) {
var titleEl = entry.querySelector( 'title' );
var linkEl = entry.querySelector( 'link' );
var updatedEl = entry.querySelector( 'updated' );
var categoryEl = entry.querySelector( 'category' );
// Die Forum-ID steht nicht im Eintrags-Link (der zeigt
// direkt auf viewtopic.php?p=...), sondern im
// scheme-Attribut der <category>.
var forumId = null;
if ( categoryEl && categoryEl.getAttribute( 'scheme' ) ) {
try {
forumId = new URL( categoryEl.getAttribute( 'scheme' ) ).searchParams.get( 'f' );
} catch ( e ) {
forumId = null;
}
}
return {
title: titleEl ? titleEl.textContent : '',
link: linkEl ? linkEl.getAttribute( 'href' ) : '',
updated: updatedEl ? new Date( updatedEl.textContent ) : null,
forumId: forumId
};
} ).filter( function ( item ) {
if ( !item.title || !item.link || !item.updated ) {
return false;
}
// News-Feed kann mehrere in der ACP ausgewaehlte Foren
// mischen, deshalb hier gezielt auf das gewuenschte
// Forum filtern.
return item.forumId === null || item.forumId === TARGET_FORUM_ID;
} );
// Vom Zielforum: erst nach Maximalalter filtern. Wenn das
// weniger als MIN_ITEMS ergibt (z.B. weil im Forum gerade
// wenig los ist), stattdessen die MIN_ITEMS neuesten
// Themen nehmen, auch wenn sie aelter als MAX_AGE_HOURS
// sind - eine leere/einsame Box wirkt sonst kaputt.
var withinAge = items.filter( function ( item ) {
var ageHours = ( now - item.updated.getTime() ) / ( 1000 * 60 * 60 );
return ageHours <= MAX_AGE_HOURS;
} );
var selected = withinAge.length >= MIN_ITEMS ? withinAge : items.slice( 0, MIN_ITEMS );
var finalItems = selected.slice( 0, MAX_ITEMS );
saveToCache( finalItems );
return finalItems;
} );
}
function renderTicker( container, items ) {
if ( !items || items.length === 0 ) {
container.style.display = 'none';
return;
}
container.style.display = '';
container.innerHTML = '';
var slides = items.map( function ( item, index ) {
var slide = document.createElement( 'div' );
slide.className = 'forum-news-ticker-slide' + ( index === 0 ? ' is-active' : '' );
var link = document.createElement( 'a' );
link.href = item.link;
link.textContent = item.title;
link.target = '_blank';
link.rel = 'noopener';
slide.appendChild( link );
container.appendChild( slide );
return slide;
} );
if ( slides.length <= 1 ) {
return;
}
var current = 0;
setInterval( function () {
var next = ( current + 1 ) % slides.length;
slides[ current ].classList.remove( 'is-active' );
slides[ next ].classList.add( 'is-active' );
current = next;
}, ROTATE_MS );
}
function init() {
var container = getContainer();
if ( !container ) {
return;
}
var cached = loadFromCache();
if ( cached ) {
renderTicker( container, cached );
return;
}
fetchFeed()
.then( function ( items ) {
renderTicker( container, items );
} )
.catch( function ( error ) {
// Bei Fehlern (Feed nicht erreichbar etc.) die Box einfach
// ausblenden, statt eine kaputte/leere Box anzuzeigen.
container.style.display = 'none';
if ( window.console && console.warn ) {
console.warn( 'Forum-News-Ticker: ', error );
}
} );
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', init );
} else {
init();
}
}() );

Aktuelle Version vom 29. August 2026, 15:32 Uhr

mw.hook('wikipage.content').add(function($content) {
    const headings = document.querySelectorAll('.citizen-section-heading');
    if (headings.length === 0) return;
    
    const sections = document.querySelectorAll('.citizen-section');
    sections.forEach(function(section, index) {
        if (index === 0) return; // Einleitungstext überspringen
        section.hidden = 'until-found';
    });
});

//Anker aufklappen und Spoiler aufklappen bei Suchen
$(document).ready(function() {
    setTimeout(function() {
        var hash = window.location.hash;
        var ref = document.referrer;
        var searchMatch = ref.match(/[?&]search=([^&]+)/);
        
        // Anker-Link: entsprechenden Abschnitt aufklappen
        if (hash) {
            var target = document.getElementById(hash.substring(1));
            if (target) {
                var h2 = target.closest('h2') ||
                         (target.tagName === 'H2' ? target : null);
                if (!h2) {
                    var section = target.closest('.citizen-section');
                    if (section) h2 = section.previousElementSibling;
                }
                if (h2 && h2.classList.contains('citizen-section-heading')) {
                    var indicator = h2.querySelector('.citizen-section-indicator');
                    if (indicator) indicator.click();
                    setTimeout(function() { target.scrollIntoView(); }, 100);
                }
            }
        }

        // Suche: ersten Abschnitt + verschachtelte Spoiler aufklappen
        if (!searchMatch) return;
        var term = decodeURIComponent(searchMatch[1]).toLowerCase();

        var sections = document.querySelectorAll('.citizen-section');
        for (var i = 0; i < sections.length; i++) {
            if (sections[i].textContent.toLowerCase().includes(term)) {
                var h2 = sections[i].previousElementSibling;
                if (h2 && h2.classList.contains('citizen-section-heading')) {
                    var indicator = h2.querySelector('.citizen-section-indicator');
                    if (indicator) indicator.click();
                }

                // Verschachtelte mw-collapsible aufklappen die den Begriff enthalten
                setTimeout(function(sec) {
                    var collapsibles = sec.querySelectorAll('.mw-collapsible.mw-collapsed');
                    collapsibles.forEach(function(col) {
                        if (col.textContent.toLowerCase().includes(term)) {
                            var toggle = col.querySelector('.mw-collapsible-toggle');
                            if (toggle) toggle.click();
                        }
                    });
                    h2.scrollIntoView();
                }, 200, sections[i]);

                break;
            }
        }
    }, 500);
});
//Hauptseite Grid Ausrichtung
$(document).ready(function() {
    setTimeout(function() {
        document.querySelectorAll('.wiki-overview-grid').forEach(function(grid) {
            var cols = grid.querySelectorAll('.wiki-overview-col');
            var firstHeaders = [];
            cols.forEach(function(col) {
                var h = col.querySelector('h4');
                if (h) firstHeaders.push(h);
            });
            
            // Natürliche Höhen vor minHeight messen
            var naturalHeights = firstHeaders.map(function(h) { return h.offsetHeight; });
            var maxH = Math.max.apply(null, naturalHeights);
            var minH = Math.min.apply(null, naturalHeights);
            
            firstHeaders.forEach(function(h) {
                h.style.minHeight = maxH + 'px';
                h.style.display = 'flex';
                h.style.alignItems = 'flex-end';
                h.style.justifyContent = 'center';
            });

            // Grid um den Leerraum nach oben verschieben
            if (maxH > minH) {
                grid.style.marginTop = '-' + (maxH - minH) + 'px';
            }
        });
    }, 300);
});

// Ausklappen des ersten Abschnitts bei fehlendem Einleitungstext
$(document).ready(function() {
    setTimeout(function() {
        var content = document.querySelector('.mw-parser-output');
        if (!content) return;

        var children = Array.from(content.children);

        // Prüfen ob die erste Section Text enthält (= Einleitungstext)
        var firstSection = children.find(function(el) {
            return el.classList.contains('citizen-section');
        });

        if (firstSection && firstSection.textContent.trim() !== '') return;

        // Erste H2 aufklappen
        var firstH2 = children.find(function(el) {
            return el.tagName === 'H2' && el.classList.contains('citizen-section-heading');
        });

        if (firstH2) {
            var indicator = firstH2.querySelector('.citizen-section-indicator');
            if (indicator) indicator.click();
        }
    }, 500);
});

// Social Icons in Sidebar ersetzen
$(function() {
    $('#n-sidebar-label-contactus').closest('ul').addClass('sgpggb-external-menu');

    var icons = {
        'n-Discord':    'fab fa-discord',
        'n-Facebook':   'fab fa-facebook-f',
        'n-Instagram':  'fab fa-instagram',
        'n-X':          'fab fa-x-twitter',
        'n-YouTube':    'fab fa-youtube',
        'n-Twitch':     'fab fa-twitch',
        'n-E-Mail':     'fas fa-envelope',
        'n-Support-us': 'fas fa-heart'
    };

    $.each(icons, function(id, cls) {
        $('#' + id + ' a').html('<i class="' + cls + '"></i>');
    });
});

var tagline = document.getElementById('footer-tagline');
if (tagline) {
    var original = tagline.innerHTML;
    var shown = localStorage.getItem('footer_gender_dismissed');

    if (!shown) {
        tagline.innerHTML = 'Aus Gründen der besseren Lesbarkeit wird auf diesem Wiki überwiegend das generische Maskulinum verwendet. Es sind stets alle Geschlechter gleichermaßen gemeint. <button id="footer-gender-dismiss" style="background:none; border:none; cursor:pointer; font-size:0.9em; opacity:0.6; padding:0 4px;" title="Verstanden">✕</button>';

        document.getElementById('footer-gender-dismiss').addEventListener('click', function() {
            tagline.innerHTML = original;
            localStorage.setItem('footer_gender_dismissed', '1');
        });
    }
}

// mw-anon Klasse für nicht angemeldete User setzen
if ( !mw.config.get('wgUserId') ) {
    document.documentElement.classList.add('mw-anon');
}


/**
 * Forum-News-Ticker
 * ------------------
 * Zeigt die neuesten Themen aus einem phpBB-Forum (via Atom-Feed) als
 * rotierendes Text-Karussell im Notice-Box-Stil an.
 *
 * VORAUSSETZUNG: In phpBB muss ACP -> Allgemein -> Feed-Einstellungen
 * aktiviert sein, und das Zielforum muss fuer Gaeste lesbar sein.
 *
 * EINBAU:
 * 1. Diesen Code an das Ende von MediaWiki:Common.js anhaengen.
 * 2. An der Stelle, wo die News-Box erscheinen soll, folgendes HTML
 *    einbauen (z.B. ueber eine Vorlage:NewsTicker):
 *
 *      <div id="forum-news-ticker" class="mw-message-box mw-message-box-notice"></div>
 *
 * 3. Konfiguration unten (FEED_URL, MAX_AGE_HOURS, etc.) anpassen.
 */

( function () {
	'use strict';

	// ---- Konfiguration ----
	// Direkter Zugriff auf phpBB scheitert an CORS (andere Subdomain),
	// deshalb ueber einen same-origin Proxy auf dem Wiki-Server selbst
	// (siehe news-proxy.php).
	var FEED_URL = '/wiki/news-proxy.php';
	var TARGET_FORUM_ID = '22';
	var MAX_AGE_HOURS = 168; // 7 Tage
	var MIN_ITEMS = 3; // falls weniger als 7 Tage alt: trotzdem so viele zeigen
	var MAX_ITEMS = 5; // wie viele Themen maximal im Karussell landen
	var CACHE_MINUTES = 10; // wie lange der Feed lokal zwischengespeichert wird
	var ROTATE_MS = 6000; // Anzeigedauer je Eintrag
	var CACHE_KEY = 'forumNewsTickerCache_v1';

	function getContainer() {
		return document.getElementById( 'forum-news-ticker' );
	}

	function loadFromCache() {
		try {
			var raw = localStorage.getItem( CACHE_KEY );
			if ( !raw ) {
				return null;
			}
			var parsed = JSON.parse( raw );
			var ageMinutes = ( Date.now() - parsed.fetchedAt ) / ( 1000 * 60 );
			if ( ageMinutes > CACHE_MINUTES ) {
				return null;
			}
			return parsed.items;
		} catch ( e ) {
			return null;
		}
	}

	function saveToCache( items ) {
		try {
			localStorage.setItem( CACHE_KEY, JSON.stringify( {
				fetchedAt: Date.now(),
				items: items
			} ) );
		} catch ( e ) {
			// localStorage evtl. voll oder deaktiviert - einfach ignorieren
		}
	}

	function fetchFeed() {
		return fetch( FEED_URL )
			.then( function ( response ) {
				if ( !response.ok ) {
					throw new Error( 'Feed nicht erreichbar: ' + response.status );
				}
				return response.text();
			} )
			.then( function ( xmlText ) {
				var xml = new DOMParser().parseFromString( xmlText, 'application/xml' );

				if ( xml.querySelector( 'parsererror' ) ) {
					throw new Error( 'Feed-XML konnte nicht geparst werden' );
				}

				var now = Date.now();
				var entries = Array.prototype.slice.call( xml.querySelectorAll( 'entry' ) );

				var items = entries.map( function ( entry ) {
					var titleEl = entry.querySelector( 'title' );
					var linkEl = entry.querySelector( 'link' );
					var updatedEl = entry.querySelector( 'updated' );
					var categoryEl = entry.querySelector( 'category' );

					// Die Forum-ID steht nicht im Eintrags-Link (der zeigt
					// direkt auf viewtopic.php?p=...), sondern im
					// scheme-Attribut der <category>.
					var forumId = null;
					if ( categoryEl && categoryEl.getAttribute( 'scheme' ) ) {
						try {
							forumId = new URL( categoryEl.getAttribute( 'scheme' ) ).searchParams.get( 'f' );
						} catch ( e ) {
							forumId = null;
						}
					}

					return {
						title: titleEl ? titleEl.textContent : '',
						link: linkEl ? linkEl.getAttribute( 'href' ) : '',
						updated: updatedEl ? new Date( updatedEl.textContent ) : null,
						forumId: forumId
					};
				} ).filter( function ( item ) {
					if ( !item.title || !item.link || !item.updated ) {
						return false;
					}

					// News-Feed kann mehrere in der ACP ausgewaehlte Foren
					// mischen, deshalb hier gezielt auf das gewuenschte
					// Forum filtern.
					return item.forumId === null || item.forumId === TARGET_FORUM_ID;
				} );

				// Vom Zielforum: erst nach Maximalalter filtern. Wenn das
				// weniger als MIN_ITEMS ergibt (z.B. weil im Forum gerade
				// wenig los ist), stattdessen die MIN_ITEMS neuesten
				// Themen nehmen, auch wenn sie aelter als MAX_AGE_HOURS
				// sind - eine leere/einsame Box wirkt sonst kaputt.
				var withinAge = items.filter( function ( item ) {
					var ageHours = ( now - item.updated.getTime() ) / ( 1000 * 60 * 60 );
					return ageHours <= MAX_AGE_HOURS;
				} );

				var selected = withinAge.length >= MIN_ITEMS ? withinAge : items.slice( 0, MIN_ITEMS );
				var finalItems = selected.slice( 0, MAX_ITEMS );

				saveToCache( finalItems );
				return finalItems;
			} );
	}

	function renderTicker( container, items ) {
		if ( !items || items.length === 0 ) {
			container.style.display = 'none';
			return;
		}
		container.style.display = '';
		container.innerHTML = '';

		var slides = items.map( function ( item, index ) {
			var slide = document.createElement( 'div' );
			slide.className = 'forum-news-ticker-slide' + ( index === 0 ? ' is-active' : '' );

			var link = document.createElement( 'a' );
			link.href = item.link;
			link.textContent = item.title;
			link.target = '_blank';
			link.rel = 'noopener';

			slide.appendChild( link );
			container.appendChild( slide );
			return slide;
		} );

		if ( slides.length <= 1 ) {
			return;
		}

		var current = 0;
		setInterval( function () {
			var next = ( current + 1 ) % slides.length;
			slides[ current ].classList.remove( 'is-active' );
			slides[ next ].classList.add( 'is-active' );
			current = next;
		}, ROTATE_MS );
	}

	function init() {
		var container = getContainer();
		if ( !container ) {
			return;
		}

		var cached = loadFromCache();
		if ( cached ) {
			renderTicker( container, cached );
			return;
		}

		fetchFeed()
			.then( function ( items ) {
				renderTicker( container, items );
			} )
			.catch( function ( error ) {
				// Bei Fehlern (Feed nicht erreichbar etc.) die Box einfach
				// ausblenden, statt eine kaputte/leere Box anzuzeigen.
				container.style.display = 'none';
				if ( window.console && console.warn ) {
					console.warn( 'Forum-News-Ticker: ', error );
				}
			} );
	}

	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', init );
	} else {
		init();
	}
}() );