Comment obtenir le parent de niveau n-ième d'un élément dans jQuery?

151

Lorsque je veux obtenir, par exemple, le parent de 3e niveau de l'élément que je dois écrire. $('#element').parent().parent().parent()Existe-t-il une méthode plus optimale pour cela?

Artur Keyan
la source
2
Je veux donner uniquement le nombre (niveau) et obtenir l'élément, car mon élément peut ne pas avoir d'identifiant ou de nom calss
Artur Keyan
1
Si vous prévoyez de réutiliser cette fonctionnalité, la solution optimale est de créer un plugin jQuery.
zzzzBov
3
Voir jsperf.com/jquery-get-3rd-level-parent pour des comparaisons de performances
a'r
1
Un autre bon outil est la fonction ".closest ()". $ ('li.item'). plus proche ('div') vous donnera le DIV qui est l'ancêtre le plus proche du li.item. Bon pour quand vous ne savez pas combien de niveaux se trouve l'élément, mais que vous connaissez son nom de variable / classe / autre chose.
Graham

Réponses:

267

Puisque parents () retourne les éléments ancêtres classés des plus proches des éléments externes, vous pouvez les enchaîner dans eq () :

$('#element').parents().eq(0);  // "Father".
$('#element').parents().eq(2);  // "Great-grandfather".
Frédéric Hamidi
la source
puis-je utiliser ce $ ('# element'). parents () [2]? or it must by with eq (2)
Artur Keyan
1
cela ne fonctionnera pas pour les sélections d'éléments multiples, un moyen plus sûr serait:$('.element').first().parents().eq(num);
zzzzBov
6
@Arthur, using [2]retournera l'élément DOM sous-jacent, using eq(2)retournera un objet jQuery.
Frédéric Hamidi
1
@zzzzBov, très vrai, mais il n'y aura qu'un seul élément sélectionné dans le cas de l'interrogateur (car il correspond à un identifiant).
Frédéric Hamidi
Si vous effectuez une recherche sur un identifiant "#element", il ne renverra qu'un seul élément car c'est ainsi que les recherches d'identifiant fonctionnent, elles renvoient le premier élément avec cet identifiant dans le dom. Si d'un autre côté vous avez fait "div # element" ou un sélecteur de classe vous auriez raison.
Henry
29

Dépend de vos besoins, si vous savez quel parent vous recherchez, vous pouvez utiliser le sélecteur .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());

Exemple utilisant l'index:

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

alert($(topTwo ).html());
Henri
la source
J'ai maintenant de cette façon, mais je veux donner le niveau
Artur Keyan
3
Lisez plus bas la réponse et tout sera révélé! (Je vous ai donné des exemples de niveau)
Henry
Cela fonctionne bien pour tous les autres types de sélecteurs. Par exemple, si vous voulez la liste de tous les parents et parents de parents avec une certaine classe, cela les retournera.
darksky
8

Vous pouvez donner au parent cible un identifiant ou une classe (par exemple myParent) et la référence est avec $('#element').parents(".myParent")

Joseph Marikle
la source
Je veux donner uniquement un nombre et obtenir un élément, car mon élément peut ne pas avoir d'identifiant ou de nom calss
Artur Keyan
6

Un moyen plus rapide consiste à utiliser javascript directement, par exemple.

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

Cela fonctionne beaucoup plus rapidement sur mon navigateur que le chaînage des .parent()appels jQuery .

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

a'r
la source
Par «nettement plus rapide», nous regardons environ un ordre de grandeur en termes de différence de vitesse (exécutant jQuery 1.10.1 sur Chrome 51). Cela vaut vraiment la peine d'être mis en œuvre si vous recherchez la vitesse.
Iain Fraser
5

Je n'ai trouvé aucune réponse en utilisant closest() et je pense que c'est la réponse la plus simple lorsque vous ne savez pas combien de niveaux il y a l'élément requis, alors postez une réponse:
vous pouvez utiliser la closest()fonction combinée avec des sélecteurs pour obtenir le premier élément qui correspond lors du déplacement vers le haut depuis l'élément:

('#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'
Danois
la source
3

C'est simple. Juste utiliser

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

où 0 est le niveau du parent (0 est le parent, 1 est le parent du parent, etc.)

zatatatata
la source
3

Ajoutez simplement un :eq()sélecteur comme celui-ci:

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

Vous spécifiez simplement index quel parent: 0 pour le parent immédiat, 1 pour le grand-parent, ...

MBO
la source
C'est le moyen le plus rapide de faire le travail. Voici le benchmark pour le prouver: jsperf.com/jquery-get-element-s-nth-parent
java-man-script
3

Si vous prévoyez de réutiliser cette fonctionnalité, la solution optimale est de créer un plugin jQuery:

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

Bien sûr, vous voudrez peut-être l'étendre pour permettre un sélecteur facultatif et d'autres choses similaires.

Une note: cela utilise un 0index basé pour les parents, c'est donc nthParent(0)la même chose que l'appel parent(). Si vous préférez une 1indexation basée, utilisezn-- > 0

zzzzBov
la source
Je pense que vous trouverez cette partie plus rapidement: var p = 1 + n; while (p--) { $p = $p.parent(); }et si vous voulez passer à 1 basé, Javascript étant "faux", vous pouvez utiliser: while (n--) { $p = $p.parent();} enregistrer une vérification conditionnelle
Mark Schultheiss
@Mark Schultheiss, ce n'est pas seulement une question de vitesse, c'est aussi une question de fiabilité. Qu'arrive-t-il à votre fonction si quelqu'un appelle par ignorance nthParent(-2)? Votre exemple est cassé.
zzzzBov
OU juste revenir(function($) { $.fn.nthParent = function(n) { return $(this).parents().eq(n); }; }(jQuery));
Mark Schultheiss
@Mark Schultheiss, encore une fois, la fiabilité. Ma fonction renvoie le nthParent pour chaque élément de la sélection, votre fonction renvoie le nième élément de la liste parentsqui sera incorrect pour les sélections avec plus d'un élément.
zzzzBov
true en ce qui concerne le -2, et comme dans votre exemple, utiliser à la var p = n >? (1 + n):1; place renverrait le premier parent dans ce cas plutôt que "rien" - ou là où il rompt la boucle dans mon exemple. SO, cela devrait probablement être: (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 vous ne voulez rien retourner.
Mark Schultheiss
3

Si vous avez un parent div commun, vous pouvez utiliser le lien parentsUntil ()

par exemple: $('#element').parentsUntil('.commonClass')

L'avantage est que vous n'avez pas besoin de vous souvenir du nombre de générations entre cet élément et le parent commun (défini par commonclass).

ashishyadaveee11
la source
1

vous pouvez aussi utiliser :

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

ex: $(this).ancestors().eq(2)-> le parent du parent de this.

Mouna Cheikhna
la source
0

Vous pouvez utiliser quelque chose comme ceci:

(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
la source
1
Pas le downvoter, mais c'est probablement la pire solution (c'est-à-dire inefficace) ici.
zatatatata
0

l'utilisation de l'eq semble saisir le DOM dynamique tandis que l'utilisation de .parent (). parent () semble saisir le DOM initialement chargé (si cela est même possible).

Je les utilise tous les deux sur un élément auquel des classes sont appliquées sur onmouseover. eq montre les classes alors que .parent (). parent () ne le fait pas.


la source
0

Lorsque parents () renvoie une liste, cela fonctionne également

$('#element').parents()[3];
DidThis
la source