document.addEventListener('DOMContentLoaded', function () { // Hilfsklasse für Debug-Logging class Logger { static debug(message, data = null) { console.log(`[Debug] ${message}`, data || ''); } static error(message, error = null) { console.error(`[Error] ${message}`, error || ''); } } // Utility-Funktionen function showLoading() { document.body.classList.add('loading'); } function hideLoading() { document.body.classList.remove('loading'); } // Bild-Modal Funktionalität function openImageModal(img) { Logger.debug('Opening image modal', img); const modal = new bootstrap.Modal(document.getElementById('imageModal')); const modalImg = document.getElementById('modalImage'); const filename = img.dataset.filename; // Bild und Metadaten setzen modalImg.src = img.src; document.getElementById('modalFilename').textContent = filename; document.getElementById('modalFormat').textContent = img.dataset.format; document.getElementById('modalTimestamp').textContent = img.dataset.timestamp; document.getElementById('modalAlbum').textContent = img.dataset.album; document.getElementById('modalCategory').textContent = img.dataset.category; document.getElementById('modalPrompt').textContent = img.dataset.prompt; document.getElementById('modalOptimizedPrompt').textContent = img.dataset.optimized_prompt; // Click-to-Close Funktionalität document.querySelector('.image-container').onclick = function(e) { if (e.target === modalImg) { modal.hide(); } }; // Download-Button Funktionalität document.getElementById('modalDownloadBtn').onclick = async function() { await downloadSingleImage(filename); }; modal.show(); } // Download-Funktionalitäten // Download functionality async function downloadSingleImage(filename) { try { showLoading(); console.log('Attempting to download:', filename); const response = await fetch('/flux-pics/single', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename }) }); if (!response.ok) { const errorText = await response.text(); console.error('Server Error:', errorText); throw new Error(`HTTP error! status: ${response.status}`); } const blob = await response.blob(); console.log('Download successful, creating blob URL'); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = filename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); hideLoading(); } catch (error) { console.error('Download error:', error); hideLoading(); alert('Ein Fehler ist aufgetreten: ' + error.message); } } // Main initialization document.addEventListener('DOMContentLoaded', function () { // Auswahlfunktionen function getSelectedImages() { const selectedImages = []; const checkboxes = document.querySelectorAll('.select-item:checked'); Logger.debug(`Found ${checkboxes.length} selected images`); checkboxes.forEach(checkbox => { const img = checkbox.closest('.card').querySelector('img'); if (img && img.getAttribute('data-filename')) { selectedImages.push(img.getAttribute('data-filename')); } else { Logger.error('Missing image or filename for selected checkbox'); } }); return selectedImages; } // Event Listener für "Alle auswählen" Checkbox const selectAllCheckbox = document.getElementById('selectAll'); if (selectAllCheckbox) { const itemCheckboxes = document.querySelectorAll('.select-item'); selectAllCheckbox.addEventListener('change', function () { itemCheckboxes.forEach(checkbox => { checkbox.checked = selectAllCheckbox.checked; }); }); } // Thumbnail-Galerie Funktionalität // Thumbnail-Galerie Funktionalität document.getElementById('thumbgalleryBtn').addEventListener('click', function () { const selectedImages = getSelectedImages(); if (selectedImages.length === 0) { alert('Keine Bilder ausgewählt.'); return; } const galleryModal = new bootstrap.Modal(document.getElementById('thumbGalleryModal')); const galleryContainer = document.getElementById('thumbGalleryContainer'); galleryContainer.innerHTML = ''; selectedImages.forEach(filename => { const container = document.createElement('div'); container.className = 'thumb-container m-2'; const img = document.createElement('img'); img.src = `/flux-pics/${filename}`; img.className = 'img-thumbnail thumbnail-img'; img.dataset.filename = filename; img.style.maxWidth = '150px'; img.style.cursor = 'pointer'; const downloadBtn = document.createElement('button'); downloadBtn.className = 'btn btn-sm btn-primary download-thumb'; downloadBtn.innerHTML = '<i class="fas fa-download"></i>'; container.appendChild(img); container.appendChild(downloadBtn); galleryContainer.appendChild(container); // Klick auf Thumbnail öffnet Vollbild img.addEventListener('click', () => openImageModal(img)); // Download Button downloadBtn.addEventListener('click', async () => { await downloadSingleImage(filename); }); }); galleryModal.show(); }); // Slideshow Funktionalität document.getElementById('slideshowBtn').addEventListener('click', function () { const selectedImages = getSelectedImages(); if (selectedImages.length === 0) { alert('Keine Bilder ausgewählt.'); return; } const slideshowModal = new bootstrap.Modal(document.getElementById('slideshowModal')); const slideshowContainer = document.getElementById('slideshowContainer'); slideshowContainer.innerHTML = ''; let currentSlideIndex = 0; let slideshowInterval; const slideInterval = 3000; // 3 Sekunden pro Bild selectedImages.forEach((filename, index) => { const div = document.createElement('div'); div.classList.add('carousel-item'); if (index === 0) div.classList.add('active'); const img = document.createElement('img'); img.src = `/flux-pics/${filename}`; img.classList.add('d-block', 'w-100'); img.dataset.filename = filename; div.appendChild(img); slideshowContainer.appendChild(div); }); const carousel = new bootstrap.Carousel(document.getElementById('carouselExampleControls'), { interval: false }); // Play/Pause Funktionalität const playBtn = document.getElementById('playSlideshow'); const pauseBtn = document.getElementById('pauseSlideshow'); playBtn.addEventListener('click', function() { slideshowInterval = setInterval(() => { carousel.next(); }, slideInterval); playBtn.style.display = 'none'; pauseBtn.style.display = 'block'; }); pauseBtn.addEventListener('click', function() { clearInterval(slideshowInterval); pauseBtn.style.display = 'none'; playBtn.style.display = 'block'; }); // Vollbild Funktionalität document.getElementById('fullscreenBtn').addEventListener('click', function() { const modalElement = document.getElementById('slideshowModal'); if (modalElement.requestFullscreen) { modalElement.requestFullscreen(); } else if (modalElement.webkitRequestFullscreen) { modalElement.webkitRequestFullscreen(); } else if (modalElement.msRequestFullscreen) { modalElement.msRequestFullscreen(); } }); // Download aktuelles Bild document.getElementById('downloadCurrentSlide').addEventListener('click', async function() { const activeSlide = slideshowContainer.querySelector('.carousel-item.active img'); if (activeSlide) { await downloadSingleImage(activeSlide.dataset.filename); } }); slideshowModal.show(); }); // Hilfsfunktion für Einzelbild-Download async function downloadSingleImage(filename) { try { const response = await fetch('/flux-pics/single', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = filename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); } catch (error) { console.error('Fehler beim Download:', error); alert('Ein Fehler ist aufgetreten: ' + error.message); } } // Grid Layout Funktionalität document.getElementById('gridLayout')?.addEventListener('change', function () { const columns = parseInt(this.value); const imageGrid = document.getElementById('imageGrid'); imageGrid.className = `row row-cols-1 row-cols-md-${columns}`; }); // Scroll-to-Top Button const scrollTopBtn = document.getElementById('scrollTopBtn'); if (scrollTopBtn) { window.addEventListener('scroll', function () { if (window.scrollY > 300) { scrollTopBtn.style.display = 'block'; } else { scrollTopBtn.style.display = 'none'; } }); scrollTopBtn.addEventListener('click', function () { window.scrollTo({ top: 0, behavior: 'smooth' }); }); } // Event Listener für Bilddetails document.querySelectorAll('.image-thumbnail').forEach(function(img) { img.addEventListener('click', function() { openImageModal(this); }); }); // Download ausgewählter Bilder document.getElementById('downloadSelected')?.addEventListener('click', async function () { const selectedImages = getSelectedImages(); Logger.debug('Selected images:', selectedImages); if (selectedImages.length === 0) { alert('Keine Bilder ausgewählt.'); return; } let downloadType = 'single'; if (selectedImages.length > 1) { const choice = confirm('Möchten Sie die Bilder als ZIP-Datei herunterladen?\nKlicken Sie "OK" für ZIP oder "Abbrechen" für Einzeldownloads.'); if (choice) { downloadType = 'zip'; } } try { if (downloadType === 'zip') { showLoading(); const response = await fetch('/flux-pics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ selectedImages }) }); if (!response.ok) { const errorText = await response.text(); Logger.error('Server Error:', errorText); throw new Error(`HTTP error! status: ${response.status}`); } const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'images.zip'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); hideLoading(); } else { for (const filename of selectedImages) { await downloadSingleImage(filename); await new Promise(resolve => setTimeout(resolve, 500)); } } alert('Download erfolgreich abgeschlossen.'); } catch (error) { Logger.error('Download error:', error); hideLoading(); alert('Ein Fehler ist aufgetreten: ' + error.message); } }); // Keyboard Navigation document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { const modals = document.querySelectorAll('.modal.show'); modals.forEach(modal => { const bootstrapModal = bootstrap.Modal.getInstance(modal); if (bootstrapModal) bootstrapModal.hide(); }); } }); }); function getImagePath(filename) { return `/flux-pics/${filename}`; } // Und dann verwenden Sie diese Funktion überall: img.src = getImagePath(filename);