如何将富文本从剪贴板粘贴到HTML文本区域元素?

29

从浏览器复制粘贴到文本处理器时,HTML标记会被转换成富文本,并且文本处理器会尝试将标记转换为自己的格式。这证明了剪贴板能够保存标记。

从浏览器窗口之间进行复制和粘贴(到普通的<textarea>或其他元素中),则忽略标记,尽管标记存在于剪贴板中。

也许有一种解决方案可以使浏览器从剪贴板中选择富文本格式。

是否有办法在<textarea>元素中访问剪贴板的富文本?

换句话说,

标记必须存在于剪贴板中(因为剪贴板还不知道用户是将其粘贴到文本处理器还是网页浏览器),它可以原样粘贴到HTTP POST变量中吗?


你试过了吗?<textarea> - Rex Adrivan
是的,我做了 - 我在问题中添加了澄清。 - Roland Seuhs
5个回答

38

我遇到了一个类似的问题:如何在从桌面应用程序粘贴到浏览器时访问丰富文本格式标记。我找到了以下文章,并有一个解决方案可以解决您的问题,尽管在撰写本文时它尚未解决我的问题。

  1. https://www.lucidchart.com/techblog/2014/12/02/definitive-guide-copying-pasting-javascript/

  2. JavaScript get clipboard data on paste event (Cross browser)

如果您只想获取格式化的HTML(浏览器已为您解析了丰富文本的结果),则答案是访问clipboardData对象并将其传递给“html”参数而不是“text”参数。请参见下面的示例(将以下内容粘贴到名为index.html的文件中并在本地运行即可):

<div id="target" contenteditable="true"></div>

<script>
    document.addEventListener('paste', function(e) {
        e.preventDefault();
        
        var pastedText = ''

        if (window.clipboardData && window.clipboardData.getData) { // IE

            pastedText = window.clipboardData.getData('Text');

        } else if (e.clipboardData && e.clipboardData.getData) {

            pastedText = e.clipboardData.getData('text/html');

        }

        document.getElementById('target').innerHTML = pastedText
    });
</script>

以上示例将clipboardData.getData()拆分成两个版本,一个适用于IE,另一个适用于其他浏览器。大致过程是:首先捕获粘贴事件,然后阻止默认行为,然后将剪贴板数据作为html获取,最后将其放置到div中。此示例的内容完全从上述两个链接中窃取,但简化了我不需要的额外内容(例如:用于管理浏览器焦点的隐藏输入以及对'copy'和'cut'事件的支持)。所有功劳都应归功于那些文章的作者。

根据我的经验(使用mac和chrome),将格式化文本(甚至带有像删除线和缩进这样的模糊格式)粘贴到#target div中会保留原始格式。祝你好运!

现在,如果有人能告诉我如何从clipboardData中获取实际的富文本格式标记,请随意回答此问题。谢谢!


我非常确定,如果你将 $("#target").html(pastedText); 改为 $("#target").text(pastedText);,它应该能够正常工作。我创建了一个类似的非 jQuery 示例。当我设置元素的 innerHTML 时,它会格式化 HTML。当我设置元素的 innerText 时,它会给我标签。 - Eric Dauenhauer

9
假设剪贴板中保存的是“HTML标记”是不正确的。当您从浏览器(或使用多重剪贴板格式的窗口)复制时,窗口会提供尽可能多的格式数据。这包括Rich Text Format (RTF) 和纯文本。 当您粘贴文本时,目标会选择它喜欢或可以呈现的内容。因此,纯文本框会选择纯文本,而您的文字处理软件则会首选富文本,并默认选择纯文本复制。
编辑: 一些浏览器-包括Chrome> v.37至少-在您将内容复制到剪贴板时可能会添加源HTML。这不是Web标准,因此不安全。

2
谢谢您的解释。那么,我该如何访问RTF格式呢?我该如何让浏览器选择RTF而不是纯文本? - Roland Seuhs
@Roland Seuhs,我认为Flash可能会是您的解决方案,但是“RTF标记不以任何方式被解释或翻译。”:http://help.adobe.com/en_US/as3/dev/WS0579B9EE-CF1E-434e-A386-A04DC7786FC9.html - Kaiido
非常遗憾。当一个人将内容粘贴到Google办公套件中时会发生什么?也许他们已经找到了解决方案或变通方法。如果没有,我认为这是Google办公套件的一个重大限制。 - Roland Seuhs
@RolandSeuhs 你可以创建一个带有 contenteditable 属性的 div。这将使 DIV 可编辑,因此当用户粘贴内容时,它将选择 RTF 并将其转换为 HTML。因此,生成的 HTML 不能保证与执行复制的原始标记匹配。请注意,我说“不能保证”,但是剪贴板可能保存有 HTML 副本,这取决于浏览器如何填充剪贴板。 - doc_id
这展示了contenteditable http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_global_contenteditable 例如在Chrome中,如果你复制页面上的任何部分并粘贴到那个div中,它将保留HTML。这可能不是其他浏览器的标准。 - doc_id
显示剩余2条评论

2

感谢优秀的Chris Chalmer的回答,但是如何让它更加完整呢?我希望能添加一些填充并获取代码...在Edge、FF和Chrome中测试过,甚至在这里也可以工作;-)

<div id="target" style="height: 75%;border:1px solid gray" contenteditable="true">Paste here...</div>
<textarea style="height:25%;width: 100%;"></textarea>
<script>
    document.addEventListener('paste', function(e) {
        e.preventDefault();
        
        var pastedText = ''

        if (window.clipboardData && window.clipboardData.getData) { // IE

            pastedText = window.clipboardData.getData('Text');

        } else if (e.clipboardData && e.clipboardData.getData) {

            pastedText = e.clipboardData.getData('text/html');

        }

        var tmp1 = ["<div style=\"", "</div>"];
        var tmp2 = [pastedText.indexOf(tmp1[0]) + tmp1[0].length, pastedText.lastIndexOf(tmp1[1])];
        pastedText = tmp1[0] + "padding:8px;" + pastedText.substr(tmp2[0], tmp2[1] - tmp2[0]);
        tmp1 = document.getElementById('target');
        tmp1.innerHTML = pastedText;
        tmp1.nextElementSibling.value = pastedText;
    });
</script>


VSC Code 默认情况下的外观如下:<html>\r\n<body>\r\n<!--StartFragment--><div style="...</div><!--EndFragment-->\r\n</body>\r\n</html> - Tom

1
Google Office支持RichText格式。当文本从IE复制时,IE会将文本复制到剪贴板中的纯文本、富文本和HTML文本。因此,从IE复制到Google办公室将显示富格式文本。另一方面,FireFox只能将文本复制为纯文本和HTML文本格式。因此,任何不接受HTML格式文本的目标都将显示纯文本中的文本。

3
有没有一种方法可以访问HTML文本缓冲区? - Roland Seuhs

0

我个人寻找了一种从剪贴板中获取rtf的解决方案,并在这个jsbin中成功实现:

console.log(event.clipboardData.types);
let paste = (event.clipboardData || window.clipboardData).getData('text/rtf');

为了在插入到文本区域时不进行转义而分配内容(不要忘记更新querySelector + html):

target.value=paste

还有其他类型可用,如文件或HTML。我通过从Excel复制进行了测试。


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