类似jQuery .closest()但遍历子孙?
有没有类似于jQuery
.closest()
的函数,但是用于遍历后代并返回最接近的函数?
我知道有.find()
函数,但它返回所有可能的匹配,不是最接近的。
编辑:
这里是最接近的定义(至less对我来说) :
首先遍历所有儿童,然后遍历每个儿童。
在下面给出的例子中, id='2'
是最接近的.closest
id="find-my-closest-descendant"
<div id="find-my-closest-descendant"> <div> <div class="closest" Id='1'></div> </div> <div class="closest" Id='2'></div> </div>
请参阅JSfiddle链接 。
根据你closest
的定义,我写了下面的插件:
(function($) { $.fn.closest_descendent = function(filter) { var $found = $(), $currentSet = this; // Current place while ($currentSet.length) { $found = $currentSet.filter(filter); if ($found.length) break; // At least one match: break loop // Get all children of the current set $currentSet = $currentSet.children(); } return $found.first(); // Return first match of the collection } })(jQuery);
如果通过“最接近”的后裔,你的意思是第一个孩子,那么你可以这样做:
$('#foo').find(':first');
要么:
$('#foo').children().first();
或者,要查找特定元素的首次出现,可以这样做:
$('#foo').find('.whatever').first();
要么:
$('#foo').find('.whatever:first');
实际上,我们需要对“最接近的后裔”的含义有一个确切的定义。
例如
<div id="foo"> <p> <span></span> </p> <span></span> </div>
哪个<span>
将$('#foo').closestDescendent('span')
返回?
您可以使用find
:first
selector:
$('#parent').find('p:first');
上面的代码会在#parent
的后代中find第一个<p>
元素。
我认为首先你必须定义“最接近”的含义。 如果您的意思是符合您的标准的后代节点是父母链接距离最短的距离,那么使用“:first”或“.eq(0)”将不一定成功:
<div id='start'> <div> <div> <span class='target'></span> </div> </div> <div> <span class='target'></span> </div> </div>
在这个例子中,第二个“.target” <span>
元素与“start” <div>
“更接近”,因为它只有一个父级跳转。 如果这就是“最接近”的意思,你需要在过滤函数中find最小距离。 jQueryselect器的结果列表总是按照DOM顺序排列。
也许:
$.fn.closestDescendant = function(sel) { var rv = $(); this.each(function() { var base = this, $base = $(base), $found = $base.find(sel); var dist = null, closest = null; $found.each(function() { var $parents = $(this).parents(); for (var i = 0; i < $parents.length; ++i) if ($parents.get(i) === base) break; if (dist === null || i < dist) { dist = i; closest = this; } }); rv.add(closest); }); return rv; };
这是一种黑客插件,因为它构build的结果对象,但想法是,你必须find你find的所有匹配元素中最短的父母path。 这个代码偏向于DOM树中向左的元素,因为<
check; <=
会偏向右方。
我制作了这个,没有位置select器的实现(他们需要的不仅仅是matchesSelector
):
演示: http : //jsfiddle.net/TL4Bq/3/
(function ($) { var matchesSelector = jQuery.find.matchesSelector; $.fn.closestDescendant = function (selector) { var queue, open, cur, ret = []; this.each(function () { queue = [this]; open = []; while (queue.length) { cur = queue.shift(); if (!cur || cur.nodeType !== 1) { continue; } if (matchesSelector(cur, selector)) { ret.push(cur); return; } open.unshift.apply(open, $(cur).children().toArray()); if (!queue.length) { queue.unshift.apply(queue, open); open = []; } } }); ret = ret.length > 1 ? jQuery.unique(ret) : ret; return this.pushStack(ret, "closestDescendant", selector); }; })(jQuery);
可能有一些错误,但没有太多的testing。
Rob W的回答对我来说并不合适。 我适应了这个工作。
//closest_descendent plugin $.fn.closest_descendent = function(filter) { var found = []; //go through every matched element that is a child of the target element $(this).find(filter).each(function(){ //when a match is found, add it to the list found.push($(this)); }); return found[0]; // Return first match in the list }
如果匹配select器,我将使用以下内容来包含目标本身:
var jTarget = $("#doo"); var sel = '.pou'; var jDom = jTarget.find(sel).addBack(sel).first();
标记:
<div id="doo" class="pou"> poo <div class="foo">foo</div> <div class="pou">pooo</div> </div>
即使这是一个古老的话题,我无法抗拒实现我最亲近的孩子。 提供最less的旅行(呼吸第一)的第一个发现的后裔。 一个是recursion的(个人最喜欢的),另一个使用待办事项列表,所以没有recursion作为jQquery扩展。
希望有人受益。
注意:recursion获取堆栈溢出,并且我改进了另一个,现在与前面给出的答案类似。
jQuery.fn.extend( { closestChild_err : function( selector ) { // recursive, stack overflow when not found var found = this.children( selector ).first(); if ( found.length == 0 ) { found = this.children().closestChild( selector ).first(); // check all children } return found; }, closestChild : function( selector ) { var todo = this.children(); // start whith children, excluding this while ( todo.length > 0 ) { var found = todo.filter( selector ); if ( found.length > 0 ) { // found closest: happy return found.first(); } else { todo = todo.children(); } } return $(); }, });
以下插件返回第n个最接近的后代。
$.fn.getNthClosestDescendants = function(n, type) { var closestMatches = []; var children = this.children(); recursiveMatch(children); function recursiveMatch(children) { var matches = children.filter(type); if ( matches.length && closestMatches.length < n ) { var neededMatches = n - closestMatches.length; var matchesToAdd = matches.slice(0, neededMatches); matchesToAdd.each(function() { closestMatches.push(this); }); } if (closestMatches.length < n) { var newChildren = children.children(); recursiveMatch(newChildren); } } return closestMatches; };
我正在寻找一个类似的解决scheme(我希望所有最接近的后代,即广度第一+所有匹配,不pipe它存在的水平),这是我最终做的:
var item = $('#find-my-closest-descendant'); item.find(".matching-descendant").filter(function () { var $this = $(this); return $this.parent().closest("#find-my-closest-descendant").is(item); }).each(function () { // Do what you want here });
我希望这有帮助。
这个方法呢?
$('find-my-closest-descendant').find('> div');
这个“直接的孩子”select器为我工作。
你有很多选项,但是$("#parent").children(".child");
是紧固件。 检查这篇文章的细节和基准