How to disable element in jQuery autocomplete list

前端 未结 3 575
离开以前
离开以前 2020-12-17 16:14

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:

相关标签:
3条回答
  • 2020-12-17 17:12

    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

    0 讨论(0)
  • 2020-12-17 17:12

    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;
        }
    });
    
    0 讨论(0)
  • 2020-12-17 17:13

    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/

    0 讨论(0)
提交回复
热议问题