Files
PDF-WEB/static/js/main.js
SimolZimol 97fd0762d7 new file: QUICKSTART.md
new file:   README_INSTALL.md
	new file:   requirements.txt
	new file:   static/css/style.css
	new file:   static/js/images-to-pdf.js
	new file:   static/js/main.js
	new file:   static/js/pdf-tools.js
	new file:   templates/pdf_tools.html
2025-10-12 22:13:29 +02:00

190 lines
5.7 KiB
JavaScript

// PDF Editor - Main JavaScript Functions
// Global variables
let uploadedFiles = [];
let sortableInstance = null;
// Utility functions
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function getFileIcon(filename) {
const extension = filename.toLowerCase().split('.').pop();
const iconMap = {
'pdf': 'fas fa-file-pdf text-danger',
'jpg': 'fas fa-file-image text-success',
'jpeg': 'fas fa-file-image text-success',
'png': 'fas fa-file-image text-success',
'gif': 'fas fa-file-image text-success',
'bmp': 'fas fa-file-image text-success',
'tiff': 'fas fa-file-image text-success',
'zip': 'fas fa-file-archive text-warning'
};
return iconMap[extension] || 'fas fa-file text-muted';
}
// Show notification
function showNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; max-width: 400px;';
notification.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(notification);
// Auto remove after 5 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 5000);
}
// Show/hide loading state
function setLoadingState(element, loading = true) {
if (loading) {
element.disabled = true;
const originalText = element.innerHTML;
element.dataset.originalText = originalText;
element.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Verarbeitung...';
} else {
element.disabled = false;
element.innerHTML = element.dataset.originalText || element.innerHTML;
}
}
// AJAX helper function
async function makeRequest(url, options = {}) {
try {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
// File upload with progress
async function uploadFiles(files, endpoint, progressCallback) {
const formData = new FormData();
if (Array.isArray(files)) {
files.forEach(file => formData.append('files', file));
} else {
formData.append('file', files);
}
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// Upload progress
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable && progressCallback) {
const percentComplete = (e.loaded / e.total) * 100;
progressCallback(percentComplete);
}
});
xhr.addEventListener('load', () => {
if (xhr.status === 200) {
try {
const response = JSON.parse(xhr.responseText);
resolve(response);
} catch (error) {
reject(new Error('Invalid JSON response'));
}
} else {
reject(new Error(`Upload failed with status: ${xhr.status}`));
}
});
xhr.addEventListener('error', () => {
reject(new Error('Upload failed'));
});
xhr.open('POST', endpoint);
xhr.send(formData);
});
}
// Drag and drop functionality
function setupDragAndDrop(element, callback) {
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
element.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
element.addEventListener(eventName, () => {
element.classList.add('dragover');
}, false);
});
['dragleave', 'drop'].forEach(eventName => {
element.addEventListener(eventName, () => {
element.classList.remove('dragover');
}, false);
});
element.addEventListener('drop', (e) => {
const files = Array.from(e.dataTransfer.files);
callback(files);
}, false);
}
// Sortable list functionality
function setupSortable(container, onUpdate) {
if (typeof Sortable !== 'undefined') {
return Sortable.create(container, {
animation: 150,
ghostClass: 'sortable-ghost',
chosenClass: 'sortable-chosen',
dragClass: 'sortable-drag',
onUpdate: onUpdate
});
}
return null;
}
// Initialize tooltips
function initializeTooltips() {
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
initializeTooltips();
// Add fade-in animation to main content
const mainContent = document.querySelector('main');
if (mainContent) {
mainContent.classList.add('fade-in');
}
});