Come posso ottenere il genitore di livello n-esimo di un elemento in jQuery?


151

Quando voglio ottenere, ad esempio, il genitore di 3 ° livello dell'elemento che devo scrivere $('#element').parent().parent().parent()Esiste un metodo più ottimale per questo?


2
Voglio dare solo il numero (Livello) e ottenere l'elemento, perché il mio elemento potrebbe non avere alcun ID o nome calss
Artur Keyan

1
Se hai intenzione di riutilizzare questa funzionalità, la soluzione ottimale è creare un plug-in jQuery.
zzzzBov,

3
Vedi jsperf.com/jquery-get-3rd-level-parent per alcuni confronti delle prestazioni
a'r

1
Un altro buon strumento è la funzione ".closest ()". $ ('li.item'). più vicino ('div') ti darà il DIV che è l'antenato più vicino di li.item. Buono per quando non sai quanti livelli sale l'elemento, ma conosci il suo tagname / classe / qualcos'altro.
Graham,

Risposte:


267

Poiché parent () restituisce gli elementi antenati ordinati dal più vicino a quelli esterni, è possibile collegarlo in eq () :

$('#element').parents().eq(0);  // "Father".
$('#element').parents().eq(2);  // "Great-grandfather".

posso usare questo $ ('# element'). parent () [2]? oppure deve avvenire con eq (2)
Artur Keyan il

1
questo non funzionerà per selezioni di più elementi, un modo più sicuro sarebbe:$('.element').first().parents().eq(num);
zzzzBov

6
@Arthur, usando [2]restituirà l'elemento DOM sottostante, usando eq(2)restituirà un oggetto jQuery.
Frédéric Hamidi,

1
@zzzzBov, molto vero, ma nel caso dell'interrogante sarà selezionato un solo elemento (perché corrisponde a un ID).
Frédéric Hamidi,

Se si esegue una ricerca su un ID "#elemento", si restituisce sempre e solo un singolo elemento poiché è così che funzionano le ricerche ID, restituiscono il primo elemento con quell'ID nel dom. Se invece facessi "div # element" o un selettore di classe avresti ragione.
Henry,

29

Dipende dalle tue esigenze, se sai quale genitore stai cercando puoi usare il selettore .parents ().

Ad esempio: http://jsfiddle.net/HenryGarle/Kyp5g/2/

<div id="One">
    <div id="Two">
        <div id="Three">
            <div id="Four">

            </div>
        </div>
    </div>
</div>


var top = $("#Four").parents("#One");

alert($(top).html());

Esempio usando l'indice:

//First parent - 2 levels up from #Four
// I.e Selects div#One
var topTwo = $("#Four").parents().eq(2);

alert($(topTwo ).html());

Ora in questo modo, ma voglio dare il livello
Artur Keyan il

3
Leggi più in basso la risposta e tutto sarà rivelato! (Ti ho dato degli esempi di livello)
Henry,

Funziona bene con tutti gli altri tipi di selettori. Ad esempio, se si desidera l'elenco di tutti i genitori e i genitori di genitori con una determinata classe, questo li restituirà.
darksky

8

Potresti dare al genitore di destinazione un ID o una classe (ad esempio myParent) e il riferimento è con $('#element').parents(".myParent")


Voglio dare solo il numero e ottenere l'elemento, perché il mio elemento potrebbe non avere alcun ID o nome calss
Artur Keyan

6

Un modo più veloce è usare javascript direttamente, ad es.

var parent = $(innerdiv.get(0).parentNode.parentNode.parentNode);

Questo è molto più veloce sul mio browser rispetto al concatenamento delle .parent()chiamate jQuery .

Vedi: http://jsperf.com/jquery-get-3rd-level-parent


Con "significativamente più veloce", stiamo osservando un ordine di grandezza in termini di differenza di velocità (con jQuery 1.10.1 su Chrome 51). Vale sicuramente la pena implementarlo se stai ottimizzando la velocità.
Iain Fraser,

5

Non ho trovato alcuna risposta utilizzando closest() e penso che sia la risposta più semplice quando non sai quanti livelli sale l'elemento richiesto, quindi pubblicando una risposta:
puoi usare la closest()funzione combinata con i selettori per ottenere il primo elemento che corrisponde quando si attraversa verso l'alto dall'elemento:

('#element').closest('div')    // returns the innermost 'div' in its parents
('#element').closest('.container')    // returns innermost element with 'container' class among parents
('#element').closest('#foo')    // returns the closest parent with id 'foo'

3

È semplice. Basta usare

$(selector).parents().eq(0); 

dove 0 è il livello principale (0 è principale, 1 è il padre principale ecc.)



3

Se hai intenzione di riutilizzare questa funzionalità, la soluzione ottimale è creare un plug-in jQuery:

(function($){
$.fn.nthParent = function(n){
  var $p = $(this);
  while ( n-- >= 0 )
  {
    $p = $p.parent();
  }
  return $p;
};
}(jQuery));

Naturalmente, potresti voler estenderlo per consentire un selettore opzionale e altre cose del genere.

Una nota: utilizza un 0indice basato per i genitori, quindi nthParent(0)equivale a chiamare parent(). Se preferisci avere l' 1indicizzazione basata, usan-- > 0


Penso che troverai questa parte più velocemente: var p = 1 + n; while (p--) { $p = $p.parent(); }e SE vuoi passare a 1 basato, Javascript essendo "falso" puoi usare: while (n--) { $p = $p.parent();} salvare un controllo condizionale
Mark Schultheiss,

@Mark Schultheiss, non si tratta solo di velocità, ma anche di affidabilità. Cosa succede alla tua funzione se qualcuno chiama in modo ignorante nthParent(-2)? Il tuo esempio è rotto.
zzzzBov,

O semplicemente ritorno(function($) { $.fn.nthParent = function(n) { return $(this).parents().eq(n); }; }(jQuery));
Mark Schultheiss,

@Mark Schultheiss, ancora una volta, affidabilità. La mia funzione restituisce l'nthParent per ogni elemento nella selezione, la tua funzione restituisce l'ennesimo elemento nell'elenco di parentscui sarà errato per le selezioni con più di un elemento.
zzzzBov,

vero per quanto riguarda -2, e come nell'esempio che usi var p = n >? (1 + n):1; invece restituirebbe il primo genitore in quel caso anziché "niente" - o dove interrompe il ciclo nel mio esempio. Quindi, probabilmente dovrebbe essere: (function($) { $.fn.nthParent = function(n) { var $p = $(this); if (!(n > -0)) { return $() }; var p = 1 + n; while (p--) { $p = $p.parent(); } return $p; }; }(jQuery)); se non si desidera restituire nulla.
Mark Schultheiss,

3

Se hai un div genitore comune puoi usare il collegamento parentUntil ()

per esempio: $('#element').parentsUntil('.commonClass')

Il vantaggio è che non è necessario ricordare quante generazioni ci sono tra questo elemento e il genitore comune (definito da commonclass).


1

puoi anche usare:

$(this).ancestors().eq(n) 

es: $(this).ancestors().eq(2)-> il genitore del genitore di this.


0

Puoi usare qualcosa del genere:

(function($) {
    $.fn.parentNth = function(n) {
        var el = $(this);
        for(var i = 0; i < n; i++)
            el = el.parent();

        return el;
    };
})(jQuery);

alert($("#foo").parentNth(2).attr("id"));

http://jsfiddle.net/Xeon06/AsNUu/


1
Non il downvoter, ma questa è probabilmente la soluzione peggiore (cioè inefficiente) qui.
Zatatatata,

0

l'utilizzo di eq sembra afferrare il DOM dinamico mentre l'uso di .parent (). parent () sembra afferrare il DOM che è stato inizialmente caricato (se ciò è persino possibile).

Li uso entrambi su un elemento a cui sono state applicate classi su onmouseover. eq mostra le classi mentre .parent (). parent () non lo fa.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.