Tech Stuff

But Working On It Anyway

I’d love to get the jQuery-file-upload gadget working. It looks wonderful, but it would require some rewriting to get it to do what I need.

And that is, have multiple file-upload widgets across a form. What we’re doing here at the shop is a review in which people from each department have to answer a long questionnaire. Most of the fields are text-entry, but interspersed among them are file uploads for supporting documents.

It’s a long and detailed questionnaire, so we’re assuming that no one is going to do it in one sitting. The jQuery autosave plugin works for most of it, but the file uploads make it necessary to have some kind of asynchronous way to push them up to the server, store them in the right place, and make the right entries to the database.

The jQuery-file-upload plugin would make it so I have to break the single form into multiples, or else put all the file uploads together into one place, which would be confusing.

So Uploadify it is, because it works on the file upload element itself, not the entire form.

Yesterday afternoon I ripped out my old Uploadify code and re-built it from the ground up. Here’s the gist of how it works:

Include the stylesheet:

<link rel="stylesheet" type="text/css" href="js/uploadify.css" />

Pull in the JQuery libraries I’m using:

<script src="js/jquery-1.6.3.min.js" type="text/javascript"></script>
<script src="js/js/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
<script src="js/jquery-validate/jquery.validate.js" type="text/javascript"></script>
<script src="js/jquery-validate/additional-methods.js" type="text/javascript"></script>
<script src="js/jquery.autosave.js" type="text/javascript"></script>

You may not need all of these of course.

Then the uploadify script itself:

<script src="js/jquery.uploadify-3.1.js" type="text/javascript"></script>

And then whatever your master script is that contains all your functions. I just happen to call it validations because it started out with the controls for form-field validation:

<script src="js/validations.js" type="text/javascript"></script>

My form fields all have IDs and names that correspond to the section of the survey they fall into, for example “III_att1” which is section 3, first attachment. I need to iterate over all 12 file upload fields and apply the widget. I also have to define three fields based on the HTML itself, because Uploadify doesn’t capture them dynamically. So start with the usual jQuery opener:
$(document).ready(function(){

And define the three global values:
var user = $('#shortname').val() ;
var submitted = $('#submitted').val();
var submissionid = $('#submissionid').val();

Next, start a loop for all the upload fields:
$('input:file').each(function() {

As I mentioned earlier, each field has a unique ID. We need to grab it:
var myinputfield = $(this).attr('id') ;

Then we summon forth the uploadify function and apply it to each. I’ll prepend the pound sign so that jQuery knows what we’re working with:
$('#' + myinputfield).uploadify({

Then — and this is some of what made me nuts yesterday so I had to build it from scratch — the two main files:

'swf' : 'uploadify/uploadify.swf',
'uploader' : 'uploadify/upload.php',

“upload.php” is going to be your own server-side script for handling the upload submission. They provide a basic example, but you’ll certainly need to do something different. Ours re-names the file, puts it into a directory for the user submitting the form, and a subdirectory for that submission. Then it records the entry in the database.

If you’re really keeping it simple, that’s almost enough. But in this example, you have to provide some of the additional form data so that it knows where to put it. Here we’re picking up the fixed values from the form, and also which form element this actually is so that it can be named and stored accurately on the back-end:

'formData' : {'user' : user, 'submissionid' : submissionid, 'field' : myinputfield},

We’re only allowing one file per field:

'multi' : false,

And only certain file types, which we explain with a helpful block of text:

'fileTypeDesc' : 'Office files, PDFs, images, zip',
'fileTypeExts' : '*.doc; *.jpg; *.gif; *.tif; *.tiff; *.png; *.mht; *.pdf; *.ppt; *.xls; *.docx; *.xlsx; *.pptx; *.zip' ,

That by itself will do for a simple implementation. Some things like status bars and success messages are built in, but I want to add a little more. The ‘onUploadSuccess’ and ‘onUploadError’ methods let me do it.

Adjacent to each file upload block there is an additional empty span with an ID of, for example, “III_att1note”. There’s also a hidden field, which we use for form validation (since Uploadify removes the original upload field and replaces it with a Flash movie there’s no static input:file for it to check, so we have to make one) named something like “III_att1_s” (“s” for success!).

So our onUploadSuccess function checks the upload script’s return value, which should be something like “cleanname=theNameOfTheFileYouUploaded”. If we get that, we’ll modify the “note” and “_s” fields accordingly:
if ( cleanname ) {
$('#' + myinputfield + 'note').text('(' + cleanname + " has been uploaded. Click on the button to replace it.)");
$('#' + myinputfield + '_s').val(cleanname);
}

And then a server error catcher:
else {
data.match(/error: /);
$('#' + myinputfield + 'note').text('(Error: no file has been uploaded. Click on the button to try again. Error returned is ' + RegExp.$1 + "." );

}

We also need to trap browser or network errors. This is kind of dumbed-down:

'onUploadError' : function(file, errorCode, errorMsg, errorString) {
alert('The file ' + file.name + ' could not be uploaded: ' + errorString);
}

Then close our loops and the document.ready function:

});

});

});

Tom
Tom McGee has been building web sites since 1995, and blogging here since 2006. Currently a senior developer at Seton Hall University, he's also a freelance web programmer and musician. Contact him if you have the need for a blog, web site, redesign or custom programming!

Leave a Reply

Your email address will not be published. Required fields are marked *