在 iOS 中使用 Javascript 复制到剪贴板
Copy to clipboard using Javascript in iOS
我正在使用此功能将 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 设备上,我的功能 returns 成功,但数据根本没有复制到剪贴板。是什么原因造成的,我该如何解决这个问题?
更新! iOS >= 10
看起来在 selection ranges 的帮助下和一些小 hack 可以直接复制到 iOS (>= 10) Safari 上的剪贴板。我亲自在 iPhone 5C iOS 10.3.3 和 iPhone 8 iOS 11.1 上进行了测试。但是,似乎有一些限制,即:
- 只能从
<input>
和 <textarea>
元素复制文本。
- 如果包含文本的元素在
<form>
中是 而不是 ,那么它必须是 contenteditable
.
- 保存文本的元素必须而不是
readonly
(尽管您可以尝试,这不是任何地方记录的"official"方法)。
- 元素内的文本必须在 selection 范围内。
要涵盖所有这四个 "requirements",您必须:
- 将要复制的文本放在
<input>
或 <textarea>
元素中。
- 保存元素的
contenteditable
和 readonly
的旧值,以便能够在复制后恢复它们。
- 将
contenteditable
更改为 true
,将 readonly
更改为 false
。
- 创建一个 range 到 select 所需的元素并将其添加到 window 的 selection.
- 为整个元素设置 selection range。
- 恢复以前的
contenteditable
和 readonly
值。
- 运行
execCommand('copy')
.
这将导致用户设备的插入符移动,select 元素中您想要的所有文本,然后自动发出复制命令。用户将看到正在 select 编辑的文本,并且将显示带有选项 select/copy/paste 的工具提示。
现在,这看起来有点复杂,而且只发出复制命令太麻烦了,所以我不确定这是不是 Apple 的设计选择,但谁知道呢...时间,这个 目前在 iOS >= 10.
上工作
话虽如此,评论中 link 的 this one could be used to simplify this action and make it cross-browser compatible (thanks @Toskan 之类的 polyfills。
工作示例
总而言之,您需要的代码如下所示:
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 上,Safari 对 Clipboard API:
有一些限制(实际上是安全措施)
- 它仅在有效的 selection 上触发
copy
事件,仅在聚焦的可编辑字段中触发 cut
和 paste
事件。
- 只支持OS剪贴板reading/writing通过快捷键,不支持
document.execCommand()
。注意"shorcut key"表示一些可点击(例如 copy/paste 操作菜单或自定义 iOS 键盘快捷键)或物理键(例如连接的蓝牙键盘)。
- 它不支持
ClipboardEvent
构造函数。
所以(至少到目前为止)无法使用 Javascript[=107 以编程方式在 iOS 设备上的剪贴板中复制一些 text/value =].只有用户可以决定是否复制某些内容。
然而,可以通过编程方式select某些东西,这样用户只需点击 "Copy" 上显示的工具提示 select离子。这可以使用与上面完全相同的代码来实现,只需删除 execCommand('copy')
,这确实行不通。
我搜索了一些解决方案并找到了一个实际有效的解决方案: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();
<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();
});
请检查我的解决方案。
它适用于 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/
希望对你有所帮助。
此致。
问题: iOS Safari 仅允许 document.execCommand('copy')
用于 contentEditable
容器中的文本。
解决方案: 检测 iOS Safari 并在执行 document.execCommand('copy')
.
之前快速切换 contentEditable
以下功能适用于所有浏览器。使用 CSS 选择器 或 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>
我的解决方案是结合此页面中的其他答案创建的。
与其他答案不同,它不需要您在页面上已经有一个元素。它将创建自己的文本区域,然后清理混乱。
function copyToClipboard(str) {
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
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();
}
document.execCommand('copy');
document.body.removeChild(el);
}
这是我的跨浏览器实现(包括iOS)
您可以通过运行下面的代码片段
进行测试
示例:
copyToClipboard("Hello World");
/**
* Copy a string to clipboard
* @param {String} string The string to be copied to clipboard
* @return {Boolean} returns a boolean correspondent to the success of the copy operation.
* @see
*/
function copyToClipboard(string) {
let textarea;
let result;
try {
textarea = document.createElement('textarea');
textarea.setAttribute('readonly', true);
textarea.setAttribute('contenteditable', true);
textarea.style.position = 'fixed'; // prevent scroll from jumping to the bottom when focus is set.
textarea.value = string;
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
const range = document.createRange();
range.selectNodeContents(textarea);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
textarea.setSelectionRange(0, textarea.value.length);
result = document.execCommand('copy');
} catch (err) {
console.error(err);
result = null;
} finally {
document.body.removeChild(textarea);
}
// manual copy fallback using prompt
if (!result) {
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
const copyHotkey = isMac ? '⌘C' : 'CTRL+C';
result = prompt(`Press ${copyHotkey}`, string); // eslint-disable-line no-alert
if (!result) {
return false;
}
}
return true;
}
Demo: <button onclick="copyToClipboard('It works!\nYou can upvote my answer now :)') ? this.innerText='Copied!': this.innerText='Sorry :(' ">Click here</button>
<p>
<textarea placeholder="(Testing area) Paste here..." cols="80" rows="4"></textarea>
</p>
NOTE: It doesn't work when it is not initiated by the user, like timeouts or any async event!
It must come from a trusted event like called from a click
event on a button
这个为我工作的只读输入元素。
copyText = input => {
const isIOSDevice = navigator.userAgent.match(/ipad|iphone/i);
if (isIOSDevice) {
input.setSelectionRange(0, input.value.length);
} else {
input.select();
}
document.execCommand('copy');
};
我在 ios 和其他浏览器上的功能在 ios 上测试后复制到剪贴板:5c,6,7
/**
* Copies to Clipboard value
* @param {String} valueForClipboard value to be copied
* @param {Boolean} isIOS is current browser is Ios (Mobile Safari)
* @return {boolean} shows if copy has been successful
*/
const copyToClipboard = (valueForClipboard, isIOS) => {
const textArea = document.createElement('textarea');
textArea.value = valueForClipboard;
textArea.style.position = 'absolute';
textArea.style.left = '-9999px'; // to make it invisible and out of the reach
textArea.setAttribute('readonly', ''); // without it, the native keyboard will pop up (so we show it is only for reading)
document.body.appendChild(textArea);
if (isIOS) {
const range = document.createRange();
range.selectNodeContents(textArea);
const selection = window.getSelection();
selection.removeAllRanges(); // remove previously selected ranges
selection.addRange(range);
textArea.setSelectionRange(0, valueForClipboard.length); // this line makes the selection in iOS
} else {
textArea.select(); // this line is for all other browsers except ios
}
try {
return document.execCommand('copy'); // if copy is successful, function returns true
} catch (e) {
return false; // return false to show that copy unsuccessful
} finally {
document.body.removeChild(textArea); // delete textarea from DOM
}
};
以上关于 contenteditable=true 的回答。我认为只属于div。并且 <textarea>
不适用。
isIOS变量可以检查为
const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);
不错,这是上面的打字稿重构,以防有人感兴趣(写成 ES6 模块):
type EditableInput = HTMLTextAreaElement | HTMLInputElement;
const selectText = (editableEl: EditableInput, selectionStart: number, selectionEnd: number) => {
const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);
if (isIOS) {
const range = document.createRange();
range.selectNodeContents(editableEl);
const selection = window.getSelection(); // current text selection
selection.removeAllRanges();
selection.addRange(range);
editableEl.setSelectionRange(selectionStart, selectionEnd);
} else {
editableEl.select();
}
};
const copyToClipboard = (value: string): void => {
const el = document.createElement('textarea'); // temporary element
el.value = value;
el.style.position = 'absolute';
el.style.left = '-9999px';
el.readOnly = true; // avoid iOs keyboard opening
el.contentEditable = 'true';
document.body.appendChild(el);
selectText(el, 0, value.length);
document.execCommand('copy');
document.body.removeChild(el);
};
export { copyToClipboard };
剪贴板 API 已添加到 Safari 13.1 中,请参阅此处 https://webkit.org/blog/10247/new-webkit-features-in-safari-13-1/
现在就像navigator.clipboard.writeText("Text to copy")
一样简单
iOS 13.4 及更高版本
从版本 13.4 开始,iOS Safari 支持现代异步剪贴板 API:
与 JavaScript 中的所有内容一样,较新的 API 大约好 1000 倍,但您仍然需要粗略的后备代码,因为您的许多用户将使用旧版本多年。
以下是如何使用新剪贴板 API 和原始问题中的代码:
function CopyUrl($this){
var querySelector = $this.next().attr("id");
var emailLink = document.querySelector("#"+querySelector);
if (navigator.clipboard) {
var myText = emailLink.textContent;
navigator.clipboard.writeText(myText).then(function() {
// Do something to indicate the copy succeeded
}).catch(function() {
// Do something to indicate the copy failed
});
} else {
// Here's where you put the fallback code for older browsers.
}
}
这通过允许将文本作为变量传递来改进 Marco 的回答。
这适用于 ios >10。
这不适用于 Windows。
function CopyToClipboardIOS(TheText) {
var el=document.createElement('input');
el.setAttribute('style','position:absolute;top:-9999px');
el.value=TheText;
document.body.appendChild(el);
var 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);
document.execCommand('copy');
el.remove();
}
我正在使用此功能将 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 设备上,我的功能 returns 成功,但数据根本没有复制到剪贴板。是什么原因造成的,我该如何解决这个问题?
更新! iOS >= 10
看起来在 selection ranges 的帮助下和一些小 hack 可以直接复制到 iOS (>= 10) Safari 上的剪贴板。我亲自在 iPhone 5C iOS 10.3.3 和 iPhone 8 iOS 11.1 上进行了测试。但是,似乎有一些限制,即:
- 只能从
<input>
和<textarea>
元素复制文本。 - 如果包含文本的元素在
<form>
中是 而不是 ,那么它必须是contenteditable
. - 保存文本的元素必须而不是
readonly
(尽管您可以尝试,这不是任何地方记录的"official"方法)。 - 元素内的文本必须在 selection 范围内。
要涵盖所有这四个 "requirements",您必须:
- 将要复制的文本放在
<input>
或<textarea>
元素中。 - 保存元素的
contenteditable
和readonly
的旧值,以便能够在复制后恢复它们。 - 将
contenteditable
更改为true
,将readonly
更改为false
。 - 创建一个 range 到 select 所需的元素并将其添加到 window 的 selection.
- 为整个元素设置 selection range。
- 恢复以前的
contenteditable
和readonly
值。 - 运行
execCommand('copy')
.
这将导致用户设备的插入符移动,select 元素中您想要的所有文本,然后自动发出复制命令。用户将看到正在 select 编辑的文本,并且将显示带有选项 select/copy/paste 的工具提示。
现在,这看起来有点复杂,而且只发出复制命令太麻烦了,所以我不确定这是不是 Apple 的设计选择,但谁知道呢...时间,这个 目前在 iOS >= 10.
上工作话虽如此,评论中 link 的 this one could be used to simplify this action and make it cross-browser compatible (thanks @Toskan 之类的 polyfills。
工作示例
总而言之,您需要的代码如下所示:
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 上,Safari 对 Clipboard API:
有一些限制(实际上是安全措施)- 它仅在有效的 selection 上触发
copy
事件,仅在聚焦的可编辑字段中触发cut
和paste
事件。 - 只支持OS剪贴板reading/writing通过快捷键,不支持
document.execCommand()
。注意"shorcut key"表示一些可点击(例如 copy/paste 操作菜单或自定义 iOS 键盘快捷键)或物理键(例如连接的蓝牙键盘)。 - 它不支持
ClipboardEvent
构造函数。
所以(至少到目前为止)无法使用 Javascript[=107 以编程方式在 iOS 设备上的剪贴板中复制一些 text/value =].只有用户可以决定是否复制某些内容。
然而,可以通过编程方式select某些东西,这样用户只需点击 "Copy" 上显示的工具提示 select离子。这可以使用与上面完全相同的代码来实现,只需删除 execCommand('copy')
,这确实行不通。
我搜索了一些解决方案并找到了一个实际有效的解决方案: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();
<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();
});
请检查我的解决方案。
它适用于 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/
希望对你有所帮助。
此致。
问题: iOS Safari 仅允许 document.execCommand('copy')
用于 contentEditable
容器中的文本。
解决方案: 检测 iOS Safari 并在执行 document.execCommand('copy')
.
contentEditable
以下功能适用于所有浏览器。使用 CSS 选择器 或 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>
我的解决方案是结合此页面中的其他答案创建的。
与其他答案不同,它不需要您在页面上已经有一个元素。它将创建自己的文本区域,然后清理混乱。
function copyToClipboard(str) {
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
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();
}
document.execCommand('copy');
document.body.removeChild(el);
}
这是我的跨浏览器实现(包括iOS)
您可以通过运行下面的代码片段
进行测试示例:
copyToClipboard("Hello World");
/**
* Copy a string to clipboard
* @param {String} string The string to be copied to clipboard
* @return {Boolean} returns a boolean correspondent to the success of the copy operation.
* @see
*/
function copyToClipboard(string) {
let textarea;
let result;
try {
textarea = document.createElement('textarea');
textarea.setAttribute('readonly', true);
textarea.setAttribute('contenteditable', true);
textarea.style.position = 'fixed'; // prevent scroll from jumping to the bottom when focus is set.
textarea.value = string;
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
const range = document.createRange();
range.selectNodeContents(textarea);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
textarea.setSelectionRange(0, textarea.value.length);
result = document.execCommand('copy');
} catch (err) {
console.error(err);
result = null;
} finally {
document.body.removeChild(textarea);
}
// manual copy fallback using prompt
if (!result) {
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
const copyHotkey = isMac ? '⌘C' : 'CTRL+C';
result = prompt(`Press ${copyHotkey}`, string); // eslint-disable-line no-alert
if (!result) {
return false;
}
}
return true;
}
Demo: <button onclick="copyToClipboard('It works!\nYou can upvote my answer now :)') ? this.innerText='Copied!': this.innerText='Sorry :(' ">Click here</button>
<p>
<textarea placeholder="(Testing area) Paste here..." cols="80" rows="4"></textarea>
</p>
NOTE: It doesn't work when it is not initiated by the user, like timeouts or any async event!
It must come from a trusted event like called from a
click
event on a button
这个为我工作的只读输入元素。
copyText = input => {
const isIOSDevice = navigator.userAgent.match(/ipad|iphone/i);
if (isIOSDevice) {
input.setSelectionRange(0, input.value.length);
} else {
input.select();
}
document.execCommand('copy');
};
我在 ios 和其他浏览器上的功能在 ios 上测试后复制到剪贴板:5c,6,7
/**
* Copies to Clipboard value
* @param {String} valueForClipboard value to be copied
* @param {Boolean} isIOS is current browser is Ios (Mobile Safari)
* @return {boolean} shows if copy has been successful
*/
const copyToClipboard = (valueForClipboard, isIOS) => {
const textArea = document.createElement('textarea');
textArea.value = valueForClipboard;
textArea.style.position = 'absolute';
textArea.style.left = '-9999px'; // to make it invisible and out of the reach
textArea.setAttribute('readonly', ''); // without it, the native keyboard will pop up (so we show it is only for reading)
document.body.appendChild(textArea);
if (isIOS) {
const range = document.createRange();
range.selectNodeContents(textArea);
const selection = window.getSelection();
selection.removeAllRanges(); // remove previously selected ranges
selection.addRange(range);
textArea.setSelectionRange(0, valueForClipboard.length); // this line makes the selection in iOS
} else {
textArea.select(); // this line is for all other browsers except ios
}
try {
return document.execCommand('copy'); // if copy is successful, function returns true
} catch (e) {
return false; // return false to show that copy unsuccessful
} finally {
document.body.removeChild(textArea); // delete textarea from DOM
}
};
以上关于 contenteditable=true 的回答。我认为只属于div。并且 <textarea>
不适用。
isIOS变量可以检查为
const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);
不错,这是上面的打字稿重构,以防有人感兴趣(写成 ES6 模块):
type EditableInput = HTMLTextAreaElement | HTMLInputElement;
const selectText = (editableEl: EditableInput, selectionStart: number, selectionEnd: number) => {
const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);
if (isIOS) {
const range = document.createRange();
range.selectNodeContents(editableEl);
const selection = window.getSelection(); // current text selection
selection.removeAllRanges();
selection.addRange(range);
editableEl.setSelectionRange(selectionStart, selectionEnd);
} else {
editableEl.select();
}
};
const copyToClipboard = (value: string): void => {
const el = document.createElement('textarea'); // temporary element
el.value = value;
el.style.position = 'absolute';
el.style.left = '-9999px';
el.readOnly = true; // avoid iOs keyboard opening
el.contentEditable = 'true';
document.body.appendChild(el);
selectText(el, 0, value.length);
document.execCommand('copy');
document.body.removeChild(el);
};
export { copyToClipboard };
剪贴板 API 已添加到 Safari 13.1 中,请参阅此处 https://webkit.org/blog/10247/new-webkit-features-in-safari-13-1/
现在就像navigator.clipboard.writeText("Text to copy")
iOS 13.4 及更高版本
从版本 13.4 开始,iOS Safari 支持现代异步剪贴板 API:
与 JavaScript 中的所有内容一样,较新的 API 大约好 1000 倍,但您仍然需要粗略的后备代码,因为您的许多用户将使用旧版本多年。
以下是如何使用新剪贴板 API 和原始问题中的代码:
function CopyUrl($this){
var querySelector = $this.next().attr("id");
var emailLink = document.querySelector("#"+querySelector);
if (navigator.clipboard) {
var myText = emailLink.textContent;
navigator.clipboard.writeText(myText).then(function() {
// Do something to indicate the copy succeeded
}).catch(function() {
// Do something to indicate the copy failed
});
} else {
// Here's where you put the fallback code for older browsers.
}
}
这通过允许将文本作为变量传递来改进 Marco 的回答。 这适用于 ios >10。 这不适用于 Windows。
function CopyToClipboardIOS(TheText) {
var el=document.createElement('input');
el.setAttribute('style','position:absolute;top:-9999px');
el.value=TheText;
document.body.appendChild(el);
var 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);
document.execCommand('copy');
el.remove();
}