18

I'm trying to allow the user to paste an image into a div. The problem is that I need it work in Firefox.

From what I've read, Firefox since version 13 (I think) doesn't allow JavaScript access to the clipboard, and event.clipboard doesn't exist in it. I know it can be done because Gmail and Yahoo alow it even in Firefox.

I just want it to work in anyway posible, be with jQuery, JavaScript, HTML5, it doesn't matter as long as it works in the latest Firefox. (No Flash though).

Whymarrh
  • 11,635
  • 13
  • 55
  • 96
Bobby Tables
  • 2,774
  • 7
  • 24
  • 48
  • possible duplicate of [How does the paste image from clipboard functionality work in Gmail and Google Chrome 12+?](http://stackoverflow.com/questions/6333814/how-does-the-paste-image-from-clipboard-functionality-work-in-gmail-and-google-c) – epascarello Mar 06 '13 at 17:32
  • 6
    @epascarello It's not really a duplicate, because i tried that and it doesn't work in firefox as i said in the post event.clipboard doesn't exist in firefox, but thanks anyway – Bobby Tables Mar 06 '13 at 19:20
  • 2
    i created a simple unified interface trying to do that under different browsers, maybe you should have a try https://github.com/Puffant/paste.js – Michael Yin Feb 10 '14 at 10:02

1 Answers1

14

I used the code from this question for my cross-browser paste implementation.. it works in all browsers I have tested (scroll down for the actual solution/code). It should be noted that event.clipboardData expires immediately after the paste event has completed execution.

I went ahead and quadruple checked that this does work in Firefox version 19 (I don't have 13 available, but it sounds like this question was about degradation of a feature in newer versions).

Below is the answer, quoted from Nico Burns:

Solution

Tested in IE6+, FF 3.5+, recent-ish versions of Opera, Chrome, Safari.

function handlepaste (elem, e) {
  var savedcontent = elem.innerHTML;
  if (e && e.clipboardData && e.clipboardData.getData) {// Webkit - get data from clipboard, put into editdiv, cleanup, then cancel event
    if (/text\/html/.test(e.clipboardData.types)) {
      elem.innerHTML = e.clipboardData.getData('text/html');
    }
    else if (/text\/plain/.test(e.clipboardData.types)) {
      elem.innerHTML = e.clipboardData.getData('text/plain');
    }
    else {
      elem.innerHTML = "";
    }
    waitforpastedata(elem, savedcontent);
    if (e.preventDefault) {
      e.stopPropagation();
      e.preventDefault();
    }
    return false;
  }
  else {// Everything else - empty editdiv and allow browser to paste content into it, then cleanup
    elem.innerHTML = "";
    waitforpastedata(elem, savedcontent);
    return true;
  }
}

function waitforpastedata (elem, savedcontent) {
  if (elem.childNodes && elem.childNodes.length > 0) {
    processpaste(elem, savedcontent);
  }
  else {
    that = {
      e: elem,
      s: savedcontent
    }
    that.callself = function () {
      waitforpastedata(that.e, that.s)
    }
    setTimeout(that.callself,20);
  }
}

function processpaste (elem, savedcontent) {
  pasteddata = elem.innerHTML;
  //^^Alternatively loop through dom (elem.childNodes or elem.getElementsByTagName) here

  elem.innerHTML = savedcontent;

  // Do whatever with gathered data;
  alert(pasteddata);
}
<div id='div' contenteditable='true' onpaste='handlepaste(this, event)'>Paste</div>

Explanation

The onpaste event has the handlepaste function attached to it, and passed two arguments: this (i.e. a reference to the element that the event is attached to) and event which is the event object.


The handlepaste function:

The first line simply saves the content of the editable div to a variable so it can be restored again at the end.

The if checks whether the browser is an webkit browser (chrome or safari), and if it is it sets contents of the editable div to the data being pasted. It then cancels the event to prevent webkit pasting anything twice. This is because webkit is awkward, and won't paste anything if you simply clear the div.

If it is not a webkit browser then it simply clears the editable div.

It then calls the waitforpastedata function


The waitforpastedata function:

This is necessary because the pasted data doesn't appear straight away, so if you just called processpaste straight away then it wouldn't have any data to process.

What it does is check if the editable div has any content, if it does then calls processpaste, otherwise it sets a timer to call itself and check again in 20 milliseconds.


The processpaste function:

This function saved the innerHTML of the editable div (which is now the pasted data) to a variable, restores the innerHTML of the editable div back to its original value, and the alert the pasted data. Obviously in a real usage scenario you would probably want to something other than just alert data, you can do whatever you like with it from here.

You will probably also want to run the pasted data through some kind of data sanitising process. This can be done either while it is still in the editable div, or on the extracted string.


In a real sitution you would probably want to save the selection before, and restore it afterwards (Set cursor position on contentEditable <div>). You could then insert the pasted data at the position the cursor was in when the user initiated the paste action.

P.S. The combination of this code, IE <= 8 and jsfiddle doesn't seem to work, but it does work in ie <= 8 in a non-jsfiddle environment.

Community
  • 1
  • 1
Dave Lasley
  • 5,072
  • 1
  • 32
  • 37
  • It worked, you're a life saver thank you very much and sorry for taking so to mark it as a correct answer – Bobby Tables Mar 11 '13 at 13:10
  • Hi, i want to change this code for clipboard images whan can i do ? – altandogan Apr 18 '13 at 06:57
  • @user990513 The above code already saves a client side clipboard image into a variable. Please further clarify if I misread your question – Dave Lasley Apr 18 '13 at 22:56
  • 5
    it works for words not image... i try to print screen and paste.Nothing came up. when i copied a paragraph and paste there is a pop up with copied paragraph but no pop up if i try to paste images, like print screen – chinna_82 Jul 16 '13 at 05:41
  • @chinna_82 I'm not understanding where the popup you are referencing is coming from. The code above will allow you to paste clipboard data into an element for processing and has been tested to work with a print screen. – Dave Lasley Jul 16 '13 at 19:23
  • 1
    when i try paste the image. It went until waitforpastedata function then else statement. It was keep on looping inside the method. I tried by putting alert window. – chinna_82 Jul 23 '13 at 08:19
  • 2
    This does not work for image data in Safari/Mac OSX. It is misleading because the question asks about image data and clearly you aren't accessing image data in this answer, the mime types you get are "text/html" or "text/plain". We would expect a mime of "image/png" and then some polyfill to replace Safari's missing image.getAsFile() API. – H Dog Mar 31 '14 at 20:35
  • @HDog Your request is entirely beyond the scope of this question/answer. All image data is sent to the div containing all necessary headers. You are attempting to pass image data directly into an API, not paste an image into a div. Furthermore, the `text/html` is so that it can be added to the div, as they do not support images directly. I have not specifically tested this with Safari, but I believe that the `clipboardData` event is still exposed. Regardless, I recommend creating a new question if you need the functionality you described. – Dave Lasley Apr 01 '14 at 23:15
  • 1
    Instead of `Timeout`, I use HTML5 `input` event on the div. – Tomáš Zato - Reinstate Monica Oct 22 '14 at 20:19
  • 1
    @Tomáš Zato: Explorers dislike input events on divs. – JavaScript Jul 21 '15 at 14:24