如何将文本复制到剪贴板(多浏览器)?

相关:Trello如何访问用户的剪贴板?


当前回答

以下方法适用于Chrome、Firefox、Internet Explorer和Edge以及Safari的最新版本(2016年10月发布的第10版增加了复制支持)。

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

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

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

出于安全原因,这只能从事件处理程序(如单击)调用(与打开窗口一样)。首次更新剪贴板时,Internet Explorer将显示权限对话框。Internet Explorer和Edge将在文本区域聚焦时滚动。execCommand()在某些情况下可能抛出。除非您使用文本区域,否则换行符和制表符可能会被吞入。(大多数文章似乎都建议使用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 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/

其他回答

我喜欢这个:

<input onclick="this.select();" type='text' value='copy me' />

如果用户不知道如何在操作系统中复制文本,那么他们很可能也不知道如何粘贴。因此,只需自动选择它,剩下的留给用户。

该代码于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>

我最近写了一篇关于这个问题的技术博客文章(我在Lucidhart工作,最近我们在剪贴板上做了一次彻底的修改)。

将纯文本复制到剪贴板相对简单,假设您尝试在系统复制事件期间执行此操作(用户按下Ctrl+C或使用浏览器菜单)。

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie")    != -1 ||
            navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

不在系统复制事件期间将文本放到剪贴板上要困难得多。看起来这些其他答案中的一些引用了通过Flash实现的方法,这是唯一的跨浏览器方式(据我所知)。

除此之外,还有一些基于浏览器的选项。

这是Internet Explorer中最简单的,您可以通过以下方式随时从JavaScript访问clipboardData对象:

window.clipboardData

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

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

document.execCommand('copy');

看起来Firefox有一些选项,允许用户授予某些站点访问剪贴板的权限,但我没有亲自尝试过这些选项。

这是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');
}

下面是同一网站的基于Ajax/会话的简单剪贴板。

请注意,会话必须启用且有效,并且此解决方案适用于同一站点。我在CodeIgniter上测试了它,但遇到了会话/AAjax问题,但这也解决了这个问题。如果不想玩会话,请使用数据库表。

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();
        }
    }
?>