UploadQueue: refactor into proper ECMAScript class
This commit is contained in:
parent
54b69ecd11
commit
229fb9e5bf
@ -1,215 +1,211 @@
|
|||||||
function UploadQueue(options) {
|
class UploadQueue {
|
||||||
this.queue = options.queue_element;
|
constructor(options) {
|
||||||
this.preview_area = options.preview_area;
|
this.queue = options.queue_element;
|
||||||
this.upload_progress = [];
|
this.preview_area = options.preview_area;
|
||||||
this.upload_url = options.upload_url;
|
this.upload_progress = [];
|
||||||
this.submit = options.submit_button;
|
this.upload_url = options.upload_url;
|
||||||
this.addEvents();
|
this.submit = options.submit_button;
|
||||||
}
|
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 (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);
|
this.submit.addEventListener('click', event => {
|
||||||
reader.readAsDataURL(file);
|
event.preventDefault();
|
||||||
};
|
this.process();
|
||||||
|
});
|
||||||
UploadQueue.prototype.process = function() {
|
|
||||||
this.showSpinner(this.submit, "Preparing to upload files...");
|
|
||||||
if (this.queue.files.length > 0) {
|
|
||||||
this.submit.disabled = true;
|
this.submit.disabled = true;
|
||||||
this.nextFile();
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
UploadQueue.prototype.nextFile = function() {
|
clearPreviews() {
|
||||||
var files = this.queue.files;
|
this.preview_area.innerHTML = '';
|
||||||
var i = ++this.current_upload_index;
|
this.submit.disabled = true;
|
||||||
if (i === files.length) {
|
this.current_upload_index = -1;
|
||||||
this.hideSpinner();
|
}
|
||||||
} else {
|
|
||||||
this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length);
|
addPreviewBoxForQueueSlot(index) {
|
||||||
this.sendFile(files[i], i, function() {
|
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();
|
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);
|
||||||
});
|
});
|
||||||
}
|
request.addEventListener('progress', event => {
|
||||||
};
|
this.updateProgress(index, event.loaded / event.total);
|
||||||
|
});
|
||||||
UploadQueue.prototype.sendFile = function(file, index, callback) {
|
request.addEventListener('load', event => {
|
||||||
// Prepare the request.
|
this.updateProgress(index, 1);
|
||||||
var that = this;
|
if (request.responseText !== null && request.status === 200) {
|
||||||
var request = new XMLHttpRequest();
|
const obj = JSON.parse(request.responseText);
|
||||||
request.addEventListener('error', function(event) {
|
if (obj.error) {
|
||||||
that.updateProgress(index, -1);
|
alert(obj.error);
|
||||||
});
|
return;
|
||||||
request.addEventListener('progress', function(event) {
|
}
|
||||||
that.updateProgress(index, event.loaded / event.total);
|
else if (callback) {
|
||||||
});
|
callback.call(this, obj);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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');
|
showSpinner(sibling, label) {
|
||||||
progress_container.className = 'progress';
|
if (this.spinner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var progress = document.createElement('div');
|
this.spinner = document.createElement('div');
|
||||||
progress_container.appendChild(progress);
|
this.spinner.className = 'spinner';
|
||||||
|
sibling.parentNode.appendChild(this.spinner);
|
||||||
|
|
||||||
var preview_box = document.getElementById('upload_preview_' + index);
|
if (label) {
|
||||||
preview_box.appendChild(progress_container);
|
this.spinner_label = document.createElement('span');
|
||||||
|
this.spinner_label.className = 'spinner_label';
|
||||||
this.upload_progress[index] = progress;
|
this.spinner_label.innerHTML = label;
|
||||||
};
|
sibling.parentNode.appendChild(this.spinner_label);
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
UploadQueue.prototype.showSpinner = function(sibling, label) {
|
setSpinnerLabel(label) {
|
||||||
if (this.spinner) {
|
if (this.spinner_label) {
|
||||||
return;
|
this.spinner_label.innerHTML = label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.spinner = document.createElement('div');
|
hideSpinner() {
|
||||||
this.spinner.className = 'spinner';
|
if (this.spinner) {
|
||||||
sibling.parentNode.appendChild(this.spinner);
|
this.spinner.parentNode.removeChild(this.spinner);
|
||||||
|
this.spinner = null;
|
||||||
if (label) {
|
}
|
||||||
this.spinner_label = document.createElement('span');
|
if (this.spinner_label) {
|
||||||
this.spinner_label.className = 'spinner_label';
|
this.spinner_label.parentNode.removeChild(this.spinner_label);
|
||||||
this.spinner_label.innerHTML = label;
|
this.spinner_label = null;
|
||||||
sibling.parentNode.appendChild(this.spinner_label);
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
UploadQueue.prototype.setSpinnerLabel = function(label) {
|
|
||||||
if (this.spinner_label) {
|
|
||||||
this.spinner_label.innerHTML = label;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
Loading…
Reference in New Issue
Block a user