24

I am writing an application that's supposed to support HTML5 drag/drop API for file, much like the on described here. I would like to perform a programmatic check on whether the browser support this kind of madness :) A solution that works for now is checking whether the browser provides a FileReader class, like this:

  if (typeof(FileReader) == "undefined") {
    $("#dropbox").hide();
  } else {
    // connect events
    $("#filebox").hide();
  }

But it is obviously not a correct one (I don't use that class at all).

Any ideas?

konryd
  • 541
  • 1
  • 5
  • 12

8 Answers8

19

Checking for the existence of FileReader is the correct way to go about this. FileReader is an official part of the File Api. I would combine this with Modernizr. Drag and Drop support is slated for release 1.2. You should be able to grab the source on GitHub and start working with this now. http://github.com/Modernizr/Modernizr/blob/master/modernizr.js

if (!!FileReader && Modernizr.draganddrop) {
  // sexy drag and drop action
} else {
  // no drag and drop support available :(
}

If you haven't seen Dive into HTML5, you should definitely check out Mark Pilgrim's suggestions on detecting HTML5.

µBio
  • 10,668
  • 6
  • 38
  • 56
dshaw
  • 2,129
  • 2
  • 14
  • 17
  • 1
    I'm not sure this would work. It checks for presence of attributes ondrag, ondrop, ondragleave etc. in a div object. This works in, say Chrome, but still doesn't let you drag-and-drop files into a website. – konryd Feb 22 '10 at 15:54
  • reader = new FileReader(); if (reader && Modernizer.draganddrop) {}... Need to test that out. – dshaw Feb 22 '10 at 16:10
  • Updated my suggestion to include check for the FileReader object, though if(!!FileReader) {} might be sufficient. :) I tested this in FF3.6 and Chrome and it works. – dshaw Feb 22 '10 at 16:31
  • Just realized that as I was thinking this through, you had mentioned that you thought evaluating for the presence of FileReader was incorrect. Even if you aren't going to be using the native implementation, FileReader is official spec and detecting for support of that feature is the right way to go about this. http://dev.w3.org/2006/webapi/FileAPI/#filereader-interface – dshaw Feb 22 '10 at 17:10
  • One last comment: If you're going to roll your own FileReader, you should make sure you implement the official interface. http://www.w3.org/TR/FileAPI/#dfn-filereader This way, you'll be able to drop your implementation once the FF implementation works the way you need it to work and other browsers begin to implement it. – dshaw Feb 22 '10 at 17:20
  • I'm almost sold to it, but it means, that whenever a browser implements FileReader API (which lets you read also from ) it also implements drag'n'drop files from desktopinto the browser. Those are seperate functions. Does the spec say they need to come together? – konryd Feb 23 '10 at 11:13
  • This is enough: if ("files" in DataTransfer.prototype) {...} – Paul Rouget Feb 23 '10 at 20:45
  • @konryd I don't think they need to be, but I assumed that what you were doing would require both. You should really consider Paul's suggestion. Haven't tested it myself, but Paul's a Mozilla Tech Evangelist. http://twitter.com/paulrouget I'd defer to greater his experience. – dshaw Feb 23 '10 at 22:32
  • @konryd I looked it up: http://www.w3.org/TR/html5/editing.html#the-dragevent-and-datatransfer-interfaces – dshaw Feb 24 '10 at 02:54
  • 3
    `if (!!FileReader)` in IE8 throws a "FileReader is undefined" error – matt b May 02 '11 at 19:20
  • Just curious, why `if(!!window.FileReader)` instead of `if(window.FileReader)` ? – OpenGG Aug 23 '12 at 09:05
  • @Rufus I think it's because the double exclamation point forces it to be a boolean. – David Millar Apr 10 '14 at 21:46
  • 1
    @mattb, for IE8 you need `window.FileReader`. See my answer for the full example. – matt burns Aug 14 '14 at 14:15
17

I had to make a slight change to dshaw's answer for support in IE8:

if (!!window.FileReader && Modernizr.draganddrop) {
  // sexy drag and drop action
} else {
  // no drag and drop support available :(
}

You can try it out here

Community
  • 1
  • 1
matt burns
  • 24,742
  • 13
  • 105
  • 107
  • 3
    You need !!window.FileReader in IE9 also. – detroitpro Jul 26 '11 at 04:43
  • 1
    You could include the [Modernizr.filereader](https://github.com/Modernizr/Modernizr/blob/master/feature-detects/file/api.js) which has better coverage of all browsers. – Hengjie Aug 31 '13 at 13:39
  • Maybe I don't know enough about JavaScript but is the `!!` necessary? Is not the statement `!!window.FileReader` equivalent to `window.FileReader` ? – racl101 Jul 29 '14 at 00:19
  • @racl101 it's an obscure way of object type coercion into a boolean... Not particularly readable to JS newcomers, sorry! http://stackoverflow.com/questions/784929/what-is-the-not-not-operator-in-javascript – matt burns Jul 29 '14 at 20:52
11
if ("files" in DataTransfer.prototype) {...}
Paul Rouget
  • 11,790
  • 2
  • 15
  • 10
  • 20
    No. prototype is a core JS programming construct. http://en.wikipedia.org/wiki/JavaScript – dshaw Feb 23 '10 at 22:38
  • 1
    @konryd See http://mckoss.com/jscript/object.htm for a better exploration of of JS object prototypes. – dshaw Feb 24 '10 at 02:19
  • 3
    Not sure why but following code is not working on Chrome if ("files" in DataTransfer.prototype) {alert('Drag Drop file support is there');} It says ... Uncaught ReferenceError: DataTransfer is not defined. Can you please help... – Anil Namde Jan 27 '11 at 06:30
  • 4
    webkit doesn't expose the DataTransfer object, see https://github.com/Modernizr/Modernizr/issues#issue/57 – meleyal Mar 30 '11 at 11:20
  • @konryd, why does not someone mention how the JS library Prototype got its name, here. It started at its core by adding functionality, majorly by modifying the prototypes of native objects - thats what I read – Om Shankar Jan 02 '13 at 07:41
  • 1
    Why is this marked as correct, when it actually isn't? At least not cross browser. – jayarjo May 07 '13 at 13:03
3

If you don't want to deal with Modernizr at all, you can just replicate what it does for drag'n'drop detection:

var supportsDragAndDrop = function() {
    var div = document.createElement('div');
    return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
}

Got it from Modernizr GitHub repository:

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/draganddrop.js

German Latorre
  • 10,058
  • 14
  • 48
  • 59
2

either use pure Modernizr approach

if (Modernizr.filereader && Modernizr.draganddrop) {
  //sexy drag and drop action
} else {
   //no drag and drop support available :(
};

or use underlying DOM check directly but with exception handling

var featuresSupported = false;
try {
   if (!!(window.File && window.FileList && window.FileReader) && Modernizr.draganddrop)
     featuresSupported = true;
)
catch (err)
{
}

if (featuresSupported)
  <do sexy effects>
else
  <perform rollback to legacy stuff>
Alfishe
  • 3,430
  • 1
  • 25
  • 19
1
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
  alert('The File APIs are not fully supported in this browser. Please upgrade your browser.');
}
Jamie Taylor
  • 4,709
  • 5
  • 44
  • 66
N A
  • 831
  • 2
  • 8
  • 28
1

This code fails in IE8. This would probably be better:

if (typeof(FileReader) === 'function' && Modernizr.draganddrop) {
  //sexy drag and drop action
} else {
   //no drag and drop support available :(
};
Steven Benjamin
  • 199
  • 1
  • 4
0

Its a bit trickier. iOS7 reports that it supports both FileReader and draganddrop pictures uploading. Since I was looking for a more general file upload that I couldn't do with iOS, I needed another answer.

Modernizr issue 57 at here talks about the issue. Now with windows 8 and both touch and mouse, its tricky. There's code in the middle by chriskeeble that I used successfully. It relies on Modernizr and agent detection.

Mark Kasson
  • 1,600
  • 1
  • 15
  • 28