How to add a "copy to clipboard" button to your website
The Challenge
I recently built an API for one of our major clients to allow their users to integrate their software with other services via Zapier. As part of that process, we created a step-by-step tutorial for those users, allowing them to customize their integrations.
Much of the tutorial involves telling them what to type where, and rather than make them select everything individually, we wanted a way for them to copy the text automatically.
The Process
The internet suggested that the best way to set up the view was to house the text-to-be-copied in a "secret" input - ie: hiding the border and making it unclickable, so that it looked like normal text.
Haml view
%h3.upcase
Step 1: API Auth Token
%div.js-copy-container
%input.js-text-to-copy{ readonly: true, value: api_auth_token }
%div.float-left= link_to "Copy", "#", class: "button js-copy-text-button"
I floated a "Copy" button to the right, and then set up my event listener in CoffeeScript. When "Copy" was clicked, I captured the value of the input, and sent it to the clipboard with an exec command (thanks for that tidbit, Stack Overflow!).
I also added an animation so that the button says "Copied!" for a few seconds before fading back to "Copy".
CoffeeScript
class ZapierPage
constructor:
->
$(document).ready
@initListeners
initListeners: =>
$(".js-copy-text-button").on "click", @onCopyTextButtonClick
onCopyTextButtonClick: (ev) ->
ev.preventDefault()
$copyButton = $(ev.target)
$textToCopy = $copyButton.closest(".js-copy-container").find(".js-text-to-copy")
$textToCopy.select()
document.execCommand("copy")
$copyButton.html("Copied!")
setTimeout ->
$copyButton.html("Copy")
, 1000
So far, so good.
And when I clicked "Copy", it did in fact copy the text to my clipboard - but it also selected the input. I tried around a million different things to try to prevent the selection, but nothing worked.
The Solution
With a little help from resident Ten Forward senior dev Brett, we added the following code right after the copy command:
document.getSelection().removeAllRanges()
An explanation why, via the MDN web docs:
The
Selection.removeAllRanges()
method removes all ranges from the selection, leaving theanchorNode
andfocusNode
properties equal tonull
and leaving nothing selected.
Et voilá!