将字符串作为文本/ html复制到剪贴板

有没有一种方法在javascript中将html字符串(即<b>xx<b> )复制到剪贴板中作为text / html,以便它可以粘贴到例如具有格式的gmail消息中(例如,xx in胆大)

有一些解决方案可以以文本(文本/纯文本)的形式复制到剪贴板,例如https://stackoverflow.com/a/30810322/460084而不是text / html

我需要一个非Flash,非jQuery的解决方案,至少可以在IE11 FF42和Chrome上运行。

理想情况下,我想在剪贴板中存储字符串的文本和html版本,以便根据目标是否支持html来粘贴正确的字符串。


由于这个答案已经得到了一些关注,我已经彻底改写了凌乱的原文,以便更容易掌握。 如果你想看一下预修版本,你可以在这里找到它。


下面的问题:

我可以使用JavaScript将某些HTML代码的格式化输出复制到用户剪贴板吗?


回答:

是的,有一些限制,你可以。


解:

以下是一个可以完全实现的功能。 我用你需要的浏览器对它进行了测试,它可以在所有浏览器中运行。 IE 11虽然会要求确认这一行动。

可以在下面找到它的工作原理,你可以在这个jsFiddle中交互地测试这个函数。

// This function expects an HTML string and copies it as rich text.

function copyFormatted (html) {
  // Create container for the HTML
  // [1]
  var container = document.createElement('div')
  container.innerHTML = html

  // Hide element
  // [2]
  container.style.position = 'fixed'
  container.style.pointerEvents = 'none'
  container.style.opacity = 0

  // Detect all style sheets of the page
  var activeSheets = Array.prototype.slice.call(document.styleSheets)
    .filter(function (sheet) {
      return !sheet.disabled
  })

  // Mount the iframe to the DOM to make `contentWindow` available
  // [3]
  document.body.appendChild(container)

  // Copy to clipboard
  // [4]
  window.getSelection().removeAllRanges()

  var range = document.createRange()
  range.selectNode(container)
  window.getSelection().addRange(range)

  // [5.1]
  document.execCommand('copy')

  // [5.2]
  for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = true

  // [5.3]
  document.execCommand('copy')

  // [5.4]
  for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = false

  // Remove the iframe
  // [6]
  document.body.removeChild(container)
}

说明:

查看上述代码中的注释,以查看您目前在以下过程中的位置:

  • 我们创建一个容器来放入我们的HTML代码。
  • 我们将容器设置为隐藏并检测页面的活动样式表。 原因将在短期内解释。
  • 我们把容器放到页面的DOM中。
  • 我们删除可能存在的选择并选择容器的内容。
  • 我们自己复制。 实际上,这是一个多步骤的过程:Chrome会根据应用的CSS样式复制文本,而其他浏览器会将其复制到浏览器的默认样式中。 因此,我们将在复制之前禁用所有用户样式,以获得最一致的结果。

  • 在我们这样做之前,我们提前执行copy命令。 这是对IE11的破解:在这个浏览器中,复制必须手动确认一次。 直到用户点击“确认”按钮,IE用户才会看到没有任何样式的页面。 为了避免这种情况,我们先复制,等待确认,然后禁用样式并再次复制。 由于IE记得我们最后的选择,所以我们不会收到确认对话框。
  • 我们实际上禁用了页面的样式。
  • 我们现在再次执行copy命令。
  • 我们重新启用样式表。
  • 我们从页面的DOM中删除容器。
  • 我们完成了。


    注意事项:

  • 格式化的内容在浏览器中不会完全一致。

    如上所述,Chrome(即Blink引擎)将采用与Firefox和IE不同的策略:Chrome会将内容与CSS样式复制,但省略任何未定义的样式。

    另一方面,Firefox和IE不会应用页面特定的CSS,它们将应用浏览器的默认样式。 这也意味着他们会应用一些奇怪的风格,例如默认字体(通常是Times New Roman)。

  • 出于安全原因,浏览器将仅允许该功能作为用户交互的效果执行(例如,点击,按键等)


  • 我已经对Loilo上面的答案做了一些修改:

  • 将焦点设置(以及稍后恢复)到隐藏的div可防止从textarea复制时FF进入无限递归

  • 将范围设置为div的内部子项可防止chrome在开始时插入额外的<br>

  • getSelection()上的removeAllRanges可防止附加到现有选择(可能不需要)

  • 尝试/抓住execCommand

  • 更好地隐藏复制div

  • 在OSX上这不起作用。 Safari不支持execCommand和chrome OSX有一个已知的bug https://bugs.chromium.org/p/chromium/issues/detail?id=552975

    码:

    clipboardDiv = document.createElement('div');
    clipboardDiv.style.fontSize = '12pt'; // Prevent zooming on iOS
    // Reset box model
    clipboardDiv.style.border = '0';
    clipboardDiv.style.padding = '0';
    clipboardDiv.style.margin = '0';
    // Move element out of screen 
    clipboardDiv.style.position = 'fixed';
    clipboardDiv.style['right'] = '-9999px';
    clipboardDiv.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
    // more hiding
    clipboardDiv.setAttribute('readonly', '');
    clipboardDiv.style.opacity = 0;
    clipboardDiv.style.pointerEvents = 'none';
    clipboardDiv.style.zIndex = -1;
    clipboardDiv.setAttribute('tabindex', '0'); // so it can be focused
    clipboardDiv.innerHTML = '';
    document.body.appendChild(clipboardDiv);
    
    function copyHtmlToClipboard(html) {
      clipboardDiv.innerHTML=html;
    
      var focused=document.activeElement;
      clipboardDiv.focus();
    
      window.getSelection().removeAllRanges();  
      var range = document.createRange(); 
      range.setStartBefore(clipboardDiv.firstChild);
      range.setEndAfter(clipboardDiv.lastChild);
      window.getSelection().addRange(range);  
    
      var ok=false;
      try {
         if (document.execCommand('copy')) ok=true; else utils.log('execCommand returned false !');
      } catch (err) {
         utils.log('execCommand failed ! exception '+err);
      }
    
      focused.focus();
    }
    

    请参阅jsfiddle,您可以在textarea中输入html片段并使用ctrl + c复制到剪贴板。


    近两年过去了,现在有一个更简单的方法来实现这一点,通过使用clipboard.js。

    它需要一个现代浏览器(Chrome 42 +,Firefox 41 +,Opera 29+,Internet Explorer 9+,Safari 10+),但它隐藏了复制粘贴复杂文本的复杂性(无需编写任何代码):

    1)参考clipboard.js

    2)创建一个按钮,并在其点击处理程序中,构建非格式化和格式化(丰富)的文本,并使用库来复制到剪贴板:

    clipboard.copy({
      "text/plain": "Normal text comes here",
      "text/html": "<b>Normal text</b> comes <div style="color: blue;">here</div>"
    })
    .then(
      function() {
         // success code here
      },
      function(err) {
         // failure code here
      }
    );
    
    链接地址: http://www.djcxy.com/p/3323.html

    上一篇: Copy string to clipboard as text/html

    下一篇: Copy / Put text on the clipboard with FireFox, Safari and Chrome