From 229fb9e5bfc1bf863b6f3b8ac262ee13267f3f4b Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 12 Mar 2023 11:45:37 +0100 Subject: [PATCH] UploadQueue: refactor into proper ECMAScript class --- public/js/upload_queue.js | 382 +++++++++++++++++++------------------- 1 file changed, 189 insertions(+), 193 deletions(-) diff --git a/public/js/upload_queue.js b/public/js/upload_queue.js index a0953ff..54384f6 100644 --- a/public/js/upload_queue.js +++ b/public/js/upload_queue.js @@ -1,215 +1,211 @@ -function UploadQueue(options) { - this.queue = options.queue_element; - this.preview_area = options.preview_area; - this.upload_progress = []; - this.upload_url = options.upload_url; - this.submit = options.submit_button; - this.addEvents(); -} +class UploadQueue { + constructor(options) { + this.queue = options.queue_element; + this.preview_area = options.preview_area; + this.upload_progress = []; + this.upload_url = options.upload_url; + this.submit = options.submit_button; + this.addEvents(); + } -UploadQueue.prototype.addEvents = function() { - var that = this; - that.queue.addEventListener('change', function() { - that.showSpinner(that.queue, "Generating previews (not uploading yet!)"); - that.clearPreviews(); - for (var i = 0; i < that.queue.files.length; i++) { - var callback = (i !== that.queue.files.length - 1) ? null : function() { - that.hideSpinner(); - that.submit.disabled = false; + addEvents() { + this.queue.addEventListener('change', event => { + this.showSpinner(this.queue, "Generating previews (not uploading yet!)"); + this.clearPreviews(); + for (let i = 0; i < this.queue.files.length; i++) { + const callback = (i !== this.queue.files.length - 1) ? null : () => { + this.hideSpinner(); + this.submit.disabled = false; + }; + + 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.'); + this.hideSpinner(); + this.submit.disabled = false; + break; + } + + this.addPreviewBoxForQueueSlot(i); + this.addPreviewForFile(this.queue.files[i], i, callback); }; - - if (that.queue.files[0].name.includes(".HEIC")) { - alert('Sorry, the HEIC image format is not supported.\nPlease convert your photos to JPEG before uploading.'); - that.hideSpinner(); - that.submit.disabled = false; - break; - } - - that.addPreviewBoxForQueueSlot(i); - that.addPreviewForFile(that.queue.files[i], i, callback); - }; - }); - that.submit.addEventListener('click', function(e) { - e.preventDefault(); - that.process(); - }); - this.submit.disabled = true; -}; - -UploadQueue.prototype.clearPreviews = function() { - this.preview_area.innerHTML = ''; - this.submit.disabled = true; - this.current_upload_index = -1; -} - -UploadQueue.prototype.addPreviewBoxForQueueSlot = function(index) { - var preview_box = document.createElement('div'); - preview_box.id = 'upload_preview_' + index; - this.preview_area.appendChild(preview_box); -}; - -UploadQueue.prototype.addPreviewForFile = function(file, index, callback) { - if (!file) { - return false; - } - - var preview = document.createElement('canvas'); - preview.title = file.name; - - var preview_box = document.getElementById('upload_preview_' + index); - preview_box.appendChild(preview); - - var reader = new FileReader(); - var that = this; - reader.addEventListener('load', function() { - var original = document.createElement('img'); - original.src = reader.result; - - original.addEventListener('load', function() { - // Preparation: make canvas size proportional to the original image. - preview.height = 150; - preview.width = preview.height * (original.width / original.height); - - // First pass: resize to 50% on temp canvas. - var temp = document.createElement('canvas'), - tempCtx = temp.getContext('2d'); - - temp.width = original.width * 0.5; - temp.height = original.height * 0.5; - tempCtx.drawImage(original, 0, 0, temp.width, temp.height); - - // Second pass: resize again on temp canvas. - tempCtx.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5); - - // Final pass: resize to desired size on preview canvas. - var context = preview.getContext('2d'); - context.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5, - 0, 0, preview.width, preview.height); - - if (callback) { - callback(); - } }); - }, false); - reader.readAsDataURL(file); -}; - -UploadQueue.prototype.process = function() { - this.showSpinner(this.submit, "Preparing to upload files..."); - if (this.queue.files.length > 0) { + this.submit.addEventListener('click', event => { + event.preventDefault(); + this.process(); + }); this.submit.disabled = true; - this.nextFile(); } -}; -UploadQueue.prototype.nextFile = function() { - var files = this.queue.files; - var i = ++this.current_upload_index; - if (i === files.length) { - this.hideSpinner(); - } else { - this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length); - this.sendFile(files[i], i, function() { + clearPreviews() { + this.preview_area.innerHTML = ''; + this.submit.disabled = true; + this.current_upload_index = -1; + } + + addPreviewBoxForQueueSlot(index) { + const preview_box = document.createElement('div'); + preview_box.id = 'upload_preview_' + index; + this.preview_area.appendChild(preview_box); + } + + addPreviewForFile(file, index, callback) { + if (!file) { + return false; + } + + const preview = document.createElement('canvas'); + preview.title = file.name; + + const preview_box = document.getElementById('upload_preview_' + index); + preview_box.appendChild(preview); + + const reader = new FileReader(); + reader.addEventListener('load', event => { + const original = document.createElement('img'); + original.src = reader.result; + + original.addEventListener('load', function() { + // Preparation: make canvas size proportional to the original image. + preview.height = 150; + preview.width = preview.height * (original.width / original.height); + + // First pass: resize to 50% on temp canvas. + const temp = document.createElement('canvas'), + tempCtx = temp.getContext('2d'); + + temp.width = original.width * 0.5; + temp.height = original.height * 0.5; + tempCtx.drawImage(original, 0, 0, temp.width, temp.height); + + // Second pass: resize again on temp canvas. + tempCtx.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5); + + // Final pass: resize to desired size on preview canvas. + const context = preview.getContext('2d'); + context.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5, + 0, 0, preview.width, preview.height); + + if (callback) { + callback(); + } + }); + }, false); + reader.readAsDataURL(file); + } + + process() { + this.showSpinner(this.submit, "Preparing to upload files..."); + if (this.queue.files.length > 0) { + this.submit.disabled = true; this.nextFile(); + } + } + + nextFile() { + const files = this.queue.files; + const i = ++this.current_upload_index; + if (i === files.length) { + this.hideSpinner(); + } else { + this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length); + this.sendFile(files[i], i, this.nextFile); + } + } + + sendFile(file, index, callback) { + const request = new XMLHttpRequest(); + request.addEventListener('error', event => { + this.updateProgress(index, -1); }); - } -}; - -UploadQueue.prototype.sendFile = function(file, index, callback) { - // Prepare the request. - var that = this; - var request = new XMLHttpRequest(); - request.addEventListener('error', function(event) { - that.updateProgress(index, -1); - }); - request.addEventListener('progress', function(event) { - that.updateProgress(index, event.loaded / event.total); - }); - request.addEventListener('load', function(event) { - that.updateProgress(index, 1); - if (request.responseText !== null && request.status === 200) { - var obj = JSON.parse(request.responseText); - if (obj.error) { - alert(obj.error); - return; + request.addEventListener('progress', event => { + this.updateProgress(index, event.loaded / event.total); + }); + request.addEventListener('load', event => { + this.updateProgress(index, 1); + if (request.responseText !== null && request.status === 200) { + const obj = JSON.parse(request.responseText); + if (obj.error) { + alert(obj.error); + return; + } + else if (callback) { + callback.call(this, obj); + } } - else if (callback) { - callback.call(that, obj); + }); + + const data = new FormData(); + data.append('uploads', file, file.name); + + request.open('POST', this.upload_url, true); + request.send(data); + } + + addProgressBar(index) { + if (index in this.upload_progress) { + return; + } + + const progress_container = document.createElement('div'); + progress_container.className = 'progress'; + + const progress = document.createElement('div'); + progress_container.appendChild(progress); + + const preview_box = document.getElementById('upload_preview_' + index); + preview_box.appendChild(progress_container); + + this.upload_progress[index] = progress; + } + + updateProgress(index, progress) { + if (!(index in this.upload_progress)) { + this.addProgressBar(index); + } + + const bar = this.upload_progress[index]; + + if (progress >= 0) { + bar.style.width = Math.ceil(progress * 100) + '%'; + } else { + bar.style.width = ""; + if (progress === -1) { + bar.className = "error"; } } - }); - - var data = new FormData(); - data.append('uploads', file, file.name); - - request.open('POST', this.upload_url, true); - request.send(data); -}; - -UploadQueue.prototype.addProgressBar = function(index) { - if (index in this.upload_progress) { - return; } - var progress_container = document.createElement('div'); - progress_container.className = 'progress'; + showSpinner(sibling, label) { + if (this.spinner) { + return; + } - var progress = document.createElement('div'); - progress_container.appendChild(progress); + this.spinner = document.createElement('div'); + this.spinner.className = 'spinner'; + sibling.parentNode.appendChild(this.spinner); - var preview_box = document.getElementById('upload_preview_' + index); - preview_box.appendChild(progress_container); - - this.upload_progress[index] = progress; -}; - -UploadQueue.prototype.updateProgress = function(index, progress) { - if (!(index in this.upload_progress)) { - this.addProgressBar(index); - } - - var bar = this.upload_progress[index]; - - if (progress >= 0) { - bar.style.width = Math.ceil(progress * 100) + '%'; - } else { - bar.style.width = ""; - if (progress === -1) { - bar.className = "error"; + if (label) { + this.spinner_label = document.createElement('span'); + this.spinner_label.className = 'spinner_label'; + this.spinner_label.innerHTML = label; + sibling.parentNode.appendChild(this.spinner_label); } } -}; -UploadQueue.prototype.showSpinner = function(sibling, label) { - if (this.spinner) { - return; + setSpinnerLabel(label) { + if (this.spinner_label) { + this.spinner_label.innerHTML = label; + } } - this.spinner = document.createElement('div'); - this.spinner.className = 'spinner'; - sibling.parentNode.appendChild(this.spinner); - - if (label) { - this.spinner_label = document.createElement('span'); - this.spinner_label.className = 'spinner_label'; - this.spinner_label.innerHTML = label; - sibling.parentNode.appendChild(this.spinner_label); - } -}; - -UploadQueue.prototype.setSpinnerLabel = function(label) { - if (this.spinner_label) { - this.spinner_label.innerHTML = label; + hideSpinner() { + if (this.spinner) { + this.spinner.parentNode.removeChild(this.spinner); + this.spinner = null; + } + if (this.spinner_label) { + this.spinner_label.parentNode.removeChild(this.spinner_label); + this.spinner_label = null; + } } } - -UploadQueue.prototype.hideSpinner = function() { - if (this.spinner) { - this.spinner.parentNode.removeChild(this.spinner); - this.spinner = null; - } - if (this.spinner_label) { - this.spinner_label.parentNode.removeChild(this.spinner_label); - this.spinner_label = null; - } -};