2013-05-17 4 views
23

Есть ли способ в Javascript или jQuery узнать, когда элемент HTML был добавлен в DOM динамически, либо через jQuery.append(), либо один из собственных манипуляторов узлов Javascript? Возможно, существует несколько способов добавления элементов HTML на страницу динамически, поэтому я не уверен, какие события или события я должен прослушивать.Определение того, был ли элемент HTML добавлен в DOM динамически

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

Я надеюсь, что есть что-то лучше, чем setTimeout() цикл на $(SOME ELEMENT).length > 0. (часть из которых я видел в How can I determine if a dynamically-created DOM element has been added to the DOM? но с 2008 года)

+2

Нет никаких хороших способов сделать это. Версия setTimeout работает повсюду, но опрос DOM обычно не является чем-то, что вы должны делать. События мутации работают в некоторых браузерах, но уже устарели и, вероятно, не должны использоваться. – adeneo

+0

Какое событие является сторонним инструментом для запуска добавления ссылки? Является ли это на загрузке страницы или нажатием какого-либо элемента на странице? –

+0

Блейк, я не могу легко сказать. Код был миниатюризирован и распространен на несколько JS-файлов, поэтому я не могу легко установить точку останова. – Stephen

ответ

10

Вы можете использовать Mutation Observers для этой цели - по крайней мере, если вам не нужно поддерживать IE/Opera.

Вот краткий пример (из html5rocks.com) о том, как они используются:

var insertedNodes = []; 
var observer = new WebKitMutationObserver(function(mutations) { 
    mutations.forEach(function(mutation) { 
     for(var i = 0; i < mutation.addedNodes.length; i++) 
      insertedNodes.push(mutation.addedNodes[i]); 
    }) 
}); 
observer.observe(document, { 
    childList: true 
}); 
console.log(insertedNodes); 

Обратите внимание на Webkit префикс. Вам необходимо использовать префикс для конкретного браузера. В Firefox это будет Moz.

+1

Хороший ответ! IE находит способ вызвать проблемы со всем :) – tymeJV

+1

Это, кажется, лучший ответ. Я хотел бы иметь возможность поддерживать IE8 +, но я думаю, что могу отстаивать компромисс, когда IE получает текст по умолчанию, который сторонний JS обслуживает, в то время как другие браузеры, поддерживающие Наблюдатели, могут это использовать. – Stephen

+1

FYI, я только что разместил решение, которое может обрабатывать IE10 +. См. Мой ответ. – naugtur

5

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

$(document).bind('DOMNodeInserted', function(event) { 
     alert('inserted ' + event.target.nodeName + // new node 
      ' in ' + event.relatedNode.nodeName); // parent 
}); 

Кроме того, я нашел некоторые другие варианты по этой ссылке:

Event when element added to page

+3

это событие устарело. – ThiefMaster

+2

Я не думаю, что это требует проголосовать. –

+4

Это устарело, потому что оно медленное и, как правило, плохая идея, но этот ответ остается верным решением. – naugtur

12

Основываясь на technique by Daniel Buchner у меня есть создала небольшую библиотеку для вставки DOM. Это более удобно использовать, чем сам хак.

Он использует события анимации css, поэтому он не основан на DOMMutationEvents, и это не Mutation Observer. Таким образом, это не замедляет работу страницы и имеет более широкую поддержку, чем MutationObserver.

Он имеет дополнительное преимущество от возможности использования с помощью любых селекторов CSS, которые вы хотите.

Пример использования:

insertionQ('.content div').every(function(element){ 
    //callback on every new div element inside .content 
}); 

Если вы вызываете его после DOMReady, он собирается поймать только новые элементы.

https://github.com/naugtur/insertionQuery Смотрите больше вариантов

+0

Это отлично работало, чтобы скрыть/показать виджет интеркома программным способом (для этого они не предоставляют API). –

+0

Другая библиотека, которая включает в себя одну и ту же технику, - это * best-dom *, предоставляющая [Live Extensions] (https://github.com/chemerisuk/better-dom/wiki/Live-extensions). – feeela

1

Не уверен, что если кто-то до сих пор ищет для этого, но я и это решение, которое я закончил с использованием.

var __css = document.createElement("style"); 
__css.type = "text/css"; 
__css.innerHTML = '.alertInsertion {animation: __nodeInserted 0.001s !important; -o-animation: __nodeInserted 0.001s !important; -ms-animation: __nodeInserted 0.001s !important; -moz-animation: __nodeInserted 0.001s !important; -webkit-animation: __nodeInserted 0.001s !important;}'+ 
'@keyframes __nodeInserted {from{outline-color: #111;}to{outline-color: #000;}}'+ 
'@-moz-keyframes __nodeInserted {from{outline-color: #111;}to{outline-color: #000;}}'+ 
'@-webkit-keyframes __nodeInserted {from{outline-color: #111;}to{outline-color: #000;}}'+ 
'@-ms-keyframes __nodeInserted {from{outline-color: #111;}to{outline-color: #000;}}'+ 
'@-o-keyframes __nodeInserted {from{outline-color: #111;}to{outline-color: #000;}}'; 
document.body.appendChild(__css); 

insertion_event = function(event){ 
    if (event.animationName == '__nodeInserted') { 
     event.target.className = event.target.className.replace(/\balertInsertion\b/,''); 
     document.dispatchEvent(new CustomEvent('elementInserted', {'target': event.target})); 
    } 
} 

document.addEventListener('animationstart', insertion_event, false); 
document.addEventListener('MSAnimationStart', insertion_event, false); 
document.addEventListener('webkitAnimationStart', insertion_event, false); 

Добавление класса «» alertInsertion в CSS страницы с помощью вызова анимации __nodeInserted.

Если анимация запускается, она удаляет класс из элемента и отправляет настраиваемое событие с именем elementInserted, которое включает в себя элемент, который его вызвал.

просто использовать его, добавив слушатель событий:

document.addEventListener('elementInserted', function(e) 
{ 
    //Do whatever you want with e.target here. 
}); 

и добавление класса .alertInsertion любых элементов, которые вы хотите, чтобы вызвать его.

Если элемент получил еще один класс с анимацией, он будет запущен после удаления этого класса.

Смежные вопросы