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

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.

This question is related to javascript jquery iphone input focus

The answer is


I have a search form with an icon that clears the text when clicked. However, the problem (on mobile & tablets) was that the keyboard would collapse/hide, as the click event removed focus was removed from the input.

text search input with close icon

Goal: after clearing the search form (clicking/tapping on x-icon) keep the keyboard visible!

To accomplish this, apply stopPropagation() on the event like so:

function clear ($event) {
    $event.preventDefault();
    $event.stopPropagation();
    self.query = '';
    $timeout(function () {
        document.getElementById('sidebar-search').focus();
    }, 1);
}

And the HTML form:

<form ng-controller="SearchController as search"
    ng-submit="search.submit($event)">
        <input type="search" id="sidebar-search" 
            ng-model="search.query">
                <span class="glyphicon glyphicon-remove-circle"
                    ng-click="search.clear($event)">
                </span>
</form>

A native javascript implementation of WunderBart's answer.

function onClick() {

  // create invisible dummy input to receive the focus first
  const fakeInput = document.createElement('input')
  fakeInput.setAttribute('type', 'text')
  fakeInput.style.position = 'absolute'
  fakeInput.style.opacity = 0
  fakeInput.style.height = 0
  fakeInput.style.fontSize = '16px' // disable auto zoom

  // you may need to append to another element depending on the browser's auto 
  // zoom/scroll behavior
  document.body.prepend(fakeInput)

  // focus so that subsequent async focus will work
  fakeInput.focus()

  setTimeout(() => {

    // now we can focus on the target input
    targetInput.focus()

    // cleanup
    fakeInput.remove()
    
  }, 1000)

}

Other References: Disable Auto Zoom in Input "Text" tag - Safari on iPhone


UPDATE

I also tried this, but to no avail:

$(document).ready(function() {
$('body :not(.wr-dropdown)').bind("click", function(e) {
    $('.test').focus();
})
$('.wr-dropdown').on('change', function(e) {
    if ($(".wr-dropdow option[value='/search']")) {
        setTimeout(function(e) {
            $('body :not(.wr-dropdown)').trigger("click");
        },3000)         
    } 
}); 

});

I am confused as to why you say this isn't working because your JSFiddle is working just fine, but here is my suggestion anyway...

Try this line of code in your SetTimeOut function on your click event:

document.myInput.focus();

myInput correlates to the name attribute of the input tag.

<input name="myInput">

And use this code to blur the field:

document.activeElement.blur();

I managed to make it work with the following code:

event.preventDefault();
timeout(function () {
    $inputToFocus.focus();
}, 500);

I'm using AngularJS so I have created a directive which solved my problem:

Directive:

angular.module('directivesModule').directive('focusOnClear', [
    '$timeout',
    function (timeout) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var id = attrs.focusOnClear;
                var $inputSearchElement = $(element).parent().find('#' + id);
                element.on('click', function (event) {
                    event.preventDefault();
                    timeout(function () {
                        $inputSearchElement.focus();
                    }, 500);
                });
            }
        };
    }
]);

How to use the directive:

<div>
    <input type="search" id="search">
    <i class="icon-clear" ng-click="clearSearchTerm()" focus-on-clear="search"></i>
</div>

It looks like you are using jQuery, so I don't know if the directive is any help.


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! :)


Try this:

input.focus();
input.scrollIntoView()

This solution works well, I tested on my phone:

document.body.ontouchend = function() { document.querySelector('[name="name"]').focus(); };

enjoy


Please try using on-tap instead of ng-click event. I had this issue. I resolved it by making my clear-search-box button inside search form label and replaced ng-click of clear-button by on-tap. It works fine now.


I faced the same issue recently. I found a solution that apparently works for all devices. You can't do async focus programmatically but you can switch focus to your target input when some other input is already focused. So what you need to do is create, hide, append to DOM & focus a fake input on trigger event and, when the async action completes, just call focus again on the target input. Here's an example snippet - run it on your mobile.

edit:

Here's a fiddle with the same code. Apparently you can't run attached snippets on mobiles (or I'm doing something wrong).

_x000D_
_x000D_
var $triggerCheckbox = $("#trigger-checkbox");_x000D_
var $targetInput = $("#target-input");_x000D_
_x000D_
// Create fake & invisible input_x000D_
var $fakeInput = $("<input type='text' />")_x000D_
  .css({_x000D_
    position: "absolute",_x000D_
    width: $targetInput.outerWidth(), // zoom properly (iOS)_x000D_
    height: 0, // hide cursor (font-size: 0 will zoom to quarks level) (iOS)_x000D_
    opacity: 0, // make input transparent :]_x000D_
  });_x000D_
_x000D_
var delay = 2000; // That's crazy long, but good as an example_x000D_
_x000D_
$triggerCheckbox.on("change", function(event) {_x000D_
  // Disable input when unchecking trigger checkbox (presentational purpose)_x000D_
  if (!event.target.checked) {_x000D_
    return $targetInput_x000D_
      .attr("disabled", true)_x000D_
      .attr("placeholder", "I'm disabled");_x000D_
  }_x000D_
_x000D_
  // Prepend to target input container and focus fake input_x000D_
  $fakeInput.prependTo("#container").focus();_x000D_
_x000D_
  // Update placeholder (presentational purpose)_x000D_
  $targetInput.attr("placeholder", "Wait for it...");_x000D_
_x000D_
  // setTimeout, fetch or any async action will work_x000D_
  setTimeout(function() {_x000D_
_x000D_
    // Shift focus to target input_x000D_
    $targetInput_x000D_
      .attr("disabled", false)_x000D_
      .attr("placeholder", "I'm alive!")_x000D_
      .focus();_x000D_
_x000D_
    // Remove fake input - no need to keep it in DOM_x000D_
    $fakeInput.remove();_x000D_
  }, delay);_x000D_
});
_x000D_
label {_x000D_
  display: block;_x000D_
  margin-top: 20px;_x000D_
}_x000D_
_x000D_
input {_x000D_
  box-sizing: border-box;_x000D_
  font-size: inherit;_x000D_
}_x000D_
_x000D_
#container {_x000D_
  position: relative;_x000D_
}_x000D_
_x000D_
#target-input {_x000D_
  width: 250px;_x000D_
  padding: 10px;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>_x000D_
<div id="container">_x000D_
  <input type="text" id="target-input" placeholder="I'm disabled" />_x000D_
_x000D_
  <label>_x000D_
    <input type="checkbox" id="trigger-checkbox" />_x000D_
    focus with setTimetout_x000D_
   </label>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to input

Angular 4 - get input value React - clearing an input value after form submit Min and max value of input in angular4 application Disable Button in Angular 2 Angular2 - Input Field To Accept Only Numbers How to validate white spaces/empty spaces? [Angular 2] Can't bind to 'ngModel' since it isn't a known property of 'input' Mask for an Input to allow phone numbers? File upload from <input type="file"> Why does the html input with type "number" allow the letter 'e' to be entered in the field?

Examples related to focus

How to remove focus from input field in jQuery? Set element focus in angular way Bootstrap button - remove outline on Chrome OS X How can I set focus on an element in an HTML form using JavaScript? Set Focus on EditText Mobile Safari: Javascript focus() method on inputfield only works with click? Correct way to focus an element in Selenium WebDriver using Java Prevent the keyboard from displaying on activity start What are some reasons for jquery .focus() not working? How can I set the focus (and display the keyboard) on my EditText programmatically