我有一个类似于下拉菜单的 div。所以当你点击一个按钮时它会弹出,它允许你滚动这个大列表。所以 div 有一个垂直滚动条。如果您在 div 外部单击,即模糊,则 div 应该会消失。
问题是当用户点击 div 的滚动条时,IE 会错误地触发该onblur
事件,而 Firefox 则不会。我猜 Firefox 仍然将滚动条视为 div 的一部分,我认为这是正确的。我只希望 IE 以相同的方式运行。
我有一个类似于下拉菜单的 div。所以当你点击一个按钮时它会弹出,它允许你滚动这个大列表。所以 div 有一个垂直滚动条。如果您在 div 外部单击,即模糊,则 div 应该会消失。
问题是当用户点击 div 的滚动条时,IE 会错误地触发该onblur
事件,而 Firefox 则不会。我猜 Firefox 仍然将滚动条视为 div 的一部分,我认为这是正确的。我只希望 IE 以相同的方式运行。
我在自动完成下拉菜单中遇到了类似的滚动条问题。由于当它附加到的表单元素失去焦点时应该隐藏下拉菜单,因此保持对正确元素的关注成为一个问题。单击滚动条时,只有 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 上滚动条所在的元素。
迟到的答案,但我有同样的问题,目前的答案对我不起作用。
弹出元素的悬停状态按预期工作,因此在您的模糊事件中,您可以检查您的弹出元素是否悬停,如果不是,则仅删除/隐藏它:
$('#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/
当您单击滚动条时,IE 触发模糊事件时遇到类似的问题。显然它只发生在 IE7 及更低版本中,而 IE8 处于 quirksmode 中。
这是我通过谷歌找到的东西
基本上,如果您知道该人单击了文档上的某个位置,而不是当前聚焦的 div,则您只会进行模糊处理。可以反向检测滚动条单击,因为单击滚动条时不会触发 document.onclick。
这是一个老问题,但由于它仍然适用于 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;
}
},
这样菜单保持可见并且用户不会丢失任何东西。
使用 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();
});
我有同样的问题。通过将菜单放在一个包装(更大)的 div 中来解决。将模糊应用于包装后,它起作用了!
也许尝试将tabindex
属性集添加-1
到div
节点。
我不认为这是一个 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.clearAfterSelect
为true
.