85

I have the following jQuery code (similar to this question) that works in Firefox and IE, but fails (no errors, just doesn't work) in Chrome and Safari. Any ideas for a workaround?

$("#souper_fancy").focus(function() { $(this).select() });
Community
  • 1
  • 1
user140550
  • 919
  • 2
  • 11
  • 21
  • I want exact behavior in safari of iPad/iPhone. This is not working in iPod/iPhone browsers. any clue. Below accepted answer is for Desktop based Chrome/safari only. – Anand Mar 29 '12 at 11:25
  • 5
    Note: The accepted answer here only solves half the problem. It makes the select work, but makes it difficult to then un-select it with subsequent clicks. A better solution can be found here: http://stackoverflow.com/questions/3380458/looking-for-a-better-workaround-to-chrome-select-on-focus-bug – SDC Sep 21 '12 at 10:44

9 Answers9

188

It's the onmouseup event that is causing the selection to get unselected, so you just need to add:

$("#souper_fancy").mouseup(function(e){
    e.preventDefault();
});
  • 3
    More ref on the bug here : http://code.google.com/p/chromium/issues/detail?id=4505 – Rajat Apr 28 '10 at 01:06
  • How to achieve the same using Prototype? – tehfink Apr 29 '11 at 02:59
  • You can also try binding to the 'click' event and avoid having to make two bindings. – gxc Feb 12 '12 at 07:26
  • @uglymunky Depending on what you're doing, binding to the click event won't work in all cases - after all, there's other means of selecting an input field than clicking on it, and you want those to work as well (e.g, tabbing in to it) – Tacroy Feb 27 '12 at 18:27
  • 2
    I want exact behavior in safari of iPad/iPhone. This is not working in iPod/iPhone browsers. any clue. – Anand Mar 29 '12 at 10:48
  • would you think this is because some event fired and causing the thing to be unselected (on ipad/iphone/android)? mine is on phonegap, and this .select() method is not working too – r4ccoon Jun 08 '12 at 00:36
  • iOS earlier than iOS6 does not allow programmatic focus of input elements in mobile safari / web views. ios6 adds an option KeyboardDisplayRequiresUserAction that can be set for UIWebViews – Luke Melia Oct 15 '12 at 03:47
  • Do what uglymunky suggests - bind to click: http://stackoverflow.com/a/3150370/3435345 – jrjensen May 07 '16 at 04:16
25
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});
Jason Sturges
  • 15,855
  • 14
  • 59
  • 80
Alex0007
  • 548
  • 7
  • 15
  • 3
    This is the best answer if your are trying to select text in a form field for a PhoneGap app running on Android. This gives a visual indication to the user that the text is selected, whereas the accepted answer does not. – BallisticPugh Aug 22 '13 at 16:28
4

This works fine for input type="text" elements. What kind of element is #souper_fancy?

$("#souper_fancy").focus(function() {
    $(this).select();
});
Joe Chung
  • 11,955
  • 1
  • 24
  • 33
  • it's a type="text" element. I tried $("input[type=text]") as well. Still not working with jQuery 1.3.2 in Safari. – user140550 Aug 13 '09 at 02:41
3

Just preventing default on mouseup causes the text selection to be ON at all times. The MOUSEUP event is responsible to clear the text selection. However, by preventing its default behaviour, you are unable to deselect the textusing the mouse.

To avoid that and get the text selection to work again, you can set a flag on FOCUS, read it from MOUSEUP and reset it so future MOUSEUP events will work as expected.

$("#souper_fancy").focus(function() {
    $(this).select();

    //set flag for preventing MOUSEUP event....
    $this.data("preventMouseUp", true);
});

$("#souper_fancy").mouseup(function(e) {
    var preventEvent = $this.data("preventMouseUp");

    //only prevent default if the flag is TRUE
    if (preventEvent) {
        e.preventDefault();
    }

    //reset flag so MOUSEUP event deselect the text
    $this.data("preventMouseUp", false);
});
Ben Wheeler
  • 6,788
  • 2
  • 45
  • 55
ThiagoPXP
  • 5,362
  • 3
  • 31
  • 44
2

Use setSelectionRange() inside of a callback to requestAnimationFrame():

$(document).on('focus', '._selectTextOnFocus', (e) => {
    var input = e.currentTarget;
    var initialType = e.currentTarget.type;

    requestAnimationFrame(() => {
        // input.select() is not supported on iOS
        // If setSelectionRange is use on a number input in Chrome it throws an exception,
        // so here we switch to type text first.
        input.type = "text";
        input.setSelectionRange(0, Number.MAX_SAFE_INTEGER || 9999);
        input.type = initialType;
    });
});

Use setSelectionRange() instead of select() since select() doesn't work in mobile Safari (see Programmatically selecting text in an input field on iOS devices (mobile Safari)).

It is necessary to wait using requestAnimationFrame before selecting the text, otherwise the element isn't correctly scrolled into view after the keyboard comes up on iOS.

When using setSelectionRange() it is important to set the input type to text, otherwise it may throw exceptions on Chrome (see selectionStart/selectionEnd on input type="number" no longer allowed in Chrome).

andrewh
  • 324
  • 4
  • 3
1

While this works for selecting it in IE, Firefox, Chrome, Safari, and Opera, it won't let you edit it by clicking a second time in Firefox, Chrome, and Safari. Not entirely sure, but I think this may be due to those 3 browsers re-issuing a focus event even though the field already has focus thus never allowing you to actually insert the cursor (since you're selecting it again), whereas in IE and Opera it appears it isn't doing that so the focus event didn't get fired again and thus the cursor gets inserted.

I found a better fix in this Stack post that doesn't have that problem and works in all browsers.

Community
  • 1
  • 1
johntrepreneur
  • 4,514
  • 6
  • 39
  • 52
1

This should work also in chrome:

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});
rubiwachs
  • 11
  • 1
1

Because there is flickering when you use setTimeout, there is another event based solution. This way the 'focus' event attach the 'mouseup' event and the event handler detach itself again.

    function selectAllOnFocus(e) {
    if (e.type == "mouseup") { // Prevent default and detach the handler
        console.debug("Mouse is up. Preventing default.");
        e.preventDefault();
        $(e.target).off('mouseup', selectAllOnFocus);
        return;
    }
    $(e.target).select();
    console.debug("Selecting all text");
    $(e.target).on('mouseup', selectAllOnFocus);
}

Then wire the first event

    $('.varquantity').on('focus', selectAllOnFocus);
0

If anyone comes again across this problem I got here a pure JS solution which is (at the moment) working on all browsers incl. mobile

<input type="text" value="Hello world..." onFocus="window.setTimeout(() => this.select());">

(without setTimeout() it's not working on Safari, mobile Safari and MS Edge)

Claudio
  • 207
  • 3
  • 4