jQuery查找与表达式匹配的所有先前元素

使用jQuery, 如何匹配DOM树中当前元素之前的元素? 使用prevAll()仅匹配以前的兄弟姐妹。

例如:

 
find this one
find the previous .findme
don't find this one

在我的具体情况下,我将在链接点击之前搜索第一个 .findme元素。

好的,这就是我想出来的 – 希望它在许多不同的情况下都会有用。 它是jQuery的2个扩展,我称之为prevALLnextALL 。 虽然标准prevAll()与之前的兄弟prevALL()匹配, prevALL()匹配DOM树中的所有前面的元素,类似于nextAll()nextALL()

我将在下面的评论中尝试解释它:

 // this is a small helper extension i stole from // http://www.texotela.co.uk/code/jquery/reverse/ // it merely reverses the order of a jQuery set. $.fn.reverse = function() { return this.pushStack(this.get().reverse(), arguments); }; // create two new functions: prevALL and nextALL. they're very similar, hence this style. $.each( ['prev', 'next'], function(unusedIndex, name) { $.fn[ name + 'ALL' ] = function(matchExpr) { // get all the elements in the body, including the body. var $all = $('body').find('*').andSelf(); // slice the $all object according to which way we're looking $all = (name == 'prev') ? $all.slice(0, $all.index(this)).reverse() : $all.slice($all.index(this) + 1) ; // filter the matches if specified if (matchExpr) $all = $all.filter(matchExpr); return $all; }; }); 

用法:

 $('.myLinks').click(function() { $(this) .prevALL('.findme:first') .html("You found me!") ; // set previous nodes to blue $(this).prevALL().css('backgroundColor', 'blue'); // set following nodes to red $(this).nextALL().css('backgroundColor', 'red'); }); 

编辑 – 从头开始​​重写的function。 我只想到了一种更快捷,更简单的方法。 查看编辑历史记录以查看我的第一次迭代。

再次编辑 – 找到一种更简单的方法!

大概你是在onclick处理程序中执行此操作,因此您可以访问被单击的元素。 我要做的是做一个prevAll来看它是否处于同一水平。 如果没有,那么我会做一个parent()。prevAll()来获取父元素的前一个兄弟,然后迭代这些兄弟元素,检查它们的内容是否有所需的元素。 继续向上移动DOM树,直到找到你想要的或者命中DOM的根。 这是一种通用算法。

如果您知道它在表中,那么您可以简单地获取包含该元素的行,并从该行向后遍历表的行,直到找到包含所需元素的行。

我认为在一个(链式)声明中没有办法做到这一点。

编辑 :此解决方案适用于您的原始问题,您在第一条评论中提到的问题,以及之后评论中详细说明的问题。

 $('.myLinks').click(function() { var findMe = ''; $(this).parents().each(function() { var a = $(this).find('.findme').is('.findme'); var b = $(this).find('.myLinks').is('.myLinks'); if (a && b) { // look for first parent that // contains .findme and .myLinks $(this).find('*').each(function() { var name = $(this).attr('class'); if ( name == 'findme') { findMe = $(this); // set element to last matching // .findme } if ( name == 'myLinks') { return false; // exit from the mess once we find // .myLinks } }); return false; } }); alert(findMe.text() ); // alerts "find this one" }); 

这适用于OP中的示例以及注释中所述的修改示例:

 
don't find this one
find this one
find the previous .findme
don't find this one

以及您添加的此测试用例:

 
don't find this one
don't find this one
find this one
find the previous .findme

我通常对元素(1,2,3 ..)(rel =“number”)进行编号,因此我使用此代码为所有以前的元素提供类:

 var num = $(this).attr("rel"); for (var i = 1; i<=num; i++) { $('.class[rel="'+i+'"]').addClass("newclass"); } 

我遇到了同样的问题,我想出了什么。 我的函数使用compareDocumentPosition 。 不知道它在性能方面与其他解决方案的比较。

 $.fn.findNext = function ( selector ) { var found, self = this.get(0); $( selector ) .each( function () { if ( self.compareDocumentPosition( this ) === 4 ){ found = this; return false; } }) return $(found); } 

当然,人们可以很容易地改变它来获取调用元素后面的所有元素。

 $.fn.nextALL= function ( selector ) { var found = [], self = this.get(0); $( selector ) .each( function () { if ( self.compareDocumentPosition( this ) === 4 ) found.push(this); }) return $(found); } 

编辑:精简版

 $.fn.findNext = function( s ){ var m = this[0], f=function(n){return m.compareDocumentPosition(n)===4;}; return this.pushStack( $(s).get().filter(f) ); }