问题 如何使用JavaScript复制到剪贴板?
将文本复制到剪贴板的最佳方法是什么? (多浏览器)
我努力了:
function copyToClipboard(text) {
if (window.clipboardData) { // Internet Explorer
window.clipboardData.setData("Text", text);
} else {
unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
clipboardHelper.copyString(text);
}
}
但在Internet Explorer中,它会出现语法错误。在Firefox中,它说 unsafeWindow is not defined
。
没有flash的好技巧: Trello如何访问用户的剪贴板?
12087
2017-12-30 13:09
起源
答案:
概观
有3个主要的浏览器API可用于复制到剪贴板:
- 异步剪贴板API
[navigator.clipboard.writeText]
- 以文本为重点的部分 Chrome 66(2018年3月)
- 访问是异步和使用 JavaScript承诺,可以编写安全用户提示(如果显示)不中断页面中的JavaScript。
- 可以直接从变量将文本复制到剪贴板。
- 仅在通过HTTPS提供的页面上受支持。
- 在Chrome中,活动标签中的66页可以在没有权限提示的情况下写入剪贴板。
document.execCommand('copy')
- 大多数浏览器都支持2015年4月〜(请参阅下面的浏览器支持)。
- 访问是同步的,即在页面中停止JavaScript直到完成,包括显示和用户与任何安全提示交互。
- 从DOM读取文本并将其放在剪贴板上。
- 在测试期间〜2015年4月,只有Internet Explorer被注意为在写入剪贴板时显示权限提示。
- 覆盖复制事件
- 请参阅剪贴板API文档 覆盖复制事件。
- 允许您修改任何复制事件在剪贴板上显示的内容,可以包括纯文本以外的其他格式的数据。
- 这里没有涉及,因为它没有直接回答这个问题。
一般发展说明
在控制台中测试代码时,不要指望与剪贴板相关的命令可以正常工作。通常,页面必须是活动的(Async Clipboard API)或需要用户交互(例如用户点击)才能允许(document.execCommand('copy')
)访问剪贴板请参阅下面的详细信息。
异步+后备
由于浏览器支持新的Async Clipboard API,您可能希望回退到 document.execCommand('copy')
获得良好浏览器覆盖率的方法。
这是一个简单的例子:
function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Fallback: Copying text command was ' + msg);
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text);
return;
}
navigator.clipboard.writeText(text).then(function() {
console.log('Async: Copying to clipboard was successful!');
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
<button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
<button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
<textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
</textarea>
</div>
请注意,此片段在StackOverflow的嵌入式预览中效果不佳,您可以在此处尝试:
https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
异步剪贴板API
请注意,可以通过Chrome 66中的权限API“请求权限”并测试对剪贴板的访问权限。
var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
console.log('Async: Copying to clipboard was successful!');
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
document.execCommand( '复制')
这篇文章的其余部分涉及到的细微差别和细节 document.execCommand('copy')
API。
浏览器支持
JavaScript document.execCommand('copy')
支持增长,请参阅下面的链接以获取浏览器更新:
简单的例子
var copyTextareaBtn = document.querySelector('.js-textareacopybtn');
copyTextareaBtn.addEventListener('click', function(event) {
var copyTextarea = document.querySelector('.js-copytextarea');
copyTextarea.focus();
copyTextarea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
});
<p>
<button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
<textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>
复杂示例:复制到剪贴板而不显示输入
如果有一个,上面这个简单的例子很有用 textarea
要么 input
元素在屏幕上可见。
在某些情况下,您可能希望将文本复制到剪贴板而不显示 input
/ textarea
元件。这是解决此问题的一种方法(基本上是插入元素,复制到剪贴板,删除元素):
使用Google Chrome 44,Firefox 42.0a1和IE 11.0.8600.17814进行测试。
function copyTextToClipboard(text) {
var textArea = document.createElement("textarea");
//
// *** This styling is an extra step which is likely not required. ***
//
// Why is it here? To ensure:
// 1. the element is able to have focus and selection.
// 2. if element was to flash render it has minimal visual impact.
// 3. less flakyness with selection and copying which **might** occur if
// the textarea element is not visible.
//
// The likelihood is the element won't even render, not even a flash,
// so some of these are just precautions. However in IE the element
// is visible whilst the popup box asking the user for permission for
// the web page to copy to the clipboard.
//
// Place in top-left corner of screen regardless of scroll position.
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = 0;
// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';
// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = 0;
// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
// Avoid flash of white box if rendered for any reason.
textArea.style.background = 'transparent';
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
<button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
<button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
<textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
</textarea>
</div>
补充笔记
仅在用户执行操作时有效
所有 document.execCommand('copy')
呼叫必须作为用户动作的直接结果发生,例如单击事件处理程序这是一种防止在用户剪贴板不期望时弄乱用户剪贴板的措施。
见 Google Developers在此发布 了解更多信息。
剪贴板API
请注意,完整的Clipboard API草案规范可以在这里找到:
https://w3c.github.io/clipboard-apis/
是否支持?
document.queryCommandSupported('copy')
应该回来 true
如果命令“由浏览器支持”。
- 和
document.queryCommandEnabled('copy')
返回 true
如果 document.execCommand('copy')
如果现在打电话会成功。检查以确保从用户启动的线程调用该命令并满足其他要求。
但是,作为浏览器兼容性问题的一个示例,Google Chrome从2015年4月到10月才返回 true
从 document.queryCommandSupported('copy')
如果从用户启动的线程调用该命令。
请注意以下兼容性细节
浏览器兼容性细节
虽然简单的电话 document.execCommand('copy')
裹着一个 try
/catch
由于用户点击而调用的块将获得最大的兼容性使用以下有一些附带条件:
任何电话 document.execCommand
, document.queryCommandSupported
要么 document.queryCommandEnabled
应该包裹在一个 try
/catch
块。
不同的浏览器实现和浏览器版本在调用而不是返回时会抛出不同类型的异常 false
。
不同的浏览器实现仍在不断变化 剪贴板API 还在吃水,所以记得做你的测试。
1593
2018-06-12 18:56
自动复制到剪贴板可能很危险,因此大多数浏览器(IE除外)都非常困难。就个人而言,我使用以下简单的技巧:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
将向用户显示提示框,其中已选择要复制的文本。现在它足以按下了 按Ctrl+C 和 输入 (关闭盒子) - 瞧!
现在剪贴板复制操作是SAFE,因为用户手动完成(但是以非常简单的方式)。当然,适用于所有浏览器。
<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>
<script>
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
</script>
1195
2018-05-19 08:06
以下方法适用于Chrome,Firefox,Internet Explorer和Edge以及最新版本的Safari(在2016年10月发布的版本10中添加了复制支持)。
- 创建textarea并将其内容设置为要复制到剪贴板的文本。
- 将textarea附加到DOM。
- 选择textarea中的文本。
- 调用document.execCommand(“copy”)
- 从dom中删除textarea。
注意:您将看不到textarea,因为它是在Javascript代码的同一个同步调用中添加和删除的。
如果您自己实现这一点,需要注意的一些事项:
- 出于安全原因,这只能从事件处理程序(如click)调用(就像打开窗口一样)。
- IE将在第一次更新剪贴板时显示权限对话框。
- IE和Edge将在textarea聚焦时滚动。
- execCommand()可能会抛出某些情况。
- 除非您使用textarea,否则可能会吞下新行和制表符。 (大多数文章似乎建议使用div)
- 显示IE对话框时,textarea将可见,您需要隐藏它,或使用IE特定的clipboardData api。
- 在IE系统中,管理员可以禁用剪贴板API。
以下功能应尽可能干净地处理以下所有问题。如果您发现任何问题或有任何改进建议,请发表评论。
// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and IE 10+.
// IE: The clipboard feature may be disabled by an administrator. By
// default a prompt is shown the first time the clipboard is
// used (per session).
function copyToClipboard(text) {
if (window.clipboardData && window.clipboardData.setData) {
// IE specific code path to prevent textarea being shown while dialog is visible.
return clipboardData.setData("Text", text);
} else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
var textarea = document.createElement("textarea");
textarea.textContent = text;
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in MS Edge.
document.body.appendChild(textarea);
textarea.select();
try {
return document.execCommand("copy"); // Security exception may be thrown by some browsers.
} catch (ex) {
console.warn("Copy to clipboard failed.", ex);
return false;
} finally {
document.body.removeChild(textarea);
}
}
}
https://jsfiddle.net/fx6a6n6x/
196
2017-11-26 00:03
如果你想要一个非常简单的解决方案(整合时间不到5分钟)并且开箱即用,那么Clippy是一些比较复杂的解决方案的不错选择。
大眼夹
它是由Github的联合创始人撰写的。示例Flash嵌入代码如下:
<object
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
width="110"
height="14"
id="clippy">
<param name="movie" value="/flash/clippy.swf"/>
<param name="allowScriptAccess" value="always"/>
<param name="quality" value="high"/>
<param name="scale" value="noscale"/>
<param NAME="FlashVars" value="text=#{text}"/>
<param name="bgcolor" value="#{bgcolor}"/>
<embed
src="/flash/clippy.swf"
width="110"
height="14"
name="clippy"
quality="high"
allowScriptAccess="always"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer"
FlashVars="text=#{text}"
bgcolor="#{bgcolor}"/>
</object>
记得要更换 #{text}
与您需要复制的文本,和 #{bgcolor}
有颜色。
93
2017-10-17 14:40
从网页读取和修改剪贴板会引起安全和隐私问题。但是,在Internet Explorer中,可以执行此操作。我找到了这个 示例代码段:
<script type="text/javascript">
function select_all(obj) {
var text_val=eval(obj);
text_val.focus();
text_val.select();
r = text_val.createTextRange();
if (!r.execCommand) return; // feature detection
r.execCommand('copy');
}
</script>
<input value="http://www.sajithmr.com"
onclick="select_all(this)" name="url" type="text" />
78
2017-12-30 13:33
我最近写过一篇 技术博客文章 关于这个问题(我在Lucidchart工作,我们最近在剪贴板上进行了大修)。
将纯文本复制到剪贴板相对简单,假设您希望在系统复制事件期间执行此操作(用户按下 按CtrlC 或使用浏览器的菜单)。
var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1
|| navigator.userAgent.toLowerCase().indexOf("trident") != -1);
document.addEventListener('copy', function(e) {
var textToPutOnClipboard = "This is some text";
if (isIe) {
window.clipboardData.setData('Text', textToPutOnClipboard);
} else {
e.clipboardData.setData('text/plain', textToPutOnClipboard);
}
e.preventDefault();
});
在系统复制事件期间不将文本放在剪贴板上要困难得多。看起来这些其他答案中的一些参考方法通过Flash来实现,这是唯一的跨浏览器方式(据我所知)。
除此之外,还有一些基于浏览器的选项。
这是IE中最简单的,您可以随时通过JavaScript访问clipboardData对象:
window.clipboardData
(但是,当您尝试在系统剪切,复制或粘贴事件之外执行此操作时,IE将提示用户授予Web应用程序剪贴板权限。)
在Chrome中,您可以创建一个Chrome扩展程序 剪贴板权限 (这就是我们为Lucidchart所做的)。然后,对于安装了扩展程序的用户,您只需要自己触发系统事件:
document.execCommand('copy');
它看起来像Firefox 一些选择 允许用户授予某些网站访问剪贴板的权限,但我没有亲自尝试过这些。
65
2017-12-03 20:31
clipboard.js 是一个小型的非Flash实用程序,允许将文本或html数据复制到剪贴板。它非常容易使用,只需包含.js并使用以下内容:
<button id='markup-copy'>Copy Button</button>
<script>
document.getElementById('markup-copy').addEventListener('click', function() {
clipboard.copy({
'text/plain': 'Markup text. Paste me into a rich text editor.',
'text/html': '<i>here</i> is some <b>rich text</b>'
}).then(
function(){console.log('success'); },
function(err){console.log('failure', err);
});
});
</script>
clipboard.js也在 GitHub上
44
2017-08-11 15:33
ZeroClipboard是我发现的最佳跨浏览器解决方案:
<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>
<script src="ZeroClipboard.js"></script>
<script>
var clip = new ZeroClipboard( document.getElementById('copy') );
</script>
如果您需要iOS的非Flash支持,您只需添加一个后备:
clip.on( 'noflash', function ( client, args ) {
$("#copy").click(function(){
var txt = $(this).attr('data-clipboard-text');
prompt ("Copy link, then click OK.", txt);
});
});
http://zeroclipboard.org/
https://github.com/zeroclipboard/ZeroClipboard
35
2017-11-21 20:41
这是我对那一个的看法..
function copy(text) {
var input = document.createElement('input');
input.setAttribute('value', text);
document.body.appendChild(input);
input.select();
var result = document.execCommand('copy');
document.body.removeChild(input)
return result;
}
30
2017-09-14 09:20