一尘不染

在iOS中使用Javascript复制到剪贴板

javascript

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

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设备上无法正常运行,在iOS设备上我的函数成功返回,但是数据根本没有复制到剪贴板。是什么原因造成的,我该如何解决这个问题?


阅读 312

收藏
2020-05-01

共1个答案

一尘不染

更新!iOS> = 10

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

  1. 只能从<input><textarea>元素复制文本。
  2. 如果包含文本的元素 在内<form>,那么它必须在内contenteditable
  3. 拿着文本的元素一定 不能readonly(虽然你可能会尝试,这不是一个“官方”方法记载任何地方)。
  4. 元素内的文本必须在选择范围内。

要满足所有这四个“要求”,您将必须:

  1. 将要复制的文本放在<input><textarea>元素内。
  2. 保存元素的contenteditable和的旧值,readonly以便能够在复制后还原它们。
  3. 更改contenteditabletruereadonlyfalse
  4. 创建一个范围以选择所需的元素,并将其添加到窗口的选择中。
  5. 设置整个元素的选择范围。
  6. 恢复先前的contenteditablereadonly值。
  7. 运行execCommand('copy')

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

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

工作实例

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

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>

旧答案:以前的iOS版本

iOS
<10
上,剪贴板API对Safari有一些限制(实际上是安全措施):

  • copy仅在有效选择上cut并且paste仅在集中的可编辑字段中触发事件。
  • 它仅支持通过快捷键(而不是通过)进行OS剪贴板的读写document.execCommand()请注意,“快捷键”是指一些可单击的键(例如,复制/粘贴操作菜单或自定义iOS键盘快捷键)或物理键(例如,已连接的蓝牙键盘)。
  • 它不支持ClipboardEvent构造函数。

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

但是,可以通过编程方式选择某些内容
,以便用户仅需点击所选内容上显示的“复制”工具提示。这可以通过使用与上面完全相同的代码来实现,只需删除execCommand('copy'),这实际上是行不通的。

2020-05-01