Sunday, April 24, 2011

jqueryui autocomplete optgroup

autocomplete's combobox doesn't support by default the optgroups, so here is what I did,http://www.blogger.com/img/blank.gif
I search every options item in the select to see it it belongs thttp://www.blogger.com/img/blank.gifo a optgroup, then I set the 'category' variable as needed...

that is, I tweaked a little the base code in jqueryui's example, joining combobox and categories

update: the complete code is here: http://bin.cakephp.org/view/73871691

but an approximation can be read in what follows

modified default's "source" method:
source:
function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.find( "option" ).map(function() {
optgroup = $(select).find('option[value="'+this.value+'"]').parent('optgroup');
if (optgroup.length == 0) {
var item_category = 0;
} else {
var item_category = optgroup.attr('label');
}
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>"
)
value: text,
category: item_category,
option: this
};
}) );

then *override _renderMenu*, as the example in 'category' from jqeuryui, but with an extra tweak:
              input.data( "autocomplete" )._renderMenu = function( ul, items ) {
var self = this,
currentCategory = "";
$.each( items, function( index, item ) {
if (item.category == 0) {

} else if ( item.category != currentCategory ) {
ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
currentCategory = item.category;
}
self._renderItem( ul, item );
});
};

6 comments:

  1. Your code doesn't seem to work. Not sure if you pasted it in properly. I'm looking to do the exact same thing with optgroups, but I can't quite figure it out.

    ReplyDelete
  2. It works indeed. I pasted the complete code here: http://bin.cakephp.org/view/73871691

    ReplyDelete
  3. When using the code, it won't pick up my pre-selected value from the HTML. Any ideas?

    ReplyDelete
  4. it should respect the 'selected' parameter... it does in my app... you sure not doing something weird?

    ReplyDelete
  5. Rachel Tan Sang SangAugust 3, 2011 at 9:22 PM

    I had the same problem as Jamie's, then I figured out it might be due to this line:
    selected = select.children( ":selected" )

    You may refer to the following link about .children method:
    http://api.jquery.com/children/

    The points that I would like to draw your attention to are:
    1) .children() method allows us to search through the immediate children ...
    2) The .find() and .children() methods are similar, except that the latter only travels a single level down the DOM tree.

    Since we've added optgroup tags, the option tags are no longer the immediate children of select, so the above line won't pick up the selected value, you may test it by adding alert() to your code:

    selected = select.children( ":selected" ),
    value = selected.val() ? selected.text() : "";
    //add alert here
    //and you'll see no value picked up
    alert(selected.val());

    So, to solve the problem, just use .find() instead:
    selected = select.find(":selected")

    It solves my problem, hope it helps you too.

    ReplyDelete
  6. Worked Great. Thanks. One note. You still need to call


    input.data("autocomplete")._renderItem ...


    as in the original widget code. This needs to be placed **after** the override _renderMenu code above

    ReplyDelete