Is there a jQuery selector to accomplish this task?
Asked Answered
D

5

13

I have these 4 HTML snippets:

  • Siblings:

    <div class="a">...</div>
    <div class="b">...</div>        <!--selected-->
    <div class="b">...</div>        <!--not selected-->
    
  • Wrapped 1:

    <div class="a">...</div>
    <div>
        <div class="b">...</div>    <!--selected-->
    </div>
    <div class="b">...</div>        <!--not selected-->
    
  • Wrapped 2:

    <div>
        <div class="a">...</div>
    </div>
    <div>
        <div class="b">...</div>    <!--selected-->
    </div>
    <div class="b">...</div>        <!--not selected-->
    
  • Separated:

    <div class="a">...</div>
    <div>...</div>
    <div class="b">...</div>        <!--selected-->
    <div>...</div>
    <div class="b">...</div>        <!--not selected-->
    <div>...</div>
    <div class="b">...</div>        <!--not selected-->
    

How can I, with jQuery, select the next .b element for any given .a element, regardless of nesting?

I want something like this:

$('.a').each(function() {
    var nearestB = $(this)./*Something epically wonderful here*/;

    //do other stuff here
});
Ducktail answered 29/6, 2010 at 13:25 Comment(3)
By chance is there a limit to how deeply nested the next b can be?Czar
Probably, but I'd prefer a general solution.Ducktail
Can you update your example to show the fact that there can be many .bs (not 1:1 with the .as)?Steffi
D
1

Ok, here's a modified version of Padel's solution, that behaves slightly differently

var lastA = null;

$('.a, .b').each(function() {
    if($(this).hasClass('a'))
    {
        lastA = $(this);
    }
    else if(lastA)
    {
        doStuff(lastA,this); //doStuff(a,b)
        lastA = null;
    }
});
Ducktail answered 29/6, 2010 at 14:47 Comment(1)
i like your own previous answer better, because it allows to be used on a per element basis, instead of only once on all elements.. i mean that it could be adapted to work on hover by finding the next .b element, while this one cannot be easily adapted to that scenario..Bleak
S
3

Can you try this to see if it suits your case?

    $(document).ready(function () {
        var isA = false;

        $('div.a, div.b').each(function () {
            if ($(this).attr('class') == "a")
                isA = true;
            if ($(this).attr('class') == "b" && isA) {
                $(this).css("background", "yellow");
                isA = false;
            }
        });
    });

Regards...

Stag answered 29/6, 2010 at 13:56 Comment(3)
Yes! That works. Although I think you may have just nudged me towards a better way.Ducktail
It's a good thing then! Maybe work on it a little (change .attr('class') == "a" with .hasClass("a") etc) to make it better... Cheers!Stag
Ok, I have a solution here that feels less like cheating (ie no changing variables). However, yours look much more efficient.Ducktail
D
3

Got it!

var both = $('.a, .b');

$('.a').each(function() {
    var nearestB = both.slice(both.index(this))
                       .filter('.b')
                       .first();

    //do stuff
});​
Ducktail answered 29/6, 2010 at 14:11 Comment(2)
It is perfectly acceptable to mark your own answer as the accepted one: meta.stackexchange.com/questions/12513/…Diclinous
Indeed. However, I can't decide whether my answer is better than Padel's.Ducktail
S
2

How are you deciding which .a to select? Is there a .b for ever .a? Are you looping over each? You could use the index of the .a and simply select the corresponding .b.

$(".a").each(function(){
    var index = $(".a").index(this);
    var theB = $(".b").get(index);
});
Steffi answered 29/6, 2010 at 13:35 Comment(1)
There is a .b for every .a. There is not an .a for every .b. So unfortunately that wouldn't work. All the a. s will be selected. See my updated question.Ducktail
D
1

Ok, here's a modified version of Padel's solution, that behaves slightly differently

var lastA = null;

$('.a, .b').each(function() {
    if($(this).hasClass('a'))
    {
        lastA = $(this);
    }
    else if(lastA)
    {
        doStuff(lastA,this); //doStuff(a,b)
        lastA = null;
    }
});
Ducktail answered 29/6, 2010 at 14:47 Comment(1)
i like your own previous answer better, because it allows to be used on a per element basis, instead of only once on all elements.. i mean that it could be adapted to work on hover by finding the next .b element, while this one cannot be easily adapted to that scenario..Bleak
C
0
$("div.a").nextAll("div.b")

Does this work?

Cetacean answered 29/6, 2010 at 13:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.