Javascript 单击 div 的滚动条会触发 IE 中的模糊事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2023779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:26:22  来源:igfitidea点击:

Clicking on a div's scroll bar fires the blur event in I.E

javascriptjqueryinternet-exploreronblur

提问by Riz

I have a div that acts like a drop-down. So it pops-up when you click a button and it allows you to scroll through this big list. So the div has a vertical scroll bar. The div is supposed to disappear if you click outside of the div, i.e. on blur.

我有一个 div 就像一个下拉菜单。因此,当您单击按钮时它会弹出,并允许您滚动浏览这个大列表。所以div有一个垂直滚动条。如果您在 div 外部单击,即在模糊时,div 应该会消失。

The problem is that when the user clicks on the div's scrollbar, IE wrongly fires the onblurevent, whereas Firefox doesn't. I guess Firefox still treats the scrollbar as part of the div, which I think is correct. I just want IE to behave the same way.

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

采纳答案by Chris MacDonald

I'm having a similar problem with IE firing the blur event when you click on a scrollbar. Apparently it only happens n IE7 and below, and IE8 in quirksmode.

当您单击滚动条时,IE 触发模糊事件时遇到了类似的问题。显然,它只发生在 IE7 及以下,以及 quirksmode 中的 IE8。

Here's something I found via Google

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

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

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

Basically you only do the blur if you know the person clicked somewhere on the document other than the currently focused div. It's possible to inversely detect the scrollbar click because document.onclick doesn'tfire when you click on the scrollbar.

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

回答by Feysal

I've had a similar problem with a scrollbar in an autocomplete dropdown. Since the dropdown should be hidden when the form element it is attached to loses focus, maintaining focus on the correct element became an issue. When the scrollbar was clicked, only Firefox (10.0) kept focus on the input element. IE (8.0), Opera (11.61), Chrome (17.0) and Safari (5.1) all removed focus from the input, resulting in the dropdown being hidden, and since it was hidden, click events would not fire on the dropdown.

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

Fortunately, the shift of focus can be easily prevented in most of the problem browsers. This is done by canceling the default browser action:

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

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

Adding a return value to the event handler sorted out the problem on all browsers except IE. Doing this cancels the default browser action, in this case the focus shift. Also, using mousedown instead of click meant that the event handler would be executed before the blur event fired on the input element.

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

This left IE as the only remaining problem (no surprise there). It turns out that there is no way to cancel the focus shift on IE. Fortunately, IE is the only browser that fires a focus event on the dropdown, meaning focus on the input element can be restored with an IE-exclusive event handler:

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

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

This solution for IE is not perfect, but while the focus shift is not cancelable, this is the best you can do. What happens is that the blur event fires on the input, hiding the dropdown, after which focus fires on the now hidden dropdown, which restores focus on the input and triggers showing the dropdown. In my code it also triggers repopulating the dropdown, resulting in a short delay and loss of the selection, but if the user wants to scroll the selection is probably useless anyway, so I deemed this acceptable.

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

I hope this is helpful, even though my example is slightly different than in the question. From what I gathered, the question was about IE firing a blur event on the dropdown itself, rather than the button that opened it, which makes no sense to me... Like my use of a focus event handler indicates, clicking on a scrollbar should move focus to the element the scrollbar is part of on IE.

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

回答by Timm

Late answer, but I had the same issue and the current answers didn't work for me.

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

The hover state of the popup element works as expected, so in your blur event you can check to see if your popup element is hovered, and only remove/hide it if it isn't:

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

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

You'll need to shift focus back to the original element that has the blur event bound to it. This doesn't interfere with the scrolling:

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

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

This does not work with IE7 or lower - so just drop support for it...

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

Example: http://jsfiddle.net/y7AuF/

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

回答by Melanie

This is an old question but since it still applies to IE11 here is what I did.

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

I listen to the mousedown event on the menu and set a flag on this event. When I catch the blur event, if the mousedown flag is on, I set the focus back. Since Edge, FF and Chrome won't fire the blur event but will fire the mouseup event (which IE won't), I reset the mousedown flag on the mouseup for them (on the blur for IE).

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

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

That way the menu stays visible and user doesn't loose anything.

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

回答by Prateek Batla

Use focusout, and focusin (IE specific events)

使用 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();
});

回答by Oumar

I had the same probleme. Resolved by putting the menu in a wrapping (bigger) div. With the blur applied to the wrapper, it worked!

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

回答by Oumar

Perhaps try adding the tabindexattribute set to -1to the divnode.

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