JSFiddle - React, Tailwind, and code Playground
by Graham Dixon
HTML
<ul class="start">
<li>
<a id="first" href="#" class='move'>Link</a>
<ul>
<li>
<a href="#" class='move'>Link</a>
<ul>
<li>
<a href="#" class='move'>Link</a>
</li>
<li>
<a href="#" class='move'>Link</a>
</li>
<li>
<a href="#" class='move'>Link</a>
</li>
</ul>
</li>
<li>
<a href="#" class='move'>Link</a>
</li>
<li>
<a href="#" class='move'>Link</a>
</li>
</ul>
</li>
</ul>
<br/>
<br/>
<br/>
<span>Selected</span>
<ul id="results"></ul>
JavaScript
$.fn.findDeepest = function() {
var results = [];
this.each(function() {
var deepLevel = 0;
var deepNode = this;
treeWalkFast(this, function(node, level) {
if (level > deepLevel) {
deepLevel = level;
deepNode = node;
}
});
results.push({"depth":deepLevel/2, "deepNode": deepNode});
});
return this.pushStack(results);
};
var treeWalkFast = (function() {
// create closure for constants
var skipTags = {
"SCRIPT": true,
"IFRAME": true,
"OBJECT": true,
"EMBED": true
};
return function(parent, fn, allNodes) {
var node = parent.firstChild,
nextNode;
var level = 1;
while (node && node != parent) {
if (allNodes || node.nodeType === 1) {
if (fn(node, level) === false) {
return (false);
}
}
// if it's an element &&
// has children &&
// has a tagname && is not in the skipTags list
// then, we can enumerate children
if (node.nodeType === 1 && node.firstChild && !(node.tagName && skipTags[node.tagName])) {
node = node.firstChild;
++level;
} else if (node.nextSibling) {
node = node.nextSibling;
} else {
// no child and no nextsibling
// find parent that has a nextSibling
--level;
while ((node = node.parentNode) != parent) {
if (node.nextSibling) {
node = node.nextSibling;
break;
}
--level;
}
}
}
}
})();
// find deepest descendant of each .start node
var deeps = $(".start").findDeepest();
// output those deepest descendants so we can see what they are
deeps.each(function(i, v) {
$("#results").append(
$("<li>").html("Node: " + $(v['deepNode']).prop("tagName") + " " + $(v['deepNode']).html())
);
$("#results").append(
$("<li>").html("Depth: " + v['depth'])
);
});