jQuery对话框在滚动时失去焦点

13

我下面有一个jQuery对话框。我正在使用jQuery UI 1.11。

$("#contactContainer").dialog({
  closeOnEscape: false,
  modal: true,
  dialogClass: 'contactsFooter', 
  open: function(event, ui) {
    $(".ui-dialog-titlebar-close").show();
    $('#dialog_footer').remove();
    $(".contactsFooter").append('<div class="" id="dialog_footer"><div class="dialog-footer-buttons"><button type="button" id ="close" class="button-style-2" onclick="$(\'#hasChangedForm\').val(\'\');" style="margin-left: 5px;">Cancel</button></div></div>');
  },
  autoOpen: false,          
  width: 300,
  minHeight: 'auto',
  maxHeight: 400,
  position: { my: 'top', at: 'top+50' },
  close:function() {
    $('#contactContainer').dialog("option", "position", { my:"top", at:"top+50", of: window });
    $('#contactContainer').html('');
  }
}); 

$("#contactContainer").dialog('open');

这里是Fiddle示例。在这个示例中:

  1. 点击任何一个文本框(表示聚焦)。在此示例中,我们聚焦的文本框有“test here”。

  2. 现在通过单击对话框的滚动条并向下/向上拖动来滚动对话框,看看会发生什么。它会失去我们所点击的文本框的聚焦。如果我按Tab键,它会再次将焦点设置为第一个字段。这很奇怪。

如果我使用鼠标滚轮,则焦点仍然在相同的字段上。这是正常的。

坦率地说,我不知道为什么会发生这种情况。有人能帮我解决如何防止滚动时对话框失去焦点吗?我希望焦点仍保留在同一个字段上。

6个回答

6

已修复。问题在于 tabindex

我给你提供了一个可以运行的示例。诀窍是在对话框初始化后立即删除 tabindex,可以像这样完成:

$(".ui-dialog.ui-widget").removeAttr("tabindex")

如果您希望使这种行为变成永久性的,您可以编辑jQuery源代码。如果您到达了对话框部分,您将看到一个名为_createWrapper的函数。在里面,您可以看到类似于以下内容:

.attr( {

            // Setting tabIndex makes the div focusable
            tabIndex: -1,
            role: "dialog"
        } )

从那里删除tabindex,就可以了!

这很有趣。tabindex有什么问题?你能解释一下吗? - Linga
我能记得正确的解释,因为几个月前我曾经处理过这个问题。但是滚动条放置在 $(".ui-dialog") 的填充区域上,所以当你点击滚动条时,就相当于点击容器,这会导致你失去焦点。移除 tabindez 使元素无法聚焦,因此当你点击它时,不会失去输入焦点。然后,在某些地方我记不清楚了,JQuery UI 有一个适当的处理程序来以正确的方式重新添加可聚焦属性。 - Iván Rodríguez Torres
是的,你说得对!!!问题出在tabindex上,但在我的情况下,我不能删除它,因为默认的浏览器导航操作(空格键和shift+空格键)只有在我们添加了tabindex后才能在弹出窗口上工作。如果我们在对话框中删除tabindex,当您按下shift+空格键时,它将仅滚动背景屏幕而不是对话框。 - Linga
抱歉@linga。我没有在所有浏览器中进行测试,但至少在Chrome中,它可以正常工作。如果您打开我的fiddle并尝试“空格/shift +空格”导航,则滚动条将按预期工作。 - Iván Rodríguez Torres
是的,你说得对。也许我漏掉了什么。让我检查一下。 - Linga
显示剩余2条评论

2
我认为这可能会对你有所帮助。
$('#divWithTheScrollbar').scroll(function() {
    $('#elementLosingFocus').focus();
});

好主意,但我不想在所有对话框中使用它。需要知道为什么会发生这种情况,是 JQuery 对话框的问题吗?不是吗? - Linga

0

从网上搜索来看,似乎@pritishvaidya添加的选项是您最可行的选择。

您必须意识到,当页面上的任何内容被点击时,都会触发焦点事件。这意味着,如果您在文本框处于焦点状态时单击滚动条,您将把滚动条放在焦点位置,并失去文本框的焦点。

我建议您实现@pritishvaidya的解决方案,但在此基础上添加某种验证,以便您知道哪个控件最后处于焦点状态,然后在滚动条失去焦点时强制将焦点放在该控件上。这将对客户端造成最小的负担,并允许您继续使用您的用例。

祝编码愉快!


你是对的,当页面上的任何东西被点击时都会触发focus事件。这意味着如果你在文本框处于焦点状态时点击了滚动条,那么你就会将滚动条设为焦点并失去文本框的焦点。但是,当我按下Tab键时,焦点又会重新设置到第一个字段,这很奇怪,不是吗? - Linga

0

试试这个,它可以工作(不需要为输入添加id或其他选择器)

var focused;
setInterval(function(){
        focused = $(':focus');
},500)

$("#contactContainer").scroll(function(){
       //console.log(focused[0]);
       $(focused).focus();
})

这不是解决问题的理想方案。 - Linga

0
这可能是一个通用的解决方案,但需要进行测试。
var lastFocus;

$(document)
  .on("focus", function(e) { lastFocus = e.target; })

$("#divWithTheScrollbar").scroll(function () {
  if (lastFocus) lastFocus.focus();
})

它通常保存上次聚焦的元素,并在滚动div时再次设置。 您需要扩展它,以便有意的blur事件仍然可以正常工作,而不会在滚动后再次聚焦该元素。


0
请尝试以下 JavaScript 更新。

https://jsfiddle.net/3q22xLhk/5/ 您可以在 fiddle 上进行检查

$("#contactContainer").dialog({
  closeOnEscape: false,
  modal: true,
  dialogClass: 'contactsFooter',
  open: function(event, ui) {
    $(".ui-dialog-titlebar-close").show();
    $('#dialog_footer').remove();
    $(".contactsFooter").append('<div class="" id="dialog_footer"><div class="dialog-footer-buttons"><button type="button" id ="close" class="button-style-2" onclick="$(\'#hasChangedForm\').val(\'\');" style="margin-left: 5px;">Cancel</button></div></div>');
  },
  autoOpen: false,
  width: 300,
  minHeight: 'auto',
  maxHeight: 400,
  position: {
    my: 'top',
    at: 'top+50'
  },
  close: function() {
    $('#contactContainer').dialog("option", "position", {
      my: "top",
      at: "top+50",
      of: window
    });
    $('#contactContainer').html('');
  }
});
var scrolling = false;
$("#contactContainer").dialog('open');
var lastFocusTextbox = null;
$("#contactContainer input").focus(function() {
  lastFocusTextbox = this;
});

$("#contactContainer").scroll(function(e) {
  scrolling = true;
});


$("#contactContainer").mouseup(function() {
  if (scrolling) {
    if (lastFocusTextbox != null) {
      $(lastFocusTextbox).focus();
    }
    scrolling = false;
  }
});

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