Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine if a dynamically-created DOM element has been added to the DOM?

Tags:

javascript

dom

According to spec, only the BODY and FRAMESET elements provide an "onload" event to attach to, but I would like to know when a dynamically-created DOM element has been added to the DOM in JavaScript.

The super-naive heuristics I am currently using, which work, are as follows:

  • Traverse the parentNode property of the element back until I find the ultimate ancestor (i.e. parentNode.parentNode.parentNode.etc until parentNode is null)

  • If the ultimate ancestor has a defined, non-null body property

    • assume the element in question is part of the dom
  • else

    • repeat these steps again in 100 milliseconds

What I am after is either confirmation that what I am doing is sufficient (again, it is working in both IE7 and FF3) or a better solution that, for whatever reason, I have been completely oblivious to; perhaps other properties I should be checking, etc.


EDIT: I want a browser-agnostic way of doing this, I don't live in a one-browser world, unfortunately; that said, browser-specific information is appreciated, but please note which browser you know that it does work in. Thanks!

like image 795
Jason Bunting Avatar asked Oct 20 '08 22:10

Jason Bunting


People also ask

How do you know if an element is attached to DOM?

To check if an element is connected or attached to the DOM or the document object ( or otherwise called the context ), you can use the isConnected property in the element's object in JavaScript. The isConnected element property returns boolean true if it connected to the DOM ( document object) and false if not.

Which method is triggered when an element is added to the DOM?

The actual answer is "use mutation observers" (as outlined in this question: Determining if a HTML element has been added to the DOM dynamically), however support (specifically on IE) is limited (http://caniuse.com/mutationobserver). So the actual ACTUAL answer is "Use mutation observers....

What is the best way to locate an element in the DOM?

The easiest way to access a single element in the DOM is by its unique ID. You can get an element by ID with the getElementById() method of the document object. In the Console, get the element and assign it to the demoId variable.

How do you tell if a DOM element is visible in the current viewport?

Summary. Use the getBoundingClientRect() method to get the size of the element and its relative position to the viewport. Compare the position of the element with the viewport height and width to check if the element is visible in the viewport or not.


1 Answers

UPDATE: For anyone interested in it, here is the implementation I finally used:

function isInDOMTree(node) {    // If the farthest-back ancestor of our node has a "body"    // property (that node would be the document itself),     // we assume it is in the page's DOM tree.    return !!(findUltimateAncestor(node).body); } function findUltimateAncestor(node) {    // Walk up the DOM tree until we are at the top (parentNode     // will return null at that point).    // NOTE: this will return the same node that was passed in     // if it has no ancestors.    var ancestor = node;    while(ancestor.parentNode) {       ancestor = ancestor.parentNode;    }    return ancestor; } 

The reason I wanted this is to provide a way of synthesizing the onload event for DOM elements. Here is that function (although I am using something slightly different because I am using it in conjunction with MochiKit):

function executeOnLoad(node, func) {    // This function will check, every tenth of a second, to see if     // our element is a part of the DOM tree - as soon as we know     // that it is, we execute the provided function.    if(isInDOMTree(node)) {       func();    } else {       setTimeout(function() { executeOnLoad(node, func); }, 100);    } } 

For an example, this setup could be used as follows:

var mySpan = document.createElement("span"); mySpan.innerHTML = "Hello world!"; executeOnLoad(mySpan, function(node) {     alert('Added to DOM tree. ' + node.innerHTML); });  // now, at some point later in code, this // node would be appended to the document document.body.appendChild(mySpan);  // sometime after this is executed, but no more than 100 ms after, // the anonymous function I passed to executeOnLoad() would execute 

Hope that is useful to someone.

NOTE: the reason I ended up with this solution rather than Darryl's answer was because the getElementById technique only works if you are within the same document; I have some iframes on a page and the pages communicate between each other in some complex ways - when I tried this, the problem was that it couldn't find the element because it was part of a different document than the code it was executing in.

like image 162
Jason Bunting Avatar answered Sep 23 '22 00:09

Jason Bunting