// 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}
${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;