UploadQueue: refactor into proper ECMAScript class

This commit is contained in:
Aaron van Geffen 2023-03-12 11:45:37 +01:00
parent 54b69ecd11
commit 229fb9e5bf

View File

@ -1,4 +1,5 @@
function UploadQueue(options) { class UploadQueue {
constructor(options) {
this.queue = options.queue_element; this.queue = options.queue_element;
this.preview_area = options.preview_area; this.preview_area = options.preview_area;
this.upload_progress = []; this.upload_progress = [];
@ -7,62 +8,60 @@ function UploadQueue(options) {
this.addEvents(); this.addEvents();
} }
UploadQueue.prototype.addEvents = function() { addEvents() {
var that = this; this.queue.addEventListener('change', event => {
that.queue.addEventListener('change', function() { this.showSpinner(this.queue, "Generating previews (not uploading yet!)");
that.showSpinner(that.queue, "Generating previews (not uploading yet!)"); this.clearPreviews();
that.clearPreviews(); for (let i = 0; i < this.queue.files.length; i++) {
for (var i = 0; i < that.queue.files.length; i++) { const callback = (i !== this.queue.files.length - 1) ? null : () => {
var callback = (i !== that.queue.files.length - 1) ? null : function() { this.hideSpinner();
that.hideSpinner(); this.submit.disabled = false;
that.submit.disabled = false;
}; };
if (that.queue.files[0].name.includes(".HEIC")) { if (this.queue.files[0].name.includes(".HEIC")) {
alert('Sorry, the HEIC image format is not supported.\nPlease convert your photos to JPEG before uploading.'); alert('Sorry, the HEIC image format is not supported.\nPlease convert your photos to JPEG before uploading.');
that.hideSpinner(); this.hideSpinner();
that.submit.disabled = false; this.submit.disabled = false;
break; break;
} }
that.addPreviewBoxForQueueSlot(i); this.addPreviewBoxForQueueSlot(i);
that.addPreviewForFile(that.queue.files[i], i, callback); this.addPreviewForFile(this.queue.files[i], i, callback);
}; };
}); });
that.submit.addEventListener('click', function(e) { this.submit.addEventListener('click', event => {
e.preventDefault(); event.preventDefault();
that.process(); this.process();
}); });
this.submit.disabled = true; this.submit.disabled = true;
}; }
UploadQueue.prototype.clearPreviews = function() { clearPreviews() {
this.preview_area.innerHTML = ''; this.preview_area.innerHTML = '';
this.submit.disabled = true; this.submit.disabled = true;
this.current_upload_index = -1; this.current_upload_index = -1;
} }
UploadQueue.prototype.addPreviewBoxForQueueSlot = function(index) { addPreviewBoxForQueueSlot(index) {
var preview_box = document.createElement('div'); const preview_box = document.createElement('div');
preview_box.id = 'upload_preview_' + index; preview_box.id = 'upload_preview_' + index;
this.preview_area.appendChild(preview_box); this.preview_area.appendChild(preview_box);
}; }
UploadQueue.prototype.addPreviewForFile = function(file, index, callback) { addPreviewForFile(file, index, callback) {
if (!file) { if (!file) {
return false; return false;
} }
var preview = document.createElement('canvas'); const preview = document.createElement('canvas');
preview.title = file.name; preview.title = file.name;
var preview_box = document.getElementById('upload_preview_' + index); const preview_box = document.getElementById('upload_preview_' + index);
preview_box.appendChild(preview); preview_box.appendChild(preview);
var reader = new FileReader(); const reader = new FileReader();
var that = this; reader.addEventListener('load', event => {
reader.addEventListener('load', function() { const original = document.createElement('img');
var original = document.createElement('img');
original.src = reader.result; original.src = reader.result;
original.addEventListener('load', function() { original.addEventListener('load', function() {
@ -71,7 +70,7 @@ UploadQueue.prototype.addPreviewForFile = function(file, index, callback) {
preview.width = preview.height * (original.width / original.height); preview.width = preview.height * (original.width / original.height);
// First pass: resize to 50% on temp canvas. // First pass: resize to 50% on temp canvas.
var temp = document.createElement('canvas'), const temp = document.createElement('canvas'),
tempCtx = temp.getContext('2d'); tempCtx = temp.getContext('2d');
temp.width = original.width * 0.5; temp.width = original.width * 0.5;
@ -82,7 +81,7 @@ UploadQueue.prototype.addPreviewForFile = function(file, index, callback) {
tempCtx.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5); tempCtx.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5);
// Final pass: resize to desired size on preview canvas. // Final pass: resize to desired size on preview canvas.
var context = preview.getContext('2d'); const context = preview.getContext('2d');
context.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5, context.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5,
0, 0, preview.width, preview.height); 0, 0, preview.width, preview.height);
@ -92,83 +91,79 @@ UploadQueue.prototype.addPreviewForFile = function(file, index, callback) {
}); });
}, false); }, false);
reader.readAsDataURL(file); reader.readAsDataURL(file);
}; }
UploadQueue.prototype.process = function() { process() {
this.showSpinner(this.submit, "Preparing to upload files..."); this.showSpinner(this.submit, "Preparing to upload files...");
if (this.queue.files.length > 0) { if (this.queue.files.length > 0) {
this.submit.disabled = true; this.submit.disabled = true;
this.nextFile(); this.nextFile();
} }
}; }
UploadQueue.prototype.nextFile = function() { nextFile() {
var files = this.queue.files; const files = this.queue.files;
var i = ++this.current_upload_index; const i = ++this.current_upload_index;
if (i === files.length) { if (i === files.length) {
this.hideSpinner(); this.hideSpinner();
} else { } else {
this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length); this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length);
this.sendFile(files[i], i, function() { this.sendFile(files[i], i, this.nextFile);
this.nextFile(); }
});
} }
};
UploadQueue.prototype.sendFile = function(file, index, callback) { sendFile(file, index, callback) {
// Prepare the request. const request = new XMLHttpRequest();
var that = this; request.addEventListener('error', event => {
var request = new XMLHttpRequest(); this.updateProgress(index, -1);
request.addEventListener('error', function(event) {
that.updateProgress(index, -1);
}); });
request.addEventListener('progress', function(event) { request.addEventListener('progress', event => {
that.updateProgress(index, event.loaded / event.total); this.updateProgress(index, event.loaded / event.total);
}); });
request.addEventListener('load', function(event) { request.addEventListener('load', event => {
that.updateProgress(index, 1); this.updateProgress(index, 1);
if (request.responseText !== null && request.status === 200) { if (request.responseText !== null && request.status === 200) {
var obj = JSON.parse(request.responseText); const obj = JSON.parse(request.responseText);
if (obj.error) { if (obj.error) {
alert(obj.error); alert(obj.error);
return; return;
} }
else if (callback) { else if (callback) {
callback.call(that, obj); callback.call(this, obj);
} }
} }
}); });
var data = new FormData(); const data = new FormData();
data.append('uploads', file, file.name); data.append('uploads', file, file.name);
request.open('POST', this.upload_url, true); request.open('POST', this.upload_url, true);
request.send(data); request.send(data);
}; }
UploadQueue.prototype.addProgressBar = function(index) { addProgressBar(index) {
if (index in this.upload_progress) { if (index in this.upload_progress) {
return; return;
} }
var progress_container = document.createElement('div'); const progress_container = document.createElement('div');
progress_container.className = 'progress'; progress_container.className = 'progress';
var progress = document.createElement('div'); const progress = document.createElement('div');
progress_container.appendChild(progress); progress_container.appendChild(progress);
var preview_box = document.getElementById('upload_preview_' + index); const preview_box = document.getElementById('upload_preview_' + index);
preview_box.appendChild(progress_container); preview_box.appendChild(progress_container);
this.upload_progress[index] = progress; this.upload_progress[index] = progress;
}; }
UploadQueue.prototype.updateProgress = function(index, progress) { updateProgress(index, progress) {
if (!(index in this.upload_progress)) { if (!(index in this.upload_progress)) {
this.addProgressBar(index); this.addProgressBar(index);
} }
var bar = this.upload_progress[index]; const bar = this.upload_progress[index];
if (progress >= 0) { if (progress >= 0) {
bar.style.width = Math.ceil(progress * 100) + '%'; bar.style.width = Math.ceil(progress * 100) + '%';
@ -178,9 +173,9 @@ UploadQueue.prototype.updateProgress = function(index, progress) {
bar.className = "error"; bar.className = "error";
} }
} }
}; }
UploadQueue.prototype.showSpinner = function(sibling, label) { showSpinner(sibling, label) {
if (this.spinner) { if (this.spinner) {
return; return;
} }
@ -195,15 +190,15 @@ UploadQueue.prototype.showSpinner = function(sibling, label) {
this.spinner_label.innerHTML = label; this.spinner_label.innerHTML = label;
sibling.parentNode.appendChild(this.spinner_label); sibling.parentNode.appendChild(this.spinner_label);
} }
}; }
UploadQueue.prototype.setSpinnerLabel = function(label) { setSpinnerLabel(label) {
if (this.spinner_label) { if (this.spinner_label) {
this.spinner_label.innerHTML = label; this.spinner_label.innerHTML = label;
} }
} }
UploadQueue.prototype.hideSpinner = function() { hideSpinner() {
if (this.spinner) { if (this.spinner) {
this.spinner.parentNode.removeChild(this.spinner); this.spinner.parentNode.removeChild(this.spinner);
this.spinner = null; this.spinner = null;
@ -212,4 +207,5 @@ UploadQueue.prototype.hideSpinner = function() {
this.spinner_label.parentNode.removeChild(this.spinner_label); this.spinner_label.parentNode.removeChild(this.spinner_label);
this.spinner_label = null; this.spinner_label = null;
} }
}; }
}