JQuery UI Автозаполнение Combobox с категориями

Я использую комбинированный список автозаполнения jquery ui, и он отлично работает, но теперь я становлюсь немного жадным. Я хотел бы иметь возможность добавлять категории к нему. Поле со списком создается из меню, поэтому, если я добавлю категории, см. Пример ниже, тег будет отображаться, как категории вверсия автозаполнения JQuery UI версии

<select>
<optgroup name="Cat 1">    
<option value="1a">One A</option>
<option value="1b">One B</option>
<option value="1c">One C</option>
</optgroup>
<optgroup name="Cat 2">    
<option value="2a">Two A</option>
<option value="2b">Two B</option>
<option value="2c">Two C</option>
</optgroup>
</select>

Я создалhttp://jsfiddle.net/nH3b6/11/.

Спасибо за любую помощь или направление.

Ответы на вопрос(4)

JQueryUI документы, вы должны настроить виджет, чтобы сделать это

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

это не проверено, но должно стать хорошим началом:

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

если это не работает, возможно, вам следует отладить, чтобы увидеть, что вitems массив, который поставляется как параметр _renderMenu.

примечание стороны: это называетсяMonkeyPatchingЯ бы не рекомендовал делать это много, но поскольку документы показывают это, я скажу, что сделайте это.

 14 июн. 2012 г., 22:04
 Mark K14 июн. 2012 г., 21:59
Спасибо за ответ. Поправьте меня, если я не прав, но вы начинаете с кода из категории "quot;" версия автозаполнения, которую я начинаю с "поля со списком" версия. Таким образом, приведенный выше код не работает.

зможностью исправления в выпадающем списке combobox, optgroup (категории) и возможностью поиска также в именах категорий. Термин поиска также выделен внутри совместимой опции и optgroup. Я использовал несколько ответов с сайта stackoverflow и jqueryui, чтобы добраться до этой точки, спасибо!

Мне нравится, чтобы он работал на последней версии jqueryui. В Jqueryui 1.9 и 1.11 были внесены критические изменения (в плагине автозаполнения и меню, последний использовался последним), и мне наконец удалось заставить его работать с последней версией jqueryui (1.11.0) и jquery (2.1.1)

JSBIN здесь

Важная часть: измените параметры виджета меню, чтобы категории не рассматривались как обычная ссылка меню через параметр новых элементов (настолько новый, что не внутри документа, а в руководстве по обновлению jqueryui до 1.11

$.extend($.ui.menu.prototype.options, {
    items: "> :not(.aureltime-autocomplete-category)"
});
 28 авг. 2014 г., 11:24
Это потрясающе! Сначала я не решался использовать это, но на самом деле это сработало и решило мою проблему, большое спасибо!

Я беру комбобокс автозаполнения с сайта jquery ui:http://jqueryui.com/autocomplete/#combobox и присоединиться к нему с ответом Эндрю Уитакера.

(function( $ ) {
$.widget( "custom.combobox_with_optgroup", {
    _create: function() {
        this.wrapper = $( "<span>" )
            .addClass( "custom-combobox" )
            .insertAfter( this.element );
        this.element.hide();
        this._createAutocomplete();
        this._createShowAllButton();
    },
    _createAutocomplete: function() {
        var selected = this.element.find( ":selected" ),
            value = selected.val() ? selected.text() : "";
        this.input = $( "<input>" )
            .appendTo( this.wrapper )
            .val( value )
            .attr( "title", "" )
            .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
            .autocomplete({
                delay: 0,
                minLength: 0,
                source: $.proxy( this, "_source" )
            })
            .tooltip({
                tooltipClass: "ui-state-highlight"
            });
        this._on( this.input, {
            autocompleteselect: function( event, ui ) {
                ui.item.option.selected = true;
                this._trigger( "select", event, {
                    item: ui.item.option
                });
            },
            autocompletechange: "_removeIfInvalid"
        });

        this.input.data("uiAutocomplete")._renderMenu = function(ul, items) {
            var self = this,
                currentCategory = "";
            $.each(items, function(index, item) {
                if (item.category != currentCategory) {
                    if (item.category) {
                        ul.append("<li class='custom-autocomplete-category'>" + item.category + "</li>");
                    }
                    currentCategory = item.category;
                }
                self._renderItemData(ul, item);
            });
        };
    },
    _createShowAllButton: function() {
        var input = this.input,
            wasOpen = false;
        $( "<a>" )
            .attr( "tabIndex", -1 )
            .attr( "title", "Показать все" )
            .tooltip()
            .appendTo( this.wrapper )
            .button({
                icons: {
                    primary: "ui-icon-triangle-1-s"
                },
                text: false
            })
            .removeClass( "ui-corner-all" )
            .addClass( "custom-combobox-toggle ui-corner-right" )
            .mousedown(function() {
                wasOpen = input.autocomplete( "widget" ).is( ":visible" );
            })
            .click(function() {
                input.focus();

                if ( wasOpen ) {
                    return;
                }

                input.autocomplete( "search", "" );
            });
    },
    _source: function( request, response ) {
        var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
        response( this.element.find( "option" ).map(function() {
            var text = $( this ).text();
            if ( this.value && ( !request.term || matcher.test(text) ) )
                return {
                    label: text,
                    value: text,
                    option: this,
                    category: $(this).closest("optgroup").attr("label")
                };
        }) );
    },
    _removeIfInvalid: function( event, ui ) {

        if ( ui.item ) {
            return;
        }

        var value = this.input.val(),
            valueLowerCase = value.toLowerCase(),
            valid = false;
        this.element.find( "option" ).each(function() {
            if ( $( this ).text().toLowerCase() === valueLowerCase ) {
                this.selected = valid = true;
                return false;
            }
        });

        if ( valid ) {
            return;
        }

        this.input
            .val( "" )
            .attr( "title", value + " не существует" )
            .tooltip( "open" );
        this.element.val( "" );
        this._delay(function() {
            this.input.tooltip( "close" ).attr( "title", "" );
        }, 2500 );
        this.input.data( "ui-autocomplete" ).term = "";
    },
    _destroy: function() {
        this.wrapper.remove();
        this.element.show();
    }
});
})( jQuery );
Решение Вопроса

я бы обновил ваш код, чтобы определить, чтоoptgroup Опция принадлежит. Оттуда вы можете использовать код, аналогичный найденному на сайте jQueryUI:

(function($) {
    $.widget("ui.combobox", {
        _create: function() {
            var input, self = this,
                select = this.element.hide(),
                selected = select.children(":selected"),
                value = selected.val() ? selected.text() : "",
                wrapper = this.wrapper = $("<span>").addClass("ui-combobox").insertAfter(select);

            input = $("<input>").appendTo(wrapper).val(value).addClass("ui-state-default ui-combobox-input").autocomplete({
                delay: 0,
                minLength: 0,
                source: function(request, response) {
                    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");

                    response(select.find("option").map(function() {
                        var text = $(this).text();
                        if (this.value && (!request.term || matcher.test(text))) return {
                            label: text.replace(
                            new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(request.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"),
                            value: text,
                            option: this,
                            category: $(this).closest("optgroup").attr("label")
                        };
                        //MK
                        $('#test').attr('style', 'display: none;');
                    }).get());
                },
                select: function(event, ui) {
                    ui.item.option.selected = true;
                    self._trigger("selected", event, {
                        item: ui.item.option
                    });
                },
                change: function(event, ui) {
                    if (!ui.item) {
                        var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
                            valid = false;
                        select.children("option").each(function() {
                            if ($(this).text().match(matcher)) {
                                this.selected = valid = true;
                                return false;
                            }
                        });
                        if (!valid) {
                            $('#test').attr('style', 'display: block;');
                            // remove invalid value, as it didn't match anything
                            //$( this ).val( "" );
                            //select.val( "" );
                            //input.data( "autocomplete" ).term = "";
                            //return false;                    
                        }
                    }
                }
            }).addClass("ui-widget ui-widget-content ui-corner-left");

            input.data("autocomplete")._renderItem = function(ul, item) {
                return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);
            };

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

            $("<a>").attr("tabIndex", -1).attr("title", "Show All Items").appendTo(wrapper).button({
                icons: {
                    primary: "ui-icon-triangle-1-s"
                },
                text: false
            }).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle").click(function() {
                // close if already visible
                if (input.autocomplete("widget").is(":visible")) {
                    input.autocomplete("close");
                    return;
                }

                // work around a bug (likely same cause as #5265)
                $(this).blur();

                // pass empty string as value to search for, displaying all results
                input.autocomplete("search", "");
                input.focus();
            });
        },

        destroy: function() {
            this.wrapper.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);

$(function() {
    $("#combobox").combobox();
    $("#toggle").click(function() {
        $("#combobox").toggle();
    });
});

Example: http://jsfiddle.net/gB32r/

 Mark K15 июн. 2012 г., 14:46
Это прекрасно работает. Спасибо.
 Mark K15 июн. 2012 г., 15:46
Nevermind понял это ... select.children (& quot; optgroup & quot;). Children (& quot; option & quot;). Each (function () {
 Mark K15 июн. 2012 г., 15:36
Привет, поэтому я обнаружил небольшую ошибку в качестве побочного продукта корректировки, которую вы сделали. Если я раскрываю список и выбираю один из вариантов в категории, он отображает «Нет совпадений». Если я выберу опцию, которая не относится к категории, она прекрасно работает. Я пытался понять это безрезультатно.
 09 июл. 2013 г., 09:25
Вы можете изменить все звонки наchildren вfind, Таким образом, он работает после обратных передач (в случае ASP.NET) и других случаях. Я хотел изменить ответ, но я думаю, что сеть компании блокирует AJAX или что-то в этом роде. Кроме того, по моему опыту, вам не нужно менять метод _renderItem.
 23 янв. 2014 г., 20:21
@FernandoSilva: Привет, Фернандо - должно работать следующее обновление:jsfiddle.net/K5q3U/2 Более поздние версии jQueryUI используют разные имена данныхuiAutocomplete а такжеui-autocomplete-item

Ваш ответ на вопрос