I'd like to be able to identify whether a given DOM node has been appended/inserted into another node yet, or whether 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'd like to be able to identify whether a given DOM node has been appended/inserted into another node yet, or whether 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.
Share Improve this question edited Apr 18, 2010 at 6:41 thomasrutter asked Apr 12, 2010 at 5:56 thomasrutterthomasrutter 117k31 gold badges153 silver badges170 bronze badges 1- I've edited the question a bit because it was not well expressed. Sorry to nickf who provided a great answer but overkill for what I really wanted! – thomasrutter Commented Apr 12, 2010 at 6:33
4 Answers
Reset to default 6I 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.