如何使用JavaScript复制到剪贴板?


3315

将文本复制到剪贴板的最佳方法是什么?(多浏览器)

我努力了:

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

一个没有闪光灯的好技巧:Trello如何访问用户的剪贴板?


只是好奇,您想将用户无法自己复制到剪贴板的是什么?
scunliffe

233
没什么特别的。他们可以自己做,但我也想提供单击按钮的可能性,而不必担心选择正确的文本部分。
圣地亚哥·科雷多伊拉

4
这篇漫长的博客文章包含许多方法来做到这一点:使用JavaScript访问系统剪贴板–圣杯?
亚伦·迪古拉

它给IE和FF中的浏览器带来了未定义的异常
Jagadeesh 2013年

1
如果我们可以将文本放入用户的剪贴板,则可以破坏他的剪贴板。
Frank Fang

Answers:


2238

总览

有三种主要的浏览器API可复制到剪贴板:

  1. 异步剪贴板API [navigator.clipboard.writeText]
    • Chrome 66中提供了以文本为中心的部分(2018年3月)
    • 访问是异步的,并且使用JavaScript Promises,可以编写,因此安全用户提示(如果显示)不会中断页面​​中的JavaScript。
    • 文本可以直接从变量复制到剪贴板。
    • 仅在通过HTTPS服务的页面上受支持。
    • 在Chrome 66中,活动标签页中的页面可以写入剪贴板而没有权限提示。
  2. document.execCommand('copy')
    • 截至2015年4月,大多数浏览器都支持此功能(请参阅下面的浏览器支持)。
    • 访问是同步的,即在页面中停止JavaScript直到完成,包括显示和用户与任何安全提示进行交互。
    • 从DOM中读取文本并将其放置在剪贴板上。
    • 在2015年4月〜测试期间,只有Internet Explorer被记录为在写入剪贴板时显示权限提示。
  3. 覆盖复制事件
    • 请参阅剪贴板API文档中有关覆盖复制事件的信息
    • 允许您通过任何复制事件来修改剪贴板上显示的内容,可以包括除纯文本之外的其他数据格式。
    • 这里没有涉及,因为它不能直接回答问题。

一般发展说明

在控制台中测试代码时,不要期望剪贴板相关的命令能够正常工作。通常,页面需要处于活动状态(异步剪贴板API)或需要用户交互(例如,用户单击)才能允许(document.execCommand('copy'))访问剪贴板,有关更多详细信息,请参见下文。

重要事项(此处注明2020/02/20)

请注意,由于该帖子最初是在跨源IFRAME和其他IFRAME“沙盒”中弃用的,因此会阻止嵌入式演示“ Run code snippet”按钮和“ codepen.io example”在某些浏览器(包括Chrome和Microsoft Edge)中运行)。

要开发创建自己的网页,请通过HTTPS连接提供该网页以进行测试和开发。

这是一个测试/演示页面,演示了代码的工作原理:https : //deanmarktaylor.github.io/clipboard-test/

异步+后备

由于浏览器对新的Async Clipboard 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('copy')

本文的其余部分将深入介绍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和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 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 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')返回truedocument.execCommand('copy')如果立即调用将成功。检查以确保从用户启动的线程调用了该命令,并且满足其他要求。

但是由于浏览器兼容性问题,谷歌Chrome从日〜4月至〜2015年10月才会返回一个例子true,从document.queryCommandSupported('copy')如果命令是由用户发起的线程调用。

请注意下面的兼容性详细信息。

浏览器兼容性详细信息

虽然通过用户单击而简单地调用document.execCommand('copy')包装在try/ catch块中的调用将使您获得最大的兼容性,但以下使用一些条件:

到任何呼叫document.execCommanddocument.queryCommandSupporteddocument.queryCommandEnabled应该被包裹在一个try/ catch块。

当调用而不是返回时,不同的浏览器实现和浏览器版本会引发不同类型的异常false

各种浏览器实现仍在不断发展,而Clipboard API仍在起草阶段,因此请记住进行测试。


41
如何直接从可变数据.IE复制:var str = "word";
jscripter

10
@BubuDaba创建一个<textarea>用JS 隐藏的虚拟对象,将其附加到document.body,将其值设置为变量,并以的速度使用它copyTextarea,然后在复制内容后立即将其删除。
SeinopSys

3
Safari是否有任何功能或在Safari中会实现的任何指标?
www139

3
我发现唯一适用于所有浏览器的版本。我发现在Boostrap Modal中使用此功能时,必须将文本区域附加到模式中。如果可以的话,我会给+1000!谢谢!
帕特里克(Patrick)

3
@AyaSalama的重点是,除非在浏览器中用户正在执行该操作,否则“复制”操作无法进行。如果将元素设置为“ display:none”样式,则用户将无法执行操作,因为他们将无法看到该元素或与其进行交互。
迪恩·泰勒

1255

自动复制到剪贴板可能很危险,因此大多数浏览器(IE除外)都使它非常困难。我个人使用以下简单技巧:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

向用户显示提示框,其中已选择要复制的文本。现在按Ctrl+ CEnter(关闭框)就足够了-瞧!

现在,剪贴板复制操作为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>


91
聪明,但这仅支持单行。
Aram Kocharyan

61
将“提示”功能更改为自定义模式很简单,诀窍在于使用可编辑的内容字段并预先选择文本,并且不会通过强制用户采用以下方式来破坏浏览器用户界面自己行动。A ++
Jon z

110
仍然不使用JavaScript复制到剪贴板^ _ ^
RozzA 2012年

23
如果您的文字超过2000个字符,它将被截断,但对于较小的文字示例,效果很好
RasTheDestroyer

445
奇怪的是,它在没有回答问题的情况下获得457投票:使用Javascript复制到剪贴板!
stevenvh 2013年

298

以下方法适用于Chrome,Firefox,Internet Explorer和Edge,以及最新版本的Safari(复制支持已添加到2016年10月发布的版本10中)。

  • 创建一个textarea并将其内容设置为要复制到剪贴板的文本。
  • 将文本区域附加到DOM。
  • 在文本区域中选择文本。
  • 调用document.execCommand(“ copy”)
  • 从dom中删除文本区域。

注意:您不会看到文本区域,因为它是在同一Javascript代码同步调用中添加和删除的。

如果您自己执行此操作,请注意以下事项:

  • 出于安全原因,只能从事件处理程序(如click)中调用(就像打开窗口一样)。
  • 第一次更新剪贴板时,Internet Explorer将显示一个权限对话框。
  • Internet Explorer和Edge将在文本区域成为焦点时滚动。
  • execCommand()在某些情况下可能会抛出。
  • 除非使用textarea,否则换行符和制表符可能会被吞下。(大多数文章似乎建议使用div)
  • 显示Internet Explorer对话框时,该文本区域将可见,您需要将其隐藏,或使用Internet Explorer特定的剪贴板数据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 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 false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/


9
不错的答案:跨浏览器支持,错误处理+清理。从对queryCommandSupported的今天新支持开始,现在可以在Javascript中复制到剪贴板了,这应该是公认的答案,而不是笨拙的“ window.prompt(“复制到剪贴板:Ctrl + C,Enter”,文本)'解决方法。IE9支持window.clipboardData,因此您应该在浏览器支持列表中添加IE9,我想也许也是IE8和以前的版本,但需要进行验证。
user627283

是的 IE 8/9应该没问题。我们的应用程序不支持它们。所以我还没有测试。IE将于1月停止支持,因此我不太在意。希望对Safari的支持将很快实现。我相信这已经在他们的雷达上了。
Greg Lowe

4
@SantiagoCorredoira:在2016年,这应该成为公认的答案。请考虑重新分配BGT(绿色勾号)。
劳伦斯·多尔

3
@Noitidart我经过测试,它非常适合firefox 54,chrome 60和边缘浏览器,即使焦点不在html文档中,您遇到的错误也可能特定于FF 55版本
Tosin John

2
@Noitidart它在这里仍然可以完美工作,专注于开发工具并没有阻止它。顺便说一下,普通的Web应用程序用户将在开发人员工具上做什么
Tosin John

97

这是我对此的看法...

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;
}

@nikksan如何复制字符串\n
sof-03

2
@ sof-03使用textarea代替输入并添加\r\n换行符
nikksan

1
在微软边缘42.17134.1.0上Win10x64不工作
Honsa Stunna

3
我已复制了您的答案。它在chrome中有效,这就是我所需要的。
user875234 '18

这是与Firefox v68.0.2(64位)一起使用的最简单的解决方案。
艾莉亚

88

如果您想要一个非常简单的解决方案(集成时间少于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}颜色替换。


12
对于任何感兴趣的人,请在复制存储库的URL时检查在GitHub上使用的Clippy。
Radek

66
仅供参考,在GitHub上使用Clippy已被ZeroClipboard取代。
James M. Greene 2013年

218
OP希望使用JavaScript解决方案。不闪烁。
MT。

21
@MT,“ JavaScript”在某些人的意思是“在浏览器客户端中”,因此虽然可能仅需要JS,但许多有机会获得此答案的人都在寻找JS或其他广泛支持的产品-客户技术。Flash并非在所有平台上都适用,但是对于诸如剪贴板支持之类的完善功能,如果可以通过弹出对话框改进UX(确实可以做到),则值得添加。
Dave Dopson

13
到现在为止,依靠Flash意味着对于一定比例的网站访问者来说,一切都无法正常进行,这几乎是每个从事Web开发的人所无法接受的。
jinglesthula

86

从网页上读取和修改剪贴板会引发安全性和隐私问题。但是,在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" />


7
使用Flash进行简单的复制操作似乎有些矫kill过正,很高兴有一种干净的JS方式可以做到这一点。而且由于我们处于公司环境中。IE浏览器就可以了。谢谢班迪!
艾迪(Eddie)

5
请解释一下execCommand(\\’copy\\’);,如果不复制到IE剪贴板,该怎么做?@mrBorna
RozzA 2012年

20
不要使用if(!document.all)if(!r.execCommand)以免其他人实现它!Document.all绝对与此无关。
m93a 2013年

1
伙计,这就是我喜欢简单简洁的代码,几乎不需要维护就可以永远工作。这为我做到了,它工作得很漂亮。
塞缪尔·拉姆赞

1
不适用于最新的chrome,firefox或MS Edge :(
Jonathan Marzullo

69

我最近写了一篇有关此问题的技术博客文章(我在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访问剪贴板数据对象:

window.clipboardData

(但是,当您尝试在系统剪切,复制或粘贴事件之外执行此操作时,IE会提示用户授予Web应用程序剪贴板权限。)

在Chrome中,您可以创建一个Chrome扩展程序,该扩展程序将为您提供剪贴板权限(这是我们对Lucidchart所做的工作)。然后,对于安装了扩展程序的用户,您只需要自己触发系统事件即可:

document.execCommand('copy');

Firefox似乎有一些选项,允许用户向某些站点授予访问剪贴板的权限,但是我个人没有尝试过这些选项。


2
博客文章中没有提到(我希望在不久的将来进行更新),它具有使用execCommand触发剪切和复制的功能。IE10 +,Chrome 43+和Opera29 +支持此功能。在这里阅读。updates.html5rocks.com/2015/04/cut-and-copy-commands
理查德·舒尔茨

这样做的问题是,它劫持了其他普通复制事件。
布罗克·亚当斯

注意!该浏览器嗅探为“不良”。做功能嗅探。您正在使IE难以更新。
奥迪尼奥-费尔蒙'18

51

剪贴板.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上

注意:现在不建议使用。迁移到这里


angular.io使用此库来进行“英雄之旅”,并以优美的模式回退以供不支持execCommand的浏览器通过显示用户刚刚要复制的预选文本来使用。
约翰·菲利普

1
看起来Clipboard.js
Joao

35

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


25
跨浏览器与Flash?无法在iOS和Android 4.4中使用
Raptor 2014年

1
查看最新答案。这为Flash用户提供了更少的步骤,并为其他所有人提供了后备资源。
贾斯汀

8
它有十亿行代码。这绝对是可笑的。最好不要在项目中完全包含这样的怪物
vsync 2014年

2
有一个简单的版本gist.github.com/JamesMGreene/8698897,它是20K,没有74k版本中的所有花哨功能。两者都不大。我的猜测是,大多数用户都可以接受额外的毫秒数,因为这会花费74k或20k的文件下载时间,因此复制/粘贴只需单击一次即可,而不是两次。
贾斯汀

@Justin即使我复制并粘贴示例,我也无法使其在本地工作(我做了最小的更改,例如srcscript标签中的值)。我觉得他们的文档不错,但是效率很低。
Gui Imamura

29

在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。

也可以对剪贴板进行更多的体操练习。在此处查看更多信息:

解锁剪贴板访问


您已链接到本地​​主机
Joe Warner

2
请注意,这在Safari(版本11.1.2)中
不起作用

1
@ arjun27希望有一天苹果能赶上来。尽管此caniuse.com/#feat=clipboard显示了您提到的部分支持的上述版本。
KhoPhi

2
我得到了两个功能READTEXT,在拒绝状态WRITETEXT一个承诺
白木

3
根据提供的链接,“仅通过HTTPS服务的页面仅支持navigator.clipboard”
TimH-Codidact

26

在我正在从事的项目之一中,一个使用零剪贴板库的jQuery复制到剪贴板插件。

如果您是大量jQuery用户,则它比本机“零剪贴板”插件更易于使用。


6
92kb的确不是那么大,它可以快速运行并且您可以使用它text()来代替innerHTML()
RozzA 2012年

17
@John:innerHTML跨浏览器已经有很长时间了。仅仅因为Microsoft最初提出了这个想法,它并没有使其变得不可靠或专有。现在它也终于被添加到了官方规范中(在每个主要的浏览器供应商都已经添加了对它的支持之后…… 叹气)。
James M. Greene

19
@John您抱怨jQuery在使用Flash的答案中不够
熟练

4
在大多数情况下,innerHTML优于替代方法。下车你的高马!它更快,更高效并且不需要重新渲染页面。
2013年

4
@RozzA 92KB真的很大。在LTE成熟之前,GPRSWW移动数据标准,始于1 KB/s。自己做数学。
Tino

23

由于Chrome 42+和Firefox 41+现在支持document.execCommand('copy')命令。因此,我结合了Tim Down的旧答案Google Developer的答案,为跨浏览器复制到剪贴板的功能创建了两个函数:

function selectElementContents(el) {
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) {
        // IE
        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>


感谢您总结一下!您的代码中有一些错误:您两次定义了“ range”变量(var range = document.createRange())。
Christian Engel

1
您是正确的@ChristianEngel。我删除了第二个。我不知道它是怎么到那里的。
杰夫·贝克

23

我非常成功地使用了它(没有 jQuery或任何其他框架)。

function copyToClp(txt){
    txt = document.createTextNode(txt);
    var m = document;
    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中是)。


这种方法中缺少空格
Bikram

1
铬。制表符转换为一个空格
Bikram '18

22

我发现以下解决方案:

在按下按键时,处理程序会创建“ 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 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('Fail to paste. :(');
     };
   }

用法:

enyby_clip = new EnybyClipboard(); //init 

enyby_clip.copyText('some_text'); // place this in 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;

在粘贴时,它会创建textarea并以相同的方式工作。

PS可能是此解决方案,可用于创建不带Flash的完全跨浏览器解决方案。它适用于FF和Chrome。


2
有人尝试过吗?听起来真是太漂亮了,以防万一它真的可以在多种浏览器上运行!
迈克尔,

1
jsfiddle.net/H2FHC演示:fiddle.jshell.net/H2FHC/show请打开它,然后按Ctrl + V或Ctrl + C。在FF 19.0中完美地分叉。在Chrome 25.0.1364.97 m中也是如此。Opera 12.14-好的。适用于Windows的Safari 5.1.7-确定。IE-失败。
Enyby

对于IE,需要将重点放在页面内的元素上。参见fiddle.jshell.net/H2FHC/3/showfiddle.jshell.net/H2FHC/3在IE 9/10中工作。IE 6/7需要以其他方式进行过程创建选择,因为不支持document.createRange。
Enyby

21

其他方法会将纯文本复制到剪贴板。要复制HTML(即,您可以将结果粘贴到WSIWYG编辑器中),则可以在IE 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解决方案stackoverflow.com/questions/34191780/...
kofifus

21

我把我认为最好的东西放在一起。

  • 使用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 programmtic execCommand copying normally, without this hack.
    // /programming/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')


13

从Flash 10开始,如果操作源自用户与Flash对象的交互,则只能复制到剪贴板。(阅读Adobe Flash 10公告中的相关部分

解决方案是在“复制”按钮上方放置一个Flash对象,或者使用任何可启动复制的元素。零剪贴板目前是使用此实现的最佳库。有经验的Flash开发人员可能只想创建自己的库。


12

  <!DOCTYPE html>

  <style>
    #t {
      width: 1px
      height: 1px
      border: none
    }
    #t:focus {
      outline: none
    }
  </style>

  <script>
    function copy(text) {
      var t = document.getElementById('t')
      t.innerHTML = text
      t.select()
      try {
        var successful = document.execCommand('copy')
        var msg = successful ? 'successfully' : 'unsuccessfully'
        console.log('text coppied ' + msg)
      } catch (err) {
        console.log('Unable to copy text')
      }
      t.innerHTML = ''
    }
  </script>

  <textarea id=t></textarea>

  <button onclick="copy('hello world')">
    Click me
  </button>


最好的答案:D,您可以使用以下方法来改进它:#t {position:absolute; 左:0;z索引:-900;宽度:0px;高度:0px;边界:无;}因此它将完全隐藏!但是,非常感谢兄弟!
Federico Navarrete

#t {resize:none;}
SmartManoj

一个解释将是有条理的。
彼得·莫滕森

12

我发现以下解决方案:

我在隐藏输入中输入了文字。由于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;
}

11

将文本从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- 将文本复制到剪贴板


11

已经有很多答案,但是喜欢添加一个(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.');
}

9

这是其他答案之间的组合。

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以确保输入不显示。例如:

.textToCopyInput{opacity: 0; position: absolute;}

或者当然,您也可以做一些内联样式

.append($('<textarea name="fname" style="opacity: 0;  position: absolute;" class="textToCopyInput"/>' )

如何直接从变量数据复制。即:var str =“ word”; ?

可变消息未使用
旅行者

更好地利用'<TextArea类= “textToCopyInput”/> </ textarea的>'的情况下,textToCopy包含\n
旅行者


8

我在从中构建自定义网格编辑(类似Excel)以及与Excel兼容时遇到了相同的问题。我必须支持选择多个单元格,复制和粘贴。

解决方案:创建一个文本区域,您将在其中插入供用户复制的数据(当用户选择单元格时对我来说),将焦点放在该文本区域上(例如,当用户按下 Ctrl文本区域),然后选择整个文本。

因此,当用户点击Ctrl+时,C他/她将获得他/她选择的复制单元格。经过测试后,只是将textarea调整为一个像素(我没有测试它是否可以在display上工作:无)。它在所有浏览器上都能很好地工作,并且对用户透明。

粘贴-您可以这样做(与目标不同)-继续关注文本区域并使用onpaste捕获粘贴事件(在我的项目中,我在单元格中使用文本区域进行编辑)。

我无法粘贴示例(商业项目),但是您明白了。



6

这是@Chase答案的扩展,其优点是它将适用于IMAGE和TABLE元素,而不仅仅是IE9上的DIV。

if (document.createRange) {
    // IE9 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 FF
} else {
    // IE 8 and earlier.  This stuff won't work on IE9.
    // (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');
}

5

看来我误解了这个问题,但是作为参考,您可以提取一定范围的DOM(不兼容剪贴板;与所有现代浏览器兼容),并将其与oncopy和onpaste和onbeforepaste事件结合使用以获得剪贴板行为。这是实现此目的的代码:

function clipBoard(sCommand) {
  var oRange=contentDocument.createRange();
  oRange.setStart(startNode, startOffset);
  oRange.setEnd(endNode, endOffset);
/* This is where the actual selection happens.
in the above, startNode and endNode are dom nodes defining the beginning 
and end of the "selection" respectively. startOffset and endOffset are 
constants that are defined as follows:

END_TO_END: 2
END_TO_START: 3
NODE_AFTER: 1
NODE_BEFORE: 0
NODE_BEFORE_AND_AFTER: 2
NODE_INSIDE: 3
START_TO_END: 1
START_TO_START: 0

and would be used like oRange.START_TO_END */
      switch(sCommand) {
    case "cut":
          this.oFragment=oRange.extractContents();
      oRange.collapse();
      break;
    case "copy":
      this.oFragment=oRange.cloneContents();
      break;
    case "paste":
      oRange.deleteContents();
      var cloneFragment=this.oFragment.cloneNode(true)
      oRange.insertNode(cloneFragment);
      oRange.collapse();
      break;
  }
}

1
实际上我更正了代码。它适用于所有浏览器,但实际上不会复制到剪贴板。只需通过变量提取(剪切),克隆(复制)内容即可。看来我已经忘记了用法。
mrBorna

5

我的错。这仅在IE中有效。

这是复制文本的另一种方法:

<p>
    <a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>

9
在当前的Chrome(V31)或FireFox(v25)中不起作用。错误是window.clipboardData未定义。从好的方面来说,它可以在IE9中使用。因此,只要您不关心优质的浏览器,并且希望将您的网站锁定为使用不良的浏览器,这就是您这样做的方式!
安东尼

2
我不明白为什么这么多愚蠢的答案。w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard
Martian2049 '18年

5

在遍历Internet的各种方式之后,这是我唯一要做的事情。这是一个混乱的话题。有很多世界各地发布的解决方案,并且他们中的大多数没有工作。这为我工作:

注意:此代码仅在作为直接同步代码执行到诸如“ onClick”方法之类的东西时才起作用。如果您以异步响应方式调用Ajax或以任何其他异步方式调用,它将不起作用。

copyToClipboard(text) {
    var copyText = document.createElement("input");
    copyText.type = "text";
    document.body.appendChild(copyText);
    copyText.style = "display: inline; width: 1px;";
    copyText.value = text;
    copyText.focus();
    document.execCommand("SelectAll");
    document.execCommand("Copy");
    copyText.remove();
}

我确实意识到这段代码将在屏幕上显示毫秒级的1像素宽的组件,但决定不担心这一点,如果真正的问题,其他人可以解决。


5

要将选定的文本(“要复制的文本”)复制到剪贴板,请创建一个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');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.