Select all DIV text with single mouse click
Asked Answered
S

15

171

How to highlight/select the contents of a DIV tag when the user clicks on the DIV...the idea is that all of the text is highlighted/selected so the user doesn't need to manually highlight the text with the mouse and potentially miss a bit of the text?

For example, say we've got a DIV as below:

<div id="selectable">http://example.com/page.htm</div>

...and when the user clicks on any of that URL the whole URL text is highlighted so they can easily drag the selected text around in the browser, or copy the complete URL with a right click.

Thanks!

Scorbutic answered 23/7, 2009 at 17:11 Comment(0)
F
224

function selectText(containerid) {
    if (document.selection) { // IE
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>

Now you have to pass the ID as an argument, which in this case is "selectable", but it's more global, allowing you to use it anywhere multiple times without using, as chiborg mentioned, jQuery.

Firdausi answered 23/7, 2009 at 17:35 Comment(8)
BTW, you can easily turn this into a jQuery click event handler replacing document.getElementById('selectable') with this. Then you can add the functionality unobtrusively to several elements, for example several divs in a container: jQuery('#selectcontainer div').click(selectText);Crew
@DenisSadowski's solution doesn't trigger $.bind("copy",function(){}); :-(Dhu
This works fine on Chrome, FF, Safari (Mac) and Chrome and IE (Windows 9+, 8 not tested). But it does not seem to work on Safari on iPad Mini (iOS6) or iPhone 4, not sure about other iOS or Android.Proclitic
Per this article, the query if (window.getSelection) { should come first for Opera (quirksmode.org/dom/range_intro.html)Proclitic
This solution seems not to work in ie11. Any idea why?Subassembly
In Chrome version 36+ this will return an error "Discontiguous selection is not supported". The solution is to add window.getSelection().removeAllRanges(); before window.getSelection().addRange(range);Pullet
I found that this was selecting the text, but also invisible overflow on the right side. I solved this by appending .firstChild to the document.getElementById calls: range.selectNode(document.getElementById(containerid).firstChild); , which gets the text node.Akbar
CSS4 solution is very clean and elegant. somone posted this solution below on this page. .selectable{ -webkit-touch-callout: all; /* iOS Safari */ -webkit-user-select: all; /* Safari */ -khtml-user-select: all; /* Konqueror HTML */ -moz-user-select: all; /* Firefox */ -ms-user-select: all; /* Internet Explorer/Edge */ user-select: all; /* Chrome and Opera */ }Rembert
A
159

UPDATE 2017:

To select the node's contents call:

window.getSelection().selectAllChildren(
    document.getElementById(id)
);

This works on all modern browsers including IE9+ (in standards mode).

Runnable Example:

function select(id) {
  window.getSelection()
    .selectAllChildren(
      document.getElementById("target-div") 
    );
}
#outer-div  { padding: 1rem; background-color: #fff0f0; }
#target-div { padding: 1rem; background-color: #f0fff0; }
button      { margin: 1rem; }
<div id="outer-div">
  <div id="target-div">
    Some content for the 
    <br>Target DIV
  </div>
</div>

<button onclick="select(id);">Click to SELECT Contents of #target-div</button>

The original answer below is obsolete since window.getSelection().addRange(range); has been deprecated

Original Answer:

All of the examples above use:

    var range = document.createRange();
    range.selectNode( ... );

but the problem with that is that it selects the Node itself including the DIV tag etc.

To select the Node's text as per the OP question you need to call instead:

    range.selectNodeContents( ... )

So the full snippet would be:

    function selectText( containerid ) {

        var node = document.getElementById( containerid );

        if ( document.selection ) {
            var range = document.body.createTextRange();
            range.moveToElementText( node  );
            range.select();
        } else if ( window.getSelection ) {
            var range = document.createRange();
            range.selectNodeContents( node );
            window.getSelection().removeAllRanges();
            window.getSelection().addRange( range );
        }
    }
Alexandros answered 19/11, 2013 at 19:5 Comment(2)
You can also use this instead of getting the element based on the ID so long as it is within the element's click listener.Langford
This is the answer you all are looking for.Hooknosed
B
72

There is pure CSS4 solution:

.selectable{
    -webkit-touch-callout: all; /* iOS Safari */
    -webkit-user-select: all; /* Safari */
    -khtml-user-select: all; /* Konqueror HTML */
    -moz-user-select: all; /* Firefox */
    -ms-user-select: all; /* Internet Explorer/Edge */
    user-select: all; /* Chrome and Opera */

}

user-select is a CSS Module Level 4 specification, that is currently a draft and non-standard CSS property, but browsers support it well — see #search=user-select.

.selectable{
    -webkit-touch-callout: all; /* iOS Safari */
    -webkit-user-select: all; /* Safari */
    -khtml-user-select: all; /* Konqueror HTML */
    -moz-user-select: all; /* Firefox */
    -ms-user-select: all; /* Internet Explorer/Edge */
    user-select: all; /* Chrome and Opera */

}
<div class="selectable">
click and all this will be selected
</div>

Read more on user-select here on MDN and play with it here in w3scools

Bandsman answered 4/5, 2017 at 12:34 Comment(3)
+1 awesome awesome elegant solution! Tested Sept 2017 and it works flawlessly on FireFox and Chrome BUT NOT IN MICROSOFT EDGE!? Any ideas why not and how to fix that? thanks!Moises
Mino, thanks this worked! One click selects the whole element. However it makes it impossible to swipe-select a subset of the text. . . . Did you possibly mean -webkit-touch-callout: none;? I'm getting a warning for all. Anyway, what is that setting doing here? . . . @Moises in 2020 I'm seeing user-select work on MS Edge. Saner heads may have prevailed.Swagman
this doesn't work if any of the element's ancestors has the draggable attribute set. In FF and Safari. In Chrome it does workCalctufa
D
13

The answer of Neuroxik was really helpful. I had only a trouble with Chrome, because when I clicked on an external div, It did not work. I could solve it removing the old ranges before add the new range:

function selectText(containerid) {
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection()) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>
Denten answered 5/2, 2013 at 17:7 Comment(0)
W
11

For content editable stuff (not regular inputs, you need to use selectNodeContents (rather than just selectNode).

NOTE: All the references to "document.selection" and "createTextRange()" are for IE 8 and lower... You'll not likely need to support that monster if you're attempting to do tricky stuff like this.

function selectElemText(elem) {

    //Create a range (a range is a like the selection but invisible)
    var range = document.createRange();

    // Select the entire contents of the element
    range.selectNodeContents(elem);

    // Don't select, just positioning caret:
    // In front 
    // range.collapse();
    // Behind:
    // range.collapse(false);

    // Get the selection object
    var selection = window.getSelection();

    // Remove any current selections
    selection.removeAllRanges();

    // Make the range you have just created the visible selection
    selection.addRange(range);

}
Weathers answered 3/7, 2015 at 3:54 Comment(0)
C
6

Using a text area field, you could use this: (Via Google)

<form name="select_all">

    <textarea name="text_area" rows="10" cols="80" 
    onClick="javascript:this.form.text_area.focus();this.form.text_area.select();">

    Text Goes Here 

    </textarea>
</form>

This is how I see most websites do it. They just style it with CSS so it doesn't look like a textarea.

Country answered 23/7, 2009 at 17:21 Comment(1)
why not just this.focus();this.select();?Catania
A
6

try this, altn adding to oncontextmenu will gice quick access to extentions allowing input this way.

<div onclick='window.getSelection().selectAllChildren(this)' id="selectable">http://example.com/page.htm</div>
Access answered 27/4, 2022 at 7:1 Comment(0)
S
5

This snippet provides the functionality you require. What you need to do is add an event to that div that which activates fnSelect in it. A quick hack that you totally shouldn't do and possibly might not work, would look like this:

document.getElementById("selectable").onclick(function(){
    fnSelect("selectable");
});

Obviously assuming that the linked to snippet had been included.

Shotton answered 23/7, 2009 at 17:27 Comment(0)
F
5

I found it useful to wrap this function as a jQuery plugin:

$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

So, it becomes a reusable solution. Then you can do this:

<div onclick="$(this).selectText()">http://example.com/page.htm</div>

And it will selected test in the div.

Fuselage answered 5/11, 2013 at 20:8 Comment(1)
Remember to call window.getSelection().removeAllRanges(); as in Josillo's code. Also: I would advocate putting window.getSelect as the first option, since this is the HTML5 standard and document.selection is the old IE fallback for IE8 and earlier.Unalloyed
C
3

How about this simple solution? :)

<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">

Sure it is not div-construction, like you mentioned, but still it is worked for me.

Ceramics answered 11/12, 2014 at 21:51 Comment(1)
Concise solution, but this doesn't account for text in an element other than an input or textarea field.Discover
F
3

Niko Lay: How about this simple solution? :)

`<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">`

.....

Code before:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly">

Code after:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly" onclick="this.select();" id="selectable">

Just this part onclick="this.select();" id="selectable" in my code worked fine. Selects all in my code box with one mouse click.

Thanks for help Niko Lay!

Framework answered 22/10, 2015 at 6:47 Comment(0)
C
3

Easily achieved with the css property user-select set to all. Like this:

div.anyClass {
  user-select: all;
}
Caliche answered 21/1, 2018 at 18:41 Comment(0)
R
2

A solution, working also in case your element is part of an iframe

element.ownerDocument?.getSelection()?.selectAllChildren(element);
Romie answered 6/10, 2022 at 14:0 Comment(0)
F
0
$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

Above answer is not working in Chrome because addRange remove previous added range. I didnt find any solution for this beside fake selection with css.

Frizzy answered 9/1, 2014 at 9:12 Comment(1)
For someone this code may be helpful as I have tested & found it working in latest version of Chrome: $.fn.selectText = function () { return $(this).each(function (index, el) { if (document.selection) { var range = document.body.createTextRange(); range.moveToElementText(el); range.select(); } else if (window.getSelection) { var range = document.createRange(); range.selectNode(el); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } }); }Saintpierre
C
0
export const selectText = (containerId) => {
  let selection = window.getSelection()
  let myElement = document.getElementById(containerId)

  if (selection.rangeCount > 0) {
    selection.removeAllRanges()
  }

  let range = document.createRange()
  range.selectNode(myElement)
  selection.addRange(range)
}**The most simplest answer works in all browsers**
Clip answered 26/4, 2021 at 12:45 Comment(2)
Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you’ve made.Accommodation
Please consider explaining your answer so that everyone can understand it better.Sitnik

© 2022 - 2024 — McMap. All rights reserved.