jQuery UI自动完成类别如何跳过类别标题

时间:2011-05-31 16:29:21

标签: jquery-ui autocomplete jquery-ui-autocomplete categories

我的Web应用程序中有一个工作自动完成字段,我正在寻找一种方法来增加字段的可用性,当使用箭头键向下滚动可用选项时,以某种方式自动跳过类别字段(输入部分搜索词后)。

例如,如果用户开始键入“an”,则自动完成将显示两个类别,每个类别中包含项目。用户想要在“人物”下选择列表中的一个项目。他们使用箭头键向下移动列表。目前,此代码将结果中的类别作为列表项插入。使用箭头键时,必须移动它们才能突出显示并选择结果。应用程序可以自动跳过这些类别标题吗?

$.widget( "custom.catcomplete", $.ui.autocomplete, {
        _renderMenu: function( ul, items ) {
            var self = this,
                currentCategory = "";
            $.each( items, function( index, item ) {
                if ( item.category != currentCategory ) {
                    ul.append( "<li class='ui-menu-item ui-category'>" + item.category + "</li>" );
                    currentCategory = item.category;
                }
                self._renderItem( ul, item );
            });
        }
    });

    var data = [
        { label: "annk K12", category: "Products" },
        { label: "annttop C13", category: "Products" },
        { label: "anders andersson", category: "People" },
        { label: "andreas andersson", category: "People" },
        { label: "andreas johnson", category: "People" }
    ];

    $( "#textfield" ).catcomplete({
        source: data,
        select: function(event, ui) {
            window.location.hash = "id_"+escape(ui.item.id);
        }
    });

2 个答案:

答案 0 :(得分:5)

这一行:

ul.append( "<li class='ui-menu-item ui-category'>" + item.category + "</li>" );

造成了这个问题。

Internally,窗口小部件使用带有类ui-menu-item的列表项来区分li是否是可以选择的实际菜单项。当您按下“向下”键时,窗口小部件会找到包含类ui-menu-item的下一个项目并移动到它。

删除该类,您的代码就像您希望的那样:

ul.append( "<li class='ui-category'>" + item.category + "</li>" );

这里有效:

http://jsfiddle.net/andrewwhitaker/pkFCF/

答案 1 :(得分:1)

由于接受的答案在最新版本的jQueryUI(&gt; 1.10.4)中不起作用,我会发布我的黑客,也许有人会发现它很有用。

我正在使用jQueryUI 1.12.0

在追加类别时我添加了新类,我称之为&#34; categoryItem&#34;:

ul.append( "<li class='ui-autocomplete-category categoryItem'>" + "Category" + "</li>" );

还需要重写一些jQueryUI函数来强制jquery忽略带有&#34; categoryItem&#34;的项目。 class(更改了两行)。

$.widget("ui.menu", $.extend({}, $.ui.menu.prototype, {
  refresh: function() {
    var menus, items, newSubmenus, newItems, newWrappers,
        that = this,
        icon = this.options.icons.submenu,
        submenus = this.element.find( this.options.menus );

    this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
    // Initialize nested menus
    newSubmenus = submenus.filter( ":not(.ui-menu)" )
        .hide()
        .attr( {
            role: this.options.role,
            "aria-hidden": "true",
            "aria-expanded": "false"
        } )
        .each( function() {
            var menu = $( this ),
                item = menu.prev(),
                submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );

            that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
            item
                .attr( "aria-haspopup", "true" )
                .prepend( submenuCaret );
            menu.attr( "aria-labelledby", item.attr( "id" ) );
        } );

    this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );

    menus = submenus.add( this.element );
    items = menus.find( this.options.items );

    // Initialize menu-items containing spaces and/or dashes only as dividers
    items.not( ".ui-menu-item" ).each( function() {
        var item = $( this );
        if ( that._isDivider( item ) ) {
            that._addClass( item, "ui-menu-divider", "ui-widget-content" );
        }
    } );

    // Don't refresh list items that are already adapted
    newItems = items.not( ".ui-menu-item, .ui-menu-divider" ).not(".categoryItem");
    newWrappers = newItems.children()
        .not( ".ui-menu" )
            .uniqueId()
            .attr( {
                tabIndex: -1,
                role: this._itemRole()
            } );
    this._addClass( newItems, "ui-menu-item" )
        ._addClass( newWrappers, "ui-menu-item-wrapper" );

    // Add aria-disabled attribute to any disabled menu item
    items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );

    // If the active item has been removed, blur the menu
    if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
        this.blur();
    }

},
    _move: function( direction, filter, event ) {
    var next;
    if ( this.active ) {
        if ( direction === "first" || direction === "last" ) {
            next = this.active
                [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
                .eq( -1 );
        } else {
            next = this.active
                [ direction + "All" ]( ".ui-menu-item" )
                .eq( 0 );
        }
    }
    if ( !next || !next.length || !this.active ) {
        next = this.activeMenu.find( this.options.items ).not(".categoryItem")[ filter ]();
    }

    this.focus( event, next );
}
}));