JQuery UI Автозаполнение отключить Выбрать и закрыть события
Я использую jQuery UI Autocomplete несколько иначе, чем это было возможно для создания.
В принципе, я хочу сохранить все те же функциональные возможности, единственное различие заключается в том, что при появлении окна предложения я не предлагаю окно скрыть, когда пользователь делает выбор, и я также не хочу, чтобы этот выбор заполнялся поле ввода, которое.автокомплект прикреплен к.
Итак, я читал документацию по jQuery UI, и кажется, что есть способ отключить события Select: and Close:, но я нахожу, как они объяснили это, чтобы быть очень запутанным, и, следовательно, это почему я здесь прошу о помощи.
Мой jQuery
$( "#comment" ).autocomplete({
source: "comments.php",
minLength: 4,
// Attempt to remove click/select functionality - may be a better way to do this
select: function( event, ui ) {
return false;
},
// Attempt to add custom Class to the open Suggestion box - may be a better way
open : function (event, ui) {
$(this).addClass("suggestion-box");
},
// Attempt to cancel the Close event, so when someone makes a selection, the box does not close
close : function (event, ui) {
return false;
}
});
Официальная документация по пользовательскому интерфейсу jQuery
Запускается, когда элемент выбран из меню; ui.item относится к выбранному элементу. По умолчанию действие select заключается в замене значения текстового поля на значение выбранный элемент. Отмена этого события запрещает обновление значения, но не запретить закрытие меню.
Примеры кода
Supply a callback function to handle the select event as an init option.
$( ".selector" ).autocomplete({
select: function(event, ui) { ... }
});
Bind to the select event by type: autocompleteselect.
$( ".selector" ).bind( "autocompleteselect", function(event, ui) {
...
});
Путаница
Что меня смущает, так это то, что они, кажется, предлагают удалить .autocomplete и заменить на .bind( "autocompleteselect" ) - что полностью отключит автозаполнение?
Большое спасибо за любую помощь, которую вы можете дать.
Ответы
Ответ 1
Второй синтаксис с использованием .bind()
- это просто еще один способ привязки обработчика событий к пользовательским событиям jQueryUI. Это точно так же, как определение обработчика событий внутри параметров виджетов (с помощью select: function(event, ui) { }
)
Представьте, если на странице было несколько виджетов автозаполнения, и вы хотели выполнить одну и ту же функцию, если любой из них поднял событие "select", например:
$(".autocomplete").bind("autocompleteselect", function(event, ui) {
/* Will occur when any element with an autocomplete widget fires the
* autocomplete select event.
*/
});
Что касается отмены события select
, у вас есть это правильно. Однако отмена события close
немного сложнее; похоже, что возвращение false из обработчика события не будет работать (close
запускается после того, как меню фактически закрыто). Вы можете выполнить небольшой хакерство и просто заменить функцию select
на свой собственный:
var $input = $("input").autocomplete({
source: ['Hello', 'Goodbye', 'Foo', 'Bar']
});
$input.data("autocomplete").menu.options.selected = function(event, ui) {
var item = ui.item.data( "item.autocomplete" );
$input.focus();
};
Вот рабочий пример этого: http://jsfiddle.net/ZGmyp/
Я не уверен, что последствия для переопределения события close, но не похоже, что на простом примере происходит что-то сумасшедшее. Я бы сказал, что это своего рода неестественное использование виджета, поэтому могут быть неожиданные последствия.
Ответ 2
Вдохновляя решение Andrews, я нашел способ сохранить автозаполнение открытым при выборе с меньшим воздействием на основные функции:
var selected; //flag indicating a selection has taken place
var $input = $("input").autocomplete({
source: ['Hello', 'Goodbye', 'Foo', 'Bar'],
select: function( event, ui ) {
selected = true;
}
});
//Override close method - see link below for details
(function(){
var originalCloseMethod = $input.data("autocomplete").close;
$input.data("autocomplete").close = function(event) {
if (!selected){
//close requested by someone else, let it pass
originalCloseMethod.apply( this, arguments );
}
selected = false;
};
})();
Таким образом, идея заключается в методе стерилизации, когда это необходимо, как указано выбранным флагом. Выбрав флаг в глобальном пространстве имен, возможно, это не лучшая идея, но для кого-то еще улучшить: -).
Подробнее о методах переопределения
Ответ 3
Я пошел немного иначе для этого и расширил на Andrew fiddle
Цель заключалась в том, что я всегда хотел, чтобы автозаполнение показывалось, в то время как определенный вход имел фокус - позволяя несколько вариантов выбора.
$("#myInput").autocomplete({
source: ["Test", "This", "Doesnt", "Close"],
minLength: 0,
select: function (event, ui) {
// Add your own custom login to manipulate ui.item.label and add what you need the input field (and ui.item.value if required.)
// We've customised how we want the select to "work" so prevent the default
// of auto clearing the input.
event.preventDefault();
},
close : function(event)
{
// We're closing the autocomplete - check if the input still has focus...
if ($("#myInput").is(":focus"))
{
// Prevent the auto complete from closing.
event.preventDefault();
// Make sure we're reshowing the autcomplete - since the input would have momentarily
// lost focus when we selected an item.
$("#myInput").autocomplete("search", "")
}
}
});
$("#myInput").focus(function () {
// We're not taking any filtering into account for this example.
$(this).autocomplete("search", "")
});
Ответ 4
Я пробовал различные идеи, представленные другими здесь без успеха.
Я использую JQuery 2.1.4 с UI 1.11.4, и именно так я получил это для работы:
JavaScript:
<script>
var lookup_selectable = false;
var lookup_term = '';
$(function() {
$( "#lookup" ).autocomplete({
source: "lookup_processor.php",
minLength: 3,
renderItem: function( ul, item ) {
// This function is called for each item returned from the 'source:'
// It is up to you to ensure that a list item element is returned.
// do whatever logic on the item data to determine if it should not be slectable..
//Example:
// The backend "source" has handled the logic of what is selectable or not
// and has set a 'selectable' parameter that we can use
if(item.selectable){
// return the item unchanged from autocompletes default behavior
return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);
}else{
// this item is not selectable so lets apply a class named 'item-disabled' to give a visual queue.
// We are also wrapping the label in a span instead of an anchor just to show that the item is still clickable, darn!
return $('<li class="ui-menu-item item-disabled"></li>').data("item.autocomplete", item).append('<span>'+item.label+'</span>').appendTo(ul);
}
},
select: function( event, ui ) {
// This item was clicked ..
// save the item.clickable value to our own external variable
// Note: We have to do this because the item object is not available in the 'close' function :-(
lookup_selectable = ui.item.selectable; // the item object is available inside the ui parameter
// store the current search term
lookup_term = $('#lookup').val();
// do any additional stuff based on the item selected, if needed...
},
close: function(event, ui){
// This function fires after select: and after autocomplete has already "closed" everything. This is why event.preventDefault() won't work.
// ** ui is an empty object here so we have to use our own variable to check if the selected item is "selectable" or not..
if (! lookup_selectable){
// We need to undo what autocomplete has already done..
$('#lookup').val(lookup_term); // Restore the search term value
$('#'+event.currentTarget.id).show(); // Keep the selection window open
// ta-da! To the end user, nothing changes when clicking on an item that was not selectable.
}
}
});
});
</script>
CSS
<style>
li.ui-menu-item.item-disabled {
text-decoration: none;
line-height: 1.5;
color: #ccc;
}
</style>
Бэкэнд-источник "lookup_processor.php":
<?php
$search_results = array();
// ..do whatever to get the data for each item
$item_data = getting_item_data();
foreach ($item_data as $data){
// The id, label, and value keys are the typical keys that autocomplete expects, but you can add ass many others as you want..
// For our example we are setting the 'selectable' key to true or false based on some simple example logic
$search_results[] = array(
'id'=>$data['id'],
'label'=>$data['label'],
'value'=>$data['value'],
'selectable'=>$data['some_thing_to_check']>0?true:false, // This is the parameter our 'select:' function is looking for
'send_it_all_if_you_want'=>json_encode($data)); // this is just an example of how you can send back anything you want
);
}
// send the results back to autocomplete
echo json_encode($search_results);
exit;
?>
Ответ 5
Переход с $input.data( "автозаполнение" ). menu.options.selected = function() {}
вызванное значение не удерживается после выбора другого элемента (наша реализация должна быть добавлена до конца. Возможно, нужно просто добавить e.preventDefault() или вернуть false перед добавлением кода). Поэтому я просто сделал переход в закрытое мероприятие.
пример с добавлением внешней переменной и написанием собственного метода лучше, но и не понравилось. Сначала я хочу использовать метод вызова вручную с передачей параметра, когда нужно закрыть автокомплекс вручную. (в нашем клиенте для реализации требуется, чтобы список был открыт при нажатии на элементы, но закрывается, когда мышь покидает контейнер текстового поля.
Итак, я просто подключил автозаполнение к контейнеру элементов текстового поля и подключил мышь и мышь. Чтобы определить, должен ли он закрыться, я использовал настраиваемую переменную jQuery (this).data( "canClose" ). В основном, то, что он делает, это просто повторное открытие автозаполнения с помощью метода поиска, когда переменная "false".
Вот окончательный код:
element.autocomplete({
minLength:0,
source: source,
appendTo: element.parent(),
close: function () {
if (!jQuery(this).data("canClose")) {
jQuery(this).autocomplete('search', '');
}
return false;
}
});
element.mouseenter(function () {
element.data("canClose", false);
jQuery(this).autocomplete('search', '');
});
element.parent().mouseleave(function () {
element.data("canClose", true);
element.delay(2000).autocomplete("close");
});
Если вам нужно сделать append вместо замены, добавьте обработчик выбора в конструктор:
select: function (event, ui) {
var text = element.text().trim();
if (text.length > 0 && !text.endsWith(",")) {
text += ", ";
}
jQuery(this).text((text + ui.item.label));
jQuery(this).focus();
return false;
}