MediaWiki

Common.js: Difference between revisions

From Illustrations in German Translations of Mark Twain's Works

No edit summary
No edit summary
Line 293: Line 293:
// ===============================
// ===============================


// Stelle sicher, dass DataTable initialisiert wird
// ===============================
// DataTable Initialisierung
// ===============================
$(document).ready(function() {
$(document).ready(function() {
     if ($('#catalog').length) {
     if ($('#catalog').length) {
Line 300: Line 302:
});
});


// -------------------------------
// ===============================
// Globale Slideshow-Objekte
// Globale Slideshow-Objekte
// -------------------------------
// ===============================
const slideshows = {
const slideshows = {
     A: { images: [], index: 0 },
     A: { images: [], index: 0 },
Line 310: Line 312:
};
};


// -------------------------------
// ===============================
// Hilfsfunktionen
// Hilfsfunktionen
// -------------------------------
// ===============================


// Gefilterte Bild-Links aus DataTable holen
// Gefilterte Bild-Links aus DataTable holen
Line 318: Line 320:
     const rows = document.querySelectorAll('#catalog tbody tr');
     const rows = document.querySelectorAll('#catalog tbody tr');
     const images = [];
     const images = [];
     rows.forEach(row => {
     rows.forEach(row => {
         if (row.style.display !== 'none') {
         if (row.style.display !== 'none') {
             const imageCell = row.cells[8];
             const cell = row.cells[8];
             const link = imageCell ? imageCell.querySelector('a') : null;
             const link = cell ? cell.querySelector('a') : null;
             if (link) {
             if (link) {
                 const imageName = link.textContent.trim();
                 const name = link.textContent.trim();
                 const imageUrl = '/index.php/Special:Redirect/file/' + imageName + '.jpg';
                 const url = '/index.php/Special:Redirect/file/' + name + '.jpg';
                 images.push({ url: imageUrl, name: imageName + '.jpg' });
                 images.push({ url: url, name: name + '.jpg' });
             }
             }
         }
         }
     });
     });
     return images;
     return images;
}
}
Line 344: Line 344:


// ===============================
// ===============================
// MediaInfo Funktionen (Top-Level)
// MediaInfo Modul (kein Top-Level async)
// ===============================
// ===============================
 
var MediaInfo = (function() {
// MediaInfo aus API laden
    async function fetch(filename) {
async function fetchMediaInfo(filename) {
        const apiUrl = '/api.php?action=query&prop=revisions&titles=File:' +
    const apiUrl = '/api.php?action=query&prop=revisions&titles=File:' +
                      encodeURIComponent(filename) +
                  encodeURIComponent(filename) +
                      '&rvprop=content&format=json';
                  '&rvprop=content&format=json';
        try {
    try {
            const response = await fetch(apiUrl);
        const response = await fetch(apiUrl);
            const data = await response.json();
        const data = await response.json();
            const pages = data.query.pages;
        const pages = data.query.pages;
            const page = pages[Object.keys(pages)[0]];
        const page = pages[Object.keys(pages)[0]];
            if (!page.revisions) return null;
        if (!page.revisions) return null;
            const wikitext = page.revisions[0]['*'] || page.revisions[0]['slots']?.main['*'];
 
            if (!wikitext) return null;
        const wikitext = page.revisions[0]['*'] || page.revisions[0]['slots']?.main['*'];
            const match = wikitext.match(/\{\{MediaInfo([\s\S]*?)\}\}/);
        if (!wikitext) return null;
            if (!match) return null;
 
            const block = match[1];
        const match = wikitext.match(/\{\{MediaInfo([\s\S]*?)\}\}/);
            const info = {};
        if (!match) return null;
            const fields = ["title","chapter","illustration","illustrator","year","tags","publication"];
 
            fields.forEach(field => {
        const block = match[1];
                const regex = new RegExp("\\|\\s*" + field + "\\s*=([^\\n]*)");
        const info = {};
                const m = block.match(regex);
        const fields = ["title","chapter","illustration","illustrator","year","tags","publication"];
                if (m) info[field] = m[1].trim();
        fields.forEach(field => {
            });
            const regex = new RegExp("\\|\\s*" + field + "\\s*=([^\\n]*)");
            return info;
            const m = block.match(regex);
        } catch(e) {
            if (m) info[field] = m[1].trim();
            console.error("Fehler beim Laden der MediaInfo:", e);
        });
            return null;
 
        }
        return info;
    } catch (err) {
        console.error("Fehler beim Laden der MediaInfo:", err);
        return null;
     }
     }
}


// MediaInfo anzeigen
    async function show(target, filename) {
async function showMediaInfo(target, filename) {
        const infoBox = document.getElementById('mediainfo' + target);
    const infoBox = document.getElementById('mediainfo' + target);
        if (!infoBox) return;
    if (!infoBox) return;
        infoBox.textContent = "Lade Informationen...";
    infoBox.textContent = "Lade Informationen...";
        const info = await fetch(filename);
 
        if (!info) {
    const info = await fetchMediaInfo(filename);
            infoBox.textContent = "Keine Informationen gefunden.";
    if (!info) {
            return;
        infoBox.textContent = "Keine Informationen gefunden.";
        }
         return;
        let html = "<ul style='margin:0; padding-left:1em'>";
        for(const [key, value] of Object.entries(info)) {
            html += "<li><b>" + key + ":</b> " + value + "</li>";
        }
        html += "</ul>";
         infoBox.innerHTML = html;
     }
     }


     let html = "<ul style='margin:0; padding-left:1em'>";
     return { show: show };
    for (const [key, value] of Object.entries(info)) {
})();
        html += "<li><b>" + key + ":</b> " + value + "</li>";
    }
    html += "</ul>";
    infoBox.innerHTML = html;
}


// ===============================
// ===============================
Line 407: Line 402:
function updateSlide(target) {
function updateSlide(target) {
     const data = slideshows[target];
     const data = slideshows[target];
     const imgElement = document.getElementById('slide' + target);
     const imgEl = document.getElementById('slide' + target);


     if (data.images.length === 0) {
     if (data.images.length === 0) {
         imgElement.src = '';
         imgEl.src = '';
         imgElement.alt = 'No Images';
         imgEl.alt = 'No Images';
         imgElement.onclick = null;
         imgEl.onclick = null;
         updateCounter(target);
         updateCounter(target);
         const infoBox = document.getElementById('mediainfo' + target);
         const infoBox = document.getElementById('mediainfo' + target);
         if (infoBox) infoBox.textContent = "";
         if(infoBox) infoBox.textContent = "";
         return;
         return;
     }
     }
Line 422: Line 417:
     if (data.index >= data.images.length) data.index = 0;
     if (data.index >= data.images.length) data.index = 0;


     const currentImage = data.images[data.index];
     const current = data.images[data.index];
     imgElement.src = currentImage.url;
     imgEl.src = current.url;
     imgElement.alt = currentImage.name;
     imgEl.alt = current.name;
     imgElement.style.cursor = "pointer";
     imgEl.style.cursor = "pointer";
     imgElement.onclick = () => window.open('/File:' + currentImage.name, '_blank');
     imgEl.onclick = () => window.open('/File:' + current.name, '_blank');


     updateCounter(target);
     updateCounter(target);
     showMediaInfo(target, currentImage.name);
     MediaInfo.show(target, current.name);
}
}


Line 437: Line 432:
     slideshows[target].index = 0;
     slideshows[target].index = 0;


     const imgElement = document.getElementById('slide' + target);
     const imgEl = document.getElementById('slide' + target);
     if (images.length > 0) {
     if(images.length > 0){
         imgElement.src = images[0].url;
         imgEl.src = images[0].url;
         imgElement.alt = images[0].name;
         imgEl.alt = images[0].name;
         imgElement.style.cursor = "pointer";
         imgEl.style.cursor = "pointer";
         imgElement.onclick = () => window.open('/File:' + images[0].name, '_blank');
         imgEl.onclick = () => window.open('/File:' + images[0].name, '_blank');
         showMediaInfo(target, images[0].name);
         MediaInfo.show(target, images[0].name);
     } else {
     } else {
         imgElement.src = '';
         imgEl.src = '';
         imgElement.alt = 'No Images';
         imgEl.alt = 'No Images';
         imgElement.onclick = null;
         imgEl.onclick = null;
         const infoBox = document.getElementById('mediainfo' + target);
         const infoBox = document.getElementById('mediainfo' + target);
         if (infoBox) infoBox.textContent = "";
         if(infoBox) infoBox.textContent = "";
     }
     }
     updateCounter(target);
     updateCounter(target);
}
}


function nextSlideX(target) {
function nextSlideX(target){
     slideshows[target].index++;
     slideshows[target].index++;
     updateSlide(target);
     updateSlide(target);
}
}


function prevSlideX(target) {
function prevSlideX(target){
     slideshows[target].index--;
     slideshows[target].index--;
     updateSlide(target);
     updateSlide(target);
}
}


function openSlideshowInNewTab(target) {
function openSlideshowInNewTab(target){
     const data = slideshows[target];
     const data = slideshows[target];
     if (!data.images || data.images.length === 0) {
     if(!data.images || data.images.length===0){
         alert("No images to display for slideshow " + target);
         alert("No images to display for slideshow " + target);
         return;
         return;
     }
     }
     const newTab = window.open();
     const newTab = window.open();
     if (!newTab) {
     if(!newTab){ alert("Popup blocked! Bitte Popups erlauben."); return; }
        alert("Popup blocked! Bitte Popups für diese Seite erlauben.");
        return;
    }
 
     let html = "<html><head><title>Slideshow " + target + "</title></head><body style='font-family:sans-serif'>";
     let html = "<html><head><title>Slideshow " + target + "</title></head><body style='font-family:sans-serif'>";
     html += "<h2>Slideshow " + target + " (" + data.images.length + " images)</h2>";
     html += "<h2>Slideshow " + target + " (" + data.images.length + " images)</h2>";
     html += "<div style='display:flex; flex-wrap:wrap; gap:10px;'>";
     html += "<div style='display:flex; flex-wrap:wrap; gap:10px;'>";
 
     data.images.forEach(img=>{
     data.images.forEach(img => {
         html += "<div><a href='/File:" + img.name + "' target='_blank'>";
         html += "<div><a href='/File:" + img.name + "' target='_blank'>";
         html += "<img src='" + img.url + "' style='max-width:300px; height:auto;'></a></div>";
         html += "<img src='" + img.url + "' style='max-width:300px; height:auto;'></a></div>";
     });
     });
     html += "</div></body></html>";
     html += "</div></body></html>";
     newTab.document.open();
     newTab.document.open();

Revision as of 14:37, 16 September 2025

/* Any JavaScript here will be loaded for all users on every page load. */

mw.loader.using('jquery').then(function () {

  console.log('jQuery ist verfügbar:', typeof $);

  $.getScript('https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js')
    .then(() => {
      console.log('DataTables geladen:', $.fn.dataTable);
      return $.getScript('https://cdn.datatables.net/datetime/1.5.1/js/dataTables.dateTime.min.js');
    })
    .then(() => $.getScript('https://cdn.datatables.net/searchbuilder/1.6.0/js/dataTables.searchBuilder.min.js'))
    .then(() => {
      console.log('DataTables + Erweiterungen geladen');
      if ($.fn.dataTable && $.fn.dataTable.SearchBuilder) {
  console.log('SearchBuilder:', $.fn.dataTable.SearchBuilder);
} else {
  console.warn('SearchBuilder nicht verfügbar');
}

      mw.hook('wikipage.content').add(function($content) {
        const $table = $content.find('#catalog');

        if ($table.length && !$.fn.DataTable.isDataTable($table)) {
          $table.DataTable({
            dom: 'Qlfrtip',
            searchBuilder: true,
            paging: true,
            pageLength: 600,
            searching: true,
            ordering: true,
            lengthMenu: [[10, 25, 50, 100, 200, 600], [10, 25, 50, 100, 200, 600]],
            order: [[1, 'asc']],
            language: {
              search: "Search:",
              lengthMenu: "Show _MENU_ Entries",
              zeroRecords: "No Matches",
              info: "Page _PAGE_ of _PAGES_ (showing _TOTAL_ of _MAX_ entries)",
              infoEmpty: "Empty",
              infoFiltered: ""
            },
            initComplete: function () {
              this.api().columns().every(function () {
                var column = this;
                var header = $(column.header());
                var columnTitle = header.text();
                $('<input type="text" placeholder="' + columnTitle + ' ..." style="width: 100%; padding: 5px;"/>')
                  .appendTo(header.empty())
                  .on('keyup change', function () {
                    column.search(this.value).draw();
                  })
                  .on('click', function (e) {
                    e.stopPropagation();
                  });
              });
            }
          });
        }
      });
    })
    .catch((err) => {
      console.error('Fehler beim Laden von DataTables oder Erweiterungen:', err);
    });

});







/*AUSKLAPPMENÜS*/
$(function () {
  $('.ausklapp-button').click(function () {
    var $button = $(this);
    var $content = $button.next('.ausklapp-inhalt');

    $content.slideToggle(200);
    var expanded = $button.attr('aria-expanded') === 'true';
    $button.attr('aria-expanded', !expanded);
  });
});



// Hover-Preview für Bild-Links in DataTables
$(document).ready(function() {
    // Neuen Image-Container einfügen
   $('body').append('<div id="image-hover-preview" style="display:none; position:absolute; z-index:9999;"><img src="" style="max-width:400px; max-height:400px; border:1px solid #ccc; background:white; padding:5px;"></div>');

    // Auf alle Links in der Tabelle achten
    $('#catalog').on('mouseenter', 'a', function(e) {
        var href = $(this).attr('href');
        if (href && href.includes('/Special:Redirect/file/')) {
            var imgUrl = href; // URL direkt verwenden
            $('#image-hover-preview img').attr('src', imgUrl);
            $('#image-hover-preview').show();
        }
    }).on('mousemove', 'a', function(e) {
        $('#image-hover-preview').css({
            top: e.pageY + 20 + 'px',
            left: e.pageX + 20 + 'px'
        });
    }).on('mouseleave', 'a', function() {
        $('#image-hover-preview').hide();
    });
});

$(document).ready(function () {
  const searchButton = document.getElementById('searchButton');
  const tagInput = document.getElementById('tagInput');

  if (searchButton && tagInput) {
    searchButton.addEventListener('click', function () {
      const tags = tagInput.value.split(',').map(tag => tag.trim());
      searchImagesByTags(tags);
    });
  } else {
    console.warn('searchButton oder tagInput nicht gefunden.');
  }
});

function searchImagesByTags(tags) {
    var url = new URL(window.location.href);
    var apiUrl = url.origin + '/w/api.php';
    
    // Hier wird eine Anfrage an die MediaWiki API gestellt, um nach Bildern zu suchen, die den Tags entsprechen
    fetch(`${apiUrl}?action=query&format=json&list=categorymembers&cmtitle=Category:${tags.join('&cmtitle=Category:')}&cmtype=file`)
        .then(response => response.json())
        .then(data => {
            var images = data.query.categorymembers;
            displayImages(images);
        })
        .catch(error => console.error('Error:', error));
}

function displayImages(images) {
    var galleryContainer = document.getElementById('galleryContainer');
    galleryContainer.innerHTML = ''; // Leere den Container, um Platz für neue Bilder zu schaffen

    // Überprüfe, ob Bilder vorhanden sind
    if (images.length === 0) {
        galleryContainer.innerHTML = '<p>No images found.</p>';
        return;
    }

    // Bilder in die Galerie einfügen
    images.forEach(image => {
        var imgElement = document.createElement('img');
        imgElement.src = '/index.php/Special:Redirect/file/' + image.title.replace('Category:', '');
        imgElement.alt = image.title;
        galleryContainer.appendChild(imgElement);
    });
}
// Funktion zur Extraktion der Dateinamen aus der Tabelle und zur Anzeige in der Galerie
function updateGalleryFromTable() {
    // Tabelle durchsuchen und Dateinamen extrahieren
    var rows = document.querySelectorAll('#catalog tbody tr');
    var imageLinks = [];

    rows.forEach(row => {
        var imageCell = row.cells[8];  // Die 9. Zelle enthält den Dateinamen als Link
        var link = imageCell.querySelector('a');  // Link innerhalb der Zelle
        if (link) {
            var imageName = link.textContent.trim();  // Der Text des Links ist der Dateiname
            var imageUrl = '/index.php/Special:Redirect/file/' + imageName + '.jpg';
            imageLinks.push(imageUrl);
        }
    });

    // Neue Seite mit Galerie öffnen
    var galleryWindow = window.open('', '_blank');
    if (galleryWindow) {
        galleryWindow.document.write('<html><head><title>Gallery</title>');
        galleryWindow.document.write('<style>');
        galleryWindow.document.write('body { font-family: sans-serif; padding: 20px; }');
        galleryWindow.document.write('img { max-width: 300px; margin: 10px; cursor: pointer; display: inline-block; }');
        galleryWindow.document.write('</style></head><body>');
        galleryWindow.document.write('<h2>Results</h2>');

        imageLinks.forEach(url => {
            galleryWindow.document.write('<img src="' + url + '" onclick="window.open(\'' + url + '\')">');
        });

        galleryWindow.document.write('</body></html>');
        galleryWindow.document.close();
    } else {
        alert('Popup wurde blockiert. Bitte erlaube Popups für diese Seite.');
    }
}

$(document).ready(function () {
    const columnCount = 9;

    // Neue Bedingung hinzufügen
    $('#addCondition').on('click', function () {
        const newRow = $('<div class="search-row" style="margin-bottom: 5px;">' +
            '<select class="bool-select">' +
                '<option value="AND">AND</option>' +
                '<option value="OR">OR</option>' +
                '<option value="NOT">NOT</option>' +
                '<option value="XOR">XOR</option>' +
            '</select>' +
            '<select class="field-select">' +
                '<option value="8">ID</option>' +
                '<option value="all">All</option>' +
                '<option value="0">Book</option>' +
                '<option value="1">Year</option>' +
                '<option value="2">Illustrator</option>' +
                '<option value="3">Chpt in Orig</option>' +
                '<option value="4">Chpt in this Ed.</option>' +
                '<option value="5">Ill. in Chpt.</option>' +
                '<option value="6">Illustration Title</option>' +
                '<option value="7">Tags</option>' +
            '</select>' +
            '<input type="text" class="search-input" placeholder=" ">' +
            '<button class="remove-condition" style="margin-left: 5px;">🗑️</button>' +
        '</div>');
        $('#searchConditions').append(newRow);
    });

    // Dynamisch hinzugefügte Bedingungen löschen
    $('#searchConditions').on('click', '.remove-condition', function () {
        if ($('#searchConditions .search-row').not('.fixed').length > 1) {
            $(this).closest('.search-row').remove();
        }
    });

    // Suche ausführen
    $('#runAdvancedSearch').on('click', function () {
        const table = $('#catalog').DataTable();
        table.search('').columns().search('');

        const filters = [];

        // 1. Feste erste Bedingung einfügen
        filters.push({
            column: '8', // ID-Spalte
            term: 'hf',
            boolOp: null
        });

        // 2. Alle weiteren Bedingungen
        $('#searchConditions .search-row').not('.fixed').each(function () {
            const column = $(this).find('.field-select').val();
            const term = $(this).find('.search-input').val().trim();
            const boolOp = $(this).find('.bool-select').val();

            if (term !== '') {
                filters.push({ column, term, boolOp });
            }
        });

        if (filters.length === 0) {
            table.draw();
            return;
        }

        // Filterlogik
        $.fn.dataTable.ext.search = [];
        $.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
            let result = null;

            filters.forEach(function (filter, i) {
                const val = filter.column === 'all'
                    ? data.join(' ').toLowerCase()
                    : (data[filter.column] || '').toLowerCase();

                const match = val.includes(filter.term.toLowerCase());

                if (i === 0) {
                    result = match;
                } else {
                    switch (filter.boolOp) {
                        case 'AND': result = result && match; break;
                        case 'OR':  result = result || match; break;
                        case 'NOT': result = result && !match; break;
                        case 'XOR': result = (result && !match) || (!result && match); break;
                    }
                }
            });

            return result;
        });

        table.draw();
    });
});

// ===============================
// Comparison / Slideshow Script
// ===============================

// ===============================
// DataTable Initialisierung
// ===============================
$(document).ready(function() {
    if ($('#catalog').length) {
        $('#catalog').DataTable();
    }
});

// ===============================
// Globale Slideshow-Objekte
// ===============================
const slideshows = {
    A: { images: [], index: 0 },
    B: { images: [], index: 0 },
    C: { images: [], index: 0 },
    D: { images: [], index: 0 },
};

// ===============================
// Hilfsfunktionen
// ===============================

// Gefilterte Bild-Links aus DataTable holen
function getFilteredImageLinks() {
    const rows = document.querySelectorAll('#catalog tbody tr');
    const images = [];
    rows.forEach(row => {
        if (row.style.display !== 'none') {
            const cell = row.cells[8];
            const link = cell ? cell.querySelector('a') : null;
            if (link) {
                const name = link.textContent.trim();
                const url = '/index.php/Special:Redirect/file/' + name + '.jpg';
                images.push({ url: url, name: name + '.jpg' });
            }
        }
    });
    return images;
}

// Counter-Update
function updateCounter(target) {
    const data = slideshows[target];
    const total = data.images.length;
    const current = total > 0 ? data.index + 1 : 0;
    const counterEl = document.getElementById("counter" + target);
    if (counterEl) counterEl.textContent = current + "/" + total;
}

// ===============================
// MediaInfo Modul (kein Top-Level async)
// ===============================
var MediaInfo = (function() {
    async function fetch(filename) {
        const apiUrl = '/api.php?action=query&prop=revisions&titles=File:' +
                       encodeURIComponent(filename) +
                       '&rvprop=content&format=json';
        try {
            const response = await fetch(apiUrl);
            const data = await response.json();
            const pages = data.query.pages;
            const page = pages[Object.keys(pages)[0]];
            if (!page.revisions) return null;
            const wikitext = page.revisions[0]['*'] || page.revisions[0]['slots']?.main['*'];
            if (!wikitext) return null;
            const match = wikitext.match(/\{\{MediaInfo([\s\S]*?)\}\}/);
            if (!match) return null;
            const block = match[1];
            const info = {};
            const fields = ["title","chapter","illustration","illustrator","year","tags","publication"];
            fields.forEach(field => {
                const regex = new RegExp("\\|\\s*" + field + "\\s*=([^\\n]*)");
                const m = block.match(regex);
                if (m) info[field] = m[1].trim();
            });
            return info;
        } catch(e) {
            console.error("Fehler beim Laden der MediaInfo:", e);
            return null;
        }
    }

    async function show(target, filename) {
        const infoBox = document.getElementById('mediainfo' + target);
        if (!infoBox) return;
        infoBox.textContent = "Lade Informationen...";
        const info = await fetch(filename);
        if (!info) {
            infoBox.textContent = "Keine Informationen gefunden.";
            return;
        }
        let html = "<ul style='margin:0; padding-left:1em'>";
        for(const [key, value] of Object.entries(info)) {
            html += "<li><b>" + key + ":</b> " + value + "</li>";
        }
        html += "</ul>";
        infoBox.innerHTML = html;
    }

    return { show: show };
})();

// ===============================
// Slideshow-Funktionen
// ===============================

function updateSlide(target) {
    const data = slideshows[target];
    const imgEl = document.getElementById('slide' + target);

    if (data.images.length === 0) {
        imgEl.src = '';
        imgEl.alt = 'No Images';
        imgEl.onclick = null;
        updateCounter(target);
        const infoBox = document.getElementById('mediainfo' + target);
        if(infoBox) infoBox.textContent = "";
        return;
    }

    if (data.index < 0) data.index = data.images.length - 1;
    if (data.index >= data.images.length) data.index = 0;

    const current = data.images[data.index];
    imgEl.src = current.url;
    imgEl.alt = current.name;
    imgEl.style.cursor = "pointer";
    imgEl.onclick = () => window.open('/File:' + current.name, '_blank');

    updateCounter(target);
    MediaInfo.show(target, current.name);
}

function populateSlideshow(target) {
    const images = getFilteredImageLinks();
    slideshows[target].images = images;
    slideshows[target].index = 0;

    const imgEl = document.getElementById('slide' + target);
    if(images.length > 0){
        imgEl.src = images[0].url;
        imgEl.alt = images[0].name;
        imgEl.style.cursor = "pointer";
        imgEl.onclick = () => window.open('/File:' + images[0].name, '_blank');
        MediaInfo.show(target, images[0].name);
    } else {
        imgEl.src = '';
        imgEl.alt = 'No Images';
        imgEl.onclick = null;
        const infoBox = document.getElementById('mediainfo' + target);
        if(infoBox) infoBox.textContent = "";
    }
    updateCounter(target);
}

function nextSlideX(target){
    slideshows[target].index++;
    updateSlide(target);
}

function prevSlideX(target){
    slideshows[target].index--;
    updateSlide(target);
}

function openSlideshowInNewTab(target){
    const data = slideshows[target];
    if(!data.images || data.images.length===0){
        alert("No images to display for slideshow " + target);
        return;
    }
    const newTab = window.open();
    if(!newTab){ alert("Popup blocked! Bitte Popups erlauben."); return; }
    let html = "<html><head><title>Slideshow " + target + "</title></head><body style='font-family:sans-serif'>";
    html += "<h2>Slideshow " + target + " (" + data.images.length + " images)</h2>";
    html += "<div style='display:flex; flex-wrap:wrap; gap:10px;'>";
    data.images.forEach(img=>{
        html += "<div><a href='/File:" + img.name + "' target='_blank'>";
        html += "<img src='" + img.url + "' style='max-width:300px; height:auto;'></a></div>";
    });
    html += "</div></body></html>";
    newTab.document.open();
    newTab.document.write(html);
    newTab.document.close();
}


// Chapter Script
importScript('MediaWiki:ChapterSlides.js');

// Chapter Script
importScript('MediaWiki:ChapterSlidesAlt.js');

// Filter Scripts, character pages 
importScript('MediaWiki:CharacterFilter.js');

// CharacterDistribution
// Chart.js von CDN laden
mw.loader.load('https://cdn.jsdelivr.net/npm/chart.js');

// CharacterDistribution.js laden (klassischer Weg)
importScript('MediaWiki:CharacterDistribution.js');

// Media Viewer Adjustments to Display Title and Tags
importScript('MediaWiki:MediaViewerDisplay.js');




if (mw.config.get('wgPageName') === 'Wiki/chardist') {
    // Chart.js von CDN laden
    mw.loader.load('https://cdn.jsdelivr.net/npm/chart.js', function() {

        document.addEventListener('DOMContentLoaded', () => {
            const canvas = document.getElementById('testChart');
            if (!canvas) return;

            const ctx = canvas.getContext('2d');
            new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: ['A','B','C'],
                    datasets: [{
                        label: 'Test',
                        data: [1,2,3],
                        backgroundColor: 'red'
                    }]
                },
                options: {}
            });
        });

    });
}