25

我有一个类似于下拉菜单的 div。所以当你点击一个按钮时它会弹出,它允许你滚动这个大列表。所以 div 有一个垂直滚动条。如果您在 div 外部单击,即模糊,则 div 应该会消失。

问题是当用户点击 div 的滚动条时,IE 会错误地触发该onblur事件,而 Firefox 则不会。我猜 Firefox 仍然将滚动条视为 div 的一部分,我认为这是正确的。我只希望 IE 以相同的方式运行。

4

8 回答 8

18

我在自动完成下拉菜单中遇到了类似的滚动条问题。由于当它附加到的表单元素失去焦点时应该隐藏下拉菜单,因此保持对正确元素的关注成为一个问题。单击滚动条时,只有 Firefox (10.0) 将焦点放在输入元素上。IE (8.0)、Opera (11.61)、Chrome (17.0) 和 Safari (5.1) 都从输入中移除了焦点,导致下拉菜单被隐藏,并且由于它被隐藏,因此不会在下拉菜单上触发点击事件。

幸运的是,在大多数有问题的浏览器中都可以轻松防止焦点转移。这是通过取消默认浏览器操作来完成的:

dropdown.onmousedown = function(event) {
    // Do stuff
    return false;
}

向事件处理程序添加返回值解决了除 IE 之外的所有浏览器上的问题。这样做会取消默认的浏览器操作,在这种情况下是焦点转移。此外,使用 mousedown 而不是 click 意味着事件处理程序将在输入元素上触发 blur 事件之前执行。

这让 IE 成为唯一剩下的问题(这并不奇怪)。事实证明,没有办法取消 IE 上的焦点转移。幸运的是,IE 是唯一在下拉菜单上触发焦点事件的浏览器,这意味着可以使用 IE 独有的事件处理程序恢复对输入元素的焦点:

dropdown.onfocus = function() {
    input.focus();
}

这个针对 IE 的解决方案并不完美,但是虽然焦点转移是不可取消的,但这是你能做的最好的。发生的情况是模糊事件在输入上触发,隐藏下拉菜单,之后焦点在现在隐藏的下拉菜单上触发,这会恢复对输入的关注并触发显示下拉菜单。在我的代码中,它还会触发重新填充下拉列表,导致短暂的延迟和选择丢失,但如果用户想要滚动选择可能无论如何都没用,所以我认为这是可以接受的。

我希望这会有所帮助,即使我的示例与问题中的示例略有不同。从我收集到的信息来看,问题是关于 IE 在下拉菜单本身上触发一个模糊事件,而不是打开它的按钮,这对我来说毫无意义......就像我使用焦点事件处理程序所表明的那样,单击滚动条应该将焦点移动到 IE 上滚动条所在的元素。

于 2012-02-09T11:44:38.473 回答
5

迟到的答案,但我有同样的问题,目前的答案对我不起作用。

弹出元素的悬停状态按预期工作,因此在您的模糊事件中,您可以检查您的弹出元素是否悬停,如果不是,则仅删除/隐藏它:

$('#element-with-focus').blur(function()
{
    if ($('#popup:hover').length === 0)
    {
        $('#popup').hide()
    }
}

您需要将焦点转移回绑定了模糊事件的原始元素。这不会干扰滚动:

$('#popup').focus(function(e)
{
    $('#element-with-focus').focus();
});

这不适用于 IE7 或更低版本 - 所以只需放弃对它的支持...

示例:http: //jsfiddle.net/y7AuF/

于 2014-05-22T22:26:31.060 回答
3

当您单击滚动条时,IE 触发模糊事件时遇到类似的问题。显然它只发生在 IE7 及更低版本中,而 IE8 处于 quirksmode 中。

这是我通过谷歌找到的东西

https://prototype.lighthouseapp.com/projects/8887/tickets/248-results-popup-from-ajaxautocompleter-disappear-when-user-clicks-on-scrollbars-in-ie6ie7

基本上,如果您知道该人单击了文档上的某个位置,而不是当前聚焦的 div,则您只会进行模糊处理。可以反向检测滚动条单击,因为单击滚动条时不会触发 document.onclick。

于 2010-01-25T22:53:34.767 回答
3

这是一个老问题,但由于它仍然适用于 IE11,这就是我所做的。

我在菜单上监听 mousedown 事件并在这个事件上设置一个标志。当我捕捉到模糊事件时,如果 mousedown 标志打开,我将焦点重新设置。由于 Edge、FF 和 Chrome 不会触发 blur 事件,但会触发 mouseup 事件(IE 不会),我为它们重置 mouseup 上的 mousedown 标志(在 IE 上的 blur 上)。

  mousedown: function (e) {
      this.mouseddown = true;
      this.$menu.one("mouseup", function(e){
        // IE won't fire this, but FF and Chrome will so we reset our flag for them here
        this.mouseddown = false;
      }.bind(this));
    }

 blur: function (e) {
      if (!this.mouseddown && this.shown) {
        this.hide();
        this.focused = false;        
      } else if (this.mouseddown) {
        // This is for IE that blurs the input when user clicks on scroll.
        // We set the focus back on the input and prevent the lookup to occur again
        this.skipShowHintOnFocus = true; // Flag used to avoid repopulating the menu
        this.$element.focus();
        this.mouseddown = false;    
      } 
    },

这样菜单保持可见并且用户不会丢失任何东西。

于 2016-07-18T13:29:18.487 回答
1

使用 focusout 和 focusin(IE 特定事件)

$(document).bind('focusout', function(){
     preventHiding = false;
     //trigger blur event
     this.$element.trigger('blur');

});

$(document).bind('focusin', function(){
     preventHiding = true;
});

$(document).bind('blur', function(){
       // Did anyone want us to prevent hiding?
       if (this.preventHiding) {
         this.preventHiding = false;
         return;
       }
       this.hide();
});
于 2014-01-06T12:25:51.317 回答
0

我有同样的问题。通过将菜单放在一个包装(更大)的 div 中来解决。将模糊应用于包装后,它起作用了!

于 2010-02-10T16:02:33.233 回答
0

也许尝试将tabindex属性集添加-1div节点。

于 2011-09-18T16:54:25.807 回答
0

我不认为这是一个 IE 问题。

它更多的是如何设计您的交互以及在哪里处理哪个事件。如果您有相关目标的唯一 css-class-accessor,取消模糊事件可以通过检查 event.relatedTarget 的 classList 来确定您想要允许或禁止启动模糊事件的元素。从我的 ES2015 项目中的自定义自动完成下拉列表中查看我的 onBlurHandler(您可能需要解决contains()旧的 JS 支持):

onBlurHandler(event: FocusEvent) {
  if (event.relatedTarget 
      && (event.relatedTarget as HTMLElement).classList.contains('folding-select-result-list')) {
    // Disallow any blur event from `.folding-select-result-list`
    event.preventDefault();
  } else if (!event.relatedTarget
      || event.relatedTarget 
      && !(event.relatedTarget as HTMLElement).classList.contains('select-item')) {
    // If blur event is from outside (not `.select-item`), clear the suggest list
    // onClickHandler of `.select-item` will clear suggestList as configured with this.clearAfterSelect
    this.clearOptions(this.clearAfterBlur);
  }
}
  • .folding-select-result-list是我的建议下拉菜单有“空白点”和“可能是滚动条”,我不需要这个模糊事件。
  • .select-item有它自己的 onClickHandler 触发选择的 XHR 请求,并在组件的另一个属性this.clearAfterSelecttrue.
于 2020-06-29T22:04:18.237 回答