7

It would be very convenient if one was able to paste images here, on Stack Exchange instead of meddling with a file dialog. Similar feature was (is?) implemented here, but only for Webkit browsers.

I was developing userscript that does that. Funny thing is that I never accomplished to get the file (which is different from raw image data) from clipboard in Webkit browsers, while in Firefox it works.

Firefox solution:

  div.addEventListener('paste', function(event){
    //I'm actually not sure what should event.originalEvent be. I copypasted this
    var items = (event.clipboardData || event.originalEvent.clipboardData);
    console.log("paste", items);
    //Try to get a file and handle it as Blob/File
    var files = items.items || items.files;
    if(files.length>0) {  
      //Being lazy I just pick first file
      var file = files[0];
      //handle the File object
      _this.processFile(file);

      event.preventDefault();
      event.cancelBubble = true;
      return false;
    }
  });

Before Chrome doesn't have as nice documentation as Firefox has (I mean MDN), I tried to inspect what's going on. I copied a file and I pasted it in Google chrome (v39). This is what I get in the DataTransfer object in the console:

paste event Google chrome

For refference, here's the same event in Firefox:

paste event files firefox

The other two arrays, items and types are not present in Firefox implementation. When I copy text or raw image data Chrome represents it as DataTransferItem. I figured out that it's best to ignore those:

  //Being lazy I just pick first file
  var file = files[0];
  //GOOGLE CHROME
  if(file.getAsFile) {
    console.log("DataTransferItem:", file);
    //HTML or text will be handled by contenteditable div
    if(file.type!="text/plain" && file.type!="text/html") {
      //handle the File object
      _this.processFile(file.getAsFile());
    }
  }
  else 
    ...

So far, I never occurred to get anything else than text/plain or text/html. For these, .getAsFile returns null.

I find the google chrome model a little confusing. It gives you more info about raw data (text/raw image), which can only be accessed using content editable div, but isn't very clear to me.

Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • Follow this bug for the Chrome issue: http://crbug.com/316472 . And you might also be interested in this one for the related Firefox issue: http://bugzil.la/891247 . Both teams seem to be trying to get their implementations to align more closely with the spec/each other. – Noyo Dec 03 '14 at 09:30

1 Answers1

1

Our magic sauce is just:

$('body').bind('paste', handlepaste);

Where handlepaste is very similar to yours, so should work for you just fine for Chrome.

Unfortunately the above completely fails for FF, and we are loath to add a contenteditable anywhere (in particular given that it has to be in focus for this to work and we don't want to steal the focus).

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • 1
    I thought `.bind` is equal to `.addEventListener`. If not, what's the difference? I don't want to include jQuery in userscript just because of this... Also pasting *file* in contenteditable doesn't paste it as image. That only works for image *data*. – Tomáš Zato Jan 20 '15 at 17:51
  • @TomášZato - it pretty much does, these days. I am also talking about pasting images, not files. – Oded Jan 20 '15 at 18:04