Search code examples
safariaddeventlistenerexeccommand

Combination of document.addEventListener and document.execCommand("copy") does not work in Safari


I have the following code, which works completely fine in Chrome/Edge/Firefox, newest versions of course, but I expect even a few year old browsers of these will work just fine.

Now in Safari 15.3 (newest I think, at least very recent) this code does not work at all.

function copy() {
 const copyListener = (event: any) => {
    event.preventDefault();
    event.stopPropagation();
    event.clipboardData.setData("text/plain", "Random text data");
    event.clipboardData.setData("text/html", "<div>Random html data</div>");
 };
 var eventListenerOptions = {
    capture: true,
    once: true,
 };
 document.addEventListener("copy", copyListener, eventListenerOptions);
 document.execCommand("copy");
}

Let's imagine that this copy() function is called inside of a onClick handler.

Then after the onClick is triggered, then the document did register this eventListener, but it is just not triggered instantly by the document.execCommand("copy") call. It is only triggered when I after the copy() call select something manually on the screen and do ctrl+c.

So question time: (1) I have heard somewhere that Safari does not emit a real copy event without any user interaction, which I guess I have confirmed sort of, it is user interaction to click on the button that calls copy() in its handler right? But maybe not the correct type of interaction. Is there any good official documentation on this? I tried to look at https://developer.apple.com/safari/ but it doesn't really provide you anything useful I think.

(2) I have seen code snippets around, and all of them for Safari uses range selections in the dom, and then call document.execCommand so an eventual solution for me is to use this as well, do a check to see which browser and then fallback to the range selection, I just do not think it supports any granularity in regards to "plain/text" and "plain/html" so I really want to avoid it because of that + less complexity if I could tweak this a little to make it work on all 4 browsers.

Any answers/comments are greatly appreciated, thanks !


Solution

  • Turns out that Safari does not support this idiom supported by Firefox/Edge/Chrome/etc.

    There is a bug report that have not been active since 2019 https://bugs.webkit.org/show_bug.cgi?id=156529