We have often seen “Copy” buttons for plain text. Thanks to navigator.clipboard‘s API, we can also programatically copy and paste HTML content.
The copy code
Let’s imagine we have a bit of HTML content that includes links and other basic HTML code. We want our end users to be able to copy it exactly as it is and use it elsewhere.
For this exercise, we will be working with a simple HTML page with a section with id=”copy-content”
that contains the HTML to be copied, and a “Copy to clipboard” button, with id=”copy-button”
. The code for this example can be found in this gist.
Initially, the javascript that makes it all happen looks like this:
const copyButton = document.getElementById("copy-button");
copyButton.addEventListener("click", copyContent);
function copyContent() {
const content = document.getElementById("copy-content").innerHTML;
addHtmlToClipboard(content);
}
function addHtmlToClipboard(content) {
const type = "text/html";
const blob = new Blob([content], { type });
const data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
() => {
console.log("copied to clipboard");
},
() => {
console.log("failed to copy to clipboard");
},
);
}
First, we add a “click” event to the “Copy to clipboard” button so that, when the button is clicked, the copyContent
function is executed.
This copyContent
function, gets the HTML content we want to copy and passes it to the addHtmlToClipboard
function.
The addHtmlToClipboard
function then takes this content, converts it into an HTML Blob
and creates a new ClipboardItem
with it. This is then writen into the clipboard using navigator.clipboard.write
.
If the clipboard API succedes, the content is ready to be pasted elsewhere. For example, in a Word document or an email.
Note the inline CSS it is also copied but not that which is in a separate file.
Firefox gotcha
Unfortunately the ClipboardItem
funtionality is not yet supported by all browsers, notably Firefox.
As a compromise, we can change the code so that at least the text content is copied to clipboard if the full functionality cannot be used. Here is the updated code:
const copyButton = document.getElementById("copy-button");
copyButton.addEventListener("click", copyContent);
function copyContent() {
const content = document.getElementById("copy-content").innerHTML;
if(typeof ClipboardItem === "function") {
addHtmlToClipboard(content);
} else {
const textContent = sanitize(content);
addTextToClipboard(textContent);
}
}
function addHtmlToClipboard(content) {
const type = "text/html";
const blob = new Blob([content], { type });
const data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
() => {
console.log("copied html to clipboard");
},
() => {
console.log("failed to copy html to clipboard");
},
);
}
// removes all HTML tags and empty spaces at either end
function sanitize(content) {
const pattern = /<\/?[\w ="'-:;\/\.]+>/g;
return content.replaceAll(pattern, "").trim();
}
function addTextToClipboard(text) {
navigator.clipboard.writeText(text).then(
() => {
console.log("copied text to clipboard");
},
() => {
console.log("failed to copy text to clipboard");
},
);
}
So what has changed? First of all, after getting the content to be copied, the copyContent
function checks whether the ClipboardItem
functionality is available.
If it is, the addHtmlToClipboard
function is run just as before. If it isn’t available, the new addTextToClipboard
function is run instead.
This new addTextToClipboard
takes the content to be copied, removes all traces of HTML code from it (via the sanitize
function) and then writes it as text into the clipboard using navigator.clipboard.writeText
.
From the callbacks, instead of console.log
s, you could for example trigger a success notification or failure warning.
Try it out to see it working!
Top comments (0)