Запретить закрытие автозаполнения 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() }
});