Two months ago, we had to add a file upload feature to our webpage. Here at Trovit we have a DIY philosophy, so we decided to create our own plugin to do so.
You’ll ask, why create your own plugin when there are hundreds that do file uploading available for free on the Internet? The answer is pretty simple: if you create your own plugin you’ll generate the minimum necessary code and it will be much more centred around your needs. Surely we could have chosen the ‘jQuery File Upload’ plugin by Sebastian Tschan, a great coder, that probably has lots of features and no limitations, but for my taste, it’s more complex than needed, so when we want to make a change, our lack of knowledge of the code will make us waste precious time. But, if we create our own *good* code, taking into account our business vision, we’ll know how to create a structure oriented to our future developments and features, and what’s best, we’ll know how to improve the code when we want to change anything.
That said, let’s talk about the code. You can find it at github, and on this website, you’ll find an example. It’s a classic jQuery plugin, it takes any DOM element and creates a layer on top of it, so when it’s clicked it opens a window where you can select the files to upload. Our specifications dictated that the files need to be uploaded one by one, but at the same time, the user needs to be able to select more than one file. As lots of people know, only modern browsers allow multiple file selection, so we had to take older browsers into account as well. Also, it’s worth saying that there are means to allow old browsers to do multiple file selection, but they are not really “clean” and they require flash.
So, to initialise this layer that will simulate a “input file”, we have to load the library and select the DOM element that we want to modify in our code:
We can also add some options to it:
extensions: [‘jpg’, ‘jpeg’, ‘jpe’, ‘png’],
defaultText: ‘Default text’
The options are:
- debug: boolean, if it’s ‘true’, it shows the possible file uploading errors in the console.
- autosubmit: boolean, it’s an option that allows you to select the files, but not upload them.
- maxSize: integer, it allows to set a file size limit. Only works in modern browsers.
- maxUploads: integer. Another limit, this time it’s the number of files to upload.
- extensions: array, the file extensions that are allowed to be uploaded.
- loaderSrc, loaderWidth, loaderHeight: these options allow us to modify the image loader.
- imageWidth, imageHeight: integers, these are the width and height of the image returned by the server.
- defaultText: Once the images have been uploaded and previewed, we can select the files, and a message will show up. This option allows us to modify this message.
- arrayImages: array of images, if these images exist it will try to load them automatically.
- defaultImgPos: integer, this allows us to select one of the uploaded images as the default.
- callBeforeUpload: This allows us to specify a method that will be called before uploading the images.
So, the parameters have been explained, and I’ll explain how the plugin works, in general. When the DOM is available, it loads the layer on top of the chosen button, and if we have set the ‘arrayImages’ option it will try to load the files and preview them. If not, it will wait until the user clicks the button to start the upload. Once the button is clicked a queue is created, containing the selected images, and they are uploaded one by one, checking with each upload if we arrived to the maximum loads. If the file is larger than the threshold or if the extension is correct. Once all the checks have been passed, the plugin will upload the image. If the browser allows file uploading via AJAX we will use this method, otherwise we’ll upload the files via ‘iframe’. Once the request to the server is made (there is a fast and ugly example written in PHP on github), the plugin returns the image URL and creates its preview.
There is nothing more to add, then, except a little CSS to clean up the preview (also on github) and we’re done!
To sum up, I’d like to say that we’ve minimised all the features and developed only what was needed for our use case. This plugin could be even smaller removing all the previsualization parts. I think every library should be doing only one thing, and doing it correctly, but in this case I merged features (the file uploading and image preview). It doesn’t exactly fit my philosophy, but that’s all right, I can still sleep at night.
If you liked the post make sure to follow David on twitter!