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.
精彩评论