Terence Eden. He has a beard and is smiling.
Theme Switcher:

A simple "copy this code" button in JavaScript

· 2 comments · 400 words · Viewed ~1,601 times · 🄯 CC BY-SA


Next to all the code samples on this blog is a little "copy" button. That makes it easier to grab any of the code I've shared.

The HTML and JS is delightfully simple:

Copied HTML to đź“‹
 HTML<button
    onclick="navigator.clipboard.writeText(
        this.parentNode.getElementsByTagName('code')[0].textContent
    );" 
    title="Copy code"
>⧉</button>

The navigator.clipboard.writeText needs a user interaction to work - so it is tied to a click on the button.

It takes some plaintext content. But how to get that content? My code samples look like this:

Copied HTML to đź“‹
 HTML<pre itemscope itemtype=https://schema.org/SoftwareSourceCode translate=no>
    <button onclick="navigator.clipboard.writeText( this.parentNode.getElementsByTagName('code')[0].textContent );">⧉</button>
    <span>
        <img alt height=32 src=html.svg width=32>
        <span itemprop=programmingLanguage> HTML</span>
    </span>
    <code itemprop=text>[…]</code>
</pre>

There are various ways I could get that <code> element:

  • Give it a unique ID (but that might clutter the code, or conflict with something else).
  • Use this.nextSibling.nextSibling (but that might not work if the layout changes).
  • Use this.lastChild.textContent (but, again, depends on the layout staying the same).
  • Select based on itemprop (could make the code a bit longer).
  • Complex filtering on a NodeList (urgh).

None of those are particularly bad per se, so I've chosen the method which makes most sense to me.

You can read more about my Classless Design, and how I use metadata to identify programming languages, including whether HTML's code blocks be translated.

To let people know that it has worked, I've added a little popover.

Every piece of code has it's own dialog element with a unique id:

Copied HTML to đź“‹
 HTML<dialog
    id=pop
    popover=hint>Copied JS to đź“‹</dialog>

No JavaScript is required to show the popover when the copy button is pressed:

Copied HTML to đź“‹
 HTML<button popovertarget=pop popovertargetaction=show>

Closing the the popover hint doesn't require JS; clicking outside it will dismiss it. But a little scrap of JS on the button's onclick will make it disappear after a few seconds:

Copied JavaScript to đź“‹
 JavaScriptsetTimeout(
    function() {
        document.getElementById("pop").hidePopover();
    }, 
3000);

The browser's default is to place it in the middle of the screen.

Positioning the popup so it is in proximity to the button also requires CSS - no JS.

Copied CSS to đź“‹
 CSSdialog[popover] {
    inset: unset;
    position: absolute;
    position-area: top;
    padding: .5em;
}

OK, that started out simple but got a bit more complex. Sorry!

Update! It turns out there are some accessibility issues with this approach. See these updates by Curtis Wilcox.


Share this post on…

2 thoughts on “A simple "copy this code" button in JavaScript”

  1. You also need to consider cases where the user has disabled JS; in this situation, clicking shows a prompt, but nothing is actually copied.

    My approach is to not display the copy button when JS is disabled.

    Reply

    1. Yeah that seems like a good solution, presumably most people who disable JS are knowledgeable to copy the code without the button anyways.

      Reply

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.

See allowed HTML elements: <a href="" title="">
<abbr title="">
<acronym title="">
<b>
<blockquote cite="">
<br>
<cite>
<code>
<del datetime="">
<em>
<i>
<img src="" alt="" title="" srcset="">
<p>
<pre>
<q cite="">
<s>
<strike>
<strong>

To respond on your own website, write a post which contains a link to this post - then enter the URl of your page here. Learn more about WebMentions.