views:

169

answers:

5

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
});
A: 
$("div.a").nextAll("div.b")

Does this work?

PeterWong
Nope [ ](http://fake)
Eric
+2  A: 

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);
});
Jonathon
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.
Eric
+3  A: 

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

Padel
Yes! That works. Although I think you may have just nudged me towards a better way.
Eric
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!
Padel
Ok, I have a solution [here](http://stackoverflow.com/questions/3141038/is-there-a-jquery-selector-to-accomplish-this-task/3141476#3141476) that feels less like cheating (ie no changing variables). However, yours look much more efficient.
Eric
+3  A: 

Got it!

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

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

    //do stuff
});​
Eric
It is perfectly acceptable to mark your own answer as the accepted one: http://meta.stackoverflow.com/questions/12513/should-i-not-answer-my-own-questions
fearoffours
Indeed. However, I can't decide whether my answer is better than Padel's.
Eric
A: 

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;
    }
});
Eric
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..
Gaby
Good point [ ](http://blank)
Eric