Determining if a HTML element has been added to the DOM dynamically

Is there a way in Javascript or jQuery to find out when a HTML element has been added to the DOM dynamically, either through jQuery.append() or one of the native Javascript's node manipulators? There are probably several different ways to add HTML elements to the page dynamically, so I'm not sure what event or events I should be listening on.

The specific example is that that an anchor tag is being added to the page by a third-party Javascript code (that I cannot modify or easily gleam). I want to change the link's text.

I am hoping there is something better than a setTimeout() loop on $(SOME ELEMENT).length > 0. (part of which I saw in How can I determine if a dynamically-created DOM element has been added to the DOM? but it's from 2008)

Answers:

Answer

You can use Mutation Observers for this purpose - at least if you do not need to support IE/Opera.

Here's a short example (taken from html5rocks.com) on how they are used:

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);

Note the Webkit prefix. You need to use the browser-specific prefix. In Firefox it would be Moz instead.

Answer

Based on the technique by Daniel Buchner I have created a small library to catch DOM insertions. It's more comfortable to use than the hack itself.

It uses css animation events, so it's not based on DOMMutationEvents, and it's not Mutation Observer. So it's not slowing down the page and it has a wider support than MutationObserver.

It has an added benefit of being able to use any CSS selectors you want.

Example usage:

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

If you invoke it after DOMReady, it's going to catch only new elements.

See https://github.com/naugtur/insertionQuery for more options

Answer

Why don't you try this? I dont remember the exact function I used but it's kinda similar than this...

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

Also, I found some other options at this link:

Event when element added to page

Answer

Not sure if anyone is still looking for this but I was and this is the solution I ended up using.

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);

Adding the class 'alertInsertion' to the css of the page with a call to the __nodeInserted animation.

if the animation is triggered it removes the class from the element and sends out a custom event called elementInserted that includes the element that triggered it.

simply use it by adding an event listener:

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

and adding the .alertInsertion class to any elements you want to trigger it.

If the element got another class with an animation it will run after this class has been removed.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.