Twitter Bootstrap模态框输入字段焦点

54

我有以下示例的模态表单:

<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn" data-toggle="modal">Launch demo modal</a>

<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Modal header</h3>
  </div>
  <div class="modal-body">
    Enter something: <input type="text" id="myInput">
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <button class="btn btn-primary">Save changes</button>
  </div>
</div>

弹出模态框后,我希望我的输入框能够获得焦点。
我尝试了自动聚焦和在 $('modal').shown() 事件中设置输入框焦点。它似乎会让输入框获得焦点(当输入框获得焦点时,我有另一个事件来显示标签),但实际上输入框并没有获得焦点,我必须按下 TAB 键才能再次将其聚焦。 我还尝试了类似以下的方法:

$(".modal").on('shown', function() {
    $(this).find("[autofocus]:first").focus();
});

为我的字段设置 autofocus:"autofocus" 属性提供了同样的效果。
我尝试过的所有方法都适用于模态框只是普通 div 的情况,它在页面加载时获得焦点。但是当模态框由按钮触发时 - 什么都不起作用(当然,我也改变了逻辑,当模态框只是普通 div 时,我可以在 onload 时聚焦它,当我通过按钮触发时,我会考虑并尝试相应地解决它)。

我想要的只是在模态框加载后,使字段集中,以便它具有闪烁的光标,用户可以开始输入。

唯一有效的方法是更改 bootstrap.js 本身,我在 bootstrap.js 模态框部分的某个位置放置了 $("#myInput").focus(),但是我忘记了它在哪里,并且第二个问题是 - 我认为更改 bootstrap.js API 不好,必须有更简单、更优雅的解决方案。请给我建议,谢谢 xD

更新:
首先,感谢您的帮助! 多亏您,我找出了我的问题是 Rails 问题。

这是我做的:
1). 运行命令 rails generate controller home index
2). app/views/home/index.htmlapp/assets/javascript/something.js 就像robertklep提供的这个 jsFiddle 一样:http://jsfiddle.net/JCaFp/
4). jquery-1.9.1.jsbootstrap.jsapp/assets/javascript/ 中(两者都是从网站上获取的,没有更改)
5). app/views/layouts/application.html.erb - 我想这个文件是我们解决问题的关键:

<!DOCTYPE html>
<html>
<head>
  <title>Udc</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

仍然无法正常工作。所有的js文件都已经被包含,但是当我在浏览器中打开我的模态框时,输入框会获取焦点但马上又失去了焦点。

我也尝试过这个方法:

  <%= javascript_include_tag "jquery" %>
  <%= javascript_include_tag "bootstrap" %>
  <%= javascript_include_tag "somehow" %>

依然是同样的东西。
有建议吗? :)

更新:

问题已解决!

在将我的somehow.js更改为

$(document).ready(function() {
    $(".modal").on('shown', function() {
        $(this).find("[autofocus]:first").focus();
    });
});

application.html.erb的样式表改为:

  <%= javascript_include_tag "jquery" %>
  <%= javascript_include_tag "bootstrap" %>
  <%= javascript_include_tag "somehow" %>

它按预期工作。再次感谢!


5
您在 shown 处理程序中的代码对我来说完全有效(前提是您确实设置了 autofocus 属性,否则选择器将找不到它):演示链接在此 - robertklep
Robert,你能把你的评论添加为答案吗?我会将其标记为正确答案 :) - konnigun
9个回答

82

我认为Bootstrap 3中的shown事件名称已更改,如this文章所述。

正如@MrDBA所指出的那样,在 Bootstrap 3 中,事件名称已更改为 changed shown.bs.modal

因此,在 Bootstrap 3 中使用:

$('#myModal').on('shown.bs.modal', function () {
    $('#myInput').focus();
})

这确实是最终的答案,因为即使您在HTML控件中将字段设置为自动对焦,模态对话框出现时该控件也会短暂地获得焦点,然后再次失去焦点。谢谢。 - raddevus

41

为了实现一般解决方案,不需要针对每个对话框编写特定的代码,您可以使用以下方法:

$('.modal').on('shown.bs.modal', function () {
  $(this).find('input:text:visible:first').focus();
})

1
我仍然想知道为什么Bootstrap会特别覆盖焦点,以及如何控制它。 - pschwamb
1
不得不放弃:text(密码字段),但除此之外,工作得很好。 - Dele Taylor
在这个例子中,您可以删除以下行(它是多余的):lastfocus = $(this); - DigitalDan
2
太棒了,谢谢。 我将 $('.modal').on 改为 $(document).on 以适应我的用例——一个动态生成模态框的单页应用程序。 - Liam Johnston
为了得到更加通用的解决方案,选择器内的 text 可以被移除,这样就可以检测到 任何 类型的输入。 - Enkk
@pschwamb 你是如何在模态框中到达最后一个元素时保持焦点的?因为使用该解决方案只有在未到达最后一个元素时才有效,一旦到达最后一个元素,焦点就会回到背景。 - user181452

13

尝试移除 tabindex="-1",这样它就可以正常工作了。

所以改成这样:

<div class="modal fade" id="modalID" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

变为:

<div class="modal fade" id="modalID" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

1
这个自动对焦元素的问题一直让我很烦恼,直到我找到了这个答案。从我的对话框中删除tabindex="-1"就解决了我的问题! - dkr88
哦,这也解决了问题。值得更多的赞!但是,tabindex为-1可能有原因。不知道我们通过删除它是否会破坏什么。 - Mārtiņš Briedis
@MārtiņšBriedis 移除tabindex会破坏使用Esc键关闭模态框的功能。 - Memet Olsen

8
如果你在使用“shown.bs.modal”遇到了问题,可以设置一个延时。
setTimeout(function() {
$('#myInput').focus();
}, 500);

7

仅仅将 $(this).find("[autofocus]:first").focus(); 改为 $(this).find("#myInput").focus(); 就使它对我起作用了。如果你已经更改了 Bootstrap API 并希望撤消该更改,你可以随时重新下载并替换文件。


6

我移除了tabindex =“-1”,现在运行得很好。

变更前的HTML代码:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

我的HTML代码更改后如下:
<div class="modal fade" id="myModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

我的输入代码:

<input id="tblModalNombreConductor" type="text" maxlength="50" placeholder="Ej: Armando Casas" autofocus/>

我在Javascript代码中没有任何设置。


这个对我只起作用一次。关闭和重新打开模态框不会聚焦。 - Memet Olsen

3

我认为这个更新后的答案非常聪明。以下是另一种解决方法。

Bootstrap 3.2的js文件包含一个脚本,用于在模态框淡入淡出转换期间和之后管理焦点。这会干扰任何jQuery、javascript或rails+HTML5专注于模态框中表单字段的操作 - bootstrap在模态框加载后会删除您的焦点。

要取消Bootstrap覆盖您的焦点能力,请在Modal脚本区域中将此行注释掉:

transition ?
    that.$element.find('.modal-dialog') // wait for modal to slide in
      .one($.support.transition.end, function () {
        // that.$element.focus().trigger(e)
        // the line above is stealing your focus after modal loads!
      })
      .emulateTransitionEnd(300) :
    that.$element.focus().trigger(e) 

现在您的字段应该能够在任何模态表单中获得焦点。

1
我也看到了这个问题。我在想那一行代码是什么意图。看起来它试图将焦点设置在模态框上。有没有办法利用Bootstrap正在做的事情,而不是猴子补丁行为? - pschwamb

1

你可以做:

例如

<%= f.text_field :first_name, class: "form-control", placeholder: "Enter first name", autofocus: true%>

请添加:autofocus: true

0

您也可以尝试

$('#the-modal').on('shown.bs.modal', function(e) {
    $('#the-input').focus();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接