2010-06-22 12 views
5

W tej próbki znaczników (przy założeniu, że dowolną liczbę elementów pomiędzy .outer i .inner:jQuery selektor filtrujący do usuwania elementów zagnieżdżone dopasowanie wzorca

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

można skonfigurować jQuery wybranie zewnętrzne i wewnętrzne div w następujący sposób:

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

działa dobrze.

jednak powiedzmy chcę, aby umożliwić nieograniczoną zagnieżdżenie tej logiki, więc może mam jes 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> 

W tej sytuacji, przy wyborze div via .outer Chcę dopasować go tylko div b. Innymi słowy, chcę wykluczyć przodków z zagnieżdżonego przodka .outer.

Chciałbym mieć parings of outer i inner (s) zawarte w ich poziomie gniazdowania.

Mam nadzieję, że .filter() może go usunąć, ale nie może myśleć o selektorze, który działałby uniwersalnie dla nieograniczonych wzorów zagnieżdżonych. Czy można to zrobić za pomocą filtra? A może nawet bezpośredni wzór selektora?

UPDATE:

Myślę, że coś takiego może działać, ale nie wiem, jak można (lub jeśli jest to dozwolone) odniesienie 'to' w selektor:

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

UPDATE 2:

Powinienem był o tym wspomnieć: .inner zawsze będzie potomkiem .outer, ale niekoniecznie bezpośrednim dzieckiem.

UPDATE 3:

Oto kilka próbek testowych HTML, które mogłyby zostać wykorzystane. W każdym przypadku chciałbym móc wybrać .outer i sparować plik .inner, który zawiera między sobą i zagnieżdżoną zewnętrzną. Dla jasności, to dodaje nazwisk każdej div (zewnętrzna x pary z wewnętrznymi-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> 

UPDATE 4

myślę skończyło się w dół podobną drogą jak Gnarf. Skończyło się to:

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

Czy jestem na dobrej drodze? To nie działa, więc zakładam, że mam jeszcze pewien błąd logiczny.

+0

To nie ma sensu - nawet jeśli pasuje do pierwszego gniazda i tylko usuń to - jego dzieci zostaną usunięte mimo wszystko. – Matt

Odpowiedz

11

Oto kolejna opcja. Załóżmy, że masz .outero, to wybrać wszystkie inner s pod nim:

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

Powinien działać identycznie do odpowiedzi Gnarf, ale nieco prostsze.

Najpierw znajduje wszystkie inner s pod tym outer.
Następnie usuń wszystkie inners że są potomkami innych outers

Interaktywny przykład praca: http://jsfiddle.net/Zb9gF/

wydajność Selector wydaje się być znacznie lepiej przy użyciu tej metody w przeciwieństwie do .filter() także: http://jsperf.com/selector-test-find-not

+0

Brilliant! Jak zwykle, odpowiedź jest prostsza niż droga, którą kończę w dół. Zmagałem się ze składnią potrzebną do połączenia obiektu z pamięci podręcznej z selektorem css i logika find() nie wystąpiła mi. Dzięki! –

+0

Dzięki! Nawiasem mówiąc, pytanie jest bardzo interesujące i wymagające, zajęło dużo pracy, aby dostać się do tej prostej linii ... – Kobi

+0

Dobra optymalizacja, żałuję, że nie pomyślałem o tym pierwszy :) - Był po prostu grać z użytecznością ['.not()'] (http://api.jquery.com/not) dla [tej odpowiedzi] (http://stackoverflow.com/questions/3089045). – gnarf

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

To by wybrać dowolny inner który znajduje się bezpośrednio pod w outer. Nie wiem dokładnie, do jakiego diva chcesz wybrać. Czy to a, b, c, czy d? Posiadanie czegoś o nazwie zewnętrznej zagnieżdżonej w czymś zwanym wewnętrznym nie ma większego sensu. Może gdybyś mógł podać bardziej konkretny przykład?

+0

+1 - Prawdopodobnie jest to najlepszy zakład, zakładając, że '.inner' jest zawsze bezpośrednim potomkiem' .outer' i nie zagnieździło innego poziomu w dół ... – gnarf

+1

Przepraszam, że nie wyjaśnienie tego. To jest rzeczywiście zmienna. Wewnętrzny będzie potomkiem, ale niekoniecznie bezpośrednim dzieckiem. –

0

Można użyć trochę css Magic:

$('.outer>.inner') 

shold daje tylko pierwszy poziom .inner elementów. :)

+1

Ten selektor będzie pasował zarówno do '.inner'ta – gnarf

2

Jeśli .inner zawsze są bezpośrednimi dzieci .outer s - children() jest prawdopodobnie najlepszym (odpowiedź jasongetsdown za)

Jeśli potrzebujesz czegoś, co wygląda jeszcze głębiej, można zrobić coś takiego:

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 ... Myślę, że jest blisko tego, co też myślałem. Dodałem aktualizację do mojego postu, który również wykorzystuje funkcję filtra. Mój nie działa, więc wypróbuje twoją składnię dalej! –

+0

Nawiasem mówiąc, +1 godzinę temu, niezły. Jestem prawie pewien, że masz rację, to wydaje się być właściwą logiką. – Kobi

1

Jeśli zakładamy prawidłowo chcesz wybrać wszystkie .inner który jest pod o .outer, z wyjątkiem jeśli istnieje .outer pomiędzy nimi, być może po zadziała (niesprawdzone):

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

aktualizowane po teście na PO przykład HTML na http://jsfiddle.net/cEwBT/1/

+0

Twoje założenie jest poprawne. Jednak ta próbka nie będzie działać.Najpierw przechowuję pamięć podręczną "zewnętrzną", a następnie chcę znaleźć wszystkie elementy wewnętrzne, które nie są potomkiem zagnieżdżonej strony zewnętrznej. Połów jest taki, że mój buforowany zewnętrzny * jest * a .outer, więc wykluczałby się sam. –

+0

Zaktualizowałem go teraz po kilku testach na jsfiddle – azatoth

0

I Zastanawiam się, dlaczego najpierw nie wybrać .inner, a następnie uzyskać closest.outer?

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

w przypadku niektóre wewnętrzne bloki mogą być nie w blokach zewnętrznych w ogóle używać tego pierwszego wiersza zamiast

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

+0

Pytanie tutaj jest w innym kierunku. Biorąc pod uwagę * jeden * "zewnętrzny", jak znaleźć jego "wewnętrzne" divy? – Kobi

+0

patrz. moje pytanie brzmi: dlaczego nie iść w innym kierunku. po podaniu .outer odpowiedź Kobiego działa idealnie. ale jeśli potrzebujesz po prostu wszystkich rozwiązań dla wszystkich outerów - możesz zacząć od zera, że ​​tak powiem – vittore