Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting Autocomplete UI Results based on match location

I'd like to sort my jQuery Autocomplete UI results based on where in the string the match occurs. The results where the match is the first letter should be prioritized above results in which the match is in the middle of the string.

A search for "M" should return:

Matt, Michael, Sam, Tim, Adam, Benjamin

Instead, since it's just returning the items in alphabetical order right now, I'm getting this:

Adam, Benjamin, Matt, Michael, Sam, Tim

Unfortunately, it looks like Autocomplete UI doesn't have any options for doing something like this, instead it just presents the results in the order it received them. Having MySql do the sorting isn't an option since all the possible matches are preloaded so that I'm not making calls to the database with every keystroke. Has anybody done anything like this?

like image 213
blim8183 Avatar asked Nov 28 '11 21:11

blim8183


1 Answers

You can provide any local filtering logic you'd like by providing the source option a function instead of a simple array. Here's a quick example that will do the basics of what you want:

var source = ['Adam', 'Benjamin', 'Matt', 'Michael', 'Sam', 'Tim'];
$("input").autocomplete({
    source: function (request, response) {
        var term = $.ui.autocomplete.escapeRegex(request.term)
            , startsWithMatcher = new RegExp("^" + term, "i")
            , startsWith = $.grep(source, function(value) {
                return startsWithMatcher.test(value.label || value.value || value);
            })
            , containsMatcher = new RegExp(term, "i")
            , contains = $.grep(source, function (value) {
                return $.inArray(value, startsWith) < 0 &&
                    containsMatcher.test(value.label || value.value || value);
            });

        response(startsWith.concat(contains));
    }
});

Example: http://jsfiddle.net/zkVrs/

Basically, the logic is to build up an array of matches that start with the term, and then concatenate that with matches that contain the term but don't start with it.

Performance could be a problem here, especially with the $.inArray call. Might be a better way to accomplish that portion, but hopefully that will give you a good starting point.

like image 101
Andrew Whitaker Avatar answered Sep 22 '22 14:09

Andrew Whitaker