Jquery UI Autocomplete Custom HTML (item is undefined)
I've been banging my head off my desk trying to get the jQuery UI Autocomplete to output custom HTML. Here is my code.
$(document).re开发者_如何转开发ady(function(){
$.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 + "<ul class='autocomplete-category'></ul></li>" );
currentCategory = item.category;
}
self._renderItem( ul, item);
});
}
});
var data = [
{ label: "anders", category: "Antigen" },
{ label: "andreas", category: "Antigen" },
{ label: "antal", category: "Antigen" },
{ label: "annhhx10", category: "Products" },
{ label: "annk K12", category: "Products" },
{ label: "annttop C13", category: "Products" },
{ label: "anders andersson", category: "People" },
{ label: "andreas andersson", category: "People" },
{ label: "andreas johnson", category: "People" }
];
$( "#typeAhead" ).catcomplete({
delay: 0,
source: data,
})
.data( "catcomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.catcomplete", item )
.append( $( "<a class='ui-menu-item'></a>" ).text( item.label ) )
.appendTo( $('ul').last('.autocomplete-category'));
};
});
I seem to be running into trouble by nesting my lists in the renderItem function. The HTML output is exactly how I want it. However when I "keydown" the I get a javascript error (item is undefined).
Any ideas or suggestions? I've tried just about everything.
You were almost there! I only made two changes to get this to work (Updated after comments from OP):
After digging into the jQueryUI autocomplete source, it looks like the underlying menu that's used by the autocomplete widget isn't too friendly toward nested elements.
I could be wrong about this, but I think the menu expects a simple <ul>
with just children <li>
s containing an anchor tag.
Edit: This line confirms my suspicion about the menu (found in jqueryUI 1.8.9's menu widget):
var items = this.element.children("li:not(.ui-menu-item):has(a)")
.addClass("ui-menu-item")
.attr("role", "menuitem");
items.children("a")
.addClass("ui-corner-all")
.attr("tabindex", -1)
// mouseenter doesn't work with event delegation
.mouseenter(function( event ) {
self.activate( event, $(this).parent() );
})
.mouseleave(function() {
self.deactivate();
});
Basically, since your a
tags were buried inside a nested list, they weren't getting recognized by the menu.
I bet you noticed in your original code that your autocomplete menu items were not highlighting when you moused over them. This highlighting actually coincides with which menu item the widget thinks is active, which was causing your widget to fail when the user selected an item.
Since there's nothing semantically wrong or visually wrong with just giving the category li
s a different class, I would restructure the widget's menu like this:
JavaScript:
_renderItem
function:
.data( "catcomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( $( "<a class='ui-menu-item'></a>" )
.text( item.label ) )
.appendTo(ul);
};
Your _renderMenu
function:
_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);
});
}
Generated HTML for AutoComplete menu:
<ul class="ui-autocomplete>
<li class="ui-autocomplete-category">Antigen</li>
<li class="ui-menu-item" role="menuitem">
<a class="ui-menu-item ui-corner-all" tabindex="-1">anders</a>
</li>
<li class="ui-menu-item" role="menuitem">
<a class="ui-menu-item ui-corner-all" tabindex="-1">andreas</a>
</li>
<li class="ui-menu-item" role="menuitem">
<a class="ui-menu-item ui-corner-all" tabindex="-1">antal</a>
</li>
<!-- More categories, items, etc.-->
</ul>
Judging by your comments, it seemed like you wanted the menu's HTML to be nested ul
s inside of li
s for each category. Let me know if changing the HTML of the generated menu isn't an option for you for some reason.
I've updated the example: http://jsfiddle.net/andrewwhitaker/pjs7a/2/
Hope that helps.
精彩评论