'use strict'; (function() { const overlay = document.getElementById('crop-modal-overlay'); const BELEG_ID = overlay.dataset.belegId; const FILE_URL = '/belege/' + BELEG_ID + '/file'; const canvas = document.getElementById('crop-canvas'); const confirmBtn = document.getElementById('crop-confirm-btn'); const sizeHint = document.getElementById('crop-size-hint'); const ctx = canvas.getContext('2d'); let img = null; let scaleX = 1, scaleY = 1; let sel = null; // {x,y,w,h} in Canvas-Koordinaten let dragging = false; let startX = 0, startY = 0; const spinner = document.getElementById('crop-spinner'); window.openCropModal = function() { overlay.style.display = 'flex'; if (img) { drawCanvas(); return; } spinner.style.display = 'flex'; img = new Image(); img.onload = function() { // Canvas auf max. 90vw / 72vh skalieren const maxW = Math.min(window.innerWidth * 0.90, 1200); const maxH = Math.min(window.innerHeight * 0.72, 900); const ratio = Math.min(maxW / img.naturalWidth, maxH / img.naturalHeight, 1); canvas.width = Math.round(img.naturalWidth * ratio); canvas.height = Math.round(img.naturalHeight * ratio); scaleX = img.naturalWidth / canvas.width; scaleY = img.naturalHeight / canvas.height; sel = null; spinner.style.display = 'none'; drawCanvas(); }; img.src = FILE_URL + '?nocache=' + Date.now(); }; window.closeCropModal = function() { overlay.style.display = 'none'; }; function drawCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); if (!sel || sel.w === 0 || sel.h === 0) return; // Abdunkeln außerhalb der Auswahl ctx.fillStyle = 'rgba(0,0,0,0.45)'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Ausschnitt freistellen ctx.drawImage(img, sel.x * scaleX, sel.y * scaleY, sel.w * scaleX, sel.h * scaleY, sel.x, sel.y, sel.w, sel.h); // Rahmen ctx.strokeStyle = '#fff'; ctx.lineWidth = 1.5; ctx.setLineDash([5, 3]); ctx.strokeRect(sel.x + 0.5, sel.y + 0.5, sel.w, sel.h); ctx.setLineDash([]); const realW = Math.round(sel.w * scaleX); const realH = Math.round(sel.h * scaleY); sizeHint.textContent = realW + ' × ' + realH + ' px'; confirmBtn.disabled = (realW < 10 || realH < 10); } function canvasPos(e) { const r = canvas.getBoundingClientRect(); const cx = e.touches ? e.touches[0].clientX : e.clientX; const cy = e.touches ? e.touches[0].clientY : e.clientY; return { x: Math.max(0, Math.min(canvas.width, Math.round(cx - r.left))), y: Math.max(0, Math.min(canvas.height, Math.round(cy - r.top))), }; } canvas.addEventListener('mousedown', startDrag); canvas.addEventListener('touchstart', startDrag, {passive: true}); function startDrag(e) { const p = canvasPos(e); startX = p.x; startY = p.y; sel = {x: p.x, y: p.y, w: 0, h: 0}; dragging = true; confirmBtn.disabled = true; sizeHint.textContent = ''; } window.addEventListener('mousemove', moveDrag); window.addEventListener('touchmove', moveDrag, {passive: true}); function moveDrag(e) { if (!dragging) return; const p = canvasPos(e); sel = { x: Math.min(startX, p.x), y: Math.min(startY, p.y), w: Math.abs(p.x - startX), h: Math.abs(p.y - startY), }; drawCanvas(); } window.addEventListener('mouseup', endDrag); window.addEventListener('touchend', endDrag); function endDrag() { dragging = false; } window.confirmCrop = async function() { if (!sel || sel.w < 1 || sel.h < 1) return; confirmBtn.disabled = true; confirmBtn.textContent = 'Wird gespeichert…'; const payload = { x: Math.round(sel.x * scaleX), y: Math.round(sel.y * scaleY), w: Math.round(sel.w * scaleX), h: Math.round(sel.h * scaleY), }; try { const res = await fetch('/belege/' + BELEG_ID + '/crop', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload), }); const data = await res.json(); if (!res.ok) throw new Error(data.error || 'Unbekannter Fehler'); location.reload(); } catch (err) { alert('Fehler beim Zuschneiden: ' + err.message); confirmBtn.disabled = false; confirmBtn.textContent = 'Zuschnitt übernehmen'; } }; // ESC schließt Modal document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && overlay.style.display !== 'none') closeCropModal(); }); // Klick auf Overlay-Hintergrund schließt overlay.addEventListener('click', function(e) { if (e.target === overlay) closeCropModal(); }); confirmBtn.addEventListener('click', function () { confirmCrop(); }); const cancelBtn = document.getElementById('crop-cancel-btn'); if (cancelBtn) cancelBtn.addEventListener('click', function () { closeCropModal(); }); }());