Need help with drag-drop?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

feross
457 Stars 70 Forks MIT License 241 Commits 2 Opened issues

Description

HTML5 drag & drop for humans

Services available

!
?

Need anything else?

Contributors list

drag-drop ci npm downloads javascript style guide

HTML5 drag & drop for humans

In case you didn't know, the HTML5 drag and drop API is a total disaster! This is an attempt to make the API usable by mere mortals.

live demo

See https://instant.io.

features

  • simple API
  • supports files and directories
  • excellent browser support (Chrome, Firefox, Safari, Edge)
  • adds a
    drag
    class to the drop target on hover, for easy styling!
  • optionally, get the file(s) as a Buffer (see buffer)

install

npm install drag-drop

This package works in the browser with browserify. If you do not use a bundler, you can use the standalone script directly in a

 tag.

usage

const dragDrop = require('drag-drop')

dragDrop('#dropTarget', (files, pos, fileList, directories) => { console.log('Here are the dropped files', files) // Array of File objects console.log('Dropped at coordinates', pos.x, pos.y) console.log('Here is the raw FileList object if you need it:', fileList) console.log('Here is the list of directories:', directories) })

Another handy thing this does is add a

drag
class to the drop target when the user is dragging a file over the drop target. Useful for styling the drop target to make it obvious that this is a drop target!

complete example

const dragDrop = require('drag-drop')

// You can pass in a DOM node or a selector string! dragDrop('#dropTarget', (files, pos, fileList, directories) => { console.log('Here are the dropped files', files) console.log('Dropped at coordinates', pos.x, pos.y) console.log('Here is the raw FileList object if you need it:', fileList) console.log('Here is the list of directories:', directories)

// files is an Array! files.forEach(file => { console.log(file.name) console.log(file.size) console.log(file.type) console.log(file.lastModifiedDate) console.log(file.fullPath) // not real full path due to browser security restrictions console.log(file.path) // in Electron, this contains the actual full path

// convert the file to a Buffer that we can use!
const reader = new FileReader()
reader.addEventListener('load', e => {
  // e.target.result is an ArrayBuffer
  const arr = new Uint8Array(e.target.result)
  const buffer = new Buffer(arr)

  // do something with the buffer!
})
reader.addEventListener('error', err => {
  console.error('FileReader error' + err)
})
reader.readAsArrayBuffer(file)

}) })

get files as buffers

If you prefer to access file data as Buffers, then just require drag-drop like this:

const dragDrop = require('drag-drop/buffer')

dragDrop('#dropTarget', files => { files.forEach(file => { // file is actually a buffer! console.log(file.readUInt32LE(0)) console.log(file.toJSON()) console.log(file.toString('hex')) // etc...

// but it still has all the normal file properties!
console.log(file.name)
console.log(file.size)
console.log(file.type)
console.log(file.lastModifiedDate)

}) })

detect drag-and-dropped text

If the user highlights text and drags it, we capture that as a separate event. Listen for it like this:

const dragDrop = require('drag-drop')

dragDrop('#dropTarget', { onDropText: (text, pos) => { console.log('Here is the dropped text:', text) console.log('Dropped at coordinates', pos.x, pos.y) } })

detect
dragenter
,
dragover
and
dragleave
events

Instead of passing just an

ondrop
function as the second argument, instead pass an object with all the events you want to listen for:
const dragDrop = require('drag-drop')

dragDrop('#dropTarget', { onDrop: (files, pos, fileList, directories) => { console.log('Here are the dropped files', files) console.log('Dropped at coordinates', pos.x, pos.y) console.log('Here is the raw FileList object if you need it:', fileList) console.log('Here is the list of directories:', directories) }, onDropText: (text, pos) => { console.log('Here is the dropped text:', text) console.log('Dropped at coordinates', pos.x, pos.y) }, onDragEnter: (event) => {}, onDragOver: (event) => {}, onDragLeave: (event) => {} })

You can rely on the

onDragEnter
and
onDragLeave
events to fire only for the drop target you specified. Events which bubble up from child nodes are ignored so that you can expect a single
onDragEnter
and then a single
onDragLeave
event to fire.

Furthermore, neither

onDragEnter
,
onDragLeave
, nor
onDragOver
will fire for drags which cannot be handled by the registered drop listeners. For example, if you only listen for
onDrop
(files) but not
onDropText
(text) and the user is dragging text over the drop target, then none of the listed events will fire.

remove listeners

To stop listening for drag & drop events and remove the event listeners, just use the

cleanup
function returned by the
dragDrop
function.
const dragDrop = require('drag-drop')

const cleanup = dragDrop('#dropTarget', files => { // ... })

// ... at some point in the future, stop listening for drag & drop events cleanup()

support pasting files from the clipboard

To support users pasting files from their clipboard, use the provided

processItems()
function to process the
DataTransferItemList
from the browser's native
'paste'
event.
document.addEventListener('paste', event => {
  dragDrop.processItems(event.clipboardData.items, (err, files) => {
    // ...
  })
})

a note about
file://
urls

Don't run your app from

file://
. For security reasons, browsers do not allow you to run your app from
file://
. In fact, many of the powerful storage APIs throw errors if you run the app locally from
file://
.

Instead, start a local server and visit your site at

http://localhost:port
.

license

MIT. Copyright (c) Feross Aboukhadijeh.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.