admin管理员组文章数量:1134232
Following lines of code used to work and stopped working after chrome upgrade to Version 74.0.3729.169 (Official Build) (64-bit). Now I get DOMException even though permission is set correctly. Appreciate if you can explain what is the bug and workaround. Exception details:
NotAllowedError: Document is not focused | code:0
navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
// If permission to read the clipboard is granted or if the user will
// be prompted to allow it, we proceed.
if (result.state === 'granted' || result.state === 'prompt') {
navigator.clipboard.readText()
.then(text => {
//my code to handle paste
})
.catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
});
Following lines of code used to work and stopped working after chrome upgrade to Version 74.0.3729.169 (Official Build) (64-bit). Now I get DOMException even though permission is set correctly. Appreciate if you can explain what is the bug and workaround. Exception details:
NotAllowedError: Document is not focused | code:0
navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
// If permission to read the clipboard is granted or if the user will
// be prompted to allow it, we proceed.
if (result.state === 'granted' || result.state === 'prompt') {
navigator.clipboard.readText()
.then(text => {
//my code to handle paste
})
.catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
});
Share
Improve this question
edited Jan 21, 2024 at 18:45
CerebralFart
3,4905 gold badges27 silver badges30 bronze badges
asked May 25, 2019 at 15:21
frostyfrosty
2,8226 gold badges31 silver badges60 bronze badges
1
- Workaround, Just paste it in setTimeout, and then focus on document. – Suraj Jain Commented Nov 19, 2019 at 10:03
15 Answers
Reset to default 81This seems to happen when executing code from the devtools console or snippets.
Workaround:
You can execute the code below and focus on the window within 3 seconds, by clicking somewhere, or just by pressing <tab>
.
e.g. from snippets
Ctrl-Enter
<Tab>
e.g. from console
Enter
<Tab>
setTimeout(async()=>console.log(
await window.navigator.clipboard.readText()), 3000)
The issue I was having was that I had an alert to say that the text had been copied, and that was removing focus from the document. Ironically, this caused the text to not be copied. The workaround was quite simple:
clipboard.writeText(clippy_button.href).then(function(x) {
alert("Link copied to clipboard: " + clippy_button.href);
});
Just show the alert when the Promise is resolved. This might not fix everybody's issue but if you came here based on searching for the error this might be the correct fix for your code.
As Kaiido said, your DOM need to be focused. I had the same problem during my development when i put a breakpoint in the code... The console developper took the focused and the error appear. With the same code and same browser, all work fine if F12 is closed
Problem
It's a security risk, clearly. :)
Solution
I assume you face this when you are trying to call it from the dev tools. Well, to make life easier, I am taking Jannis's answer, to a less adrenaline-oriented way. :)
I am adding a one-time focus
listener to window
to do the things magically after hitting "tab" from the Devtools.
function readClipboardFromDevTools() {
return new Promise((resolve, reject) => {
const _asyncCopyFn = (async () => {
try {
const value = await navigator.clipboard.readText();
console.log(`${value} is read!`);
resolve(value);
} catch (e) {
reject(e);
}
window.removeEventListener("focus", _asyncCopyFn);
});
window.addEventListener("focus", _asyncCopyFn);
console.log("Hit <Tab> to give focus back to document (or we will face a DOMException);");
});
}
// To call:
readClipboardFromDevTools().then((r) => console.log("Returned value: ", r));
Note: The return value is a Promise as it's an asynchronous call.
In latest Chrome dev tools, there is an option called "Emulate a focused page" in its Rendering panel. You can simply enable that option and then the clipboard code would
if you want to debug a and play around to view result. also can hide this <p></p>
.
async function readClipboard () {
if (!navigator.clipboard) {
// Clipboard API not available
return
}
try {
const text = await navigator.clipboard.readText();
document.querySelector('.clipboard-content').innerText = text;
} catch (err) {
console.error('Failed to copy!', err)
}
}
function updateClipboard() {
// Here You Can Debug without DomException
debugger
const clipboard = document.querySelector('.clipboard-content').innerText;
document.querySelector('.clipboard-content').innerText = 'Updated => ' + clipboard;
}
<button onclick="readClipboard()">Paste</button>
<p class="clipboard-content"></p>
<button onclick="updateClipboard()">Edit</button>
You can simply add an alert which focus your document and then run what you want after it right away like so:
alert("Copied to clipboard.");
navigator.clipboard.writeText("a sample text!");
I was facing this in a Cypress test, this fixed it for me:
- first focus the copy icon/button which is about to be clicked, then
- use cy.realClick from cypress-real-events instead of cy.click
Suppose there is a p
element. you want to copy its innerText
.
So, lets not use navigation.clipboard
(because 0f the error your are facing)
So below given is a example which copies the innerText
of the p
element when that button is clicked. your do not to rely upon "clicking" the button manually by using the code below. you can trigger the "click" by executing code like pElement.click()
from devtools console.
Your devtools console problem, that @jannis-ioannou mentioned in his post above, will not occur!
function myFunction() {
var copyText = document.getElementById("copy-my-contents");
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(copyText);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("copy");
}
<p id="copy-my-contents">copy-me</p>
<button onclick="myFunction()">Copy text</button>
I just discovered that I don't need to write any code to debug this. When you pause on a breakpoint in Chrome DevTools, it adds a small yellow box to the page you're debugging which says, "Paused in debugger" and has play and step over buttons. I've never used it before, preferring the more extensive controls in DevTools.
I just discovered that if you use the step over button in this yellow box, the DOM stays focused and no error is thrown.
Cypress - Use the right window/navigator and focus on the document.
I tried to programatically populate the clipboard in my Cypress test so I could paste the contents into a text-area input element. When I was struggling with this issue I found out that there were two things causing the problem.
The first issue was that I used the wrong window. Inside the test function scope window
returns the Window object in test scope, while cy.window()
returns the Window object for the Application Under Test (AUT).
Second issue was that document was not in focus, which can be easily resolved by calling cy.window().focus();
.
Since both result in the same DOMException
:
NotAllowedError: Document is not focused.
It was not always clear that there were 2 issues going on. So when debugging this:
- Make sure you use the right window/navigator of the page you are testing.
- Make sure that the document is focused on.
See following Cypress tests demonstrating the above:
describe('Clipboard tests', () => {
before(() => {
cy.visit('/');
// Focus on the document
cy.window().focus();
});
it('window object in test scope is not the window of the AUT', () => {
cy.window().then((win) => {
expect(window === win).to.equal(false);
expect(window.navigator === win.navigator).to.equal(false);
})
});
it('See here the different results from the different Window objects', () => {
expect(window.navigator.clipboard.writeText('test').catch(
(exception) => {
expect(exception.name).to.equal('NotAllowedError')
expect(exception.message).to.equal('Document is not focused.')
},
));
cy.window().then((win) => {
return win.navigator.clipboard.writeText('test').then(() => {
return win.navigator.clipboard.readText().then(
result => expect(result).to.equal('test'),
);
});
});
})
});
Browser requires user-interactive event or already focused to copy/read to/from clipboard. A solution is wait for a click:
async function wait(){
await window.navigator.clipboard.writeText("foobar");
document.removeEventListener("click",wait);
}
document.addEventListener("click",wait);
As the exception message says, you need to have the Document actively focused in order to use this API.
We saw a handful of these in our production app, and after some digging it turned out that the root cause in our case was the user was copying a lot of data, and switched tabs during the process (thus causing the relevant DOM to lose focus, and triggering the error). We were only able to replicate this by using CPU throttling in chrome, and even then it doesn't happen every time!
There was nothing to be "fixed" in this case - instead we're just catching the error and notifying the user via a toast that the copy failed and that they should try again. Posting in case it's of use to anyone else seeing this!
If you're using Selenium and getting this, you need to bring the test window to the front:
webDriver.switchTo().window(webDriver.getWindowHandle());
I have to do this repeatedly so I have it in a loop with a Thread.sleep() until the the paste works.
Full details: https://stackoverflow.com/a/65248258/145976
本文标签: javascriptDOMException on calling navigatorclipboardreadText()Stack Overflow
版权声明:本文标题:javascript - DOMException on calling navigator.clipboard.readText() - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736806534a1953713.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论