Search code examples
javascriptclipboard

JS: How I can detect if HTML was successfully copied to the clipboard?


This sample code for copying plain text seems to work with most browsers…

navigator.clipboard.writeText(text).then(() => {
    console.log("Copied.");
}).catch(err => {
    console.log("Error.");
});

…whereas this sample code for copying HTML to the clipboard does NOT work with Mobile Chrome nor does it return an error…

navigator.permissions.query({name: "clipboard-write"}).then((result) => {
    if (result.state === "granted" || result.state === "prompt") {
        const blobInput = new Blob([exportContent], {type: "text/html"});
        const clipboardItemInput = new ClipboardItem({"text/html" : blobInput});                        

        navigator.clipboard.write([clipboardItemInput]).then(() => {
            console.log("Copied");
        }).catch(err => {
            console.log("Error.");
        });
    }
    else {
        console.log("Permission denied.");
    }   
});

Is there another way to construct the second example to work in Android; and if not, how can I detect the failure given that navigator.clipboard.write does not return an error in Mobile Chrome?


UPDATE: Better-Than-Nothing Workaround

Given that I'm not hopeful that this can be resolved without Google addressing the issue, I at least wanted to: (1) find a way to not have users blame my website/app for the Clipboard being empty; (2) not get on the slippery slope of trying to detect the devices that have the problem along with writing special case code; and (3) ensure that the process immediately starts working if Google ever gets around to fixing the problem. So…

Since I can successfully write plain text to the keyboard, I now have two parts to the code:

  1. I first write a plain text message like "[App name] sent HTML to the Clipboard. If this is what got pasted, it means your device is…[along with a suggested alternative of attaching the content in a file in lieu of pasting]."
  2. I then attempt to write the HTML to the Clipboard.

When writing the HTML works, the user doesn't see the message from Part 1 when pasting. When it doesn't work, the user sees the message and at least knows more about the problem and an alternative.


FINAL UPDATE

I have come to believe the HTML is on the Clipboard but not consistently accessible. That explains the reason for no errors being thrown. If I can get Gmail in Android to display a context menu, which it only does 20% of the time, I can successfully paste the HTML. GBoard never shows the HTML content but always shows the plain text.

I can live with the aforementioned workaround. It's a minor hassle for users the first time they encounter the issue, but after they realize their device has a problem, they just start using the alternative (which actually has some benefits).


Solution

  • I had this issue and I tried hard to solve it till I found that some mobile browsers just don't support it. So your first simple code is the best solution but instead of showing an error, I suggest you show a prompt telling the user to copy the given text in case the browser can't do it or doesn't support it.

    function copyText() {
    
        navigator.clipboard.writeText(text).then(() => {
          alert("text is copied to clipboard");
        }, () => {
          window.prompt("Please copy this text", text);
        });
      }
    

    Edit: regarding your comment, for that you can just put the prompt block in try and catch:

    function copyText() {
    
        navigator.clipboard.writeText(text).then(() => {
          alert("text is copied to clipboard");
        }, () => {
    
          try {
    
            window.prompt("Please copy this text", text);
    
          } catch (error) {
            
            alert("Your browser doesn't support this function");
          }
          
        });
      }