Javascript 移动 Safari 自动对焦文本字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6287478/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:07:30  来源:igfitidea点击:

Mobile Safari Autofocus text field

javascriptfocusmobile-safariautofocus

提问by boymc

In Mobile Safari I am unable to focus onto a text field after setting a delay period. I'm attaching some example code showcasing the issue. If, onclick of the button, you trigger .focus(), everything works as expected. If you hang the focus on a callback, like the setTimeout function, then it fails ONLY in mobile safari. In all other browsers, there is a delay, then the focus occurs.

在 Mobile Safari 中,我无法在设置延迟期后专注于文本字段。我附上了一些展示问题的示例代码。如果单击按钮时触发 .focus(),则一切正常。如果您将焦点挂在回调上,例如 setTimeout 函数,那么它只会在移动 safari 中失败。在所有其他浏览器中,有一个延迟,然后焦点发生。

Confusingly, the "focusin" event is triggered, even in mobile safari. This (and ~similar~ comments in SO) make me think that it's a mobile safari bug. Any guidance will be accepted.

令人困惑的是,即使在移动 safari 中,也会触发“focusin”事件。这(以及 ~ 类似 ~ SO 中的评论)让我认为这是一个移动 safari 错误。任何指导都将被接受。

I've tested in the emulator, and on iPhone 3GS/4 iOS4.

我已经在模拟器和 iPhone 3GS/4 iOS4 上进行了测试。

Example HTML:

示例 HTML:

<!DOCTYPE html> 
  <html lang='en'> 
    <head> 
      <title>Autofocus tests</title> 
      <meta content='width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0' name='viewport'> 
      <meta content='yes' name='apple-mobile-web-app-capable'> 
    </head> 
    <body>
      <h1> 
        Show keyboard without user focus and select text:
      </h1> 
      <p> 
        <button id='focus-test-button'> 
          Should focus on input when you click me after .5 second
        </button> 
        <input id='focus-test-input' type='number' value='20'> 
      </p> 
      <script type="text/javascript"> 
        //<![CDATA[
        var button = document.getElementById('focus-test-button');
        var input  = document.getElementById('focus-test-input');

        input.addEventListener('focusin', function(event) {
          console.log('focus');
          console.log(event);
        });

        button.addEventListener('click', function() {
          // *** If triggered immediately - functionality occurs as expected
          // input.focus();
          // *** If called by callback - triggers the focusin event, but does not bring up keyboard or cursor
          var t = setTimeout("input.focus();",500);
        });
        //]]>
      </script>
    </body>
  </html>

~Similar~ SO questions:

~类似~ 所以问题:

回答by Matthew

I think this is a feature of mobile Safari rather than a bug. In our work on FastClick, my colleagues and I found that iOS will only allow focus to be triggered on other elements, from within a function, if the first function in the call stack was triggered by a non-programmatic event. In your case, the call to setTimeoutstarts a new call stack, and the security mechanism kicks in to prevent you from setting focus on the input.

我认为这是移动 Safari 的一个特性,而不是一个错误。在我们关于FastClick的工作中,我和我的同事发现,如果调用堆栈中的第一个函数是由非编程事件触发的,iOS 将只允许在函数内的其他元素上触发焦点。在您的情况下,调用将setTimeout启动一个新的调用堆栈,并且安全机制会启动以防止您将焦点设置在输入上。

Remember that on iOS setting focus on an input element brings up the keyboard - so all those web pages out there that set focus on an input element on page load, like Google does, would be extremely annoying to use on iOS. I guess Apple decided they had to do something to prevent this. So I disagree with @DA: this is a feature not a bug.

请记住,在 iOS 上将焦点设置在输入元素上会调出键盘 - 所以所有那些在页面加载时将焦点设置在输入元素上的网页,就像谷歌一样,在 iOS 上使用会非常烦人。我猜苹果决定他们必须采取措施来防止这种情况发生。所以我不同意@DA:这是一个功能而不是一个错误。

There's no known workaround for this, so you'll have to ditch the idea of using a delay.

对此没有已知的解决方法,因此您必须放弃使用延迟的想法。

Update August 2012:

2012 年 8 月更新:

As of iOS 5, handlers triggered by synthesised click events are allowed to trigger focus on input elements. Try the updated FastClick input focus example.

从 iOS 5 开始,允许由合成的点击事件触发的处理程序触发对输入元素的关注。尝试更新的FastClick 输入焦点示例

回答by Nick Saretzky

I was able to raise the keyboard by dispatching a click event only when the original event was from user interaction, not from setTimeout. I believe the outcome is that you can raise the keyboard from a touchend event, but still not from a timeout.

只有当原始事件来自用户交互而不是来自 setTimeout 时,我才能够通过调度点击事件来提升键盘。我相信结果是您可以从 touchend 事件中提升键盘,但仍然不能从超时中提升。

回答by elweilando

It seems that focus() works only, if you have added the site to the home screen and has opened the site with this link.

似乎只有在您将站点添加到主屏幕并使用此链接打开站点时,focus() 才有效。

回答by Marz

I was capable of making .focus() work by attaching it to two separate events in the events map but it's kind of hacky.

我能够通过将 .focus() 附加到事件映射中的两个单独事件来使其工作,但它有点笨拙。

After adding FastClick.js, this is what happens in iOS: .focus() only works when its activated by a function that is attached to an event. BUT focus is also an event in mobile safari's event map that is actually called when you use jQuery's .focus(). SO you can be redundant and attach another .focus() on the focus event of the object to make certain that it pulls through. This works especially well when you're creating an input in the DOM. I like programming for MeteorJS lately, this is what the solution looks like there:

添加 FastClick.js 后,这就是 iOS 中发生的情况: .focus() 仅在被附加到事件的函数激活时才起作用。但是 focus 也是 mobile safari 事件映射中的一个事件,当您使用 jQuery 的 .focus() 时,它实际上会被调用。所以你可以是多余的,并在对象的焦点事件上附加另一个 .focus() 以确保它通过。当您在 DOM 中创建输入时,这尤其有效。我最近喜欢为 MeteorJS 编程,这就是那里的解决方案:

Template.templateName.events({
    "click button":function(){
        Session.set("makeButtonVisible",true);
        $("input.created").focus();
    },
    "focus input.created":function(){
        $("input.created").focus();
    }
});

Hopefully this is useful to someone out there, took me like two hours to figure this one out.

希望这对那里的人有用,我花了两个小时才弄明白。

EDIT:Well, for MeteorJS in particular, you can't use Template.templateName.rendered function either because the .focus() must be invoked from an event. BUT for some reason when you add an input through jQuery you can focus on it inside the event. Guess that's the way to go. This is what I ended up doing:

编辑:嗯,特别是对于 MeteorJS,您不能使用 Template.templateName.rendered 函数,因为 .focus() 必须从事件中调用。但是由于某种原因,当您通过 jQuery 添加输入时,您可以在事件中关注它。猜猜这是要走的路。这就是我最终做的:

Template.templateName.events({
    "click button":function(){
        $("body").append("<input class='created' type='tel'>");
        $("input.created").focus();
    }
});

回答by dodysw

Adding to Matt answer. At least on Safari on iOS 5.1, this issue is fixed. Your FastClickworks, that is, synthesizing a click event won't fail focus. However this does not help people who want their single focus()code to work on all iOS versions, sigh.

添加到马特答案。至少在 iOS 5.1 上的 Safari 上,这个问题是固定的。你的FastClick作品,也就是合成一个点击事件不会使焦点失效。然而,这并不能帮助那些希望他们的单一focus()代码在所有 iOS 版本上工作的人,叹息。

回答by Dimash

You answered yourself. You need just trigger if you use Jquery. Change focus() on trigger("focus"); in any part of your code.

你自己回答。如果您使用 Jquery,您只需要触发。在触发器上更改焦点()(“焦点”);在您的代码的任何部分。

$("#searchField").trigger("focus");

$("#searchField").trigger("focus");