jQuery UI Автозаполнение категории Как пропустить заголовки категории - PullRequest
9 голосов
/ 31 мая 2011

У меня есть рабочее поле автозаполнения в моем веб-приложении, и я ищу способ повысить удобство использования поля, каким-то образом автоматически пропуская поля категорий, когда клавиша со стрелкой используется для прокрутки вниз доступных вариантов (после ввода в частичный поисковый термин).

Например, если пользователь начинает вводить «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 ]

6 голосов
/ 31 мая 2011

Эта строка:

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

вызывает проблему.

Внутренне , виджет использует элементы списка с классом ui-menu-item, чтобы различать, является ли li фактическим пунктом меню, который можно выбрать. Когда вы нажимаете клавишу «вниз», виджет находит следующий элемент с классом ui-menu-item и перемещается к нему.

Удалите класс, и ваш код работает так, как вы хотите:

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

Вот это работает:

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

2 голосов
/ 14 июля 2016

Поскольку принятый ответ не работает в последних версиях jQueryUI (> 1.10.4), я опубликую свой хак, возможно, кто-то найдет его полезным.

Я использую jQueryUI 1.12.0

При добавлении категории я добавил новый класс, я назвал его «categoryItem»:

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

Некоторые функции jQueryUI также необходимо переопределить, чтобы заставить jquery игнорировать элементы с классом categoryItem(две строки изменены).

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