Sorting Autocomplete UI Results based on match location
Asked Answered
W

3

8

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?

Wondrous answered 28/11, 2011 at 21:24 Comment(0)
L
18

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.

Levin answered 28/11, 2011 at 22:3 Comment(12)
Ah, that makes sense. Here's my variation on your idea: source: function(request, response){ var results = jQuery.ui.autocomplete.filter(data, request.term); results = results.sort(function(a, b){ return a.title.toLowerCase().indexOf(request.term.toLowerCase()) - b.title.toLowerCase().indexOf(request.term.toLowerCase()); }); response(results.slice(0,10)); }Wondrous
@blim8183: Yep, that would definitely work too and might be fasterLevin
Oi, is there a way to format code in comments? That's almost unreadable, glad you could decipher it. Thanks for your help!Wondrous
@blim8183: Sure thing! Just use the backtick (`)Levin
But this doesn't seem to work for multiple values, jQuery autocomplete.??Pluvial
@JavierBrooklyn I'm not sure, I didn't write it with that in mind. It might be worth opening another question if you're having trouble.Levin
Here is the link to question that relates to multiple value jQuery autocomplete - #14785294Pluvial
can you answer that similar question #38857501\Paradies
@blim8183, your code doesn't work when the request term is not found, because indexOf will return -1, and therefore the term will always be at the beginning. So I changed it this way : results = results.sort(function(a, b){ var posa = a.produit.toLowerCase().indexOf(request.term.toLowerCase()); var posb = b.produit.toLowerCase().indexOf(request.term.toLowerCase()); if ( posa == -1 ) posa = 1000; if ( posb == -1 ) posb = 1000; return posa - posb; });Reitareiter
Why are there commas instead of semicolons? It looks unreadable.Frankly
@Frankly The commas aren't instead of semicolons, the two are not interchangeable here. JS variables declared with var are function-scoped. Declaring all of your variables at the top of a function was typically a good practice 12 years ago when this answer was written. Using a single var statement within a function body was also common practice. This code is simply declaring and initializing multiple variables in a single var statement.Levin
@AndrewWhitaker even jsfiddle warns about misleading linebreaks in your code. Imho this would look better jsfiddle.net/0k45r3htFrankly
G
0

A possible optimization: cull items from the source list as they go into startsWith, and then you don't need to test for repetition when appending things that contain the search string. However, the trade-off is that the source array would need to be regenerated every time the input string changed.

Garlandgarlanda answered 16/1, 2014 at 15:57 Comment(3)
This would make a better comment (though do I know you probably can't comment yet :) )Herdsman
I wanted to post it as a comment. But, as you say.Garlandgarlanda
Better yet, in terms of deduping, is to use this slick one-liner to clean it up after the fact. gist.github.com/jasdeepkhalsa/5227812Garlandgarlanda
R
0

It does seem to have problems when spaces are present in between words, please try the following as source

    source=[" Family And Community " , 
" Finance And Legal " , 
" Food And Beverages " , 
" Government " , 
" Health And Medicine " , 
" Home And Garden " , 
" Industrial Supplies And Services " ,
 " Non-governmental Organisations (ngos) " , 
" Personal Care " , 
" Public Utilities And Environment " , 
" Real-estate And Insurance " , 
" Religious Organisations And Associations " , 
" Shopping And Specialty Stores " , 
" Sports And Recreation " ,
 " Transportation " , 
" Travel And Tourism " , 
" Farming " , 
" Farming Equipments And Services " , 
" Feed, Seed And Grain " , 
" Fishing " , 
" Fishing Equipments And Services " , 
" Forests " , 
" Timber Equipments And Services " , 
" General Supplies And Services " , 
" Livestock " , 
" Wildlive " , 
" Minerals And Organic Matte " , 
" Accessories " , 
" Detailing And Aesthetics " , 
" Motorcycles " , 
" Motorised Vehicles " , 
" New And Used Dealers " , 
" Parts And Supplies " , 
" Related Services " , 
" Repairs Body Work " , 
" Repairs Mechanical " , 
" Trailers " , 
" Administrative And Specialty Services " , 
" Advertising " , 
" Associations - Organisations " , 
" Communication And Audio-visual " , 
" Consultants " , 
" Document Services " , 
" Employment And Career Resources " , 
" Engineers " , 
" Furniture And Office - Industrial Machines " , 
" Import And Export Services " , 
" Lawyers " , 
" Marketing And Sales " , 
" Office Supplies - General " , 
" Printing, Publishing And Copying " , 
" Shipping, Packaging And Postal Services " , 
" Trade Shows, Expositions And Conventions " , 
" Alterations And Services " , 
" Clothing - General " , 
" Clothes And Fashion Accessories " , 
" Footwear " , 
" Outerwear " , 
" Uniforms And Work Clothing " , 
" Communications Services And Equipments " , 
" Computer Equipments " , 
" Computer Services " , 
" Electronics - Services And Equipments " , 
" Information Systems " , 
" Internet - Communication And Events " , 
" Internet - Development And Services " , 
" Building Materials And Equipments " , 
" Ceramics And Tiles " , 
" Chimneys " , 
" Concrete, Cement And Paving " , 
" Contractor Equipments And Services " , 
" Design And Architecture " , 
" Electrical Products And Services " , 
" Floors, Ceilings And Roofs " , 
" Foundations And Piling " , 
" Hardware - Supplies And Services " , 
" Heavy Construction And Equipments " , 
" Inspectors And Surveyors " , 
" Painting And Plastering " , 
" Plumbing And Piping " , 
" Academic " , 
" Libraries " , 
" Services And Supplies " , 
" Specialised Schools "]
Rolfe answered 25/6, 2015 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.