summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-23 19:46:59 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-23 19:46:59 +0200
commit7ebb5ce8ef276e6d23d818c216be6ef2974369cc (patch)
tree75ec93871392c94e10c2627327efd5994f324de0 /public
parentcef5d1a685f324a4779ea6d18da0b0bbf6cfb7b1 (diff)
Turn the asset upload forms into file drop targets
Dropped files land in the existing file input and submit through the unchanged form. An empty name field is prefilled from the basename.
Diffstat (limited to 'public')
-rw-r--r--public/javascripts/admin_interface.js38
-rw-r--r--public/stylesheets/admin.css11
2 files changed, 49 insertions, 0 deletions
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js
index 5514f3b3..284d2b72 100644
--- a/public/javascripts/admin_interface.js
+++ b/public/javascripts/admin_interface.js
@@ -85,6 +85,44 @@ $(document).ready(function () {
85 desktop_mq.addEventListener('change', sync_metadata); 85 desktop_mq.addEventListener('change', sync_metadata);
86 } 86 }
87 87
88 var dropzone = document.getElementById('asset_dropzone');
89 if (dropzone) {
90 var input = dropzone.querySelector('input[type=file]');
91
92 // Without these, a drop that misses the zone navigates the browser
93 // to the file, losing the half-filled form.
94 ['dragover', 'drop'].forEach(function(ev) {
95 window.addEventListener(ev, function(e) { e.preventDefault(); });
96 });
97
98 ['dragenter', 'dragover'].forEach(function(ev) {
99 dropzone.addEventListener(ev, function(e) {
100 e.preventDefault(); dropzone.classList.add('dragging');
101 });
102 });
103 ['dragleave', 'drop'].forEach(function(ev) {
104 dropzone.addEventListener(ev, function(e) {
105 e.preventDefault(); dropzone.classList.remove('dragging');
106 });
107 });
108
109 dropzone.addEventListener('drop', function(e) {
110 if (!e.dataTransfer.files.length) return;
111 var dt = new DataTransfer();
112 dt.items.add(e.dataTransfer.files[0]);
113 input.files = dt.files;
114 input.dispatchEvent(new Event('change', { bubbles: true }));
115 });
116
117 input.addEventListener('change', function() {
118 var name_field = document.getElementById('asset_name');
119 if (input.files.length && name_field && name_field.value === '') {
120 name_field.value = input.files[0].name.replace(/\.[^.]+$/, '');
121 }
122 });
123 }
124
125
88 jQuery.ajaxSetup({ 126 jQuery.ajaxSetup({
89 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");} 127 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");}
90 }); 128 });
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css
index 9f737752..69f0fcf2 100644
--- a/public/stylesheets/admin.css
+++ b/public/stylesheets/admin.css
@@ -1386,6 +1386,17 @@ div#draft_list table td.actions a {
1386 background-color: #fffdf5; 1386 background-color: #fffdf5;
1387} 1387}
1388 1388
1389#asset_dropzone {
1390 border: 2px dashed #ccc;
1391 border-radius: 6px;
1392 padding: 1.5rem;
1393}
1394
1395#asset_dropzone.dragging {
1396 border-color: #f96;
1397 background: #fff8f2;
1398}
1399
1389/* ============================================================ 1400/* ============================================================
1390 Live edit preview 1401 Live edit preview
1391 ============================================================ */ 1402 ============================================================ */