benni_mac_b
benni_mac_b

Reputation: 8877

Unable to find next element

I want to have multiple elements on a page which will toggle visibility of the next content span when the a header span is clicked. All the content span contents are hidden on document ready.

The toggle of content works when targeting the entire class but not when trying to target the next content span element on from the header span being clicked.

The particular markup is being used as we are trying to manipulate text entered via a telerik radeditor

http://jsfiddle.net/hn5ss2au/

HTML

<p>
   <span class="collapsibleHeader">Content Header</span><br />
   <span class="collapsibleContent">Sed dignissim velit non congue consequat.</span>
</p>

<p>
   <span class="collapsibleHeader">Content Header</span><br />
   <span class="collapsibleContent">Sed dignissim velit non congue consequat.</span>
</p>

JQuery

$(document).ready(function () {
$('.collapsibleContent').hide();
    $('.collapsibleHeader').click(function (e) {
        $(this).parent().next('.collapsibleContent').toggle();
        e.preventDefault();
    });
});

Upvotes: 1

Views: 143

Answers (3)

iCollect.it Ltd
iCollect.it Ltd

Reputation: 93551

You are going up one level, to the p element, then next to the next element (see next note), but .collapsibleContent is a child of that p and a <br/> is actually the next() element to the p (so the filter does not match anything either). next() only ever returns the next element, then applies the filter to see if it matches.

Drop the parent() and use nextAll() with your selector:

$(document).ready(function () {
    $('.collapsibleContent').hide();
    $('.collapsibleHeader').click(function (e) {
        $(this).nextAll('.collapsibleContent').toggle();
        e.preventDefault();
    });

    $('.collapsibleContent2').hide();
    $('.collapsibleHeader2').click(function (e) {
        $('.collapsibleContent2').toggle();
        e.preventDefault();
    });
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/hn5ss2au/3/

You can use siblings() with the same filter, but it is slower than nextAll(). If there happen to be more than one of each match, also add first()

e.g.

$(this).nextAll('.collapsibleContent').first().toggle();

Note: nextall is faster than the alternatives of siblings() and parent().children(): http://jsperf.com/jquery-next-vs-siblings/5

Upvotes: 3

Andre Morgan
Andre Morgan

Reputation: 96

Accessing the parent and then .next() will get you the next paragraph element rather than your content. There's no need to hit parent in this scenario. You need to fetch the siblings of the clicked element that have the class .collapsibleContent. Fetching next on the clicked elem also won't work because technically your next elem after the header is a break tag. the following will do that trick:

 $('.collapsibleHeader').click(function (e) {
   e.preventDefault();
   $(this).siblings('.collapsibleContent').toggle();
 });

Upvotes: 1

koralarts
koralarts

Reputation: 2112

The reason why next isn't working is because you're using parent().

Inside the click callback function, you're calling $(this).parent(). When the callback is called, $(this) will be .collapsibleHeader so when you call .parent(), it will return the p tag.

To get the .collapsibleContent you must call .children('.collapsibleContent') as opposed to .next().

Your code will be as follows:

$(this).parent().children('.collapsibleContent').toggle();

jsFiddle: http://jsfiddle.net/qetcd7o4/

Upvotes: 1

Related Questions