当使用带超时的模糊来实现点击外部关闭时,时间间隔有时太短



我有一个小部件,它有一个链接列表,可以打开和关闭:

<div class="widget">
<input class="focuser">
<a href="javascript:;">View options</a>
<ul>
<li>Option 1</li>
<li>Option 1</li>
</ul>
</div>

所以,当我点击View options时,列表就会出现,当点击任何选项时,做一些事情并关闭选项列表。

我需要有click-outside-close功能——当用户点击列表之外的任何位置时,只需关闭列表。

我通过在显示选项时聚焦一个不可见的输入,并在输入的blur上——在一段时间后隐藏选项来实现这一点。这样:

  1. 当用户在外部单击时-模糊超时时间用完-隐藏选项
  2. 如果用户点击任何选项-清除超时,隐藏选项&做东西

现在的问题是,有时超时会在单击之前结束。我将超时间隔增加到了200ms,但仍然不能100%确定,而且用户在选项列表关闭之前会看到延迟。

知道如何修复和/或改进吗?

编辑:

这是JavaScript代码的简化版本:

CartSidebar.DwCustomSelect = Ember.View.extend({
blurTimeout: false,
focusOut: function(e) {
if (e.target.className == 'focuser') {
var self = this;
this.blurTimeout = setTimeout(function() {
clearTimeout(self.blurTimeout);
$(self.element).removeClass('opened'); // hide options .. 
}, 180);
}
},
click: function(e) {
var clickedElement = e.target;
clearTimeout(this.blurTimeout);
if (clickedElement.tagName.toLowerCase() == 'li') {
$(this.element).removeClass('opened'); // hide options .. 
doStuff();
}
}
}

编辑2:

我创建了一个plunker,所以你可以看到它的作用:

https://plnkr.co/edit/boA6yC0sEbLAZU9tjyso?p=preview

(我把超时时间做得太小了,所以你可以看到问题。但即使你增加间隔,你也会看到focusOutclick之前触发。)

如果你想要一个功能,当用户点击除div之外的任何地方时,你都需要隐藏你的div,那么你可以在整个文档中添加一个点击监听器,并使用隐藏div的代码。

var a = document.querySelector("a");
var ul = document.querySelector("ul");
a.addEventListener('click', function(e){
e.stopPropagation();
if(ul.classList.contains('show')){
ul.classList.remove('show');
ul.classList.add('hide');
}else{
ul.classList.remove('hide');
ul.classList.add('show');
}   
});
document.addEventListener('click', function(){
ul.classList.remove('show');
ul.classList.add('hide');
});

有关详细示例,请查看下面的jsbin

http://jsbin.com/mamexev/edit?html,css,js,输出

超时是一个选项。但您必须定义一个大的间隔,因为这将取决于浏览器处理所有内容的速度。它在99.99%的情况下都能工作,但正如你所说,它不是防弹的。

另一个技巧是倾听整件事的模糊。如果将tabindex属性赋予某个元素,它将接收焦点事件。如果你设置tabindex="0",它会得到一个自动索引,你就不必担心了

因此,与其听input的模糊,不如听div.widget的模糊。当焦点从输入转到链接或lis时,它将仍然在widget的焦点内,并且blur事件不会激发。

最新更新