133 votes

Similaire à jQuery .closest () mais traversant des descendants?

Est-il une fonction similaire jQuery .closest() mais pour parcourir les descendants et retour seulement plus proches?

Je sais qu'il y a .find() de la fonction, mais il renvoie toutes les correspondances possibles, pas plus proche.

Edit:

Voici la définition de la plus proche (au moins pour moi):

En premier lieu, tous les enfants sont parcourus, puis de chaque individu pour enfants sont parcourus.

Dans l'exemple donné ci-dessous id='2' est plus proche .closest des descendants d' id="find-my-closest-descendant"

<div id="find-my-closest-descendant">
    <div>
        <div class="closest" Id='1'></div>
    </div>
    <div class="closest" Id='2'></div>
</div>

Veuillez voir JSfiddle lien.

130voto

James Points 56229

Si par descendant "le plus proche" vous entendez le premier enfant, alors vous pouvez faire:

 $('#foo').find(':first');
 

Ou:

 $('#foo').children().first();
 

Ou, pour rechercher la première occurrence d'un élément spécifique, vous pouvez faire:

 $('#foo').find('.whatever').first();
 

Ou:

 $('#foo').find('.whatever:first');
 

En réalité, il nous faut une définition précise de ce que signifie "descendant le plus proche".

Par exemple

 <div id="foo">
    <p>
        <span></span>
    </p>
    <span></span>
</div>
 

Quels <span> %% $('#foo').closestDescendent('span') reviendraient?

44voto

Rob W Points 125904

Selon votre définition de closest , j'ai écrit le plugin suivant:

 (function($) {
    $.fn.closest_descendent = function(filter) {
        var $found = $(),
            $currentSet = this; // Current place
        while ($currentSet.length) {
            $found = $currentSet.filter(filter);
            if ($found.length) break;  // At least one match: break loop
            // Get all children of the current set
            $currentSet = $currentSet.children();
        }
        return $found.first(); // Return first match of the collection
    }    
})(jQuery);
 

21voto

FishBasketGordo Points 14957

Vous pouvez utiliser find avec le sélecteur :first :

 $('#parent').find('p:first');
 

La ligne ci-dessus trouvera le premier élément <p> dans les descendants de #parent .

0voto

Pointy Points 172438

Je pense que vous devez d'abord définir ce que "le plus proche". Si vous voulez dire le descendant du nœud correspondant à vos critères est la plus courte distance dans les conditions de l'autorité parentale, des liens, puis à l'aide de "premier" ou ".eq(0)" ne fonctionnera pas nécessairement:

<div id='start'>
  <div>
    <div>
      <span class='target'></span>
    </div>
  </div>
  <div>
    <span class='target'></span>
  </div>
</div>

Dans cet exemple, le deuxième ".cible" <span> élément est "proche" de la "start" <div>, parce que c'est seulement une parentale hop loin. Si c'est ce que tu veux dire par "plus proche", vous auriez besoin de trouver la distance minimum dans une fonction de filtre. La liste des résultats à partir d'un sélecteur jQuery est toujours en ordre DOM.

Peut-être:

$.fn.closestDescendant = function(sel) {
  var rv = $();
  this.each(function() {
    var base = this, $base = $(base), $found = $base.find(sel);
    var dist = null, closest = null;
    $found.each(function() {
      var $parents = $(this).parents();
      for (var i = 0; i < $parents.length; ++i)
        if ($parents.get(i) === base) break;
      if (dist === null || i < dist) {
        dist = i;
        closest = this;
      }
    });
    rv.add(closest);
  });
  return rv;
};

C'est en quelque sorte d'un hack plugin raison de la façon dont il construit l'objet de résultat, mais l'idée est que vous avez à trouver le plus court parental chemin d'accès de tous les éléments que vous trouvez. Ce code partis pris à l'égard des éléments vers la gauche dans l'arborescence DOM en raison de l' < chèque; <= fausserait rightwards.

0voto

Esailija Points 74052

Je l’ai concocté, aucune implémentation pour les sélecteurs de position (ils ont besoin de plus que matchesSelector ):

Démo: http://jsfiddle.net/TL4Bq/3/

 (function ($) {
    var matchesSelector = jQuery.find.matchesSelector;
    $.fn.closestDescendant = function (selector) {
        var queue, open, cur, ret = [];
        this.each(function () {
            queue = [this];
            open = [];
            while (queue.length) {
                cur = queue.shift();
                if (!cur || cur.nodeType !== 1) {
                    continue;
                }
                if (matchesSelector(cur, selector)) {
                    ret.push(cur);
                    return;
                }
                open.unshift.apply(open, $(cur).children().toArray());
                if (!queue.length) {
                    queue.unshift.apply(queue, open);
                    open = [];
                }
            }
        });
        ret = ret.length > 1 ? jQuery.unique(ret) : ret;
        return this.pushStack(ret, "closestDescendant", selector);
    };
})(jQuery);
 

Il y a probablement quelques bugs cependant, je ne l'ai pas beaucoup testé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X