MediaWiki:Common.js

Aus quickguide.bitcointoolz.com
Zur Navigation springenZur Suche springen

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
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
console.log('[Common.js] My Common.js is running');



/* Das folgende JavaScript wird für alle Benutzer geladen. */
// Funktion, ob JavaScript geladen wird
//console.log('Common.js wird geladen');
// Funktion, um Benutzergruppen zu erkennen
mw.loader.using('mediawiki.user', function () {
    mw.user.getGroups().done(function (groups) {
        // Überprüfe, ob der Benutzer ein Admin ist (sysop-Gruppe)
        if (groups.indexOf('sysop') === -1) {
            // Verstecke den Link zu den Spezialseiten
            $('a[href*="Special:SpecialPages"]').parent().hide();
            // Verstecke den Link zu den Seiteninformationen
            $('a[href*="Special:PageInformation"]').parent().hide();
            // Verstecke den Link zu Änderungen an verlinkten Seiten
            $('#t-recentchangeslinked').hide();
            // Verstecke den Link zur Druckversion
            $('#t-print').hide();
            // Verstecke den Link zu Links auf diese Seite
            $('#t-whatlinkshere').hide();
            // Verstecke den Link zu den Spezialseiten (deutsch)
            $('a[href*="Spezial:Spezialseiten"]').parent().hide();
            // Verstecke den Link zu den Seiteninformationen (deutsch)
            $('a[href*="Spezial:Seiteninformationen"]').parent().hide();
            // Verstecke den Link zu Änderungen an verlinkten Seiten (deutsch)
            $('a[href*="Spezial:Änderungen an verlinkten Seiten"]').parent().hide();
            // Verstecke den Link zur Druckversion (deutsch)
            $('#t-print').hide();
            // Verstecke den Link zu Links auf diese Seite (deutsch)
            $('a[href*="Spezial:Linkliste"]').parent().hide();
            // Verstecke den Link zum permanenten Link (deutsch)
            $('a[href*="Spezial:Permanenter_Link"]').parent().hide();
            // Verstecke den Link zum permanenten Link (deutsch)
            $('a[href*="oldid"]').parent().hide();
            // Verstecke den Link zu Letzte Änderungen (deutsch)
            $('a[href*="Spezial:Letzte_Änderungen"]').parent().hide();
            $('#n-recentchanges').hide(); // Verstecke den Link zu Letzte Änderungen (ID)
        }
    });
});
// ********************************************************************************************************************

// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

// ********************************************************************************************************************
// *START************************ Fügt den CSS-Code für das schlagende Herz hinzu *************************************

mw.loader.using( 'mediawiki.util', function () {
    var css = '.red-heart {' +
        'color: #FB0000;' +
        'font-size: 17px;' +
        'animation: heartbeat 1.8s infinite ease-in-out;' +
        'display: inline-block;' +
        'vertical-align: middle;' +
    '}' +
    '@keyframes heartbeat {' +
        '0%, 100% {' +
            'transform: scale(0.8) translateY(-1px);' +
            'opacity: 0.5;' +
        '}' +
        '25%, 75% {' +
            'transform: scale(1.0) translateY(-1px);' +
            'opacity: 1;' +
        '}' +
    '}';
var style = document.createElement('style');
    style.type = 'text/css';
    if (style.styleSheet) {
        style.styleSheet.cssText = css;
    } else {
        style.appendChild(document.createTextNode(css));
    }
    document.getElementsByTagName('head')[0].appendChild(style);
});
// *************************************************************
mw.loader.using('mediawiki.util', function () {
    // Erstelle das neue Element für den Text unter dem Logo
    var logoText = document.createElement('div');
    logoText.innerHTML = '<strong>We <span class="red-heart" style="position: relative; top: -3px;">❤️</span><span style="color: #ff5000; font-size: 17px;"> ₿</span>itcoin</strong>'; // Setzt das ₿-Symbol in Orange und größer
    logoText.style.textAlign = 'center';  // Zentriert den Text
    logoText.style.marginTop = '-20px';  // Fügt Abstand zum Logo hinzu
    logoText.style.marginLeft = '-5px';  // Verschiebt den Text 10px nach links
// Füge das Element unter dem Logo hinzu
    var logoContainer = document.getElementById('p-logo');
    if (logoContainer) {
        logoContainer.appendChild(logoText);
    }
});
// *****************************************
mw.loader.using('mediawiki.util', function () {
    // Finde den Container des Logos (#p-logo)
    var logoContainer = document.getElementById('p-logo');
    
    // Wenn das Logo existiert, verschiebe es um 5px nach oben und 10px nach rechts
    if (logoContainer) {
        logoContainer.style.marginTop = '-5px';    // Verschiebt das Logo um -5px nach oben
        logoContainer.style.marginLeft = '5px';   // Verschiebt das Logo um 5px nach rechts
    }
});

// *ENDE************************* Fügt den CSS-Code für das schlagende Herz hinzu *************************************
// ********************************************************************************************************************

// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

// ********************************************************************************************************************
// *START*********************************** ₿-Rakete "To the Moon" ***************************************************


(function($, mw) {
    $(function() {
        // Überprüfen, ob der "Nach oben"-Container bereits existiert
        if ($('#back-to-top-container').length === 0) {
            // Erstelle den Container für den Button und die Animationen
            var $backToTopContainer = $('<div id="back-to-top-container"></div>').css({
                position: 'fixed',     // Fixiert den Container am Bildschirm
                bottom: '20px',        // Abstand vom unteren Bildschirmrand
                right: '20px',         // Abstand vom rechten Bildschirmrand
                width: '50px',         // Breite des Containers
                textAlign: 'center',   // Zentriert den Inhalt horizontal
                zIndex: '1000'         // Platzierung über anderen Elementen
            }).appendTo('body');
            
            // Initialer Text "To the Top"
            var $backToTopText = $('<div id="back-to-top-text">To <br>the<br>Top</div>').css({
                fontSize: '12pt',                               // Schriftgröße des Textes
                color: 'rgba(255, 96, 0, 0.8)',                 // Schriftfarbe mit Transparenz
                backgroundColor: 'rgba(255, 255, 255, 0.8)',    // Hintergrundfarbe mit Transparenz
                padding: '5px',                                 // Innenabstand des Textcontainers
                borderRadius: '15px',                           // Abgerundete Ecken
                marginBottom: '10px',                           // Abstand nach unten
                marginLeft: '-3px',                             // Leichte Verschiebung nach links
                position: 'relative',                           // Relative Positionierung
                zIndex: '1'                                     // Niedriger z-index für die z-Achsen-Ordnung
            }).appendTo($backToTopContainer);
            
            // Bitcoin-Symbol für die Animation
            var $bitcoin = $('<div id="bitcoin">₿</div>').css({
                position: 'absolute',       // Absolute Positionierung für freie Bewegung
                bottom: '75px',             // Startposition von unten
                left: '50%',                // Horizontale Zentrierung
                transform: 'translateX(-50%)', // Korrekte Zentrierung
                fontSize: '28px',           // Schriftgröße
                fontWeight: 'bold',         // Fettschrift
                color: '#FF6000',           // Bitcoin Orange
                opacity: '0',               // Unsichtbar bis zur Animation
                zIndex: '2'                 // Höherer z-index für Vordergrund
            }).appendTo($backToTopContainer);
            
            // Raketen-Symbol für die Animation
            var $rocket = $('<div id="rocket">🚀</div>').css({
                position: 'absolute',       // Absolute Positionierung für freie Bewegung
                bottom: '42px',             // Startposition von unten
                left: '50%',                // Horizontale Zentrierung
                transform: 'translateX(-50%) rotate(-45deg)', // Zentrierung und Drehung
                fontSize: '24px',           // Schriftgröße
                opacity: '0',               // Unsichtbar bis zur Animation
                zIndex: '2'                 // Höherer z-index für Vordergrund
            }).appendTo($backToTopContainer);
            
            // "Nach oben"-Button
            var $backToTopButton = $('<div id="back-to-top">▲</div>').css({
                width: '50px',                              // Breite des Buttons
                height: '50px',                             // Höhe des Buttons
                backgroundColor: 'rgba(255, 96, 0, 0.5)',   // Hintergrundfarbe mit Transparenz
                color: '#fff',                              // Schriftfarbe
                lineHeight: '50px',                         // Vertikale Zentrierung des Pfeils
                fontSize: '22px',                           // Schriftgröße des Pfeils
                fontWeight: 'bold',                         // Schriftart des Pfeils
                borderRadius: '50%',                        // Runde Form
                cursor: 'pointer',                          // Hand-Cursor bei Hover
                opacity: '0.6',                             // Anfangs-Transparenz
                textAlign: 'center',                        // Zentrierung des Pfeils
                position: 'relative',                       // Relative Positionierung
                zIndex: '1'                                 // Gleicher z-index wie der Text
            }).appendTo($backToTopContainer);
    
            // Klick-Ereignis für den Button (scrollt nach oben)
            $backToTopButton.on('click', function() {
                $('html, body').animate({ scrollTop: 0 }, 'slow');
            });
// Variable, um den Animationsstatus zu verfolgen
            var isAnimating = false;
    
            // Hover-Ereignis für den Button
            $backToTopButton.hover(
                function() {
                    $(this).css('opacity', '0.9');
// Prüfen, ob bereits eine Animation läuft
                    if (!isAnimating) {
                        isAnimating = true; // Animation wird gestartet
// Text zu "To the Moon" ändern
                        $backToTopText.fadeOut('slow', function() {
                            $backToTopText.html('„To <br>the<br>Moon!“').fadeIn('slow');
                        });
        
                        // Bitcoin-Symbol animieren
                        $bitcoin.stop(true, true).css({ bottom: '75px', opacity: '1' }).animate(
                            { bottom: '485px', opacity: '0' },
                            3000
                        );
        
                        // Rakete animieren
                        $rocket.stop(true, true).css({ bottom: '42px', opacity: '1' }).animate(
                            { bottom: '360px', opacity: '0' },
                            3000,
                            function() {
                                // Nach Abschluss der Raketenanimation
                                $rocket.css({ bottom: '42px', opacity: '0' });
                                $bitcoin.css({ bottom: '75px', opacity: '0' });
            
                                // Text langsam zurück zu "To the Top" ändern
                                $backToTopText.fadeOut('slow', function() {
                                    $backToTopText.html('To <br>the<br>Top').fadeIn('slow');
                                });
isAnimating = false; // Animation ist beendet
                            }
                        );
                    }
                },
                function() {
                    // Zurücksetzen der Button-Transparenz beim Verlassen des Hover-Effekts
                    $(this).css('opacity', '0.6');
                }
            );
    
            // Button anzeigen
            $backToTopButton.show();
        }
    });
})(jQuery, mediaWiki);

// *ENDE************************************ ₿-Rakete "To the Moon" ***************************************************
// ********************************************************************************************************************

// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

// ********************************************************************************************************************
// *START********************* Script zum täglichen Abruf und Einfügen des Bitcoin-Kurses 2024-10-05 ******************

$(document).ready(function() {
    console.log("Document is ready - Starting Bitcoin price script");

    // Variable zum Zwischenspeichern der zuletzt abgerufenen Bitcoin-Kursdaten
    var cachedBitcoinData = null;
    var lastUpdateTime = null;

    // Funktion zum Abrufen des Bitcoin-Kurses von der CoinGecko API mit Ratenbegrenzung
    function fetchWithRateLimit(url) {
        console.log("[fetchWithRateLimit] URL: ", url);
        const maxRequestsPerMinute = 3;
        if (!window.requestCount) {
            window.requestCount = 0;
        }
        if (!window.requestTimer) {
            window.requestTimer = setInterval(function () {
                window.requestCount = 0; // Reset alle 60 Sekunden
                console.log("[fetchWithRateLimit] Request count reset");
            }, 60000);
        }
        if (window.requestCount >= maxRequestsPerMinute) {
            console.warn("[fetchWithRateLimit] Max requests per minute reached");
            return Promise.reject(new Error('Maximale Anfragenanzahl erreicht. Bitte warten.'));
        }
        window.requestCount++;
        console.log("[fetchWithRateLimit] Request count incremented: ", window.requestCount);
        return fetch(url).then(function(response) {
            console.log("[fetchWithRateLimit] Fetch response status: ", response.status);
            if (!response.ok) {
                throw new Error('Fehler bei der Anfrage: ' + response.statusText);
            }
            return response;
        }).catch(function(error) {
            console.error('[fetchWithRateLimit] Fehler bei der Anfrage:', error);
            throw error; // Fehler weiterreichen, um sicherzustellen, dass sie ordnungsgemäß behandelt werden
        });
    }

    // Funktion zum Abrufen des Bitcoin-Kurses über die CoinGecko-API
    function getBitcoinPrice(callback) {
        console.log("[getBitcoinPrice] Fetching Bitcoin price from CoinGecko...");
        fetchWithRateLimit('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd,eur')
            .then(function(response) {
                console.log("[getBitcoinPrice] Response received");
                if (!response.ok) {
                    if (response.status === 429) {
                        throw new Error('[getBitcoinPrice] Zu viele Anfragen - Bitte versuche es später erneut');
                    } else {
                        throw new Error('[getBitcoinPrice] Netzwerkantwort war nicht ok');
                    }
                }
                return response.json();
            })
            .then(function(data) {
                console.log("[getBitcoinPrice] Response data: ", data);
                if (data && data.bitcoin && typeof data.bitcoin.usd === 'number' && typeof data.bitcoin.eur === 'number') {
                    console.log("[getBitcoinPrice] Bitcoin price successfully fetched");
                    cachedBitcoinData = data;
                    lastUpdateTime = formatTime();
                    callback(null, data);
                } else {
                    throw new Error("[getBitcoinPrice] Unerwartete Datenstruktur von der API");
                }
            })
            .catch(function(error) {
                console.error('[getBitcoinPrice] Fehler beim Abrufen des ₿itcoin-Kurses:', error);
                callback(new Error('[getBitcoinPrice] Abruf fehlgeschlagen'), null);
            });
    }

    // Funktion zum Formatieren der Kurswerte in Euro und Dollar
    function formatCurrency(value, currency) {
        console.log("[formatCurrency] Formatting value: ", value, " Currency: ", currency);
        return value.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' ' + currency;
    }


    // Funktion zum Formatieren von Datum und Zeit
    function formatTime() {
        var now = new Date();
        var year = now.getFullYear();
        var month = (now.getMonth() + 1).toString().padStart(2, '0');
        var day = now.getDate().toString().padStart(2, '0');
        var hours = now.getHours().toString().padStart(2, '0');
        var minutes = now.getMinutes().toString().padStart(2, '0');
        var formattedTime = year + '-' + month + '-' + day + '; ' + hours + ':' + minutes + ' Uhr';
        console.log("[formatTime] Formatted time: ", formattedTime);
        return formattedTime;
    }

    // Funktion zum Setzen des Bitcoin-Kurses im MediaWiki
    function setBitcoinPrice() {
        console.log("[setBitcoinPrice] Setting Bitcoin price...");
        var placeholders = document.querySelectorAll('.bitcoin-price-placeholder');
        if (placeholders.length === 0) {
            console.warn("[setBitcoinPrice] Kein Platzhalter für Bitcoin-Kurs gefunden, Abbruch...");
            return;
        }

        placeholders.forEach(function (placeholder) {
            placeholder.textContent = 'Lade ₿itcoin-Kurs...';
        });

        getBitcoinPrice(function (error, data) {
            if (!error && data && data.bitcoin) {
                var bitcoinPriceUSD = data.bitcoin.usd;
                var bitcoinPriceEUR = data.bitcoin.eur;
                var currentTime = formatTime();

                var formattedPrice = "<strong>₿itcoin-Kurs: $ " + formatCurrency(bitcoinPriceUSD, '') + " = " + formatCurrency(bitcoinPriceEUR, '€') + "</strong>";
                formattedPrice += "<br><span style=\"font-size:10px; color: #555555;\">(Stand: " + currentTime + " von <a href='https://www.coingecko.com/' target='_blank' style='color:black;'>CoinGecko</a>; ohne Gewähr)</span>";

                placeholders.forEach(function (placeholder) {
                    placeholder.innerHTML = formattedPrice;
                });
            } else {
                console.error("[setBitcoinPrice] Fehler beim Abrufen des Bitcoin-Kurses, Daten nicht verfügbar");
                placeholders.forEach(function (placeholder) {
                    placeholder.textContent = 'Fehler beim Abrufen des ₿itcoin-Kurses. Bitte später erneut versuchen.';
                });
            }
        });
    }

    // Funktion zum Starten des täglichen Updates des Bitcoin-Kurses
    function startDailyBitcoinUpdate() {
        console.log("[startDailyBitcoinUpdate] Starting daily Bitcoin update...");
        setBitcoinPrice();

        var now = new Date();
        var nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0);
        var timeToMidnight = nextMidnight - now;

        console.log("[startDailyBitcoinUpdate] Time to midnight: ", timeToMidnight);

        setTimeout(function () {
            console.log("[startDailyBitcoinUpdate] Updating Bitcoin price at midnight...");
            setBitcoinPrice();
            setInterval(setBitcoinPrice, 24 * 60 * 60 * 1000);
        }, timeToMidnight);
    }

    // Funktion zum Anzeigen des Bitcoin-Kurses als Tooltip beim Überfahren des Logos
    function addTooltipForLogo() {
        function applyTooltipStyles() {
            var tooltip = document.getElementById('bitcoin-price-tooltip');
            if (tooltip) {
                tooltip.style.position = 'absolute';
                tooltip.style.display = 'none';
                tooltip.style.border = '1px solid black';
                tooltip.style.backgroundColor = '#696969';
                tooltip.style.borderRadius = '5%';
                tooltip.style.padding = '10px';
                tooltip.style.color = 'white';
                tooltip.style.zIndex = '1000';
                tooltip.style.pointerEvents = 'none';
                console.log("[applyTooltipStyles] Tooltip styles applied");
            }
        }

        var logoElement = document.querySelector('#p-logo a, #p-logo img');
        if (!logoElement) {
            console.error('[addTooltipForLogo] Logo-Element nicht gefunden.');
            return;
        }

        var tooltip = document.createElement('div');
        tooltip.id = 'bitcoin-price-tooltip';
        tooltip.className = 'bitcoin-tooltip';
        document.body.appendChild(tooltip);
        applyTooltipStyles();

        logoElement.addEventListener('mouseenter', function(event) {
            console.log("[addTooltipForLogo] Mouse entered logo");
            if (cachedBitcoinData) {
                updateTooltipContent(event, cachedBitcoinData);
                tooltip.style.display = 'block';
            } else {
                getBitcoinPrice(function (error, data) {
                    if (!error && data) {
                        updateTooltipContent(event, data);
                        tooltip.style.display = 'block';
                    }
                });
            }
        });

        logoElement.addEventListener('mousemove', function(event) {
            tooltip.style.left = (event.pageX + 10) + 'px';
            tooltip.style.top = (event.pageY + 10) + 'px';
            console.log("[addTooltipForLogo] Tooltip position updated");
        });

        logoElement.addEventListener('mouseleave', function() {
            console.log("[addTooltipForLogo] Mouse left logo");
            tooltip.style.display = 'none';
        });

        function updateTooltipContent(event, data) {
            var bitcoinPriceUSD = data.bitcoin.usd;
            var bitcoinPriceEUR = data.bitcoin.eur;
            var tooltipContent = "<div style='text-align:center;'>" +
                "<span style='font-size:18px; font-weight:bold;'>₿itcoin-Kurs:&nbsp;$&nbsp;</span>" +
                "<span style='font-size:18px; color:orange;'>" + bitcoinPriceUSD.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + "</span>" +
                "<span style='font-size:18px; color:white; padding: 0 5px;'> = </span>" +
                "<span style='font-size:18px; color:orange;'>" + bitcoinPriceEUR.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + "</span>" +
                "<span style='font-size:18px; font-weight:bold;'>&nbsp;€&nbsp;</span></div>" +
                "<br><div style='font-size:10px; text-align:right;'>(Stand: " + lastUpdateTime + " von <a href='https://www.coingecko.com/' target='_blank' style='color:black;'>CoinGecko</a>; ohne Gewähr)</div>";
            tooltip.innerHTML = tooltipContent;
            tooltip.style.left = (event.pageX + 10) + 'px';
            tooltip.style.top = (event.pageY + 10) + 'px';
            console.log("[updateTooltipContent] Tooltip content updated");
        }
    }

    // Starte das tägliche Update, um den Bitcoin-Kurs automatisch zu aktualisieren
    startDailyBitcoinUpdate();
    // Füge die Tooltip-Funktionalität zum Logo hinzu
    addTooltipForLogo();
});

// *ENDE********************* Script zum täglichen Abruf und Einfügen des Bitcoin-Kurses 2024-10-05 *******************
// ********************************************************************************************************************

// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

// ********************************************************************************************************************
// *START************************** Übersetzungen mit Google-API OHNE iframe-Einbindungen *****************************
// ********************************************************************************************************************

// Google API Übersetzung Dropdown mit Benutzerspracheinstellungen
var selectImportant, selectAll;

// Funktion zur Erstellung der Dropdown-Menüs für wichtige und alle weiteren Sprachen
function createTranslateDropdowns() {
    // Container für die Dropdown-Menüs erstellen
    var container = document.createElement('div');
    container.id = 'translate_container';
    container.style.position = 'fixed'; // Fixierte Position, damit der Container immer sichtbar bleibt
    container.style.top = '5px'; // Abstand vom oberen Rand des Fensters
    container.style.left = '0px'; // Abstand vom linken Rand des Fensters
    container.style.width = '95%'; // Passt die Breite des Containers an, um auf mobilen Geräten sichtbar zu sein
    container.style.maxWidth = '380px'; // Maximale Breite für größere Bildschirme
    container.style.height = 'auto'; // Höhe wird automatisch basierend auf dem Inhalt angepasst
    container.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; // Halbtransparente Hintergrundfarbe für bessere Lesbarkeit
    container.style.border = '1px solid #aaa'; // Rahmen um den Container in hellem Grau (#aaa)
    container.style.padding = '5px'; // Innenabstand innerhalb des Containers (5px auf allen Seiten)
    container.style.zIndex = '1000'; // Stellt sicher, dass der Container über anderen Elementen auf der Seite liegt
    container.style.display = 'flex'; // Flexbox für einfaches Layout der Dropdown-Elemente
    container.style.flexDirection = 'row'; // Elemente im Container werden horizontal nebeneinander angezeigt
    container.style.flexWrap = 'wrap'; // Wenn die Breite nicht ausreicht, werden die Elemente umgebrochen
    container.style.justifyContent = 'space-between'; // Die Dropdowns werden mit gleichem Abstand dazwischen verteilt
    document.body.appendChild(container);

    // Wrapper für die wichtigen Sprachen erstellen
    var importantWrapper = document.createElement('div');
    importantWrapper.style.display = 'inline-block';
    importantWrapper.style.marginBottom = '0px'; // Kein Abstand nach unten

    // Label für wichtige Sprachen erstellen
    var importantLabel = document.createElement('label');
    importantLabel.textContent = 'Translate to:'; // Beschriftung für das Dropdown-Menü
    importantLabel.classList.add('no-translate'); // Klasse, damit das Label nicht übersetzt wird
    importantLabel.style.fontWeight = 'bold'; // Fettschrift für bessere Lesbarkeit
    importantLabel.style.marginRight = '2px'; // Abstand zwischen Label und Dropdown
    importantLabel.style.fontSize = '0.8em';
    importantLabel.style.fontFamily = 'Arial, sans-serif';
    importantWrapper.appendChild(importantLabel);

    // Dropdown für wichtige Sprachen erstellen
    selectImportant = createDropdown('important_languages', 'Main Languages', getImportantLanguages());
    selectImportant.style.width = '100px'; // Breite des Dropdowns
    selectImportant.style.padding = '2px'; // Innenabstand innerhalb des Dropdowns
    selectImportant.style.marginRight = '2px'; // Abstand zwischen Dropdown und weiteren Elementen
    selectImportant.style.borderRadius = '1px'; // Leichte Abrundung der Ecken
    selectImportant.style.fontFamily = 'Arial, sans-serif';
    selectImportant.style.fontSize = '0.8em';
    importantWrapper.appendChild(selectImportant);

    container.appendChild(importantWrapper);

    // Wrapper für alle Sprachen erstellen
    var allWrapper = document.createElement('div');
    allWrapper.style.display = 'inline-block';
    allWrapper.style.marginLeft = '5px'; // Abstand links zwischen dem Wrapper und anderen Elementen
    allWrapper.style.marginBottom = '0px'; // Kein Abstand nach unten

    // Label für alle Sprachen erstellen
    var allLabel = document.createElement('label');
    allLabel.textContent = 'All:'; // Beschriftung für das Dropdown-Menü
    allLabel.classList.add('no-translate'); // Klasse, damit das Label nicht übersetzt wird
    allLabel.style.fontWeight = 'bold'; // Fettschrift für bessere Lesbarkeit
    allLabel.style.marginRight = '2px'; // Abstand zwischen Label und Dropdown
    allLabel.style.fontSize = '0.8em';
    allLabel.style.fontFamily = 'Arial, sans-serif';
    allWrapper.appendChild(allLabel);

    // Dropdown für alle Sprachen erstellen
    selectAll = createDropdown('all_languages', 'Select Of All', getAllLanguages());
    selectAll.style.width = '115px'; // Breite des Dropdowns
    selectAll.style.padding = '2px'; // Innenabstand innerhalb des Dropdowns
    selectAll.style.marginRight = '4px'; // Abstand rechts vom Dropdown zum nächsten Element
    selectAll.style.borderRadius = '2px'; // Leichte Abrundung der Ecken
    selectAll.style.fontFamily = 'Arial, sans-serif';
    selectAll.style.fontSize = '0.8em';
    allWrapper.appendChild(selectAll);

    container.appendChild(allWrapper);

    // Event Listener für Sprachänderungen hinzufügen
    selectImportant.addEventListener('change', function () {
        if (selectImportant.value !== 'de') {
            handleLanguageChange(selectImportant.value)
                .then(function() {
                    localStorage.setItem('selectedLanguage', selectImportant.value); // Speichert die ausgewählte Sprache lokal
                    syncDropdowns(selectImportant.value); // Synchronisiert die Dropdowns
                })
                .catch(function(error) {
                    console.error("[selectImportant] Fehler bei der Sprachänderung: ", error);
                });
        } else {
            resetToDefaultLanguage(); // Setzt die Sprache auf Deutsch zurück, wenn 'de' ausgewählt ist
        }
    });

    selectAll.addEventListener('change', function () {
        if (selectAll.value !== 'de') {
            handleLanguageChange(selectAll.value)
                .then(function() {
                    localStorage.setItem('selectedLanguage', selectAll.value); // Speichert die ausgewählte Sprache lokal
                    syncDropdowns(selectAll.value); // Synchronisiert die Dropdowns
                })
                .catch(function(error) {
                    console.error("[selectAll] Fehler bei der Sprachänderung: ", error);
                });
        } else {
            resetToDefaultLanguage(); // Setzt die Sprache auf Deutsch zurück, wenn 'de' ausgewählt ist
        }
    });
}

// Erstellt ein Dropdown-Menü
function createDropdown(id, placeholderText, languages) {
    var select = document.createElement('select');
    select.id = id;
    select.style.padding = '2px'; // Innenabstand des Dropdowns
    select.style.marginRight = '4px'; // Abstand rechts vom Dropdown, um Platz zwischen Elementen zu schaffen
    select.style.borderRadius = '0'; // Keine abgerundeten Ecken, um das Dropdown rechteckig zu halten
    select.style.fontFamily = 'Arial, sans-serif'; // Konsistente Schriftart
    select.style.fontSize = '0.8em'; // Schriftgröße reduziert für ein kompakteres Layout

    // Platzhalteroption erstellen
    var placeholderOption = document.createElement('option');
    placeholderOption.value = '';
    placeholderOption.textContent = placeholderText; // Platzhaltertext, der angezeigt wird, bevor eine Auswahl getroffen wird
    placeholderOption.disabled = true; // Platzhalteroption kann nicht ausgewählt werden
    placeholderOption.selected = true; // Platzhalter ist standardmäßig ausgewählt
    select.appendChild(placeholderOption);

    // Optionen für Sprachen hinzufügen
    for (var i = 0; i < languages.length; i++) {
        var lang = languages[i];
        var option = document.createElement('option');
        option.value = lang.lang;
        option.textContent = lang.name; // Name der Sprache, die im Dropdown angezeigt wird
        option.style.fontFamily = 'Arial, sans-serif';
        option.style.fontSize = '1.0em';
        select.appendChild(option);
    }

    return select;
}

// Wichtige Sprachen - Rückgabe einer Liste der wichtigsten Sprachen
function getImportantLanguages() {
    return [
        { lang: 'de', name: '⟶ German (orig.)' },
        { lang: 'en', name: 'English' },
        { lang: 'es', name: 'Spanish' },
        { lang: 'zh-CN', name: 'Chinese (Simp.)' },
        { lang: 'fr', name: 'French' },
        { lang: 'pt', name: 'Portuguese' },
        { lang: 'ru', name: 'Russian' },
        { lang: 'ja', name: 'Japanese' },
        { lang: 'ko', name: 'Korean' },
        { lang: 'it', name: 'Italian' }
    ];
}

// Alle Sprachen - Rückgabe einer Liste aller unterstützten Sprachen
function getAllLanguages() {
    return [
        { lang: 'af', name: 'Afrikaans' }, { lang: 'am', name: 'Amharic' }, { lang: 'ar', name: 'Arabic' },
        { lang: 'az', name: 'Azerbaijani' }, { lang: 'be', name: 'Belarusian' }, { lang: 'bg', name: 'Bulgarian' },
        { lang: 'bn', name: 'Bengali' }, { lang: 'bs', name: 'Bosnian' }, { lang: 'ca', name: 'Catalan' },
        { lang: 'zh-CN', name: 'Chinese (Simp.)' }, { lang: 'zh-TW', name: 'Chinese (Trad.)' },
        { lang: 'hr', name: 'Croatian' }, { lang: 'cs', name: 'Czech' }, { lang: 'da', name: 'Danish' },
        { lang: 'nl', name: 'Dutch' }, { lang: 'en', name: 'English' }, { lang: 'et', name: 'Estonian' },
        { lang: 'tl', name: 'Filipino' }, { lang: 'fi', name: 'Finnish' }, { lang: 'fr', name: 'French' },
        { lang: 'de', name: '⟶ German (orig.)' }, { lang: 'el', name: 'Greek' }, { lang: 'gu', name: 'Gujarati' },
        { lang: 'he', name: 'Hebrew' }, { lang: 'hi', name: 'Hindi' }, { lang: 'hu', name: 'Hungarian' },
        { lang: 'is', name: 'Icelandic' }, { lang: 'id', name: 'Indonesian' }, { lang: 'it', name: 'Italian' },
        { lang: 'ja', name: 'Japanese' }, { lang: 'kn', name: 'Kannada' }, { lang: 'ko', name: 'Korean' },
        { lang: 'lv', name: 'Latvian' }, { lang: 'lt', name: 'Lithuanian' }, { lang: 'ms', name: 'Malay' },
        { lang: 'ml', name: 'Malayalam' }, { lang: 'mr', name: 'Marathi' }, { lang: 'ne', name: 'Nepali' },
        { lang: 'no', name: 'Norwegian' }, { lang: 'fa', name: 'Persian' }, { lang: 'pl', name: 'Polish' },
        { lang: 'pt', name: 'Portuguese' }, { lang: 'pa', name: 'Punjabi' }, { lang: 'ro', name: 'Romanian' },
        { lang: 'ru', name: 'Russian' }, { lang: 'sr', name: 'Serbian' }, { lang: 'sk', name: 'Slovak' },
        { lang: 'sl', name: 'Slovenian' }, { lang: 'es', name: 'Spanish' }, { lang: 'sw', name: 'Swahili' },
        { lang: 'sv', name: 'Swedish' }, { lang: 'ta', name: 'Tamil' }, { lang: 'te', name: 'Telugu' },
        { lang: 'th', name: 'Thai' }, { lang: 'tr', name: 'Turkish' }, { lang: 'uk', name: 'Ukrainian' },
        { lang: 'ur', name: 'Urdu' }, { lang: 'vi', name: 'Vietnamese' }, { lang: 'cy', name: 'Welsh' },
        { lang: 'zu', name: 'Zulu' }
    ];
}

// Sprachänderungsfunktion mit Google Translate API
function handleLanguageChange(selectedLang) {
    return new Promise(function(resolve, reject) {
        var googleTranslateApiUrl = "https://translation.googleapis.com/language/translate/v2";
        var apiKey = "AIzaSyBe4xJokSKneAvA_7_aaU984vS2R8gSFtM";

        if (selectedLang !== "" && selectedLang !== "de") {
            var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
            var nodes = [];
            var node;
            // Durchlaufen aller Textknoten im Dokument
            while ((node = walker.nextNode())) {
                if (node.nodeValue.trim() !== "") {
                    nodes.push(node); // Füge alle Textknoten hinzu, die nicht leer sind
                }
            }

            var maxTextLength = 500; // Maximal erlaubte Textlänge für eine Anfrage
            var textGroups = [];
            var currentGroup = [];
            var currentLength = 0;

            // Gruppiere die Textknoten basierend auf der maximalen Textlänge
            nodes.forEach(function (textNode) {
                if (currentLength + textNode.nodeValue.length > maxTextLength) {
                    textGroups.push(currentGroup);
                    currentGroup = [];
                    currentLength = 0;
                }
                currentGroup.push(textNode);
                currentLength += textNode.nodeValue.length;
            });
            if (currentGroup.length > 0) {
                textGroups.push(currentGroup);
            }

            // Sende jede Textgruppe zur Übersetzung
            var groupPromises = textGroups.map(function (group) {
                var textToTranslateArray = group.map(function (textNode) {
                    return textNode.nodeValue;
                });

                return fetch(googleTranslateApiUrl + "?key=" + apiKey, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        q: textToTranslateArray,
                        source: "de",
                        target: selectedLang,
                        format: "text"
                    })
                }).then(function (response) {
                    if (!response.ok) {
                        throw new Error("Netzwerkantwort war nicht ok");
                    }
                    return response.json();
                }).then(function (data) {
                    if (data.data && data.data.translations) {
                        for (var i = 0; i < data.data.translations.length; i++) {
                            group[i].nodeValue = " " + data.data.translations[i].translatedText + " "; // Leerzeichen erhalten
                        }
                        console.log("Übersetzung erfolgreich");
                    } else {
                        throw new Error("Fehlerhafte Antwort von der Übersetzungs-API");
                    }
                });
            });

            Promise.all(groupPromises).then(function() {
                resolve();
            }).catch(function (error) {
                console.error("Fehler bei der Übersetzung: ", error);
                reject(error);
            });
        } else {
            resolve();
        }
    });
}

// Setzt die Sprache zurück auf die Standardsprache Deutsch
function resetToDefaultLanguage() {
    localStorage.removeItem('selectedLanguage'); // Entfernt die gespeicherte Sprache
    window.location.reload(); // Lädt die Seite neu, um die Standard-Sprache anzuwenden
}

// Synchronisiert beide Dropdowns
function syncDropdowns(selectedLang) {
    if (selectImportant) selectImportant.value = selectedLang;
    if (selectAll) selectAll.value = selectedLang;
}

// Google Translate Script laden und Dropdown-Menü erstellen
function initializeTranslationFeature() {
    createTranslateDropdowns(); // Erstellt die Dropdown-Menüs
    var savedLanguage = localStorage.getItem('selectedLanguage'); // Holt die gespeicherte Sprache
    if (savedLanguage && savedLanguage !== 'de') {
        handleLanguageChange(savedLanguage).then(function() {
            syncDropdowns(savedLanguage); // Synchronisiert die Dropdowns
        }).catch(function(error) {
            console.error("[initializeTranslationFeature] Fehler bei der Sprachänderung: ", error);
        });
    } else {
        syncDropdowns('de'); // Setzt die Dropdowns auf die Standardsprache
    }
}

// Document ready
$(document).ready(function () {
    document.body.style.paddingTop = '75px'; // Abstand vom oberen Rand der Seite, um sicherzustellen, dass der Inhalt nicht überlagert wird
    initializeTranslationFeature(); // Initialisiert die Übersetzungsfunktion
});


// *ENDE*************************** Übersetzungen mit Google-API OHNE iframe-Einbindungen *****************************
// ********************************************************************************************************************

// ********************************************************************************************************************
// *START********************* Script zum dynamischen Aufbau des E-Mail-Share-Links 2025-05-28 *********************
mw.loader.using('mediawiki.util', function() {
  $(function(){
    var title   = mw.config.get('wgTitle'),
        page    = mw.config.get('wgPageName'),
        server  = mw.config.get('wgServer'),
        script  = mw.config.get('wgScriptPath'),
        fullUrl = server + script + '/index.php?title=' + encodeURIComponent(page),
        subject = encodeURIComponent(
                    'Entdecke den tollen Bitcoin-Wiki-Artikel zum Thema »' + title + '«'
                  ),
        body    = encodeURIComponent(
                    'Hey, du Krypto-Fan! Entdecke jetzt den tollen Bitcoin-Wiki-Artikel zum Thema »'
                      + title
                      + '« unter '
                      + fullUrl
                  ),
        mailto  = 'mailto:info@example.org?subject=' + subject + '&body=' + body,
        link    = '<a href="' + mailto + '">Jetzt per E-Mail teilen✉</a>';

    $('#share-email-placeholder').html(link);
  });
});
// *ENDE********************* Script zum dynamischen Aufbau des E-Mail-Share-Links 2025-05-28 *******************
// ********************************************************************************************************************



/**
 * Unmined-Bitcoin-Skript für MediaWiki:Common.js
 *
 * Dieses Skript holt alle fünf Minuten die aktuelle Anzahl der bereits geminten Bitcoins von der CoinGecko-API (serverseitig via PHP-Proxy)
 * ab, berechnet daraus die verbleibende Anzahl bis zur Obergrenze von 21 000 000, formatiert das Ergebnis in deutscher Schreibweise
 * mit Punkten als Tausender-Trennzeichen und gibt es in einem DIV-Container im Wiki-Artikel aus.
 *
 * Ablauf:
 * 1. Sobald der DOM fertig geladen ist (jQuery(document).ready), wird geprüft, ob der DIV-Container mit der ID "unmined-btc-widget" existiert.
 *    Ist der Container nicht vorhanden, bricht das Skript ab.
 *
 * 2. Über die Funktion fetchRemainingBTC() wird via jQuery.ajax eine JSON-Anfrage an den PHP-Proxy auf Deinem Server gestellt:
 *    URL: https://test.toepperwien.de/unmined_bitcoin/unmined_btc.php
 *
 *    Der PHP-Proxy:
 *      • Ruft serverseitig die CoinGecko-API ab (https://api.coingecko.com/api/v3/coins/bitcoin).
 *      • Berechnet auf dem Server den verbleibenden Bitcoin-Betrag (21 000 000 − circulating_supply) und gibt ein JSON zurück:
 *        {
 *          "circulating_supply": 19xxxxxx,
 *          "remaining": 1xxxxxx
 *        }
 *      • Setzt in der HTTP-Antwort zwingend den Header Access-Control-Allow-Origin: *,
 *        damit der Browser keine CORS-Fehler wirft.
 *
 * 3. Im success-Callback von jQuery.ajax wird das zurückgelieferte JSON geparst. Falls das JSON ein Feld "error" enthält, wird
 *    „Fehler: <Fehlermeldung>“ ins DIV geschrieben. Andernfalls werden die Felder "circulating_supply" und "remaining" ausgelesen.
 *    Der Wert „remaining“ wird dann in deutscher Tausender-Notation formatiert und in das DIV geschrieben als:
 *      Noch <formatted> Bitcoin
 *
 * 4. Sollte die AJAX-Anfrage (z. B. beim Netzwerkausfall) scheitern, wird im error-Callback „Fehler beim Laden“ angezeigt.
 *
 * 5. Direkt nach DOM-ready wird im DIV zunächst „Lade Daten…“ angezeigt, dann der erste Aufruf von fetchRemainingBTC() durchgeführt.
 *    Mit setInterval(fetchRemainingBTC, 10 * 60 * 1000) wird das Skript alle 10 Minuten (300 000 ms) erneut ausgeführt.
 */

jQuery(function () {
    // Debug: Prüfen, ob Common.js geladen wird
    console.log('[UnminedBTC] Starting fetch script');

    // 1) Container per jQuery abrufen
    //    Dieser DIV muss im Artikel stehen: <div id="unmined-btc-widget">Lade Daten…</div>
    var $container = jQuery('#unmined-btc-widget');
    if ($container.length === 0) {
        // Falls das DIV nicht existiert, brechen wir ab
        console.warn('[UnminedBTC] Kein Container #unmined-btc-widget gefunden, Abbruch.');
        return;
    }

    // 2) Konstanten: Maximale Gesamtmenge aller Bitcoins
    var TOTAL_SUPPLY = 21000000;

    /**
     * formatThousand(num)
     *
     * Formatiert eine Zahl in deutsche Tausender-Notation mit Punkten als Trennzeichen.
     * Beispiel: 2500000 → "2.500.000"
     *
     * @param {number} num - Die zu formatierende Zahl (wird auf ganze Zahl abgerundet).
     * @return {string}   - Die formatierte Zahl als String mit Punkt-Trennungen.
     */
    function formatThousand(num) {
        // Ganzzahl-String erzeugen
        var s = Math.floor(num).toString();
        var parts = [];
        var rest = s;

        // Solange mehr als drei Ziffern übrig sind, letzten drei Ziffern extrahieren
        while (rest.length > 3) {
            var idx = rest.length - 3;
            parts.unshift(rest.slice(idx));   // Letzte 3 Ziffern ins Array vorne einfügen
            rest = rest.slice(0, idx);        // Rest ohne die letzten 3 Ziffern
        }
        parts.unshift(rest);  // Übrigen Teil (1–3 Ziffern) ebenfalls ins Array einfügen

        // Array mit Punkten verbinden, z. B. ["1", "126", "085"] → "1.126.085"
        return parts.join('.');
    }

    /**
     * fetchRemainingBTC()
     *
     * Ruft per AJAX den eigenen PHP-Proxy auf, der serverseitig die CoinGecko-API
     * abfragt und die verbleibenden Bitcoins bis 21 000 000 berechnet. Anschließend
     * wird das Ergebnis ins DIV-Element (ID "unmined-btc-widget") geschrieben.
     *
     * Der PHP-Proxy liefert ein JSON-Objekt in folgender Struktur:
     * {
     *   "circulating_supply": <Number>,
     *   "remaining": <Number>
     * }
     *
     * Oder bei Fehlern:
     * {
     *   "error": "<Fehlermeldung>"
     * }
     */
    function fetchRemainingBTC() {
        // 4a) URL zu deinem PHP-Proxy auf deinem Server
        //     Der Proxy muss CORS erlauben (Access-Control-Allow-Origin: *) und gibt JSON zurück.
        var url = 'https://test.toepperwien.de/unmined_bitcoin/unmined_btc.php';
        console.log('[UnminedBTC] AJAX-Request an URL:', url);

        // 4b) AJAX-Aufruf mit jQuery.ajax (ES5)
        jQuery.ajax({
            url: url,
            dataType: 'json',   // Erwartet JSON-Antwort
            timeout: 5000,      // Timeout nach 5 Sekunden
            success: function (data) {
                console.log('[UnminedBTC] AJAX success, rohes JSON:', data);

                // 4c) Prüfen, ob der Proxy einen Fehler zurückliefert
                if (data.error) {
                    console.error('[UnminedBTC] PHP-Proxy-Fehler:', data.error);
                    // Zeige Fehlermeldung im DIV an
                    $container.text('Fehler: ' + data.error);
                    return;
                }

                // 4d) Auslesen von remaining und circulating_supply
                var remaining = data.remaining;
                var circ = data.circulating_supply;
                console.log('[UnminedBTC] circulating_supply:', circ, 'remaining:', remaining);

                // 4e) Validierung: remaining muss eine Zahl sein
                if (typeof remaining !== 'number' || isNaN(remaining)) {
                    $container.text('Fehler: ungültige Daten');
                    return;
                }

                // 4f) Ausgabe im DIV: "<formatted> Bitcoin"
                //     Beispiel: "Noch 1.126.085 Bitcoin"
                var formatted = formatThousand(remaining);
                $container.text(formatted);
            },
            error: function (xhr, status, error) {
                console.error('[UnminedBTC] AJAX-Fehler:', status, error);
                // Zeige generische Fehlermeldung im DIV
                $container.text('Fehler beim Laden');
            }
        });
    }

    // 5) Initialisierung: Zuerst "Lade Daten…" ins DIV schreiben
    $container.text('Lade Daten…');
    // 5a) Ersten Abruf sofort starten
    fetchRemainingBTC();
    // 5b) Alle 10 Minuten (10 * 60 * 1000 ms) erneut abrufen
    setInterval(fetchRemainingBTC, 10 * 60 * 1000);
});



// --------------------------------------------------------------------------------------------------------------------

/* Anonymer Song-Zähler + Cover-Play (ohne Cookies/PII) */
(function () {
  function ajaxGET(url, done) {
    try {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          var ok = (xhr.status >= 200 && xhr.status < 300);
          done(ok, ok ? xhr.responseText : null);
        }
      };
      xhr.send(null);
    } catch (e) { done(false, null); }
  }

  function initSongBlocks() {
    var wrappers = document.querySelectorAll ? document.querySelectorAll('.wiki-song') : [];
    var playedOnce = window.__wikiSongPlayedOnce || (window.__wikiSongPlayedOnce = {});

    for (var i = 0; i < wrappers.length; i++) {
      (function (wrap) {
        var id = wrap.getAttribute('data-song-id') || '';
        var audio = wrap.querySelector ? wrap.querySelector('.wiki-song-audio') : null;
        var countEl = wrap.querySelector ? wrap.querySelector('[data-song-count]') : null;
        var coverBtn = wrap.querySelector ? wrap.querySelector('.wiki-song-cover-play') : null;

        // 1) aktuellen Zählerstand laden
        if (id && countEl) {
          ajaxGET('/audio/count.php?song=' + encodeURIComponent(id), function (ok, text) {
            if (!ok || !text) { return; }
            try {
              var ob = JSON.parse(text);
              if (ob && typeof ob.plays === 'number') { countEl.textContent = String(ob.plays); }
            } catch (e) {}
          });
        }

        // 2) einmalig bumpen beim ersten Play
        if (id && audio) {
          audio.addEventListener('play', function () {
            wrap.classList && wrap.classList.add('is-playing');
            if (!playedOnce[id]) {
              playedOnce[id] = true;
              ajaxGET('/audio/bump.php?song=' + encodeURIComponent(id), function () {});
              if (countEl) {
                var n = parseInt(countEl.textContent, 10);
                if (!isNaN(n)) { countEl.textContent = String(n + 1); }
              }
            }
          }, false);
          audio.addEventListener('pause', function () { wrap.classList && wrap.classList.remove('is-playing'); }, false);
          audio.addEventListener('ended', function () { wrap.classList && wrap.classList.remove('is-playing'); }, false);
        }

        // 3) Cover-Button steuert Play/Pause
        if (coverBtn && audio) {
          coverBtn.addEventListener('click', function () {
            try {
              if (audio.paused) { audio.play(); } else { audio.pause(); }
            } catch (e) {}
          }, false);
        }
      })(wrappers[i]);
    }
  }

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

/* Inline-Anzeige der Song-Aufrufe hinter "Wiki-Song" */
(function () {
  function ajaxGET(url, done) {
    try {
      var x = new XMLHttpRequest();
      x.open('GET', url, true);
      x.onreadystatechange = function(){ if (x.readyState === 4) done(x.status>=200&&x.status<300, x.responseText); };
      x.send(null);
    } catch (e) { done(false, null); }
  }

  function updateInlineCounts() {
    var nodes = document.querySelectorAll ? document.querySelectorAll('.wiki-song-inline-count') : [];
    if (!nodes.length) return;

    // ggf. mehrere IDs auf einer Seite unterstützen
    var byId = {};
    for (var i=0;i<nodes.length;i++) {
      var id = nodes[i].getAttribute('data-song-id') || '';
      if (!id) continue;
      (byId[id] = byId[id] || []).push(nodes[i]);
    }

    for (var id in byId) if (byId.hasOwnProperty(id)) {
      (function(songId, targets){
        ajaxGET('/audio/count.php?song=' + encodeURIComponent(songId), function(ok, text){
          var n = 0;
          if (ok && text) { try { var ob = JSON.parse(text); if (ob && typeof ob.plays === 'number') n = ob.plays|0; } catch(e){} }
          for (var j = 0; j < targets.length; j++) {
            var el = targets[j].querySelector ? targets[j].querySelector('.count') : null;
            if (el) {
              el.textContent = String(n);              // nur die Zahl austauschen
            } else {
              // Fallback, falls mal kein .count drin ist:
              targets[j].innerHTML = '<em>Bislang ' + String(n) + ' Aufrufe</em>';
            }
          }

        });
      })(id, byId[id]);
    }
  }

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



// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------