2009-12-01 61 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

相關問題