42

I've got contenteditable div as below.

<div style=" border:solid 1px #D31444" contenteditable="true">12 some text...</div>

What I need is, when I click on the div, all the text will automatically get selected. Can you give me solution please?

angry kiwi
  • 10,730
  • 26
  • 115
  • 161
  • This answer provides the most 'correct' way to do what you want: http://stackoverflow.com/a/6150060/2703399 – josh Apr 28 '16 at 19:42

3 Answers3

58

This will do it. The timer is there for Chrome and Safari because in those browsers, the native browser behaviour that selects the whole element seems to trigger after the focus event, thereby overriding the effect of the selection code unless postponed until after the focus event:

var div = document.getElementById("editable");

div.onfocus = function() {
    window.setTimeout(function() {
        var sel, range;
        if (window.getSelection && document.createRange) {
            range = document.createRange();
            range.selectNodeContents(div);
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.body.createTextRange) {
            range = document.body.createTextRange();
            range.moveToElementText(div);
            range.select();
        }
    }, 1);
};
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • 1
    Shouldn't there be a way to do this with preventDefault or stopPropagation too? Using setTimeout seems kind of ugly because you have to break the call stack. – Adam May 09 '12 at 20:43
  • 1
    @Adam: I don't think so. You don't want to prevent the editable element from receiving focus, so `preventDefault()` is out. `stopPropagation()` only stops the event from propagating to the next target, which is not useful for this. – Tim Down May 09 '12 at 23:32
  • tim, why aren't you a moderator? – Lucas Sep 03 '12 at 07:46
  • @think123: Three reasons: I haven't put myself forward, I don't really want to and I don't know whether I'd do it well anyway. – Tim Down Sep 07 '12 at 14:14
  • This should be the accepted answer - it doesn't require an inline script. Can I ask what are the various compatibility reasons for the "getSelection", "createRange" property checks etc..? – jrz Nov 21 '12 at 15:20
  • 3
    @Jonz: `window.getSelection()` and `document.createRange()`, which are both now standardized, are supported in most browsers but not IE < 9. IE does have its own selection/range API though, accessed here via `document.body.createTextRange()`. – Tim Down Nov 21 '12 at 17:23
  • Thanks! I minified your function with UglifyJS2 also... `Element.prototype.SelectAll=function(d){d=this;var sel,range;window.getSelection&&document.createRange?(range=document.createRange(),range.selectNodeContents(d),sel=window.getSelection(),sel.removeAllRanges(),sel.addRange(range)):document.body.createTextRange&&(range=document.body.createTextRange(),range.moveToElementText(d),range.select())}` –  Nov 24 '15 at 11:00
  • @TimDown I want to set focus() and for some columns need to select text on focus. Unable to figure out these both on this function could you help on it. – k11k2 Jan 19 '18 at 04:56
56

Try this:

<div style="border:solid 1px #D31444"
     contenteditable="true"
     onclick="document.execCommand('selectAll',false,null)">12 some text...</div>

Update: Note that document.execCommand is now deprecated although it still works.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Danylo Mysak
  • 1,514
  • 2
  • 16
  • 22
  • 11
    This would be better done using the `focus` event, because using the click event will highlight everything whenever the user tries to click to position the caret. – Tim Down Sep 27 '10 at 16:58
  • 2
    Well, probably, but that depends on what the author of the question wants. – Danylo Mysak Sep 27 '10 at 17:41
  • 3
    I just tried this in Chrome Version 24.0.1312.57 OS X. Using jQuery 1.9.1, binding to the `focus` _does not_ work. Binding to the `click` event did select the text: `$('.editable').on('click', function () { document.execCommand('selectAll', false, null); });` – berto Feb 19 '13 at 17:54
  • After tinkering a bit more I noticed that the `focus` event does work, but there are subsequent events (positioning the cursor, maybe) that undo the selection. I tried `stopPropagation()`, but that didn't work for me. – berto Feb 19 '13 at 18:08
  • 5
    http://jsfiddle.net/rudiedirkx/MgASG/1/show/ might help? – Rudie Apr 04 '13 at 23:01
  • 5
    This doesn't work when the user navigates to the contenteditable div with the 'Tab' key. – Engin Yapici Nov 30 '14 at 19:10
  • @Rudie thank you! I'll have to look into the performance implications of this, but works perfectly for me! – Jordan Dec 09 '14 at 17:58
  • @berto is correct. Chrome doesn't handle `selectAll` on `focus` correctly, and I [filed an issue about it](https://code.google.com/p/chromium/issues/detail?id=508081). `click` works, but as Tim pointed out, usability suffers when the user wants to select only part of the text. – Dan Dascalescu Jul 08 '15 at 13:07
  • You cannot `focus` a div, unless you set its `tabindex` property. – Supreme Dolphin Feb 13 '16 at 20:48
  • The elegance of this answer is unparalleled for this task. – Umagon Jun 10 '16 at 20:26
7

The problem with focus event on a div is that it can't fire because it thinks a div should not be editable. Editable contents in the DOM are marked with tabindex in the background, so in order for your div to receive the onfocus event, you need to explicitly declare the div's tabindex property. HTML:

<div style=" border:solid 1px #D31444" contenteditable="true" tabindex="1" onfocus="document.execCommand('selectAll',false,null)" >12 some text...</div>

That should work with onfocus.

Supreme Dolphin
  • 2,248
  • 1
  • 14
  • 23
  • 3
    Doing this causes it to select the whole entire document. You can use the same code, but I recommend using a `setTimeout` for `150` ms so it won't select the whole document. Hope this helps you all! – Cameron Nov 15 '17 at 23:25
  • Rather than working around the workaround (see *'XY Problem'* on [Wikipedia](//w.wiki/MfS) & [Stack Exchange](//meta.stackexchange.com/q/66377)), use the ` – ashleedawg Aug 31 '21 at 07:59