如何使用JavaScript将富文本内容复制到剪贴板?

71

前提条件

我需要使用JavaScript将富文本复制到剪贴板中,但是我搜索了许多资料都没有找到满足我的特定需求的方法。

代码

function ctrlA1(corp) {
  with(corp) {}
  if (document.all) {
    txt = corp.createTextRange()
    txt.execCommand("Copy")
  } else
    setTimeout("window.status=''", 5000)
}
<div id="sc1">hello <br> <b> world </b> </div>
<button onclick="ctrlA1(document.getElementById('sc1') )"></button>

问题

上述代码不起作用,并导致 object expected error 错误。感谢任何帮助! 我见过一个名为 zeroclipboard 的库,但更喜欢编写自己的函数。


编辑:

现在我有了这个选择页面文本的功能。是否可能编写一个公式以原样复制所选范围?

function containerSelect(id) {
  containerUnselect();
  if (document.selection) {
    var range = document.body.createTextRange();
    range.moveToElementText(id);
    range.select();
  } else if (window.getSelection) {
    var range = document.createRange();
    range.selectNode(id);
    window.getSelection().addRange(range);
  }
}
<label onclick="containerSelect(this); select_all()">
  <p>hello world</p>
  <img src="imagepath.png">
</label>


顺便说一下,不建议使用with语句,因为它可能是混淆错误和兼容性问题的源头。 - Andy
仅使用JS的解决方案,请参见http://jsfiddle.net/jdhenckel/km7prgv4/3 - John Henckel
7个回答

102
使用现代浏览器,如果你只想复制富文本,有一个非常简单的解决方案,而且不需要使用任何软件包。请参考这个链接:http://jsfiddle.net/jdhenckel/km7prgv4/3 以下是来自这个示例的源代码。
<button onclick="copyToClip(document.getElementById('foo').innerHTML)">
  Copy the stuff
  </button>
  
<div id=foo style="display:none">
  This is some data that is not visible. 
  You can write some JS to generate this data. 
  It can contain rich stuff.  <b> test </b> me <i> also </i>
  <span style="font: 12px consolas; color: green;">Hello world</span> 
  You can use setData to put TWO COPIES into the same clipboard, 
  one that is plain and one that is rich. 
  That way your users can paste into either a
  <ul>
    <li>plain text editor</li>
    <li>or into a rich text editor</li>
  </ul>
</div>

功能

function copyToClip(str) {
  function listener(e) {
    e.clipboardData.setData("text/html", str);
    e.clipboardData.setData("text/plain", str);
    e.preventDefault();
  }
  document.addEventListener("copy", listener);
  document.execCommand("copy");
  document.removeEventListener("copy", listener);
};

⚠️ ClipboardEvent.clipboardData 是实验性技术。请查看MDN中的浏览器兼容性表格(05-03-21) 编辑: 使用execCommand已被弃用!请查看新的ClipboardAPI。我强烈推荐阅读Artemis的文章

谢谢。我通过将其复制并粘贴到Word中进行了测试。在Chrome上运行得非常好。但是在IE11上似乎根本无法工作。在Edge上,它会粘贴文本但不包括格式。 - gordon613
抱歉,我没有在IE 11或Edge上进行测试。我想知道...如果你交换两个 e.clipboardData.setData,那么也许你可以在IE Edge上粘贴富文本...?只是一个想法。 - John Henckel
2
在Safari 11.1.1中无法工作。无论如何都不能复制,先前剪贴板上的内容仍然存在。 - John Smith
1
这对我在FF,Chrome,Edge和IE11中有效。 IE11会提示用户是否允许访问剪贴板。 在Safari中不起作用。 需要另一种方法,并且据我所知,您无法复制“富文本”,只能复制纯文本。 - Mmm
3
你可以使用稍微修改过的代码为不能渲染 HTML 的编辑器提供仅文本版本:http://jsfiddle.net/kt4jdm95/1/ - SleepWalker
注意:document.execCommand已被弃用 - undefined

12

这个微小的JS插件可以复制富文本,而无需使用Flash:https://www.npmjs.com/package/clipboard-js

它基于https://clipboardjs.com/ - 但我认为这是一种升级,因为原始版本仅支持纯文本。

代码很简单:

clipboard.copy({
    "text/html": "<i>Markup</i> <b>text</b>. Paste me into a rich text editor."
});

1
运行得非常好,而且确实很简单。 - Mat
9
对于现代浏览器,如果你只想复制富文本,有一个非常简单的解决方案 不需要使用任何软件包。请参考 https://jsfiddle.net/jdhenckel/km7prgv4/3/。 - John Henckel
1
@JohnHenckel,太棒了!你应该把它作为答案! - Dan Lenski
3
提醒一下,对于IE浏览器,@SFlagg的解决方案只会复制纯文本而非富文本。 - gordon613
如果富文本包含图片,我无法使其正常工作。 - Jules Colle
我在这里创建了一个功能性的示例:https://dev59.com/NZHea4cB1Zd3GeqPliuD#33758293 - Mr. Polywhirl

8

这是我使用新的剪贴板API测试的示例:

const content = '<a href="http://google.com/">test</a>';
const blob = new Blob([content], {type: 'text/html'});
const clipboardItem = new window.ClipboardItem({ 'text/html': blob });
navigator.clipboard.write([clipboardItem]);

使用此方法,您可以将HTML复制到剪贴板。需要注意的一个有用的事情是这可以包括图像(可以是数据URL)。这是我发现的唯一一种将多个图像粘贴到剪贴板的方式。

1
这在Firefox上不起作用。请参见我在类似的帖子中的答案 - tst
如果在控制台中尝试此操作,可能会失败,因为文档本身没有焦点,这种情况下,您可能需要将此代码放入setTimeout中,以便您有时间将焦点移回文档。 - BallpointBen

3
这是一个简单的函数,它使用剪贴板 API(在我写这篇文章时,除了 Firefox 之外的所有地方都支持)并在不支持的情况下回退到document.execCommand("copy")方法(已弃用,但目前在所有地方都有效),希望 Firefox 在放弃对execCommand的支持之前能添加对剪贴板 API 的支持 :)
/** Paste richly formatted text.
 *
 * @param {string} rich - the text formatted as HTML
 * @param {string} plain - a plain text fallback
 */
async function pasteRich(rich, plain) {
  if (typeof ClipboardItem !== "undefined") {
    // Shiny new Clipboard API, not fully supported in Firefox.
    // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#browser_compatibility
    const html = new Blob([rich], { type: "text/html" });
    const text = new Blob([plain], { type: "text/plain" });
    const data = new ClipboardItem({ "text/html": html, "text/plain": text });
    await navigator.clipboard.write([data]);
  } else {
    // Fallback using the deprecated `document.execCommand`.
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand#browser_compatibility
    const cb = e => {
      e.clipboardData.setData("text/html", rich);
      e.clipboardData.setData("text/plain", plain);
      e.preventDefault();
    };
    document.addEventListener("copy", cb);
    document.execCommand("copy");
    document.removeEventListener("copy", cb);
  }
}

你可能也想尝试一下适用于Clipboard API的合适的polyfill

1

OP在他的问题中提到了zeroclipboard,而我在我的评论中谈到了它。 - Andy
我只是想提供一个答案。因为没有可靠的JS方法可以做到这一点。 - James Harrington
@codenamejames:好的,我尝试使用ZC上的帮助,但我觉得我还不太成功。这是我的代码,它仍然无法工作:( - marv
<div id="d_clip_button">复制到剪贴板</div> <script type="text/javascript" src="ZeroClipboard.js"></script> <script type="text/javascript"> ZeroClipboard.setMoviePath("ZeroClipboard.swf"); var client = new ZeroClipboard( document.getElementById('d_clip_button') ); </script> - marv
@codenamejames,不幸的是那个方法没起作用。我得到了一个“对象不支持此方法”的错误。我有另一个函数可以选择网页上的文本/图像(在我的帖子上编辑)。现在我能否编写一个函数来复制所选范围? - marv
显示剩余2条评论


-3
我已经搜索了一个星期,终于找到了答案!!! 对于那些想要使用JavaScript将富文本复制到剪贴板的人,可以使用下面链接中的函数,非常好用。 不需要使用Flash或其他建议的东西:) 使用JavaScript / jQuery将图像复制到剪贴板

2
那是针对图片的,不是富文本。而且它只支持IE :-( - John Henckel

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