2009-12-01 65 views
16

next,prev,nextAll和prevAll方法非常有用,但如果您尝试查找的元素不在同一父元素中,则不会。我想要做的是这样的:jQuery查找某个类的next/prev元素,但不一定是兄弟

<div> 
    <span id="click">Hello</span> 
</div> 
<div> 
    <p class="find">World></p> 
</div> 

当按下id为click跨度,我想下一个元素与类find,在这种情况下是不被点击的兄弟匹配元素如此next()nextAll()将无法​​正常工作。

+0

可能重复的[jQuery来找到匹配表达式的所有先前的元件](http://stackoverflow.com/questions/322912/jquery-to-find-all-previous-elements-that-match- an-expression) – sachleen 2012-07-18 19:29:19

回答

8

我是工作在今天这个问题我自己,这就是我想出了:在你的榜样

/** 
* Find the next element matching a certain selector. Differs from next() in 
* that it searches outside the current element's parent. 
* 
* @param selector The selector to search for 
* @param steps (optional) The number of steps to search, the default is 1 
* @param scope (optional) The scope to search in, the default is document wide 
*/ 
$.fn.findNext = function(selector, steps, scope) 
{ 
    // Steps given? Then parse to int 
    if (steps) 
    { 
     steps = Math.floor(steps); 
    } 
    else if (steps === 0) 
    { 
     // Stupid case :) 
     return this; 
    } 
    else 
    { 
     // Else, try the easy way 
     var next = this.next(selector); 
     if (next.length) 
      return next; 
     // Easy way failed, try the hard way :) 
     steps = 1; 
    } 

    // Set scope to document or user-defined 
    scope = (scope) ? $(scope) : $(document); 

    // Find kids that match selector: used as exclusion filter 
    var kids = this.find(selector); 

    // Find in parent(s) 
    hay = $(this); 
    while(hay[0] != scope[0]) 
    { 
     // Move up one level 
     hay = hay.parent();  
     // Select all kids of parent 
     // - excluding kids of current element (next != inside), 
     // - add current element (will be added in document order) 
     var rs = hay.find(selector).not(kids).add($(this)); 
     // Move the desired number of steps 
     var id = rs.index(this) + steps; 
     // Result found? then return 
     if (id > -1 && id < rs.length) 
      return $(rs[id]); 
    } 
    // Return empty result 
    return $([]); 
} 

所以

<div><span id="click">hello</span></div> 
<div><p class="find">world></p></div> 

你现在可以找到和使用操作的“p”元素

$('#click').findNext('.find').html('testing 123'); 

我怀疑它会在大型结构上表现良好,但这里是:)

+0

如果要选择的元素是兄弟元素,则不起作用。它声明了全局变量“干草”。 – 2013-10-17 09:16:40

+1

谁会修改此查找上一个? – Relm 2015-03-26 22:54:38

+0

写得很好! – 2017-04-06 16:11:32

0

我认为解决这个问题的唯一方法是对当前元素之后的元素进行递归搜索。 jQuery提供的这个问题没有简单的解决方案。如果您只想在父元素的同级中查找元素(如您的示例中所示),则不需要执行递归搜索,但必须执行多次搜索。

我创建了一个例子(实际上,它不是递归的),它做你想做的(我希望)。它选择当前点击的元素之后的所有元素,并让他们红:

<script type="text/javascript" charset="utf-8"> 
    $(function() { 
     $('#click').click(function() { 
      var parent = $(this); 
      alert(parent); 
      do { 
       $(parent).find('.find').css('background-color','red'); 
       parent = $(parent).parent(); 
      } while(parent !== false); 
     }); 
    }); 
</script> 
0

下面的表达式应该(不包括语法错误!)查找包含p.find元素的父的所有兄弟姐妹,然后找到那些p.find元素和变化他们的颜色变成蓝色。

$(this).parent().nextAll(":has(p.find)").find(".find").css('background-color','blue'); 

当然,如果你的页面结构是这样的:p.find发生在一个完全不同的层次结构(例如祖父母的兄弟姐妹)的,它不会工作。

3

我的解决方案将涉及到调整你的标记,使jQuery更容易。如果这不可能或不是一个有吸引力的答案,请忽略!

我会缠绕你想要做什么是“父”包装......

<div class="find-wrapper"> 
    <div><span id="click">hello</span></div> 
    <div><p class="find">world></p></div> 
</div> 

现在,找到find

$(function() { 
    $('#click').click(function() { 
     var $target = $(this).closest('.find-wrapper').find('.find'); 
     // do something with $target... 
    }); 
}); 

这使您可以灵活地,有什么我建议的包装内有一种标记和层次结构,并且仍然可靠地找到您的目标。

祝你好运!

13

试试这个。它会标记你的元素,创建一组与你的选择器匹配的元素,并收集元素后面的所有元素。

$.fn.findNext = function (selector) { 
    var set = $([]), found = false; 
    $(this).attr("findNext" , "true"); 
    $(selector).each(function(i , element) { 
     element = $(element); 
     if (found == true) set = set.add(element) 
     if (element.attr("findNext") == "true") found = true; 
    }) 
    $(this).removeAttr("findNext") 
    return set 
} 

EDIT

简单得多的解决方案使用jquerys索引方法。你需要调用该方法的元素是可选择由相同的选择,虽然

$.fn.findNext = function(selector){ 
    var set = $(selector); 
    return set.eq(set.index(this,) + 1) 
} 

从这一障碍释放功能,我们可以忧色浏览器拥有compareDocumentposition

$.fn.findNext = function (selector) { 
    // if the stack is empty, return the first found element 
    if (this.length < 1) return $(s).first(); 
    var found, 
     that = this.get(0); 
    $(selector) 
    .each(function() { 
     var pos = that.compareDocumentPosition(this); 
     if (pos === 4 || pos === 12 || pos === 20){ 
     // pos === 2 || 10 || 18 for previous elements 
     found = element; 
     return false; 
     }  
    }) 
    // using pushStack, one can now go back to the previous elements like this 
    // $("#someid").findNext("div").remove().end().attr("id") 
    // will now return "someid" 
    return this.pushStack([ found ]); 
}, 

EDIT 2 使用jQuery的$ .grep这非常容易。这里是新代码

$.fn.findNextAll = function(selector){ 
     var that = this[ 0 ], 
      selection = $(selector).get(); 
     return this.pushStack(
     // if there are no elements in the original selection return everything 
     !that && selection || 
     $.grep(selection, function(n){ 
      return [4,12,20].indexOf(that.compareDocumentPosition(n)) > -1 
     // if you are looking for previous elements it should be [2,10,18] 
     }) 
    ); 
    } 
    $.fn.findNext = function(selector){ 
     return this.pushStack(this.findNextAll(selector).first()); 
    } 

当压缩变量名称时,这成为仅仅两个班轮。

编辑3 使用按位运算,这个函数可能会更快?

$.fn.findNextAll = function(selector){ 
    var that = this[ 0 ], 
    selection = $(selector).get(); 
    return this.pushStack(
    !that && selection || $.grep(selection, function(n){ 
     return that.compareDocumentPosition(n) & (1<<2); 
     // if you are looking for previous elements it should be & (1<<1); 
    }) 
); 
} 
$.fn.findNext = function(selector){ 
    return this.pushStack(this.findNextAll(selector).first()); 
} 
+0

我没有想到的一个缺点就是你调用findNext的元素需要用同一个选择器来选择,否则它只会遍历所有内容而不会找到你标记的元素。 – lordvlad 2012-12-02 20:23:12

+0

谢谢,我已经看遍了,没有人像你一样简洁地回答了非兄弟姐妹的情况。 – 2013-01-20 03:35:19

+0

谢谢你的工作。对于非常大型的表格文档,Edit 2加快了我想要做的量级! – David 2013-05-10 20:37:10

相关问题