阻止jQuery UI对话框将焦点设置为第一个文本框

时间:2009-07-29 18:15:32

标签: javascript jquery jquery-ui

我已经设置了一个jQuery UI模式对话框,以便在用户单击链接时显示。在该对话框div标签中有两个文本框(我只显示简洁的代码),它被更改为jQuery UI DatePicker文本框,对焦点作出反应。

问题是jQuery UI对话框('open')以某种方式触发第一个文本框有焦点,然后触发datepicker日历立即打开。

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

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

30 个答案:

答案 0 :(得分:77)

jQuery UI 1.10.0 Changelog列出ticket 4731已修复。

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

  

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

因此,使用autofocus属性标记一个元素,这是应该获得焦点的元素:

<input autofocus>

the documentation中,解释焦点逻辑(在目录下,标题为'焦点'):

  

打开对话框后,焦点会自动移动到第一个项目   符合以下内容:

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

答案 1 :(得分:72)

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

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

答案 2 :(得分:59)

在jQuery UI&gt; = 1.10.2中,您可以用安慰剂函数替换_focusTabbable原型方法:

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

Fiddle

这会影响页面中的所有dialog,而无需手动编辑每个autofocus

原始函数除了将焦点设置为具有tabbable属性/ noop元素的第一个元素/或者回退到对话框本身之外什么都不做。因为它的用途只是设置一个元素,所以用{{1}}替换它应该没有问题。

答案 3 :(得分:28)

我发现以下代码是用于打开的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可用作解决方法。

答案 4 :(得分:27)

从jQuery UI 1.10.0开始,您可以选择使用HTML5属性 自动对焦来关注哪个输入元素。

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

<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 :(得分:13)

在玩游戏时想出来。

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

如果对话框打开并且您立即按 ESC ,它将无法关闭对话框(如果已启用),因为焦点位于某个隐藏字段或其他位置,并且没有得到按键事件。

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

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

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

答案 6 :(得分:10)

将输入的tabindex设置为-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");
        }
    });
});

答案 7 :(得分:10)

我的解决方法:

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

答案 8 :(得分:7)

我的内容比对话框长。在打开时,对话框将会弹到第一个:位于底部的tabbable。这是我的修复。

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

答案 9 :(得分:7)

简单的解决方法:

使用tabindex = 1创建一个不可见的元素... 这不会关注datepicker ......

例如:

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

答案 10 :(得分:3)

这是我在阅读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;
}

答案 11 :(得分:2)

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

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

答案 12 :(得分:1)

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

$('#lnkAddReservation').click(function () {
    dlg.dialog('open');

    // you may want to change the selector below
    $('input,textarea,select').blur();

    return false;
});

没有测试过,但应该可以正常工作。

答案 13 :(得分:1)

如果您正在使用对话框按钮,只需在其中一个按钮上设置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>

答案 14 :(得分:1)

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

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

在此处找到:unable-to-remove-autofocus-in-ui-dialog

答案 15 :(得分:1)

我有类似的问题。我在验证失败时打开一个错误对话框并抓住焦点,就像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);
};

答案 16 :(得分:1)

我正在寻找一个不同的问题,但同样的原因。问题是对话框集中于它找到的第一个<a href="">.</a>。因此,如果对话框中有大量文本并且滚动条出现,则可能会出现滚动条滚动到底部的情况。我相信这也解决了第一个问题。虽然其他人也这样做。

简单易懂的修复方法。 <a id="someid" href="#">.</a>作为对话框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 }
    });

上面没有任何重点,滚动条将保留在它所属的顶部。 <a>获得焦点但随后被隐藏。因此整体效果是预期的效果。

我知道这是一个旧线程,但至于UI文档,没有解决这个问题。这不需要模糊或焦点工作。不确定它是否是最优雅的。但这对任何人都很有意义,也很容易解释。

答案 17 :(得分:1)

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

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

调用此AFTER对话框已初始化,例如:

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

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

答案 18 :(得分:1)

嗯,现在没人找到解决方案很酷,但看起来我有东西给你。坏消息是,即使内部没有输入和链接,对话框也会抓住焦点。 我使用对话框作为工具提示,绝对需要专注于原始元素。这是我的解决方案:

使用选项[autoOpen:false]

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

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

据我所知,原帖只是为了避免把焦点放在第一个元素上,但是在打开对话框之后(在我的代码之后)你可以轻松决定焦点的位置。

在IE,FF和Chrome中测试过。

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

答案 19 :(得分:1)

我遇到了同样的问题并通过在datepicker之前插入一个空输入来解决它,每次打开对话框时都会窃取焦点。此输入在对话框的每个开口处都隐藏,并在关闭时再次显示。

答案 20 :(得分:0)

我遇到了同样的问题。

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

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

答案 21 :(得分:0)

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

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

不适用于尺寸0px。我认为使用真正透明的图片(.png.gif更好,但我还没试过。

目前在iPad上工作正常。

答案 22 :(得分:0)

我有类似的问题。 在我的页面上,第一个输入是带有jQuery 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();

});   

答案 23 :(得分:0)

如前所述,这是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

答案 24 :(得分:0)

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

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

答案 25 :(得分:0)

在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 :(得分:0)

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

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

答案 27 :(得分:0)

我遇到了类似的问题,并在打开后关注对话框解决了这个问题:

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

答案 28 :(得分:-1)

您可以添加:

...

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

...

答案 29 :(得分:-2)

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