One of the features I wanted to include in our new CMS system was the ability for users to upload files via AJAX, without using a form post to reload the page, and so that they can begin uploading a new file while an upload is already in progress.
JQuery to the rescue!
The plugin does the following things:
- Sets up the form so that when the user submits, an invisble iframe is added to the page, and the form post is sent to that
- Your back-end programming (PHP in my case) outputs some info as JSON to indicate whether the upload was successful
- The plugin polls the iframe until it has loaded and found some data
You can use the plugin by attaching it to an HTML upload form as so:
$('#myUploadForm').ajaxUpload({
onComplete : function(data) {
// data is the JSON output from your PHP script
}
})
The following callbacks can be passed in:
- onStart: this is called first, right when the user clicks the ‘submit’ button
- loading: this is called next, when the form has been posted and we’re waiting for the upload to complete
- onComplete: this is called when the upload has been completed, and received the JSON output from your backend script as its argument
You can download the script here, or here it is below too:
/**
* Author: James Carmichael
* www.siteclick.co.uk
*
* If you use this plugin in your project, please kindly consider linking to the above
*
* JQuery ajax upload plugin
*
* v0.1 22/06/2008
* v0.2 01/05/2009 Added 'onStart' function to settings, so upload start can be detected
*
* License: MIT
*/
jQuery.fn.ajaxUpload = function(settings) {
// Set defaults
var settings = jQuery.extend({
'loading' : function() {},
'onComplete' : function() {},
'onStart' : function() {},
'type' : 'json'
}, settings);
var _this = this;
// For each item
return this.each(function(){
jQuery(this).submit(function() {
// Do onStart function
settings.onStart(this);
// Make up a number
var iframeId = 'upload_' + Math.round(Math.random() * 1000000);
// Create iframe for data transfer
var iframe = jQuery('<iframe name="' + iframeId + '" id="' + iframeId + '"></iframe>');
jQuery(document.body).append(iframe);
jQuery(iframe).hide();
// Set form action attribute
jQuery(this).attr('target', iframeId);
// Call the loading function
settings.loading();
/**
* Function to poll iframe every second
*/
_this.pollIframe = function() {
// Get iframe HTML
var html = jQuery('#'+iframeId).contents().find('body').html();
// Data blank - try later
if(!html) {
window.setTimeout(_this.pollIframe, 1000);
return;
}
// We have some data - send it to the oncomplete function
switch(settings.type) {
case 'json':
var data = eval('('+html+')');
settings.onComplete(data);
break;
}
// Discard the iframe
jQuery('#'+iframeId).remove();
}
// Begin polling
window.setTimeout(_this.pollIframe, 1000);
})
})
}
Greetings,
Thanks for posting this; I was looking for a simple ajax-y uploader to handle some image uploads without page refreshes and yours looks good and doesn’t depend on flash like most other similar scripts appear to.
I am however having a problem with it — I see the onStart and loading callbacks trigger, but the upload form does not appear to submit, and the onComplete callback is never called.
My upload form is created in a table cell on demand, and then I call .ajaxUpload() on it like this:
[...]
var $dataid = ...
var $formid = ...
var $this_form = ...
td.html($this_form);
$('#' + $formid).ajaxUpload({
onStart: function() {
console.log("Upload for dataid " + $dataid + " starting!");
td.html("Loading anim maybe goes here?");
},
loading: function() {
console.log("Upload for dataid " + $dataid + " loading!");
td.html("Loading anim goes here!");
},
onComplete: function(returned_json) {
console.log("Upload for dataid " + $dataid + " complete, status " + returned_json);
td.html("Image thumbnail goes here!");
}
});
I’m using jQuery v1.6.2. When I trigger the creation of the form it looks fine. I select a file and click the submit button to start the upload, and I see the onStart and loading callbacks are called and log to the console, but no request is sent to the server, and the onComplete callback is never called.
I’m using Firefox 6 (on Ubuntu/Linux) at the moment. If I try with Chrome 13, the upload request appears to actually be sent, but the onComplete callback still doesn’t fire.
Any advice? Does this script have incompatibilities with newer jQuery or newer browsers? Is there any info I can collect you’d like to see?
Thanks,
Charles