Files
KantSites/public/assets/media-drop.js
T
kantarciandClaude Opus 5.5 76613b9f8e Add videos: library, block and section background
Videos join the media library as their own table (schema v28), with a
video block and a looping background on sections. video.js starts loops
only while visible, offers a pause button and leaves the still image for
reduced motion and data saving.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PWYm8kjAWmZaB2QB2xuBhU
2026-11-05 05:23:17 +00:00

52 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Dragging images and PDFs onto the upload field, and saying which files are about to go up.
*
* Everything here is an addition. Without this script the field is still a file input with a
* label: clicking it opens the file picker and the form submits the same way. The script never
* uploads by itself - the button stays the moment where something is sent.
*/
const zone = document.querySelector('[data-dropzone]');
const input = zone?.querySelector('input[type="file"]');
const chosen = document.querySelector('[data-chosen]');
if (zone && input && chosen) {
const ACCEPTED = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf', 'video/mp4', 'video/webm'];
const describe = (files, ignored = 0) => {
if (!files.length) {
chosen.textContent = ignored
? `Keine passende Datei dabei. ${ignored} Datei(en) übersprungen – erlaubt sind JPEG, PNG, WebP und PDF.`
: 'Noch keine Datei gewählt.';
return;
}
const names = [...files].map(file => file.name).join(', ');
const size = [...files].reduce((total, file) => total + file.size, 0);
chosen.textContent = `${files.length} Datei(en) gewählt (${(size / 1048576).toFixed(1)} MB): ${names}`
+ (ignored ? ` · ${ignored} Datei(en) übersprungen, erlaubt sind JPEG, PNG, WebP und PDF.` : '');
};
input.addEventListener('change', () => describe(input.files));
// Without preventDefault the browser navigates to the dropped file and the page is gone.
for (const event of ['dragenter', 'dragover']) {
zone.addEventListener(event, dragged => {
dragged.preventDefault();
zone.classList.add('is-dragging');
});
}
for (const event of ['dragleave', 'dragend']) {
zone.addEventListener(event, () => zone.classList.remove('is-dragging'));
}
zone.addEventListener('drop', dropped => {
dropped.preventDefault();
zone.classList.remove('is-dragging');
const files = [...(dropped.dataTransfer?.files ?? [])];
const images = files.filter(file => ACCEPTED.includes(file.type));
// The input is what the form submits, so the dropped files have to end up in it.
const transfer = new DataTransfer();
images.forEach(file => transfer.items.add(file));
input.files = transfer.files;
describe(input.files, files.length - images.length);
});
}