Reputation: 3480
DOMNodeInserted is known to make dynamic pages slow, MDN even recommends not using it altogether, but doesn't provide any alternatives.
I'm not interested in the element inserted, I just need to know when some script modifies the DOM. Is there a better alternative to mutation event listeners (maybe getElementsByTagName inside an nsiTimer)?
Upvotes: 30
Views: 31358
Reputation: 63
try to use customElements
, but not for already created elements!
customElements.define( 'insertion-triggerable', class extends HTMLElement {
connectedCallback() {
console.log( 'connected' )
}
disconnectedCallback() {
console.log( 'disconnected' )
}
adoptedCallback() {
console.log( 'adopted' )
}
} );
let element = document.createElement( 'insertion-triggerable' );
OR
customElements.define( 'insertion-triggerable', class extends HTMLDivElement {
// --||--
}, { extends: 'div' } );
let divElement = document.createElement( 'div', { is: 'insertion-triggerable' } );
Upvotes: 0
Reputation: 8249
If you are creating a web app that targets recent mobile phones and newer versions of browsers (Firefox 5+, Chrome 4+, Safari 4+, iOS Safari 3+, Android 2.1+), you can use the following code to create an awesome event for the insertion of dom nodes, and it even runs on the nodes initially part of the page's static mark-up!
Here's the link to the full post with and example: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/
Note on Mutation Observers: while the newer Mutation Observers features in recent browsers are great for monitoring simple insertions and changes to the DOM, do understand that this method can be used to do far more as it allows you to monitor for any CSS rule match you can thing of. This is super powerful for many use-cases, so I wrapped this up in a library here: https://github.com/csuwildcat/SelectorListener
You'll need to add the appropriate prefixes to the CSS and animationstart event name if you want to target various browsers. You can read more about that in the post linked to above.
CSS:
@keyframes nodeInserted {
from {
outline-color: #fff;
}
to {
outline-color: #000;
}
}
div.some-control {
animation-duration: 0.01s;
animation-name: nodeInserted;
}
JavaScript:
document.addEventListener('animationstart', function(event){
if (event.animationName == 'nodeInserted'){
// Do something here
}
}, true);
This enables things that are almost impossible to do with Mutation Observers
CSS:
@keyframes adjacentFocusSequence {
from {
outline-color: #fff;
}
to {
outline-color: #000;
}
}
.one + .two + .three:focus {
animation-duration: 0.01s;
animation-name: adjacentFocusSequence;
}
JavaScript:
document.addEventListener('animationstart', function(event){
if (event.animationName == 'adjacentFocusSequence'){
// Do something here when '.one + .two + .three' are
// adjacent siblings AND node '.three' is focused
}
}, true);
Upvotes: 43
Reputation: 105
The same technique as csuwldcat described has been made into an easy to use jQuery plugin (if that's your thing): https://github.com/liamdanger/jQuery.DOMNodeAppear
Upvotes: 0
Reputation: 2441
One new alternative that @naugtur briefly mentioned is MutationObserver. It's designed as a replacement for the deprecated mutation events, if the browser(s) you're developing for supports it (like if you're developing a browser extension).
Upvotes: 12
Reputation: 84
This is posted here because this question is where I landed looking for help with DOMNodeInserted failing with IE9, but please note this solution is specifically for a situation where jQuery is being used within an ASP.NET context that uses an End Request function. Your mileage may vary, etc....
Basically, we are going to throw away the DOMNodeInserted altogether and use End Request to load our event handler:
OLD:
$(document).ready(function() {
$(document).bind('DOMNodeInserted', function(event){
My jQuery event handler...
});
});
===================================
NEW:
function Ajax_EndRequest {
function2();
}
function2 (a,b){
My jQuery event handler...
}
$(document).ready(function(){
add_endRequest(Ajax_EndRequest); //this is what actually invokes the function upon request end.
My jQuery event handler...//REMOVED -- don't need this now
});
Upvotes: 0
Reputation: 19
If all you want to do is trigger an event when the DOM changes, do something like this:
var nodes=document.getElementsByTagName('*')||document.all;
function domchange(){
alert('Hello');
}
window.setInterval(function(){
var newnodes=document.getElementsByTagName('*')||document.all;
if(newnodes!=nodes){
nodes=newnodes;
domchange();
}
},1);
Upvotes: -23