Live Demo Download GitHub

Supported browsers

  • Firefox since 3.5
  • Chrome since 7
  • Internet Explorer since 10
  • Safari since 5
  • Opera since 11

Legacy iframe upload

  • Internet Explorer since 6

Detailed chart • Report supportedbroken

Preface

Features:

  • No JS dependencies, Flash or Java applets
  • 900 lines of code, 1300 lines of comments
  • 18 KiB minified, 6 KiB gzipped
  • HTML5, drag & drop for modern browsers
  • IFrame fallback for legacy agents (IE 6+)
  • Flexible event system with over 15 callbacks
  • Multiple independent FileDrops on one page
  • Ready for jQuery, PHP, ASP.net and others
  • 600+ lines of unit tests (tests.html)
  • /media/ie.png Internet Explorer only supports drag & drop since version 10 — previous versions can use built-in iframe fallback

References:

  1. New FileAPI usage — for Firefox
  2. GMail drag & drop — for Google Chrome
  3. The XMLHttpRequest specification
  4. hTML5 Drag And Drop And File API Tutorial
  5. Reading local files in JavaScript
  6. W3C File System API draft
  7. Folder drag & drop demo with ueful links below

Our friends:

Project news /media/feed-16.png by TextFeeder

Video tutorial on the basics

Nat Dunn from Webucator has created a video on FileDrop basics which you can check out here.

xRequestedWith option

FileDrop class has received xRequestedWith opt to change or disable the default X-Requested-With sent by the library, as per issue on GitHub.

Fixed big file support

Removed obsolete calls to readAsBinaryString() (now simulated with readAsArrayBuffer()). Also removed fd.toBinary(). Verified to work on 60 MiB files in latest Chrome and Firefox.

Also added two extra headers when sending files: X-File-Type (MIME) and X-File-Date (GMT; modification date or //now// if unknown).

Support for Chrome directories

Added listEntries() method to File using W3C's draft on File System API (now supported in Chrome 21+). This is pretty cool — check out the sample. Thanks to kevinkrouse for the reference.

Also added recreateInput option to DropHandle — when enabled (by default) lets user upload the same file twice in a row but has a slight chance to break your old code. Thanks to rafaelmaiolla.

Upload sample for ASP.Net Web Forms

Options for sendTo

It is now possible to pass an arbitrary object of values to sendTo() overriding things like XHR method (POST by default). They can also be overriden in File.opt.

Internet Explorer 10-11 support

Added and verified support for Internet Explorer 10 with its incomplete File API. Internet Explorer 11 is fully supported.

FileDrop — revamped

FileDrop just got a brand-new look and feel. Revised and extended documentation, dedicated website, fully documented code, complete test suite and validation across all possible browsers. New features like data reading and Blob slicing.

Two years and one day sharp after the first launch.

New logo

Thanks to CamiloMM for creating a beautiful new logo!

Fixes and features

  • Now throwing exception when attempting to create a DropHandle on a non-existent DOM node
  • Fixed support for inputless zones (DropHandle.opt.input set to null)
  • Added fd.all array containing all instantinated DropHandle objects
  • Added on.event - per-zone event previewer for any FileDrop class in addition to global fd.onObjCall

jQuery integration

jQuery integration function was added — simply execute fd.jQuery(); to plug it into $.filedrop(). All zone and file events are available through regular events — $.on('filesend') and so on. More details in this section.

Disabled drag & drop in IE 6-10

Disabled drag & drop for Internet Explorer 10 and below — even if they fire ondrop they actually send empty POST body upon submission. Regular <iframe> upload is still possible. Thanks to Andreas, listerical85 and others for reporting this.

Also, drag & drop was verified to work in Opera 12.15.

Fixed sendAsBinary() in Chrome

Fixed sendAsBinary() method for Chrome (and possibly others) - thanks to scratchresistor.

Fixed <fieldset> in Firefox 13+

Fixed visual bugs when <fieldset> was used as a drop zone in Firefox 13 and up.

First version

Logos & buttons

If you like FileDrop you can spread the word with these cute image (feel free to hotlink; browse directory):

/logos/16.png Icons of various dimensions: 16, 32, 64, 128
/logos/16.png The same icons not optimized for web (if the above look broken in your editor): 16, 32, 64, 128

/logos/80x15.png /logos/88x31.png /logos/ubar-h.png /logos/ubar-v.png

/logos/480x166-desc.png /logos/480x166-logo.png

Download & License

FileDrop is released in public domain — feel free to use it however you like. However, a humble backlink to this site (filedropjs.org) will inspire the author to create even more useful libraries :)

First FileDrop release has been in January 2012.

FileDrop is hosted at GitHub — feel free to fork it, report bugs and otherwise contribute to the project.

Last v1 release is available at the separate branch named v1.

See also on-line demo page which speaks better than thousand words.

For development purposes you can hotlink to the script on GitHub:

https://raw.github.com/ProgerXP/FileDrop/master/filedrop.js
https://raw.github.com/ProgerXP/FileDrop/master/filedrop-min.js

Getting started

FileDrop works out of the box in any supported browser as long as its JavaScript is linked into your page. Additionally, if you want to use legacy upload for browsers not suporting drag & drop (these include IE and Opera) you need to include the following CSS (you can change it but be careful not to break things):

css/***
  Styles below are only required if you're using <iframe> fallback in
  addition to HTML5 drag & drop (only working in Firefox/Chrome/Opera 15+).
 ***/

/* Essential FileDrop zone element configuration: */
.fd-zone {
  position: relative;
  overflow: hidden;
  /* The following are not required but create a pretty box: */
  width: 15em;
  margin: 0 auto;
  text-align: center;
}

/* Hides <input type="file"> while simulating "Browse" button: */
.fd-file {
  opacity: 0;
  font-size: 118px;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1;
  padding: 0;
  margin: 0;
  cursor: pointer;
  filter: alpha(opacity=0);
  font-family: sans-serif;
}

/* Provides visible feedback when user drags a file over the drop zone: */
.fd-zone.over { border-color: maroon; background: #eee; }

Simplest, most basic usage example is available in the included demo page as basic.html.

Nat Dunn from Webucator has created a video on FileDrop basics:

Migrating from v1

10 times more the documentation. HTML5 more the support.

New FileDrop version is not a drop-in replacement for the old one. However, there are no changes that will require you rewriting the code completely… Server-side compatibility has been preserved so no migration is necessary in this area.

You are highly encouraged to use the new version since it contains all the features of the first one while adding new ones and fixing lots of bugs and compatibility issues.

Changelog

  1. Changed names from UpperCamelCase to lowerCamelCase — e.g. SendTo became sendTo.
  2. Added return values and checks to many utility methods making them less prone to unexpected argument types.
  3. Removed semicolons.
  4. Removed hardcoded references to window.fd, wrapped everything in closure. Now it’s easy to export this module or replace window.fd with something else of your liking.
  5. Events were moved from on property to events (the former still exists but is deprecated). Added event() and preview() methods — an interface to un/binding FileDrop events (not DOM events).
  6. Renamed zone property into el (old name is still accessible but deprecated).
  7. jQuery plugin now adds $el property that requals to $(el): zone.$el.
  8. Events can now have namespaces after a colon: event:namespace. See event() description for details.
  9. Reformatted the code, removed extra indentation.
  10. multiple() no more throws an exception if the object doesn’t use xml<iframe> upload (just does nothing).
  11. SetClassesTo() was removed.
  12. Added File’s xhrSetup event (occurs before sendXHR).
  13. Renamed sendXHR event to xhrSend (old name is still accessible but deprecated).
  14. Added type (MIME) and modDate (Date object) props to File.
  15. Replaced native array object given to send event with FileList-like array-like object with some useful methods.
  16. Added File.readData() and readDataURI() to read binary/data URL/text data of the underlying native File object.
  17. Object-wise event preview was renamed from event to any.
  18. fd.onObjCall() property renamed to onObjectCall.
  19. Added dropEffect option for DropHandle.

Some functions have been renamed in addition to case change:

Samples

The minimum

To create a drop zone you need to have a basic element — such as a fieldset. It’s typically marked up in HTML and then retrieved by ID as in the example below. In this example, if you select or drop a file nothing will happen yet.

JS
// We can deal with iframe uploads using this URL:
var options = {iframe: {url: 'upload.php'}}
// 'zone' is an ID but you can also give a DOM node:
var zone = new FileDrop('zone', options)

// Do something when a user chooses or drops a file:
zone.event('send', function (files) {
  // FileList might contain multiple items.
  files.each(function (file) {
    // Send the file:
    file.sendTo('upload.php')
  })
})
HTML
<!-- A FileDrop area. Can contain any text or elements, or be empty.
     Can be of any HTML tag too, not necessary fieldset. -->
<fieldset id="zone">
  <legend>Drop a file inside...</legend>
  <p>Or click here to <em>Browse</em>...</p>
</fieldset>
Drop a file inside...

Or click here to Browse...

Reacting to success

Let’s extend the first example with a simple on-done listener:

JS
var options = {iframe: {url: 'upload.php'}}
var zone = new FileDrop('zone1', options)

zone.event('send', function (files) {
  files.each(function (file) {
    // React on successful AJAX upload:
    file.event('done', function (xhr) {
      // Here, 'this' points to fd.File instance.
      alert(xhr.responseText)
    })

    file.sendTo('upload.php')
  })
})

// Successful iframe upload uses separate mechanism
// from proper AJAX upload hence another listener:
zone.event('iframeDone', function (xhr) {
  alert(xhr.responseText)
})
HTML
<div id="zone1">
  <p class="legend">Drop a file inside...</p>
</div>

Reacting to success

Drop a file inside...

Passing custom data

When using both HTML5 and legacy uploads we can only rely on GET query variables — POST might be used to pass file data in one raw stream.

JS
var zone = new FileDrop('zone2')

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('done', function (xhr) {
      alert(xhr.responseText)
    })

    // byID() gets checkbox node by its ID:
    var value = fd.byID('upload_option').checked ? '1' : '0'
    // Change the receiving URL:
    file.sendTo('upload.php?upload_option=' + value)
  })
})
HTML
<!-- As you see we don't have to use a fieldset, any container will work: -->
<div id="zone2">
  <p class="legend">Drop a file inside...</p>
  <p>
    <input type="checkbox" id="upload_option">
    <label for="upload_option">Toggle me!</label>
  </p>
</div>

Passing custom data

Drop a file inside...

Error handling

Sometimes request might fail. Below example will handle AJAX errors. Legacy xml<iframe> upload doesn’t support error callbacks.

JS
var zone = new FileDrop('zone3')

zone.event('send', function (files) {
  files.each(function (file) {
    // Listen for errors:
    file.event('error', function (e, xhr) {
      alert(xhr.status + ', ' + xhr.statusText)
    })

    file.sendTo('this-is-a-wrong-place-to-go.php')
  })
})
HTML
<div id="zone3">
  <p class="legend">Drop a file inside...</p>
</div>

Error handling

Drop a file inside...

Timeout reporting

Error event will be fired if server returns a non-200 response code or the AJAX request fails. Note that it won’t be fired by a timeout — you need so set it up yourself like this:

Note that it isn’t possible to catch errors of legacy xml<iframe> upload so the best way is to have a timeout timer that will be aborted if server response is received earlier than it triggers.

JS
var zone = new FileDrop('zone4')

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('error', function (e, xhr) {
      if (xhr.readyState == 4 && !xhr.status) {
        alert('Timeout reached, request aborted.')
      } else {
        alert(xhr.status + ', ' + xhr.statusText)
      }
    })

    setTimeout(function () {
      // Aborting a request changes XMLHttpRequest status to
      // "done but failed" and thus fires all registered error
      // callbacks. The same happens if user aborts upload
      // implicitly by navigating away or pressing Escape.
      file.abort()
    }, 3000)

    file.sendTo('wait-forever.php')
  })
})
HTML
<div id="zone4">
  <p class="legend">Drop a file inside...</p>
</div>

Timeout reporting

Drop a file inside...

Aborting an upload

JS
var zone = new FileDrop('zone5')

// FileList is a simple array-like object
// with many useful File-related methods:
var active = new fd.FileList

// Enabling multifile upload so you can
// test aborting several requests at once
// (one file is sent by its own XMLHttpRequest):
zone.multiple(true)

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('done', function (xhr) {
      alert(xhr.responseText)
    })

    file.sendTo('wait-forever.php')
    active.push(file)
  })
})

// This is called when you click the button:
window.stopAll = function () {
  active.abort()
  alert('Aborted ' + active.length + ' upload(s).')
  active.clear()
}
HTML
<div id="zone5">
  <p class="legend">Drop a file inside...</p>
  <p><button onclick="stopAll()">Stop them!</button></p>
</div>

Aborting uploads

Drop a file inside...

IFrame fallback

Legacy xml<iframe> fallback is necessary if you want to support non-File API browsers (all but Firefox and Chrome-based agents as of today).

JS
var options = {iframe: {url: 'upload.php'}}
var zone = new FileDrop('zone6', options)

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('done', function (xhr) {
      alert(xhr.responseText)
    })

    var value = fd.byID('zone6_option').checked ? '1' : '0'
    file.sendTo('upload.php?upload_option=' + value)
  })
})

// Update <iframe> URL when the checkbox is toggled:
fd.addEvent(fd.byID('zone6_option'), 'change', function () {
  var value = fd.byID('zone6_option').checked ? '1' : '0'
  zone.opt.iframe.url = 'upload.php?upload_option=' + value
})
HTML
<div id="zone6">
  <p class="legend">Drop a file inside...</p>
  <p>
    <input type="checkbox" id="zone6_option">
    <label for="zone6_option">Toggle me!</label>
  </p>
</div>

IFrame-aware upload

Drop a file inside...

This sample is identical to that passing custom data except that upload.php was specified in iframe.url option and a listener was added to the checkbox to update upload URL when its state changes.

When user clicks the drop zone and selects one or more files in the Browse dialog FileDrop will upload them by submitting a form that’s automatically created inside the drop zone (but it doesn’t wrap its contents).

Query variables are passed differently depending on whether upload happens via xml<iframe> or not:

Zone-wrapping form

In the above example we had to manually update the xml<iframe> URL. However, if there are many elements this can be troublesome. When creating a drop zone FileDrop will first check to see if it already contains a form that can be used for legacy upload. If it does — no extra elements will be created which means that we can wrap all our input fields into a form and when FileDrop automatically submits it to the server as a result of user selecting a file that request will come along with the relevant POST data.

For this we can simply copy FileDrpo’s HTML code when it creates a regular drop zone — using Firebug or other tool.

Note that we have added name attribute to the checkbox element.

JS
var options = {iframe: {url: 'upload.php'}}
var zone = new FileDrop('zone7', options)

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('done', function (xhr) {
      alert(xhr.responseText)
    })

    var value = fd.byID('zone7_option').checked ? '1' : '0'
    file.sendTo('upload.php?upload_option=' + value)
  })
})
HTML
<div id="zone7">
  <iframe name="wrapFrame" src="javascript:false"
          id="wrapFrame" style="display: none"></iframe>

  <form enctype="multipart/form-data" method="post" target="wrapFrame">
    <input type="hidden" name="fd-callback">
    <input type="file" name="fd-file" class="fd-file">

    <p>
      <input type="checkbox" id="zone7_option" name="zone7_option">
      <label for="zone7_option">Toggle me!</label>
    </p>
  </form>

  <p class="legend">Drop a file inside...</p>
</div>

Form-wrapped zone

Drop a file inside...

Drop-only control

Sometimes you’d ditch IFrame support in favour of drag & drop goodness for Firefox and Chrome (and now Opera). For example, you have a large text area where a user can input text manually but also drop a file to be sent to the server via AJAX. This way you don’t need to create a hidden file input that, when clicked, will allow the user to select files to upload. The server can respond with some modified version of the original file that you will use to populate the area.

This is done by setting input option to false turning drop zone into pure HTML5 upload area. With this iframe options and events are no more working.

JS
var options = {input: false}
var zone = new FileDrop('zone8', options)

zone.event('send', function (files) {
  files.each(function (file) {
    file.event('done', function (xhr) {
      zone.el.value = xhr.responseText
    })

    file.sendTo('upload.php')
  })
})
HTML
<textarea id="zone8">
Type something here or drag & drop a file from your computer.
</textarea>

Drop-only control

Reading dropped data

We can enhance drag & drop onto custom control sample by avoiding server communication at all. Once we have obtained a fd.File object in FileDrop’s send event we can use its readXXX() methods to generate thumbnails or just read text or raw binary data.

readData() is heavily documented in the comments with many examples so check out the sources for the details. See also HTML5 File API samples below and sample thumb generator of the demo page.

JS
var options = {input: false}
var zone = new FileDrop('zone9', options)

zone.event('send', function (files) {
  files.each(function (file) {
    file.readData(
      function (str) { zone.el.value = str },
      function (e) { alert('Terrible error!') },
      'text'
    )
  })
})
HTML
<textarea id="zone9" readonly="readonly">
Drag & drop a file here to view its contents.
</textarea>

Reading dropped data

Progress bar

File’s progress event lets you easily track large file uploads if it’s supported by the browser. In Firefox this event only works on big files.

JS
var zone = new FileDrop('zone10')

zone.event('send', function (files) {
  files.each(function (file) {
    // Reset the progress when a new upload starts:
    file.event('sendXHR', function () {
      fd.byID('bar_zone10').style.width = 0
    })

    // Update progress when browser reports it:
    file.event('progress', function (current, total) {
      var width = current / total * 100 + '%'
      fd.byID('bar_zone10').style.width = width
    })

    file.sendTo('upload.php')
  })
})
HTML
<div id="zone10">
  <p class="legend">
    Drop a large file to see some progress...
  </p>

  <!-- You can also use <progress> tag of HTML5: -->
  <p class="progress">
    <span id="bar_zone10"></span>
  </p>
</div>

Upload progress bar

Drop a large file to see some progress...

HTML5 File API

HTML5 specification finally allows us to find out some info about user-selected files before they’re submitted to the server and it even les us read their data. FileDrop simplifies and uniformizes this access across different borwsers.

If you have a file input that you want to read files from the following code will create a collection of normalized fd.File objects and use their properties to show file info:

JS
var zone = new FileDrop('zone11')
zone.multiple(true)

// opt.input contains file input created by FileDrop:
zone.opt.input.file.onchange = function (e) {
  // eventFiles() retrieve dropped File objects in
  // a cross-browser fashion:
  zone.eventFiles(e).each(function (file) {
    alert(file.name + ' (' + file.size + ') bytes')
  })
}
HTML
<div id="zone11">
  <p class="legend">Click here to browse for files...</p>
</div>

HTML5 input change

Click here to browse for files...

Pure HTML5 drop zone

The previous example with file input and onchange is a bit oldschool. We can use HTML5 drag & drop events to catch dropped files without having to select them in a file dialog. We listen to send event just like usual but disable file input creation on this drop zone to be «completely HTML5» (no support for older browsers).

Note that files given to send is of the same type as that we obtain from eventFiles() in the example above — FileList collection.

If we leave input option enabled browsers like earlier Opera will trigger onchange event and upload the file via xml<iframe> instead of letting us read file information on drop.

JS
var zone = new FileDrop('zone12', {input: false})

zone.event('send', function (files) {
  files.each(function (file) {
    alert(file.name + ' (' + file.size + ') bytes')
  })
})
HTML
<div id="zone12">
  <p class="legend">Drop some files here...</p>
</div>

Pure HTML5

Drop some files here...

Generating thumbnails

This is among the coolest tasks — uploading photos. FileDrop makes it easy to generate thumbnails prior to sending files to the server — just when they were dropped onto your drop zone. It requires HTML5 File API support and won’t work on fallback xml<iframe> uploads. See also on-line demo page with a similar example.

JS
var zone = new FileDrop('zone13', {input: false})

zone.event('send', function (files) {
  // images() filter away all but image/* files:
  files.images().each(function (file) {
    file.readData(
      function (uri) {
        var img = new Image
        img.src = uri
        alert('Got an ' + file.type)    // e.g. image/jpeg.
        zone.el.appendChild(img)
      },
      function (error) {
        alert('Ph, noes! Cannot read your image.')
      },
      'uri'
    )
  })
})
HTML
<div id="zone13">
  <p class="legend">Drop some files here...</p>
</div>

HTML5 thumbs

Drop some files here...

Last parameter to readData() specifies the form of argument that will be passed to the first callback. For thumbs (value of xml<img src="...">) we can pass uri, url or src — all of which are aliases to readAsDataURL.

Instead of the above readData() call we could also use either this alias:

jsfile.readDataURI(
  function (uri) {
    // as above: img.src = url
  },
  function (error) {
    // as above.
  }
)

Or event this if we don’t need error handling:

jsfile.readDataURI(function (uri) {
  // as above: img.src = url
})

Partial reading — Blob slices

Another nice feature of HTML5 File API is that it allows us processing really big files with no real limit. We can read file from arbitrary offset with arbitrary length and even specify a Content-Type for the new chunk. We can treat this chunk as Data URI, text or binary data just like entire file.

FileDrop lets you read slices and handle errors using a single function — read(). readData() and readDataURI() that we’ve seen above are shortcuts much like jQuery.getJSON() and jQuery.ajax()).

JS
var zone = new FileDrop('zone14', {input: false})

zone.event('send', function (files) {
  files.each(function (file) {
    file.read({
      start: 5,
      end: -10,
      func: 'cp1251',
      onDone: function (str) {
        alert('A snippet from your CP1251-encoded file:\n' + str)
      },
      onError: function (e) {
        alert('Failed to read the file! Error: ' + e.fdError)
      }
    })
  })
})
HTML
<div id="zone14">
  <p class="legend">Drop a text file here...</p>
</div>

HTML5 file slice

Drop a text file here...

This example will display file contents starting with 5th byte and ending on 11th byte from the end (end doesn’t include given offset) treated as a string in CP1251 encoding. These options can be combined in different ways to achieve desired effect. Here’s another idea:

jsfile.read({
  // Read first 4 bytes (start defaults to 0).
  end: 5,
  // Mark them as a picture.
  mime: 'image/jpeg',
  // Read as a Data URI for our thumb <img>.
  func: 'uri',
  onDone: function (uri) {
    // We've defined no onError handler so read() will call onDone passing error
    // object with custom fdError property as the first argument.
    if (typeof bytes == 'object') {
      alert('Problem: ' + bytes.fdError)
    } else {
      fd.byID('myImg').src = uri
    }
  }
})

Reading directories

W3C has a working draft on File System API that introduces lots of interesting features allowing us to read and write files and directories (currently supported only in Chrome 21+). FileDrop lets you use its FileList and File methods to list folders, upload files, read file data (full or partial) and so on.

JS
var zone = new FileDrop('zone15', {input: false})

zone.event('upload', function (e) {
  zone.eventFiles(e).each(function (root) {
    var ok = root.listEntries(
      function (files) {
        // We now have standard FIleDrop's FileList with File
        // members that are either files or directories.
        files.images().each(function (file) {
          // Just as in the other sample...
          file.readDataURI(function (uri) {
            var img = new Image
            img.src = uri
            zone.el.appendChild(img)
          })
        })
      },
      function (e) {
        alert('Problem reading the file system: ' + e.code)
      }
    )

    ok || alert('Cannot list ' + root.name + ' - unsupported?')
  })
})
HTML
<div id="zone15">
  <p class="legend">Drop a directory with images here...</p>
</div>

File System API

Drop a directory with images here...

jQuery integration

FileDrop can be integrated with jQuery by simply calling the following method (once, after loading both FileDrop and jQuery): jsfd.jQuery().

Drop zone events are prefixed with fd while individual file events start with file. DOM node events are triggered before those assigned to obj.on.XXX arrays and if a node handler returns non-null value on’s events are skipped.

Note that jQuery will prepend its own event object in front of FileDrop’s normal event arguments since they’re triggered as regular events of a DOM node. See extensive comments in the sources for more details and examples.

More information in the corresponding section.

jsfd.jQuery()  // you can also pass an object like 'jQuery' or '$'.

// Henceforth it's possible to access FileDrop as $().filedrop().
$('<div><p>Drop something here...</p></div>')
  .appendTo(document.body)
  .filedrop()
  // jQuery always passes event object as the first argument.
  .on('fdsend', function (e, files) {
    files.invoke('sendTo', 'upload.php')
  })
  .on('filedone', function (e, file) {
    alert('Done uploading ' + file.name + ' on ' + this.tagName)
  })

FileList

New FileDrop provides special FileList object instead of arrays that were used when passing dropped files to event listeners. This object is array-like and contains useful methods for filtering, sorting and updating the collection. Below are some examples — look in the docs and sources for complete info.

jszone.event('send', function (files) {
  alert('Dropped files: ' + files.length + '\n' +
        'First file: ' + files.first().name + '\n' +
        'File recently changed: ' + files.newest().name + '\n' +
        'Biggest file: ' + files.largest().name + '\n' +
        'Number of images: ' + files.images().length + '\n' +
        'Files starting with "A": ' + files.named(/^a/i).length)

  files.sortBy(function (f) { return f.size })
  files.reverse()
})

Documentation

All FileDrop implementation is contained within window.fd object. This object includes global options, utility functions and classes (mainly FileDrop itself). window.fd can be defined before including the script (filedrop.js or filedrop-min.js) — useful if you need to override certain options before FileDrop is loaded.

For example:

xml<script type="text/javascript">
  window.fd = {logging: false};
</script>

<script type="text/javascript" src="filedrop.js"></script>

FileDrop makes extensive use of events and lets you customize virtually every aspect of the drag & drop or upload process by intercepting and overriding default handlers.

Global options

Global options are set in window.fd:

loggingIf set all event calls will be logged to console if one is present.
hasConsoleIndicates if console.log, info, warn and dir are available for usage.
onObjectCallIf set must be a function that’s called on every event being fired. See how it works in callAllOfObject().
allAll DropHandle objects that were instantinated on this page. Note that these are not FileDrop instances as not all DropHandles might be part of FileDrop+s. Use DropHandle.filedrop property to determine parent FileDrop, if any.
isIE6Test for IE version, true for 6-7 and below and false for any other version/browser.
isIE9Test for IE version, true for 9 and below and false for any other version/browser.
isChromeTest for Google Chrome. This isn’t used to determine available File API but only to work around certain event glitches.
nsPropName of Function object property where event namespace is stored. See funcNS(), splitNS(), DropHandle’s event().

Global functions

Below is a brief description of all functions placed into window.fd. Find examples and up-to-date information in the extensively commented source code.

Function signatures with zero or one arguments are omitted for brevity.

randomIDProduces random ID (non necessary unique to anything) with given prefix or ’fd’ if it’s not passed.
uniqueIDGenerates random DOM node ID that’s unique to this document with given prefix or ’fd’ if it’s not passed.
byIDRetrieves DOM element by its ID attribute or returns id itself if it’s an element.
isTag jsfunction (element, tag). Checks if given object is a proper DOM node. If tag is passed also checks if that DOM node is of the same tag (case-insensitive). Returns true or false.
newXHRCreates new XMLHttpRequest object. Falls back for ActiveX for IE 6. Throws an exception if couldn’t succeed (this shouldn’t happen these days).
isArrayChecks if given value is a native Array object. Note that jQuery and other pseudo-arrays are reported as false.
toArray jsfunction (value, skipFirst). Converts passed value into an array. If value is already an array its copy is returned (so changing value later doesn’t affect the returned clone). skipFirst, if given, omits specified number of elements from the start. Useful for turning arguments into arrays.
addEvent jsfunction (element, type, callback). Adds an event listener to a DOM element. Works for old IE as well as modern W3C-compliant browsers. type is short event name (without on prefix). Does nothing if any parameter is invalid. Returns the DOM element itself or whatever was given as this argument.
stopEventStops propagation and default browser action of an event. Works for old IE and modern W3C-compliant browsers.
setClass jsfunction (element, className, append). Adds or removes HTML class of a DOM element. Keeps old classes. element can be either ID string or a DOM node. Returns the element (even if ID was passed) or null if passed value is neither a string nor a DOM node or if there’s no element with this ID.
hasClass jsfunction (element, className). Determines if given element has class attribute containing the className word. Accepts DOM element or ID string. Returns true or false.
classRegExpReturns a regular expression suitable for testing of HTML class-like strings to find out if it contains a given word or not (it’s not as simple as a substring match: some class contains words some and class but not som and cl or ame and ass). Shouldn’t be used for testing multiple words (space-separated) — will only match if they are in the same position in testing string which doesn’t have to be true: jsclassRegExp('some class') would match this is some class but won’t match some of the class. Returns a never matching regexp for bad parameter like an object or an empty string.
extend jsfunction (child, base, overwrite). Copies properties from object base to object child. If overwrite is passed and true then base’s properties will replace those in child even if child has its own properties of that name. Note that it doesn’t clone child, it’s edited in-place. Also note that defined properties that are undefined on child are replaced by base’s even if overwrite is false (see examples). Returns the modified child (first argument).
callAll jsfunction (list, args, obj). Calls every handler of the passed callback list with given arguments and in context of obj or this if it’s omitted. list can be undefined, a single function or an array (non-function members are skipped). Throws exception if list is something else. args is converted to array with toArray() so it can be a single value, an arguments object or something else — see that function for info. Returns result of the last called function. If any function returns a non-null and non-undefined value all following handlers are skipped.
callAllOfObject jsfunction (obj, event, args). Calls event handlers attached on given FileDrop object to passed event name with arguments. Hands off most work to callAll(). obj is an object with the events property (object with keys = event names and values = arrays of functions). Before calling handlers of obj looks if global configuration has a preview handler specified — if it does then calls that handler and if it returns non-null and non-undefined value doesn’t call obj’s handlers but returns that value immediately. After the global preview function it checks for object-wise preview — its any event handlers which are treated likewise. Preview functions are called with event name pushed in front of the other event args.
appendEventsToObject jsfunction (events, funcs). Appends event listeners to given object with events property according to passed parameters. See DropHandle’s event() for details. this must be set to the object which events are updated.
previewToObject jsfunction (events, funcs). Prepends event listeners to given object with events property according to passed parameters. See DropHandle’s event() for details. this must be set to the object which events are updated.
addEventsToObject jsfunction (obj, prepend, args). Adds event listeners to given object with ’events’ property according to passed parameters. See DropHandle’s event() for details. Returns nothing if couldn’t handle given parameter combination.
funcNS jsfunction (func, ns). Adds namespace identifier to a Function object. Used when labeling event listeners in DropHandle’s event(). If given just one parameter reads attached namespace, if present.
splitNSExtracts namespace identifier from the string. Uses colon as a separator: event:namespace. Both parts can be empty. If colon is omitted returns js'' instead of namespace. Returns array with two items — event name (or other prefix) and namespace.

DropHandle class

Has some file upload functionality (mostly legacy xml<iframe>) but is mainly used to handle all drag & drop operations in a cross-browser way. You can use it as a basis for your own component. Main FileDrop class extends it and listens for produced drop events.

Constructor:

jsnew fd.DropHandle(zone, opt);
// Example:
new fd.DropHandle(document.body, {zoneClass: 'with-filedrop'});

zone — ID or DOM element which accepts drag & drop. This is often a xml<fieldset>. If such element doesn’t exist an exception is thrown when trying to create the class. DropHandle will add some children to this element to facilitate external drop events. Once created this element is accessible as js(new DropHandle(...)).el property.

opt — object, key/value pairs of options. See the code for the list of keys and their purpose. Can be omitted or empty to use defaults. Current option values are accessible as the opt property.

Properties

elReferences zone DOM node that was given to the constructor. In v1 this was named zone.
filedropIf this DropHandle was created by a FileDrop instance this property will point to that instance.

Options

zoneClassThe zone element gets this HTML class appended immediately after the DropHandle object is created.
inputClassDropHandle creates a hidden form and xml<input type="file">. The input is completely transparent so the contents underneath is visible but at the same time a dropped object lands on the input triggering its DOM events. This option specifies the class name assigned to this input.
inputContains DOM nodes of fallback upload via xml<iframe>. If null necessary elements for xml<iframe> upload will be created automatically. If this is false (boolean) then DropHandle creates no input at all. This is useful if you need pure drag & drop upload that works in Firefox and Chrome-based browsers, no <iframe> uploads for IE 9-, Opera, Safari and others. This creates «perfect» drop zone that doesn’t prevent user interaction with underlying components so the zone can be extended onto large document area or the entire window. After construction opt.input’s structure — see comments for details.
recreateInputIf using xml<input type="file"> (legacy xml<iframe> upload, see input option) some browsers including IE 6-10 and Opera will keep last selected file in the input after upload which will prevent the user from uploading the same file twice in a row (this doesn’t apply to drag & drop uploads). When enabled, this option will let FileDrop recreate the file input thus resetting file selection. This is safe in most cases but if your project does some extra customization on opt.input.file this might erase them and attached events unless you are doing that in inputSetup event. When disabled, input will be cleared in Firefox/Chrome thus preventing user from reuploading the same file one after another in other browsers.
fullDocDragDetectChrome, unlike Firefox, dispatches drop events for the entire document rather than the input element. For Chrome this option is always true. If you want the same behaviout in Firefox then you can manually set it to true to let all of your drop zones receive drop events as soon as they enter the browser’s window but not those zones’ bounds.
multipleInitial state of the multiple selection in browser’s Open File dialog appearing when clicking on the drop zone ( xml<input type="file">). After this object was created toggle this setting with jsthis.multiple().
dropEffectCursor displayed when a user drags an object over this drop zone. Working values depend on the browser. copy and none work for Firefox and Chrome; the latter also supports move, link. Setting to none will cause «No Drop» cursor and will cause drop operation to be ignored on this drop zone (on-drop event not fired). This option can be set on runtime. See this MDN page for more info and also FileList’s dropEffect property.

IFrame options for fallback upload for browsers lacking native drag & drop support — IE and others:

iframe.urlURL to send uploaded file to. It’s a regular form upload with xmlenctype="multipart/form-data" so if you’re using PHP it’s handled with PHP$_FILES as usual. The URL can have query string. It will have the fd-callback parameter appended containing the name of function your server script must call when generating JavaScript output — if it does the upload succeeds, otherwise it «fails». Calling external function is the only reliable way to know that we’ve uploaded the file right. Plus you can pass any data to that function as its parameters. For the practical server-side example see included upload.php. If unset xml<iframe> upload is disabled so only drag & drop-aware browsers (Firefox and Crhome-based) will handle this drop zone.
iframe.callbackParamName of GET input variable containing the name of the global window callback function to be called by the server in the generated page after uploading a file via xml<iframe>.
iframe.fileParamName of POST file input variable ( xml<input type="file" name="$nameParam">). Maps to PHP$_FILE[] in PHP.

Events

For the explanation of event handling see Samples, demo page and source code comments.

anyObject-wise event preview handlers. They get executed on any event of this object (like dragEnter) and if any of them returns a non-null and non-undefined value actual event handlers are not called and that value is returned. These callbacks receive the same arguments as the target event plus that event’s name in front. See callAllOfObject() for more details.
dragEnter jsfunction (eventObject). Occurs when a user drags something across this zone element (Firefox) or across the entire browser window (Chrome or if opt.fullDocDragDetect is set).
dragLeave jsfunction (eventObject). Occurs when user drags the object away from the zone element (Firefox) or outside of the window (Chrome or if opt.fullDocDragDetect is set).
dragOver jsfunction (eventObject). Occurs periodically after dragEnter while user is still dragging an object inside the drop zone. If not using DropHandle be aware that Chrome requires a listener attached to ondragover or it will discard the drop operation. DropHandle takes care of this for you.
dragEnd jsfunction (eventObject). Not really useful or working but they’re still listened to in case you need to hook them.
dragExit jsfunction (eventObject). Not really useful or working but they’re still listened to in case you need to hook them.
upload jsfunction (eventObject). Occurs when a file has been dropped on the zone element or when a file was selected in/dropped onto fallback xml<form> to trigger xml<iframe> upload. The former occurs in Firefox and Chrome-based browsers that support drag & drop natively. The latter occurs in Opera and others that only work with regular form file uploads.
uploadElsewhere jsfunction (DropHandle). Occurs when another DropHandle object on the page initiates upload event. Can be used to reset some visual state of all drop zones but the one that’s actually got the file landed.
inputSetup jsfunction ({ file: DOM_Input, form: DOM_Form }, oldFileInput). Occurs after xml<input type="file"> used to accept file drops was created or found (see the description of the input option). Here it’s used to assign it some HTML classes. You can do similar setup. Is also fired after recreating file input on upload if opt.recreateInput is set — in this case is passed old xml<input type="file"> (that was cloned).
iframeSetup jsfunction (DOM_Iframe). Occurs when a fallback xml<iframe> element was created. Can be used for setup actions similar to inputSetup.
iframeDone jsfunction (response). Occurs when a file was successfully uploaded to the server, i.e. when the form was submitted and the server has returned the output that calls fd-callback function to indicate successful (or unsuccessful) upload to the client page. See the iframe option and included upload.php for samples and explanations.

Methods

Below is a brief description of all methods available on a DropHandle instance. Find examples and up-to-date information in the extensively commented source code.

Function signatures with zero or one arguments are omitted for brevity.

abortIFrame
Can be used to abort xml<iframe> upload. Isn’t guaranteed to work since it’s unreliable and highly browser-dependent (especially IE) but at least it might work. Does nothing if this DropHandle doesn’t use xml<iframe> upload (see the input option).
sendViaIFrame
jsfunction (url). Sends the data via xml<iframe> as a fallback for proper File API AJAX upload. If url is omitted iframe.url option is used. See its description for more info. Does nothing if this DropHandle doesn’t use xml<iframe> upload (see the input option). FileDrop class calls this automatically if an upload was triggered by an unsupported browser (neither Firefox nor Chrome-based). Unlike File API events that let you decide what to do with the file — read, upload or descrad it — xml<iframe> upload is an imitation that simply submits the form as long as xml<input type="file"> was changed according to onchange event. There’s no way to make sure it was populated or retrieve any info about the file — this can only be done by the server which may return something useful in response. For this reason DropHandle automatically facilitates the upload and offers only one iframeDone event when all went fine. Returns true if upload was sent (but no guarantees about its success, use iframeDone event for this purpose).
resetForm
Clears value of the file input so that the same file (with the same

local path) can be uploaded again without reloading the page.

multiple
jsfunction (enable). Toggles selection of multiple files in the browser’s open file dialog that appears when you click on xml<input type="file">. Does nothing if this DropHandle doesn’t use xml<iframe> upload (see the input option). If an argument is given it’s used to set the new state. If no arguments are passed then current state is read. When doing initial setup on object construction you can pass js{multiple: true} as an option instead of calling this method right after.
event
jsfunction (events, funcs). Function to manipulate events that correspond to DropHandle’s events (not DOM node events). Without parameters returns copy of js{event: [func, func, ...], ...} event map — all handlers attached to this zone. When given a single non-array parameter returns array of handlers of that particular event. When givne a single array parameter acts similarly to parameterless form — returns event map of those particular events. When givne one object parameter — an event map — all its handlers are added (values can be either functions or arrays, namespaces are not supported by this call form). When given two parameters and the second is null removes all handlers of event(s) listen in the first parameter (array or string). When given two parameters and the second is either a function or array adds listeners to listed event(s). Since two parameter-long calls return this you can easily chain multiple calls to the object methods like in jQuery. For more usage info, namespaces and lots of examples see the comment before this method in the source code.
preview
jsfunction (events, funcs). A simplified companion of event() that adds listeners not after existing but in front of them. Useful for intercepting and overriding calls of certain events. Supports namespaces. Has several call forms which are identical to event(): one parameter — object (event map), two parameters — array/array, array/func, string/array, string/func. Any other parameter combination will result in exception.

Some low-level internal methods:

hookPrepares target DOM element for drag & drop and xml<iframe> uploads by adding more child nodes and listening to appropriate events. Usually you don’t need to call this function since it’s automatically called for the zone element (given to the constructor).
hookDragOnAttaches listeners for drag events — when an object is moved in or out the scope of the zone element (or document for Chrome). This provides common layer for various browser-specific ways to utilize drag* events. Once a suitable event occurs DropHandle’s own event callbacks are invoked.
hookDropOnAttaches listeners to drop events. Just like hookDragOn provides common browser-independent ground by normalizing occurred events and calling DropHandle’s own event handlers.
prepareInputFinds or creates xml<input type="file"> used to facilitate non-drag & drop uploads for browsers othat than Firefox and Chrome-based. Returns that input’s DOM element and its parent xml<form>(h) or, if none, throws an exception since there’s no meaning in having xml<input type="file"> and no xml<form> as both are only reuqired for fallback <iframe> upload. This result is assigned to input option.
findInputRecursiveSearches for xml<input type="file"> containing HTML class opt.inputClass among the children of parent. Is used to autodetect pre-created input of a drop zone. parent must be a DOM element. Returns DOM element or null.
createInputAtCreates elements necessary for xml<iframe> upload to work — the input, form and iframe itself. A random unique ID is generated and assigned to the iframe, plus new form’s target attribute. Once xml<input type="file"> gets clicked (and file chosen in the appeared dialog) or once it gets a file dropped onto (supported by some browsers) its onchange event occurs which we’re intercepting in hookDropOn(). With that we trigger xml<form> submission which sends data to our hidden xml<iframe>. Just like old times. Returns the DOM element of (new) xml<input type="file">.

FileDrop class

Based on DropHandle to abstract from browser-specific drag & drop and fallback xml<iframe> upload quirks, this class adds actual upload functionality. It listens for drop events and xml<iframe> submission triggering dedicated events with normalized parameters. Underlying DropHandle class can be accessed via this.handle property. It shares options and events with FileDrop object so changing one affects another.

DropHandle properties and methods are available on this object as well.

This object is defined in window.fd and aliased as window.FileDrop.

Constructor:

jsnew FileDrop(zone, opt);
// Example:
new FileDrop(document.body, {zoneClass: 'with-filedrop'});

Parameters are identical to those of DropHandle.

Options

See also those inherited from DropHandle.

dragOverClassHTML class name for the zone DOM node that is set when an object is being dragged over that zone (Firefox) or over entire document (Chrome-powered browsers). It’s removed once the object was dragged away or drag & drop was cancelled.
iframe.forceIf set FileDrop will always upload files by using fallback xml<iframe> method. This only makes sense in debugging and for some browsers (Opera before migrating to Chrome engine).

Properties

See also those inherited from DropHandle.

handleUnderlying DropHandle instance providing browser-independent handlers for drag & drop and xml<iframe> upload facility.

Events

See also those inherited from DropHandle.

send jsfunction (fd.FileList). Occurs when a file is ready to be sent via drag & drop. Doesn’t occur for xml<iframe> uploads since the only thing you can do about them is submit the file to the server (no file info is available). If for some reason you still need to know when a file was *potentially* placed into xml<input type="file"> for such fallback uploads listen or preview the upload event (inherited from DropHandle).
fileSetup jsfunction (fd.File). Occurs when a new File object was created. You can use this to attach your own events if you don’t want to do this on every send occurrence.

Methods

Find examples and up-to-date information in the extensively commented source code.

See also those inherited from DropHandle.

eventFiles jsfunction (e, orFalse). Retrieves File objects from an on-drop event. Returns a FileList array-like object (not W3C FileList). If orFalse is unset always returns a FileList even if event e was invalid, otherwise returns false in such occurrences instead of empty FileList.

FileList class

It’s sort of W3C class (that has no special methods defined in the spec) with a bunch of File-oriented methods that this object is meant to contain. It’s an array-like object with length, splice() and other methods.

Constructor:

jsnew fd.FileList(event);

event is native event object given by the browser in reply to onchange or ondrop events.

Properties

dropEffectIf set can be copy, move or other action. Doesn’t reliably work cross-browser and cross-platform. See this MDN page for more info and also DropHandle’s dropEffect option.
lengthNumber of File items in this object, just like an array.

Methods

Below is a brief description of all methods available on a FileList instance. Find examples and up-to-date information in the extensively commented source code.

Function signatures with zero or one arguments are omitted for brevity.

pushAdds new File object to this list.
popRemoves last File object from this list and returns it. Returns null if this list is empty.
firstReturns first File object or undefined.
lastReturns last File object or undefined.
removeRemoves File item with given index, if exists (like an array). Returns and changes self.
clearRemoves all items from this list. Returns and changes self.
reverseReverts the order of File items in this list. Returns and changes self.
concatCreates copy of this list and adds items from FileList or array to the end of the returned copy.
sort jsfunction (func, cx). Sorts this list by calling comparator func in context cx (or this FileList if omitted). func = jsfunction (File a, File b, aIndex, bIndex) — if returns < 0 second file (b) must go before first (a). Very similar to Array.sort().
sortBy jsfunction (func, cx). Sorts this list by calling func on each File alone and using that value (e.g. hash) to compare items between themselves. Like Underscore’s sortBy().
find jsfunction (func, cx). Calls func in context cx for every File in the list and if it returns a non-null value returns the File object on which func was invoked. If this list is empty or if func didn’t return anything for any file returns undfined.
each jsfunction (func, cx). The same as find() but ignores returned value of the callback invoking it for every File in the list.
invoke jsfunction (method, arg_1). Calls method on every contained object with given arguments. Returns self.
abortAborts all uploads of files contained in this list. Does nothing if upload isn’t active. Doesn’t abort xml<iframe> uploads — for this call abortIFrame() on the corresponding DropHandle object.
findCompare jsfunction (func, cx). Runs through over all items in this list calling func in context cx (or this) and storing returned values. Returns File object for which func generated the largest value (or first such File for multiple same values). Returns undefined if this list is empty.
filter jsfunction (func, cx). Returns new list that only contains items for which func called in context cx (or this) has returned a truthy value.
largestReturns File with biggest size or undefined for empty list.
smallestReturns File with smallest size or undefined for empty list.
oldestReturns File that was changed the longest time before or undefined for empty list.
newestReturns File that was most recently changed or undefined for empty list.
ofTypeReturns new list of all files which MIME type matches. MIME shouldn’t contain RegExp symbols except for /. To match MIME group like image/* don’t include trailing /* — just image.
imagesReturns new list with File items with image/* MIME type.
namedIf name is string returns File with name exactly matching that string. If name is RegExp returns new list containing File items which name match given RegExp.
spliceIs included for compatibility with Array duck typing and may even work but isn’t recommended to use.

File class

It’s passed on FileDrop send event as members of fd.FileList and provides cross-browser access to file information and ability to upload it to the server. Wraps around native browser’s File object.

Constructor:

jsnew fd.File(file);

file is native browser File object according to W3C specification that can be retrieved from the on-drop event object. Can be accessed via this.nativeFile property.

Properties

nativeFileNative browser File object that was initially given to the constructor. Is null for directory entries if on lists produced by listEntries.
nativeEntryIn Chrome 21+ will be set to native Entry (FileEntry, DirectoryEntry, etc.) instance. See the W3C spec.
nameLocal file name like myfile.txt, possibly relative (webkitdirectory).
sizeLocal file size (bytes).
typeLocal file MIME type like text/plain.
modDateLast modification of the local time. Standard Date object. Is set to now() if this info isn’t provided by the browser.
xhrXMLHttpRequest object that was used to upload the file to the server. Only filled after sendTo() was called. Use this.abort() to stop the upload.

Options

Values here specify default values for sendTo() options — like HTTP method used to submit the data. They can be overriden by passing an object to sendTo() — e.g. jssendTo('upload.php', {method: 'PUT'}).

extraHeadersIf enabled this object will add several X-... headers to provide information about the original file to the server (e.g. name and size).
xRequestedWithThe value of X-Requested-With header sent with XMLHttpRequest used to upload the dropped file(s). If false then this header is not set (but you can use xhrSetup/xhrSend events to set it). If true — it’s set to one of FileDrop-XHR-.... A string sets it to that string — e.g.XMLHttpRequest’ would simulate regular $.ajax() request.
methodHTTP method used to submit the upload data. Useful for contacting WebDAV services which might accept PUT or DELETE. Given to XMLHttpRequest.open() in sendTo().

Events

For the explanation of event handling see Samples, demo page and source code comments.

anyObject-wise event preview handlers. See DropHandle’s any description.
xhrSetup jsfunction (XMLHttpRequest, opt). Occurs after a XMLHttpRequest object was prepared to submit the file to the server. All FileDrop-specific headers and other customization (Content-Type, etc.) was already done. You can set extra headers or add event listeners here before it’s dispatched to the server.
xhrSend jsfunction (XMLHttpRequest, data, opt). Occurs when a file and XMLHttpRequest were prepared for upload and need to be sent. It’s handled by fd.File.xhrSend() but you might want to add your logic here. Is passed the request object, options and raw file data that is browser-specific (it might not be raw binary string in some older browsers as it is in Firefox and Chrome-based). opt is the object passed to sendTo() with missing fields populated as this.opt.
progress jsfunction (sentBytes, totalBytes, XMLHttpRequest, eventObject). Occurs during file upload with information on current upload progress. This happens on browser-sepcific intervals and usually on somewhat large files only. Is passed two integers (already uploaded bytes and total amount of data — local file size, of which first or both might be unset if browser can’t provide this info), the request object that is uploading this file and native browser event object that was given to the XMLHttpRequest’s event handler of File.
done jsfunction (XMLHttpRequest, eventObject). Occurs when a file has successfully finished uploading. Is passed the request object that was used to upload the file and native browser event object that was given to the XMLHttpRequest’s event handler of File.
error jsfunction (eventObject, [XMLHttpRequest]). Occurs when a file has failed during upload much like regular XMLHttpRequest error. Note that «failing» means all response code except for 200 — even 2xx like 202 Accepted (WebDAV and such) or 3xx (redirects). This isn’t called when upload was aborted — if you specifically need to track this call jsfd.addEvent(fileObject, 'abort', function ...) (see global functions).

Methods

Below is a brief description of all methods available on a File instance. Find examples and up-to-date information in the extensively commented source code.

Function signatures with zero or one arguments are omitted for brevity.

abortAborts current upload, if any.
sendTo jsfunction (url, opt). Submits the dropped file to the server script at given URL and with optional options opt (fields default to this fd.File.opt). Incapsulates browser-specific logic behind reading a local file. If an upload request has been already made on this File instance will abort it (unless it’s finished) and start anew.
readData jsfunction (onDone, onError, func). Browser-independent way of reading binary data. Doesn’t work on all browsers. Asynchronous. If onError is omitted then onDone is called with the usual arguments (errorObject). If onError is false errors are not reported (onDone not called). Third parameter specifies the way to read the file and if omitted or bin reads binary data, if url, uri or src reads Data URI (very nice for generating thumbnails), if array reads it as ArrayBuffer, if text reads data as UTF-8 string, if starts with read is assumed to be a method name on native File object which will be called. Any other string value is treated as character encoding (e.g. cp1251) and data is read as text in that encoding. If 3rd parameter is an array its first element is treated as File’s method name and all other parameters are parameters for that method. For more usage info, namespaces and lots of examples see the comment before this method in the source code. See also Samples above and the demo page with code snippets.
readDataURL jsfunction (onDone, onError). Alias to readData() that reads Data URI suitable for xml<img src> attribute. Unlike readData() if onError isn’t passed explicitly it’s set to false (errors suppressed, onDone not called).
readDataURIAlias to readDataURL().
read jsfunction (opt). Advanced reading function that can be used to read Blobs and make slices of this file rather than load the entire data into memory. Accepts various options, see the code for information and comments for examples.
listEntries jsfunction (onDone, onError). Uses W3C draft File System API to traverse this DirectoryEntry. Currently supported in Chrome 21+. Spec. This function is not recursive. onDone is a function callback that receives FileDrop.FileList object. Each entry there can be either a file or a directory. Files have nativeFile set (but not in case of error — if so use nativeEntry’s isDirectory and isFile props to determine which one is which). On these, correct files you can use any of FileDrop methods — sendTo(), readFile(), etc. On directories (but not failed files) you can use listEntries() to traverse them further. onError is an optional function called by the browser when it runs into errors. It gets passed error object. Note that it might be called multiple times and that onDone can be still called (this might happen if FileEntry can’t read particular File object when using file()).
event jsfunction (events, funcs). Adds event listeners to this object. See DropHandle’s event() code for extended comment and examples.
preview jsfunction (events, funcs). Adds event listeners to this object in front of existing handlers. Can be used to intercept/override certain events. See DropHandle’s event() code for extended comment and examples.

Some low-level internal methods:

sendDataReadyTo jsfunction (url, e). Internal method that’s called when file data was read and is ready for upload. For FileAPI (Firefox) gets called on readAsArrayBuffer() onload event; for Safari/early Chrome it’s called immediately and gets passed the native file object itself.
hookXHR jsfunction (xhr). Attaches internal event listeners to the XMLHttpRequest object that is used to upload the dropped file.

jQuery interface

After both FileDrop and jQuery (v1 or v2) scripts have loaded call fd.jQuery(). Don’t forget to include/write your FileDrop’s CSS as well if you’re using xml<iframe>.

Once done it becomes possible to access FileDrop as js$('#zone').filedrop() and avoid accessing its methods and bind event altogether. FileDrop will trigger events as if they originated from the zone’s DOM node itself and prefix each event with either fd (DropHandle/FileDrop classes) or file (File class). For example, dragEnter becomes fd.dragenter. Arguments remain the same except that:

Note that this points to jQuery collection and no more to the FileDrop or File instance that has initiated the event.

js$('<div><p>Drop something here...</p></div>')
  .appendTo(document.body)
  .filedrop()
  .on('fdsend', function (e, files) {
    // Occurs when FileDrop's 'send' event is initiated.
    $.each(files, function (i, file) {
      file.sendTo('upload.php')
    })
  })
  .on('filedone', function (e, file) {
    // Occurs when a File object has done uploading.
    alert('Done uploading ' + file.name + ' on ' + this.tagName)
  })

When constructing FileDrop instance by jQuery in addition to regular el property $el is set to point to $(el) — zone node wrapped as jQuery collection.

Also, it’s still possible to attach listeners to FileDrop object with jsfd.event('event', func) but these events are called after corresponding DOM events (added with jQuery). If a DOM event handler returns a non-null and non-undefined value then FileDrop’s handlers won’t be called.

Event preview handlers (any event) can only be attached directly to FileDrop:

js$('#zone')
  .fildrop()
  .filedrop().event('any', function () { ... })

You can access underlying FileDrop object by calling filedrop() without parameters (first such call creates FileDrop, later calls return the instance on the first element in the collection):

js$('#zone')            // select <p id="zone">
  .filedrop()         // turn it into a FileDrop zone
  .css({color: red})  // any normal jQuery code
  .filedrop()         // retrieve FileDrop object
  .multiple(true)     // call its method

Alternatively you can pass a string to filedrop() to select a property or call a method — in this case their value/result is returned:

js$('#zone')
  .filedrop()
  .filedrop('multiple', true)
    // returns the new state of 'multiple' option, not jQuery object.

It’s also possible to pass custom options to FileDrop constructor:

js$('#zone')
  .filedrop({
    multiple: true,
    iframe: {url: '/upload.php'}
  })

Legacy Docs (v1)

An entire FileDrop facility is contained in window.fd. In itself, FileDrop in itself is split into 2 classes: DropHandle and FileDrop, plus one File class. Apart from these there are global options and functions (belonging to window.fd instead of a particular FileDrop class).

FileDrop uses event-driven approach for better flexibility. See also CallOf() and CallAll() functions that call event chains (sets of callbacks).

Documentation in this section describes previous FileDrop version. General code structure has been precerved with the new edition but this section may refer to events and functions that have been changed or removed. See Changelog for more details or the latest docs section.

Last v1 release of FileDrop is available at the separate branch named v1.

Global options

Global options are set in window.fd:

loggingBoolean value toggling logging of debug messages to window.console. Logging is always disabled if there’s no console support.
onObjCall jsfunction (event, args), gets called before calling a chain of FileDrop events. this is set to the calling object.
  • This method is used on the demo page to log events called by FileDrop.
allArray of all DropHandle/FileDrop objects that were instantinated.

Global functions

RandomIDReturns a random node ID of form fd_ + random number between 1 and 9999. Doesn’t check its uniqueness.
ByIDReturns an element given its ID or, if passed argument is already a DOM element node (see IsTag) — that node itself.
IsTagReturns true if passed argument is a proper DOM element node (note: not text node or other type), false otherwise.
NewXHRConstructs a XMLHttpRequest object; supports IE 6 ActiveX.
InstanceOfReturns name of instance function used to construct given object.
IsArrayReturns true if given object is a real Array.
AddEventCross-browser event attachment.
StopEventStops propagation of the given event object.
SetClassAdds or removes class name of the given DOM node.
HasClassReturns true if given DOM element has given class name.
ClassRegExpReturns a RegExp object with pattern for detecting passed class name (for a DOM element).
ExtendCopies properties from one object to another; can optionally copy only undefined properties.
CallAllCalls handlers from given event chain event-driven system); if a handler returns non-null value all remaining handlers are skipped. Returns result value of the last invoked handler.
CallOfA shortcut for calling event chain located in obj.on[event] object property; see it usages in FileDrop code to get the main idea.
jQueryIntegrates FileDrop into jQuery — can be passed an object, by default $ is used.

DropHandle class

This is an abstraction layer that provides FileDrop class with normalized events occurring on file Drag & Drop and Browse. It creates xml<input type="file"> and xml<iframe> elements and handlers their activity.

DropHandle doesn’t do anything except handling node events — it doesn’t change the appearence of zone or respond to Browse or Drag & Drop, it only invokes corresponding event handlers.

Constructor:

js// zone - a DOM element or ID to hook file upload events for.
// opt - optional options, see below.
new fd.DropHandle(zone, opt);

Options:

zoneClassClass name to add to passed zone.
inputClassClass name to set to the constructed xml<input type="file"> element.
iframeAn object with xml<iframe> fallback settings. Currently has only one field (but FileDrop has more):
url
URL to point constructed xml<iframe> element to. Must be a server-side script that handles iframe upload.
fullDocDragDetectA compatibility option that if set will cause Drag & Drop events to be detected document-wise rather than on given zone (currently only supported by Firefox). If unset this is autodected. Is always true for Google Chrome.

Note: you can access passed zone element using zone property of the DropHandle class.

Events

Events are stored in on property, e.g. jsaDropHandle.on[dragEnter]. Each on member is an array of callbacks.

event jsfunction (event, args). Gets called before all events fired by this object; see onObjCall global option for details.
upload jsfunction (e). Occurs when a file is dropped to zone. It happens in Firefox and Google Chrome because they support dropping files on xml<input type="file">.
uploadElsewhere jsfunction (zone). Occurs when an upload is triggered on another FileDrop (DropHandle object). By default is used to reset drag-over styles on all zones that haven’t received an object (mostly useful in Chrome which provides document-wise rather than element-wise drag-over detection).
inputSetup jsfunction (input). Occurs when a xml<input type="file"> element was created and needs to be set up. Default handler adds opt.inputClass to it and sets its parent xml<form>’s style.position to relative to avoid overflow problem in Firefox 10 (it would still show the presumably hidden part of the input even outside the container bounds).
iframeSetup jsfunction (iframe). Occurs when an xml<iframe> element was constructed and can be set up. Currently there’s no default handler.
iframeDone jsfunction (response). Occurs when an xml<iframe> upload has finished. response is the object returned by the server script plus several XMLHttpRequiest-like response properties making it suitable to use one callback function both for this and File’s done event.
Drag & Drop

All handlers are of form jsfunction (e) where e is the native browser event object. Most useful events are dragEnter and dragLeave because others either don’t work, are unstable or unclear.

For a detailed description of HTML 5 Drag & Drop events see this MozDev page.

dragEnterOccurs in supported browsers when a Drag & Drop event is received by zone (Firefox) or entire document (Chrome).
dragLeaveOccurs when Drag & Drop ends — e.g. the mouse pointer leaves zone or browser window.
dragOverAnother drag & drop event that doesn’t appear to be useful; see this page for description.
dragEndAnother drag & drop event that doesn’t appear to be useful; see this page for description.
dragExitAnother drag & drop event that doesn’t appear to be useful; see this page for description.

Methods

Only methods of interest are listed here, others are easy to determine from the code.

Hook (node)Initializes and attaches events to given node. Is called when constructing DropHandle.
PrepareInput (node)Constructs required DOM elements (form, file input, iframe and others).
AbortIFrame ()Aborts file upload happening using xml<iframe>, if there was any happening.
SendViaIFrame (url)This method can be called to send a file using fallback xml<iframe> and xml<form> elements. It will prepare the form and set up the response handler that will call iframeDone event.
Multiple ()Returns true if the xml<input type="file"> element is configured for multiple file selection.
Multiple (Toggles)Toggles multiple file selection of the xml<input type="file">. This affects «Browse» dialog popping up when user clicks on the drop zone (zone node DropHandle was constructed for).

FileDrop class

This class provides the actual FileDrop features. It’s based on DropHandle that gives a good degree of cross-browser abstraction. FileDrop uses DropHandle’s events to respond to user actions and as such provides the same callbacks as that class.

Also, all DropHandle options, methods and other fields exist in FileDrop as well.

Constructor:

js// zone - a DOM element or ID to hook file upload events for.
// opt - optional options, see below.
new fd.FileDrop(zone, opt);
// a global (window[]) alias exists - you should use it instead:
new FileDrop(zone, opt);

Options (see also DropHandle options):

dragOverClassClass name to add to passed zone when a Drag & Drop session is active and a file is being hovered over zone (Firefox) or document (Chrome).
iframeAdds one field to DropHandle’s iframe:
force
If true, xml<iframe> upload will be forced even if browser supports AJAX upload using FileAPI or Chrome/Safari File false by default.

Note: you can access DropHandle object by handle property of the FileDrop class.

Events

Events are stored in on property, e.g. jsaFileDrop.on[send]. Each on member is an array of callbacks.

send jsfunction (files). Occurs when a set of files can be safely sent — user agent supports some kind of FileAPI (of Firefox, Chrome or Safari). An xml<iframe> upload can still be done when handling this event using DropHandle SendViaIFrame(), if desired. Currently there’s no default handler.
fileSetup jsfunction (file). Occurs when a File object was constructed and can be set up. Currently there’s no default handler.

Methods

Only methods of interest are listed here, others are easy to determine from the code.

OnUpload ℮A default FileDrop handler for DropHandle’s upload event. It either fires send event or initiates xml<iframe> upload if the browser doesn’t support any FileAPI.
GetFilesFrom ℮Is used by OnUpload() to convert native file upload event object to an array of browser-neutral File classes. Returns false if there’s no FileAPI support.

File class

Browser-independent abstraction layer for dealing with File objects of supported browsers (currenly Firefox/, Chrome and Safari). Wraps around native browser File// object that it’s passed in the constructor.

It also provides a number of events wrapping around XMLHttpRequest (see SendTo() method).

Constructor:

js// file - a native File object returned by the browser from an event object.
new fd.File(file);

File class has one option:

extraHeadersIf true (by default) will send 3 extra headers along with XMLHttpRequest when sent using SendTo(). Note: if you turn this off server script will have no information regarding file name and size when uploading them using Drag & Drop (AJAX).
  1. X-File-Name — URL-encoded file name.
  2. X-File-Size — original file size.
  3. X-Requested-With — two values: FileDrop-XHR-FileAPI (for Firefox) and FileDrop-XHR-Chrome (for Google Chrome and Apple Safari).

File class has the following properties:

nativeFileNative File object passed to File’s constructor.
nameFile name.
sizeFile size.
xhrAn instance of XMLHttpRequest that was last used to send the file by SendDo() or null if there was none.

Events

Events are stored in on property, e.g. jsaFile.on[error]. Each on member is an array of callbacks.

event jsfunction (event, args). Gets called before all events fired by this object; see onObjCall global option for details.
sendXHR jsfunction (xhr, data) where data is an already read raw binary string (for Gecko and Chrome) or a native file object (for Safari). Occurs when a XMLHttpRequest object needs to be sent. Default handler (fd.File.SendXHR()) attempts to use sendAsBinary() if it’s available falling back to send() with possible sendAsBinary() imitation for Chrome.
progress jsfunction (current, total, xhr, e) where current might be null if can’t be determined; current and total are the number of bytes uploaded and total correspondingly.
done jsfunction (xhr, e). Occurs when the file has been uploaded ( jsxhr.readyState == 4 && xhr.status == 200) and server response was received. Note: DropHandle provides callback for xml<iframe> upload — see SendViaIFrame() with simulated xhr structure.
error jsfunction (e, xhr). There was an error while uploading the file or reading file binary data — in this case xhr parameter will be undefined.

Methods

Only methods of interest are listed here, others are easy to determine from the code.

SendTo (url)Performs AJAX upload: reads file data, constructs and prepares a XMLHttpRequest object and sends read data to the server. Works in Firefox (using FileAPI), Google Chrome and Apple Safari. Calls error event on error and sendXHR when the request needs to be submitted.
  • Request is sent in POST mode and with application/octet-stream MIME/Content-Type. The latter is used to avoid encoding and other transformations done by some browsers (e.g. Firefox) when uploading text files.
  • Constructed XMLHttpRequest instance is stored in File’s xhr property replacing previous if there was any.
HookXHR (xhr)Is used by SendTo() to attach event callbacks to the given XMLHttpRequest object.
Abort ()Terminates last sent XMLHttpRequest request; does nothing if there was any (see also File’s xhr property).

End of documentation. Live DemoDownloadGitHubTop