2012-11-09 15 views
10

Mam zagnieżdżonej struktury tabeli jakjQuery: find() dzieci aż pewien element progu napotkał

<table> 

     <td id="first"> 

      <div class="wrapper"> 
       <input name=1> 
      </div> 

      <input name=2> 

      <table> 

       <td id="second"> 

        <input name=3> 

mam wybór jQuery $("#first"). Chciałbym przemierzyć wszystkie i find() wszystkie dzieci <input>s w tym kontekście <td>, ale nie do zejścia do zagnieżdżonych <table> s.

Więc muszę trick jQuery który

  • Will find() wszystkie dzieci elementy pewnego elementu

  • Will zejście n poziomy w dół w DOM drzewa

  • Ale zatrzyma malejąco jeśli napotkano pewien element (<table>), tak że selektor nie wybiera danych wejściowych zagnieżdżonych tabel (które będą obsługiwane osobno)

  • Nie może być dowolna liczba zagnieżdżonych <table> poziomach, więc rozwiązanie powinno działać bez względu na to, ile rodzic <table> lub dzieci <table> występują w zakresie $ („pierwszy #”) <td> lub inny <td>

Sprawdziłem inne znalezisko jQuery do czasu pytań. Mają odpowiedzi, ale wydaje się, że nie wypełniają ostatnie kryteria

+0

czy uważasz, że struktura tabeli jest w porządku tutaj? – freebird

+1

czy struktura odbywa się za pomocą '

' lub jakiś inny element jest oczywiście bez znaczenia dla pytanie –

+0

Zapytałem, ponieważ twoje tagi wejściowe nie są zbyt dobre powstaje również brak 'tr'. – freebird

Odpowiedz

5

miałem podobny problem w this other question. Skończyło się na tym, że w końcu wymyśliłem własną wtyczkę po tym, jak chodziłem tam iz powrotem, próbując wymyślić selektor znajdowania.

ZASTOSOWANIE: ExclusiveInputs = $('#first').findExclude('input','table');

// Find-like method which masks any descendant 
// branches matching the Mask argument. 
$.fn.findExclude = function(Selector, Mask, result){ 

    // Default result to an empty jQuery object if not provided 
    var result = typeof result !== 'undefined' ? 
       result : 
       new jQuery(); 

    // Iterate through all children, except those match Mask 
    this.children().each(function(){ 

     var thisObject = jQuery(this); 
     if(thisObject.is(Selector)) 
      result.push(this); 

     // Recursively seek children without Mask 
     if(!thisObject.is(Mask)) 
      thisObject.findExclude(Selector, Mask, result); 
    }); 

    return result; 
} 

(skrócona wersja):

$.fn.findExclude = function(selector, mask, result) 
{ 
    var result = typeof result !== 'undefined' ? result : new jQuery(); 
    this.children().each(function(){ 
     var thisObject = jQuery(this); 
     if(thisObject.is(selector)) 
      result.push(this); 
     if(!thisObject.is(mask)) 
      thisObject.findExclude(selector, mask, result); 
    }); 
    return result; 
} 
2

eh, mam lepszy pomysł ..

var badTable = "table.bad"; //the one you want to avoid 
var $goodInputs = $("#first").find('input').filter(function() { 
    return $(this).closest(badTable).length == 0; 
}); 

to może być lub może nie być wystarczająco szybka. to zależy od twojego DOM, o czym nie chcesz rozmawiać;)

jeśli jest powolny, po prostu napisz kod algorytmu ręcznie. Nie ma skrótu selektora.

+0

Jak wskazuje pytanie, nie można zidentyfikować, która tabela jest "zła" z kontekstu, ale musi działać z dowolnym poziomem zagnieżdżenia bez specjalnych znaczników klasy –

3

Aktualizacja: Przyjmijmy jeszcze raz.

Zasadniczo, chcesz dopasować wszystkie elementy, które są <input> potomkowie #first i że nie są dziećmi <td> elementów zagnieżdżonych głęboko więcej niż jeden poziom pod #first.

(Nie jestem pewien co do tej ostatniej części under #first, ale jej implementacja pozwala nam obsługiwać elementy <td> powyżej #first w łańcuchu nadrzędnym.)

Technicznie następujący selektor sam powinien spełniać wymagania:

var inputs = $("#first td:not(#first td td) > input"); 

Jeśli to nie działa w przeglądarce (Trzask powinien być na wysokości zadania myślę, ale złożone selektory jak :not() zawsze są trudne), można powierzyć przetwarzanie metod jQuery:

var inputs = $("#first td").not("#first td td").children("input"); 

Original swer następująco:

Można użyć not() wykluczyć <input> elementy, które mają więcej niż jedno <td> przodka:

var firstLevelCells = $("#first").find("input").not("td td input"); 
+1

Nie rozumiem tego; nie musi to być '$ (" # first "). find (" input "). not (" td td input ")'? – lnrbob

+0

Masz całkowitą rację, straciłem kontrolę nad faktycznym elementem, który pasuje do ciebie po drodze. Odpowiedź odpowiednio zaktualizowana, dzięki za heads-up :) –

1

miałem podobny problem i wciąż kwestionowane coś zrobić bez pętli przedłużacza lub mające dokładna struktura DOM. W moim przypadku miałem już odniesienie do elementu "#first", który, jeśli nie, moglibyśmy uzyskać go na przykład z każdym (nawet jeśli jest to tylko jeden obiekt). Sztuką jest powrót do drzewa z parentsuntil i zatrzymanie się na swoim górnym elemencie, aby zobaczyć, czy istnieje jakiś element pośredni spełniający warunek.

Korzystanie skrótowym zapisie lambda dla funkcji (jak można napisać w maszynopisie) Prowadziłoby to do tego:

$('#first').each((idx, f) => $(f).find('input').filter((idx2, inp) => $(inp).parentsUntil(f, 'table').length == 0) 

może nie być najbardziej efektywny sposób (jak najpierw wybrać wszystko, by następnie rzucić Odległość elementy ponownie montażu w DOM-drzewa, ale jest zwarta i dość generycznych.

Powiązane problemy