开发者

Javascript: how to tell if a node object has been inserted into a document/another element yet

I'd like to be able to identify whether a given DOM node has been appended/inserted into another node yet, or wheth开发者_开发技巧er it is fresh out of document.createElement() or similar and has not been placed anywhere.

In most browsers just checking the parentNode works.

if (!node.parentNode) {
  // this node is not part of a larger document
}

However, in Internet Explorer it appears that new elements, even right after they've been created with document.createElement() already have a parentNode object (of type DispHTMLDocument??).

Any other nice cross-browser and reliable way?

Edit: looks like Internet Explorer is implicitly creating a DocumentFragment (with nodeType of 11) and setting that as the node's parentNode property.


I think that even without IE's foibles, checking for the presence of parentNode might not be enough. For example:

var d = document.createElement('div');
var s = document.createElement('span');
d.appendChild(s);
if (s.parentNode) {
    // this will run though it's not in the document
}

If something is in the document, then eventually one of its ancestors will be the document itself. Try this out and see how it goes:

function inDocument(node) {
    var curr = node;
    while (curr != null) {
        curr = curr.parentNode;
        if (curr == document) return true;
    }
    return false;
}

// usage: 
// if (inDocument(myNode)) { .. }

If you only want to check to a certain depth - that is, you know that your newly created elements aren't going to be nested any further than IE's Fragment, try this:

function inDocument(node, depth) {
    depth = depth || 1000;
    var curr = node;
    while ((curr != document) && --depth) {
        curr = curr.parentNode;
        if (curr == null) return false;
    }
    return true;
}

inDocument(myNode, 2);  // check only up to two deep.
inDocument(myNode);     // check up to 1000 deep.


I've found an answer to my own question. Sorry! I seem to be doing that a lot lately.

Document fragments have a nodeType of 11, and are never inserted into the document, so you can check it like this:

if (!node.parentNode || node.parentNode.nodeType == 11) {
  // this node is floating free
}

You only need a Document fragment when you are inserting more than one peer node. IE implicitly creates one for all newly created nodes though. Anyway checking the nodeType for 11 works.


DOM level 3 introduced the compareDocumentPosition method for a Node that gives positional information on how two nodes are related to each other. One of the return values is DOCUMENT_POSITION_DISCONNECTED meaning the nodes are not connected to each other. Could use this fact to check if a node is not contained inside another node using:

Boolean(parent.compareDocumentPosition(descendant) & 16)

DOCUMENT_POSITION_DISCONNECTED = 0x01;
DOCUMENT_POSITION_PRECEDING    = 0x02;
DOCUMENT_POSITION_FOLLOWING    = 0x04;
DOCUMENT_POSITION_CONTAINS     = 0x08;
DOCUMENT_POSITION_CONTAINED_BY = 0x10;
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;

Google has written a cross-browser implementation (I think, no mention of IE there) of a contains function that can be found at http://code.google.com/p/doctype-mirror/wiki/ArticleNodeContains. You could use that for checking if a given node is a descendant of document

.contains(document, someNode)


In what version of IE were you testing this:


if (!node.parentNode) {
  // this node is not part of a larger document
}

perhaps with older versions of IE you should try:


if (!node.parentElement) {
  // this node is not part of a larger document
}

instead.

Although on nines you'll get >>null<< with both approaches providing that the top created container element isn't parsed yet which in turn gets translated into >>false<< exactly as you wanted it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜