13

是否可以在自动完成中禁用列表元素,使其不可选择(并且变灰)?

我有这段代码,取自 jQuery UI 示例页面:

HTML:

<input id="tags" />

jQuery:

$(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
  });
});

例如 - 如果列表中的项目超过 3 个,是否可以禁用最后一个元素?

在我的真实代码中,我有一个 AJAX 请求,但我不想在自动完成框中显示超过 20 个结果,所以如果有更多,它应该显示类似“请缩小搜索范围”并禁用最后一个元素,所以它是不可选择的(但只有最后一个元素应该被禁用)。

上面的代码在这里有一个小提琴演示,http://jsfiddle.net/m6zvf/

4

3 回答 3

30

如果我理解正确,您想添加一个禁用选项,并在结果超过 X 时显示缩小搜索范围的消息,因为您需要自定义response和渲染方法:

工作小提琴

$(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);
        }
    };
});

您可以参考文档以获取有关响应方法的更多信息,该_renderItem函数没有记录,但我在其中一个示例的源代码中找到了它

于 2013-08-27T07:11:15.880 回答
3

通过一些技巧工作,您可以做一些事情:

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/

编辑 :

然后您需要修改渲染器:

$( "#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 );
    };

编辑 2,e.toElement 技巧

在调查事件时发现了这一点:

$("#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);
    };

不再需要 CSS。

http://jsfiddle.net/techunter/zyGNQ/

于 2013-08-27T06:47:10.167 回答
0

箭头键也应该解决。禁用的项目应该被跳过。禁用的项目在源中由属性标记。可以通过更改活动项目和设置相应的类来完成:

    $( "#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;
    }
});
于 2020-11-30T15:34:06.080 回答