Estou usando .on()
para vincular eventos de divs que são criados após o carregamento da página. Funciona bem para clicar, entrar com o mouse ... mas preciso saber quando um novo div da classe MyClass foi adicionado. Estou procurando por isso:
$('#MyContainer').on({
wascreated: function () { DoSomething($(this)); }
}, '.MyClass');
Como eu faço isso? Consegui escrever meu aplicativo inteiro sem um plugin e quero mantê-lo assim.
Obrigado.
Respostas:
Anteriormente, era possível se conectar ao
domManip
método jQuery para capturar todas as manipulações dom do jQuery e ver quais elementos foram inseridos etc., mas a equipe da jQuery desligou isso no jQuery 3.0+, pois geralmente não é uma boa solução para se conectar a métodos jQuery dessa maneira, e fizemos isso de forma que odomManip
método interno não esteja mais disponível fora do código jQuery principal.Eventos de mutação também foram descontinuados, como antes que se pudesse fazer algo como
$(document).on('DOMNodeInserted', function(e) { if ( $(e.target).hasClass('MyClass') ) { //element with .MyClass was inserted. } });
isso deve ser evitado e, hoje, devem ser usados Observadores de mutação, que funcionariam assim
var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation) if (mutation.addedNodes && mutation.addedNodes.length > 0) { // element added to DOM var hasClass = [].some.call(mutation.addedNodes, function(el) { return el.classList.contains('MyClass') }); if (hasClass) { // element has class `MyClass` console.log('element ".MyClass" added'); } } }); }); var config = { attributes: true, childList: true, characterData: true }; observer.observe(document.body, config);
fonte
Aqui está meu plug-in que faz exatamente isso - jquery.initialize
O uso é o mesmo que você usaria a
.each
função, mas com.initialize
função no elemento, a diferença.each
é que também inicializará elementos adicionados no futuro sem qualquer código adicional - não importa se você o adiciona com AJAX ou qualquer outra coisa.Initialize tem exatamente a mesma sintaxe da função .each
$(".some-element").initialize( function(){ $(this).css("color", "blue"); });
Mas agora, se um novo elemento correspondente ao seletor de algum elemento aparecer na página, ele será inicializado instantaneamente. A forma como o novo item é adicionado não é importante, você não precisa se preocupar com retornos de chamada, etc.
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
Plugin é baseado em
MutationObserver
fonte
.initialize
funçãocallback
apenas para elementos que são adicionados dinamicamente (por exemplo, via Ajax) e pular o retorno de chamada para elementos já presentes quando a página carrega inicialmente? Estou tentando adicionar um parâmetro aoptions
para fazer isso, mas até agora não consegui fazer isso funcionar.$('.myClass').addClass('ignore-initialize'); $.initialize('.myClass:not(.ignore-initialize)', callback);
Depois de revisar este e vários outros posts, tentei destilar o que achei o melhor de cada um em algo simples que me permitiu detectar quando uma classe de elementos é inserida e então agir sobre esses elementos .
function onElementInserted(containerSelector, elementSelector, callback) { var onMutationsObserved = function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { var elements = $(mutation.addedNodes).find(elementSelector); for (var i = 0, len = elements.length; i < len; i++) { callback(elements[i]); } } }); }; var target = $(containerSelector)[0]; var config = { childList: true, subtree: true }; var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; var observer = new MutationObserver(onMutationsObserved); observer.observe(target, config); } onElementInserted('body', '.myTargetElement', function(element) { console.log(element); });
É importante para mim que isso permite que a) o elemento de destino exista em qualquer profundidade dentro de "addedNodes" eb) a capacidade de lidar com o elemento apenas quando inicialmente inserido (sem necessidade de pesquisar a configuração do documento inteiro ou ignorar "já processado" bandeiras).
fonte
if(mutation.addedNodes.length)
porqueaddedNodes
e osremovedNodes
arrays estão sempre lá emmutation
do tipochildList
(verificado no IE11, Chrome53, FF49). Ainda +1, pois a sua é a única resposta ondeaddedNodes
é considerada (callback
é chamada somente quando um nó é adicionado); não apenas neste tópico, mas em muitos outros tópicos. Todos os outros estão apenas invocando ocallback
for all mutations, mesmo se o nó estiver sendo excluído.3 anos de experiência depois, é assim que escuto "elemento de uma determinada classe adicionado ao DOM" : você simplesmente adiciona um gancho na
html()
função jQuery , como este:function Start() { var OldHtml = window.jQuery.fn.html; window.jQuery.fn.html = function () { var EnhancedHtml = OldHtml.apply(this, arguments); if (arguments.length && EnhancedHtml.find('.MyClass').length) { var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is } return EnhancedHtml; } } $(Start);
Isso funciona se você estiver usando jQuery, o que eu faço. E não depende do evento específico do navegador
DOMNodeInserted
, que não é compatível com navegadores diferentes. Eu também adicionei a mesma implementação para.prepend()
No geral, isso funciona como um encanto para mim e, espero, para você também.
fonte
html
helper do jQuery para modificar o DOM, não apenas "usando jQuery" em geral. Os elementos adicionados usando, digamos,jQuery.append
não acionarão este evento.insertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
você poderia usar eventos de mutação
http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents
EDITAR
do MDN: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events
Obsoleto Este recurso foi removido da web. Embora alguns navegadores ainda possam suportá-lo, ele está em processo de exclusão. Não o use em projetos antigos ou novos. Páginas ou aplicativos da Web que o usam podem quebrar a qualquer momento.
Observadores de mutação são a substituição proposta para eventos de mutação em DOM4. Eles devem ser incluídos no Firefox 14 e Chrome 18.
https://developer.mozilla.org/en/docs/Web/API/MutationObserver
MutationObserver
fornece aos desenvolvedores uma maneira de reagir às mudanças em um DOM. Ele é projetado como uma substituição para eventos de mutação definidos na especificação de eventos DOM3.Exemplo de uso
O exemplo a seguir foi retirado de http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/ .
// select the target node var target = document.querySelector('#some-id'); // create an observer instance var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); // configuration of the observer: var config = { attributes: true, childList: true, characterData: true }; // pass in the target node, as well as the observer options observer.observe(target, config); // later, you can stop observing observer.disconnect();
fonte
Duas adições à resposta de adeneo:
(1) podemos mudar a linha
return el.classList.contains('MyClass');
Para
if( el.classList ) { return el.classList.contains('MyClass'); } else { return false; }
Portanto, não veremos o
"Uncaught TypeError: Cannot read property 'contains' of undefined"
erro.(2) add
subtree: true
noconfig
para encontrar nós adicionados de forma recursiva em todos os elementos adicionados.fonte