Skip to content

Instantly share code, notes, and snippets.

@paulherron
Created September 28, 2012 11:24
Show Gist options
  • Save paulherron/3799276 to your computer and use it in GitHub Desktop.
Save paulherron/3799276 to your computer and use it in GitHub Desktop.
XHR multiple image upload
$(document).ready(function() {
var fileInput = $('#ImageImage');
var fileList = $('#file_list');
var form = $('#ImageAdminAddForm');
var fileCount = 0;
// The submit button might have loaded 'disabled' (e.g. if the page was refreshed half-way through an upload) so be sure to remove this.
$('input[type=submit]', form).removeAttr('disabled');
/**
* Creates a thumbnail preview of the specified file, with progress bar.
* @param object file The selected file to upload
* @param int fileNumber Which number file this is in the batch upload
*/
function createPreview(file, fileNumber) {
var li = document.createElement('li'),
div = document.createElement('div'),
img,
progressBarContainer = document.createElement('div'),
progressBar = document.createElement('div'),
reader,
xhr,
fileInfo;
// If the file is an image and the web browser supports FileReader, present a preview in the file list.
if(typeof FileReader !== 'undefined' && (/image/i).test(file.type)) {
img = document.createElement('img');
img.title = file.name;
if(window.webkitURL) {
img.src = window.webkitURL.createObjectURL(file);
} else {
img.src = window.URL.createObjectURL(file);
}
li.appendChild(img);
}
progressBarContainer.className = 'progress_bar_container';
$(progressBarContainer).attr('id', 'progress_bar_container_' + fileNumber);
progressBar.className = 'progress_bar';
progressBarContainer.appendChild(progressBar);
li.appendChild(progressBarContainer);
$(progressBarContainer).html('Ready to upload…');
fileList.append(li);
}
/**
* Uploads the specified file, alongside all the other fields in the form.
* @param object file The selected file to upload
* @param int fileNumber Which number file this is in the batch upload
*/
function uploadFile(fileNumber) {
file = fileInput.prop('files')[ fileNumber ];
console.log('uploading file ' + fileNumber);
progressBarContainer = $('#progress_bar_container_' + fileNumber);
progressBar = document.createElement('progress');
progressBarContainer.html(progressBar);
xhr = new XMLHttpRequest();
// Update the progress bar as the file uploads.
xhr.upload.addEventListener('progress', function (evt) {
if(evt.lengthComputable) {
percentComplete = (evt.loaded / evt.total) * 100;
console.log(percentComplete);
progressBar.max = 100;
progressBar.value = percentComplete;
}
}, false);
// Show in the progress bar when the upload is complete.
xhr.addEventListener('load', function () {
progressBarContainer.addClass('uploaded');
progressBarContainer.html('<span>&#10003;</span> Done');
console.log('upload for file ' + fileNumber + ' finished');
if(fileNumber < fileCount - 1) {
// As there are more files to upload, call the upload function again.
uploadFile(++fileNumber);
} else {
// As all the files were uploaded, redirect.
if(typeof xhr.responseText !== 'undefined') {
window.location = JSON.parse(xhr.responseText).redirect_url;
} else {
window.location = document.referrer;
}
}
}, false);
xhr.open('post', location.pathname + '.json');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// Get the entire contents of the form, including all fields.
formSubmission = form.clone(true, true);
// This script aims to upload the images one-by-one, so if multiple images were selected they need to be removed from the submission.
$('#ImageImage', formSubmission).remove();
formData = new FormData(formSubmission[0]);
// Now append the one image to be uploaded to the POST request.
formData.append('data[Image][image]', fileInput.prop('files')[ fileNumber ]);
xhr.send(formData);
}
/**
* Monitors for a new selection of files being made.
*/
fileInput.change(function() {
if(typeof this.files !== 'undefined') {
fileList.empty();
for(var i=0, l=this.files.length; i<l; i++) {
createPreview(this.files[i], i);
}
}
});
/**
* Monitors for the form submit button being pressed, and uploads the files.
*/
form.submit(function(event) {
fileCount = fileInput.prop('files').length;
if(typeof fileInput.prop('files') !== 'undefined' && fileCount) {
// Convey that the upload is happening by disabling the submit button and jumping to the first file in the upload list.
$('input[type=submit]', form).attr('disabled', 'disabled');
// Scroll up to the file list to show that the upload has begun.
window.location.hash = 'file_list';
event.preventDefault();
uploadFile(0);
}
return false;
});
/**
* Dynamically updates the selected="selected" attributes on <select> options when a different option is chosen. Otherwise FormData will send values for whatever was selected when the page first loaded, which is not desired.
*/
$('select', form).change(function() {
newValue = $(this).val();
$('option', this).removeAttr('selected');
$('option[value="' + newValue + '"]', this).attr('selected', 'selected');
});
});
@johnyardstick
Copy link

This helped me wrap my head around this.

SO THANKS! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment