// Images to PDF - JavaScript Functionality let imagesToPdfFiles = []; let imagesToPdfSortable = null; // DOM elements let uploadArea, fileInput, fileList, filesContainer, convertBtn, clearBtn; let progressBar, progressText, uploadProgress, resultArea, errorArea; let downloadLink; // Initialize when page loads document.addEventListener('DOMContentLoaded', function() { // Get DOM elements uploadArea = document.getElementById('upload-area'); fileInput = document.getElementById('file-input'); fileList = document.getElementById('file-list'); filesContainer = document.getElementById('files-container'); convertBtn = document.getElementById('convert-btn'); clearBtn = document.getElementById('clear-btn'); progressBar = document.getElementById('progress-bar'); progressText = document.getElementById('progress-text'); uploadProgress = document.getElementById('upload-progress'); resultArea = document.getElementById('result-area'); errorArea = document.getElementById('error-area'); downloadLink = document.getElementById('download-link'); // Setup event listeners setupEventListeners(); // Setup drag and drop setupDragAndDrop(uploadArea, handleFiles); }); function setupEventListeners() { // File input change fileInput.addEventListener('change', function(e) { handleFiles(Array.from(e.target.files)); }); // Convert button convertBtn.addEventListener('click', convertToPdf); // Clear button clearBtn.addEventListener('click', clearFiles); // Upload area click uploadArea.addEventListener('click', function() { fileInput.click(); }); } function handleFiles(files) { // Hide previous results/errors hideResults(); if (!files || files.length === 0) { showError('Keine Dateien ausgewählt.'); return; } // Filter valid image files const validFiles = files.filter(file => { const isValid = file.type.startsWith('image/'); if (!isValid) { showNotification(`${file.name} ist keine gültige Bilddatei.`, 'warning'); } return isValid; }); if (validFiles.length === 0) { showError('Keine gültigen Bilddateien gefunden.'); return; } // Show upload progress showUploadProgress(); // Upload files uploadImages(validFiles); } async function uploadImages(files) { try { const response = await uploadFiles(files, '/api/upload-images', updateProgress); if (response.success) { imagesToPdfFiles = response.files; displayFiles(); showNotification(response.message, 'success'); } else { throw new Error(response.error || 'Upload fehlgeschlagen'); } } catch (error) { showError(`Upload-Fehler: ${error.message}`); } finally { hideUploadProgress(); } } function updateProgress(percent) { progressBar.style.width = percent + '%'; progressText.textContent = Math.round(percent) + '%'; } function displayFiles() { filesContainer.innerHTML = ''; imagesToPdfFiles.forEach((file, index) => { const fileItem = createFileItem(file, index); filesContainer.appendChild(fileItem); }); // Show file list fileList.style.display = 'block'; // Enable convert button convertBtn.disabled = false; // Setup sortable setupSortableList(); } function createFileItem(file, index) { const div = document.createElement('div'); div.className = 'list-group-item file-item-enhanced'; div.dataset.index = index; // Initialize rotation if not set if (!file.rotation) { file.rotation = 0; } div.innerHTML = `
${file.original_name}
${file.original_name}
${formatFileSize(file.size)}
${file.rotation}°
`; return div; } function setupSortableList() { if (imagesToPdfSortable) { imagesToPdfSortable.destroy(); } imagesToPdfSortable = setupSortable(filesContainer, function(evt) { // Update array order const item = imagesToPdfFiles.splice(evt.oldIndex, 1)[0]; imagesToPdfFiles.splice(evt.newIndex, 0, item); // Refresh display displayFiles(); }); } function moveFileUp(index) { if (index > 0) { [imagesToPdfFiles[index], imagesToPdfFiles[index - 1]] = [imagesToPdfFiles[index - 1], imagesToPdfFiles[index]]; displayFiles(); } } function moveFileDown(index) { if (index < imagesToPdfFiles.length - 1) { [imagesToPdfFiles[index], imagesToPdfFiles[index + 1]] = [imagesToPdfFiles[index + 1], imagesToPdfFiles[index]]; displayFiles(); } } function removeFile(index) { imagesToPdfFiles.splice(index, 1); if (imagesToPdfFiles.length === 0) { clearFiles(); } else { displayFiles(); } showNotification('Datei entfernt.', 'info'); } async function convertToPdf() { if (imagesToPdfFiles.length === 0) { showError('Keine Dateien zum Konvertieren vorhanden.'); return; } hideResults(); setLoadingState(convertBtn, true); try { // Include rotation data for each file const filesWithRotation = imagesToPdfFiles.map(file => ({ filename: file.filename, rotation: file.rotation || 0, original_name: file.original_name })); const response = await makeRequest('/api/convert-images-to-pdf', { method: 'POST', body: JSON.stringify({ files: filesWithRotation }) }); if (response.success) { showResult(response.filename, response.message); } else { throw new Error(response.error || 'Konvertierung fehlgeschlagen'); } } catch (error) { showError(`Konvertierungs-Fehler: ${error.message}`); } finally { setLoadingState(convertBtn, false); } } function clearFiles() { imagesToPdfFiles = []; filesContainer.innerHTML = ''; fileList.style.display = 'none'; convertBtn.disabled = true; fileInput.value = ''; hideResults(); if (imagesToPdfSortable) { imagesToPdfSortable.destroy(); imagesToPdfSortable = null; } } function showUploadProgress() { uploadProgress.style.display = 'block'; progressBar.style.width = '0%'; progressText.textContent = '0%'; } function hideUploadProgress() { uploadProgress.style.display = 'none'; } function showResult(filename, message) { resultArea.style.display = 'block'; downloadLink.href = `/download/${filename}`; downloadLink.querySelector('.me-2').nextSibling.textContent = 'PDF herunterladen'; // Update message if provided if (message) { resultArea.querySelector('p').textContent = message; } } function showError(message) { errorArea.style.display = 'block'; document.getElementById('error-message').textContent = message; } function hideResults() { resultArea.style.display = 'none'; errorArea.style.display = 'none'; } function rotateImage(index, degrees) { if (index >= 0 && index < imagesToPdfFiles.length) { imagesToPdfFiles[index].rotation = (imagesToPdfFiles[index].rotation + degrees) % 360; if (imagesToPdfFiles[index].rotation < 0) { imagesToPdfFiles[index].rotation += 360; } displayFiles(); showNotification(`Bild um ${degrees}° gedreht.`, 'info'); } } function showImageModal(filename, originalName, index) { // Create modal if it doesn't exist let modal = document.getElementById('image-modal'); if (!modal) { modal = document.createElement('div'); modal.className = 'modal fade image-modal'; modal.id = 'image-modal'; modal.setAttribute('tabindex', '-1'); modal.setAttribute('aria-hidden', 'true'); modal.innerHTML = ` `; document.body.appendChild(modal); } else { // Update existing modal document.getElementById('image-modal-title').textContent = originalName; const modalImage = document.getElementById('modal-image'); modalImage.src = `/uploads/${filename}`; modalImage.alt = originalName; modalImage.className = `img-fluid rotate-${imagesToPdfFiles[index].rotation}`; // Update rotation buttons const rotateButtons = modal.querySelectorAll('.btn-outline-primary'); rotateButtons[0].onclick = () => rotateImageInModal(index, -90); rotateButtons[1].onclick = () => rotateImageInModal(index, 90); } // Show modal const bootstrapModal = new bootstrap.Modal(modal); bootstrapModal.show(); } function rotateImageInModal(index, degrees) { rotateImage(index, degrees); // Update modal image const modalImage = document.getElementById('modal-image'); modalImage.className = `img-fluid rotate-${imagesToPdfFiles[index].rotation}`; } function updatePreviewSize() { const previewSize = document.getElementById('preview-size').value; const previews = document.querySelectorAll('.image-preview'); previews.forEach(preview => { // Remove existing size classes preview.classList.remove('size-small', 'size-medium', 'size-large'); // Add new size class preview.classList.add('size-' + previewSize); }); } // Global functions for button actions window.moveFileUp = moveFileUp; window.moveFileDown = moveFileDown; window.removeFile = removeFile; window.rotateImage = rotateImage; window.showImageModal = showImageModal; window.rotateImageInModal = rotateImageInModal; window.updatePreviewSize = updatePreviewSize;