在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。 但是,似乎有一些限制,它们是:
- 文本只能从
<input>
和<textarea>
元素复制。 - 如果持有该文本的元素不在
<form>
,则必须是contenteditable
。 - 持有文本的元素不能是
readonly
(尽pipe您可以尝试,但这不是任何地方logging的“官方”方法)。 - 元素内的文本必须在select范围内。
要涵盖所有这四个“要求”,您将不得不:
- 将文本复制到
<input>
或<textarea>
元素中。 - 保存元素的
contenteditable
和readonly
的旧值,以便能够在复制后恢复它们。 - 将
contenteditable
更改为true
并readonly
为false
。 - 创build一个范围来select所需的元素,并将其添加到窗口的select。
- 设置整个元素的select范围 。
- 恢复以前的
contenteditable
和readonly
值。 - 运行
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
事件,并仅在专注的可编辑字段中cut
和paste
。 - 它只支持操作系统剪贴板读/写通过快捷键,而不是通过
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(); });