What is dropfile.js
dropfile.js is a shim/polyfill for adding support for dragging files from the desktop to IE browsers prior to IE10 and FF prior to 3.6 browsers
Demo http://adodson.com/dropfile/
Video http://vimeo.com/18326844
<iframe src="http://player.vimeo.com/video/18326844" width="400" height="300" style="float:right;" frameborder="0"></iframe>How to use dropfile.js
-
Save dropfile.js and dropfile.xap into the same directory on your site.
-
Add to the bottom of you page the dropfile.js script
<script src="somepath/dropfile.js"></script>
-
Add HTML5 code for handling the action on an element, here i'm attaching event handling to my #holder element.
window.onload = function () { var holder = document.getElementById('holder'); holder.ondragover = function () { return false; }; holder.ondragenter = function () { return false; }; holder.ondrop = function (e) { e = e || window.event; // Read from e.files, as well as e.dataTransfer var files = (e.files || e.dataTransfer.files); var s = ""; for (var i = 0; i < files.length; i++) { (function (i) { var reader = new FileReader(); reader.onload = function (event) { holder.innerHTML = "<li><img src='" + event.target.result + "' /> " + (files[i].name) + "</li>" + holder.innerHTML; }; reader.readAsDataURL(files[i]); })(i); } return false; }; }
Working with jQuery
jQuery and other API's, wrap the original javascript event object and makes it available at e.originalEvent. This script does not recognise jQuery but does recognise the ondrop event that was assigned by jQuery and will execute that when used. However now the original event object is passed to the handler not the wrapped up event object used in jQuery. But not to worry its easy to write code which can accommodate both approaches. See http://mrswitch.github.com/dropfile/demo-jquery.htm
Browser Support
Browser | IE7 | IE8 | IE9 | IE10 | FF3.5 | FF3.6 | Chrome 6+ | Safari 5 (win) | Safari 6 (win) | Opera 10 |
---|---|---|---|---|---|---|---|---|---|---|
File API / dropfile | dropfile | File API | dropfile | File API | File API | dropfile | File API | no1 |
- Silverlight does not run in Opera, nor does Opera support the File API
Contribute
- MIT license, so anyone can use it, modify it, and add it to their own application.
- "source" folder contains the Visual Studiio Solution files if you fancy modifying the code
How it works
This fix works by "polyfilling" browsers which dont support the File API ... aka, they also dont expose file data when a file drop triggers a dropevent.
We take advantage of silverlight which does support the dragging files in. So to add this to native HTML elements in the background a dragenter event gets hijacked by a silverlight widget which sneaks under the mouse cursor and picks up the file data. The Silverlight widget then interacts with javascript, transfering data about the file(s) being dropped, which then triggers the ondrop
drop event on the element.
Break down of code
- Checks whether the browser needs has no support for the File API and
- Adds a silverlight object to the page and hides it by positioning it outside the window view
- Adds
ondragenter
event to thewindow.document
and performs the following actions: - The silverlight widget follows the mouse cursor
- Creates
window.dropfile
in the scope of the element. - When files gets dropped on to the Silverlight widget, the Silverlight widget passes file data over to
window.dropfile
which triggers the ondrop event on that element in scope - An example of which is in the sample code below.
Why it was done this way, rather than...
-
Why not, Make the Silverlight object transparent over element.
answer: The Silverlight object needs to be in "windowless" mode for transparency, however in this mode we lose the drag and drop UI. See http://msdn.microsoft.com/en-us/library/cc838156(VS.95).aspx
-
Why not, Add drop functionality implictly to objects
answer: So this is the Event Delegation vs Event Handling argument. Using Event Delegation we add this to the document ondragenter event and explicitly add this to elements which match a condition as the user drags over elements, thus avoiding having to add functional code.
-
Why not, Update e.dataTransfer.files instead of having to write (e.files||e.dataTransfer.files)
answer: The Event object dataTransfer is immutable therefore we can only pass in a bespoke method. This is only for IE8 and less, in IE9 we can define the dataTransfer files.
-
Why not... Call the widget on just the elements which have an ondrop event, rather than the whole doc.
answer: initially i required elements to have a flag to say, yes this has an ondropevent because there is no way to find out if they do (i.e. "Event delegation"). And it's too much hassle to add classNames, i guess i could add a strict mode, but i wanted a script that could be "dropped in", if you'll pardon the pun.
To Do
Shim up <input type="file" onchange="handleFiles(this.files)" >
. Aka.. add file references to the file object + trigger te onchange event.