我在 bookmarklet/favlet 中有以下(经过清理和格式化的)javascript 代码。该代码从一些与
querySelector
定义匹配的对象中复制文本。然后它将其复制到剪贴板并告诉用户它已被复制。
!function () {
// get objects from web page
let n = document.querySelector("span.flipper"),
e = n.querySelectorAll("span.OptionLabel"),
o = e.length;
// loop through and construct output from text in objects
for (var t = "", r = 0; r < o; r++)
t += e[r].textContent + ", ";
// wait for text to be written to clipboard
async function c() {
await navigator.clipboard.writeText(t);
console.log("chesterton's fence") // partial fix??
}
// tell user what was copied
confirm('Click "OK" to copy the list to your clipboard.' + o + "\n\n" + t + "\n"), c()
}();
代码有时可以工作。自从我添加了
console.log
以来,它似乎更频繁地工作。如果我将代码粘贴到开发人员工具(Edge)上的控制台中,它就会起作用。但是,当我执行“ctrl+L”[聚焦地址栏]、“* ext”[查找小书签],然后选择小书签时,大多数情况下它不起作用。
Edge 中的控制台错误是:
Uncaught (in promise) DOMException: Document is not focused.
我想了解原因,当然也想纠正这种行为。我知道与剪贴板交互存在安全限制,但有时它可以工作(也许只有在打开开发工具之后?)。
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard#using_the_clipboard_api似乎没有给出任何关于为什么这不起作用的答案?
也许我错误地使用了异步?这是我第一次使用该功能。
可能与页面动态写入的对象有关?我必须打开一个下拉菜单才能显示元素,然后运行我的书签。
confirm
始终显示我想要的文本,因此只是写入剪贴板失败。
例如,我发现这个问题 Document notfocused errorwhenwriting toclipboardusingClipboardAPIinchromeextension 相关但没有答案;其他类似的问题已经超过 3 年了,似乎没有帮助,所以我再次询问,因为安全将继续进行。不过,它是可能的,有时它会起作用,除非这是边缘浏览器的错误。
document.execCommand('copy')
有一些有希望的解决方法,但它已被弃用,所以我想避免使用它,即使 Edge 目前仍然支持它。该页面是 HTTPS,脚本位于书签的 URL 中。
如果在
setTimeout
之后添加 0ms confirm()
即可。这是一个不寻常的技巧,可以强制某些代码在调用堆栈的末尾执行。我怀疑这是因为 confirm()
调出了本机浏览器控件,从而抢走了焦点。然后,浏览器可能不会将任务排队以将焦点返回到页面,直到调用堆栈结束。因此,您也可以通过在之后对剪贴板副本进行排队来在它自己的游戏中击败它。
!function () {
// get objects from web page
let n = document.querySelector("span.flipper"),
e = n.querySelectorAll("span.OptionLabel"),
o = e.length;
// loop through and construct output from text in objects
for (var t = "", r = 0; r < o; r++)
t += e[r].textContent + ", ";
// wait for text to be written to clipboard
async function c() {
await navigator.clipboard.writeText(t);
console.log("chesterton's fence") // partial fix??
}
// tell user what was copied
confirm('Click "OK" to copy the list to your clipboard.' + o + "\n\n" + t + "\n")
setTimeout(() => c(), 0)
}();