【问题标题】:Prevent jQuery UI dialog from setting focus to first textbox防止 jQuery UI 对话框将焦点设置到第一个文本框
【发布时间】:2010-11-15 04:23:31
【问题描述】:

我设置了一个 jQuery UI 模式对话框,当用户单击链接时显示。该对话框 div 标记中有两个文本框(为简洁起见,我只显示 1 的代码),它被更改为对焦点做出反应的 jQuery UI DatePicker 文本框。

问题在于 jQuery UI 对话框('open')以某种方式触发第一个文本框获得焦点,然后触发日期选择器日历立即打开。

所以我正在寻找一种方法来防止焦点自动发生。

<div><a id="lnkAddReservation" href="#">Add reservation</a></div>

<div id="divNewReservation" style="display:none" title="Add reservation">
    <table>
        <tr>
            <th><asp:Label AssociatedControlID="txtStartDate" runat="server" Text="Start date" /></th>
            <td>
                <asp:TextBox ID="txtStartDate" runat="server" CssClass="datepicker" />
            </td>
        </tr>
    </table>

    <div>
        <asp:Button ID="btnAddReservation" runat="server" OnClick="btnAddReservation_Click" Text="Add reservation" />
    </div>
</div>

<script type="text/javascript">
    $(document).ready(function() {
        var dlg = $('#divNewReservation');
        $('.datepicker').datepicker({ duration: '' });
        dlg.dialog({ autoOpen:false, modal: true, width:400 });
        $('#lnkAddReservation').click(function() { dlg.dialog('open'); return false; });
        dlg.parent().appendTo(jQuery("form:first"));
    });
</script>

【问题讨论】:

  • 它甚至会为图像设置焦点!常规 标签以及

标签: javascript jquery jquery-ui


【解决方案1】:

在其上方添加一个隐藏的 span,使用 ui-helper-hidden-accessible 使其通过绝对定位隐藏。我知道你有那个类,因为你正在使用来自 jquery-ui 的对话框,它在 jquery-ui 中。

<span class="ui-helper-hidden-accessible"><input type="text"/></span>

【讨论】:

  • 很好的解决方法。不需要js,不改变布局,jquery ui原生支持。
  • 同意,很好的解决方法。也很高兴了解隐藏的可访问类!谢谢!!
  • 这会给使用辅助技术(例如屏幕阅读器)的人带来问题
  • @rink.attendant.6 有哪些问题?
  • 惊人的解决方案
【解决方案2】:

jQuery UI 1.10.0 Changelogticket 4731 列为已修复。

看起来 focusSelector 没有实现,而是使用了对各种元素的级联搜索。从票:

扩展自动对焦,从 [autofocus] 开始,然后是 :tabbable 内容,然后是按钮窗格,然后是关闭按钮,然后是对话框

所以,用autofocus 属性标记一个元素,这就是应该获得焦点的元素:

<input autofocus>

the documentation 中,解释了焦点逻辑(就在目录下,在标题“焦点”下):

打开对话框后,焦点会自动移至第一项 符合以下条件:

  1. 对话框中具有autofocus 属性的第一个元素
  2. 对话框内容中的第一个 :tabbable 元素
  3. 对话框按钮窗格中的第一个 :tabbable 元素
  4. 对话框的关闭按钮
  5. 对话框本身

【讨论】:

  • 反对票有什么用?如果是因为我将 1.9 列为修复版本,我已经更新到 1.10 以匹配票证。
  • 我正在查看 Dialog 的 jquery-ui 1.10 文档,但没有看到。我在api中搜索了“focusSelector”,没有。
  • 将焦点设置到屏幕外的任何元素都会将窗口向上或向下滚动到该元素,并且只要窗口获得焦点就会发生这种情况,而不仅仅是在对话框打开时。如果我使用 Firebug 来“检查元素”,然后在文档窗口中单击返回,我的窗口会向上或向下滚动到 jQuery-UI 关注的任何元素。问题不是如何选择哪个元素获得焦点,而是如何防止焦点。选择一个不同的元素来关注并不能解决问题。
  • jQuery UI 认为这是“固定”的想法是疯狂的。解决方法是完全删除 any 自动对焦逻辑。我让你打开一个对话框,而不是专注于输入。太烦人了。
  • fwiw,我在第一个输入上方添加了一个带有 type="hidden" 的输入,并为其添加了自动对焦属性。它并不意味着你认为它的意思,但它可以解决这个问题。
【解决方案3】:

在 jQuery UI >= 1.10.2 中,您可以将 _focusTabbable 原型方法替换为安慰剂函数:

$.ui.dialog.prototype._focusTabbable = $.noop;

Fiddle

这将影响页面中的所有dialogs,而无需手动编辑每一个。

原始函数除了将焦点设置到具有autofocus 属性/tabbable 元素的第一个元素/或返回到对话框本身之外什么都不做。由于它的用途只是将焦点放在一个元素上,因此将其替换为 noop 应该没有问题。

【讨论】:

  • 为此花费了数小时和数小时。我的客户谢谢你。
  • 这应该是答案!
  • 2 天搜索此解决方案...没有其他工作...非常感谢!
  • 警告:当对话框弹出时,按 Escape 键不会关闭对话框(直到您聚焦对话框)。
  • @Robert,不是用$.noop替换它,而是用记下活动对话框的函数替换它,然后注册一个拦截ESC并关闭“活动”的全局键事件处理程序如果有对话框。
【解决方案4】:

从 jQuery UI 1.10.0 开始,您可以使用 HTML5 属性选择要聚焦的输入元素 autofocus

您所要做的就是创建一个虚拟元素作为您在对话框中的第一个输入。 它会为你吸收焦点。

<input type="hidden" autofocus="autofocus" />

这已于 2013 年 2 月 7 日在 Chrome、Firefox 和 Internet Explorer(所有最新版本)中进行了测试。

http://jqueryui.com/upgrade-guide/1.10/#added-ability-to-specify-which-element-to-focus-on-open

【讨论】:

    【解决方案5】:

    我发现以下代码打开了 jQuery UI 对话框功能。

    c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();
    

    您可以解决 jQuery 行为或更改行为。

    tabindex -1 是一种解决方法。

    【讨论】:

    • tabindex=-1 不会阻止我跳到文本框吗?
    • 感谢您的研究。现在我知道这是实际的代码在做这件事。我可能会建议 jQuery UI 团队添加一个选项来禁用此自动对焦。
    • @slolife - 很抱歉让这个非常老的线程复活,但那张票说修复(focusSelector 选项)应该在 jQueryUI 1.8 中,我们现在在 1.8.13 和我在jQueryUI dialog docs 中没有看到它。这是怎么回事?
    • 没关系。我在修改历史中看到“里程碑从 TBD 更改为 1.8”,但没有注意到它实际上在顶部显示 1.9。
    • 我有类似的问题,我的解决方法在这里描述 - stackoverflow.com/a/12250193/80002
    【解决方案6】:

    只是在玩的时候想出来的。

    我发现使用这些解决方案来移除焦点,导致 ESC 键在第一次进入对话框时停止工作(即关闭对话框)。

    如果对话框打开并且您立即按下 ESC,它不会关闭对话框(如果您启用了该功能),因为焦点位于某个隐藏字段或其他东西上,而不是获取按键事件。

    我修复它的方法是将它添加到 open 事件中以从第一个字段中移除焦点:

    $('#myDialog').dialog({
        open: function(event,ui) {
            $(this).parent().focus();
        }
    });
    

    这会将焦点设置到不可见的对话框,然后 ESC 键起作用。

    【讨论】:

    • 这似乎是唯一可行的解​​决方案,不包括添加无用的 HTML、删除 tabindex 或破坏 ESC 键。
    【解决方案7】:

    设置输入的t​​abindex为-1,以后需要的话再设置dialog.open恢复tabindex:

    $(function() {
        $( "#dialog-message" ).dialog({
            modal: true,
            width: 500,
            autoOpen: false,
            resizable: false,
            open: function()
            {
                $( "#datepicker1" ).attr("tabindex","1");
                $( "#datepicker2" ).attr("tabindex","2");
            }
        });
    });
    

    【讨论】:

    • tabindex=-1 不会阻止我跳到文本框吗?
    • 你可以在对话框显示后使用 setTimeout 来设置 tabindex
    【解决方案8】:

    我的解决方法:

    open: function(){
      jQuery('input:first').blur();
      jQuery('#ui-datepicker-div').hide();
    },  
    

    【讨论】:

    • +1。在 FF/Chrome/IE9 中使用 :first 选择器或 .first() 就像一个魅力。将其放入 dialogopen 绑定也可以。
    • 这个也把我带到了那里。除了我,我的对话框根本没有输入,第一个链接正在获得焦点......所以我在我的 jQuery 对话框中添加了这个选项:open: function(){ $('a').blur(); // no autofocus on links }
    【解决方案9】:

    我的内容比对话长。打开时,对话框将滚动到底部的第一个 :tabbable。这是我的解决方法。

    $("#myDialog").dialog({
       ...
       open: function(event, ui) { $(this).scrollTop(0); }
    });
    

    【讨论】:

    • 这对我有用,但我使用 $('...').blur(); 而不是滚动。
    • 我的内容也很长。 blur 删除了选择,但对话框滚动到底部。 scrollTop 将内容滚动到顶部但离开了选择。我最终使用了 $('...').blur(); $(this).scrollTop(0);像冠军一样工作。
    【解决方案10】:

    简单的解决方法:

    只需使用 tabindex=1 创建一个不可见元素 ... 这不会关注日期选择器...

    例如:

    <a href="" tabindex="1"></a>
    ...
    Here comes the input element
    

    【讨论】:

    • 在 ie9 和 firefox 中运行良好,但在 safari/chrome 中运行良好。
    【解决方案11】:

    这是我在阅读jQuery UI ticket #4731 后实施的解决方案,最初由 slolife 发布,作为对另一个答案的回应。 (票也是他自己制作的。)

    首先,无论您使用何种方法将自动完成功能应用到页面,添加以下代码行:

    $.ui.dialog.prototype._focusTabbable = function(){};
    

    这会禁用 jQuery 的“自动对焦”行为。为确保您的网站可以继续被广泛访问,请封装您的对话框创建方法以便可以添加额外的代码,并添加一个调用以聚焦第一个输入元素:

    function openDialog(context) {
    
        // Open your dialog here
    
        // Usability for screen readers.  Focus on an element so that screen readers report it.
        $("input:first", $(context)).focus();
    
    }
    

    为了进一步解决通过键盘选择自动完成选项时的可访问性,我们覆盖了 jQuery UI 的“选择”自动完成回调并添加了一些额外的代码,以确保 textElement 在进行选择后不会在 IE 8 中失去焦点。

    以下是我们用于将自动完成应用于元素的代码:

    $.fn.applyAutocomplete = function () {
    
        // Prevents jQuery dialog from auto-focusing on the first tabbable element.
        // Make sure to wrap your dialog opens and focus on the first input element
        // for screen readers.
        $.ui.dialog.prototype._focusTabbable = function () { };
    
        $(".autocomplete", this)
            .each(function (index) {
    
                var textElement = this;
    
                var onSelect = $(this).autocomplete("option", "select");
                $(this).autocomplete("option", {
                    select: function (event, ui) {
                        // Call the original functionality first
                        onSelect(event, ui);
    
                        // We replace a lot of content via AJAX in our project.
                        // This ensures proper copying of values if the original element which jQuery UI pointed to
                        // is replaced.
                        var $hiddenValueElement = $("#" + $(textElement).attr('data-jqui-acomp-hiddenvalue'));
                        if ($hiddenValueElement.attr("value") != ui.item.value) {
                            $hiddenValueElement.attr("value", ui.item.value);
                        }
    
                        // Replace text element value with that indicated by "display" if any
                        if (ui.item.display)
                            textElement.value = ui.item.display;
    
                        // For usability purposes.  When using the keyboard to select from an autocomplete, this returns focus to the textElement.
                        $(textElement).focus();
    
                        if (ui.item.display)
                            return false;
    
                    }
                });
            })
            // Set/clear data flag that can be checked, if necessary, to determine whether list is currently dropped down
            .on("autocompleteopen", function (event, ui) {
                $(event.target).data().autocompleteIsDroppedDown = true;
            })
            .on("autocompleteclose", function (event, ui) {
                $(event.target).data().autocompleteIsDroppedDown = false;
            });
    
        return this;
    }
    

    【讨论】:

      【解决方案12】:

      您可以提供此选项,改为聚焦关闭按钮。

      .dialog({
            open: function () {
                    $(".ui-dialog-titlebar-close").focus();
                  }
         });
      

      【讨论】:

        【解决方案13】:

        这可能是浏览器行为而不是 jQuery 插件问题。您是否尝试在打开弹出窗口后以编程方式移除焦点。

        $('#lnkAddReservation').click(function () {
            dlg.dialog('open');
        
            // you may want to change the selector below
            $('input,textarea,select').blur();
        
            return false;
        });
        

        尚未测试,但应该可以正常工作。

        【讨论】:

        • 很遗憾这不起作用。不确定它是 IE 的东西,还是 jquery UI 的东西。但即使您以编程方式将焦点移到其他地方,日历也会保持打开状态。
        【解决方案14】:

        我有同样的问题,并通过在日期选择器之前插入一个空输入来解决它,每次打开对话框时都会窃取焦点。此输入在每次打开对话框时都会隐藏,并在关闭时再次显示。

        【讨论】:

          【解决方案15】:

          嗯,很高兴目前没有人找到解决方案,但看起来我有一些东西要给你。坏消息是,即使里面没有输入和链接,对话框在任何情况下都会抓住焦点。 我将对话框用作工具提示,并且绝对需要将焦点留在原始元素中。这是我的解决方案:

          使用选项 [autoOpen: false]

          $toolTip.dialog("widget").css("visibility", "hidden"); 
          $toolTip.dialog("open");
          $toolTip.dialog("widget").css("visibility", "visible");
          

          虽然对话框不可见,但焦点不会设置在任何地方并停留在原始位置。 它适用于只有纯文本的工具提示,但未针对更多功能对话框进行测试,在这些对话框中,在打开时刻显示对话框可能很重要。在任何情况下都可以正常工作。

          我知道最初的帖子只是为了避免将焦点放在第一个元素上,但您可以在对话框打开后(在我的代码之后)轻松决定焦点应该在哪里。

          在 IE、FF 和 Chrome 中测试。

          希望这会对某人有所帮助。

          【讨论】:

            【解决方案16】:

            在我看来,这个解决方案非常好:

            $("#dialog").dialog({
                open: function(event, ui) {
                    $("input").blur();
                }
            });
            

            在这里找到:unable-to-remove-autofocus-in-ui-dialog

            【讨论】:

              【解决方案17】:

              我也有类似的问题。当验证失败并抓住焦点时,我会打开一个错误对话框,就像 Flugan 在他的 answer 中显示的那样。问题是即使对话框内没有元素是可选项卡的,对话框本身仍然是焦点。这是来自 jquery-ui-1.8.23\js\jquery.ui.dialog.js 的原始未缩小代码:

              // set focus to the first tabbable element in the content area or the first button
              // if there are no tabbable elements, set focus on the dialog itself
              $(self.element.find(':tabbable').get().concat(
                uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
                  uiDialog.get()))).eq(0).focus();
              

              评论是他们的!

              这对我来说真的很糟糕,有几个原因。最烦人的是,用户的第一反应是按退格键删除最后一个字符,却提示他离开页面,因为退格键是在输入控件之外按的。

              我发现以下解决方法对我来说非常有效:

              jqueryFocus = $.fn.focus;
              $.fn.focus = function (delay, fn) {
                jqueryFocus.apply(this.filter(':not(.ui-dialog)'), arguments);
              };
              

              【讨论】:

              • 这可以通过使用 .dialog() 中的 'dialogClass' 选项扩展为仅影响特定对话框,然后更改上述 :not 过滤器以包含您的类。例如 :not(.ui-dialog.myDialogClass)
              【解决方案18】:

              我一直在寻找不同的问题,但原因相同。问题是对话框将焦点设置为它找到的第一个&lt;a href=""&gt;.&lt;/a&gt;。因此,如果您的对话框中有大量文本并且出现滚动条,您可能会遇到滚动条滚动到底部的情况。我相信这也解决了第一人称的问题。尽管其他人也这样做。

              简单易懂的修复。 &lt;a id="someid" href="#"&gt;.&lt;/a&gt; 作为对话框 div 的第一行。

              示例:

               <div id="dialogdiv" title="some title">
                  <a id="someid" href="#">.</a>
                  <p>
                      //the rest of your stuff
                  </p>
              </div>
              

              对话开始的地方

              $(somediv).dialog({
                      modal: true,
                      open: function () { $("#someid").hide(); otherstuff or function },
                      close: function () { $("#someid").show(); otherstuff or function }
                  });
              

              上面没有任何焦点,滚动条将保持在它所属的顶部。 &lt;a&gt; 获得焦点但随后被隐藏。所以整体效果就是想要的效果。

              我知道这是一个旧线程,但至于 UI 文档,没有解决此问题的方法。这不需要模糊或聚焦即可工作。不确定它是否是最优雅的。但这只是有意义且易于向任何人解释。

              【讨论】:

                【解决方案19】:

                如果您只有一个 Jquery 对话框形式的字段并且它是需要 Datepicker 的字段,或者,您可以将焦点设置在对话框标题栏中的对话框 关闭(交叉)按钮上:

                $('.ui-dialog-titlebar-close').focus();
                

                在对话框初始化后调用这个,例如:

                $('#yourDialogId').dialog();
                $('.ui-dialog-titlebar-close').focus();
                

                因为关闭按钮是在调用.dialog() 之后呈现的。

                【讨论】:

                  【解决方案20】:

                  如果您使用对话框按钮,只需在其中一个按钮上设置autofocus 属性:

                  $('#dialog').dialog({
                    buttons: [
                      {
                        text: 'OK',
                        autofocus: 'autofocus'
                      },
                      {
                        text: 'Cancel'
                      }
                    ]
                  });
                  <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
                  <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
                  <link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
                  
                  <div id="dialog" title="Basic dialog">
                    This is some text.
                    <br/>
                    <a href="www.google.com">This is a link.</a>
                    <br/>
                    <input value="This is a textbox.">
                  </div>

                  【讨论】:

                    【解决方案21】:

                    我遇到了同样的问题。

                    我所做的解决方法是在对话框容器的顶部添加虚拟文本框。

                    <input type="text" style="width: 1px; height: 1px; border: 0px;" />
                    

                    【讨论】:

                      【解决方案22】:

                      如前所述,这是 jQuery UI 的一个已知错误,应该很快就会修复。到那时……

                      这是另一种选择,因此您不必乱用 tabindex:

                      暂时禁用日期选择器,直到对话框打开:

                      dialog.find(".datepicker").datepicker("disable");
                      dialog.dialog({
                          "open": function() {$(this).find(".datepicker").datepicker("enable");},
                      });
                      

                      为我工作。

                      重复问题:How to blur the first form input at the dialog opening

                      【讨论】:

                        【解决方案23】:

                        要扩展之前的一些答案(并忽略辅助日期选择器方面),如果您想在对话框打开时阻止 focus() 事件聚焦第一个输入字段,请尝试以下操作:

                        $('#myDialog').dialog(
                            { 'open': function() { $('input:first-child', $(this)).blur(); }
                        });
                        

                        【讨论】:

                          【解决方案24】:

                          我也遇到过类似的问题,打开后关注对话框解决了:

                          var $dialog = $("#pnlFiltros")
                              .dialog({
                                  autoOpen: false,
                                  hide: "puff",                   
                                  width: dWidth,
                                  height: 'auto',
                                  draggable: true,
                                  resizable: true,
                                  closeOnScape : true,
                                  position: [x,y]                    
                              });
                          $dialog.dialog('open');
                          $("#pnlFiltros").focus(); //focus on the div being dialogued (is that a word?)
                          

                          但在我的情况下,第一个元素是一个锚点,所以我不知道在你的情况下这是否会使日期选择器保持打开状态。

                          编辑:仅适用于 IE

                          【讨论】:

                            【解决方案25】:

                            在 jquery.ui.js 中查找

                            d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(); 
                            

                            并替换为

                            d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(-1).focus();
                            

                            【讨论】:

                              【解决方案26】:

                              jQuery 1.9 已发布,但似乎没有修复。尝试通过一些建议的方法阻止第一个文本框的焦点在 1.9 中不起作用。我认为因为这些方法试图模糊焦点或移动焦点发生在对话框中的文本框已经获得焦点并完成其肮脏的工作之后。

                              我在 API 文档中看不到任何让我认为在预期功能方面发生任何变化的内容。关闭以添加开启按钮...

                              【讨论】:

                              【解决方案27】:

                              我有类似的问题。 在我的页面上,第一个输入是带有 jQ​​uery UI 日历的文本框。 第二个元素是按钮。 由于日期已经有价值,我将焦点设置在按钮上,但首先在文本框上添加模糊触发器。这解决了所有浏览器以及所有版本的 jQuery 中的问题。在 1.8.2 版本中测试。

                              <div style="padding-bottom: 30px; height: 40px; width: 100%;">
                              @using (Html.BeginForm("Statistics", "Admin", FormMethod.Post, new { id = "FormStatistics" }))
                              {
                                  <label style="float: left;">@Translation.StatisticsChooseDate</label>
                                  @Html.TextBoxFor(m => m.SelectDate, new { @class = "js-date-time",  @tabindex=1 })
                                  <input class="button gray-button button-large button-left-margin text-bold" style="position:relative; top:-5px;" type="submit" id="ButtonStatisticsSearchTrips" value="@Translation.StatisticsSearchTrips"  tabindex="2"/>
                              }
                              

                              <script type="text/javascript">
                              $(document).ready(function () {        
                                  $("#SelectDate").blur(function () {
                                      $("#SelectDate").datepicker("hide");
                                  });
                                  $("#ButtonStatisticsSearchTrips").focus();
                              
                              });   
                              

                              【讨论】:

                                【解决方案28】:

                                这对于智能手机和平板电脑来说非常重要,因为当输入具有焦点时,键盘就会出现。这就是我所做的,在 div 的开头添加这个输入:

                                <input type="image" width="1px" height="1px"/>
                                

                                不适用于大小 0px。我想使用真正的透明图像会更好,.png.gif 但我没有尝试过。

                                目前在 iPad 上运行良好。

                                【讨论】:

                                  【解决方案29】:

                                  你可以添加这个:

                                  ...

                                  dlg.dialog({ autoOpen:false,
                                  modal: true, 
                                  width: 400,
                                  open: function(){                  // There is new line
                                    $("#txtStartDate").focus();
                                    }
                                  });
                                  

                                  ...

                                  【讨论】:

                                  • 他在问如何防止焦点,而不是添加焦点。
                                  【解决方案30】:

                                  作为第一个输入:&lt;input type="text" style="position:absolute;top:-200px" /&gt;

                                  【讨论】:

                                    猜你喜欢
                                    • 2010-10-20
                                    • 1970-01-01
                                    • 2018-07-18
                                    • 2018-08-27
                                    • 2010-12-20
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多