Sep 17, 20191 min read

Click to Copy Text with Javascript

In my snippet code component, I’ve added a button to copy the entire snippets when it’s clicked. It looks like this:

JS
let hello = "Click on the copy button on top right corner to copy this entire snippet"
let hello = "Click on the copy button on top right corner to copy this entire snippet"

You can add this using library like Clipboard.js to do it, but for the sake of learning I decided to do it myself from scratch.

In order to achieved that, we need to simulate how we actually copy something on the page. I’ve break it down the necessary steps and it looks pretty much like this:

  1. Select the content/text that we want to copy.
  2. Execute the “COPY” command by using cmd + c or right-click and copy

Turns out the command to achieve step no.2 is pretty simple because there’s a ‘copy’ command available on document object. But for step no.1, it’s pretty complicated because how to get the content of an HTML element is different for each tag.

Let’s do the Code

Let’s assume we have this markup, and we want to copy the text content inside the <div> tag.

HTML
<div class="content">Hi, I want you to copy me!</div>
<button class="button">Copy!</button>
<div class="content">Hi, I want you to copy me!</div>
<button class="button">Copy!</button>
JS
let container = document.querySelector(".content")
let button = document.querySelector(".button")
// Run the copyContent when button clicked!
button.addEventListener("click", copyContent)
function copyContent() {
// 1. Select the Content/Text that we want to copy
let content = container.innerText
// 2. Create a <textarea /> element as placeholder to select and copy the text content
let placeholder = document.createElement("textarea")
// 3. Assign the content into the placeholder
placeholder.value = content
// 4. Hide the placeholder from the screen
placeholder.style.fontSize = "12pt"
placeholder.style.border = "0"
placeholder.style.padding = "0"
placeholder.style.margin = "0"
placeholder.style.position = "absolute"
placeholder.style.opacity = 0
let yPosition = window.pageYOffset || document.documentElement.scrollTop
placeholder.style.top = `${yPosition}px`
// 5. Add the placeholder to DOM, so we can actually select and copy it's content
container.appendChild(placeholder)
// 6. Select the placeholder content by running the selectContent function
selectContent(placeholder)
// 7. Run the Copy command
document.execCommand("copy")
// 8. Remove the placeholder element
container.removeChild(placeholder)
}
// Selecting the Content
// Taken from https://github.com/zenorocha/select
function selectContent(element) {
var selectedText
if (element.nodeName === "SELECT") {
element.focus()
selectedText = element.value
} else if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA") {
var isReadOnly = element.hasAttribute("readonly")
if (!isReadOnly) {
element.setAttribute("readonly", "")
}
element.select()
element.setSelectionRange(0, element.value.length)
if (!isReadOnly) {
element.removeAttribute("readonly")
}
selectedText = element.value
} else {
if (element.hasAttribute("contenteditable")) {
element.focus()
}
var selection = window.getSelection()
var range = document.createRange()
range.selectNodeContents(element)
selection.removeAllRanges()
selection.addRange(range)
selectedText = selection.toString()
}
return selectedText
}
let container = document.querySelector(".content")
let button = document.querySelector(".button")

// Run the copyContent when button clicked!
button.addEventListener("click", copyContent)

function copyContent() {
  // 1. Select the Content/Text that we want to copy
  let content = container.innerText

  // 2. Create a <textarea /> element as placeholder to select and copy the text content
  let placeholder = document.createElement("textarea")

  // 3. Assign the content into the placeholder
  placeholder.value = content

  // 4. Hide the placeholder from the screen
  placeholder.style.fontSize = "12pt"
  placeholder.style.border = "0"
  placeholder.style.padding = "0"
  placeholder.style.margin = "0"
  placeholder.style.position = "absolute"
  placeholder.style.opacity = 0
  let yPosition = window.pageYOffset || document.documentElement.scrollTop
  placeholder.style.top = `${yPosition}px`

  // 5. Add the placeholder to DOM, so we can actually select and copy it's content
  container.appendChild(placeholder)

  // 6. Select the placeholder content by running the selectContent function
  selectContent(placeholder)

  // 7. Run the Copy command
  document.execCommand("copy")

  // 8. Remove the placeholder element
  container.removeChild(placeholder)
}

// Selecting the Content
// Taken from https://github.com/zenorocha/select
function selectContent(element) {
  var selectedText

  if (element.nodeName === "SELECT") {
    element.focus()
    selectedText = element.value
  } else if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA") {
    var isReadOnly = element.hasAttribute("readonly")

    if (!isReadOnly) {
      element.setAttribute("readonly", "")
    }

    element.select()
    element.setSelectionRange(0, element.value.length)

    if (!isReadOnly) {
      element.removeAttribute("readonly")
    }

    selectedText = element.value
  } else {
    if (element.hasAttribute("contenteditable")) {
      element.focus()
    }

    var selection = window.getSelection()
    var range = document.createRange()

    range.selectNodeContents(element)
    selection.removeAllRanges()
    selection.addRange(range)

    selectedText = selection.toString()
  }

  return selectedText
}
See Demo on Codepen »