progress: javascript to post image uploads
authorMischa POSLAWSKY <perl@shiar.org>
Sun, 4 Nov 2018 15:29:29 +0000 (16:29 +0100)
committerMischa POSLAWSKY <perl@shiar.org>
Fri, 1 Jan 2021 17:30:40 +0000 (18:30 +0100)
Track code written for contact form at Lijtweg commit v2.6-167-gd6338eb73e
(2018-11-04) [upload: hijack file input to show progress] with updates until
v2.6-171-gb68eaa5bbd (2018-11-05) [upload: support multiple files]
in preparation of general reuse.

progress.js [new file with mode: 0644]

diff --git a/progress.js b/progress.js
new file mode 100644 (file)
index 0000000..b93d61f
--- /dev/null
@@ -0,0 +1,72 @@
+function showsize(bytes) {
+       return (bytes / 1024 / 1024).toFixed(2);
+}
+
+function trackupload(input) {
+       var progress = document.getElementById('progress');
+       if (!progress) {
+               progress = document.createElement('DIV');
+               progress.id = 'progress';
+               progress.textContent = '0%';
+               progress.style.width = '0';
+               var bar = document.createElement('DIV');
+               bar.className = 'bar';
+               bar.appendChild(progress);
+               input.parentNode.insertBefore(bar, input.nextSibling);
+       }
+
+       var ajax = new XMLHttpRequest();
+       ajax.upload.addEventListener('progress', function (e) {
+               var percent = (e.loaded / e.total) * 100;
+               progress.style.width = percent + '%';
+               progress.textContent = Math.floor(percent) + '%';
+               progress.innerHTML += ' <small>(' + showsize(e.loaded) + ' / ' + showsize(e.total) + ' MB)</small>';
+       }, false);
+       ajax.addEventListener('load', function (e) {
+               if (e.target.status == 200) {
+                       progress.textContent = 'voltooid';
+                       progress.innerHTML += ' <small>(' + showsize(input.files[0].size) + ' MB)</small>';
+                       input.value = '';
+               }
+               else {
+                       progress.textContent = 'fout';
+                       progress.innerHTML += ': <small>' + e.target.responseText + '</small>';
+               }
+               progress.style.width = '100%';
+               input.parentNode.removeChild(cancel);
+       }, false);
+       ajax.addEventListener('error', function (e) {
+               progress.textContent = 'mislukt: ' + e.target.responseText;
+       }, false);
+       ajax.addEventListener('abort', function (e) {
+               progress.textContent = 'afgebroken';
+               input.parentNode.removeChild(cancel);
+               input.parentNode.removeChild(progress.parentNode);
+       }, false);
+
+       ajax.open('POST', input.form.action);
+       ajax.setRequestHeader('Accept', 'text/plain')
+
+       var form = new FormData();
+       for (let file of input.files) {
+               form.append('image[]', file);
+       }
+       ajax.send(form);
+
+       var cancel = document.createElement('BUTTON');
+       cancel.textContent = 'Afbreken';
+       cancel.onclick = function () { ajax.abort() };
+       cancel.style.float = 'left';
+       input.parentNode.insertBefore(cancel, progress.parentNode);
+}
+
+document.addEventListener('DOMContentLoaded', e => {
+       for (let row of document.forms[0].elements) {
+               if (row.name == 'image[]') {
+                       row.form.onsubmit = () => {
+                               trackupload(row);
+                               return false;
+                       };
+               }
+       }
+});