移动 Safari:输入字段上的 Javascript focus() 方法仅适用于单击?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12204571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mobile Safari: Javascript focus() method on inputfield only works with click?
提问by matt
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 …
我正在尝试focus()
在一个函数中使用它。所以在一个随机函数里面(不管它是什么函数)我有这条线......
$('.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.
但是它在我的 iPhone 上不起作用。该字段未聚焦,并且我的 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.
知道为什么focus()
我的 iPhone 上的超时功能不起作用。
To see the live example, test this fiddle on your iPhone. http://jsfiddle.net/Hc4sT/
要查看现场示例,请在您的 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.
我有一个选择框——当“改变”时——将焦点设置到输入字段并滑入 iPhone 或其他移动设备上的 kexboard。我发现 focus() 设置正确,但键盘没有显示。我需要键盘出现。
回答by Gregory Magarshak
Actually, guys, there is a way. I struggled mightily to figure this out for [LINK REMOVED] (try it on an iPhone or iPad).
其实,伙计们,有办法。我费了很大劲才为 [LINK REMOVED] 弄清楚了这一点(在 iPhone 或 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:
基本上,触摸屏设备上的 Safari 在focus()
处理文本框时很吝啬。如果你这样做,甚至一些桌面浏览器也会做得更好click().focus()
。但触屏设备上的 Safari 设计者意识到,当键盘不断出现时,用户会很烦,所以他们只关注以下情况:
1) The user clicked somewhere and focus()
was called while executing the click event. If you are doing an AJAX call, then you mustdo it synchronously, such as with the deprecated (but still available) $.ajax({async:false})
option in jQuery.
1) 用户点击某处并focus()
在执行点击事件时被调用。如果您正在执行 AJAX 调用,那么您必须同步执行,例如使用$.ajax({async:false})
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!
2) 此外——这个让我忙了一段时间——focus()
如果当时关注其他一些文本框,似乎仍然不起作用。我有一个执行 AJAX 的“Go”按钮,所以我尝试touchstart
在 Go 按钮事件上模糊文本框,但这只会使键盘消失并在我有机会完成点击 Go 按钮之前移动了视口. 最后,我尝试touchend
在 Go 按钮事件上模糊文本框,这就像一个魅力!
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! :)
当您将#1 和#2 放在一起时,您会得到一个神奇的结果,它将您的登录表单与所有蹩脚的网络登录表单区分开来,将焦点放在您的密码字段中,并使它们感觉更原生。享受!:)
回答by Raine Revere
A native javascript implementation of WunderBart's answer.
WunderBart 答案的原生 javascript 实现。
Disable auto zoom using font size.
使用字体大小禁用自动缩放。
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)
}
回答by WunderBart
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 switchfocus 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 fakeinput 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.
我最近遇到了同样的问题。我找到了一个显然适用于所有设备的解决方案。您不能以编程方式进行异步焦点,但是当其他一些输入已经聚焦时,您可以将焦点切换到目标输入。因此,您需要做的是创建、隐藏、附加到 DOM 并将假输入聚焦在触发器事件上,并且当异步操作完成时,只需在目标输入上再次调用焦点即可。这是一个示例片段 - 在您的手机上运行它。
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>
回答by DeBraid
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
.
我有一个带有图标的搜索表单,单击时会清除文本。然而,这个问题(在移动和平板电脑)是,键盘会崩溃/隐藏,因为click
删除事件focus
从取出input
。
Goal: after clearing the search form (clicking/tapping on x-icon) keep the keyboard visible!
目标:清除搜索表单(单击/点击 x 图标)后,保持键盘可见!
To accomplish this, apply stopPropagation()
on the event like so:
要做到这一点,请stopPropagation()
像这样应用事件:
function clear ($event) {
$event.preventDefault();
$event.stopPropagation();
self.query = '';
$timeout(function () {
document.getElementById('sidebar-search').focus();
}, 1);
}
And the HTML form:
和 HTML 表单:
<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>
回答by istvan makary
This solution works well, I tested on my phone:
此解决方案效果很好,我在手机上进行了测试:
document.body.ontouchend = function() { document.querySelector('[name="name"]').focus(); };
enjoy
请享用
回答by martinmose
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:
我正在使用 AngularJS,所以我创建了一个指令来解决我的问题:
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.
看起来您正在使用 jQuery,所以我不知道该指令是否有帮助。
回答by Alex
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...
我很困惑为什么你说这不起作用,因为你的 JSFiddle 工作得很好,但无论如何这是我的建议......
Try this line of code in your SetTimeOut function on your click event:
在单击事件的 SetTimeOut 函数中尝试以下代码行:
document.myInput.focus();
myInput correlates to the name attribute of the input tag.
myInput 与输入标签的名称属性相关。
<input name="myInput">
And use this code to blur the field:
并使用此代码模糊字段:
document.activeElement.blur();
回答by nishan mk
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.
请尝试使用 on-tap 而不是 ng-click 事件。我有这个问题。我通过在搜索表单标签内制作我的清除搜索框按钮并通过点击替换清除按钮的 ng-click 来解决它。它现在工作正常。