So now we have a simple form that uses AJAX to upload a file and submits some metadata for the server to associate with that file.
It doesn't really give any useful feedback, though. No real end-user's going to read the console, I'm not actually doing anything with the file upload progress, and using an alert to show that the metadata uploaded is incredibly lame.
Easy part first. The response from the XHR. Add a div for feedback:
<div id="metadataFeedback"></div>
And let's make the response handler do something vaguely interesting:
if(typeof data == "error"){
alert("Error!");
console.log(args);
}else{
dojo.fadeOut({node: box, duration:0}).play();
box.innerHTML = data;
dojo.fadeIn({node: box, duration:5000, delay:500}).play();
}
(I did warn you that it was only vaguely interesting).
The point to doing the fadeOut first is to avoid animation flicker while the DOM is being updated.
Feedback about the file upload is a tad bit more involved.
Add some divs for tracking upload progress:
<div id="uploadProgress"></div>
<div id="uploadResult"></div>
So far, I've limited these articles to using events assigned in the markup. Now we have to scrape the surface of Dojo's rich event system. The nutshell version is that, in an addOnLoad method (or whenever else seems appropriate) you connect various named events to whatever function you want to fire when that event happens.
For starters, let's inform the user that we realize they've selected a file:
dojo.connect(uploader, "onChange", function(data){
dojo.forEach(data, function(d){
if(selectMultipleFiles){
dojo.byId("fileToUpload").innerHTML += "File to upload: " +
d.name+" " + Math.ceil(d.size*.001)+"kb \n";
}else{
dojo.byId("fileToUpload").innerHTML = "File to upload: " + d.name
+ " " + Math.ceil(d.size*.001)+"kb \n";
}
});
});
Letting the user know that the upload is complete should be this simple:
dojo.connect(uploader, "onComplete", function(data){
console.log("Upload complete");
console.dir(data);
dojo.forEach(data, function(d){
dojo.byId("uploadProgress").innerHTML = d.name;
// FIXME: Actually, want to display the uploaded picture
dojo.byId("uploadResult").innerHTML = "Finished: " + d;
console.dir(d);
});
});
For whatever reason, that event isn't firing. That forces me to shoehorn things in the progress event:
dojo.connect(uploader, "onProgress", function(data){
dojo.byId("uploadProgress").innerHTML = "";
// Think the forEach is for handling multiple files
dojo.forEach(data, function(d){
var progress = "(" + d.percent + "%) " + d.name;
dojo.byId("uploadProgress").innerHTML += progress;
var movie = uploader.flashMovie;
// Kludge because onComplete isn’t getting called:
if(d.percent == 100){
// Do another AJAX postback to get the URL to the image
dojo.xhrGet({
url: "/beta/test/get_url?id=some_guid",
handleAs: "text",
handle: function(data, args){
var box = dojo.byId("metadataFeedback");
if(typeof data == "error"){
// Unfortunately, w/ web2py, we never actually get here
alert("Error!");
console.log(args);
}else{
console.log("URL: " + data);
var result = dojo.byId("uploadResult");
result.innerHTML = '<img src="' + data + '" />'
}
}
});
}
});
});
Obviously, your server should be handling the file upload and be able to return a URL to the newly added picture.
Have I mentioned before that Dojo's file-handling abilities seem to leave a bit to be desired?