Reading and copying selected text to clipboard using JavaScript
Updated: Nov 6th, 2015
Ask most developers how to copy the contents of a user selection to
clipboard, and they'll mention the need for Flash (hence the popularity of
scripts such as
Zeroclipboard). However, an adjustment in that thinking is now due with
recent improvements in browser support for the key piece of technology in
JavaScript that makes copying to clipboard possible on its own-
document.execCommand()
. Supported in IE9+, Firefox 41+, and Chrome
42+, this JavaScript method finally brings native cut/copy support to
browsers themselves. In this tutorial, we'll see how to read the textual
contents of a user selection, dynamically select some text on the page, and last
but not least, copy whatever is selected to clipboard, all using just
JavaScript. We're entering a Flash free zone now!
Retrieving the text contents of the user selection
Lets start at the top, retrieving what the user has selected on
the page as far as any textual contents. For this we use
window.getSelection()
, a method supported in all modern browsers and
IE9+:
function getSelectionText(){ var selectedText = "" if (window.getSelection){ // all modern browsers and IE9+ selectedText = window.getSelection().toString() } return selectedText }
window.getSelection()
returns the currently
selected text on the page and returns a
Selection
object containing that data. To retrieve the actual text,
we use toString()
to turn it into a string. The following example
calls our function getSelectionText()
whenever the user mouses up
over the document so see what (if anything) the user has selected:
document.addEventListener('mouseup', function(){ var thetext = getSelectionText() if (thetext.length > 0){ // check there's some text selected console.log(thetext) // logs whatever textual content the user has selected on the page } }, false)
We check first that there's some text selected, as if the user simply clicked on the page, there will be none.
Selecting and reading the text contents of non form elements on the page
Moving on, instead of simply retrieving what the user has
selected, we can also take charge and dynamically select then retrieve what we
want on the page instead, such as the contents of a specific DIV. This is very
different from simply using an element's innerHTML
or
innerText
property to get its contents; we want to actually select
that content via JavaScript, which opens up other possible operations such as
copying it to the user's clipboard.
To select the textual contents of an non form field
element, we start by creating a new
Range object and setting it to encompass the desired element. Then, add the
range to the Selection
object to actually select it. Lets see
exactly how this works with a function that dynamically selects an element's
textual contents based on the element passed into it:
function selectElementText(el){ var range = document.createRange() // create new range object range.selectNodeContents(el) // set range to encompass desired element text var selection = window.getSelection() // get Selection object from currently user selected text selection.removeAllRanges() // unselect any user selected text (if any) selection.addRange(range) // add range to Selection object to select it }
To create a
Selection
object with which to add a range to, we use
window.getSelection()
; since this method by default returns the user
selected text (if any), we call its removeAllRanges()
method
immediately afterwards to clear the slate. Then, we go about creating a blank
range, zeroing in on the element's content to select using
range.selectNodeContents()
, before adding that range to the
Selection
object to select it.
Once we've selected the text we wish to read, we then turn to
our previous getSelectionText()
method to read the selected
element's contents, for example:
"My mama always said, 'Life was like a box of chocolates. You never know what you're gonna get.'" -Forrest
The code:
var para = document.getElementById('para') selectElementText(para) // select the element's text we wish to read var paratext = getSelectionText() // read the user selection alert(paratext) // alerts "My mama always says..."
Selecting and reading the contents of form elements such as INPUT text or TEXTAREA
For selecting and reading form related field values such as
INPUT text and TEXTAREA, the process differs from selecting regular text. Most
of us already know to select the entire value of a form field, we could just use
inputElement.select()*
, and to retrieve that value, probe
inputElement.value
. However, there's also programmatically selecting a
portion of the field's value and getting that value back. Lets see how to do
that.
- Programmatically selecting a portion of a field's value
To dynamically select a portion of an INPUT text or TEXTAREA
element, use
formElement.setSelectionRange()
to indicate the starting and ending
index of the desired selection within the field:
var emailfield = document.getElementById("email") emailfield.focus() // this is necessary in most browsers before setSelectionRange() will work emailfield.setSelectionRange(0, 5) // select first 5 characters of input field emailfield.setSelectionRange(5, emailfield.value.length) // select the 5th to last characters of input field
Note that the 2nd parameter of
formElement.setSelectionRange()
should be the index of the ending
character to select plus 1, so to select the first 5 characters of a form
field, the ending index value to enter should be 5, or 4 (the index of the 5th
character) plus 1.
*Note:
In iOS devices (as of iOS9), using inputElement.select()
to
quickly select all of a form element's contents doesn't seem to work.
However, using inputElement.setSelectionRange()
does. So the
following selects all of a form field's text across browsers and devices:
inputElement.setSelectionRange(0, inputElement.value.length)
- Reading the selected portion of a field's value
Regardless of how a portion of the form field's value is selected, whether by
using setSelectionRange()
to dynamically select that portion, or
the user dragging his/her mouse to make a user defined selection, the way to
retrieve the selection is to get the indices of the selection's starting and
ending character, then extracting that portion from the form field's value using
them. We can get the indices of the active selection using:
formElement.selectionStart
: The index of the selected text's first character. If no text is selected, this contains the index of the character that follows the input cursor.formElement.selectionEnd
: The index of the selected text's last character. If no text is selected, this contains the index of the character that follows the input cursor.
The above properties are especially useful in getting any user selected text from a form field where the indices of the selection isn't already known. The following demo echoes what the user has selected from a TEXTAREA using these properties:
Demo (select some text inside textarea):
Output:
The code:
<textarea id="quote" cols="50" rows="5"> Some text here </textarea> <div id="output"></div> <script> var quotearea = document.getElementById('quote') var output = document.getElementById('output') quotearea.addEventListener('mouseup', function(){ if (this.selectionStart != this.selectionEnd){ // check the user has selected some text inside field var selectedtext = this.value.substring(this.selectionStart, this.selectionEnd) output.innerHTML = selectedtext } }, false) </script>
We attach a "mouseup
" event to the target TEXTAREA to listen for
when the user mouses up inside it. Inside the event handler function, to detect
what the user has selected, first, we check whether the TEXTAREA's
selectionStart
and selectionEnd
properties contain different values- if they are
the same, it means nothing has been selected, in which case they both point to
the index of the character that follows the input cursor. If their values are
different, we proceed with mapping the selected text's indices to the value of
the form field value to derive the actual selected text, using
formElement.value.substring()
.
Copying the selected text to user clipboard
Ok, now that the nitty gritty of how to read what was selected on the page is
taken care of, whether on the page in general, or inside a specific DIV or form
element, we can move on to the next pressing issue, actually copying that
content to clipboard. As alluded to at the start of the tutorial, it comes down
to using the method
document.execCommand()
to execute a command to "copy" (or "cut") the
text to clipboard:
function copySelectionText(){ var copysuccess // var to check whether execCommand successfully executed try{ copysuccess = document.execCommand("copy") // run command to copy selected text to clipboard } catch(e){ copysuccess = false } return copysuccess }
The key here is the line document.execCommand("copy")
, which
actually performs the action to copy whatever is currently selected on the page
to the clipboard. To detect whether the browser supports the execCommand()
method properly, we put the operation inside a try/catch()
block;
if the call to execCommand()
fails, we know the browser doesn't
support this method.
We can use our newly conjured copySelectionText()
function with
any of the previous methods for selecting/ retrieving some text to then copy it
to clipboard. For example, the snippet below would copy whatever the user has
selected on the page when the user mouses up over the document:
document.body.addEventListener('mouseup', function(){ var copysuccess = copySelectionText() // copy user selected text to clipboard }, false)
We can refine this process though to only perform a "copy" action if the user selection actually contains some data; if the user simply clicks on the page without highlighting anything for example, no data is selected, in which case the copy action should be aborted. This can be done simply by looking at what was selected by the user beforehand:
document.body.addEventListener('mouseup', function(){ var selected = getSelectionText() // call getSelectionText() to see what was selected if (selected.length > 0){ // if selected text length is greater than 0 var copysuccess = copySelectionText() // copy user selected text to clipboard } }, false)
Time for a live demo now. Try selecting any text inside the following paragraph to see its contents copied to clipboard (press "Ctrl V" afterwards to paste and confirm). I've also added a tooltip that shows up temporarily to indicate success each time:
Demo (select any text inside the paragraph below to copy it to clipboard):
"To enjoy good health, to bring true happiness to one's family, to bring peace to all, one must first discipline and control one's own mind. If a man can control his mind he can find the way to Enlightenment, and all wisdom and virtue will naturally come to him." -Buddha
The code:
createtooltip() // create tooltip by calling it ONCE per page. See "Note" below var buddhaquote = document.getElementById('buddhaquote') buddhaquote.addEventListener('mouseup', function(e){ var selected = getSelectionText() // call getSelectionText() to see what was selected if (selected.length > 0){ // if selected text length is greater than 0 var copysuccess = copySelectionText() // copy user selected text to clipboard showtooltip(e) } }, false)
Note: Click here for the source to the tooltip function.
Copying the selected form field value to user clipboard
Moving on, we can easily perform the same hat trick on form field values. In the next example we add a control next to an INPUT text field to let users quickly copy its value:
Demo:
The code:
<script> function copyfieldvalue(e, id){ var field = document.getElementById(id) field.focus() field.setSelectionRange(0, field.value.length) var copysuccess = copySelectionText() if (copysuccess){ showtooltip(e) } } </script> <fieldset style="max-width:600px"> <legend>Share this tutorial</legend> <input id="url" type="text" size="60" value="http://www.javascriptkit.com/javatutors/copytoclipboard.shtml" /> <a href="#" onClick="copyfieldvalue(event, 'url');return false">Copy</a> </fieldset>
Copying a DIV's contents to clipboard
And finally, just for good measure, lets also see an example of auto selecting and copying a DIV's contents to clipboard upon clicking on it:
Demos (click on any of the quotes below to select its contents):
The code:
<div id="motivatebox" style="overflow: hidden; margin: 1em auto"> <div class="motivate"> "Just when the caterpillar thought the world was ending, he turned into a butterfly." --Proverb </div> <div class="motivate"> "Great minds discuss ideas; average minds discuss events; small minds discuss people." --Eleanor Roosevelt </div> <div class="motivate"> "No one can make you feel inferior without your consent." --Eleanor Roosevelt </div> </div> <script> var motivatebox = document.getElementById('motivatebox') motivatebox.addEventListener('mouseup', function(e){ var e = e || event // equalize event object between modern and older IE browsers var target = e.target || e.srcElement // get target element mouse is over if (target.className == 'motivate'){ selectElementText(target) // select the element's text we wish to read var copysuccess = copySelectionText() if (copysuccess){ showtooltip(e) } } }, false) </script>
Nothing new here- we simply monitor the "mouseup
"
event of the quotes DIVs' shared parent container to detect when the user has
clicked on one of those inner DIVs. When that happens, we select the DIV"s
contents before copying it to clipboard using the functions created earlier.
In Conclusion
As you can see, reading, and more importantly, copying text to the clipboard can now be a fully JavaScript affair. With Flash falling out of favour fast with browsers and users alike, this is good news indeed. All of the examples above work in IE9+, Firefox 41+, and Chrome 42+.
End of Tutorial