【问题标题】:Javascript Copy To Clipboard on safari?Safari上的Javascript复制到剪贴板?
【发布时间】:2017-03-02 01:19:15
【问题描述】:

这可能是重复的问题,但我没有找到解决方案。

我正在尝试在单击按钮时复制文本。它适用于 chrome、mozilla(适用于 windows 和 mac,但不适用于 linux)。而且它不适用于 safari。

我正在使用document.execCommand("copy") 命令进行复制。

safari 支持这个命令吗?

有什么方法可以支持所有浏览器吗?

【问题讨论】:

标签: javascript jquery google-chrome firefox safari


【解决方案1】:

请检查我的解决方案。

它适用于 Safari(在 iPhone 7 和 iPad 上测试)和其他浏览器。

window.Clipboard = (function(window, document, navigator) {
    var textArea,
        copy;

    function isOS() {
        return navigator.userAgent.match(/ipad|iphone/i);
    }

    function createTextArea(text) {
        textArea = document.createElement('textArea');
        textArea.value = text;
        document.body.appendChild(textArea);
    }

    function selectText() {
        var range,
            selection;

        if (isOS()) {
            range = document.createRange();
            range.selectNodeContents(textArea);
            selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            textArea.setSelectionRange(0, 999999);
        } else {
            textArea.select();
        }
    }

    function copyToClipboard() {        
        document.execCommand('copy');
        document.body.removeChild(textArea);
    }

    copy = function(text) {
        createTextArea(text);
        selectText();
        copyToClipboard();
    };

    return {
        copy: copy
    };
})(window, document, navigator);

// How to use
Clipboard.copy('text to be copied');

https://gist.github.com/rproenca/64781c6a1329b48a455b645d361a9aa3 https://fiddle.jshell.net/k9ejqmqt/1/

希望对你有所帮助。

问候。

【讨论】:

  • 知道了!更新以添加代码。感谢您的反馈。
  • 谢谢,这很有用。我不得不稍微调整一下以满足我的要求。浏览器检测代码在 mac 上不起作用(很容易修复)。此外,在我的 iPhone 上,调用此代码时会弹出键盘。还有一种简单的方法可以解决这个问题(将焦点返回到触发副本的元素)。
  • 你能为此激活小提琴吗?
  • 提到的演示链接处于非活动状态。请问可以激活吗?
【解决方案2】:

我发现对于 safari,需要在 document.execCommand() 起作用之前选择文本。

此外,其他浏览器 (deprecated in Chrome) 不支持 addRange(),这意味着在某些情况下它没有正确地将选择和范围合并在一起。这对用户体验意味着用户需要在 Safari 中单击两次才能复制该值。在添加范围之前添加 .removeAllRanges() 将有助于确保您为副本获取正确的选择。不清楚您是否还需要第二个 .removeAllRanges() 但我保留它以确保安全。

 copy(id) {
    var configId = document.querySelector(id);
    var range = document.createRange();
    range.selectNode(configId);
    var selection = window.getSelection()
    selection.removeAllRanges();
    selection.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');
    }

    selection.removeAllRanges();
  }

使用(在同一类中):

<Button icon="copy" onClick={() => {this.copy(id)}}/>

id 可以是任何 html 选择器

这在 Chrome 和 Safari 中对我有用。

【讨论】:

  • 这是在 React.js 的上下文中吗?
  • @Brimby “使用”在 React Button 中,但复制功能是纯 JS。
  • 我认为出于这个答案的目的,您应该使用香草 js 侦听器将按钮重新格式化为纯 html,或者编写“这里它由 react.js 组件调用”,以便那些不对js不太了解或者react不会糊涂。
【解决方案3】:

因为第一个答案在 iPhone 10 Safari 上对我不起作用,所以我试图找到其他解决方案,但我发现了一个描述为 here

基本上它说的是一个非常相似的解决方案,但语法不同:

受“IE 10+、Chrome 43+、Firefox 41+ 和 Opera 29+”支持

var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
  // Select the email link anchor text  
  var emailLink = document.querySelector('.js-emaillink');
  var range = document.createRange();
  range.selectNode(emailLink);
  window.getSelection().addRange(range);

  try {
    // Now that we've selected the anchor text, execute the copy command  
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copy email command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  // Remove the selections - NOTE: Should use
  // removeRange(range) when it is supported  
  window.getSelection().removeAllRanges();
});
body {
  padding: 10px;
}
<p>Email me at <a class="js-emaillink" href="mailto:chriscoyier@gmail.com">chriscoyier@gmail.com</a></p>

<p><button class="js-emailcopybtn">Copy Email</button></p>

它还提到了一个名为 clipboardjs 的库,看起来很棒。

在我的例子中,这个简单的 js 代码可以运行:

  • iPhone 10 Safari
  • chrome (android / pc (67.0.3396.79))
  • 歌剧(PC(53.0.2907.68))

不幸的是它不起作用:

  • pc/安卓火狐(60.0.1(64位))

对于 Firefox,简单的选择和复制就可以了。

element.select();
document.execCommand('copy');

【讨论】:

    【解决方案4】:

    这个问题问了 4 年后,

    safari 添加了剪贴板 API!

    您可以在 safari 上将文本和任意数据写入和读取到剪贴板(在 iOS 中从 v13.4 和桌面 v13.1 开始)。

    MDN docs about Clipboard Clipboard 接口实现 Clipboard API,提供——如果 用户授予权限——对 系统剪贴板。 Clipboard API 可用于实现剪切, 在 Web 应用程序中复制和粘贴功能。

    这就是你可以实现你想要的:

    navigator.clipboard.writeText("YOUR_TEXT").then(function() {
    
      /* clipboard successfully set */
    
    }, function() {
    
      /* clipboard write failed */
    
    });
    

    【讨论】:

    • 我想他们终于意识到有些开发者可能需要这个功能。
    • 我现在刚刚在 ios 14.4.2 (iPhone 8) 上试用,所以它运行良好,同样根据 caniuse.comMDN 它受到 safari 14 @HoangMinh 的支持
    • 您可能会在非安全协议(HTTPS 和 localhost)上对其进行测试,或者您的剪贴板权限在 safari 设置中被阻止 @HoangMinh
    • 我在这个问题上花了一整天。基本上在我的情况下,我需要复制的值是从后端返回的,所以我在我的 observable 中触发了 clipboard.writeText 并且它不起作用。我认为出于某些原因,Apple 会限制您这样做。只要我准备好值,我就可以使用此函数进行复制,但我不能将其放入可观察对象中。它适用于其他浏览器(Chrome、Edge、Firefox),但 Safari 只是拒绝复制它
    • @HoangMinh 我遇到了和你说的一样的问题,你有没有找到解决办法?
    【解决方案5】:

    最近我偶然发现了同样的问题并发现了以下内容:

    document.execCommand("copy") 现在可以在 Safari 中正常工作。

    如果您有一个复制命令的特定用例仅在 safari 中不工作,您可能要检查的一件事是您的复制命令是否在 API 回调中或以其他类似的异步方式运行。此外,只有在来自 DOM 事件时才能在 Safari 中复制(控制台测试不起作用)。

    对我来说,我要复制的文本来自异步调用的响应。我不得不将 API 调用移到 onClick 之外以预取文本,然后仅在单击复制按钮时复制该文本。成功了!

    以下代码可以在 Safari 中正常工作(因为它直接写入到像 onClick 这样的 DOM 事件处理程序):

    var clipBoardElem = document.createElement("input");
    document.body.appendChild(clipBoardElem);
    clipBoardElem.value = "text";
    clipBoardElem.select();
    var successfulCopy = document.execCommand('copy');
    

    完成后,您可以删除临时元素:

    document.body.removeChild(clipBoardElem)
    

    【讨论】:

      【解决方案6】:

      使用copy 事件似乎对我有用。

      window.addEventListener('copy', (event) => {
        event.preventDefault();
        event.clipboardData.setData('text/plain', `foo: ${Date.now()}`);
      });
      click here, press Cmd-C, paste outside the browser

      在 Chrome 83、Safari 13.1、Firefox 77 中测试

      【讨论】:

      • 我认为这不能回答问题的“点击按钮时复制”部分。
      【解决方案7】:

      根据 CanIUse 的说法,iOS 上的 Safari 不支持 document.execCommand('copy'),可能是出于安全原因。

      【讨论】:

      • 那么对于所有浏览器,copy to clipboard 的最佳方式是什么,或者我们如何在 safari 中做到这一点?
      • 如果你不知道@Mahi clipboardjs 实际上是使用document.execCommand('copy') 实现的。查看源代码。
      • document.execCommand('copy') 确实适用于版本 10 的 safari
      • Safari 有什么替代品吗?我们有一个内部内容管理应用程序,我们在其中设置了一些用于营销的 html 模板,它们都使用 Mac 和 Safari……让他们使用 Chrome 是一场斗争。
      【解决方案8】:

      我遇到了同样的问题 - 原来我的问题是因为我创建了一个临时的 select 元素来复制文本,这很好,但我也通过各种方法隐藏它,罪魁祸首是 @ 987654322@。删除它并使用其他方法隐藏它解决了我的问题。

      希望这对遇到同样问题的人有所帮助。

      【讨论】:

        猜你喜欢
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-23
        • 1970-01-01
        • 1970-01-01
        • 2010-11-17
        相关资源
        最近更新 更多