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

后端 未结 11 903
滥情空心
滥情空心 2020-12-02 20:07

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-create

相关标签:
11条回答
  • 2020-12-02 20:35
    var finalElement=null; 
    

    I am building dom objects in a loop, when the loop is on the last cycle and the lastDomObject is created then:

     finalElement=lastDomObject; 
    

    leave loop:

    while (!finalElement) { } //this is the delay... 
    

    The next action can use any of the newly created dom objects. It worked on the first try.

    0 讨论(0)
  • 2020-12-02 20:36

    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.

    0 讨论(0)
  • 2020-12-02 20:37

    Instead of walking the DOM tree up to the document element just use element.ownerDocument. see here: https://developer.mozilla.org/en-US/docs/DOM/Node.ownerDocument and do this:

    element.ownerDocument.body.contains(element)
    

    and you're good.

    0 讨论(0)
  • 2020-12-02 20:39

    Can you no do a document.getElementById('newElementId'); and see if that returns true. If not, like you say, wait 100ms and try again?

    0 讨论(0)
  • 2020-12-02 20:40

    You could query document.getElementsByTagName("*").length or create a custom appendChild function like the folllowing:

    var append = function(parent, child, onAppend) {
      parent.appendChild(child);
      if (onAppend) onAppend(child);
    }
    
    //inserts a div into body and adds the class "created" upon insertion
    append(document.body, document.createElement("div"), function(el) {
      el.className = "created";
    });
    

    Update

    By request, adding the information from my comments into my post

    There was a comment by John Resig on the Peppy library on Ajaxian today that seemed to suggest that his Sizzle library might be able to handle DOM insertion events. I'm curious to see if there will be code to handle IE as well

    Following on the idea of polling, I've read that some element properties are not available until the element has been appended to the document (for example element.scrollTop), maybe you could poll that instead of doing all the DOM traversal.

    One last thing: in IE, one approach that might be worth exploring is to play with the onpropertychange event. I reckon appending it to the document is bound to trigger that event for at least one property.

    0 讨论(0)
  • 2020-12-02 20:41

    Here is another solution to the problem extracted from the jQuery code. The following function can be used to check if a node is attached to the DOM or if it is "disconnected".

    function isDisconnected( node ) {
        return !node || !node.parentNode || node.parentNode.nodeType === 11;
    }
    

    A nodeType === 11 defines a DOCUMENT_FRAGMENT_NODE, which is a node not connected to the document object.

    For further information see the following article by John Resig: http://ejohn.org/blog/dom-documentfragments/

    0 讨论(0)
提交回复
热议问题