Is it possible to disable a list element in an autocomplete, so it is not chooseable (and greyed out)?
I have this code, taken from the jQuery UI example page:
If I understand correctly you want to add a disabled option with the message saying to narrow down the search when the results are more than X, for that you'd need a custom response
and render methods:
Working fiddle
$(function () {
$("#tags").autocomplete({
source: availableTags,
response: function (event, ui) {
//Check if we have more than 3 results
if (ui.content.length > 3) {
//Remove all elements until there are only 3 remaining (the use of slice() was not supported)
while (ui.content.length > 3) {
ui.content.pop();
}
//Add message
ui.content.push({
'label': 'Please narrow down your search',
'value': ''
});
}
}
}).data("ui-autocomplete")._renderItem = function (ul, item) {
//Add the .ui-state-disabled class and don't wrap in <a> if value is empty
if(item.value ==''){
return $('<li class="ui-state-disabled">'+item.label+'</li>').appendTo(ul);
}else{
return $("<li>")
.append("<a>" + item.label + "</a>")
.appendTo(ul);
}
};
});
You can refer to the documentation for more info on the response method, the _renderItem
function is not documented but I found it in the source code of one of the examples
Arrow keys should be resolved too. Disabled items should be skipped. Disabled items are marked by attribute in source. It can be done by changing of active item nad setting corresponding class:
$( "#tags" ).autocomplete({
source: [
{value: "ActionScript", disabled: false},
{value: "AppleScript", disabled: true},
{value: "Asp", disabled: false},
{value: "BASIC", disabled: true},
{value: "Erlang", disabled: false},
{value: "Fortran", disabled: true}
],
create: function () {
$(this).data('ui-autocomplete')._renderItem = function (ul, item) {
let value = item.value;
let listItem;
if (item.disabled) {
listItem = $('<li class="ui-state-disabled"><div>' + value + '</div></li>')
.appendTo(ul);
} else {
listItem = $("<li>")
.append('<div>' + value + '</div>')
.appendTo(ul);
}
return listItem;
}
},
select: function (event, ui) {
if (ui.item.disabled) {
// suppress disabled items
event.preventDefault();
}
return false;
},
focus: function (event, ui) {
if (ui.item.disabled) {
//
// skip disabled items
//
let data = $(this).data('ui-autocomplete');
$(data.menu.active).find('div.ui-state-active').removeClass('ui-state-active'); // remove active class
if (event.originalEvent.key === 'ArrowDown') {
let liBefore = $(data.menu.active).prev(); // li before key pressing
let nextLi = data.menu.active;
if (!$(nextLi).is(':last-child')) {
while ($(nextLi).hasClass('ui-state-disabled')) {
// search first not disabled item
nextLi = $(nextLi).next();
}
if (nextLi.length === 0) {
// not found
nextLi = liBefore;
}
} else {
// last item
nextLi = liBefore;
}
// setting of active item in jquery-ui autocomplete
data.menu.active = nextLi;
$(nextLi).find('div').addClass('ui-state-active');
} else {
if (event.originalEvent.key === 'ArrowUp') {
let liBefore = $(data.menu.active).next(); // li before key pressing
let prevLi = data.menu.active;
if (!$(prevLi).is(':first-child')) {
while ($(prevLi).hasClass('ui-state-disabled')) {
// search first not disabled item
prevLi = $(prevLi).prev();
}
if (prevLi.length === 0) {
// not found
prevLi = liBefore;
}
} else {
// first item
prevLi = liBefore;
}
// setting of active item in jquery-ui autocomplete
data.menu.active = prevLi;
$(prevLi).find('div').addClass('ui-state-active');
}
}
}
return false;
}
});
With some trick work you could do something around :
JS
$( "#tags" ).autocomplete({
source: availableTags,
focus:function(e){e.stopPropagation();return false;},
select:function(e){e.stopPropagation();return false;}
});
CSS
.ui-autocomplete .ui-state-focus{
border:0 !important;
background:0 !important;
}
http://jsfiddle.net/techunter/zyGNQ/
EDIT :
You need to modify the renderer then :
$( "#tags" ).autocomplete({
source: availableTags,
focus:function(e, ui){
//if focusing on the extra elements return false thus doing nothing
return ui.item.idx<=2;
},
select:function(e, ui){
//if selecting on the extra elements return false thus doing nothing
return ui.item.idx<=2;}
}) .data( "ui-autocomplete" )._renderItem = function( ul, item ) {
//small trick to get the current element index while the list is constructing, we set this as a helper for later usage inside the item.
item.idx=ul[0].childElementCount;
return $( "<li>" )
//if index is greater than 2 then we add a custom 'disable' class. this will help formating the disabled elements
.toggleClass('disable',ul[0].childElementCount>2)
//appending the element
.append( "<a>" + item.label + "</a>" ).appendTo( ul );
};
EDIT 2, e.toElement trick
found this while looking into the event :
$("#tags").autocomplete({
source: availableTags,
focus: function (e, ui) {
$(e.toElement).toggleClass('ui-state-focus', ui.item.idx <= 2);
return ui.item.idx <= 2;
},
select: function (e, ui) {
return ui.item.idx <= 2;
}
}).data("ui-autocomplete")._renderItem = function (ul, item) {
item.idx = ul[0].childElementCount;
return $("<li>").append("<a>" + item.label + "</a>").appendTo(ul);
};
No more need of the CSS.
http://jsfiddle.net/techunter/zyGNQ/