如何选择与过滤器匹配的连续元素
给出以下示例:
<img class="a" /> <img /> <img class="a" /> <img class="a" id="active" /> <img class="a" /> <img class="a" /> <img /> <img class="a" />
(我只是以img标签为例,这不是我的代码中的内容)
使用jQuery,我们如何选择与#active(在此示例中为中间四个)相邻的类为" a"的img标签?
我们可以通过遍历所有后续元素和前面的元素来相当容易地做到这一点,在过滤条件失败时停止,但是我想知道jQuery是否可以本机运行?
解决方案
回答
我相信循环播放是我们最好的选择。但是我们可以尝试每个活动,然后在条件打破之前和之后移动,如果条件足够大,则速度会更快。
回答
代字号(〜)是兄弟姐妹选择器:
$('#active ~ img.a').hide();
回答
@Prestaul
$('#active ~ img.a')
只会选择以下兄弟姐妹,也将包括非连续兄弟姐妹。文件:http://docs.jquery.com/Selectors/siblings#prevsiblings
回答
这是另一种方法,尽管兄弟选择器的答案很酷:
var next = $('#active').next('.a'); var prev = $('#active').prev('.a');
编辑:我重新阅读了要求,这不是我们想要的。我们可以使用nextAll和prevAll,但是那些也不会在没有类名的情况下在IMG处停止。
回答
这是我最后想出的。
// here's our active element. var $active = $('#active'); // here is the filter we'll be testing against. var filter = "img.a"; // $all will be the final jQuery object with all the consecutively matched elements. // start it out by populating it with the current object. var $all = $active; for ($curr = $active.prev(filter); $curr.length > 0; $curr = $curr.prev(filter)) { $all = $all.add($curr); } for ($curr = $td.next(filter); $curr.length > 0; $curr = $curr.next(filter)) { $all = $all.add($curr); }
对于后续问题,我可以看到如何通过将其变为带有两个参数的函数来轻松将其概括:一个初始元素和一个过滤器字符串,任何人都可以向我指出正确的方向以找出如何扩展jQuery对象添加这样的功能?
编辑:从那以后,我发现each()函数在某些用途上会做得很好。在我自己的情况下,它并不是很干净,因为我要为所有这些元素使用单个jQuery对象,但是这里介绍了如何将每个jQuery对象用于不同的目的(在此示例中隐藏连续的" .a"元素:)
$('#active') .nextAll() .each(hideConsecutive) .end() .prevAll() .each(hideConsecutive) ; function hideConsecutive(index, element) { var $e = $(element); if (!$e.is(".a")) { return false; // this stops the each function. } else { $e.hide('slow'); } }
--
编辑:我已经把它放到一个插件中了。如果我们有兴趣的话,请访问http://plugins.jquery.com/project/Adjacent。
回答
下面的代码将添加两个新函数,nextConsecutive()和prevConsecutive()。他们应该做你想做的。
$ .each(['prev','next'],function(unusedIndex,name){
$ .fn [name +'Consecutive'] = function(matchExpr){
var $all = (name == 'prev') ? $(this).prevAll() : $(this).nextAll(); if (!matchExpr) return $all; var $notMatch = $($all).not(matchExpr).filter(':first'); if ($all.index($notMatch) != -1) return $allConsecutive = $all.slice(0, $all.index($notMatch)); return $all; };
});