Drag and Drop MooTools File Uploads
Honesty hour confession: file uploading within the web browser sucks. It just does. Like the ugly SELECT element, the file input is almost unstylable and looks different on different platforms. Add to those criticism the fact that we're all used to drag and drop operations, yet up until recently, you couldn't drag files into a browser to upload them, making file uploading within the browser unintuitive. With recent advancements in browser technology, the drag and drop method is now supported, but it doesn't look good without a bit of work. Luckily MooTools Core Developer Arian Stolwijk has created a set of classes to accommodate styling drag and drop file uploading within the browser. Let's have a look at how it works!
The HTML
The basic setup is the same as a traditional form upload within the browser; a FORM
element with an INPUT
of file type:
<form method="post" action="mootools-upload.php" enctype="multipart/form-data" id="uploadForm"> <div> <div class="formRow"> <label for="file" class="floated">File: </label> <input type="file" id="file" name="file[]" multiple><br> </div> <div class="formRow"> <input type="submit" name="upload" value="Upload"> </div> </div> </form>
This setup allows file uploading even if JavaScript is not enabled. (Note to IT snobs: get over yourselves and turn JavaScript back on)
The CSS
The "drop zone" and "progress bar" areas can be easily styled in any fashion you'd like. My sample CSS looks like this:
.droppable { border: #ccc 1px solid; border-radius: 8px; background: #eee; color: #666; padding: 20px; margin: 10px; clear: both; text-align: center; } .droppable.hover { background: #ddd; } .uploadList { margin: 0; padding: 0; list-style: none; } .uploadItem { overflow: hidden; border-bottom: #BCBCBC 1px solid; margin: 0 20px; padding: 3px; } .uploadItem span { overflow: hidden; width: 150px; float: left; display: block; } a.addInputRow, a.delInputRow, .uploadItem a { display: inline-block; background: url(add.png) no-repeat; height: 16px; width: 16px; text-indent: -999px; } .uploadItem a { float: left; display: block; padding-left: 20px; background-image: url(delete.png); } a.delInputRow { background-image: url(delete.png); } .progress { margin: 5px 0; height: 15px; border-radius: 3px; background: #545A74; }
Since we have (unfortunately) become accustomed to the ugly INPUT type=file
, my only CSS advice is to make sure you make not only your "drop zone" apparent but explain that the user should drag and drop.
The MooTools JavaScript
Arian has provided 3 JavaScript classes within his mootools-form-upload repository:
Form.Upload
: The main worker class, detecting the browser capabilities and building a file uploader based on those featuresForm.MultiFileInput
: A class which builds and manages the list of files to be uploaded.Request.File
: Manages the FormData object, sends files, and reports progress.
Another resource, iFrameFormRequest, can be included in case the user is rocking a legacy browser. With the resources above added to the page, let's set up our drag and drop file uploader:
window.addEvent('domready', function(){ // Create the file uploader var upload = new Form.Upload('file', { dropMsg: "Drop files here", onComplete: function(){ alert('Files uploaded!'); } }); // Use iFrameFormRequest, which posts to iFrame if (!upload.isModern()) { new iFrameFormRequest('uploadForm', { onComplete: function(response){ alert('Files uploaded!'); } }); } });
We start by creating an instance of Form.Upload
, passing it the INPUT
node and the class options. The onComplete
option is most important, as it represents the event that fires when all uploads have completed, allowing you to notify the user.
For more customizable uploads, like notifications for progress and success, you can pair Form.MultipleFileInput
and Request.File
directly:
// From ReadMe.md // the input element, the list (ul) and the drop zone element. var input, list, drop; // Form.MultipleFileInput instance var inputFiles = new Form.MultipleFileInput(input, list, drop, { onDragenter: drop.addClass.pass('hover', drop), onDragleave: drop.removeClass.pass('hover', drop), onDrop: drop.removeClass.pass('hover', drop) }); // Request instance; var request = new Request.File({ url: 'files.php' // onSuccess // onProgress }); myForm.addEvent('submit', function(event){ event.preventDefault(); inputFiles.getFiles().each(function(file){ request.append('url[]' , file); }); request.send(); });
This solution would be good for using detailed progress bars.
Outstanding work once again by Arian. His contribution to the MooTools JavaScript framework has been priceless, and he continues that effort with his drag and drop file upload system. These classes prove the power of MooTools and the advancement of browsers today. Give your users the elegant option of drag and drop uploads!
Great stuff. This is going into my “to implement later” bag.
You didn’t link to Arian’s classes though
Added the link! No idea how I missed that!
I recently switched from jQuery to Mootools and I have to say I really like how elegant it is. The forge alone is an unbeatable resource and the OO approach for me, as a web application developer, is just perfect. I am redesigning the image gallery for our website and was trying to find a simple and easy way to manage multiple file uploads. I originally was using Uploadify but now I have come across this jewel. Thank you for all of your contributions to the open source community and I will definitely be waiting for your next post, cheers!
David, I don’t know if you know this or not, but you are my hero! :D keep up all of the great tuts, I hit up your site daily.
When David writes new articles about MooTools stuff, I’m in ecstasy.
I love MooTools so much that if David was a female I would also love him.toFemale();
I don’t even care if Joomla ditches MooTools in its next major version. I feel so high!
Hi there,
This looks awesome! although on trying to implement, I find that I don’t understand where the files are being uploaded to?
Could someone point in the right direction please?
Thanks
They’ll be uploaded to the form’s “action” attribute / URL.
Thanks for the reply, I had tried that, perhaps I had some permissions issues.. Regardless, I’ll give it another go and thanks for the reply! :)
Is the request showing up in Firebug? It should…
actually no.. Although I need to put this out on the web somewhere so perhaps someone else could verify.. Embarrassingly I’ve not used firebug until today :$ and I’m not sure if it’s just me mis-reading things..
I’ll try and get something on the web and post.. here again?
I’m also having problems figuring out where the files are going…
“the drag and drop method is not supported” You mean the opposite =
“the drag and drop method is now supported” I assume.
I like this, but I unable to remove files from the collections, file names are removing from display but not from collections.
Please do the needful
Hi,
very nice snippet.
But can you give me a hint how the php-file shld look like to handle the files and save them on the server?
kind regard
ani
I see that file ‘file.php’ is incomplete. The tag php dont close.
For something reason. The file ‘file.php’ isnt to loaded. That way, we cant be implementing a code for upload the files.
Is there any thing special i need to do to update this code to work with mootools 1.4.5 ? (Joomla 2.5 included mootools)
The drag and drop seems to work. The images get added to the list. the delete button seems to remove the images when clicked as well.
But when I hit my Submit button (or the upload from the example) I get this following error threw firebug :
event is undefined
(?)(event=undefined)Form.Upload.js (line 78)
fireEvent(f=function())mootools-core.js (line 375)
forEach()mootools-core.js (line 40)
i = function()
v = form#adminForm index.php
fireEvent(e="submit", c=[], b=undefined)mootools-core.js (line 375)
submitform(a="fichephotoupload.save", b=form#adminForm index.php)core.js (line 4)
submitform(a="fichephotoupload.save")core.js (line 4)
onclick(event=click clientX=1726, clientY=124)index....onclick (line 2)
[Break On This Error]
event.preventDefault();
Something to do with: Form.Upload.js (line 78)
any ideas?
can i please have a copy of your source code?
http://davidwalsh.name/demo/mootools-upload.php
where is the source code ! i tried to try make new uploader ! link ? link ?
works great, progress indicator is there but integer percent showing would be great idea too.
Great job !! congratulations!! could you post a link to download the source code?
Please i need it .
Thanks in advance.
I’m using your library to be able to upload videos in YouTube through
XMLHttpRequest
.I can successfully upload a video but after uploading Youtube respond with a HTTP 302 header, how can I follow the redirection url or how can I get the redirection url?
I hope someone has a solution for this.
Has anyone all files? I´m missing the mootools-upload.php… Can anyone send me all the files to “wick.moritz{at}gmail.com” ? Thanks!
here is demo code and script files
https://github.com/arian/mootools-form-upload
Can I make upload for single file ? How to do it? Thanks
I’m not able to use this either. Seems that the files.php only has 8 lines of code. Looking at the version comments, it looks like it should be doing the work of saving the files, but isnt doing anything.
Please give us the contents of files.php…
Doesn’t seem to work with any version of IE. IE10 returns true to (‘FormData’ in window) but you can’t drop your files. So, that being as it is I altered the code just a bit:
Hi David,
Thanks for this wonderful script. I would like to send extra parameters to the upload page. I tried using vars parameter but the script not working as expected. I have passed the values from hidden input value. Can you pls explain how can we send the extra parameters to the uploader page ?
Great post as always. I use this upload system. One thing I noticed was some commenters looking for info on how to process the file at the php side. I suggest a very good place to start is here:
http://www.sitepoint.com/file-uploads-with-php
It explains the issues clearly and importantly give you an idea how to deal with the important security issues associated with file upload.
I tried the sample code given but unable to get it working.
I basically wrote a PHP class to handle all the generating the form and actions for it.
And inside Form.Upload.js, I had to comment out
For it to call my php script after submitting the files but still unable to get the files uploaded as the $_FILES array is empty.
Please advise. Thanks.
in the above code inputname is the name for the file if i want to change it to image what should i change with
Hi,
I was stuck when post my form values along with the files value, but I am unable get the form data.
I want to implement drag drop feature in my contact form.
Can you help me to get the form data with files data.
Waiting for you reply.
Thanks,
Khalid Khan