Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

javascript - How can I determine if a dynamically-created DOM element has been added to the 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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...