Mobile Safari: Javascript focus() method on inputfield only works with click?

matt picture matt · Aug 30, 2012 · Viewed 121.4k times · Source

I have a simple input field like this.

<div class="search">
   <input type="text" value="y u no work"/>
</div>​

And I'm trying to focus() it inside a function. So inside of a random function (doesn't matter what function it is) I have this line …

$('.search').find('input').focus();

This works just fine on every Desktop whatsoever.

However it doesn't work on my iPhone. The field is not getting focused and the keyboard is not shown on my iPhone.

For testing purposes and to show you guys the problem I did a quick sample:

$('#some-test-element').click(function() {
  $('.search').find('input').focus(); // works well on my iPhone - Keyboard slides in
});

setTimeout(function() {
  //alert('test'); //works
  $('.search').find('input').focus(); // doesn't work on my iPhone - works on Desktop
}, 5000);​

Any idea why the focus() wouldn't work with the timeout function on my iPhone.

To see the live example, test this fiddle on your iPhone. http://jsfiddle.net/Hc4sT/

Update:

I created the exact same case as I'm currently facing in my current project.

I have a select-box that should — when "changed" — set the focus to the input field and slide-in the kexboard on the iphone or other mobile devices. I found out that the focus() is set correctly but the keyboard doesn't show up. I need the keyboard to show up.

Answer

Gregory Magarshak picture Gregory Magarshak · May 17, 2013

Actually, guys, there is a way. I struggled mightily to figure this out for [LINK REMOVED] (try it on an iPhone or iPad).

Basically, Safari on touchscreen devices is stingy when it comes to focus()ing textboxes. Even some desktop browsers do better if you do click().focus(). But the designers of Safari on touchscreen devices realized it's annoying to users when the keyboard keeps coming up, so they made the focus appear only on the following conditions:

1) The user clicked somewhere and focus() was called while executing the click event. If you are doing an AJAX call, then you must do it synchronously, such as with the deprecated (but still available) $.ajax({async:false}) option in jQuery.

2) Furthermore -- and this one kept me busy for a while -- focus() still doesn't seem to work if some other textbox is focused at the time. I had a "Go" button which did the AJAX, so I tried blurring the textbox on the touchstart event of the Go button, but that just made the keyboard disappear and moved the viewport before I had a chance to complete the click on the Go button. Finally I tried blurring the textbox on the touchend event of the Go button, and this worked like a charm!

When you put #1 and #2 together, you get a magical result that will set your login forms apart from all the crappy web login forms, by placing the focus in your password fields, and make them feel more native. Enjoy! :)