jQuery autocomplete should skip disabled element when using keyboard
Asked Answered
P

2

7

If you see this Fiddle demo, not done by me, how can I then avoid that the keyboard can go down and choose the disabled element? The mouse is working fine (not being able to select it) but I can go down with the keyboard and select it, resulting in an empty search :-/

The Fiddle demo is from this post, How to disable element in jQuery autocomplete list

jQuery code:

$(function () {
var availableTags = [
    "ActionScript",
    "AppleScript",
    "Asp",
    "BASIC",
    "C",
    "C++",
    "Clojure",
    "COBOL",
    "ColdFusion",
    "Erlang",
    "Fortran",
    "Groovy",
    "Haskell",
    "Java",
    "JavaScript",
    "Lisp",
    "Perl",
    "PHP",
    "Python",
    "Ruby",
    "Scala",
    "Scheme"];

$("#tags").autocomplete({
    source: availableTags,
    response: function (event, ui) {
        if (ui.content.length > 3) {
            while (ui.content.length > 3) {
                ui.content.pop();
            }
            ui.content.push({
                'label': 'Please narrow down your search',
                    'value': ''
            });
        }
    }
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    return $("<li " + (item.value == '' ? 'class="ui-state-disabled"' : '') + ">")
        .append("<a>" + item.label + "</a>")
        .appendTo(ul);
};
});
Prothonotary answered 27/8, 2013 at 12:31 Comment(1)
I also have the same problem...Debor
S
4

Autocomplete "knows" to highlight items based on the presense of an <a> inside each li. You can disable keyboard selection of an event by just removing the anchor:

.data("ui-autocomplete")._renderItem = function (ul, item) {
        var $el = $("<li>");
        if (item.value === '') {
            $el.addClass("ui-state-disabled")
               .text(item.label);

        } else {
            $el.append("<a>" + item.label + "</a>");
        }

        return $el.appendTo(ul);
    };

Example: http://jsfiddle.net/m6zvf/12/

Sweat answered 27/8, 2013 at 14:17 Comment(6)
Why write var $el = $("<li>") and not just var el = $("<li>")? Is the $-sign an old habbit from other coding language or is it required elsewhere in jQuery?Prothonotary
It's a convention that you can use if you want to designate that a variable contains a jQuery object. It's just convention, not required. See this this question for more info.Sweat
This no longer seems to work with the new jQuery UI (1.11). Would love to see a solution for that.Rubble
@ragulka: I don't have time to come up with an example now, but the "categories" example here jqueryui.com/autocomplete/#categories has an example of items in the list that cannot be selected.Sweat
@AndrewWhitaker: thanks, that's a good start - it seems that it's only a matter of using a different class for the non-selectable items.Rubble
@Rubble surely this is a bug in jQuery UI 1.11? Having to explicitly set this.widget().menu("option", "items", "> :not(.ui-state-disabled)"); seems odd to me.Burden
I
3

Alternatively to Andrews answer, if you want to preserve the down key wrapping the focus to the first item, you can use the focus event to trigger a mouseenter on the first item upon the unfocusable item coming into focus.

Just add the code below as a focus property

WORKING JS FIDDLE

    focus: function(event, ui){
        var curr = $(event.currentTarget).find('a.ui-state-focus');
        if(curr.parent().hasClass('ui-state-disabled'))
        {
            event.preventDefault(); 
            curr.parent().siblings().first().children('a').mouseenter();  
        }
    }
Irremediable answered 27/8, 2013 at 14:57 Comment(1)
mouseenter dos not put value into an input so I trigger keydown: focus : function(event, ui) { if (ui.item === '') { event.preventDefault(); // skip first item and select second one var secondItem = $(event.currentTarget).children().eq(1); var e = jQuery.Event("keydown"); e.keyCode = 40; secondItem.trigger(e); } }Holstein

© 2022 - 2024 — McMap. All rights reserved.