2011-01-17 18 views
16

Questo sembra un qualcosa che potrebbe essere "incorporato" in jQuery, ma penso che valga la pena chiedere ancora.Iterating Through N Level Children

Ho un problema in cui questo può essere risolto facilmente iterando attraverso tutti i figli di un elemento. Ho scoperto di recente che devo rendere conto dei casi in cui avrei bisogno di fare un livello o due più profondo rispetto al "1 livello" (basta chiamare .children() una volta) che sto facendo attualmente.

jQuery.each(divToLookAt.children(), function(index, element) 
    { 
     //do stuff 
    } 
    ); 

Questo è ciò che sto facendo attualmente. Per approfondire un secondo livello, eseguo un altro ciclo dopo aver eseguito il codice roba per ciascun elemento.

jQuery.each(divToLookAt.children(), function(index, element) 
{ 
    //do stuff 
    jQuery.each(jQuery(element).children(), function(indexLevelTwo, elementLevelTwo) 
    { 
     //do stuff 
    } 
    ); 
} 
); 

Se voglio approfondire un altro livello, devo rifarlo tutto da capo.

Questo non è chiaramente buono. Mi piacerebbe dichiarare una variabile di "livello" e quindi averne tutto a cuore. Qualcuno ha qualche idea per una soluzione jQueryish pulita ed efficiente?

Grazie!

+0

Che cosa cerchi negli elemtns? – amosrivera

+0

+1 perché sono sorpreso che jquery non abbia un selettore nativo per questo, e perché mi manca un lol manuale di dom dom. – goat

risposta

6

Questa è una domanda stupenda a causa della cattura profonda dei livelli. Check out the fiddle.

Convertito in un plug-in.

Attiva

$('#div').goDeep(3, function(deep){ // $.fn.goDeep(levels, callback) 
    // do stuff on `this` 
}); 

Plugin

$.fn.goDeep = function(levels, func){ 
    var iterateChildren = function(current, levelsDeep){ 
     func.call(current, levelsDeep); 

     if(levelsDeep > 0) 
      $.each(current.children(), function(index, element){ 
       iterateChildren($(element), levelsDeep-1); 
      }); 
    }; 

    return this.each(function(){ 
     iterateChildren($(this), levels); 
    }); 
}; 
+0

Fai in modo che filtri i contenuti invece di essere un visitatore con capacità limitate. Più jquery'ish/flessibile imo. – goat

+0

@chris - Non riesco a vedere come ottenere tutti gli elementi con un contenitore, quindi il filtro basato su un selettore dinamico potrebbe essere più flessibile/efficiente –

0
var lvlFunc = function(elmt, depth) { 
    if(depth > 0) { 
     elmt.children().each(function(i, e){ 
      // do stuff on the way down 
      lvlFunc($(this), --depth); 
      // do stuff on the way out 
     }); 
     // do stuff 
    } 
}; 

lvlFunc(divToLookAt, 3); 

Assicurarsi che mettete il vostro codice di "fare le cose" nella giusta posizione, se le questioni che ordinano la "roba" viene eseguita in.

+1

'--depth' non funzionerà fyi –

2

Questa domanda è impressionante :-)

Se sai che il tuo DOM non è troppo gigantesca, si può solo trovare tutti i discendenti e filtrare quelli che non dovessero rientrare:

var $parent = $('#parent'); 
var $childrenWithinRange = $parent.find('*').filter(function() { 
    return $(this).parents('#parent').length < yourMaxDepth; 
}); 

Dopo di che, l'istanza di jQuery "$ childrenWithinRange" sarebbe tutti i nodi figlio di quel genitore <div> che si trovano entro una profondità massima. Se volessi esattamente quella profondità, cambieresti "<" in "===". Potrei essere fuori da qualche parte.

+0

+1 Questo è come lo farei, a meno che non sentissi che filtrerei troppe cose per discendenti molto profondi. – goat

1

Si dovrebbe essere in grado di fare proprio con il all-selector(docs), il child-selector(docs) e multiple-selector(docs) come questo:

Esempio:http://jsfiddle.net/mDu9q/1/

$('#start > *,#start > * > *,#start > * > * > *').doSomething(); 

...o se si solo voluto indirizzare i bambini 3 livelli di profondità, si potrebbe fare questo:

Esempio:http://jsfiddle.net/mDu9q/2/

$('#start > * > * > *').doSomething(); 

Entrambi questi selettori sono validi per querySelectorAll, il che significa grande spinta di prestazioni nei browser supportati.