- {# Hidden actual file input #}
- {{ form_widget(form.image, {'attr': {'class': 'd-none', 'id': 'search-photo-input'}}) }}
+ {# File input — opacity:0 so label-click still works in all browsers #}
+ {{ form_widget(form.image, {'attr': {'style': 'position:absolute;opacity:0;width:0;height:0;', 'tabindex': '-1', 'id': searchInputId}}) }}
{{ form_errors(form.image) }}
- {# Preview #}
-
-
![Vorschau]()
-
-
+ {# Drop zone / placeholder (also a drop target) #}
+
+ {# Preview (hidden until photo selected) #}
+
+
![Vorschau]()
+
+
+
+
+ {# Empty state #}
+
+
+ Foto hier ablegen oder Schaltfläche nutzen
- {# Placeholder when empty #}
-
-
- Noch kein Foto ausgewählt
-
-
-
+
-
+
@@ -125,9 +131,10 @@
Weitere Fotos (optional)
- {# Hidden input that holds extra files #}
+ {# Plain HTML input — label trigger works without JS tricks #}
+ accept="image/jpeg,image/png,image/webp" multiple
+ style="position:absolute;opacity:0;width:0;height:0;">
@@ -243,7 +250,7 @@
errDiv.style.display = 'block';
// Mobile fallback: trigger native camera input
if (cameraTarget === 'search') {
- document.getElementById('search-photo-input').click();
+ searchInput?.click();
} else {
document.getElementById('extra-photos-input').click();
}
@@ -285,14 +292,16 @@
});
/* ── Search photo ──────────────────────────────────────────── */
- const searchInput = document.getElementById('search-photo-input');
+ const dropZone = document.getElementById('search-drop-zone');
+ const searchInput = document.getElementById(dropZone.dataset.input);
const searchPreview = document.getElementById('search-photo-preview');
- const searchImg = document.getElementById('search-photo-img');
- const searchHolder = document.getElementById('search-photo-placeholder');
+ const searchImg = document.getElementById('search-photo-img');
+ const searchHolder = document.getElementById('search-photo-placeholder');
document.getElementById('btn-search-camera').addEventListener('click', () => openCamera('search'));
- document.getElementById('btn-search-file').addEventListener('click', () => searchInput.click());
- document.getElementById('search-photo-clear').addEventListener('click', () => {
+
+ document.getElementById('search-photo-clear').addEventListener('click', e => {
+ e.stopPropagation();
searchInput.value = '';
searchImg.src = '';
searchPreview.style.display = 'none';
@@ -303,6 +312,24 @@
if (searchInput.files[0]) setSearchPhoto(searchInput.files[0]);
});
+ // Drag & drop on the drop zone
+ dropZone.addEventListener('dragover', e => {
+ e.preventDefault();
+ dropZone.style.borderColor = '#0d6efd';
+ dropZone.style.background = '#e8f0fe';
+ });
+ dropZone.addEventListener('dragleave', () => {
+ dropZone.style.borderColor = '';
+ dropZone.style.background = '';
+ });
+ dropZone.addEventListener('drop', e => {
+ e.preventDefault();
+ dropZone.style.borderColor = '';
+ dropZone.style.background = '';
+ const file = e.dataTransfer.files[0];
+ if (file) setSearchPhoto(file);
+ });
+
function setSearchPhoto(file) {
const dt = new DataTransfer();
dt.items.add(file);
@@ -310,6 +337,8 @@
searchImg.src = URL.createObjectURL(file);
searchPreview.style.display = 'block';
searchHolder.style.display = 'none';
+ dropZone.style.borderColor = '';
+ dropZone.style.background = '';
}
/* ── Extra photos ──────────────────────────────────────────── */