如何在 JavaScript 中复制到剪贴板?
Posted
技术标签:
【中文标题】如何在 JavaScript 中复制到剪贴板?【英文标题】:How do I copy to the clipboard in JavaScript? 【发布时间】:2010-09-28 20:24:49 【问题描述】:将文本复制到剪贴板(多浏览器)的最佳方式是什么?
我试过了:
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 的好技巧:How does Trello access the user's clipboard?
【问题讨论】:
只是好奇,你想复制到剪贴板而用户不能自己做的事情是什么? 没什么特别的。他们可以自己做,但我还想提供点击按钮的可能性,而不必担心选择正确的文本部分。 这篇长篇博文包含很多方法:Accessing the System Clipboard with javascript – A Holy Grail? 它在 IE 和 FF 中给浏览器未定义的异常 如果我们可以将文本放入用户的剪贴板,我们就可以毁掉他的剪贴板。 【参考方案1】:概述
有三个主要的浏览器 API 用于复制到剪贴板:
Async Clipboard API[navigator.clipboard.writeText]
document.execCommand('copy')
(deprecated) ?
覆盖复制事件
请参阅 Overriding the copy event 上的剪贴板 API 文档。 允许您修改任何复制事件中显示在剪贴板上的内容,可以包括纯文本以外的其他格式的数据。 此处未涉及,因为它不能直接回答问题。一般开发说明
当您在控制台中测试代码时,不要期望剪贴板相关的命令能够正常工作。通常,页面需要处于活动状态(异步剪贴板 API)或需要用户交互(例如用户单击)以允许 (document.execCommand('copy')
) 访问剪贴板,详情请参见下文。
重要提示(此处注明 2020/02/20)
请注意,由于这篇文章最初是由deprecation of permissions in cross-origin IFRAMEs 和其他IFRAME "sandboxing" 编写的,因此会阻止嵌入式演示“运行代码 sn-p”按钮和“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 示例可能不起作用,请阅读上面的“重要”说明) 请注意,此 sn-p 在 Stack Overflow 的嵌入式预览中效果不佳,您可以在此处尝试:https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
异步剪贴板 API
MDN Reference Chrome 66 announcement post (March 2018) 参考Async Clipboard 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('copy')
本文的其余部分将探讨 document.execCommand('copy')
API 的细微差别和细节。
浏览器支持
JavaScript (deprecated) ?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 和 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 Developers post here 了解更多信息。
剪贴板 API
请注意,可在此处找到完整的剪贴板 API 草案规范: https://w3c.github.io/clipboard-apis/
是否支持?
如果“浏览器支持”命令,document.queryCommandSupported('copy')
应该返回 true
。
和 document.queryCommandEnabled('copy')
如果现在调用 document.execCommand('copy')
将成功,则返回 true
。检查以确保命令是从用户启动的线程调用的,并且满足其他要求。
但是,作为浏览器兼容性问题的一个示例,Google Chrome 从 2015 年 4 月到 10 月仅在从用户启动的线程调用命令时才从 document.queryCommandSupported('copy')
返回 true
。
请注意下面的兼容性详细信息。
浏览器兼容性详情
虽然对 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 当然,但替代品(剪贴板 API)尚未完全烘焙和支持。
目前全球 91% 的用户都支持剪贴板 API:caniuse.com/mdn-api_clipboard_writetext
样式注意事项:我只使用opacity: 0
来隐藏<textarea>
。还有z-index:-1
,如果你想完全安全的话。所以我们实际上只需要定义三个样式属性:position: fixed
和前面提到的两个。
我只是在回退后添加了焦点的重置:var previousFocusElement = document.activeElement (....all the fallback code...) previousFocusElement.focus();
【参考方案2】:
自动复制到剪贴板可能很危险,因此大多数浏览器(Internet Explorer 除外)都很难做到。就个人而言,我使用以下简单技巧:
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>
【讨论】:
但是该对话框中显示的字符数量有限制,因此要复制的数据量也有限制。 聪明,但这只支持单行。 将“提示”功能更改为自定义模式很简单,关键在于使用可编辑的内容字段并预先选择文本,并且不会破坏浏览器UI 通过强制用户自己执行操作。一个++ 如果您的文本超过 2000 个字符,它将被截断,但对于较小的文本样本,它效果很好 @RasTheDestroyer - 在 2k 字符处截断似乎是 Chrome 的问题,但无论如何都很高兴知道【参考方案3】:以下方法适用于 Chrome、Firefox、Internet Explorer 和 Edge,以及最新版本的 Safari(2016 年 10 月发布的版本 10 中添加了复制支持)。
创建一个 textarea 并将其内容设置为您要复制到剪贴板的文本。 将文本区域附加到 DOM。 选择文本区域中的文本。 调用 document.execCommand("copy") 从 dom 中删除 textarea。注意:您不会看到 textarea,因为它是在 Javascript 代码的同一个同步调用中添加和删除的。
如果您自己实现此功能需要注意一些事项:
出于安全原因,这只能从事件处理程序中调用,例如 click(就像打开窗口一样)。 第一次更新剪贴板时,Internet Explorer 将显示一个权限对话框。 Internet Explorer 和 Edge 将在 textarea 获得焦点时滚动。 execCommand() 在某些情况下可能会抛出异常。 除非您使用 textarea,否则换行符和制表符可能会被吞掉。 (大多数文章似乎都建议使用 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);
https://jsfiddle.net/fx6a6n6x/
【讨论】:
不错的答案:跨浏览器支持,错误处理 + 清理。从今天对 queryCommandSupported 的新支持开始,复制到剪贴板现在在 Javascript 中是可行的,这应该是公认的答案,而不是笨拙的 'window.prompt("Copy to clipboard: Ctrl+C, Enter", text)' 解决方法。 IE9支持window.clipboardData,所以你应该在浏览器支持列表中添加IE9,我认为IE8及之前的版本也可能,但需要验证。 @SantiagoCorredoira:在 2016 年,这应该是公认的答案。请考虑重新分配 BGT(绿色大勾号)。 @Noitidart 我测试过,它适用于 firefox 54、chrome 60 和 edge 浏览器,即使焦点不在 html 文档中,您遇到的错误也可能特定于版本 FF 55 @Noitidart 它在这里仍然可以完美运行,专注于开发工具并没有阻止它。顺便说一句,普通的网络应用用户会在开发者工具上做什么 jQuery UI 用户:请注意,如果您尝试在模式对话框中使用此功能,则会遇到此方法的问题。我怀疑这是因为 jQuery UI 模式正在管理/操作文档焦点。如果它适合您的用例,一种解决方法是先关闭模式对话框,然后复制文本。或者,简单地使用非模态对话框。我怀疑您也可以修改此函数,以便将文本区域添加到模态而不是正文。【参考方案4】:这是我对那个的看法......
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 在 cmets 中提到的,使用 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;
【讨论】:
@sof-03 使用 textarea 代替 input 并添加\r\n
换行
在 Win10x64 上的 Microsoft Edge 42.17134.1.0 中不工作
我已经复制了你的答案。它适用于 chrome,这就是我所需要的。
这是最简单的解决方案,适用于 Firefox v68.0.2(64 位)。
出于某种原因,我通常的“创建一个隐藏的输入或文本区域,然后选择它并执行命令”不起作用,这是迄今为止列出的最佳解决方案,尽管其他解决方案很全面并且喜欢完整的***页面,这个对我来说效果很好,所以 +1【参考方案5】:
从网页读取和修改剪贴板会引发安全和隐私问题。但是,在 Internet Explorer 中,可以做到这一点。我找到了这个example snippet:
<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" />
【讨论】:
使用 flash 进行简单的复制操作似乎有点矫枉过正,很高兴有一种干净的 JS 方法可以做到这一点。而且由于我们处于企业环境中。 IE很好。谢谢班迪! 请解释execCommand(\\’copy\\’);
的作用,如果不复制到 IE 的剪贴板? @mrBorna
不要使用if(!document.all)
但if(!r.execCommand)
以免其他人实现它! Document.all 与此完全无关。
当人们使用 Flash 更改剪贴板时,为什么这些隐私问题十年来从未提出过?如果我们只允许一种方式(即复制,而不是阅读其内容),这会如何产生隐私问题?
@MuhammadbinYusrat:虽然不是隐私问题,但它是用户体验问题。假设用户复制了一些东西,并认为他知道剪贴板上的内容,然后浏览您的网站,突然剪贴板中包含他不需要的东西,他丢失了他最初复制的内容。【参考方案6】:
如果您想要一个非常简单的解决方案(集成时间不到 5 分钟)并且开箱即用看起来不错,那么Clippy 是一些更复杂解决方案的不错替代方案。
它是由 GitHub 的联合创始人编写的。示例 Flash 嵌入代码如下:
<object
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
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"
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
替换为颜色。
【讨论】:
对于任何感兴趣的人,请在复制 repo 的 URL 时检查在 GitHub 上使用的 Clippy。【参考方案7】:我最近就这个问题写了technical blog post(我在 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 扩展程序,该扩展程序将为您提供clipboard permissions(这就是我们为 Lucidchart 所做的)。然后对于安装了您的扩展程序的用户,您只需要自己触发系统事件:
document.execCommand('copy');
看起来 Firefox 有 some options 允许用户授予某些网站访问剪贴板的权限,但我个人没有尝试过这些。
【讨论】:
博文中没有提到(我希望在不久的将来更新它),是使用 execCommand 触发剪切和复制的能力。这在 IE10+、Chrome 43+ 和 Opera29+ 中受支持。在这里阅读它。 updates.html5rocks.com/2015/04/cut-and-copy-commands 这样做的一个问题是它劫持了其他正常的复制事件。 注意!这种浏览器嗅探很糟糕。做特征嗅探。你让 IE 很难更新。【参考方案8】:我喜欢这个:
<input onclick="this.select();" type='text' value='copy me' />
如果用户不知道如何在其操作系统中复制文本,那么他们很可能也不知道如何粘贴。因此,只需自动选择它,其余的留给用户。
【讨论】:
我也喜欢它,因为它很短。也可以复制:<input onclick="this.select(); document.execCommand('copy');" type='text' value='copy me' />
【参考方案9】:
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。
注意:现在已弃用。迁移到here。
【讨论】:
这个库被 angular.io 用于其英雄之旅,并通过显示用户只需复制的预选文本以优雅模式回退不支持 execCommand 的浏览器。 看起来clipboard.js 已被替换或分叉,但它似乎仍然存在并在npmjs.com/package/clipboard 积极维护【参考方案10】:在 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。
也可以对剪贴板内容进行更多操作。在此处查看更多信息:
Unblocking Clipboard Access
【讨论】:
你已经链接到本地主机 请注意,这在 Safari(版本 11.1.2)中不起作用 @arjun27 希望有一天苹果能赶上。虽然这个caniuse.com/#feat=clipboard 显示了你提到的部分支持的上述版本。 我得到两个函数 readText, writeText 一个 Promise 处于拒绝状态 根据提供的链接,“navigator.clipboard 仅支持通过 HTTPS 提供的页面”【参考方案11】:我使用它非常成功(没有 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 中)。
【讨论】:
无法在 firefox 上运行,我收到一条错误消息,提示缺少用户激活 @Luke_ Firefox 对吗?您是否在没有用户直接点击的情况下调用它?【参考方案12】: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
【讨论】:
使用 Flash 跨浏览器?不适用于 iOS 和 android 4.4 查看更新的答案。这允许 Flash 用户的步骤更少,并为其他所有人提供后备。 它有十亿行代码。这绝对是嘲笑。最好不要在项目中包含这样的怪物 有一个简单的版本gist.github.com/JamesMGreene/8698897 是 20K,它没有 74k 版本中的所有花里胡哨。两者都不是很大。我的猜测是大多数用户都可以接受下载 74k 或 20k 文件所花费的额外毫秒数,因此复制/粘贴只需单击一次而不是两次。 @Justin 我无法让它在本地工作,即使我复制和粘贴示例(我做了最小的更改,例如脚本标签中src
的值)。我觉得他们的文档很漂亮但效率低下。【参考方案13】:
由于 Chrome 42+ 和 Firefox 41+ 现在支持 document.execCommand('copy') 命令,我使用Tim Down's old answer 和 Google Developer's answer 的组合:
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>
【讨论】:
感谢您的总结!您的代码中有一些错误:您定义了两次“范围”变量(var range = document.createRange())。 你是对的@ChristianEngel。我已经删除了第二个。我不知道它是怎么进来的。 您好,杰夫,如果我想自定义“复制到剪贴板”怎么办。请帮忙!【参考方案14】: $("td").click(function (e)
var clickedCell = $(e.target).closest("td");
navigator.clipboard.writeText(clickedCell.text());
alert(clickedCell.text());
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>First<td>
</tr>
<tr>
<td>Second<td>
</tr>
<tr>
<td>Third<td>
</tr>
<tr>
<td>Fourth<td>
</tr>
</table>
我已阅读所有答案,截至 2020 年 6 月 1 日,当我终于找到文档时,我一直在努力解决这个问题:
$("td").click(function (e)
var clickedCell = $(e.target).closest("td");
navigator.clipboard.writeText(clickedCell.text());
);
它将点击的单元格文本写入浏览器剪贴板。
您可以根据需要更改选择器“td”,您可以添加 console.log 以进行调试和/或警报功能。
这是文档: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
【讨论】:
不兼容 IE【参考方案15】:来自我一直从事的一个项目,一个利用 ZeroClipboard 库的 jQuery 复制到剪贴板插件。
如果你是一个重度 jQuery 用户,它比原生零剪贴板插件更容易使用。
【讨论】:
92kb 并没有那么大,它运行得很快,如果你愿意,你可以使用text()
而不是innerHTML()
..
@John: innerHTML
已经支持跨浏览器很长时间了。仅仅因为微软最初提出了这个想法,它并没有使它不可靠或专有。它现在也终于被添加到官方规范中(在每个主要浏览器供应商都已经添加了对它的支持之后......sigh)。
@John 你抱怨 jQuery 在使用 Flash 的答案中不够 JavaScript ;)
innerHTML 在大多数情况下都比替代品好。下马!它更快、更高效,并且不需要重新渲染页面。
@RozzA 92KB
真的很大。直到LTE 成熟GPRS 是WW mobile data standard,它从1 KB/s
开始。自己算算。【参考方案16】:
我把我认为最好的放在一起。
使用 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://***.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')
【讨论】:
【参考方案17】:我找到了以下解决方案:
on-key-down 处理程序创建一个“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。
【讨论】:
有人试过吗?听起来很不错,以防它真的适用于一系列浏览器! jsfiddle.net/H2FHC 演示:fiddle.jshell.net/H2FHC/show 请打开它并按 Ctrl+V 或 Ctrl+C。在 FF 19.0 中完美分叉。在 Chrome 25.0.1364.97 m 中也是如此。歌剧 12.14 - 好的。适用于 Windows 的 Safari 5.1.7 - 好的。 IE - 失败。 对于 IE 需要在页面内的元素上运行焦点。请参阅 fiddle.jshell.net/H2FHC/3/show 和 fiddle.jshell.net/H2FHC/3 在 IE 9/10 中工作。 IE 6/7 需要以其他方式创建选择,因为不支持 document.createRange。【参考方案18】:其他方法会将纯文本复制到剪贴板。要复制 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();
【讨论】:
在这里查看更完整的 HTML 解决方案***.com/questions/34191780/…【参考方案19】:此代码已于 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>
【讨论】:
【参考方案20】:从 Flash 10 开始,如果操作源自用户与 Flash 对象的交互,则只能复制到剪贴板。 (Read the related section from Adobe's Flash 10 announcement.)
解决方案是在复制按钮或启动复制的任何元素上方覆盖 Flash 对象。 ZeroClipboard 是目前具有此实现的最佳库。经验丰富的 Flash 开发人员可能只想制作自己的库。
【讨论】:
【参考方案21】:我找到了以下解决方案:
我在隐藏的输入中有文本。因为setSelectionRange
不适用于隐藏输入,所以我暂时将类型更改为文本,复制文本,然后再次将其隐藏。如果要从元素中复制文本,可以将其传递给函数并将其内容保存在目标变量中。
jQuery('#copy').on('click', function ()
copyToClipboard();
);
function copyToClipboard()
var target = jQuery('#hidden_text');
// Make it visible, so can be focused
target.attr('type', 'text');
target.focus();
// Select all the text
target[0].setSelectionRange(0, target.val().length);
// Copy the selection
var succeed;
try
succeed = document.execCommand("copy");
catch (e)
succeed = false;
// Hide input again
target.attr('type', 'hidden');
return succeed;
【讨论】:
【参考方案22】:已经有很多答案了,但是想添加一个(jQuery)。适用于任何浏览器,也适用于移动浏览器(即,关于安全性的提示,但当您接受它时,它就可以正常工作)。
function appCopyToClipBoard(sText)
var oText = false,
bResult = false;
try
oText = document.createElement("textarea");
$(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
oText.select();
document.execCommand("Copy");
bResult = true;
catch(e)
$(oText).remove();
return bResult;
在您的代码中:
if (!appCopyToClipBoard('Hai there! This is copied to the clipboard.'))
alert('Sorry, copy to clipboard failed.');
【讨论】:
【参考方案23】:将文本从 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()
方法。
来源:W3Schools - Copy Text to Clipboard
【讨论】:
【参考方案24】:从(类似于 Excel)构建自定义网格编辑以及与 Excel 的兼容性时,我遇到了同样的问题。我必须支持选择多个单元格、复制和粘贴。
解决方案:创建一个文本区域,您将在其中插入数据以供用户复制(对我来说,当用户选择单元格时),将焦点设置在它上面(例如,当用户按下 Ctrl 时)并选择整个文本。
所以,当用户点击 Ctrl + C 时,他/她会得到他/她选择的复制单元格。测试后,只需将 textarea 的大小调整为一个像素(我没有测试它是否可以在 display:none 上工作)。它适用于所有浏览器,并且对用户透明。
粘贴 - 您可以这样做(因目标而异) - 将注意力集中在 textarea 上并使用 onpaste 捕获粘贴事件(在我的项目中,我使用单元格中的 textareas 进行编辑)。
我无法粘贴示例(商业项目),但你明白了。
【讨论】:
【参考方案25】:这是其他答案之间的一点组合。
var copyToClipboard = function(textToCopy)
$("body")
.append($('<textarea name="fname" class="textToCopyInput"/>' )
.val(textToCopy))
.find(".textToCopyInput")
.select();
try
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
alert('Text copied to clipboard!');
catch (err)
window.prompt("To copy the text to clipboard: Ctrl+C, Enter", textToCopy);
$(".textToCopyInput").remove();
它使用 jQuery,但它当然不是必须的。如果你愿意,你可以改变它。我只是有 jQuery 供我使用。您还可以添加一些 CSS 以确保不显示输入。例如:
.textToCopyInputopacity: 0; position: absolute;
当然你也可以做一些内联样式
.append($('<textarea name="fname" style="opacity: 0; position: absolute;" class="textToCopyInput"/>' )
【讨论】:
如何直接从变量数据中复制。即:var str = "word"; ? 变量 msg 未使用 最好使用 '' 以防textToCopy
包含 \n
【参考方案26】:
在 Internet Explorer 以外的浏览器中,您需要使用一个小的 Flash 对象来操作剪贴板,例如
Auto copy to clipboard【讨论】:
这已经过时了...查看 GvS 的建议 GvS的建议是用flash电影?这不是同一个想法吗?【参考方案27】:function copytoclipboard(element)
var $temp = $("<input>");
$("body").append($temp);
$temp.val('0' + element).select();
document.execCommand("copy");
$temp.remove();
【讨论】:
谢谢你,你是救命稻草【参考方案28】:我用过 clipboard.js。
我们可以在 npm 上得到它:
npm install clipboard --save
还有Bower
bower install clipboard --save
用法和示例位于https://zenorocha.github.io/clipboard.js/。
【讨论】:
我担心它与动态内容不兼容,但它是 ;-) 我认为它是比 2008 年的旧解决方案更好的解决方案。 他们说:"While Bower is maintained, we recommend using Yarn and Webpack or Parcel for front-end projects"【参考方案29】:要将选定的文本(“要复制的文本”)复制到剪贴板,请创建一个 Bookmarklet(执行 JavaScript 的浏览器书签)并执行它(单击它)。它将创建一个临时文本区域。
来自 GitHub 的代码:
https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d
(function (text)
var node = document.createElement('textarea');
var selection = document.getSelection();
node.textContent = text;
document.body.appendChild(node);
selection.removeAllRanges();
node.select();
document.execCommand('copy');
selection.removeAllRanges();
document.body.removeChild(node);
)('Text To Copy');
【讨论】:
【参考方案30】:这是 Chase Seibert's answer 的扩展,其优点是它适用于 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');
【讨论】:
以上是关于如何在 JavaScript 中复制到剪贴板?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用javascript从多个div中仅复制一个DIV到剪贴板
使用 Javascript 选择一个完整的表(要复制到剪贴板)