2010-06-22 38 views
5

Với đánh dấu mẫu này (giả sử một số ngẫu nhiên của các yếu tố giữa .outer.inner:jQuery lọc chọn để loại bỏ các yếu tố lồng nhau phù hợp với mô hình

<div class="outer"> 
    <div> 
     <div> 
      <div class="inner"></div> 
     </div> 
    </div> 
</div> 

tôi có thể thiết lập jQuery để chọn divs bên ngoài và bên trong như vậy:

$outer = $('.outer'); 
$inner = $outer.find('.inner') 

trình tốt.

Tuy nhiên, chúng ta hãy nói rằng tôi muốn cho phép một tổ không giới hạn của logic này, vì vậy tôi có thi s:

<div class="outer"> div a 
    <div class="inner"> div b 
     <div class="outer"> div c 
      <div class="inner"> div d </div> 
     </div> 
    </div> 
</div> 

Trong trường hợp đó, khi chọn div a qua .outer Tôi muốn khớp nó với chỉ div b. Trong các từ khác, tôi muốn loại trừ tổ tiên của tổ tiên lồng nhau .outer.

Tôi muốn có các phần vỏ bên ngoài và bên trong được chứa trong mức lồng của chúng.

Tôi hy vọng .filter() có thể xóa nó đi, nhưng không thể nghĩ ra một bộ chọn sẽ hoạt động phổ biến cho các mẫu lồng nhau không giới hạn. Có thể sử dụng bộ lọc không? Hoặc thậm chí có thể là một mẫu chọn trực tiếp?

UPDATE:

Tôi nghĩ rằng một cái gì đó như thế này có thể làm việc, nhưng không chắc chắn như thế nào người ta có thể (hoặc nếu nó cho phép) tham chiếu 'này' trong một selector:

$outer = $('.outer'); 
$inner = $outer.not('this .outer').find('.inner') 

UPDATE 2:

Tôi nên đề cập đến điều này một cách trực tiếp: .inner sẽ luôn là hậu duệ của .outer nhưng không nhất thiết là một đứa trẻ ngay lập tức.

CẬP NHẬT 3:

Đây là một số mẫu thử HTML có thể được sử dụng. Trong mỗi trường hợp, tôi muốn có thể chọn .outer và ghép cặp .inner của nó chứa giữa chính nó và bên ngoài lồng nhau. Để rõ ràng, tôi đã thêm tên cho mỗi div (cặp bên ngoài-x với nội-x)

//sample 1 
<div class="outer"> outer-a 
    <div> 
     <div class="inner"> inner-a 
      <div class="outer"> inner-b 
       <div class="inner"> inner-b </div> 
      </div> 
     </div> 
    </div> 
    <div> 
     <div class="inner"> inner-a </div> 
    </div> 
</div> 

//sample 2 
<div class="outer"> outer-a 
     <div class="inner"> inner-a 
      <div class="outer"> inner-b 
       <div> 
        <div class="inner"> inner-b </div> 
       </div> 
      </div> 
     </div> 
</div> 

//sample 3 
<div class="outer"> outer-a 
     <div class="inner"> inner-a 
      <div class="outer"> inner-b 
       <div class="inner"> inner-b 
        <div class="outer"> outer-c 
         <div class="inner"> inner-c</div> 
        </div> 
       </div> 
      </div> 
     </div> 
</div> 

//bonus sample (we're trying to avoid this) 
<div class="outer"> outer-a 
     <div class="inner outer"> inner-a outer-b 
      <div class="inner"> inner-b </div> 
     </div> 
</div> 

CẬP NHẬT 4

Tôi nghĩ rằng tôi đã kết thúc đi xuống một con đường tương tự như gnarf. Tôi đã kết thúc với điều này:

var $outer = $('.outer'); 
var $inner = $outer.find('.inner').filter(function(){ 
    $(this).each(function(){ 
     return $(this).closest('.outer') == $outer; 
    });                 
}); 

Tôi có đi đúng hướng không? Nó không hoạt động vì vậy tôi cho rằng tôi vẫn còn một chút lỗi logic.

+0

này không có ý nghĩa - ngay cả khi bạn kết hợp tổ đầu tiên và duy loại bỏ điều đó - con cái của nó sẽ bị loại bỏ anyway – Matt

Trả lời

11

Dưới đây là một tùy chọn. Giả sử bạn có .outero, điều này sẽ chọn tất cả inner s dưới nó:

o.find('.inner').not(o.find('.outer .inner')) 

Nó sẽ làm việc giống hệt với câu trả lời gnarf, nhưng một chút đơn giản hơn.

Đầu tiên, nó tìm thấy tất cả inner s theo số outer này.
Tiếp theo, loại bỏ tất cả inners đó là hậu duệ của khác outers

dụ làm việc tương tác: http://jsfiddle.net/Zb9gF/

hiệu suất Selector có vẻ là tốt hơn nhiều sử dụng phương pháp này như trái ngược với .filter() cũng như: http://jsperf.com/selector-test-find-not

+0

Brilliant! Như thường lệ, câu trả lời đơn giản hơn con đường mà tôi kết thúc. Tôi đã đấu tranh với cú pháp cần thiết để kết hợp một đối tượng được lưu trữ với một bộ chọn css và logic find() không xảy ra với tôi. Cảm ơn! –

+0

Cảm ơn! Nhân tiện, câu hỏi rất thú vị và đầy thử thách, phải mất rất nhiều công sức để có được dòng đơn giản này ... – Kobi

+0

Tối ưu hóa tốt đẹp, ước gì tôi nghĩ về nó trước :) - Chỉ là chơi với tính hữu ích của ['.not()'] (http://api.jquery.com/not) ngày hôm qua cho [câu trả lời này] (http://stackoverflow.com/questions/3089045). – gnarf

1
$('.outer').children('.inner'); 

Điều đó sẽ chọn bất kỳ inner nào nằm ngay bên dưới outer. Tôi không thực sự rõ ràng về div bạn đang cố gắng chọn. Nó là a, b, c, hay d? Có một cái gì đó gọi là bên ngoài lồng nhau trong cái gì đó gọi là bên trong không làm cho một toàn bộ rất nhiều ý nghĩa. Có lẽ nếu bạn có thể cung cấp một ví dụ cụ thể hơn?

+0

+1 - Đây có lẽ là cược tốt nhất giả định rằng '.inner' luôn là con trực tiếp của' .outer' và không lồng nhau lên một mức khác ... – gnarf

+1

xin lỗi vì không làm rõ điều đó. Đó là, thực sự, một biến. Nội tâm sẽ là hậu duệ, nhưng không nhất thiết là một đứa trẻ ngay lập tức. –

0

Bạn có thể sử dụng một số css kỳ diệu:

$('.outer>.inner') 

shold cung cấp cho bạn chỉ cấp độ đầu tiên của .inner yếu tố. :)

+1

Bộ chọn đó sẽ khớp với cả hai '.inner''s – gnarf

2

Nếu .inner luôn trẻ em trực tiếp của .outer s - children() có lẽ là lựa chọn tốt nhất của bạn (câu trả lời jasongetsdown của)

Nếu bạn cần cái gì đó trông thậm chí còn sâu hơn, bạn có thể làm một cái gì đó như thế này:

var $outer = $('.outer').first(); // grab the first .outer 
$outer.find('.inner').filter(function() { 
    // only if the closest parent .outer is the same as the .outer we are looking in 
    return $(this).closest('.outer').get(0) == $outer.get(0); 
}).css('border','1px solid #000'); 

jsfiddle demo

+0

@gnarf ... Tôi nghĩ nó gần giống với những gì tôi đang nghĩ. Tôi cũng đã thêm bản cập nhật cho bài đăng của mình sử dụng chức năng lọc. Tôi không làm việc như vậy sẽ cố gắng cú pháp của bạn tiếp theo! –

+0

Nhân tiện, cách đây 1 giờ, tốt nhất. Tôi khá chắc chắn bạn là chính xác, điều này có vẻ như logic đúng. – Kobi

1

Nếu giả định một cách chính xác bạn muốn chọn tất cả .inner đó là dưới một .outer, ngoại trừ nếu có một Inbetween .outer, có lẽ sau đây sẽ làm việc (chưa được kiểm tra):

$('.outer:not(.inner):has(:not(.outer) .inner:not(.outer), > .inner:not(.outer))'); 

cập nhật sau khi thử nghiệm trên OP dụ HTML tại http://jsfiddle.net/cEwBT/1/

+0

Giả định của bạn là chính xác. Tuy nhiên, mẫu đó sẽ không hoạt động.Tôi lần đầu tiên bộ nhớ cache 'bên ngoài' và sau đó muốn tìm tất cả các bên trong đó không phải là một đứa trẻ của một bên ngoài lồng nhau. Việc nắm bắt là bên ngoài được lưu trữ của tôi * là * a .outer vì vậy sẽ không bao gồm chính nó. –

+0

Tôi đã cập nhật nó ngay bây giờ sau khi một số kiểm tra trên tại jsfiddle – azatoth

0

tôi tự hỏi tại sao không chọn .inner lúc đầu, và sau đó nhận được closest.outer?

 
$inner = $('.inner'); 
$outer = $inner.closest('.outer'); 

trong trường hợp một số khối bên trong có thể không nằm trong khối ngoài ở tất cả, sử dụng dòng đầu tiên này để thay thế

$inner = $('.outer .inner');

+0

Câu hỏi ở đây là theo một hướng khác. Đưa ra * một * 'bên ngoài', làm thế nào để bạn tìm thấy các div bên trong của nó? – Kobi

+0

xem. câu hỏi của tôi là tại sao không đi theo hướng khác. có .outer, câu trả lời của Kobi hoàn hảo. nhưng nếu bạn chỉ cần có được tất cả người chơi cho tất cả người chơi - có thể bạn có thể bắt đầu từ đầu để nói – vittore

Các vấn đề liên quan