jQuery при загрузке динамического элемента

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

Скажем, у меня есть контейнер:

<div id="container"></div>

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

$('#container').on('click', '.sub-element', function() { ... });

Но к чему мне привязываться, чтобы получить "одноразовый" хук при добавлении элемента в #container. Я пытался привязать к ready и load безрезультатно. Есть ли способ сделать это, или мне нужно придумать другое решение моей проблемы?

Эта скрипта содержит мой нерабочий пример.


person Klaus Byskov Pedersen    schedule 07.03.2012    source источник
comment
Во всех браузерах событие загрузки не всплывает. В Internet Explorer 8 и более ранних версиях события вставки и сброса не всплывают. Такие события не поддерживаются для использования с делегированием, но их можно использовать, когда обработчик событий напрямую подключен к элементу, генерирующему событие. (api.jquery.com/on) Теперь, как обойти это...   -  person Corbin    schedule 08.03.2012
comment
Будет ли проблемой удалить функциональность «загрузки», которую вы пытаетесь выполнить вместе, и вместо этого манипулировать html после того, как элемент добавлен с помощью «цепочки»? $('#container').append('‹div class=sub-element›Не работает!‹/div›’).html(’‹b›yaay!‹/b›');   -  person Ohgodwhy    schedule 08.03.2012
comment
@Ohgodwhy, дело не в том, что я не могу придумать обходной путь (и тем более для этого глупого примера), я просто хочу знать, есть ли пропущенное мной событие, которое можно использовать для цели, которую я описываю. .   -  person Klaus Byskov Pedersen    schedule 08.03.2012
comment
@Corbin Событие load срабатывает только для элементов, с которыми связан URL-адрес, например изображение или таблица стилей.   -  person Jasper    schedule 08.03.2012
comment
На самом деле я начал писать об этом в своем комментарии, но решил, что, поскольку вы все равно не можете делегировать нагрузку, это не имеет значения. Хорошо бы включить, я полагаю.   -  person Corbin    schedule 08.03.2012


Ответы (2)


Вы можете инициировать пользовательское событие для вновь добавленного элемента DOM, которое может быть получено обработчиком событий jQuery:

//bind to our custom event for the `.sub-element` elements
$('#container').on('custom-update', '.sub-element', function(){
    $(this).html('<b>yaay!</b>');
});

//append a new element to the container,
//then select it, based on the knowledge that it is the last child of the container element,
//and then trigger our custom event on the element
$('#container').append('<div class="sub-element">No worky!</div>').children().last().trigger('custom-update');

Вот демонстрация: http://jsfiddle.net/ggHh7/4/

Этот метод позволяет вам делать что-то глобально, даже если вы загружаете динамическое содержимое разными методами.

Обновлять

Я не уверен в поддержке браузера (я предполагаю, что IE8 и более ранние версии не поддерживают это), но вы можете использовать событие мутации DOMNodeInserted, чтобы определить, когда добавляется элемент DOM:

$('#container').on('DOMNodeInserted', '.sub-element', function(){
    $(this).html('<b>yaay!</b>');
})

$('#container').append('<div class="sub-element">No worky!</div>');

Вот демонстрация: http://jsfiddle.net/ggHh7/7/

ОБНОВИТЬ

Для этого существует новый API, поскольку в настоящее время DOMNodeInserted устаревает. Я не изучал его, но он называется MutationOvserver: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

person Jasper    schedule 07.03.2012
comment
Интересно, +1 и все такое... так вы говорите, что я никак не могу быть уведомлен, когда какой-то сторонний подключаемый модуль добавляет элемент в какой-то контейнер. Если я не тот, кто добавляет это, я облажался? - person Klaus Byskov Pedersen; 08.03.2012
comment
Вы можете установить интервал, который время от времени проверяет наличие новых элементов DOM. В противном случае есть события мутации, DOMNodeInserted, вероятно, то, что вам нужно, но поддержка браузера может быть не тем, что вам нужно: developer.mozilla.org/en/DOM_Client_Object_Cross-Reference/ (см. раздел Mutation and mutation name event types). См. мое обновление для примера использования DOMNodeInserted. - person Jasper; 08.03.2012
comment
Вам нужно будет использовать такой метод, как Long Polling, чтобы отслеживать изменение длины элемента, если длина изменяется, а затем захватить разницу в длине. Это даст вам любой «объект», который там находится. Это нестандартно, но сработает. - person Ohgodwhy; 08.03.2012
comment
Большое спасибо, Джаспер. Я не думаю, что это решает мою проблему с проблемами совместимости и всем остальным, но точно отвечает на мой вопрос. Спасибо за ваше время. - person Klaus Byskov Pedersen; 08.03.2012
comment
DOMNodeInserted устарел - person toutpt; 07.01.2014
comment
@toutpt Спасибо, я обновил ответ ссылкой на новый API. - person Jasper; 07.01.2014

Прочитав приведенный выше ответ, я теперь успешно использую это:

$('body').on({
   DOMNodeInserted : function(){
      alert('I have been added dynamically');
   },
   click : function(){
      alert('I was clicked');
   },
   '.dynamicElements'
});

Теперь все мои dynamicElements могут делать что-то по мере загрузки, используя потрясающую карту событий .on().

person tim    schedule 03.03.2013