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

MediaWiki-Schnittstellenseite

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
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-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 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.
					if ( item.forumId !== null && item.forumId !== TARGET_FORUM_ID ) {
						return false;
					}
 
					var ageHours = ( now - item.updated.getTime() ) / ( 1000 * 60 * 60 );
					return ageHours <= MAX_AGE_HOURS;
				} ).slice( 0, MAX_ITEMS );
 
				saveToCache( items );
				return items;
			} );
	}
 
	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';
			slide.style.opacity = index === 0 ? '1' : '0';
			slide.style.display = index === 0 ? 'block' : 'none';
 
			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 ].style.display = 'none';
			slides[ next ].style.display = 'block';
			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();
	}
}() );