Я изучаю использование виджета jQuery UI autocomplete для реализации поиска пользователя по имени или фамилии. Похоже, что автозаполнение по умолчанию просматривает слова по последовательности символов, независимо от его появления в слове. Поэтому, если у вас есть такие данные, как: javascript, asp, haskell
и вы вводите 'as'
, вы получите все три. Я бы хотел, чтобы это соответствовало началу слова. Поэтому в приведенном выше примере вы получаете только 'asp'
. Есть ли способ настроить виджет автозаполнения для этого?
В конечном итоге было бы лучше совпадение по началу первого или последнего имени, как в Gmail.
Примечание. Я пытаюсь выяснить, как это сделать, используя виджет jQuery UI. Поскольку я уже использую jQuery UI в своем проекте, я планирую придерживаться его и стараюсь не добавлять дополнительные библиотеки в свое веб-приложение.
В jQuery UI v1.8rc3, виджет автозаполнения принимает source, который может быть либо строкой, либо массивом, либо функцией обратного вызова. Если это строка, автозаполнение делает GET на этом URL-адресе, чтобы получить параметры/предложения. Если массив, автозаполнение выполняет поиск, как вы указали, для наличия типизированных символов в любой позиции в терминах массива. Окончательный вариант - это то, что вы хотите - функция обратного вызова.
Из документации автозаполнения:
Третий вариант, обратный вызов, обеспечивает максимальную гибкость и может использоваться для подключения любого источника данных к автозаполнению. Обратный вызов получает два аргумента:
• Объект
request
с единственным свойством, называемым "term", который ссылается на значение, которое в настоящее время присутствует в текстовом вводе. Например, когда пользователь вводил "новое лет" в поле города, которое настроено на выполнение автозаполнения,request.term
будет удерживать "новый год".
• Функцияresponse
, обратный вызов, который ожидает, что один аргумент будет содержать данные, предлагаемые пользователю. Эти данные должны быть отфильтрованы на основе предоставленного термина и должны быть массивом в формате, разрешенном для простых локальных данных: String-Array или Object-Array с меткой/значением/оба свойства.
Пример кода:
var wordlist= [ "about", "above", "across", "after", "against",
"along", "among", "around", "at", "before",
"behind", "below", "beneath", "beside", "between",
"beyond", "but", "by", "despite", "down", "during",
"except", "for", "from", "in", "inside", "into",
"like", "near", "of", "off", "on", "onto", "out",
"outside", "over", "past", "since", "through",
"throughout", "till", "to", "toward", "under",
"underneath", "until", "up", "upon", "with",
"within", "without"] ;
$("#input1").autocomplete({
// The source option can be an array of terms. In this case, if
// the typed characters appear in any position in a term, then the
// term is included in the autocomplete list.
// The source option can also be a function that performs the search,
// and calls a response function with the matched entries.
source: function(req, responseFn) {
var re = $.ui.autocomplete.escapeRegex(req.term);
var matcher = new RegExp( "^" + re, "i" );
var a = $.grep( wordlist, function(item,index){
return matcher.test(item);
});
responseFn( a );
}
});
Несколько ключевых моментов:
$.ui.autocomplete.escapeRegex(req.term);
, который ускоряет поиск
так что любые регулярные выражения, содержащиеся в тексте, введенном пользователем, рассматриваются как простой текст. Например, точка (.) Имеет смысл для регулярного выражения. Я узнал об этой функции escapeRegex, прочитав исходный код автозаполнения.new Regexp()
. Он задает регулярное выражение, начинающееся с ^ (Circumflex), что подразумевает, что оно будет соответствовать только тогда, когда типизированные символы появятся в начале члена в массиве, чего вы хотели. Он также использует опцию "i", которая подразумевает нечувствительность к регистру.$.grep()
просто вызывает предоставленную функцию для каждого термина в предоставленном массиве. Функция в этом случае просто использует regexp, чтобы увидеть, соответствует ли член в массиве для того, что было напечатано.рабочая демонстрация: http://jsbin.com/ezifi
как выглядит:
Просто примечание: я считаю, что документация по автозаполнению будет довольно незрелой на данный момент. Я не нашел примеров, которые сделали это, и я не мог найти рабочий документ, для которого необходимы файлы .css или какие классы .css будут использоваться. Я узнал все это от проверки кода.
См. также как я могу настроить параметры подключаемого модуля Autocomplete?
escapeRegex
и ваш пост прекрасно это объясняет.
Я использую автозаполнение из devbridge. http://www.devbridge.com/projects/autocomplete/jquery/
Он совпадает только с начальными символами.
alt text http://i46.tinypic.com/2ihq7pd.jpg
Что касается соответствия на основе имени или фамилии, вам просто нужно предоставить список поиска с именем и фамилией.
Пример использования:
var wordlist = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December' ];
var acOptions = {
minChars:2,
delimiter: /(,|;)\s*/, // regex or character
maxHeight:400,
width:300,
zIndex: 9999,
deferRequestBy: 10, // miliseconds
// callback function:
onSelect: function(value, data){
//$('#input1').autocomplete(acOptions);
if (typeof data == "undefined") {
alert('You selected: ' + value );
}else {
alert('You selected: ' + value + ', ' + data);
}
},
// local autosuggest options:
lookup: wordlist
};
Параметр lookup
, который вы передаете для инициализации элемента управления автозаполнением, может быть списком или объектом. Вышеприведенное показало простой список. Если вы хотите, чтобы некоторые данные были привязаны к возвращаемым предложениям, сделайте lookup
опцией объект, например:
var lookuplist = {
suggestions: [ "Jan", "Feb", "Mar", "Apr", "May" ],
data : [ 31, 28, 31, 30, 31, ]
};
спасибо cheeso для создания jsbin.com,
i расширил ваш код для поддержки совпадений с первым и последним.
$("#input1").autocomplete({
source: function(req, responseFn) {
addMessage("search on: '" + req.term + "'<br/>");
var matches = new Array();
var needle = req.term.toLowerCase();
var len = wordlist.length;
for(i = 0; i < len; ++i)
{
var haystack = wordlist[i].toLowerCase();
if(haystack.indexOf(needle) == 0 ||
haystack.indexOf(" " + needle) != -1)
{
matches.push(wordlist[i]);
}
}
addMessage("Result: " + matches.length + " items<br/>");
responseFn( matches );
}
});
demo: http://jsbin.com/ufimu3/
введите 'an' или 're'
Если вы хотите найти начало каждого слова в строке, более элегантным решением для ханчмана является использование cheeso, но просто используйте специальный символ границы слова регулярного выражения:
var matcher = new RegExp( "\\b" + re, "i" );
Пример: http://jsbin.com/utojoh/2 (попробуйте найти 'bl')
Где вы получаете данные для заполнения автозаполнения? Это из базы данных? Если это так, вы можете делать то, что хотите в своем запросе, и возвращать результаты, соответствующие началу каждого слова (имя/фамилия)
Theres еще один подключаемый модуль автозаполнения jQuery, который по желанию выполняет поиск только в начале каждого элемента (опция matchContains=false
, я думаю, что это тоже значение по умолчанию).
Учитывая отсутствие такой опции в плагине jQuery UI, я предполагаю, что вам придется либо использовать другой плагин, либо переписать тот, который вы используете сейчас.