rails3-jquery-autocomplete: как расширить функцию выбора?

Я использую rails3-jquery-autocomplete 1.0.9 с Rails 3.2.8.

Я пытаюсь заменить поле со списком (<select>) автозаполнением. Как и в поле со списком, если пользователь выбирает значение, я хочу обновить идентификатор в базе данных. Также, как и в поле со списком, не должно быть возможности выбрать недопустимое значение.

Одним из аспектов этого является то, что если пользователь начинает вводить текст в поле, но покидает его, не выбрав значение из списка выбора, само поле и соответствующее скрытое поле #to_contact_id должны быть пустыми.

Вот определения полей:

<%= autocomplete_field_tag "to_contact_name", '',
      autocomplete_contact_display_name_messages_path,
      :id_element => "#to_contact_id",
      :value => to_contact_name %>
<%= f.hidden_field :to_contact_id, :id => "to_contact_id" %>

Мой план состоял в том, чтобы установить флаг, когда пользователь выбирает элемент из списка выбора, а затем проверить флаг на размытие (потеря фокуса). Я нашел пример переопределения функции автозаполнения здесь , и закодировал этот Javascript:

var picklist_value_selected = false;

$('input[data-autocomplete]').focus(function() {
  // add autocomplete event handler on focus
  $(this).autocomplete({
    select: function(event, ui) {
      picklist_value_selected = true;
    }
  });
});

$('input[data-autocomplete]').blur(function() {
  // If user leaves field without selecting value, clear values.
  if (!picklist_value_selected) {
    $(this).val('')
    $('#to_contact_id').val('');
  };
});

Проблема в том, что когда я переопределяю select, как указано выше, функция "по умолчанию" не выполняется, а это означает, что #to_contact_id никогда не заполняется в первую очередь.

Я предполагаю, что мне нужно расширить select, а не переопределить его, поэтому выполняется и мой код, и базовый код rails3-jquery-autocomplete? Как я могу это сделать? Различные попытки, такие как следующие, либо не вызываются, либо жалуются на неопределенные методы:

$.extend($(this).autocomplete, {
  select: function(event, ui) {
    picklist_value_selected = true;
  }
});

person Mark Berry    schedule 27.10.2012    source источник


Ответы (1)


Лучший способ сделать это — использовать событие изменения автозаполнения. Он срабатывает, когда поле размыто, если значение изменилось, и позволяет узнать, какой элемент (если есть) был выбран. Вы можете привязаться к нему следующим образом:

$('input[data-autocomplete]').bind('autocompletechange', function(event, ui) {
    if(!ui.item) {
        // clear the fields
    }
});

Обновлять:

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

Посмотрите здесь. Здесь инициализируется автозаполнение. select — это анонимная функция, которая передается как опция для автозаполнения. Вы можете расширить его следующим образом (надеюсь, код не требует пояснений):

var originalSelect = $('input[data-autocomplete]').autocomplete('option', 'select');
$('input[data-autocomplete]').autocomplete('option', 'select', function(event, ui) {
    originalSelect.call(this, event, ui);
    doSomeOtherStuff();
});

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

$('input[data-autocomplete]').bind('autocompleteselect', function(event, ui) {
    doSomeOtherStuff();
}); 
person mechanicalfish    schedule 27.10.2012
comment
Полезно, спасибо. Почти то же самое, что было предложено в статье, которую я цитировал, но я упустил тот факт, что ui.item фактически заполняется вновь выбранным значением, если таковое имеется. Поскольку я так долго боролся с этим сегодня, мне все еще было бы интересно узнать, как расширить функцию. Может, это действительно сложно? Хороших примеров не нашел. - person Mark Berry; 27.10.2012
comment
Еще раз спасибо, оба этих примера расширения работают. Итак, чтобы привязать новую функцию к существующему событию, вы смешиваете текущие имена функций/событий? Никогда бы не догадался. Гарантирован ли порядок выполнения, т. е. моя новая функция всегда будет выполняться первой? Мне нравится хак за более очевидный контроль над последовательностью выполнения и более знакомый вызов функции super. Другой синтаксис, который я нашел для super, например, return $.ui.sortable.prototype._init.apply(this, arguments);, но я так и не смог определить правильное пространство имен для его вызова. - person Mark Berry; 30.10.2012
comment
Я только что увидел, что патч для rails3-jquery-autocomplete, решающий проблему очистки значений, был объединен четыре дня назад и выпущен как 1.0.10. Это вызвало у меня проблемы, поэтому я все еще на 1.0.9. См. обсуждение здесь: github.com/crowdint/rails3-jquery-autocomplete/pull /167. - person Mark Berry; 31.10.2012