Drag out files like Gmail
Google in their quest to keep me busy in trying to figure out how they do their innovative features in Gmail are at it again. First it was drag and drop uploading which used a clever trick to make it work in Chrome which currently doesn’t support the FileReader in their stable release. Now they’ve added the ability to drag out attachments to your file system, allowing you to bypass the usual method of the save dialog.
While the first feature of drag and drop uploading I figured out quite easily, this drag out feature was a doozy.
How did I figure it out?
There were two clues which got me started. One it only works in Chrome so it had to be an extension to the current Drag and Drop API. Two, after some poking around in gmail, there was a custom attribute on the attachment link called download_url which colon separated the attachments mime type, file name and download link.
Since Gmails JavaScript is obfuscated to within in an inch of its life there was no easy way to attach the built in debugger to anything that might give it away. So I tried downloading the script and running it through various unobfuscaters which made it format nicely but I still had to work with function names like vHG etc.
My last hope was chromiums bug tracker and searching to see if any bugs or feature requests were filed that could help give it away. I knew the download_url attribute played a role and it would be set using setData method on the dataTransfer object. So I searched high and low on Chromiums bug tracker for matches to “download_url”, “downloadurl” & “downloadurl setData” nothing nada, zip. So I turned to the webkit bug tracker, still nothing! So I thought maybe Mozilla had discussed it on their bug tracker, a long shot but worth a try. Bingo! This bug led me to this bug, on webkits bug tracker don’t ask why the search didn’t bring this up, and then onto this proposal. We’re in business!
How does it work?
So we’ve found the details let’s play with it.
Update: I’ve rolled out drag to desktop across my site for all my demo source files. If you’re using Chrome 5+ just drag the “Download the source files” link to your desktop!
The above demo will, in Chrome 5+, allow you to drag any of the items to your desktop and save them without having to go through the usual save dialog process.
var file = document.getElementById("dragout"); file.addEventListener("dragstart",function(evt){ evt.dataTransfer.setData("DownloadURL",fileDetails); },false);
From the code above you attach an ondragstart event listener to something you want to “drag out” and save to your file system. On the dragstart event you set the data using the new “DownloadURL” type and pass file information to it.
In order to pass the correct information to the event we access the download_url attribute and use that for our setData call. I’ve made one change that is slightly different to how Gmail sets and gets the attribute.
<a href="Eadui.ttf" id="dragout" draggable="true" data-downloadurl="
application/octet-stream
:Eadui.ttf
:http://thecssninja.com/gmail_dragout/Eadui.ttf">Font file</a>Instead of creating a new attribute I have instead used the new custom data attributes specified in the HTML5 spec. While not officially supported by Chrome yet we can still use it and add a simple test for support and fork the code either way.
The custom attribute needs three things specified that are separated by colons in order for it to work. The files mime type, the name you wish it to be saved as (this can be anything) and the url to where the file can be downloaded from.
var fileDetails; if(typeof file.dataset === "undefined") { // Grab it the old way fileDetails = file.getAttribute("data-downloadurl"); } else { fileDetails = file.dataset.downloadurl; }
Above I do a check to see if the element supports the dataset attribute if not use getAttribute to grab the value.
A cool finding
Playing around with this new functionality I did find a cool side effect that if I drag a file that’s set the DownloadURL type on the setData method into a page using Firefox 3.6+ that will capture a drop event the dataTransfer file attribute will act as though it’s captured a local file and can be manipulated with the FileAPI e.g. In my font dragr web app if I drag a font file that’s been attached to an email it will render the font as though I’ve dragged it from my local file system! Doing the same with Chrome 6, which also supports file attribute on the dataTransfer property, will ignore the drop.
Predicting the next challenge from Google
So what do I think the Gmail team will do next? Since they announced, and are now starting, their 6 week release cycle of chrome. I foresee the ability to upload folders not just individual files, being able to capture a photo from your web cam straight into an embedded picture using the proposed media capture proposal. Whatever it is I’m sure it’ll knock everyone’s socks off and make me rack my brain in trying to figure it out.
Short URL: http://cssn.in/ja/028
Post filed under: html5, javascript.
Comments
Trackbacks
-
[...] » HowTo: GMail File Dragout Der CSS Ninja hat eine gute Anleitung erstellt, wie er den File Dragout von GMail entsprechend nachgebaut [...]
-
[...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtmlthecssninja.com [...]
-
[...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtml – August 25th %(postalicious-tags)( tags: javascript html5 css gmail dragdrop chrome download file reference )% [...]
-
[...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]
-
[...] This post was Twitted by theystolemynick [...]
-
[...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]
-
[...] via Drag out files like Gmail | The CSS Ninja — All things CSS, Javascript & xhtml. [...]
-
[...] }Brad Neuberg Read Post Ryan Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]
-
[...] 26 Aug 2010 Powered by Max Banner Ads Ryan Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]
-
[...] La gente de CSS Ninja ha publicado un artículo explicando como conseguirlo nosotros mismos en nuestras páginas…. [...]
-
[...] by a blogpost of the css-ninja which i stumbled upon at ajaxian.com, i quickly hacked this jQuery plugin – [...]
-
[...] http://www.thecssninja.com/javascript/gmail-dragout [...]
-
[...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtml (tags: dragdrop file web) This entry was posted on Friday, August 27th, 2010 at 8:04 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. « links for 2010-08-24 [...]
-
[...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]
-
[...] [...]
-
[...] Drag Files out of Browser onto Desktop – http://www.thecssninja.com/javascript/gmail-dragout Drag File into Browser Upload – [...]
Very well done! You are a true thinker, keep up the good work!
Nadav, August 17th, 2010seems that it works in firefox too
l4u, August 17th, 2010@l4u – Firefox appears to work but what it’s really doing is creating a shortcut to the anchor link where ever you drag it out to on windows. Not sure what it does on other OS platforms.
The Css Ninja, August 18th, 2010Nice, this is pretty cool. I hate that damn save file dialog box.
Jared, August 21st, 2010I didn’t even know you could do that in gmail.
Great work, thanks! A quick test shows this also works for Data URLs, which thus offers an easy way to download client-generated files. Awesome!
Alexis Deveria, August 26th, 2010@Alexis – Nice, the canvas image editors could benefit from that.
The Css Ninja, August 27th, 2010On firefox on ubuntu it works, and it downloads the file to the desktop. (nautilus does the download job, not the browser)
Jonathan Schemoul, August 29th, 2010Nice article! I am trying to apply this to my product, but having no success in dragging a div out of the browser window. I feel like dnd from browser to desktop is only applicable to <a> and <img>.
What I tried to do is that when I drag a div item, I change the event object’s target/srcTarget properties to point to a hidden element that contains the data-downloadurl, but those properties (event.target/event.srcTarget) seem to be somewhat read-only.
I cannot change the div item to <a> . Any suggestion on how I can drag this thing out without adding anything visual (such as an explicit download link or icon) to the UI?
Thanks!
David Tong, September 4th, 2010@David T – That’s because anchor and img elements are natrually draggable, to enable it for other elements you need to add the draggable attribute and some CSS for webkit browsers.
<div draggable="true"></div>and the CSS for webkit browsers.
like usually, always write great article…
Beben, September 13th, 2010its like a jutsu in ninja :P
thanks a lot ☼ ○
Ninja, I submitted a bug to Chromium titled “dataTransfer setData multiple formats does not work in Chrome for Windows if one of the types is ‘DownloadURL’”
http://code.google.com/p/chromium/issues/detail?id=55071&can=5&colspec=ID%20Stars%20Pri%20Area%20Feature%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS
From your research on this topic, did you find a workaround for this issue?
Warren, September 19th, 2010@Warren – No I haven’t come across that issue thanks for the heads up.
The Css Ninja, September 20th, 2010This is cool. I noticed that FF and IE allow drag and drop images to the desk top. I did a little test to see if that could be exploited to accomplish a wider drag out functionality.
In FF 3.6 I was able place an image on a page using the name of a file I would ultimately like to dnd to the desktop. At render time it pointed to a gif (but was named myfile.txt). Image rendered fine. I also ensured the file was not cached by using server. I attached some synchronous AJAX code to the drag start that changed the content of myfile.txt on the server. Made it contain text.
When the user clicks the image and DnD’s to the desktop, the file is re-loaded from the server and copied to the desktop. The result was a file named myfile.txt that contains text (not the original image).
In IE 8.0 this did not work. I think because the file was not a known image mime type, IE would not allow me to drop it on the desktop.
Foss Tighe, October 6th, 2010I noticed that this works fine dragging to the desktop but dragging into another HTML page (I tried with http://www.html5rocks.com/tutorials/file/dndfiles/#toc-selecting-files-dnd ) doesn’t seem to work.
I’m in Chrome on Windows… is this the bug @Warren is talking about above?
Anentropic, November 22nd, 2010@Anentropic – Dragging from Chrome to Firefox with the html5rocks demo loaded in Firefox will work like you are dragging a local file from your file system. This behaviour only seems to work in Firefox and not Chrome. It’s not the bug that @Warren is talking about.
The Css Ninja, November 22nd, 2010@ninja but it doesn’t work for me, either chrome->chrome or chrome->firefox… it doesn’t work like dropping a local file. The drop page reacts, but with a blank content. This is different to if you first drag out of chrome onto the desktop and then from the desktop into the drop page.
Anentropic, December 7th, 2010@Anentropic – It works for me from chrome 8 to FF3.6. I did a quick screencast to prove it http://screenr.com/StL this has worked for me on Vista and Win7. Haven’t tried Linux or Mac.
The Css Ninja, December 8th, 2010@ninja hmm, I’ll try again with your fontdragr page on Win 7 some time. With FF3.6 and Chrome 8 on OSX it still doesn’t work – the drop box highlights but doesn’t receive anything (and Chrome -> Chrome it doesn’t even highlight). Probably not your code, but obviously still some issues with the browsers on this feature!
Anentropic, December 8th, 2010It could very well be a windows only side effect. Chrome to Chrome doesn’t work it’s only Chrome to Firefox that works for me. I’m using the propriety CSS psuedo-class
The Css Ninja, December 9th, 2010:-moz-drag-overfor the highlight on drag over in Firefox.@ninja …just tried on Win 7, FF3.6.12, Chrome 8… it works! :)
Anentropic, December 10th, 2010is there a possibility to drag out multiple files at once? Any ideas on that?
tariq, January 29th, 2011@tariq
The Css Ninja, January 29th, 2011Not at the moment but that would a useful addition to fleshout for the Chromium team if they ever decide to spec the downloadURL.
Dragging out file from browser is easy, if you don’t want any script tag, you can do this.
For example:
Which do the same thing. (You can also use div instead of a)
Derek, March 23rd, 2011Read Google’s http://www.html5rocks.com/ for more info. :)
Great article. Great comments.
> and the CSS for webkit browsers.
For other browsers, it is user-select: none;
The entire rule set:
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
}
See you on Twitter: @4digitalmasters
@4digitalmasters, April 29th, 2011Doesn’t work in Firefox 8 (FF8) on OS X Lion.
Looks like they’ve dropped support. The only reference I could find is for extensions:
Dragging files to an operating system folder
https://developer.mozilla.org/User:venesa/Recommended_Drag_Types#Dragging_files_to_an_operating_system_folder
AJ ONeal, November 12th, 2011@AJ ONeal –
This never worked for Firefox, only Chrome as they added support for the proprietry “downloadURL” type.
Ryan Seddon, November 16th, 2011Cool! Good Job!!
iuwei, December 25th, 2011