15

I can't work out why I can't get the the content of a textarea to be selected when the textarea receives focus.

Please visit a live example here: http://jsfiddle.net/mikkelbreum/aSvst/1

Using jQuery, this is my code. (IN SAFARI) It makes the text selected in case of the click event, but not the focus event:

$('textarea.automarkup')
.mouseup(function(e){
    // fixes safari/chrome problem
    e.preventDefault();
})
.focus(function(e){
    $(this).select();
})
.click(function(e){
    $(this).select();
});
mikkelbreum
  • 3,021
  • 9
  • 38
  • 41
  • 3
    That sounds like a recipe for wiping out all the content when someone tries to edit it … painful. A triple click will select the content of a text area in most browsers (and most other applications). I suggest sticking to standard UI conventions. – Quentin Jun 01 '11 at 12:41
  • the content is not supposed to be edited, just copied. – mikkelbreum Jun 01 '11 at 12:43
  • 1
    but you've got a point.. however, all that aside, I would like to find out what's going on with Safari and the firing of events here.. (see my note on the jsfiddle page) – mikkelbreum Jun 01 '11 at 12:44
  • A textarea is designed for editing content. Use something designed to give output, not request input. Possibly with a Flash based "Copy this to clipboard" button. – Quentin Jun 01 '11 at 12:45
  • 3
    As far as I'm concerned, Flash is dead. IMO, a textarea is ok for giving a raw text for copying, and certainly less evil that using flash. But again, I appreciate your input, but please let me hear from someone regarding the actual problem stated in the question.. – mikkelbreum Jun 01 '11 at 12:48
  • does safari force the textbox to not select it's text on focus (overriding the javascript request) in order to prevent the potential problem that Quentin points out? anyone knows? – mikkelbreum Jun 01 '11 at 12:50
  • 2
    I know it's been a while since this post, but if anyone is worried about the user modifying the text while trying to copy it, you can just add `readonly` as an attribute in the ` – VictorKilo Apr 25 '12 at 22:10

6 Answers6

35

The simplest thing to do is to combine your existing code with a timer, since the focus event is generally too early in WebKit:

jsFiddle example: http://jsfiddle.net/NWaav/2/

Code:

$('textarea.automarkup').focus(function() {
    var $this = $(this);

    $this.select();

    window.setTimeout(function() {
        $this.select();
    }, 1);

    // Work around WebKit's little problem
    function mouseUpHandler() {
        // Prevent further mouseup intervention
        $this.off("mouseup", mouseUpHandler);
        return false;
    }

    $this.mouseup(mouseUpHandler);
});
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • But the line $this.unbind("mouseup"); seems to be unnecessary, and maybe not a good idea. returning false is enough. Why did you put that in? – mikkelbreum Jun 01 '11 at 19:58
  • @mikkelbreum: The unbind part is to allow the `mouseup` event to fire normally while the textarea is focussed. It's only necessary to suppress it the first time, when the textarea first receives the focus. Admittedly, if the focus has come via keyboard instead the first `mouseup` after that will be suppressed, which is not ideal, but unlikely to be a problem in practice. – Tim Down Jun 01 '11 at 23:18
  • 2
    `$this = $(this);` creates a global variable named $this. Use the 'var' keyword to limit the scope of this variable and prevent introducing a global variable: `var $this = $(this);` – Andy Ford Nov 01 '11 at 23:15
  • @AndyFord: Yes, I know. Typo. Thanks for pointing out the error. – Tim Down Nov 02 '11 at 01:06
3

Tim Down's answer got me close, but it still didn't work when clicking & dragging in Chrome, so I did this (Coffeescript).

$.fn.extend
    copyableInput: ->
        @.each ->
            $input = $(this)

            # Prevent the input from being edited (but allow it to be selected)
            $input.attr 'readonly', "readonly"

            if $input.is 'textarea'
                $input.unbind('focus').focus ->
                    input = $(this).select()
                    $input.data 'selected', true

                    setTimeout ->
                        input.select()
                    , 0

                # Work around WebKit's little problem
                $input.bind 'mousedown mouseup', (e) ->
                    $input.select()

                    if $input.data('selected') == true
                        e.preventDefault()
                        return false


                $input.unbind('blur').blur ->
                    $input.data 'selected', false

            else
                # Select all the text when focused (I'm intentionally using click for inputs: http://stackoverflow.com/questions/3150275/jquery-input-select-all-on-focus)
                $input.unbind('click').click ->
                    input = $(this).select();

                    setTimeout ->
                        input.select()
                    , 0
timmfin
  • 2,025
  • 1
  • 15
  • 14
3

This is the only thing that works in Safari. Focus won't work.

<script type="text/javascript">
function SelectAll(id)
{
    document.getElementById(id).focus();
    document.getElementById(id).select();
}
</script>

Textarea:<br>
<textarea rows="3" id="txtarea" onclick="SelectAll('txtarea');" onfocus="SelectAll('txtarea');" style="width:200px" >This text you can select all by clicking here </textarea>

Input TextBox:<br>
<input type="text" id="txtfld" onclick="SelectAll('txtfld');" style="width:200px" value = "This text you can select all" />
brunoais
  • 6,258
  • 8
  • 39
  • 59
Karl Laurentius Roos
  • 4,360
  • 1
  • 33
  • 42
1
$("textarea").on("focus", function(event) {
  event.preventDefault();
  setTimeout(function() { $(event.target).select(); }, 1); 
});

http://jsfiddle.net/xCrN6/2/

1

It seems that the focus event interferes with the select method. Call it after a short lag:

<textarea id="ta0" onfocus="
  var inp=this;
  setTimeout(function(){inp.select();},10);
">Here is some text</textarea>

Given this is for coping only, perhaps the textarea should be readonly.

RobG
  • 142,382
  • 31
  • 172
  • 209
-1

I don't have a Safari browser but I had the same issue with IE and using the following works there:

$(document).ready(function() {
    $('body').delegate('textarea.automarkup', 'focus', function(e) {
        var myText = $(this);
        var mytxt = myText.text();
        myText.text(mytxt + "\n event fired: " + e.type);
        myText.select();
    });
    $('body').delegate('textarea.automarkup', 'click', function(e) {
        var myText = $(this);
        var mytxt = myText.text();
        myText.text(mytxt + "\n event fired: " + e.type);
        myText.select();
    });
});

EDIT: After a bit more playing around I used:

$(document).ready(function(e) {
        $(document).delegate('textarea.automarkup', 'focus click', function(e) {
        var myText = $(this);
        var mytxt = myText.text();
        //myText.text(mytxt + "\n event fired: " + e.type);
        myText.select();
        e.stopImmediatePropagation(); 
        $('#igot').text(mytxt+e.type);
        return false;
    });
});

in this example: http://jsfiddle.net/MarkSchultheiss/aSvst/23/

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100