如何在Ajax中使用实现自动完成插件? [英] How to use materialize autocomplete plugin with ajax?
问题描述
我正在尝试将 materializecss自动完成插件与我的ajax调用一起使用根据输入字段上的内容动态加载数据.
I am trying to make work together the materializecss autocomplete plugin with my ajax call in order to dynamically load data according to what is typed on the input field.
我的ajax请求在一个keydown事件中被调用.所有获取的数据都会自动推送到键/值对象数组中.
My ajax request is called inside a keydown event. All data fetched are automatically pushed into a key/value object array.
然后,我将自动完成功能放在ajax的成功函数中,并且键"data"的值是之前建立的对象数组.
Then, i put the autocomplete function in the ajax's success function and the value of the key "data" is the object array built right before.
看来我是个好方法,但是当我在浏览器中进行测试时,每次我键入内容时,建议下拉菜单都会按预期显示结果,但不是每次按键后都更新提示,而是另一个下拉列表与上一个等等...
It's seems i am on the good way but when i am testing in the browser, each time i type something, the suggestion dropdown shows up as expected with results, but rather than be renewed after each keydown, another dropdown list overlap the previous one and so one...
这就是我的问题:如何避免下拉建议列表重叠,而是在每次按下键时使它重新显示?
So this is my problem : How to do to avoid the dropdown suggestion list to overlap and rather make it renew each time i press a key ?
感谢您的帮助.
var dat = {};
$('input').on('keydown',function(e){
var d = {
"query": {
"prefix": {
"body": e.target.value
}
}
};
$.ajax({
url:'https://xxxxxxxxxxxxxxx.eu-west-1.es.amazonaws.com/xxxxxxxxxxxxx',
type:'POST',
contentType : "application/json",
crossDomain : true,
data:JSON.stringify(d),
dataType:'JSON',
async:true,
success: function(da){
var c = da.hits.hits.length;
for(var i = 0; i < c; i++){
dat[da.hits.hits[i]._source.body] = null;
}
$("input").autocomplete({
data : dat
},
error: function(jqXHR, errorStatus, errorThrown){
console.log(jqXHR);
console.log(errorStatus);
console.log(errorThrown);
}
})
推荐答案
以@ friek108的出色答案为基础,让我们添加以下功能.
Building on top of @friek108's excellent answer, let's add the following features.
- 在其外部单击时关闭自动完成小部件.
- 允许使用箭头键滚动结果并使用Enter键进行选择.
- 仅在输入预定义的最小字符数之后,才进行AJAX调用.
- 阻止某些键触发AJAX调用.
这采用了超时& @ friek108的答案中的ajax呼叫取消功能.您可能要先检查一下.
This adopts the timeout & ajax call cancelling features from @friek108's answer. You might want to check it first.
ajaxAutoComplete({inputId:'autocomplete-input',ajaxUrl:'/search/my-auto-complete-results'})
function ajaxAutoComplete(options)
{
var defaults = {
inputId:null,
ajaxUrl:false,
data: {},
minLength: 3
};
options = $.extend(defaults, options);
var $input = $("#" + options.inputId);
if (options.ajaxUrl){
var $autocomplete = $('<ul id="ac" class="autocomplete-content dropdown-content"'
+ 'style="position:absolute"></ul>'),
$inputDiv = $input.closest('.input-field'),
request,
runningRequest = false,
timeout,
liSelected;
if ($inputDiv.length) {
$inputDiv.append($autocomplete); // Set ul in body
} else {
$input.after($autocomplete);
}
var highlight = function (string, match) {
var matchStart = string.toLowerCase().indexOf("" + match.toLowerCase() + ""),
matchEnd = matchStart + match.length - 1,
beforeMatch = string.slice(0, matchStart),
matchText = string.slice(matchStart, matchEnd + 1),
afterMatch = string.slice(matchEnd + 1);
string = "<span>" + beforeMatch + "<span class='highlight'>" +
matchText + "</span>" + afterMatch + "</span>";
return string;
};
$autocomplete.on('click', 'li', function () {
$input.val($(this).text().trim());
$autocomplete.empty();
});
$input.on('keyup', function (e) {
if (timeout) { // comment to remove timeout
clearTimeout(timeout);
}
if (runningRequest) {
request.abort();
}
if (e.which === 13) { // select element with enter key
liSelected[0].click();
return;
}
// scroll ul with arrow keys
if (e.which === 40) { // down arrow
if (liSelected) {
liSelected.removeClass('selected');
next = liSelected.next();
if (next.length > 0) {
liSelected = next.addClass('selected');
} else {
liSelected = $autocomplete.find('li').eq(0).addClass('selected');
}
} else {
liSelected = $autocomplete.find('li').eq(0).addClass('selected');
}
return; // stop new AJAX call
} else if (e.which === 38) { // up arrow
if (liSelected) {
liSelected.removeClass('selected');
next = liSelected.prev();
if (next.length > 0) {
liSelected = next.addClass('selected');
} else {
liSelected = $autocomplete.find('li').last().addClass('selected');
}
} else {
liSelected = $autocomplete.find('li').last().addClass('selected');
}
return;
}
// escape these keys
if (e.which === 9 || // tab
e.which === 16 || // shift
e.which === 17 || // ctrl
e.which === 18 || // alt
e.which === 20 || // caps lock
e.which === 35 || // end
e.which === 36 || // home
e.which === 37 || // left arrow
e.which === 39) { // right arrow
return;
} else if (e.which === 27) { // Esc. Close ul
$autocomplete.empty();
return;
}
var val = $input.val().toLowerCase();
$autocomplete.empty();
if (val.length > options.minLength) {
timeout = setTimeout(function () { // comment this line to remove timeout
runningRequest = true;
request = $.ajax({
type: 'GET',
url: options.ajaxUrl + val,
success: function (data) {
if (!$.isEmptyObject(data)) { // (or other) check for empty result
var appendList = '';
for (var key in data) {
if (data.hasOwnProperty(key)) {
var li = '';
if (!!data[key]) { // if image exists as in official docs
li += '<li><img src="' + data[key] + '" class="left">';
li += "<span>" + highlight(key, val) + "</span></li>";
} else {
li += '<li><span>' + highlight(key, val) + '</span></li>';
}
appendList += li;
}
}
$autocomplete.append(appendList);
}else{
$autocomplete.append($('<li>No matches</li>'));
}
},
complete: function () {
runningRequest = false;
}
});
}, 250); // comment this line to remove timeout
}
});
$(document).click(function () { // close ul if clicked outside
if (!$(event.target).closest($autocomplete).length) {
$autocomplete.empty();
}
});
}
}
我没有将结果一个接一个地附加到自动完成小部件中,而是将所有这些结果与一个长字符串附加在一起,以加快处理速度. (正确阅读jQuery .append()方法的精彩分析此处).
Instead of appending results to the autocomplete widget one by one, I've appended all of them together with one single, long string to make the process faster. (Read a wonderful analysis of jQuery .append() method here).
这篇关于如何在Ajax中使用实现自动完成插件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!