Warning – the demos are for this tutorial went a little crazy when I recently made a change to the jquery file. I will be working to bring the demos for this tutorial back online. Until then, don’t view the tutorials if you are using IE.


Many months ago, when trying to catch up to all the AJAX hype, I was surfing the FiftyFourEleven site looking at wonderful examples of innovative javascript code when I stumbled up some code for “Upload Multiple Files With A Single File Element“.

So when I decided to launch 15 Days of jQuery, this was one of the very first scripts that I wanted to give a jQuery makeover.

Enter the Accessibility Zealots

Looking through my server logs a few days ago I see that I’ve got a trackback from a site I don’t recognize. I check it out only to discover that two of my jQuery tutorials are being listed as an example of what the author hates about javascript.

According to this twerp, any tool or technique that doesn’t put accessibility as the numero uno priority is bad.

Although I strongly disagree with this widely held belief, it got me thinking about this particular tutorial. I went back to the drawing board and created a way to create a similar effect unobtrusively… so that if my critic decides to visit with javascript turned off, he’ll be able to use the form too.

Two Tutorials for The Price of One

Goal #1: To permit multiple file uploads using one file input element… and to make the whole interaction sexy.

Goal #2: To make multiple file uploads sexy… without sacrificing usability. The focus here is unobtrusive javascript to shape a form with multiple file input fields.

The Examples

Demonstration one – only one file input element, but with the addition of jQuery and some custom code that you’re about to see it becomes a user-friendly multiple file upload script.

Multiple file upload with one file input

Demonstration two – multiple file input elements in the (x)html source of the form but jQuery modifies what the visitor sees and gives a similar feel to the first demonstration. The advantage to this method is that it is unobtrusive… with javascript turned off the visitor can still upload multiple files.

Multiple file upload with several file inputs

Explanation

Single file input –

The jQuery $(document).ready() function does two things:

Creates a div where the maximum files allowed is shown to the visitor.
Finds the file upload field (assuming there is only one) and attaches an onChange event to it.

$("input[@type=file]").change(function(){
doIt(this, fileMax);
});

The doIt() function (nice name, huh?) checks to see if the maximum file limit has been reached, and if not, it hides the file input field, adds a new one inside the containing div, puts the name of the file chosen inside the div with id “files_list”, and adds a Delete button on the end.

To navigate the DOM tree I use jQuery’s parent() function and then remove elements using the remove() function. I also make use of append() and prepend() to add in the file names and new input fields respectively.

Two key points:

1- You determine the maximum number of files allowed with this line

var fileMax = 3;

2- The file input fields must be named appropriately

<input type="file" class="upload" name="fileX[]"
  />

I do this so that the fields can be added and removed by the visitor without any concern for keeping track of id’s or names. When the form is submitted to a server side script, the information is sent in an array that can be easily traversed.

Multiple file input –

This was was trickier to pull off.

First, the number of files allowed is determined by the number of file input fields in your (x)html. Second, you should still name them in a way that stacks the field information into an array.

<input type="file" class="upload" name="fileX[]"
  />

The big difference in this second version is that I loop through each file input field and apply the doIt() function when the field value changes. By looping through each one, I can send an additional piece of information that’s critical to my code: the order of the field in the “stack”.

In other words, as the code executes, it’s specifically targeting the first input field, or the second, or the third.

The code for this is found here:

$("input[@type=file]:nth-of-type("+n+")")

jQuery’s flexibility allows me to use CSS and XPath descriptions to target specific elements.

You’ll notice that as each file is chosen, the file input field is replaced by the name of the file. Clicking on the name of the file allows you to choose a different file.

[tags]multiple file upload, javascript, DOM, unobtrusive, jQuery[/tags]