Запретить закрытие автозаполнения JQuery после каждого выбора

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

<meta charset="utf-8">

<script>
$(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"
    ];
    function split( val ) {
        return val.split( /,\s*/ );
    }
    function extractLast( term ) {
        return split( term ).pop();
    }

    $( "#tags" ).autocomplete({
        minLength: 0,
        source: function( request, response ) {
            // delegate back to autocomplete, but extract the last term
            response( $.ui.autocomplete.filter(
                availableTags, extractLast( request.term ) ) );
        },
        focus: function() {
            // prevent value inserted on focus
            return false;
        },
        select: function( event, ui ) {
            var terms = split( this.value );
            // remove the current input
            terms.pop();
            // add the selected item
            terms.push( ui.item.value );
            // add placeholder to get the comma-and-space at the end
            terms.push( "" );
            this.value = terms.join( ", " );
            return false;
        }
    });
});
</script>
  Языки программирования тегов:

Ответ 1

Вы можете сделать что-то вроде этого: сначала определите переменную с именем readyToClose и установите ее как false в начале. И когда вы хотите закрыть свое меню при следующем выборе, установите эту переменную в true. А также мы должны переопределить метод close JQuery UI.

Здесь я переопределял метод close JQuery UI в коде, а не в исходном файле! Это то же самое, что мы делаем для отображения списка по-своему (например, http://jqueryui.com/demos/autocomplete/custom-data.html)

var readyToClose = false;
$( "#tags" ).autocomplete({
    minLength: 0,
    source: function( request, response ) {
        // delegate back to autocomplete, but extract the last term
        response( $.ui.autocomplete.filter(
            availableTags, extractLast( request.term ) ) );
    },
    focus: function() {
        // prevent value inserted on focus
        return false;
    },
    select: function( event, ui ) {
        var terms = split( this.value );
        // remove the current input
        terms.pop();
        // add the selected item
        terms.push( ui.item.value );
        // add placeholder to get the comma-and-space at the end
        terms.push( "" );
        this.value = terms.join( ", " );
        return false;
    }
}).data( "autocomplete" ).close = function(e){
    if(readyToClose)
        clearTimeout(this.closing), this.menu.element.is(":visible") && (this.menu.element.hide(), this.menu.deactivate(), this._trigger("close", e));
    else
        return false;    
};

Примечание. В новых версиях jQuery (например, 1.9.0) замените "автозаполнение" на "uiAutocomplete", как в:

$("#tags")
    .autocomplete({...})
    .data("uiAutocomplete").close = ...

Ответ 2

Я знаю, что это старый вопрос, который может больше не относиться к OP, но ради полноты, более чистым решением было бы extend виджет автозаполнения и переопределение _close, а также extend события объект в обработчике событий select. Это позволяет вам выполнять пользовательскую логику, чтобы определить, следует ли закрывать меню или нет в каждом конкретном случае (событие за событием). Смотрите также http://learn.jquery.com/jquery-ui/widget-factory/extending-widgets/

//override the autocomplete widget
jQuery.widget( "ui.autocomplete", jQuery.ui.autocomplete, {
    _close: function( event ) {
        if(event!== undefined && event.keepOpen===true) {
            //trigger new search with current value
            this.search( null, event );
            return true;
        }
        //otherwise invoke the original
        return this._super( event );
    }
});

$('ac').autocomplete(
    {
        ...custom options...
        select: function( event, ui ) {
            ...custom logic...
            if(menu should remain open) {
                //extend original event with special flag to keep dropdown open
                //the o-event continues to be passed through the chain of listeners
                //and will end up being processed during _close()
                jQuery.extend(event.originalEvent,{keepOpen:true});
                //modify value as required
                jQuery(this).val(...);
                return false; //prevent selected value from being set,
                              //i.e. keeping modified value above
            }
        }
    }
);

В приведенном выше jQuery.extend(event.originalEvent, {keepOpen: true}); используется для добавления специального свойства keepOpen к event.originalEvent. Поскольку extend изменяет исходный объект (первый аргумент), любое последующее использование того же самого event.originalEvent будет иметь это свойство доступным. Прочитав код и пройдя по нему, он становится тем же объектом, на который ссылается event в методе _close. Этот код сломается, если это изменится в будущем, однако его гораздо проще поддерживать, чем эквивалент того, что ингредиент_15939 предложил 18 месяцев назад.

Ответ 3

Команда jQuery UI считает, что это плохая практика UX: http://forum.jquery.com/topic/enhanced-autocomplete-interest-in-getting-this-into-jqueryui#14737000001125152

Таким образом, нет встроенного способа его отмены. Вы можете повторить запуск автозаполнения после событий выбора и закрытия. Вероятно, вы должны кэшировать массив результатов, чтобы новые запросы не выполнялись (если они были в режиме Ajax).

Не вдавался в подробности, хотя - я убедил своего дизайнера интерфейса, что нам это не нужно для этой версии:)

Ответ 4

Мне нужна была эта же способность. ИМО авторы могли легко дать нам возможность. Я сделал исключение автозаполнения из пакета UI и включил отредактированную копию отдельного файла: jquery.ui.autocomplete.js (получить его из папки "development-bundle\ui" ).

Я добавил пару новых опций closeOnSelect и updateElement (оба значения по умолчанию boolean), как показано ниже (вверху файла):

$.widget("ui.autocomplete", {
  options: {

  ...

  closeOnSelect: true, // add this line - controls list closing.
  updateElement: true  // add this line - controls updating input box.
},

Затем найдите строку " selected:" в коде (будет только одно вхождение). В пределах этой функции замените эти последние несколько строк:

if ( false !== self._trigger( "select", event, { item: item } ) ) {
    self.element.val( item.value );
}
// reset the term after the select event
// this allows custom select handling to work properly
self.term = self.element.val();

self.close( event );
self.selectedItem = item;

При этом:

if (false !== self._trigger("select", event, { item: item })) {

  if (self.options.updateElement) {
    self.element.val(item.value);
    self.term = self.element.val(); // Ensure term string is same.
  }
  if (self.options.removeOnSelect) { // Remove menu item if option is true.
    console.log(ui);
  } else {
    self.selectedItem = item;
  }
  if (self.options.closeOnSelect) self.close(event); // Close menu if option is true.

} else { // Returned false.
  self.term = self.element.val(); // Ensure term string is same, in case callback changed element value.
}

Затем найдите строку " focus: function" (опять же, только одно вхождение). В пределах этой функции замените строку:

self.element.val(item.value);

При этом:

if (self.options.updateElement) self.element.val(item.value);

Теперь, когда вы создаете автозаполнение, просто установите эти два параметра по своему усмотрению:

$("#txtsearch").autocomplete({
  closeOnSelect: false, // Keep list open when item selected.
  updateElement: false, // Don't change the input box contents.
  // etc...

Это отлично работает для меня. Независимо от того, считали ли они "плохой пользовательский интерфейс" оригинальными авторами, все потребности разные, и там должны быть варианты!:)

Ответ 5

Вам нужно будет отредактировать javascript файл jquery-ui. В разделе автозаполнения замените

close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}}

с

close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){if(this._trigger("close",a)!==false){this.menu.element.hide();this.menu.deactivate()}}}

то вы должны иметь возможность отменить событие закрытия, как описано в ответе Shaans.

Ответ 6

Не очень хорошее решение, но я справился с этим так:

var $input = $('input').autocomplete({
    select: function(event, obj) {
        var ac_data = $(event.target).data("autocomplete");
        ac_data.instaSearch = true;

        // Your action

        return false;
    }
});
$input.data("autocomplete")._close = function( event ) {
    if ( this.menu.element.is( ":visible" )) {
        this.menu.element.hide();
        this.menu.blur();
        this.isNewMenu = true;
        this._trigger( "close", event );
        if (this.instaSearch) {
            this.search(this.term);
            this.instaSearch = false;
        }
    }
};

Ответ 7

Это решение сработало для меня. Я использовал Autocomplete, чтобы отобразить список первых четырех символов для имен. Затем, если пользователь выбирает один из них, тогда у меня Autocomplete отображаются имена, связанные с выбором. Вывод автозаполнения остается открытым после первого выбора, и вы можете увидеть изменение списка на другие параметры. Надеюсь, что это поможет в этой теме.

select: function( event, ui ) {
    // the number of chars was driving my decision for behavior, yours may be different
    if (chars.length <= 4) {
        jq.each(ui, function(key, value) {
            jq.each(value, function(key1, value1) {
                // put the selected value in the text area, 
                // since normal behavior will be prevented
                jq("#mod_autocomplete").val(value1);

                // trigger another search
                jq("#mod_autocomplete").autocomplete("search");

                // open the autocomplete dropdown
                jq("#mod_autocomplete").autocomplete("open");
            });

        });

        event.preventDefault();

    } else {
        // put whatever behavior you need here for next selection
    }

}

Ответ 8

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

Используйте тот же код из ответа, который будет продолжать открывать меню, и теперь, чтобы скрыть меню из стороны в сторону (на теле), используйте следующий фрагмент кода.

 $('body').on('click', function(e){
            // click event will prevent for the input and for auto complete menu div
            if($(e.target).hasClass('ui-autocomplete-input') || $(e.target).hasClass('ui-menu-item-wrapper')){
                e.preventDefault();
                return;
            }
// in other case hide the menu
            $("ul.ui-autocomplete").hide();
        });

Ответ 9

Вы можете обработать событие закрытия автозаполнения http://jqueryui.com/demos/autocomplete/#multiple

Примеры кода

Поставить функцию обратного вызова для обработки события закрытия в качестве параметра init.

$( ".selector" ).autocomplete({
   close: function(event, ui) { ... }
});

Привязать к событию закрытия по типу: autocompleteclose.

$( ".selector" ).bind( "autocompleteclose", function(event, ui) {
  ...
});

Ответ 10

select: function (event, ui)

if (event.keyCode == 13) {
    document.getElementById("#idofautocomplete").value = document.getElementById("#idofautocomplete").value;
 } else if (event.keyCode == 27) {
        $("#idofautocomplete").autocomplete("close");                                                                                   }

close: function (event, ui)

document.getElementById("idofautocomplete").value = "";

выглядит глупо, но это работает для меня. пользователь ищет элементы, выбирает элемент с помощью клавиши ввода, автозаполнение все еще открыто, пользователь может выбрать дополнительные параметры, в любое время пользователь может нажать кнопку ESC, закрыть автозаполнение, закрыть функцию, очистить текст от автозаполнения. я получаю всю свою информацию из базы данных

Ответ 11

Я изменил решение из пользовательского интерфейса JQuery, чтобы ответить на событие закрытия и снова открыть меню автозаполнения, если вход все еще имеет фокус, побег не был нажат, чтобы закрыть всплывающее окно, а значение ввода заканчивается либо a ',' или '' (пробел):

close: function(e) {
  if ($el.is(':focus') && e.keyCode !== $.ui.keyCode.ESCAPE && (this.value != null) && /[,\s]+$/.test(this.value)) {
    return $el.autocomplete('search', '');
  }
}

полное решение:

var $el = $('#autocomplete-field');
$el.bind('keydown', function(e) {
  if (e.keyCode === $.ui.keyCode.TAB && $(this).data('autocomplete').menu.active) {
    e.preventDefault();
  }
}).autocomplete({
  delay: 0,
  autoFocus: true,
  minLength: 0,
  source: function(req, resp) {
    resp($.ui.autocomplete.filter(source, extractLast(req.term)));
  },
  focus: function() {
    return false;
  },
  select: function(e, ui) {
    var terms;
    terms = regexSplit(this.value);
    terms.pop();
    terms.push(ui.item.value);
    terms.push('');
    this.value = terms.join(', ');
    return false;
  },
  close: function(e) {
    if ($el.is(':focus') && e.keyCode !== $.ui.keyCode.ESCAPE && (this.value != null) && /[,\s]+$/.test(this.value)) {
      return $el.autocomplete('search', '');
    }
  }
}).focus(function() {
  $el.autocomplete('search', '');
});

Ответ 12

Быстро, только css и небольшое хакерское решение:

...
close: function() {
   $('.ui-menu').css('display', 'block'); //or using #ui-id-x where x is number of autocomplete
}
...

Ответ 13

Я знаю, что это старый вопрос, но он по-прежнему полезен,

Ниже приведено решение для последней версии jquery UI.

$.ui.autocomplete.prototype._close = function(e){
        return false;    
};

OP может изменить этот код в соответствии с его потребностями.

Ответ 14

Просто столкнулся с этим вопросом сам. Вот простой вкладыш для всех вас, просто добавьте его в опции автозаполнения.

$ac.autocomplete({
  ...
  close: function () { $('.ui-autocomplete').show() }
});

Если вы хотите закрыть его или хотите, чтобы он закрывался при закрытии, вы можете удалить оператор закрытия или просто добавить .fadeOut() в конец соответственно.

$ac.autocomplete({
  ...
  close: function () { $('.ui-autocomplete').show().fadeOut() }
});