57

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

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

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

示例 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>

〜类似〜所以问题:

4

6 回答 6

84

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

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

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

2012 年 8 月更新:

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

于 2011-09-07T10:13:38.340 回答
6

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

于 2012-09-11T15:46:12.027 回答
2

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

于 2013-07-04T14:27:05.757 回答
0

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

于 2012-06-16T00:14:55.657 回答
0

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

添加 FastClick.js 后,iOS 中会发生这种情况: .focus() 仅在被附加到事件的函数激活时才有效。但是焦点也是移动 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();
    }
});

希望这对那里的人有用,我花了两个小时才弄清楚这一点。

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

Template.templateName.events({
    "click button":function(){
        $("body").append("<input class='created' type='tel'>");
        $("input.created").focus();
    }
});
于 2013-09-08T06:47:38.697 回答
-9

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

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

于 2013-09-13T20:46:15.857 回答