Disaster

message saying drag images into text area to upload them to imgur

This was originally going to be a post about mobile vs. web apps, but as I was putting the finishing touches on it, I dragged an image from my desktop into the post, expecting it to be uploaded to imgur and replaced with a link to the image. This used to work (and has since been fixed), but we forgot to re-enable it after we did a recent redesign of the site. So instead of some nice behavior to make the post better, I instead got chrome’s default behavior when dragging an image into the browser: the page was replaced by the image. You can imagine what expletives were running through my head when I realized that all the work I had put into the post was lost.

Recovery (at least for next time)

Now, to prevent losing forms in the future, I’ve installed the excellent Lazarus: Form Recovery chrome extension, but I still don’t like chrome’s default behavior where dragging an image replaces the entire page in the active tab.

Prevention

In order to override chrome’s default drag and drop behavior, I wrote a user script that will remind me that I might be doing something I’m not intending to when I’m dragging a file into the browser. Now there are several cases where I do actually want to drop a file into a page (automatically detecting these cases would make the script more powerful), so I decided to have the browser pop up a confirmation dialog, where I can select that I do really want the default behavior. If I click cancel, instead of ignoring the drag, the brower will open up the file in a new tab.

// ==UserScript==
// @match http://*/*
// @match https://*/*
// ==/UserScript==

function preventDrag(e) {
  e.stopPropagation();
  e.preventDefault();
}

function handleDrop(e) {
  if (e.dataTransfer.files.length > 0) {
    if (!confirm("Are you sure you want to drop this file here? "
                +"(Cancel opens it in a new tab)")) {
      e.stopPropagation();
      e.preventDefault();

      var file = e.dataTransfer.files[0];
      var reader = new FileReader();

      reader.onload = function(event) {
        window.open(reader.result);
      }
      reader.readAsDataURL(file);
    }
  }
}

document.addEventListener('drop', handleDrop, false);
document.addEventListener('dragenter', preventDrag, false);
document.addEventListener('dragover', preventDrag, false);

In order to open the file in a new tab, I read it in as a base64-encoded data URI with a FileReader, and then open a new window with that data. I was hoping the userscript would have enough security privileges to get a file:// path for the file, but this doesn’t appear to be possible: StackOverflow: How do I get the URL for a dropped image using a chrome userscript?

Installing

  1. general rule: Read through a UserScript before installing it, to make sure that you know what it’s doing and trust it.
  2. Save the script to a file with a .user.js suffix
  3. browse to chrome://extensions
  4. Drag the script into the chrome extensions tab

Thanks