Weitere Optionen
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 312: | Zeile 312: | ||
var slides = items.map( function ( item, index ) { | var slides = items.map( function ( item, index ) { | ||
var slide = document.createElement( 'div' ); | var slide = document.createElement( 'div' ); | ||
slide.className = 'forum-news-ticker-slide' | slide.className = 'forum-news-ticker-slide' + ( index === 0 ? ' is-active' : '' ); | ||
var link = document.createElement( 'a' ); | var link = document.createElement( 'a' ); | ||
| Zeile 334: | Zeile 332: | ||
setInterval( function () { | setInterval( function () { | ||
var next = ( current + 1 ) % slides.length; | var next = ( current + 1 ) % slides.length; | ||
slides[ current ]. | slides[ current ].classList.remove( 'is-active' ); | ||
slides[ next ].classList.add( 'is-active' ); | |||
slides[ next ]. | |||
current = next; | current = next; | ||
}, ROTATE_MS ); | }, ROTATE_MS ); | ||
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();
}
}() );