Programster's Blog

Tutorials focusing on Linux, programming, and open source

Copy To Clipboard

You've probably noticed by now that this blog has lots of snippets that you want to copy into a script before executing. It would be convenient if you didn't have to manually select all of the text to copy it into your clipboard.

Up until now I've ignored adding this capability because I had understood that this capability required flash. However, we can now use clipboard.js to simplify the adding of this functionality. You can see that I have now implemented it into this blog with a link at the bottom of all code snippets that you can click to copy the snippet to your clipboard.

The clipboard.js site has a lot of great examples, but I wanted to bury something into my pre elements and didn't want to use a button, so I took it a bit further and have put an example below that you can use/extend. The example below is pretty ugly, but its mostly going to be a matter of applying your own much better CSS to it. The key things are that it

  • Uses a CDN to fetch the library, so you don't have to worry about adding the source code to something like a blog that you might not have access to the files on.
  • Ensures that the "copy to clipboard" text itself isn't accidentally copied by the user.
  • Parses the snippet to convert it back to html code in case you sanitized it for rendering on a web page like I have done.

In the future, I want to replace the textual link with an icon that appears in the top right corner whenever you hover over the pre element, but this is a quick fix for now.

<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.6.0/clipboard.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous"></script>

        <style>
        pre {
            width:100%;
            background-color: black;
            color: white;
            padding: 1.5em;
            font-size: 1em;
        }

        .copy-to-text-div a {
            color: white;
            display:inline-block;
            position: relative;
        }
        </style>
    </head>
    <body>
        <pre>here is some text</pre>

        <pre>here is some other text</pre>

        <!-- script to add copy to clipboard to all pre elements -->
        <script type="text/javascript">
            var preElements = $('pre');
            
            // convert sanitized html into html.
            // http://stackoverflow.com/questions/1248849/converting-sanitised-html-back-to-displayable-html
            function htmlDecode(input){
                var e = document.createElement('div');
                e.innerHTML = input;
                return e.childNodes[0].nodeValue;
            }
            
            var preElementHandler = function(index, preElement) {
                var textToCopy = htmlDecode(preElement.innerHTML);
                var hoverLink = document.createElement("div");
                var centerTag = document.createElement("center");
                hoverLink.setAttribute("class", "copy-to-text-div");
                var innerLink = document.createElement("a");
                innerLink.href = 'javaScript:void(0);';
                innerLink.onclick = "";
                innerLink.setAttribute("data-clipboard-text", textToCopy);
                innerLink.innerHTML = "Copy to clipboard";
                innerLink.setAttribute("style", "color: grey; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none;");

                var clipboard = new Clipboard(innerLink);
                
                $(preElement).append(innerLink);
                clipboard.on('error', function(e) {
                    alert("There was an error copying text to your clipboard. Please use Chrome or Firefox.")
                });
                
                centerTag.append(innerLink);
                hoverLink.append(centerTag);
                preElement.append(hoverLink);
            };
            
            $.each(preElements, preElementHandler);
        </script>
    </body>
</html>