A good[ish] website
Web development blog, loads of UI and JavaScript topics
Here’s a post that looks into how to programmatically copy text from the DOM using JavaScript. I’m going to use React as a library, but this stuff converts easily into vanilla JavaScript.
There’s two ways to go about doing this:
execCommand method.clipBoard interface.Although now deprecated, but still used around quit a bit, slightly hacky and clearly an archaic way of doing this. But worth knowing about.
It works like this (check out the corresponding numbers in the example code):
textarea or in input field.copy command and the selected text is copied into the clipboard.Here’s the program and under is a demo for that:
import React from 'react'
const clearSelection = () => {
if (window.getSelection) window.getSelection().removeAllRanges()
}
const CopyApp = () => {
const textareaRef = React.useRef(null)
const [copyState, setCopyState] = React.useState('👈 Copy with that button')
const handleClick = () => {
if (textareaRef.current) {
textareaRef.current.focus() // 1 textareaRef.current.select() // 2
try {
const wasSuccessful = document.execCommand('copy') // 3 setCopyState(wasSuccessful ? '👍 Text copied' : 'Unable to copy')
} catch (error) {
setCopyState('Error happened')
console.log(error)
}
clearSelection() // 4 textareaRef.current.blur() // 5 }
}
return (
<div className="app">
<h1>Copy text with JavaScript</h1>
<textarea
className="textBox"
defaultValue="Heres some text that we can to copy using JavaScript."
ref={textareaRef}
/>
<button onClick={handleClick}>Copy text</button>
<span className="copy-msg">{copyState}</span>
</div>
)
}
export default CopyAppAnd an execCommand demo:
The problem with the execCommand method is that the text needs to be in a textarea or an input, because it needs to be selected, because the execCommand relies on the Document.designMode.
If the layout requires that text is not in a textarea or an input field, and using this method is mandatory, in that case you can have a hidden textarea on the page: <textarea hidden>Text</textarea>, which holds the same content as the div, or whatever the element is.
The clipboard API has a way more modern feel to it, of course the old browsers aren’t supported, but all the moderns ones are, so it’s not a big deal.
The clipboard method lives in the navigator: navigator.clipboard.writeText(), and it has a writeText('foo') method that takes a string as its parameter, which is then written into the clipboard. It returns a promise, so async functions can be used to deal with it.
The process is much simpler:
Here’s a small React app that copies using the clipboard API:
import React from 'react'
const CopyApp = () => {
const textRef = React.useRef(null)
const [copyState, setCopyState] = React.useState('👈 Copy with that button')
const handleClick = async () => {
if (!textRef.current) return
const text = textRef.current.textContent // 1
try {
await navigator.clipboard.writeText() // 2 setCopyState('👍 Text copied')
} catch (error) {
setCopyState('🚫 Error happened')
}
}
return (
<div className="app">
<h1>Copy text with JavaScript</h1>
<div className="text-box" ref={textRef}>
Copyabe looking text!
</div>
<button onClick={handleClick}>Copy text</button>
<span className="copy-msg">{copyState}</span>
</div>
)
}
export default CopyAppNOTE: For some reason the copy doesn’t work in the CodeSandbox frame, but it does work if you view the demo page. It just errors out with an empty Error object.
Here are all the 4 methods the clipboard interface provides:
writeText()write()readText()read()To sun it up: writing doesn’t need permissions, reading does.
The execCommand method works on any browser and when initiated from Iframes, and what not, but the clipboard API is the way to go!
Also, the execCommand is deprecated, browsers probably won’t remove it any time soon, but you know, it’s on its way out.
Comments would go here, but the commenting system isn’t ready yet, sorry.