kof*_*fus 23 javascript clipboard
有没有办法在javascript中将html字符串(即<b>xx<b>
)复制到剪贴板中作为text/html,以便可以将其粘贴到例如带格式的gmail邮件中(即xx以粗体显示)
存在以文本(文本/纯文本)形式复制到剪贴板的解决方案,例如/sf/answers/2156722571/,但不是text/html
我需要一个非闪存,非jquery解决方案,至少可以在IE11 FF42和Chrome上运行.
理想情况下,我想在剪贴板中存储字符串的text和html版本,以便可以粘贴正确的版本,具体取决于目标是否支持html.
Loi*_*ilo 29
由于这个答案得到了一些关注,我已经完全重写了凌乱的原创,以便更容易掌握.如果您想查看修订前的版本,可以在此处找到它.
简而言之的问题:
我可以使用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 container 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 container
// [6]
document.body.removeChild(container)
}
Run Code Online (Sandbox Code Playgroud)
说明:
查看上面代码中的注释,以查看您在以下过程中的当前位置:
我们自己进行复制.这实际上是一个多步骤的过程:Chrome将使用应用的CSS样式复制文本,而其他浏览器将使用浏览器的默认样式复制它.因此,我们将在复制之前禁用所有用户样式,以获得最一致的结果.
copy
命令.这是IE11的黑客攻击:在此浏览器中,必须手动确认一次复制.在用户单击"确认"按钮之前,IE用户将看到没有任何样式的页面.为避免这种情况,我们首先复制,等待确认,然后禁用样式并再次复制.那个时候我们不会得到确认对话,因为IE记得我们的最后选择.copy
再次执行命令.我们已经完成了.
注意事项:
格式化的内容在浏览器中不会完全一致.
如上所述,Chrome(即Blink引擎)将采用与Firefox和IE不同的策略:Chrome将使用CSS样式复制内容,但省略任何未定义的样式.
另一方面,Firefox和IE将不会应用特定于页面的CSS,它们将应用浏览器的默认样式.这也意味着它们会应用一些奇怪的样式,例如默认字体(通常是Times New Roman).
出于安全原因,浏览器只允许该功能作为用户交互的效果执行(例如点击,按键等)
tst*_*tst 18
对于那些寻找使用ClipboardItem执行此操作的方法并且即使将dom.events.asyncClipboard.clipboardItem设置为true也无法使其工作的人,可以在nikouusitalo.com找到答案。
这是我的工作代码(在 Firefox 102 上测试)。
const clipboardItem = new
ClipboardItem({'text/html': new Blob([html],
{type: 'text/html'}),
'text/plain': new Blob([html],
{type: 'text/plain'})});
navigator.clipboard.write([clipboardItem]).
then(_ => console.log("clipboard.write() Ok"),
error => alert(error));
Run Code Online (Sandbox Code Playgroud)
确保尝试将其粘贴到富文本编辑器(例如 gmail)中,而不是粘贴到纯文本/Markdown 编辑器(例如 stackoverflow)中。
小智 17
有一个更简单的解决方案。复制页面(元素)的一部分而不是复制 HTML。
使用这个简单的功能,您可以将页面或整个文档上的任何内容(文本、图像、表格等)复制到剪贴板。该函数接收元素id或元素本身。
function copyElementToClipboard(element) {
window.getSelection().removeAllRanges();
let range = document.createRange();
range.selectNode(typeof element === 'string' ? document.getElementById(element) : element);
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges();
}
Run Code Online (Sandbox Code Playgroud)
如何使用:
copyElementToClipboard(document.body);
copyElementToClipboard('myImageId');
Run Code Online (Sandbox Code Playgroud)
小智 12
如果你想使用新的Clipboard API,请使用如下write
方法:
var type = "text/html";
var blob = new Blob([text], { type });
var data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
function () {
/* success */
},
function () {
/* failure */
}
);
Run Code Online (Sandbox Code Playgroud)
目前(2021 年 9 月),问题是Firefox 不支持此方法。
我对上面 Loilo 的回答做了一些修改:
设置(并稍后恢复)焦点到隐藏的 div 防止 FF 在从 textarea 复制时进入无限递归
将范围设置为 div 的内部子级可防止 chrome<br>
在开头插入额外的内容
getSelection() 上的 removeAllRanges 防止附加到现有选择(可能不需要)
尝试/抓住 execCommand
更好地隐藏复制 div
在 OSX 上,这将不起作用。Safari 不支持 execCommand 并且 chrome OSX 有一个已知错误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();
}
Run Code Online (Sandbox Code Playgroud)
请参阅jsfiddle,您可以在其中将 html 段输入 textarea 并使用 ctrl+c 复制到剪贴板。
归档时间: |
|
查看次数: |
28417 次 |
最近记录: |