pics/public/js/upload_queue.js

179 lines
4.6 KiB
JavaScript

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();
}
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.addPreviewForFile(that.queue.files[i], i, callback);
};
});
that.submit.addEventListener('click', function(e) {
e.preventDefault();
that.process();
});
};
UploadQueue.prototype.clearPreviews = function() {
this.preview_area.innerHTML = '';
}
UploadQueue.prototype.addPreviewForFile = function(file, index, callback) {
if (!file) {
return false;
}
var preview = document.createElement('img');
preview.title = file.name;
preview.style.maxHeight = '150px';
var preview_box = document.createElement('div');
preview_box.id = 'upload_preview_' + index;
preview_box.appendChild(preview);
var reader = new FileReader();
var that = this;
var appendMe = function() {
preview.src = reader.result;
if (callback) {
preview.addEventListener('load', function() {
callback();
});
}
that.preview_area.appendChild(preview_box);
};
var waitForMe = function() {
var previews = that.preview_area.childNodes;
if (previews.length === 0 || previews[previews.length - 1].id === 'upload_preview_' + (index - 1)) {
appendMe();
} else {
setTimeout(waitForMe, 10);
}
};
reader.addEventListener('load', waitForMe, false);
reader.readAsDataURL(file);
};
UploadQueue.prototype.process = function() {
this.showSpinner(this.submit, "Preparing to upload files...");
var files = this.queue.files;
for (var i = 0; i < files.length; i++) {
this.setSpinnerLabel("Uploading file " + (i + 1) + " out of " + files.length);
var callback = (i !== files.length - 1) ? null : function() {
this.hideSpinner();
};
this.sendFile(files[i], i, callback);
};
};
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;
}
else if (callback) {
callback.call(that, obj);
}
}
});
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';
var progress = document.createElement('div');
progress_container.appendChild(progress);
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";
}
}
};
UploadQueue.prototype.showSpinner = function(sibling, label) {
if (this.spinner) {
return;
}
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;
}
}
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;
}
};