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

我正在使用此function将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> = 10

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

  1. 文本只能从<input><textarea>元素复制。
  2. 如果持有该文本的元素不在 <form> ,则必须是contenteditable
  3. 持有文本的元素不能readonly (尽pipe您可以尝试,但这不是任何地方logging的“官方”方法)。
  4. 元素内的文本必须在select范围内。

要涵盖所有这四个“要求”,您将不得不:

  1. 将文本复制到<input><textarea>元素中。
  2. 保存元素的contenteditablereadonly的旧值,以便能够在复制后恢复它们。
  3. contenteditable更改为truereadonlyfalse
  4. 创build一个范围来select所需的元素,并将其添加到窗口的select。
  5. 设置整个元素的select范围 。
  6. 恢复以前的contenteditablereadonly值。
  7. 运行execCommand('copy')

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

现在,这看起来有点复杂,太麻烦了,只是发出一个复制命令,所以我不确定这是苹果计划的deviseselect,但是谁知道…同时,这个目前的工作在iOS> = 10上

这样说,像这样的 polyfills可以用来简化这个动作,并使其跨浏览器兼容(感谢@Toskan在评论中的链接)。

工作示例

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

 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(实际上是安全措施)有一些限制:

  • 它仅在有效的select上触发copy事件,并仅在专注的可编辑字段中cutpaste
  • 它只支持操作系统剪贴板读/写通过快捷键,而不是通过document.execCommand() 请注意,“shorcut key”意思是一些可点击的(例如复制/粘贴操作菜单或自定义iOS键盘快捷键)或物理键(例如连接的蓝牙键盘)。
  • 它不支持ClipboardEvent构造函数。

所以(至less现在是这样) ,不可能在iOS设备上使用Javascript以编程方式复制剪贴板中的某些文本/值 。 只有用户可以决定是否要复制一些东西。

然而,可以通过编程来select一些东西 ,这样用户只需要点击select中显示的“复制”工具提示即可。 这可以通过与上面完全相同的代码来实现,只是删除execCommand('copy') ,这实际上不会工作。

我已经search了一些解决scheme,我发现一个实际工作: http : //www.seabreezecomputers.com/tips/copy2clipboard.htm

基本上,例子可以是这样的:

 var $input = $(' some input/textarea '); $input.val(result); if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { var el = $input.get(0); var editable = el.contentEditable; var readOnly = el.readOnly; el.contentEditable = true; el.readOnly = false; var range = document.createRange(); range.selectNodeContents(el); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); el.setSelectionRange(0, 999999); el.contentEditable = editable; el.readOnly = readOnly; } else { $input.select(); } document.execCommand('copy'); $input.blur(); 

出于安全原因,iOS Safari只允许document.execCommand('copy')用于contentEditable容器中的文本。

解决方法是在执行document.execCommand('copy')之前检测iOS Safari并快速切换contentEditable

以下函数可以在所有浏览器/设备中工作,并接受一个CSSselect器HTMLElement

 function copyToClipboard(el) { // resolve the element el = (typeof el === 'string') ? document.querySelector(el) : el; // handle iOS as a special case if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { // save current contentEditable/readOnly status var editable = el.contentEditable; var readOnly = el.readOnly; // convert to editable with readonly to stop iOS keyboard opening el.contentEditable = true; el.readOnly = true; // create a selectable range var range = document.createRange(); range.selectNodeContents(el); // select the range var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); el.setSelectionRange(0, 999999); // restore contentEditable/readOnly to original state el.contentEditable = editable; el.readOnly = readOnly; } else { el.select(); } // execute copy command document.execCommand('copy'); } 
 input { font-size: 14px; font-family: tahoma; } button { font-size: 14px; font-family: tahoma; } 
 <input class="important-message" type="text" value="Hello World" /> <button onclick="copyToClipboard('.important-message')">Copy</button> 

请检查我的解决scheme。

它适用于Safari(在iPhone 7和iPad上testing)以及其他浏览器。

 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/

希望能帮助你。

问候。

 <input id="copyIos" type="hidden" value=""> var clipboard = new Clipboard('.copyUrl'); //兼容ios复制$('.copyUrl').on('click',function() { var $input = $('#copyIos'); $input.val(share_url); if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { clipboard.on('success', function(e) { e.clearSelection(); $.sDialog({ skin: "red", content: 'copy success!', okBtn: false, cancelBtn: false, lock: true }); console.log('copy success!'); }); } else { $input.select(); } //document.execCommand('copy'); $input.blur(); });