JQueryUI smartAutocomplete






4.75/5 (9投票s)
这个小部件通过在从远程源加载数据时添加无限滚动,扩展了 jQueryUI Autocomplete 小部件的功能。

引言
这个小部件通过在从远程源加载数据时添加无限滚动,扩展了 jQueryUI Autocomplete 小部件 的功能。
您可以在 我的博客上找到原始文章。
先决条件
- JavaScript, jQuery, jQueryUI
- ASP.NET
背景
假设我们有一个项目正在使用 Autocomplete Widget,并且每次按键给出的结果数量非常多,影响了应用程序的响应速度。
我们希望能够最初只加载少量项目,并且对于每次其他请求,只加载给定数量的项目。 因此,我们将加载前 N 个项目,并且当用户到达最后一个项目时(通过滚动到它或不断按下向下键直到到达最后一个项目),我们向服务器发出另一个请求以加载接下来的 N 个项目。
Using the Code
假设我们有一个输入框
<input id="inp" style="width: 350px;" type="text" />
以及小部件实现
$("#inp").autocomplete(options);
有关此代码的更多详细信息,请访问 jQueryUI Autocomplete 文档网站。
我们希望尽可能少地更改代码,以获得无限滚动的预期效果。 新代码将如下所示
$("#inp").smartautocomplete({
getDataFunc: getData,
pageSize: 15
...
});
为了本示例的目的,我使用了一个 ASP.NET 应用程序,该应用程序公开了一个 WebMethod
,该方法返回一些虚拟数据以与我们的输入一起使用。 该函数如下所示
//In this example I use a WebMethod, but you can call anything from a
//local source to a web service.
var getData = function (input, pageIndex, pageSize, callback) {
PageMethods.GetData(input, pageIndex, pageSize, function (response) {
if (response) {
//Data is assumed to be received in a {label: , value: , ...} form,
//as needed by jQueryUI Autocomplete. Of course, if you change
//the _renderItem function, you are free to modify this as you want
response = $.map(response, function (item) {
return {
label: item,
value: item
}});
callback(response);
}
else callback();
});
}
如上所示,我们有一个从中获取数据的来源。 它可以是 Web 服务或其他任何东西。
代码
我们将不得不创建一个包装器小部件,该小部件在下面具有原始的自动完成小部件,但是以略有不同的方式处理数据加载逻辑。 我们首先按照 jQuery 插件创作文档的说明创建一个 jQuery 插件。 新的小部件将采用两个新参数
pageSize
:每次请求加载的项目数getDataFunc
:用于从服务器返回数据的要调用的函数
我们用我们自己的函数覆盖 option.source
参数,该函数可以执行魔法
//We overwrite the source logic to call our getDataFunc function
options.source = function (request, response) {
...
//We call the function to get the data
options.getDataFunc(term, pageIndex + 1, options.pageSize, function (r) {
if (r) {
//We allow scrolling
if (!r.length)
startedLoadingFromScroll = false;
//If data already exists, we add our new data to the existing data
if (data.length)
for (var i = 0; i < r.length; i++)
data.push(r[i]);
else data = r;
response(data);
//We scroll to the last position
autocomplete.scrollTop(lastScrollTop);
//We increment the current page index
pageIndex++;
}
});
...
};
接下来,我们绑定到由自动完成小部件触发的几个事件。 我们首先绑定到 autocompletecreate
事件,以便在自动完成小部件创建后立即实现我们自己的功能。 在这里,我们将绑定到自动完成下拉列表的滚动事件,以处理我们到达列表末尾的情况。 我们通过不断验证以下不等式来实现此目的
autocomplete[0].scrollHeight - autocomplete.scrollTop()
只有当我们滚动到列表末尾时,结果才为 true
。 如果是这种情况,我们将调用我们的 startSearching
函数。
.bind('autocompletecreate', function () {
//We get the elements created by JqueryUI Autocomplete
autocomplete = $(this).autocomplete('widget');
menu = parent.data().autocomplete.menu.element;
if (autocomplete.attr('sa-scroll') != 'on') {
//We create the scrolling functionality to request new data
//when we arrived at the end of list
autocomplete.scroll(function (e) {
if (loading)
return stopEvent(e);
if (startedLoadingFromScroll) {
if ($.browser.msie || $.browser.mozilla)
autocomplete.scrollTop(lastScrollTop);
return stopEvent(e);
}
if (autocomplete[0].scrollHeight - autocomplete.scrollTop()
接下来,我们绑定到 autocompletefocus
。 每次我们使用键盘在下拉项中导航时,都会调用此方法。 默认情况下,自动完成为焦点元素提供类 ui-state-hover。 因此,通过验证 autocomplete.find(".ui-menu-item:last .ui-state-hover").length == 1
,我们可以确定*最后一项已聚焦。 这是我们需要加载更多数据的另一种情况。
.bind('autocompletefocus', function (event, ui) {
focusedItem = ui.item;
if (ignoreFocus) {
ignoreFocus = false;
return;
}
//If we reached the last element in the list, we get new data
if (autocomplete.find(".ui-menu-item:last .ui-state-hover").length)
startSearching();
})
*jQueryUI 有一种特定的方式来呈现列表项。 如果我们 更改项的呈现方式,则必须重新考虑此验证。
然后,我们绑定到 autocompleteopen
以将焦点设置到下拉列表关闭之前最后聚焦的项目。
.bind('autocompleteopen', function (event, ui) {
if (!selectedIndex) {
if (options.autoFocus) {
ignoreFocus = true;
menu.menu('activate', event, autocomplete.find(".ui-menu-item:first"));
}
}
else {
ignoreFocus = true;
menu.menu('activate', event, autocomplete.find
(".ui-menu-item:eq(" + selectedIndex + ")"));
}
})
我们要做的最后一件事是绑定到 autocompleteclose
以重置我们的搜索数据。
.bind('autocompleteclose', function (event, ui) {
//When the dropdown closes, we reset the current search
resetData();
})
未来开发需要考虑的事项
- 该小部件利用了尚未发布的 Menu Widget。 因此,其功能的任何更改都会直接影响我们的功能。
- 我们基于以下前提找到焦点项目的算法:它具有 ui-state-hover 类。 当自定义搜索结果渲染系统时,这可能不是一件好事。
- 应为本地源实现分页。
历史
- 2012 年 2 月 4 日:初始版本
- 2012 年 2 月 22 日:更新的源代码