Reputation: 91
I'm using jQuery UI Autocomplete with a categorized search result and I want to spice it up with CSS.
Unfortunately, jQuery UI doesn't make it easy and the default markup is really difficult to work with:
<input class="ui-autocomplete-input"/>
<ul class="ui-autocomplete ui-menu ui-widget ui-widget-content ui-corner-all">
<li class='ui-autocomplete-category'>Category 1</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 1</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 2</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 3</a>
</li>
<li class='ui-autocomplete-category'>Category 2</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 1</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 2</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 3</a>
</li>
</ul>
The markup that I want is this:
<input class="ui-autocomplete-input"/>
<ul class="ui-autocomplete ui-catcomplete">
<div class="ui-block">
<div class="ui-autocomplete-category">Category 1</div>
<div class="ui-list">
<li class="ui-menu-item">
<a class="ui-corner-all">item 1</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 2</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 3</a>
</li>
</div>
</div>
<div class="ui-block">
<div class="ui-autocomplete-category">Category 1</div>
<div class="ui-list">
<li class="ui-menu-item">
<a class="ui-corner-all">item 1</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 2</a>
</li>
<li class="ui-menu-item">
<a class="ui-corner-all">item 3</a>
</li>
</div>
</div>
</ul>
And that's where I reach my limit.
I actually managed to create the markup, but I could no longer select and submit by clicking on the item.
Here is the code I came up with:
$.widget( "custom.catcomplete", $.ui.autocomplete, {
_renderMenu: function( ul, items ) {
var self = this,
currentCategory = "",
i = 0;
$.each( items, function( index, item ) {
if ( item.category != currentCategory ) {
ul.append( "<div class='ui-autocomplete-category'>" + item.category + "</div>");
currentCategory = item.category;
}
self._renderItem( ul, item );
});
/* This is how I thought it would work */
ul.find('.ui-autocomplete-category').each(function() {
$(this).nextUntil('div')
.andSelf()
.wrapAll('<div class="ui-block">')
.nextUntil('div')
.wrapAll('<div class="ui-list">');
});
},
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
});
$(function() {
$( "#ui-autocomplete-input" ).catcomplete({
source: '<?php echo SITEURL?>/users/complete/',
delay: 0,
autoFocus: true,
select: function(event, ui) {
if(ui.item)
{
$('#ui-autocomplete-input').attr('value',ui.item.value);
}
$('#ui-autocomplete-form').submit();
}
});
});
So basically, the select: function part doesn't work at all.
Could anyone help me with this?
I'm sure there is a simpler way to modify the default markup and make it work just fine.
This is what I want it to look like:
Upvotes: 4
Views: 7871
Reputation: 91
I eventually found the solution by myself and it involves some CSS trickery and some simple jQuery.
CSS:
.ui-autocomplete {
width:424px;
margin:0;
padding:0 0 14px 0;
}
.ui-autocomplete-category {
width:100px;
position: absolute;
padding:0 20px;
margin:20px 0 0 0;
}
.ui-menu-item {
padding-left:140px;
}
.ui-first {
padding-top:20px;
}
jQuery:
$( "#search" ).catcomplete({
delay: 0,
source: data,
autoFocus: true,
select: function(event, ui) {
if(ui.item) { $('#search').attr('value',ui.item.value);}
$('#form').submit();
},
/* This is the important part! */
open: function() {
$('.ui-autocomplete-category').next('.ui-menu-item').addClass('ui-first');
}
});
Basically, I play with absolute positioning for putting the category name on the left and I add a class to the first LI element with jQuery in order to create some spacing with PADDING.
It's not perfect but it works flawlessly :)
Upvotes: 4
Reputation: 12838
You could solve this without changing the HTML with a little bit of CSS trickery:
ul.ui-autocomplete {
padding-left: 200px;
}
ul.ui-autocomplete li.ui-autocomplete-category {
width: 200px;
height: 50px;
margin-left: -200px;
margin-bottom: -50px;
}
It's not perfect (the height of the category li might exceed the height of the results - OR it might not fit the contents of the li) but it works.
Btw: the only valid child element of a ul is a li. So span wouldn't help you either.
Upvotes: 1