Branislav
Branislav

Reputation: 221

jquery ui combobox results sorting

I have a Jquery UI Combobox autocomplete widget, and I'm trying to write a matcher function that will sort search results. I'm trying to get the preferred result:

When you type for eg. lo the results should be sorted this way:

When it's term that matches the first typed letters, it's on the first place, when it's term that contains letters it appears after the first rule.

I've found something similar but I can't make it work. I can't find a way to establish a relation between my matcher variable and term variable in this solution.

Combobox original

source: function( request, response ) {
              // match by first letters in search term
              var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex(request.term), "i" ); 
              response( select.children( "option" ).map(function() {
                var text = $( this ).text();
                if ( this.value && ( !request.term || matcher.test(text) ) )
                  return {
                    label: text.replace(
                      new RegExp(
                        "(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(request.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"
                      ), "<strong>$1</strong>" ),
                    value: text,
                    option: this
                  };
              }) );
            },

Solution for jquery ui autocomplete

$(document).ready(function () {
    // my source is in html
    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));
        }
    });
});

Link to similar answer I found

JS FIDDLE

Any possible feedback would be much appreciated.

Thank you.

Upvotes: 1

Views: 643

Answers (1)

Amac
Amac

Reputation: 168

I was able to get this working by adding the following:

source: function (request, response) {
                var matcher = $.ui.autocomplete.escapeRegex(request.term),
                startsWithMatcher = new RegExp("^" + matcher, "i"), 
                startsWith = $.grep(select.children("option"), function(value) {
                        return startsWithMatcher.test(value.label || value.value || value);
                    }),
                    containsMatcher = new RegExp(matcher, "i"),
                    contains = $.grep(select.children("option"), function (value) {
                        return $.inArray(value, startsWith) < 0 &&
                            containsMatcher.test(value.label || value.value || value);
                    });
                response(startsWith.concat(contains).map(function(option) {
                  var text = $(option).text();
                  var val = $(option).val();  
                  return {
                    label: text,
                    value: val,
                    option: $(option)
                  };
                }));
            }

I also needed to delete the first blank option from the select box otherwise you get an empty result. Instead I added a placeholder for the combobox input

$('.ui-combobox-input').attr('placeholder','Search Here').val('');

JS Fiddle

Upvotes: 1

Related Questions