Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
32
rated 0 times [  33] [ 1]  / answers: 1 / hits: 55152  / 9 Years ago, sat, may 16, 2015, 12:00:00

Okay, I am trying to get this set of information to hide individually.



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


It works when I type this:



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


but not when I do this:



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


What is happening that makes the second option not work? I've been at it for days and can't bloody figure it out! I appreciate your input!


More From » jquery

 Answers
90

The Problem



If you look at the documentation for .next(selector), it does not find the next sibling that matches the selector. Rather, it looks at JUST the next sibling and ONLY returns that element if it matches the selector which is not what you want.



Here's what the doc for .next() says:




Description: Get the immediately following sibling of each element in
the set of matched elements. If a selector is provided, it retrieves
the next sibling only if it matches that selector.




So, you can see that .next(.box) will look at the h2 element that immediately follows your .arrow element (that's the next sibling element) and then compare that to the .box selector and since they don't match, it will return an empty jQuery object.






A Solution Using .nextAll()



If you want the next sibling that matches a selector, you can use this:



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


This finds all the siblings that follow that match the selector and then extracts just the first one.






Create Your Own .findNext() Method



I've so often wondered why jQuery doesn't have a method for this that I've made one myself:



// 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);
}


And, then you would just use:



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





Option: Add More Structure to the HTML to Make Things Simpler and More Flexible



FYI, a common approach to problems like this is to put a containing div around each set of DOM elements like this:



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


Then, you can use code that is a little less sensitive to exact positioning of elements:



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


This goes up to the containing and common parent using .closest() and then uses .find() to find the .box element in that group.


[#66578] Thursday, May 14, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
travion

Total Points: 137
Total Questions: 96
Total Answers: 103

Location: India
Member since Wed, Aug 4, 2021
3 Years ago
travion questions
Mon, Dec 16, 19, 00:00, 5 Years ago
Sat, Oct 19, 19, 00:00, 5 Years ago
Fri, Sep 20, 19, 00:00, 5 Years ago
Wed, Nov 14, 18, 00:00, 6 Years ago
Sun, Oct 28, 18, 00:00, 6 Years ago
;