web-dev-qa-db-fra.com

jQuery: this: "$ (this) .next (). next ()" fonctionne, mais "$ (this) .next ('. div')" ne fonctionne pas

D'accord, j'essaie d'obtenir cet ensemble d'informations à masquer individuellement.

<img class="arrow" src="images/navigation/arrowright.png">
<H2>More Information</H2>
<div class="box">
    <h2>Bibendum Magna Lorem</h2>
    <p>Cras mattis consectetur purus sit amet fermentum.</p>
</div>

<img class="arrow" src="images/navigation/arrowright.png">
<H2>A Second Group of Information</H2>
<div class="box">
    <h2>Bibendum Magna Lorem</h2>
    <p>Cras mattis consectetur purus sit amet fermentum.</p>
</div>

Cela fonctionne quand je tape ceci:

$(".arrow").click(function() {
    $(this).next().next().slideToggle();
});

mais pas quand je fais ça:

$(".arrow").click(function() {
    $(this).next('.box').slideToggle();
});

Que se passe-t-il qui empêche la deuxième option de fonctionner? J'y suis depuis des jours et je ne peux pas le comprendre! J'apprécie votre contribution!

17
fjaxyu

Le problème

Si vous regardez la documentation pour .next(selector), elle ne "trouve" pas le prochain frère qui correspond au sélecteur. Au contraire, il regarde JUSTE le frère suivant et retourne UNIQUEMENT cet élément s'il correspond au sélecteur qui n'est pas ce que vous voulez.

Voici ce que dit la doc pour .next():

Description: Obtenez le frère immédiatement suivant de chaque élément dans l'ensemble des éléments correspondants. Si un sélecteur est fourni, il ne récupère le frère suivant que s'il correspond à ce sélecteur.

Ainsi, vous pouvez voir que .next(".box") examinera l'élément h2 Qui suit immédiatement votre élément .arrow (C'est le prochain élément frère), puis le comparera à l'élément .box Et comme ils ne correspondent pas, il retournera un objet jQuery vide.


Une solution utilisant .nextAll ()

Si vous voulez que le prochain frère qui corresponde à un sélecteur, vous pouvez utiliser ceci:

$(this).nextAll(".box").eq(0).slideToggle();

Cela trouve tous les frères et sœurs qui suivent qui correspondent au sélecteur, puis extrait uniquement le premier.


Créez votre propre méthode .findNext ()

Je me suis si souvent demandé pourquoi jQuery n'avait pas de méthode pour cela que j'en ai créé une moi-même:

// get the next sibling that matches the selector
// only processes the first item in the passed in jQuery object
// designed to return a jQuery object containing 0 or 1 DOM elements
jQuery.fn.findNext = function(selector) {
    return this.eq(0).nextAll(selector).eq(0);
}

Et, alors vous utiliseriez simplement:

$(this).findNext(".box").slideToggle();

Option: ajouter plus de structure au HTML pour rendre les choses plus simples et plus flexibles

Pour info, une approche commune à des problèmes comme celui-ci consiste à mettre un div contenant autour de chaque ensemble d'éléments DOM comme ceci:

<div class="container">
    <img class="arrow" src="images/navigation/arrowright.png">
    <H2>More Information</H2>
    <div class="box">
            <h2>Bibendum Magna Lorem</h2>
            <p>Cras mattis consectetur purus sit amet fermentum.</p>
    </div>
</div>

<div class="container">
     <img class="arrow" src="images/navigation/arrowright.png">
     <H2>A Second Group of Information</H2>
     <div class="box">
            <h2>Bibendum Magna Lorem</h2>
            <p>Cras mattis consectetur purus sit amet fermentum.</p>
     </div>    
</div>

Ensuite, vous pouvez utiliser du code un peu moins sensible au positionnement exact des éléments:

$(".arrow").click(function() {
    $(this).closest(".container").find(".box").slideToggle();
});

Cela va jusqu'au parent contenant et commun en utilisant .closest() puis utilise .find() pour trouver l'élément .box Dans ce groupe.

44
jfriend00