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


156

我已经设置了一个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>

它甚至可以将焦点设置在图像上!既是常规<img>标记-也是<input type = image>
Simon_Weaver 2011年

Answers:


78

jQuery UI 1.10.0 Changelog故障单4731列出为已修复。

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

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

因此,用autofocus属性标记一个元素,该元素应成为焦点:

<input autofocus>

文档中,对焦点逻辑进行了说明(在目录下,标题为“焦点”):

打开对话框后,焦点将自动移至与以下内容匹配的第一项:

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

什么是反对票?如果是因为我列出了1.9作为修订版本,则我已更新为1.10以与故障单匹配。
slolife 2012年

1
我正在查看Dialog的jquery-ui 1.10文档,但没有看到它。我在api中搜索了“ focusSelector”,但它不存在。
Paul Tomblin

3
将焦点设置为屏幕外的任何元素都会向上或向下滚动窗口到该元素,并且只要窗口获得焦点,就会发生这种情况,而不仅是在对话框打开时。如果我使用Firebug来“检查元素”,然后在文档窗口中单击回来,则我的窗口将向上或向下滚动到jQuery-UI重点关注的元素。问题不是如何选择哪个元素获得焦点,而是如何防止焦点。选择其他要关注的元素将无法解决问题。
弗拉基米尔·科纳

4
jQuery UI认为此“已修复”的想法很疯狂。解决方法是完全删除所有自动对焦逻辑。我要求您打开一个对话框,而不是专注于输入。很烦人。
AJB

2
首先,我在第一个输入上方添加了一个w / type =“ hidden”输入,并为其添加了autofocus属性。这并不意味着您认为的含义,但是可以解决此问题。
jinglesthula 2016年

77

在其上方添加一个隐藏范围,使用ui-helper-hidden-accessible使其通过绝对定位隐藏。我知道您有该课程,因为您使用的是来自jquery-ui的对话框,它位于jquery-ui中。

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

1
伟大的工作。不需要js,不会更改布局,而jQuery ui本身支持它。
2012年

同意,请做好工作。也很高兴了解隐藏可访问的类!谢谢!!
user1055761 2012年

4
这给使用辅助技术的人(例如,屏幕阅读器)带来了问题
rink.attendant.6 2014年

1
@ rink.attendant.6哪些问题?
oxfn 2015年

令人惊讶的解决方案
Pedro Coelho

63

在jQuery UI> = 1.10.2中,您可以用_focusTabbable安慰剂函数替换prototype方法:

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

小提琴

这将影响dialog页面中的所有,而无需手动进行编辑。

原始函数除了将焦点设置为具有autofocus属性/ tabbableelement / 的第一个元素,或者回退到对话框本身之外,什么也不做。因为它的使用只是将重点放在某个元素上,所以用替换它应该没有问题noop


7
数小时,数小时,数小时,数小时地消耗掉了。我的客户谢谢你。
lamarant 2014年

1
这应该是答案!
briansol

搜索此解决方案2天...没有其他工作...非常感谢!
军团士兵2015年

1
警告:弹出对话框时,按Escape键将不会关闭对话框(直到聚焦对话框)。
罗伯特

1
@Robert而不是将其替换为,而是将其$.noop替换为记录活动对话框的函数,然后注册一个全局键事件处理程序,该处理程序将拦截ESC并关闭“活动”对话框(如果存在)。
珀金斯


27

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


1
tabindex = -1会阻止我进入文本框吗?
slolife

2
感谢您的研究。现在,我知道执行此操作的是实际代码。我可能会建议jQuery UI团队添加一个选项来禁用此自动对焦。
slolife

3
@slolife-很抱歉要复活这个确实很旧的线程,但是票证上说修复(该focusSelector选项)应该在jQueryUI 1.8中,而我们现在是1.8.13,我在jQueryUI对话框文档中没有看到它。怎么了
Tom Hamming

没关系。我曾在修改历史中看到过“里程碑从TBD更改为1.8”,却没有注意到它实际上是1.9。
汤姆·汉明

我有一个类似的问题,此处介绍了我的解决方法
标记

15

只是在玩耍时弄清楚了这一点。

我发现这些解决方案可以消除焦点,导致该ESC键在首次进入对话框时停止工作(即关闭对话框)。

如果对话框打开并且您立即按ESC,则它不会关闭对话框(如果您已启用该对话框),因为焦点位于某个隐藏字段或某些内容上,并且没有按键事件。

我解决问题的方法是将其添加到open事件中,以将焦点从第一个字段中移除:

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

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


3
这似乎是唯一可行的解​​决方案,其中不包括添加无用的HTML,删除tabindex或破坏ESC键。
BojanBedrač'16

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");
        }
    });
});

4
tabindex = -1会阻止我进入文本框吗?
slolife

1
在显示对话框后,您可以使用setTimeout来设置tabindex的值
redsquare

10

我的解决方法:

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

+1。使用:first选择器或.first()在FF / Chrome / IE9中可像超级按钮一样工作。将其扔到dialogopen绑定中也可以。
尼克

这个也带我去。除了我之外,我的对话框根本没有任何输入,并且第一个链接正在获得焦点...因此我将此选项添加到了jQuery对话框中:open: function(){ $('a').blur(); // no autofocus on links }
Marcus

8

我的内容比对话框长。在打开时,对话框将与底部的第一个:tabbable冲突。这是我的解决办法。

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

这对我有用,但是我使用$('...').blur();而不是滚动。
贾瓦

4
我的内容也很长。模糊删除了选择,但对话框仍滚动到底部。scrollTop将内容滚动到顶部,但保留所选内容。我最终使用$('...')。blur(); $(this).scrollTop(0); 像冠军一样工作。

7

简单的解决方法:

只需创建一个带有tabindex = 1的不可见元素...这将不会使datepicker聚焦...

例如。:

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

在ie9和Firefox中可以正常工作,但在Safari / chrome中则不能。
索2012年

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


1

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

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

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

    return false;
});

尚未测试,但应该可以。


1
不幸的是,这行不通。不确定是IE还是jquery UI。但是即使您以编程方式将焦点移到其他位置,日历也保持打开状态。
帕特里夏

1

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


1

好吧,很酷的是暂时没人找到解决方案,但是看来我有适合您的解决方案。坏消息是,即使内部没有输入和链接,对话框在任何情况下都可以吸引焦点。我将对话框用作工具提示,并且绝对需要将重点放在原始元素上。这是我的解决方案:

使用选项[autoOpen:false]

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

当对话框不可见时,焦点不会设置在任何地方,而是停留在原始位置。它仅适用于纯文本的工具提示,但并未经过更多功能性对话框的测试,这些对话框在打开时刻可见对话框可能很重要。在任何情况下都可能会正常工作。

我知道原始文章只是为了避免将注意力集中在第一个元素上,但是您可以轻松地确定在打开对话框后(在我的代码之后)应将焦点放在哪里。

经过IE,FF和Chrome测试。

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



1

我有一个类似的问题。验证失败时,我打开一个错误对话框,它抓住了焦点,就像Flugan在他的答案中显示的那样。问题在于,即使对话框中没有任何元素是可Tabable的,对话框本身仍然是焦点。这是来自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)
安德鲁·马丁内斯

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文档而言,对此没有修复。这不需要模糊或聚焦即可工作。不知道这是否是最优雅的。但这对任何人都有意义且易于解释。


1

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

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

对话框初始化后调用此方法,例如:

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

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


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>


0

我遇到了同样的问题。

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

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

0

如前所述,这是jQuery UI的已知错误,应尽快修复。直到那时...

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

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

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

为我工作。

重复的问题:如何在对话框打开时模糊第一个表单输入


0

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

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

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


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();

0

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

我在API文档中看不到任何东西,使我认为就预期功能而言,一切都没有改变。单击关闭以添加打开按钮...


根据jQuery票证,此修复程序现已推至1.10:bugs.jqueryui.com/ticket/4731
slolife 2012年

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();

});   


0

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

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

不适用于尺寸0px。我想这是更好的一个真正的透明图像,无论是.png.gif,但我没试过。

到目前为止,在iPad上运行良好。


-1

您可以添加:

...

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

...


3
他在问如何防止焦点,而不是增加焦点。
CBarr 2012年

-2

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.