¿Cómo obtengo el enésimo nivel primario de un elemento en jQuery?

151

Cuando quiero obtener, por ejemplo, el padre del tercer nivel del elemento que debo escribir $('#element').parent().parent().parent()¿Hay un método más óptimo para esto?

Artur Keyan
fuente
2
Quiero dar solo un número (Nivel) y obtener un elemento, porque mi elemento puede no tener ninguna identificación o nombre de
Calss
1
Si planea reutilizar esta funcionalidad, la solución óptima es crear un complemento jQuery.
zzzzBov
3
Visite jsperf.com/jquery-get-3rd-level-parent para ver algunas comparaciones de rendimiento
2011
1
Otra buena herramienta es la función ".closest ()". $ ('li.item') .arest ('div') le dará el DIV que es el ancestro más cercano del li.item. Bueno para cuando no sabes cuántos niveles tiene el elemento, pero sí sabes su nombre de etiqueta / clase / algo más.
Graham

Respuestas:

267

Como los padres () devuelven los elementos ancestrales ordenados desde los más cercanos a los externos, puede encadenarlos en eq () :

$('#element').parents().eq(0);  // "Father".
$('#element').parents().eq(2);  // "Great-grandfather".
Frédéric Hamidi
fuente
¿Puedo usar este $ ('# elemento'). parents () [2]? o debe hacerlo con la ecuación (2)
Artur Keyan
1
esto no funcionará para selecciones de elementos múltiples, una forma más segura sería:$('.element').first().parents().eq(num);
zzzzBov
66
@Arthur, utilizando [2]devolverá el elemento DOM subyacente, utilizando eq(2)devolverá un objeto jQuery.
Frédéric Hamidi
1
@zzzzBov, muy cierto, pero solo habrá un elemento seleccionado en el caso del interrogador (porque coincide con una identificación).
Frédéric Hamidi
Si realiza una búsqueda en un ID "#elemento", solo devolvería un único elemento, ya que así es como funcionan las búsquedas de ID, devuelven el primer elemento con esa ID en el dom. Si, por otro lado, hiciste "elemento div #" o un selector de clase, estarías en lo cierto.
Henry
29

Depende de tus necesidades, si sabes qué padre estás buscando, puedes usar el selector .parents ().

EG: 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());

Ejemplo usando el índice:

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

alert($(topTwo ).html());
Enrique
fuente
Ahora de esta manera, pero quiero dar nivel
Artur Keyan
3
¡Lea más abajo la respuesta y todo será revelado! (Te he dado ejemplos de nivel)
Henry
Esto funciona muy bien para todos los otros tipos de selectores. Por ejemplo, si desea la lista de todos los padres y padres de padres con una clase determinada, esto los devolverá.
darksky
8

Puede darle al padre objetivo una identificación o clase (por ejemplo, myParent) y la referencia es con $('#element').parents(".myParent")

Joseph Marikle
fuente
Quiero dar sólo el número y obtener elemento, porque mi elemento puede no tener ninguna identificación o nombre calss
Artur Keyan
6

Una forma más rápida es usar javascript directamente, por ejemplo.

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

Esto funciona significativamente más rápido en mi navegador que encadenar .parent()llamadas jQuery .

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

Arkansas
fuente
Por "significativamente más rápido", estamos viendo un orden de magnitud en términos de diferencia de velocidad (ejecutando jQuery 1.10.1 en Chrome 51). Definitivamente vale la pena implementarlo si está ajustando la velocidad.
Iain Fraser
5

No encontré ninguna respuesta usando closest() y creo que es la respuesta más simple cuando no sabes cuántos niveles tiene el elemento requerido, así que publica una respuesta:
puedes usar la closest()función combinada con selectores para obtener el primer elemento que coincida al atravesar hacia arriba desde el 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'
danés
fuente
3

Es sencillo. Solo usa

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

donde 0 es el nivel primario (0 es primario, 1 es primario, etc.)

zatatatata
fuente
3

Simplemente agregue un :eq()selector como este:

$("#element").parents(":eq(2)")

Simplemente especifique el índice qué padre: 0 para el padre inmediato, 1 para el abuelo, ...

MBO
fuente
Esta es la forma más rápida de hacer el trabajo. Aquí está el punto de referencia para demostrarlo: jsperf.com/jquery-get-element-s-nth-parent
java-man-script
3

Si planea reutilizar esta funcionalidad, la solución óptima es hacer un complemento jQuery:

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

Por supuesto, es posible que desee extenderlo para permitir un selector opcional y otras cosas similares.

Una nota: esto usa un 0índice basado para padres, por lo que nthParent(0)es lo mismo que llamar parent(). Si prefiere tener 1una indexación basada, usen-- > 0

zzzzBov
fuente
Creo que encontrará esta parte más rápido: var p = 1 + n; while (p--) { $p = $p.parent(); }y SI desea cambiar a 1 basado, Javascript es "falsey" que puede usar: while (n--) { $p = $p.parent();} guardar una verificación condicional
Mark Schultheiss
@ Mark Schultheiss, no se trata solo de velocidad, sino también de confiabilidad. ¿Qué le sucede a su función si alguien ignorante llama nthParent(-2)? Tu ejemplo está roto.
zzzzBov
O simplemente regrese(function($) { $.fn.nthParent = function(n) { return $(this).parents().eq(n); }; }(jQuery));
Mark Schultheiss
@ Mark Schultheiss, nuevamente, confiabilidad. Mi función devuelve el nthParent para cada elemento de la selección, su función devuelve el enésimo elemento en la lista del parentscual será incorrecto para las selecciones con más de un elemento.
zzzzBov
true con respecto a -2, y como en su ejemplo, usar en su var p = n >? (1 + n):1; lugar devolvería el primer padre en ese caso en lugar de "nada", o donde se rompe el ciclo en mi ejemplo. Entonces, probablemente debería ser: (function($) { $.fn.nthParent = function(n) { var $p = $(this); if (!(n > -0)) { return $() }; var p = 1 + n; while (p--) { $p = $p.parent(); } return $p; }; }(jQuery)); si no desea devolver nada.
Mark Schultheiss
3

Si tiene un div padre común, puede usar parentsUntil () enlace

p.ej: $('#element').parentsUntil('.commonClass')

La ventaja es que no necesita recordar cuántas generaciones hay entre este elemento y el padre común (definido por commonclass).

ashishyadaveee11
fuente
1

también puedes usar :

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

ex: $(this).ancestors().eq(2)-> el padre del padre de this.

Mouna Cheikhna
fuente
0

Podrías usar algo como esto:

(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/

Alex Turpin
fuente
1
No es el votante negativo, pero esta es probablemente la peor solución (es decir, ineficiente) aquí.
zatatatata
0

el uso de eq parece capturar el DOM dinámico mientras que el uso de .parent (). parent () parece capturar el DOM que se cargó inicialmente (si eso es posible).

Los uso a ambos en un elemento que tiene clases aplicadas en onmouseover. eq muestra las clases mientras que .parent (). parent () no.


fuente
0

Como los padres () devuelve una lista, esto también funciona

$('#element').parents()[3];
Hice esto
fuente