最低限度、完整、可验证、示例
为了轻松查看此结果,您必须打开开发工具并限制网络流量,以便 ajax 连接需要一点时间
Here's a Demo of the issue in jsFiddle
处理库事件(不起作用)
我最初的想法是你可以在EAC lifecycle events 被触发的一些过程中处理这个问题,比如onLoadEvent 或onShowListEvent:
var options = {
url: "https://raw.githubusercontent.com/KyleMit/libraries/gh-pages/libraries/people.json",
getValue: "name",
list: {
match: {
enabled: true
},
onLoadEvent: function() {
console.log('LoadEvent', this)
},
onShowListEvent: function() {
console.log('ShowListEvent', this)
}
},
};
但是,这些方法似乎没有提供更改控制流和防止未来事件发生的选项
更新源代码(作品)
查看库的源代码,Easy AutoComplete 执行以下操作...
-
Handles keyup events
-
然后调用loadData
-
触发AJAX request with the provided URL
根据网络和服务器速度,在第 4 步之前可以经过任意时间,输入可能会失去焦点
-
一旦 ajax 承诺返回,将调用showContainer()
-
容器上有哪个triggers the "show.eac" event
-
然后opens the list 带有选定的动画
在第 6 步中,我们可以添加最后一项检查,以确认所选输入在实际打开之前仍然具有焦点,如下所示:
$elements_container.on("show.eac", function() {
// if input has lost focus, don't show container
if (!$field.is(":focus")) {return}
// ... rest of method ...
Here's a working demo in Plunker 在新文件中修改库的源代码
不幸的是,这不是一个很好的做法,因为它会让您对未来的更改很脆弱,并将 lib 维护的所有权转移到您的代码库。但它确实有效。
我使用建议的更改创建了 Pull Request #388,因此希望库本身的长期修复将在未来的某个时候提供。
包装器(现在推荐)
如果您不想使用第三方代码,可以使用一些奇怪的解决方法来干扰内部执行。我们无法修改 showContainer 方法,因为它位于闭包内。
我们可以在show.eac 事件上添加另一个侦听器,这样我们就可以成为事件管道的一部分,但是这里也有一些挑战。理想情况下,我们希望在库处理程序执行之前触发并有条件地停止传播。但是,初始化 EAC 将 a) 创建我们必须侦听的容器并 b) 附加事件侦听器。
注意:jQuery 中的事件处理程序是按照它们附加的顺序触发的!
因此,我们必须等到 lib 加载后才能附加我们的处理程序,但这意味着我们只会在列表已显示后触发。
从How to order events bound with jQuery 的问题中,我们可以深入 jQuery 内部并重新排序附加事件,以便我们可以在调用库的处理程序之前触发我们的处理程序。看起来像这样:
$._data(element, 'events')["show"].reverse()
注意:e.stopPropagation() 和 e.preventDefault() 都不起作用,因为它们会阻止未来的事件;相反,我们需要立即采取行动e.stopImmediatePropagation()
所以包装器看起来像这样:
$("#countries").easyAutocomplete(options);
$(".easy-autocomplete-container").on("show.eac", function(e) {
var inputId = this.id.replace('eac-container-','')
var isFocused = $("#"+inputId).is(":focus")
if (!isFocused ) {
e.stopImmediatePropagation()
}
});
$(".easy-autocomplete-container").each(function() {
$._data(this, 'events')["show"].reverse()
})
Here's a working demo in CodePen