从Firefox剪贴板获取粘贴的图像

18
我试图让用户把图片粘贴到一个
中。问题在于我需要它在Firefox中工作。
据我所知,自从Firefox 13版本以来JavaScript无法访问剪贴板,并且其中不存在event.clipboard。我知道这是可以实现的,因为即使在Firefox中,Gmail和Yahoo也可以允许用户这样操作。
我只想让它以任何方式都能正常工作,使用jQuery、JavaScript、HTML5都可以,只要它能在最新的Firefox中工作就行(不使用Flash)。

6
不是完全重复,因为我已经尝试过那个方法,但在火狐浏览器中不起作用,就像我在帖子中说的那样,event.clipboard在火狐浏览器中不存在,但还是谢谢。 - Bobby Tables
2
我创建了一个简单的统一接口,尝试在不同的浏览器下实现它,也许你应该试试 https://github.com/Puffant/paste.js - Michael Yin
1个回答

14

我使用了这个问题中的代码来实现跨浏览器粘贴功能。它在我测试过的所有浏览器中都可以运行(请向下滚动查看实际解决方案/代码)。需要注意的是,在粘贴事件完成执行后,event.clipboardData会立即过期。

我已经四重检查过,在Firefox 19版本中也可以正常工作(我没有13版本可用,但似乎这个问题是关于新版本中某个功能退化的)。

解决方案

在IE6+、FF 3.5+、近期版本的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>

说明

onpaste事件中,将handlepaste函数附加到它上面,并传递两个参数:this(即对事件所附加的元素的引用)和event,它是事件对象。


handlepaste函数:

第一行只是把可编辑div的内容保存到一个变量中,以便在最后恢复。

if检查浏览器是否为WebKit浏览器(Chrome或Safari),如果是,则将可编辑div的内容设置为正在粘贴的数据。然后取消事件,以防止WebKit粘贴两次。这是因为WebKit很棘手,如果您仅清除div,则不会粘贴任何内容。

如果不是WebKit浏览器,则只需清除可编辑div。

然后调用waitforpastedata函数。


waitforpastedata函数:

这是必要的,因为粘贴的数据不会立即出现,因此如果您立即调用processpaste,则它将没有任何要处理的数据。

它所做的是检查可编辑div是否有任何内容,如果有,则调用processpaste,否则它将设置一个计时器,以便在20毫秒后再次调用自身并重新检查。


processpaste函数:

此函数将可编辑div的innerHTML(现在是粘贴的数据)保存到变量中,将可编辑div的innerHTML恢复为其原始值,然后警告粘贴的数据。显然,在实际使用场景中,您可能希望除了警告数据之外做一些其他事情,您可以从这里开始做任何您想做的事情。

您可能还希望通过某种数据消毒过程运行已粘贴的数据。这可以在可编辑div中或提取的字符串中进行。


在实际情况下,您可能想在保存选择之前和之后进行恢复(在contentEditable <div>上设置光标位置)。然后,可以将粘贴的数据插入用户启动粘贴操作时光标所在的位置。

P.S. 这段代码、IE <= 8和jsfiddle的组合似乎不起作用,但在非jsfiddle环境中的ie <= 8中有效。


5
它适用于文字而非图像...我尝试截屏和粘贴,但没有任何反应。当我复制一个段落并进行粘贴时,弹出一个包含复制段落的窗口,但如果我尝试粘贴图片(例如截屏),则不会弹出窗口。 - chinna_82
1
当我尝试粘贴图像时,它一直运行到waitforpastedata函数,然后进入else语句。它在方法内部不断循环。我尝试通过放置警报窗口来解决问题。 - chinna_82
3
在Safari/Mac OSX中,这对图像数据无效。问题涉及到图像数据,但是在此答案中没有访问图像数据,你获得的MIME类型为"text/html"或"text/plain",这很具有误导性。我们期望的是获得一个"image/png"的MIME类型并使用一些polyfill来替换Safari缺失的image.getAsFile() API。 - FirstVertex
1
我使用HTML5 input事件替代了Timeout,应用在div上。 - Tomáš Zato
1
@Tomáš Zato:开发者不喜欢在div上使用输入事件。 - JavaScript
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接