如何将文本复制到剪贴板(多浏览器)?
如何将文本复制到剪贴板(多浏览器)?
有三种主要的浏览器API可用于复制到剪贴板:
异步剪贴板 API [navigator.clipboard.writeText]
document.execCommand('copy')
(已弃用)
覆盖复制事件
在测试控制台中的代码时,不要期望剪贴板相关命令能够正常工作。通常情况下,页面需要处于活动状态(异步剪贴板 API),或需要用户交互(例如用户点击)才能允许使用 (document.execCommand('copy')
) 访问剪贴板,详情请参见下文。
请注意,自此帖子最初编写以来,跨域 IFRAME 权限的弃用 和其他 IFRAME 的"沙盒化" 控制在某些浏览器(包括 Chrome 和 Microsoft Edge)中阻止了嵌入式演示的 "运行代码片段" 按钮和 "codepen.io 示例" 的正常工作。
为了进行开发,请创建您自己的网页,并通过 HTTPS 连接提供该页面以进行测试和开发。
这里是一个演示代码工作的测试/演示页面: https://deanmarktaylor.github.io/clipboard-test/document.execCommand('copy')
方法以获得良好的浏览器覆盖率。function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
// Avoid scrolling to bottom
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
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>
请注意,在 Chrome 66 中,通过权限 API 可以“请求权限”并测试访问剪贴板的功能。
请注意,此代码段在 Stack Overflow 的嵌入式预览中可能无法正常工作,请在 此处 尝试。
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('copy')
API的细节和详细信息。
JavaScript (已弃用)document.execCommand('copy')
的支持已经增加,请参阅以下链接获取浏览器更新:
(may not work embedded in this site, read "important" note above)
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 和 Internet Explorer 11.0.8600.17814 上进行了测试。
(may not work embedded in this site, read "important" note above)
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 the 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
// Internet Explorer the element is visible whilst the popup
// box asking the user for permission for the web page to
// copy to the clipboard.
//
// Place in the 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 the 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开发人员文章。
请注意,完整的Clipboard API草案规范可以在此处找到: https://w3c.github.io/clipboard-apis/
document.queryCommandSupported('copy')
应返回true
,如果浏览器“支持该命令”。document.queryCommandEnabled('copy')
如果现在调用document.execCommand('copy')
将成功,则返回true
。检查以确保从用户启动的线程调用命令以及满足其他要求。document.execCommand
已经过时。请参考 https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand - tnkhvar previousFocusElement = document.activeElement (....所有回退代码...) previousFocusElement.focus();
- Matthias自动复制到剪贴板可能存在风险,因此大多数浏览器(除了Internet Explorer)都会设置非常严格的限制。个人建议采用以下简单的技巧:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
<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>
以下方法适用于Chrome、Firefox、Internet Explorer和Edge,以及最近版本的Safari(复制支持在2016年10月发布的第10版中添加)。
注意:您不会看到textarea,因为它是在同步调用Javascript代码的同一次添加和删除内完成的。
如果您要自己实现这些,请注意以下几点:
下面的函数应尽可能清晰地处理所有这些问题。如果您发现任何问题或有任何改进建议,请留下评论。
// 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 Internet Explorer 10+.
// Internet Explorer: 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) {
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
return window.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 Microsoft 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 prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
finally {
document.body.removeChild(textarea);
}
}
}
以下是我的看法...
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;
}
@korayem: 请注意,使用html input
字段将不会尊重换行符\n
,并将任何文本变成单行。
如@nikksan在评论中提到的那样,使用textarea
将解决这个问题:
function copy(text) {
var input = document.createElement('textarea');
input.innerHTML = text;
document.body.appendChild(input);
input.select();
var result = document.execCommand('copy');
document.body.removeChild(input);
return result;
}
从网页读取和修改剪贴板会引起安全和隐私问题。但是,在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" />
execCommand('copy');
是做什么用的,如果不是将内容复制到IE的剪贴板中?这段代码使用 execCommand()
方法执行一个命令,在此例中是将选定文本复制到剪贴板上。虽然该方法在早期版本的IE浏览器中可以直接使用,但在现代浏览器中需要更多的代码才能实现跨浏览器兼容性。 - RozzAif(!document.all)
,而应该使用if(!r.execCommand)
,以免其他人也实现它!document.all
与此完全无关。 - m93a如果你想要一个真正简单的解决方案(不到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}
替换为颜色。
我最近写了一篇技术博客,讲述了这个问题(我在Lucidchart工作,我们最近对剪贴板进行了大修)。
如果你尝试在系统复制事件期间(用户按下Ctrl+C或使用浏览器菜单)将纯文本复制到剪贴板中,那么这相对简单。
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进行操作的方法,这是目前我所了解的唯一跨浏览器的方式。
除此之外,在不同的浏览器中有一些选项可供选择。
在Internet Explorer中,这是最简单的,您可以通过JavaScript随时访问clipboardData对象:
window.clipboardData
但是,如果您在系统剪切、复制或粘贴事件之外尝试执行此操作,则Internet Explorer会提示用户授予Web应用程序剪贴板权限。
在Chrome中,您可以创建一个Chrome扩展程序,为您提供剪贴板权限(这就是我们为Lucidchart所做的)。然后对于已安装您扩展程序的用户,您只需要自己触发系统事件即可:
document.execCommand('copy');
看起来火狐浏览器有一些选项允许用户授予某些网站访问剪贴板的权限,但我个人尚未尝试过。
我喜欢这个:
<input onclick="this.select();" type='text' value='copy me' />
如果用户不知道如何在操作系统中复制文本,那么他们可能也不知道怎样粘贴。因此,只需将它自动选择,剩下的就留给用户。
如果用户不知道如何在操作系统中复制文本,那么他们可能也不知道如何进行粘贴。 因此,最好让文本自动选中,剩下的就交给用户处理。
<input onclick="this.select(); document.execCommand('copy');" type='text' value='copy me' />
- Roubiclipboard.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 上。
注意: 此版本已被弃用,请迁移到此处。
2018 年,以下是如何进行的方法:
async copySomething(text?) {
try {
const toCopy = text || location.href;
await navigator.clipboard.writeText(toCopy);
console.log('Text or Page URL copied');
}
catch (err) {
console.error('Failed to copy: ', err);
}
}
这是我在Angular 6+代码中的使用方式:
<button mat-menu-item (click)="copySomething()">
<span>Copy link</span>
</button>
如果我传入一个字符串,它会复制它。如果没有传入任何内容,则会复制页面的URL。
还可以对剪贴板相关操作进行更多的处理。在此处查看更多信息: