不知道为什么今天这对我来说如此困难,但由于某种原因,我似乎无法让它将当前 URL 复制到剪贴板。总的来说,我正在寻找一种方法来做到这一点,而不需要创建一些隐藏的文本元素。 这就是我到目前为止正在尝试的:
var shareBtn = document.querySelector(".share-button");
shareBtn.addEventListener('click', function(event) {
var cpLink = window.location.href;
cpLink.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copy command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
event.preventDefault;
});
当我尝试使用
.select()
进行操作时,我收到此错误:
t.select is not a function
所以我不能 100% 确定解决这个问题的最佳方法是什么。再次强调,不使用 jQuery(或任何其他 JS 库),也不使用某种隐藏文本字段。input
元素来满足我们的需求。这个想法是创建一个输入,将其值设置为当前文档的 URL,选择其内容并执行
copy
。然后我们清理混乱,而不是将输入设置为隐藏并污染 DOM。
var dummy = document.createElement('input'),
text = window.location.href;
document.body.appendChild(dummy);
dummy.value = text;
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
window.navigator.clipboard.writeText(textToCopy);
确实是浏览器处理复制时所需要的一切,而不涉及任何剪贴板事件的自定义处理。 但是,如果您或某个库挂钩了复制事件(例如,
window.addEventListener('copy', ...)
,然后如果该处理程序依赖于使用
window.getSelection()
,那么一个 19 岁的Firefox 问题将会困扰您。就像 MDN 所说的: 值得注意的是,目前
getSelection()
不适用于 Firefox、Edge(旧版)和 Internet Explorer 中的
和<textarea>
元素的内容。 因此,<input>
getSelection()
在
HTMLInputElement#select
之后返回非空结果,但不提供实际选定的内容。使用非输入元素临时保存 URL 即可轻松修复:function copyUrl() {
if (!window.getSelection) {
alert('Please copy the URL from the location bar.');
return;
}
const dummy = document.createElement('p');
dummy.textContent = window.location.href;
document.body.appendChild(dummy);
const range = document.createRange();
range.setStartBefore(dummy);
range.setEndAfter(dummy);
const selection = window.getSelection();
// First clear, in case the user already selected some other text
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
document.body.removeChild(dummy);
}
(当没有自定义处理程序挂钩复制事件时,上述内容也将起作用。)
我基本上做的是这样的:
获取链接作为 Url 和实际链接元素
Element.prototype.getLink = function () {
let link = document.createElement("a");
link.href = this.getUrl();
link.innerText = this.innerText;
return link;
};
Element.prototype.getUrl = function () {
return new URL(window.location.origin + window.location.pathname + '#' + this.id);
};
Clipboard.prototype.writeHTML = function (html, text) {
let textContent = text || html.innerText;
let htmlContent = "";
if (typeof (html) == "string") htmlContent = html;
else if (html instanceof Element) htmlContent = html.outerHTML;
else htmlContent = html.toString();
if (ClipboardItem) //bug in firefox : https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem
{
let content = [
new ClipboardItem({
"text/html": new Blob([htmlContent], { type: "text/html" }), //this can be interpreted by applications like teams or office word
"text/plain": new Blob([textContent], { type: "text/plain" }) //while this is required for other apps, like plain text editors
})
];
return this.write(content);
}
else {
return this.writeText(textContent);
}
};
let header = document.getElementById("some-header");
let button = document.getElementById("copy-button");
let feedback = document.getElementById("feedback");
button.addEventListener("click", function(){
navigator.clipboard
.writeHTML(header.getLink(), header.getUrl())
.then(function () {
feedback.innerText = "copied!";
})
.catch((error) => {
feedback.innerText = `Oops... that shoudln't have happened. ${error}`;
});
});
<h4 id="some-header">Some Header</h4>
<button id="copy-button" role="button">Copy URL to Header</button>
<div id="feedback">nothing copied yet</div>