Dans jQuery, vous pouvez appeler closest pour trouver le parent le plus proche.

Si j'ai un a dans un li dans un ul dans un td dans un table. Je veux savoir si le parent ul est plus proche que le parent table. De toute évidence, dans ce cas, la réponse est évidente.

Si je lance $('a').closest('table').length ou $('a').closest('ul').length, les deux renvoient 1.

Je voudrais savoir quel parent est le plus proche dans le DOM.

Techniquement, s'il y avait une méthode, dans ce cas, $('a').closer('ul', 'table') retournerait le ul car il est plus proche dans le DOM.

<table> <!-- Is this closer -->
    <tr>
        <td>
            <ul> <!-- Or is this closer -->
                <li>
                    <a href="#">A button</a>
                </li>
            </ul>
        </td>
    </tr>
</table>
4
Johnston 7 mars 2016 à 02:40

5 réponses

Meilleure réponse

Vous pouvez lister plusieurs sélecteurs d'éléments pour la fonction closest, il ne trouvera que le plus proche de l'un d'eux:

$('a').closest('table, ul')

Exemple:

$(document).on("click", function( event ) {
  $(event.target).closest("li, b").toggleClass("hilight");
});
.hilight{
  background: rgba(255, 0, 0, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li><b>Click me!</b></li>
  <li>You can also click this line <b>or click me!</b></li>
</ul>
6
Fabian Horlacher 27 avril 2017 à 14:06

Utilisez .parents(). Il renvoie une liste de tous les parents qui sont classés du plus proche au plus éloigné.

La différence entre utiliser ceci et utiliser .closest(selector) est qu'il accepte un objet jQuery au lieu d'une chaîne de sélection, qui doit être codée en dur. Pendant ce temps, les objets jQuery peuvent être des collections et peuvent donc être générés à la volée.

(function($) {
  $.fn.getClosest = function(testElements) {
    var element = $(this);
    var parents = element.parents();
    var indexClosest = Number.MAX_VALUE;
    testElements.each(function() {
      var index = parents.index($(this));
      if (index > -1 && index < indexClosest)
        indexClosest = index;
    });
    return parents.eq(indexClosest);
  };
})(jQuery);

Utilisez la fonction comme ceci:

$("a").getClosest($("table, ul"))

Violon avec cas d'utilisation avancée

3
4castle 7 mars 2016 à 13:22

J'aime la réponse de Fabian; mais pour mesurer réellement la distance, vous pouvez utiliser ceci:

var $parentsUntilTable = $('li').parentsUntil('table');
var $parentsUntilUl = $('li').parentsUntil('ul');
console.log($parentsUntilTable.length < $parentsUntilUl.length
           ? 'table is closer'
           : 'ul is closer');
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
  <tr>
    <td>
      <ul>
        <li>
        </li>
      </ul>
    </td>
  </tr>
</table>
2
Amadan 6 mars 2016 à 23:52

Un élément n'a qu'un seul nœud parent, au-dessus de ceux-ci se trouvent des nœuds ancêtres.

À partir d'ici: https://stackoverflow.com/a/15149590/1876047 - vous pouvez utiliser

$(elem1).offset().top - $(elem2).offset.().top

Étant donné que les deux nœuds sont les ancêtres de l'élément que vous envisagez, le plus éloigné de la racine de l'arborescence DOM est le placard de votre élément.

Donc, si la différence ci-dessus est supérieure à 0, alors elem2 est le plus proche, sinon elem1 est le plus proche.

-1
Community 23 mai 2017 à 12:34

Voici une implémentation simple de la méthode .closer() qui retourne le sélecteur le plus proche de l'élément donné:

$.fn.closer = function(varargs) {
  var $elem = $(this);
  while ($elem.length) {
    for (var i = 0, len = arguments.length; i < len; i++) {
      if ($elem.is(arguments[i])) {
        return arguments[i];
      }
    }
    $elem = $elem.parent();
  }
  return null;
};

Voyez-le en action sur jsFiddle.

1
GregL 6 mars 2016 à 23:53