HTML/Javascript: Drag and drop images and files

HTML5 has a drag and drop implementation. It's used to drag images from other websites and to drag images from our filesystem.

<div id="drop" 
   style="height: 200px; width: 200px; background: blue;" 
   ondragenter="ondragenter" 
   ondragleave="ondragleave">
</div>

We specify two event handlers, ondragenter and ondragleave. These will highlight our div when the user drags an image over it.

These are global handlers for blog-post convenience. I've placed them on our div and made them global functions.

<script>
  var drop = document.querySelector("#drop")
  ondragenter = ev => {
    if (ev.target.id == "drop") 
      ev.target.style.backgroundColor = "red"
  }
  ondragleave = ev => {
    if (ev.target.id == "drop") 
      ev.target.style.backgroundColor = "blue"
  }
</script>

We need to make our div to accept images and files. It needs ondrop and ondropover. ondropover needs to return false or call event.preventDefault() to make the div a drop target. ondrop also needs to call event.preventDefault() and in that function all the magic happens.

<div id="drop" 
   style="height: 200px; width: 200px; background: blue;" 
   ondragenter="ondragenter" 
   ondragleave="ondragleave"
   ondrop="ondrop"
   ondragover="return false">
</div>
<script>
  var drop = document.querySelector("#drop")
  ondrop = ev => {
    ev.preventDefault()
    alert("You dragged something")
  }
  ondragenter = ev => {
    if (ev.target.id == "drop") 
      ev.target.style.backgroundColor = "red"
  }
  ondragleave = ev => {
    if (ev.target.id == "drop") 
      ev.target.style.backgroundColor = "blue"
  }
</script>

You can test it by trying to drag an image below.


In ondrop, we have an event that has a dataTransfer object. This has a files object that is full if the user dragged a file from their filesystem. You can upload this and each file object has a name property.

If it wasn't a file, we can call getData("text/html") on dataTransfer to get the html of what was dragged, make that into an element and run querySelector to get the img's src property, which could either be a file or a base64 encoded file.

Below is an expanded ondrop.

ondrop = ev => {
  ev.preventDefault()
  var html;
  if(ev.dataTransfer.files.length > 0) {
    var file = ev.dataTransfer.files[0]
    var form_data = new FormData()
    form_data.append("files[]", file)
    alert("Ready to upload some form data", file.name)
  } else if(html = ev.dataTransfer.getData("text/html")) {
    var img_ob = image_src_from_html(html)
    console.log(img_ob)
  } else {
    console.log("there wasn't any html or a filelist")
  }
}
function image_src_from_html(html) {
  var ret = {}
  var el = document.createElement("div")
  el.innerHTML = html
  var img = el.querySelector("img")
  if(!img) return ret
  var src = img.getAttribute("src")
  if(src.startsWith("data:image")) ret.urlencoded = src
  else ret.src = src
  return ret
}  
javascript html

Edit on github
comments powered by Disqus
Click me