I am working a lot with nodes before they are attached to the main page's DOM; and I need to perform some work depending on whether or not a given node is contained within the main document or not.
My current method is to walk up the parents, via:
if this.el$.closest("body").length > 0
Is there a more appropriate way to do this? (Preferrably one that doesn't have to walk all of the node's ancestors?)
Use the getElementsByTagName to Check the Existence of an Element in DOM. The function getElementsByTagName() can return all elements with the specified tagName in DOM . The return of the function can be one or more elements or null if no element is found.
Nodes are in the DOM aka Document Object model. In the DOM, all parts of the document, such as elements, attributes, text, etc. are organized in a hierarchical tree-like structure; consisting of parents and children. These individual parts of the document are known as nodes.
So, in a nutshell, a node is any DOM object. An element is one specific type of node as there are many other types of nodes (text nodes, comment nodes, document nodes, etc...). The DOM consists of a hierarchy of nodes where each node can have a parent, a list of child nodes and a nextSibling and previousSibling.
The most common methods for selecting/creating a list of nodes in an HTML document are: querySelectorAll() getElementsByTagName() getElementsByClassName()
You have several options which execute at several different speeds.
var $document = $(document);
var $element = $("#jq-footer");
var exists;
// Test if the element is within a body
exists = $element.closest("body").length;
// Test if the document contains an element
// wrong syntax, use below instead --> exists = $.contains($document, $element);
exists = $.contains(document.documentElement, $element[0]);
// Test if the element is within a body
$($element).parents().is("body");
// Manually loop trough the elements
exists = elementExists($element[0]);
// Used for manual loop
function elementExists(element) {
while (element) {
if (element == document) {
return true;
}
element = element.parentNode;
}
return false;
}
See Performance Test
For this test I copied a huge amount of html to traverse over, I copied the source of one of the jQuery pages into a fiddle, stripping out all the script tags leaving only the body and the html in between.
Feel free you use document instead of "body" and vice-versa or add more tests but it should give you the general idea.
Edit
I updated the performance test to use the correct syntax for contains as the previous one was incorrect and always returned true even if the element did not exist. the blow now returns true if the element exists but if you specify a selector which doesn't exist it will return false.
exists = $.contains(document.documentElement, $element[0]);
I also added the suggested alternative mentioned by MrOBrian in the comments of the question which is again slightly faster than contains.
Nice one MrOBrian.
Edit
Here is the jsPerf performance test with all the nice charts.
Thanks Felix Kling for spotting the issue and helping me fix the jsPerf tests.
Added more test results from the comments, this one is really good:
jsPerf performance test: dom-tree-test-exists
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With