简体   繁体   中英

jqueryui autocomplete how to pass in an array of keywords to search through for each object?

I'm trying to use jQueryUI Autocomplete to implement a site quick searching feature for various functionality pages in my site. So when they search for "create" it will bring up the Create user option and the Create organisation option. When they search for "create u" it will only show the Create User option. These are just some of the links. But as you can see, each page will have some various keywords/synonyms that would all point to the same page.

Basically I want a structure like this:

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/'
}];

So as they're typing it should look up the links array then search through the keywords arrays looking for a partial text match based on what they've typed in. If it finds one then it will show that entry in the auto completer. But if the second or third search word doesn't match any of the keywords then it will not show it.

Now I've heard you may be able to do it by supplying the source as a callback?

Here's my code so far (Edit: updated with working solution):

        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 = [];

                // Get entered search terms (request.term) from user and search through all links keywords
                for (var k = 0; k < links.length; 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 )
            {
                $( "#searchTerms" ).val( ui.item.label );
                return false;
            },
            select: function( event, ui )
            {
                // Redirect to the url
                $( "#searchTerms" ).val( ui.item.label );
                window.location.replace(ui.item.url);

                return false;
            }
        })
        .data( "autocomplete" )._renderItem = function( ul, item ) {
            return $( "<li></li>" )
                .data( "item.autocomplete", item )
                .append( '<a href=""><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(searchWords, keywords)
        {
            var searchWords = searchWords.toLowerCase();    // Lowercase the search words
            var searchWords = searchWords.split(' ');       // 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;
        }
    });

Ok so the checkSearchWordsMatchKeywords function at the end there definitely works because I've tested it. What isn't working is I don't know what I'm supposed to return from the jQueryUI search: function.

Any help please?

I run over this issue at work. In order to fix it we created our own search function. In order to search in the keywords even if they are in the actual string you want to display.

$( "#searchTerms" ).autocomplete({
   search: function(event, ui) {  
      // Add your super search function here
   }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM