9

If I add a prompt to the function it works once, but gives the error:

"Uncaught (in promise) DOMException: Document is not focused" at the second attempt.

This is the code:

function site(str) {
  var url = prompt();
  var text = 'The URL is ';
  (async() => {
    await navigator.clipboard.writeText(text + url);
  })();
}
<button class="button" onclick='site()'>URL</button>

I've asked my best friend, Google, but I can't find any solutions. What am I doing wrong?

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
geirilja
  • 91
  • 1
  • 2
  • 7
    Your code is working fine. The error popups because maybe you are executing code from the devtools console or snippets. While executing your DOM needs to be focused. Check this out https://stackoverflow.com/questions/56306153/domexception-on-calling-navigator-clipboard-readtext – navnath Oct 03 '21 at 13:46
  • The error when running the code snippet here is: `The Clipboard API has been blocked because of a permissions policy applied to the current document. See https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-permissions-in-cross-origin-iframes` This is probably because the code snippet environment is a complex one that has work in a SO web page. Copying the code to a file, test.html, and launching it runs fine. My clipboard contains "The URL is xxxx". – Old Geezer Oct 03 '21 at 15:52

5 Answers5

6

It is probably caused by this bug in chromium (Issue #1085949) which makes your prompt call take focus from the Document and not return it when closed. I was not able to reproduce this issue on Safari and Firefox.

The same bug can be reproduced by doing alert instead of prompt followed by navigator.clipboard.writeText.

Alexander Suraphel
  • 10,103
  • 10
  • 55
  • 90
2

Your JS may be running on a child page. The following works for me:

await parent.navigator.clipboard.writeText('text to copy to Clipboard here.);
Zach Jensz
  • 3,650
  • 5
  • 15
  • 30
Leo PHAM
  • 21
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 17 '22 at 10:53
1

Thanks to @alexandersuraphel !

I fixed in my React app with:

const handleClick = async (text: string) => {
   await navigator.clipboard.writeText(text);
   alert("Text copied!");
};

<button onClick={() => handleClick('Copy this text')}>
   Copy
</button>
Klian
  • 1,520
  • 5
  • 21
  • 32
0

The same error will occur, if you don't await AND immediately after the command e.g. do an alert for feedback to the user, as the alert will steal the focus. Or if you otherwise navigate away or change the focus as a side effect.

(not the case in the above question, but just in case someone else stumbles across this problem and finds this question, I'll leave it here)

lilalinux
  • 2,903
  • 3
  • 43
  • 53
0

This issue occurred to me in Vue3 with the toastify-js library. User would click the copy button and then I would try to copy with navigator as well as use showToast() function.

Ultimately, I think the root of the issue is that something is causing the navigator document root to be taken away such as the showToast() function.

I simply created an async method that calls showToast() and the issue was fixed.

So I suggest looking for any library that is generating a new window or UI element and then just moving that to a separate async function.

Ex

function onClick() {
    Toastify.showToast();
    await navigator.clipboard.writeText(currentUrl);
}

To

function onClick() {
    showToast();
    await navigator.clipboard.writeText(currentUrl);
}

function showToast() {
   Toastify.showToast();
}
Marcus Salinas
  • 356
  • 3
  • 8