在 iOS 中使用 Javascript 复制到剪贴板 [英] Copy to clipboard using Javascript in iOS

查看:26
本文介绍了在 iOS 中使用 Javascript 复制到剪贴板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用此功能将 URL 复制到剪贴板:

I'm using this function to copy a URL to the clipboard:

function CopyUrl($this){

  var querySelector = $this.next().attr("id");
  var emailLink = document.querySelector("#"+querySelector);

  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', false, null);
    var msg = successful ? 'successful' : 'unsuccessful'; 

    if(true){
        $this.addClass("copied").html("Copied");
    }

  } catch(err) {  
    console.log('Oops, unable to copy');  
  }  

  // Remove the selections - NOTE: Should use   
  // removeRange(range) when it is supported  
  window.getSelection().removeAllRanges();
}

在桌面浏览器上一切正常,但在 iOS 设备上却不行,我的函数成功返回,但数据根本没有复制到剪贴板.这是什么原因造成的,我该如何解决这个问题?

Everything works fine on desktop browsers, but not on iOS devices, where my function returns successfully, but the data isn't copied to the clipboard at all. What's causing this and how could I solve this problem?

推荐答案

更新!iOS >= 10

看起来在选择范围和一些小技巧的帮助下,可以直接复制到 iOS (>= 10) Safari 上的剪贴板.我亲自在 iPhone 5C iOS 10.3.3 和 iPhone 8 iOS 11.1 上进行了测试.但是,似乎有一些限制,它们是:

Update! iOS >= 10

Looks like with the help of selection ranges and some little hack it is possible to directly copy to the clipboard on iOS (>= 10) Safari. I personally tested this on iPhone 5C iOS 10.3.3 and iPhone 8 iOS 11.1. However, there seem to be some restrictions, which are:

  1. 文本只能从 <input><textarea> 元素复制.
  2. 如果保存文本的元素不是<form>中,那么它必须是contenteditable.
  3. 包含文本的元素必须readonly(尽管您可以尝试,但这不是任何地方记录的官方"方法).
  4. 元素内的文本必须在选择范围内.
  1. Text can only be copied from <input> and <textarea> elements.
  2. If the element holding the text is not inside a <form>, then it must be contenteditable.
  3. The element holding the text must not be readonly (though you may try, this is not an "official" method documented anywhere).
  4. The text inside the element must be in selection range.

要满足所有这四个要求",您必须:

To cover all four of these "requirements", you will have to:

  1. 将要复制的文本放在 <input><textarea> 元素中.
  2. 保存元素的 contenteditablereadonly 的旧值,以便在复制后能够恢复它们.
  3. contenteditable 更改为 true 并将 readonly 更改为 false.
  4. 创建一个 range 以选择所需的元素并添加将其添加到窗口的选择中.
  5. 为整个元素设置选择范围.
  6. 恢复之前的 contenteditablereadonly 值.
  7. 运行execCommand('copy').
  1. Put the text to be copied inside an <input> or <textarea> element.
  2. Save the old values of contenteditable and readonly of the element to be able to restore them after copying.
  3. Change contenteditable to true and readonly to false.
  4. Create a range to select the desired element and add it to the window's selection.
  5. Set the selection range for the entire element.
  6. Restore the previous contenteditable and readonly values.
  7. Run execCommand('copy').

这将导致用户设备的插入符号移动并选择所需元素中的所有文本,然后自动发出复制命令.用户将看到被选中的文本,并显示带有选项选择/复制/粘贴的工具提示.

This will cause the caret of the user's device to move and select all the text in the element you want, and then automatically issue the copy command. The user will see the text being selected and the tool-tip with the options select/copy/paste will be shown.

现在,这看起来有点复杂,而且仅仅发出一个复制命令太麻烦了,所以我不确定这是 Apple 的预期设计选择,但谁知道......同时,这目前适用于 iOS >= 10.

Now, this looks a little bit complicated and too much of an hassle to just issue a copy command, so I'm not sure this was an intended design choice by Apple, but who knows... in the mean time, this currently works on iOS >= 10.

话虽如此,this one 之类的 polyfill 可用于简化此操作并使其实现跨浏览器兼容(感谢 @Toskan 提供评论中的链接).

With this said, polyfills like this one could be used to simplify this action and make it cross-browser compatible (thanks @Toskan for the link in the comments).

工作示例

总而言之,您需要的代码如下所示:

To summarize, the code you'll need looks like this:

function iosCopyToClipboard(el) {
    var oldContentEditable = el.contentEditable,
        oldReadOnly = el.readOnly,
        range = document.createRange();

    el.contentEditable = true;
    el.readOnly = false;
    range.selectNodeContents(el);

    var s = window.getSelection();
    s.removeAllRanges();
    s.addRange(range);

    el.setSelectionRange(0, 999999); // A big number, to cover anything that could be inside the element.

    el.contentEditable = oldContentEditable;
    el.readOnly = oldReadOnly;

    document.execCommand('copy');
}

请注意,此函数的 el 参数必须是 <input><textarea>.

Note that the el parameter to this function must be an <input> or a <textarea>.

iOS 上

10 Safari 对 Clipboard API 有一些限制(实际上是安全措施):

On iOS < 10 there are some restrictions for Safari (which actually are security measures) to the Clipboard API:

  • 它仅在有效选择时触发 copy 事件,并且仅在聚焦的可编辑字段中触发 cutpaste.
  • 它只支持通过快捷键读取/写入操作系统剪贴板,不支持通过document.execCommand().注意快捷键"是指一些可点击的(例如复制/粘贴操作菜单或自定义 iOS 键盘快捷键)或物理键(例如连接的蓝牙键盘).
  • 它不支持 ClipboardEvent 构造函数.
  • It fires copy events only on a valid selection and cut and paste only in focused editable fields.
  • It only supports OS clipboard reading/writing via shortcut keys, not through document.execCommand(). Note that "shorcut key" means some clickable (e.g. copy/paste action menu or custom iOS keyboard shortcut) or physical key (e.g. connected bluetooth keyboard).
  • It doesn't support the ClipboardEvent constructor.

因此(至少到目前为止)无法使用 Javascript 以编程方式在 iOS 设备上的剪贴板中复制某些文本/值.只有用户可以决定是否复制某些内容.

So (at least as of now) it's not possible to programmatically copy some text/value in the clipboard on an iOS device using Javascript. Only the user can decide whether to copy something.

但是可以通过编程方式选择某些内容,因此用户只需点击所选内容上显示的复制"工具提示.这可以使用与上面完全相同的代码来实现,只是删除 execCommand('copy'),这确实不起作用.

It is however possible to select something programmatically, so that the user only has to hit the "Copy" tool-tip shown on the selection. This can be achieved with the exact same code as above, just removing the execCommand('copy'), which is indeed not going to work.

这篇关于在 iOS 中使用 Javascript 复制到剪贴板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆