移动 Safari: inputfield 上的 Javascript focus()方法只能通过 click 工作?

我有一个像这样的简单输入域。

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

我尝试在函数中对它进行 focus()。 所以在一个随机函数内部(不管是什么函数)我有这条线..。

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

这在任何桌面上都能正常工作。

但是它在我的 iPhone 上无法工作。该字段没有得到集中,键盘也没有显示在我的 iPhone 上。

为了测试的目的,为了向你们展示这个问题,我做了一个简单的例子:

$('#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);​

知道为什么 focus()不能在我的 iPhone 上使用超时功能吗。

要查看实时示例,请在您的 iPhone 上测试此小提琴

更新:

我创建了与我目前面临的项目完全相同的情况。

我有一个选择框,当“更改”时,它应该将焦点设置为输入字段,并将幻灯片放入 iphone 或其它移动设备的键盘。我发现焦点()设置正确,但键盘没有显示出来。我需要键盘出现。

153076 次浏览

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();

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

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.

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>

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).

var $triggerCheckbox = $("#trigger-checkbox");
var $targetInput = $("#target-input");


// Create fake & invisible input
var $fakeInput = $("<input type='text' />")
.css({
position: "absolute",
width: $targetInput.outerWidth(), // zoom properly (iOS)
height: 0, // hide cursor (font-size: 0 will zoom to quarks level) (iOS)
opacity: 0, // make input transparent :]
});


var delay = 2000; // That's crazy long, but good as an example


$triggerCheckbox.on("change", function(event) {
// Disable input when unchecking trigger checkbox (presentational purpose)
if (!event.target.checked) {
return $targetInput
.attr("disabled", true)
.attr("placeholder", "I'm disabled");
}


// Prepend to target input container and focus fake input
$fakeInput.prependTo("#container").focus();


// Update placeholder (presentational purpose)
$targetInput.attr("placeholder", "Wait for it...");


// setTimeout, fetch or any async action will work
setTimeout(function() {


// Shift focus to target input
$targetInput
.attr("disabled", false)
.attr("placeholder", "I'm alive!")
.focus();


// Remove fake input - no need to keep it in DOM
$fakeInput.remove();
}, delay);
});
label {
display: block;
margin-top: 20px;
}


input {
box-sizing: border-box;
font-size: inherit;
}


#container {
position: relative;
}


#target-input {
width: 250px;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container">
<input type="text" id="target-input" placeholder="I'm disabled" />


<label>
<input type="checkbox" id="trigger-checkbox" />
focus with setTimetout
</label>
</div>

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

Try this:

input.focus();
input.scrollIntoView()