Подтвердить что ты не робот

Как вручную запустить делегированное событие с помощью jQuery?

Есть ли способ с jQuery вручную запускать делегированный обработчик событий?

Возьмем следующий пример кода:

<div class="container">
  <input type="button" value="Hello">
  <span class="output"></span>
</div>
​
<script>
  $('.container')
    .on('click', '[type=button]', function(e) {
      $(e.delegateTarget).find('.output').text($(this).val());
    })
    .find('[type=button]').triggerHandler('click');​
</script>

(Онлайн: http://jsfiddle.net/TcHBE/)

Я ожидал, что это сработает, и текст "Hello" появится в промежутке без нажатия кнопки, но это не так.

Я использую e.delegateTarget внутри обработчика, потому что элемент .ouput не будет находиться в известном отношении к кнопке, кроме некоторого места внутри .container. Вот почему я использую делегированный обработчик событий в первую очередь.

Update:

Также я использую triggerHandler, потому что событие имеет поведение по умолчанию в реальном коде, который я не хочу запускать. (В реальном коде событие является настраиваемым событием hide плагина Bootstrap Modal, но на самом деле я не хочу скрыть модальность при запуске обработчика события при загрузке страницы).

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

4b9b3361

Ответ 1

Вы можете создать объект "Событие" вручную и установить свойство target, чтобы обмануть jQuery, подумав, что событие раздуто.

var c = $('#container');

c.on('click', '[type=button]', function(e) {
    $(e.delegateTarget).find('span').text($(this).val());
});

var event = jQuery.Event('click');
event.target = c.find('[type=button]')[0];

c.trigger(event);

http://jsfiddle.net/PCLFx/

Ответ 2

Селекторы в методе .on() являются необязательными.
Когда вы пишете:

  $('.container')
    .on('click', '[type=button]', function(e) {
      $(e.delegateTarget).find('.output').text($(this).val());
    })
    .find('[type=button]').triggerHandler('click');​

Вы сообщаете обработчику событий прослушивать только щелчок кнопки внутри контейнера.
$(e.delegateTarget) - это просто ссылка на внешний контейнер.

Я обновил свою скрипту, чтобы повторить это.

Это цитата из API:

Когда предоставляется селектор, обработчик события называется делегированы. Обработчик не вызывается, когда событие происходит непосредственно на связанный элемент, но только для потомков (внутренних элементов), которые сопоставить селектор. jQuery пузыриет событие от целевого события к элементу, в котором прикреплен обработчик (то есть, наиболее внешний элемент) и запускает обработчик для любых элементов вдоль этого путь, соответствующий селектору.

Ответ 3

В дополнение к ответу @Prinzhorn, может быть полезно иметь эту функцию JQuery:

(function( $ ){
    $.fn.triggerParent = function (eventName, parent) {
        this.each(function() {
            var event = jQuery.Event(eventName);
            event.target = this;
            $(parent).trigger(event);
        });
    };
})( jQuery );

Ответ 4

Мы можем передать дополнительную event configuration в jQuery $.Event() в качестве second argument. Больше информации здесь.

$('#click-me').on('click', function(evt){
  $(document).trigger($.Event('custom-click', {target: evt.currentTarget}));
});

$(document).on('custom-click', '#click-me', function(evt){
  alert('${evt.type} was triggered on button with ${evt.target.id} id.');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<button id="click-me">Click Me</button>

Ответ 5

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

Идея состоит в том, чтобы просто создать событие для нужного целевого элемента напрямую: $(target_selector).trigger(event_type) или - еще короче для стандартных событий, таких как "click" - сделать $(target_selector).click(), см. Мою маленькую скрипку ниже:

$(function(){
 $('.container').on('click','button',function(){
  console.log('delegated click on '+$(this).text());
  return false;
 });
 $('#other').click(e=>$('.container button').trigger('click'));
 $('#clickone').click(e=>$('.container .one').click());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="container">
<button type="submit" class="one">click 1</button> and another chance to click here on <button class="two">click 2</button>.
</form><br>
<div id="other">Trigger clicks on both buttons here!</div><br>
<div id="clickone">Trigger a click on button "one" only.</div>