如何在JavaScript中复制到剪贴板上?
如何将文本复制到剪贴板上(多浏览器)?
相关的: Trello如何访问用户的剪贴板?
概述
有三个主要的浏览器API用于复制到剪贴板上:
异步剪贴板 API
[navigator.clipboard.writeText]
- 在Chrome 66(2018年3月)中提供以文本为重点的部分。
- 访问是异步的,并且使用JavaScript Promises,可以编写成安全用户提示(如果显示的话)不会中断页面中的JavaScript。
- 文本可以直接从一个变量中复制到剪贴板上。
- 只支持通过HTTPS提供的页面。
- 在Chrome 66中,不活动的标签页可以写到剪贴板上,而不会有权限提示。
document.execCommand('copy')
(弃用)👎- 从2015年4月起,大多数浏览器都支持这个功能(见下面的浏览器支持)。
- 访问是同步的,即停止页面中的JavaScript,直到完成包括显示和用户与任何安全提示的互动。
- 从DOM中读取文本,并放置在剪贴板上。
- 在测试期间~2015年4月,只有Internet Explorer被指出在写入剪贴板时显示权限提示。
重写复制事件
- 请参阅关于覆盖复制事件的Clipboard API文档。
- 允许你修改从任何复制事件中出现在剪贴板上的内容,可以包括除纯文本以外的其他格式的数据。
- 这里不涉及,因为它没有直接回答这个问题。
一般开发说明
当你在控制台中测试代码时,不要指望与剪贴板有关的命令会工作。一般来说,页面需要被激活(Async Clipboard API)或需要用户互动(如用户点击)以允许(document.execCommand('copy')
)访问剪贴板,更多细节见下文。
重要(在此指出2020/02/20)。
请注意,自本帖最初撰写以来,跨源IFRAME中权限的取消和其他IFRAME "沙盒化"使嵌入式演示"运行代码片段" 按钮和"codepen.io 示例"无法在某些浏览器(包括 Chrome 和 Microsoft Edge)中正常工作。
要开发创建你自己的网页,通过HTTPS连接提供该网页,以进行测试和开发。
下面是一个演示代码工作的测试/演示页面:https://deanmarktaylor.github.io/clipboard-test/。
异步+回退
由于浏览器对新的异步剪贴板API的支持程度,你很可能想退回到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>
(codepen.io的例子可能不起作用,请阅读上面的"重要"说明)注意,这个片段在Stack Overflow的嵌入式预览中工作得不好,你可以在这里试试: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 (deprecated) 👎document.execCommand('copy')
的支持已经增加,请看下面的浏览器更新链接:
- Internet Explorer 10+(尽管本文档表明从Internet Explorer 5.5+开始就有了一些支持)。
- 谷歌浏览器43+ (~2015年4月)
- 火狐41+ (2015年9月发货)
- Opera 29+ (基于Chromium 42, ~April 2015).
简单的例子
(可能无法嵌入本网站,请阅读上面的"重要"说明)
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
元素。这是解决这个问题的一个例子(基本上是插入一个元素,复制到剪贴板,删除元素):
使用谷歌浏览器44、火狐浏览器42.0a1和Internet Explorer 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 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 开发人员的帖子,以了解更多信息。
剪贴板应用程序接口
注意完整的剪贴板API规范草案可以在这里找到:https://w3c.github.io/clipboard-apis/。
它是否得到支持?
- 如果该命令被浏览器支持,则
document.queryCommandSupported('copy')
应返回true
。 - 和
document.queryCommandEnabled('copy')
返回true
,如果现在调用document.execCommand('copy')
会成功。检查以确保该命令是从用户发起的线程中调用的,并满足其他要求。
然而,作为浏览器兼容性问题的一个例子,谷歌浏览器从~2015年4月到~10月,如果命令是从用户发起的线程中调用的,则只返回true
,而不是document.queryCommandSupported('copy')
。
请注意下面的兼容性细节。
浏览器兼容性详解
虽然一个简单的调用document.execCommand('copy')
包裹在用户点击后调用的try
/catch
块中,会让你获得最大的兼容性使用,但下面有一些限制条件:
任何对document.execCommand
、document.queryCommandSupported
或document.queryCommandEnabled
的调用都应该被包裹在一个try
/catch
的块中。
不同的浏览器实现和浏览器版本在调用时都会抛出不同类型的异常,而不是返回false
。
不同的浏览器实现仍在不断变化,并且Clipboard API仍在起草中,所以记得要进行测试。
document.execCommand is obsolete
。见developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
- tnkh 2020-10-12
var previousFocusElement = document.activeElement (....all the fallback code...) previousFocusElement.focus();
- Matthias 2021-10-20
自动复制到剪贴板可能会有危险,因此大多数浏览器(除IE浏览器外)都会让它变得非常困难。就我个人而言,我使用下面这个简单的技巧:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
用户会看到一个提示框,其中要复制的文本已经被选中。现在只需按下Ctrl+C和Enter(关闭提示框)--就可以了!
现在,剪贴板复制操作是安全的,因为用户是手动操作的(但方式很直接)。当然,它在所有的浏览器中都能工作。
<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,并将其内容设置为你想复制到剪贴板的文本。
- 将文本区追加到DOM中。
- 选择文本区中的文本。
- 调用document.execCommand("copy")。
- 从dom中删除textarea。
注意:你不会看到文本区域,因为它是在同一个同步调用的Javascript代码中被添加和删除的。
如果你自己实施的话,有一些事情需要注意:
- 出于安全考虑,这只能从一个事件处理程序中调用,如点击(就像打开窗口一样)。
- 在第一次更新剪贴板时,Internet Explorer会显示一个权限对话框。
- Internet Explorer和Edge会在文本区被聚焦时进行滚动。
- execCommand()在某些情况下可能会被抛出。
- 除非你使用一个文本区域,否则换行符和制表符会被吞噬。(大多数文章似乎都建议使用div)。
- 当Internet Explorer对话框显示时,文本区域将是可见的,你要么需要隐藏它,要么使用Internet Explorer特定的clipboardData API。
- 在Internet Explorer中,系统管理员可以禁用剪贴板的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 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?@mrBorna
- RozzA 2012-04-24
if(!document.all)
,而要使用if(!r.execCommand)
,以免有其他人实现它!Document.all与此绝对不相关。
- m93a 2013-04-15
如果您想要一个真正简单的解决方案(只需不到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会提示用户授予网络应用程序剪贴板的权限)。
在Chrome浏览器中,您可以创建一个Chrome扩展,该扩展将为您提供clipboard权限(这就是我们为Lucidchart做的事情)。然后对于安装了你的扩展的用户,你只需要自己触发系统事件:
document.execCommand('copy');
看起来Firefox有一些选项,允许用户向某些网站授予访问剪贴板的权限,但我还没有亲自尝试过这些选项。
我喜欢这个人:
<input onclick="this.select();" type='text' value='copy me' />
如果一个用户不知道如何在他们的操作系统中复制文本,那么很可能他们也不知道如何粘贴。因此,只要让它自动选择,其余的就留给用户。
<input onclick="this.select(); document.execCommand('copy');" type='text' value='copy me' />
- Roubi 2021-05-28
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>
剪贴板.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。
也可以对剪贴板进行更多操作。在此处查看更多信息:
我非常成功地使用了这个方法(没有jQuery或任何其他框架)。
function copyToClp(txt){
var m = document;
txt = m.createTextNode(txt);
var w = window;
var b = m.body;
b.appendChild(txt);
if (b.createTextRange) {
var d = b.createTextRange();
d.moveToElementText(txt);
d.select();
m.execCommand('copy');
}
else {
var d = m.createRange();
var g = w.getSelection;
d.selectNodeContents(txt);
g().removeAllRanges();
g().addRange(d);
m.execCommand('copy');
g().removeAllRanges();
}
txt.remove();
}
警告:在此情况下,请勿使用 "不正当手段"。
选项卡被转换为空格(至少在Chrome中是这样)。
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);
});
});
src
的值)。我觉得他们的文档很漂亮,但效率很低。
- Gui Imamura 2015-07-23
由于Chrome 42+和Firefox 41+现在支持document.execCommand('copy')命令,我使用Tim Down的旧答案和Google Developer的答案的组合,为跨浏览器复制到剪贴板的能力创建了几个函数:
function selectElementContents(el) {
// Copy textarea, pre, div, etc.
if (document.body.createTextRange) {
// Internet Explorer
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.select();
textRange.execCommand("Copy");
}
else if (window.getSelection && document.createRange) {
// Non-Internet Explorer
var range = document.createRange();
range.selectNodeContents(el);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copy command was ' + msg);
}
catch (err) {
console.log('Oops, unable to copy');
}
}
} // end function selectElementContents(el)
function make_copy_button(el) {
var copy_btn = document.createElement('input');
copy_btn.type = "button";
el.parentNode.insertBefore(copy_btn, el.nextSibling);
copy_btn.onclick = function() {
selectElementContents(el);
};
if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {
// Copy works with Internet Explorer 4+, Chrome 42+, Firefox 41+, Opera 29+
copy_btn.value = "Copy to Clipboard";
}
else {
// Select only for Safari and older Chrome, Firefox and Opera
copy_btn.value = "Select All (then press Ctrl + C to Copy)";
}
}
/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy,
but there was a bug in Chrome versions 42 to 47 that makes it return "false". So in those
versions of Chrome feature detection does not work!
See https://code.google.com/p/chromium/issues/detail?id=476508
*/
make_copy_button(document.getElementById("markup"));
<pre id="markup">
Text that can be copied or selected with cross browser support.
</pre>
在JavaScript/TypeScript中,最好的和简单的方法是使用这个命令
navigator.clipboard.writeText(textExample);
只需在textExample中传递你想复制到剪贴板的值即可。
我已经把我认为最好的一个放在一起了。
- 使用cssText来避免在Internet Explorer中出现异常,而不是直接使用样式。
- 如果有选择,则恢复选择。
- 设置为只读,这样在移动设备上就不会出现键盘了
- 有一个针对iOS的解决方法,这样它就能真正发挥作用,因为它通常会阻止execCommand的运行。
在这里,它是:
const copyToClipboard = (function initClipboardText() {
const textarea = document.createElement('textarea');
// Move it off-screen.
textarea.style.cssText = 'position: absolute; left: -99999em';
// Set to readonly to prevent mobile devices opening a keyboard when
// text is .select()'ed.
textarea.setAttribute('readonly', true);
document.body.appendChild(textarea);
return function setClipboardText(text) {
textarea.value = text;
// Check if there is any content selected previously.
const selected = document.getSelection().rangeCount > 0 ?
document.getSelection().getRangeAt(0) : false;
// iOS Safari blocks programmatic execCommand copying normally, without this hack.
// https://stackoverflow.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
const editable = textarea.contentEditable;
textarea.contentEditable = true;
const range = document.createRange();
range.selectNodeContents(textarea);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
textarea.setSelectionRange(0, 999999);
textarea.contentEditable = editable;
}
else {
textarea.select();
}
try {
const result = document.execCommand('copy');
// Restore previous selection.
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
return result;
}
catch (err) {
console.error(err);
return false;
}
};
})();
使用方法:copyToClipboard('some text')
其他方法将复制纯文本到剪贴板。要复制HTML(即你可以将结果粘贴到所见即所得的编辑器中),你可以在Internet Explorer only中进行如下操作。这与其他方法有根本的不同,因为浏览器实际上是明显地选择内容。
// Create an editable DIV and append the HTML content you want copied
var editableDiv = document.createElement("div");
with (editableDiv) {
contentEditable = true;
}
editableDiv.appendChild(someContentElement);
// Select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();
r.execCommand("Copy");
// Deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(someHiddenDiv);
r.select();
我找到了以下的解决方案:
按键式处理程序创建了一个"pre"标签。我们设置要复制的内容到这个标签,然后在这个标签上进行选择并在处理程序中返回true。这就调用了Chrome的标准处理程序,并复制了选定的文本。
如果你需要,你可以为恢复前一个选择的函数设置超时。我在MooTools上的实现:
function EnybyClipboard() {
this.saveSelection = false;
this.callback = false;
this.pastedText = false;
this.restoreSelection = function() {
if (this.saveSelection) {
window.getSelection().removeAllRanges();
for (var i = 0; i < this.saveSelection.length; i++) {
window.getSelection().addRange(this.saveSelection[i]);
}
this.saveSelection = false;
}
};
this.copyText = function(text) {
var div = $('special_copy');
if (!div) {
div = new Element('pre', {
'id': 'special_copy',
'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
});
div.injectInside(document.body);
}
div.set('text', text);
if (document.createRange) {
var rng = document.createRange();
rng.selectNodeContents(div);
this.saveSelection = [];
var selection = window.getSelection();
for (var i = 0; i < selection.rangeCount; i++) {
this.saveSelection[i] = selection.getRangeAt(i);
}
window.getSelection().removeAllRanges();
window.getSelection().addRange(rng);
setTimeout(this.restoreSelection.bind(this), 100);
} else return alert('Copy did not work. :(');
};
this.getPastedText = function() {
if (!this.pastedText) alert('Nothing to paste. :(');
return this.pastedText;
};
this.pasteText = function(callback) {
var div = $('special_paste');
if (!div) {
div = new Element('textarea', {
'id': 'special_paste',
'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
});
div.injectInside(document.body);
div.addEvent('keyup', function() {
if (this.callback) {
this.pastedText = $('special_paste').get('value');
this.callback.call(null, this.pastedText);
this.callback = false;
this.pastedText = false;
setTimeout(this.restoreSelection.bind(this), 100);
}
}.bind(this));
}
div.set('value', '');
if (document.createRange) {
var rng = document.createRange();
rng.selectNodeContents(div);
this.saveSelection = [];
var selection = window.getSelection();
for (var i = 0; i < selection.rangeCount; i++) {
this.saveSelection[i] = selection.getRangeAt(i);
}
window.getSelection().removeAllRanges();
window.getSelection().addRange(rng);
div.focus();
this.callback = callback;
} else return alert('Failed to paste. :(');
};
}
使用方法:
enyby_clip = new EnybyClipboard(); // Init
enyby_clip.copyText('some_text'); // Place this in the Ctrl+C handler and return true;
enyby_clip.pasteText(function callback(pasted_text) {
alert(pasted_text);
}); // Place this in Ctrl+V handler and return true;
在粘贴时,它创建了一个文本区域,并以同样的方式工作。
PS:也许这个方案可以用来创建一个没有Flash的完整的跨浏览器解决方案。它可以在Firefox和Chrome中使用。
此代码在2021年5月测试过。在Chrome , IE , Edge上工作。下面的'message'参数是你要复制的字符串值。
<script type="text/javascript">
function copyToClipboard(message) {
var textArea = document.createElement("textarea");
textArea.value = message;
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
alert('Copying text command was ' + msg);
} catch (err) {
alert('Unable to copy value , error : ' + err.message);
}
document.body.removeChild(textArea);
}
</script>
这可以直接工作,使用最新的Clipboard API,以及一个用户互动:
copy.addEventListener("pointerdown", () => navigator.clipboard.writeText("Hello World!"))
<button id="copy">Copy Hello World!</button>
将HTML输入的文本复制到剪贴板上:
function myFunction() {
/* Get the text field */
var copyText = document.getElementById("myInput");
/* Select the text field */
copyText.select();
/* Copy the text inside the text field */
document.execCommand("Copy");
/* Alert the copied text */
alert("Copied the text: " + copyText.value);
}
<!-- The text field -->
<input type="text" value="Hello Friend" id="myInput">
<!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>
注意: Internet Explorer 9和更早的版本不支持document.execCommand()
方法。
最好的方法是复制文本字段内的文本。 使用navigator.clipboard.writeText。
<input type="text" value="Hello World" id="myId">
<button onclick="myFunction()" >Copy text</button>
<script>
function myFunction() {
var copyText = document.getElementById("myId");
copyText.select();
copyText.setSelectionRange(0, 99999);
navigator.clipboard.writeText(copyText.value);
}
</script>
我不愿意在这个问题上增加另一个答案,但为了帮助像我这样的菜鸟,而且因为这是谷歌的顶级结果,我将会这样做。
在2022年,要将文本复制到剪贴板,你要使用一行。
navigator.clipboard.writeText(textToCopy);
这将返回一个Promise,如果它复制了,就会被解决,如果它失败了,就会被拒绝。
一个完整的工作功能是这样的:
async function copyTextToClipboard(textToCopy) {
try {
await navigator.clipboard.writeText(textToCopy);
console.log('copied to clipboard')
} catch (error) {
console.log('failed to copy to clipboard. error=' + error);
}
}
警告!如果你在测试时打开Chrome开发工具,将会失败因为浏览器要启用剪贴板,需要你有窗口的焦点。这是为了防止随机网站在你不希望的情况下改变你的剪贴板。Dev Tools会窃取这个焦点,所以关闭Dev Tools,你的测试就会成功。
如果你想复制其他东西(图片等)到剪贴板上,请看这些文件。
https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
这在浏览器中得到了足够的支持,你可以使用它。如果你担心Firefox,可以使用权限查询来显示或隐藏该按钮,如果浏览器支持的话。https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query
我也有同样的问题,从(类似Excel的东西)建立一个自定义的网格编辑,并与Excel兼容。我不得不支持选择多个单元格,复制和粘贴。
解决方案:创建一个文本区域,在那里你将插入数据供用户复制(对于我来说,当用户选择单元格时),将焦点设置在它上面(例如,当用户按Ctrl时),并选择整个文本。
所以,当用户点击Ctrl+C时,他/她会得到复制的单元格,他/她选择。经过测试,只是将文本区域的大小调整到一个像素(我没有测试它是否会在 display:none 的情况下工作)。它在所有的浏览器上都能很好地工作,而且对用户是透明的。
粘贴--你可以这样做(取决于你的目标)--保持对文本区域的关注,并使用onpaste捕捉粘贴事件(在我的项目中,我在单元格中使用文本区域来编辑)。
我不能粘贴一个例子(商业项目),但你会明白这个道理。
这是Chase Seibert的答案的扩展,其优点是它将适用于IMAGE和TABLE元素,而不仅仅是Internet Explorer 9上的DIV。
if (document.createRange) {
// Internet Explorer 9 and modern browsers
var r = document.createRange();
r.setStartBefore(to_copy);
r.setEndAfter(to_copy);
r.selectNode(to_copy);
var sel = window.getSelection();
sel.addRange(r);
document.execCommand('Copy'); // Does nothing on Firefox
} else {
// Internet Explorer 8 and earlier. This stuff won't work
// on Internet Explorer 9.
// (unless forced into a backward compatibility mode,
// or selecting plain divs, not img or table).
var r = document.body.createTextRange();
r.moveToElementText(to_copy);
r.select()
r.execCommand('Copy');
}
我已经使用了clipboard.js。
我们可以在npm上得到它:
npm install clipboard --save
还有就是在Bower上。
bower install clipboard --save
new ClipboardJS("#btn1");
document.querySelector("#btn2").addEventListener("click", () => document.querySelector("#btn1").dataset.clipboardText = Math.random());
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
<button id="btn1" data-clipboard-text="Text to copy goes here">
Copy to clipboard
</button>
<button id="btn2">Click here to change data-clipboard-text</button>
<br /><br />
<input type="text" placeholder="Paste here to see clipboard" />
更多的用法& 例子在https://zenorocha.github.io/clipboard.js/。
我的错。这只在Internet Explorer中有效。
这里有另一种复制文本的方法:
<p>
<a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
这里是同一网站的simpleAjax/session based clipboard。
注意,会话必须启用&有效,这个方案对同一个网站也有效。我在CodeIgniter上测试了它,但我遇到了会话/Ajax问题,但this也解决了这个问题。如果你不想玩会话,可以使用数据库表。
JavaScript/jQuery
<script type="text/javascript">
$(document).ready(function() {
$("#copy_btn_id").click(function(){
$.post("<?php echo base_url();?>ajax/foo_copy/"+$(this).val(), null,
function(data){
// Copied successfully
}, "html"
);
});
$("#paste_btn_id").click(function() {
$.post("<?php echo base_url();?>ajax/foo_paste/", null,
function(data) {
$('#paste_btn_id').val(data);
}, "html"
);
});
});
</script>
HTML的内容
<input type='text' id='copy_btn_id' onclick='this.select();' value='myvalue' />
<input type='text' id='paste_btn_id' value='' />
PHP代码
<?php
class Ajax extends CI_Controller {
public function foo_copy($val){
$this->session->set_userdata(array('clipboard_val' => $val));
}
public function foo_paste(){
echo $this->session->userdata('clipboard_val');
exit();
}
}
?>