如果我有一组元素:
<div class="start">
<div>
<span>Text 1</span>
</div>
</div>
<div class="start">
<span>
<div>
<span>Text 2</span>
</div>
<div>
<div>
<span>Text 3</span>
</div>
</div>
</span>
</div>
最好的方法(使用jQuery)检索最嵌套的子元素(在这种情况下是跨越“Text 1”和“Text 3”),而不知道具体事先是什么元素结构?
这是我正在使用的jsFiddle。
另外,如果之前有人问我,我很抱歉,但我没有找到类似这个问题的任何内容。
答案 0 :(得分:4)
这是一个实现,它使用我之前编写的treeWalk函数,然后将其包装在jquery方法中,该方法查找传入的jQuery对象中每个项目的最深层后代,并返回包含这些节点的新jQuery对象。
使用递归和大量jQuery的解决方案可以使用更少的代码来完成,但它可能会更慢。这是基于遍历树的通用本机JS树步行函数。
使用比OP的HTML更复杂的HTML测试用例的演示:http://jsfiddle.net/jfriend00/8tC3a/
$.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(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;
}
}
}
}
})();
var deeps = $(".start").findDeepest();
deeps.each(function(i,v){
$("#results").append(
$("<li>").html($(v).prop("tagName") + " " + $(v).html())
);
});
答案 1 :(得分:2)
答案 2 :(得分:2)
使用最少的代码行的另一种方法(可能不那么快)可以如下:
var all_matched_elements = $(":contains('" + text_to_search + "')");
var all_parent_elements = $(all_matched_elements).parents();
var all_deepest_matches = $(all_matched_elements).not(all_parent_elements);
如果您的文本位于具有其他子元素的元素内,则此方法特别有用:
<div class="start">
<div>
<div>Text 1<span>Alpha Beta Gamma</span></div>
</div>
</div>
但是,上面的代码不适用于看起来如下的DOM:
<div class="start">
<div>
<div id="zzz">search-text
<div id="aaa">search-text</div>
</div>
</div>
</div>
在上述情况下,它只会选择内部最多的id&#34; #aaa&#34;。它会丢弃id&#34;#zzz&#34;。如果有人想选择id&#34;#zzz&#34;然后必须修改开头的代码以从&#34; all_parent_elements&#34;中删除元素。其直接文本也与搜索文本匹配。
答案 3 :(得分:0)
我认为这对你有用。
var deepestLevel = 0;
var deepestLevelText = "";
function findDeepNested(element, currentLevel) {
if ((element.children().length == 0) && (deepestLevel < currentLevel)) {
// No children and current level is deeper than previous most nested level
deepestLevelText="<li>" + element.text() + "</li>";
}
else { // there are children, keep diving
element.children().each( function () {
findDeepNested($(this), currentLevel + 1);
});
}
}
$(".start").each( function () {
deepestLevel = 0;
deepestLevelText = "";
findDeepNested($(this), 0);
$("#results").append(deepestLevelText);
});
答案 4 :(得分:-1)
<script type="text/javascript">
function findFarthestNode(node)
{
if(node.parent().length && node.parent().prop("tagName") != "BODY")
return findFarthestNode(node.parent());
return node;
}
jQuery(document).ready(function() {
node = jQuery("span");
farthest = findFarthestNode(node);
console.log(farthest);
});
</script>