jQueryUI Автозаполнение - как сопоставить слова поиска со списком ключевых слов и показать соответствующие результаты? - PullRequest
3 голосов
/ 28 января 2012

Я пытаюсь использовать автозаполнение jQueryUI для реализации функции быстрого поиска по сайту для различных страниц функциональности на моем сайте. Я думаю, вы могли бы сказать, что это похоже на Google Instant Search, но оно индексирует страницы на моем сайте.

Таким образом, когда они ищут «создать», это вызовет опцию Создать пользователя и опцию Создать организацию. Когда они ищут «создать использование», будет отображаться только опция «Создать пользователя». Затем они могут нажать на результаты, и он загрузит эту страницу. Это только некоторые из ссылок. Но, как вы можете видеть, каждая страница будет иметь несколько различных ключевых слов / синонимов, которые все указывают на одну и ту же страницу.

Хорошо, так что функция checkSearchWordsMatchKeywords в конце там определенно работает, потому что я ее протестировал. Что не работает, так это то, что я не знаю, что я должен вернуть из функции поиска jQueryUI:

Также, если вы знаете, как оптимизировать эту функцию checkSearchWordsMatchKeywords (), тогда я весь в ушах. :)

Редактировать: обновленный с рабочим решением ниже (работает с jQueryUI 1.9.x):

var links = [
{
    keywords: ['create', 'add', 'make', 'insert', 'user'],
    label: "Create user",
    desc: "Create a user in the system",
    url: 'http://mysite.com/user/create/'
},
{
    keywords: ['create', 'add', 'make', 'insert', 'organisation'],
    label: "Create organisation",
    desc: "Create an organisation in the system",
    url: 'http://mysite.com/organisation/create/'
}];

$('#searchTerms').autocomplete(
{
    minLength: 2,
    source: function(request, response)
    {
        var matched = [];
        var numOfLinks = links.length;

        // Get entered search terms (request.term) from user and search through all links keywords
        for (var k = 0; k < numOfLinks; k++)
        {
            // If it matches, push the object into a new array
            if (checkSearchWordsMatchKeywords(request.term, links[k].keywords))
            {
                matched.push(links[k]);
            }
        }

        // Display the filtered results
        response(matched);
    },
    focus: function(event, ui)
    {
        // When the item is selected, put the label text into the search box
        $('#searchTerms').val(ui.item.label);
        return false;
    },
    select: function(event, ui)
    {
        // Put the selected link's label in the text box and redirect to the url
        $('#searchTerms').val(ui.item.label);

        // Redirect to the page using .href so the previous page is saved into the user's browser history
        window.location.href = ui.item.url;
        return false;
    }
})
.data('autocomplete')._renderItem = function(ul, item)
{
    // Show a description underneath the link label. Using the hyperlink here too so that mouse click still works
    return $('<li></li>')
        .data('item.autocomplete', item )
        .append('<a href="' + item.url + '"><b>' + item.label + '</b><br>' + item.desc + '</a>')
        .appendTo(ul);
};

/**
 * Check that each word in a search string matches at least one keyword in an array
 * E.g. searchWords = 'create use'  and  keywords = ['create', 'add', 'make', 'insert', 'user'] will return true
 */
function checkSearchWordsMatchKeywords(searchString, keywords)
{
    var searchWords = searchString.toLowerCase().split(' ');    // Lowercase the search words & break up the search into separate words
    var numOfSearchWords = searchWords.length;                  // Count number of search words
    var numOfKeywords = keywords.length;                        // Count the number of keywords
    var matches = [];                                           // Will contain the keywords that matched the search words

    // For each search word look up the keywords array to see if the search word partially matches the keyword
    for (var i = 0; i < numOfSearchWords; i++)
    {
        // For each keyword
        for (var j = 0; j < numOfKeywords; j++)
        {   
            // Check search word is part of a keyword
            if (keywords[j].indexOf(searchWords[i]) != -1)
            {
                // Found match, store match, then look for next search word
                matches.push(keywords[j]);
                break;
            }
        }
    }

    // Count the number of matches, and if it equals the number of search words then the search words match the keywords
    if (matches.length == numOfSearchWords)
    {
        return true;
    }

    return false;
}

Перейти к странице

1 Ответ

4 голосов
/ 28 января 2012

У меня нет события "поиск", это место, где вы можете делать то, что вам нужно.Лучше реализовать параметр source в качестве обратного вызова:

$("#searchTerms").autocomplete({
    ...
    source: function(request, response) {        
        var matched = [];
        // Search "request.term" through all links keywords
        for (var k = 0; k < links.length; k++) {
            if (checkSearchWordsMatchKeywords(request.term, links[k]['keywords'])) {
                matched.push(links[k]);
            }
        }
        // display the filtered results
        response(matched);
    }
});
  • объект request содержит свойство term, которое представляет собой текст, который вводится во входные данные
  • параметр response - это обратный вызов, который вы должны вызывать для отображения результатов.

Таким образом, вы получаете и фильтруете свои данные и передаете их в response() для отображения меню.

...