Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping results in JQuery UI Autocomplete plugin?

I'm trying to create some search functionality across several types of data, with autocomplete. I'd prefer to have custom views for each autocomplete suggestion, as well as for the suggestions to be grouped according to type. The groups should also be separated.

If my explanation is poor, you can see the search functionality on hotels.com for an example: The suggestions are grouped according to city, landmarks, airports etc.

I've been looking at the JQuery UI Autocomplete plugin, and it seems to be able to do most of what I need, but I have not seen any example of the grouping.

Since my javascript/JQuery skills are a bit lacking, I'm hoping someone here could tell me whether it is possible to achieve what I want Autocomplete plugin, or if there's some other plugin that might do the trick? An example/outline of how it can be done would also be greatly appreciated.

like image 457
rogerkk Avatar asked Aug 20 '11 23:08

rogerkk


4 Answers

You can overwrite the way that autocomplete renders by changing the default _renderMenu function. I did something similar to what you are talking about by (1) returning the json results sorted by category and (2) overwriting this function. No code to help you specifically but here is an example from my own code

$.widget( "custom.catcomplete", $.ui.autocomplete, {
        _renderMenu: function( ul, items ) {
            var self = this,
                currentCategory = "";
            $.each( items, function( index, item ) {
                if ( item.category != currentCategory ) {
                    ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
                    currentCategory = item.category;
                }
                self._renderItem( ul, item );
            });
        }
    });
like image 170
natedavisolds Avatar answered Nov 05 '22 13:11

natedavisolds


I tried the above answers. However, one problem is that if the category is not ordered, e.g.

var availableTags = [
        {category: "favourite", label: "c#",         value: "c#", },
        {category: "other",     label: "Java",       value: "Java"},
        {category: "favourite", label: "JavaScript", value: "JavaScript"},
        {category: "other",     label: "J#",         value: "J#"},
    ];

it will create duplicates "favourite" and "other" category.

Here is a working demo I created for jquery ui autocomplete grouping. This can categorize items even when their categories are not in sorted order.

http://jsfiddle.net/jooooice/qua87frd/

$(function(){
    
    var availableTags = [
        {category: "favourite", label: "c#",         value: "c#", },
        {category: "other",     label: "c++",        value: "c++"},
        {category: "other",     label: "c",          value: "c"},
        {category: "other",     label: "Java",       value: "Java"},
        {category: "favourite", label: "JavaScript", value: "JavaScript"},
        {category: "other",     label: "J#",         value: "J#"},
    ];
        
    var customRenderMenu = function(ul, items){
        var self = this;
        var categoryArr = [];
        
        function contain(item, array) {
            var contains = false;
            $.each(array, function (index, value) {
                if (item == value) {
                    contains = true;
                    return false;
                }
            });
            return contains;
        }
        
        $.each(items, function (index, item) {
            if (! contain(item.category, categoryArr)) {
                categoryArr.push(item.category);
            }
            console.log(categoryArr);
        });
        
        $.each(categoryArr, function (index, category) {
            ul.append("<li class='ui-autocomplete-group'>" + category + "</li>");
            $.each(items, function (index, item) {
                if (item.category == category) {
                    self._renderItemData(ul, item);
                }
            });
        });
    };
        
    $("#tags").tagit({
        autocomplete: {
            source: availableTags,
            create: function () {
                //access to jQuery Autocomplete widget differs depending 
                //on jQuery UI version - you can also try .data('autocomplete')
                $(this).data('uiAutocomplete')._renderMenu = customRenderMenu;
            }
        }
    })
});
.ui-autocomplete-group {
    line-height: 30px;
    background-color: #aaa;
}
.ui-menu-item {
    padding-left: 10px;
}
<input id="tags" type="text" />
like image 40
JoyceJi Avatar answered Nov 05 '22 14:11

JoyceJi


This is the accepted answer by @natedavisolds updated for use with Jquery UI 1.10.

  $.widget("custom.catcomplete", $.ui.autocomplete, {
    _renderMenu: function( ul, items ) {
      var that = this;
      var currentCategory = "";
      $.each( items, function( index, item ) {
        if (item.category != currentCategory) {
          $('<li/>').addClass('ui-autocomplete-category').html(convert_category(item.category)).appendTo(ul);
          currentCategory = item.category;
        }
        that._renderItemData( ul, item );
      });
    }   
  });
like image 4
Stephen Avatar answered Nov 05 '22 13:11

Stephen


And in addition, you may replace:

ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );

with:

ul.append( "<span class='ui-autocomplete-category'>" + item.category + "</span>" );

otherwise you will see many errors in the console, like: n is undefined, or item is undefined...

like image 2
the_root Avatar answered Nov 05 '22 12:11

the_root