我有一个div,就像一个下拉菜单。因此,当您单击按钮时弹出窗口,它允许您滚动浏览此大列表。所以div有一个垂直滚动条。如果你点击div的外部,即在模糊时,div应该会消失。
问题是,当用户点击div的滚动条时,IE错误地触发了onblur
事件,而Firefox却没有。我猜Firefox仍然将滚动条视为div的一部分,我认为这是正确的。我只是希望IE的行为方式相同。
答案 0 :(得分:16)
我在自动完成下拉列表中遇到了与滚动条类似的问题。由于下拉列表应该在附加的表单元素失去焦点时隐藏,因此保持对正确元素的关注成为一个问题。单击滚动条时,只有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上的一部分。
答案 1 :(得分:4)
迟到的答案,但我遇到了同样的问题,目前的答案对我没有用。
popup元素的悬停状态按预期工作,因此在您的模糊事件中,您可以检查您的弹出元素是否悬停,只有删除/隐藏它才会显示:
$('#element-with-focus').blur(function()
{
if ($('#popup:hover').length === 0)
{
$('#popup').hide()
}
}
您需要将焦点移回到已绑定模糊事件的原始元素。这不会干扰滚动:
$('#popup').focus(function(e)
{
$('#element-with-focus').focus();
});
这不适用于IE7或更低版本 - 所以只需删除对它的支持......
答案 2 :(得分:3)
当你点击滚动条时,我遇到类似的问题,IE触发模糊事件。显然它只发生在IE7及以下,而IE8在quirksmode中。
这是我通过Google找到的东西
如果你知道在文档上某个地方点击的人而不是当前关注的div,你基本上只会做模糊。可以反向检测滚动条点击,因为当您单击滚动条时,document.onclick 不会触发。
答案 3 :(得分:3)
这是一个老问题,但由于它仍适用于IE11,这就是我所做的。
我在菜单上听mousedown事件并在此事件上设置一个标志。当我捕捉模糊事件时,如果mousedown标志打开,我将焦点设置回来。由于Edge,FF和Chrome不会触发模糊事件,但会触发鼠标事件(IE赢了),我为它们重置鼠标上的mousedown标志(在IE的模糊上)。 / p>
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;
}
},
这样菜单保持可见,用户不会丢失任何东西。
答案 4 :(得分: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();
});
答案 5 :(得分:0)
我有同样的问题。通过将菜单放在包装(更大)div中解决。随着模糊应用于包装器,它工作!
答案 6 :(得分:0)
也许尝试将tabindex
属性集-1
添加到div
节点。
答案 7 :(得分: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.clearAfterSelect
的另一个属性为true
时关闭下拉列表。