jquery next siblings

18,532

Solution 1

The root of your problem is that the <li>s you have classed as parent really are NOT parents of the <li>s "below" them. They are siblings. jQuery has many, many functions that work with actual parents. I'd suggest fixing your markup, really. It'd be quicker, cleaner, easier to maintain, and more semantically correct than using jQuery to cobble something together.

Solution 2

actually, you can easily do this using nextUntil(). no need to write your own "nextUntil" since it already exists.

ex. -

$(".a").nextUntil(".b");

or as suggested by Vincent -

$(".parent:first").nextUntil(".parent");

Solution 3

I don't think there is a way to do this without using each since any of the other selectors will also select the second parent and it's next siblings.

function getSibs( elem ) {
    var sibs = [];
    $(elem).nextAll().each( function() {
        if (!$(this).hasClass('parent')) {
            sibs.push(this);
        }
        else {
            return false;
        }
    });
    return $(sibs);
 }

Solution 4

You will have to run the loop yourself since jQuery does not know how to stop on a specific condition.

jQuery.fn.nextUntil = function(selector)
{
    var query = jQuery([]);
    while( true )
    {
        var next = this.next();
        if( next.length == 0 || next.is(selector) )
        {
            return query;
        }
        query.add(next);
    }
    return query;
}

// To retrieve all LIs avec a parent
$(".parent:first").nextUntil(".parent");

But you may be better using a really structured list for your parent/children relationship

<ul>
<li class="parent"> <span>headertext</span>
    <ul>
    <li> text </li>
    <li> text </li>
    <li> text </li>
    </ul>
</li>
<li class="parent"> <span>headertext</span>
    <ul>
    <li> text </li>
    <li> text </li>
    </ul>
</li>
</ul>
Share:
18,532
Contra
Author by

Contra

Working as a web dev in Norway.

Updated on August 24, 2022

Comments

  • Contra
    Contra over 1 year

    I've been trying to get this problem solved, but I can't seem to figure it out without some serious workarounds.

    if I have the following HTML:

    <ul>
        <li class="parent"> headertext </li>
        <li> text </li>
        <li> text </li>
        <li> text </li>
        <li class="parent"> headertext </li>
        <li> text </li>
        <li> text </li>
    </ul>
    

    Now, how do I now just select the <li> tags following the first parent (or second, for that matter)? Basically selecting an <li> with class="parent" and the following siblings until it reaches another <li> with the parent class.

    I could restructure the list with nested lists, but I don't want to do that. Any suggestions?

  • Ropstah
    Ropstah almost 15 years
    $("li.parent ~ li:not(li.parent)"); <<<<< this will leave out the next class="parent"s . It doesn't stop at that point however....
  • tvanfosson
    tvanfosson almost 15 years
    I agree with this, though, I have posted a potential solution. It would be much easier if the DOM relationships matched the actual relationships.
  • Mark Hurd
    Mark Hurd almost 15 years
    shudder Great idea, but geez, I'd hate to use it myself. :)
  • Contra
    Contra almost 15 years
    yeah, actually, I figured the "parent" classname was a bit wrong after I posted it. calling it "header" might be better. I may have to use nested lists after all
  • Contra
    Contra almost 15 years
    yeah I just wrote that exact same code, but as you mentioned it doesnt stop when it reaches the next class=parent
  • Contra
    Contra almost 15 years
    haha, actually, that is veery close to the workaround im using atm :) shame
  • Mark Hurd
    Mark Hurd almost 15 years
    I think in the long run that's the better approach. I know you don't want to redo it now, but you may thank yourself later.
  • Contra
    Contra almost 15 years
    Yep, I realized now that this is more clean. Also alot more easy to work with, as someone mentioned. I just thought there were some selector wizardry I couldnt figure out, but It seems that it isnt possible without manipulating the array afterwards.
  • Contra
    Contra almost 15 years
    I should've redone it at first when I noticed the difficuly on selecting the elements I wanted, since the work redoing the markup is alot less work then beating my jquery code to death :) lesson learned.
  • Contra
    Contra over 13 years
    This did not exist before version 1.4 of jQuery, which dropped a bit after the time of the question. But yeah, this will work now :)