views:

113

answers:

5

I have a structure of divs inside divs, something like this:

<div class='parent'>
    <div class='a first'>something here</div>
    <div class='a'>something here</div>
    <div class='a last'>something here</div>
    <div>something here</div>
    <div>something here</div>
    <div class='a first'>something here</div>
    <div class='a'>something here</div>
    <div class='a'>something here</div>
    <div class='a'>something here</div>
    <div class='a last'>something here</div>
    <div>something here</div>
    <div>something here</div>
    <div>something here</div>
    <div class='a first last'>something here</div>
</div>
<div class='parent'>
    <div>something here</div>
    <div class='a first'>something here</div>
    <div class='a last'>something here</div>
    <div>something here</div>
    <div>something here</div>
    <div class='a first'>something here</div>
    <div class='a'>something here</div>
    <div class='a'>something here</div>
    <div class='a last'>something here</div>
</div>

As you can see, there are "consecutive blocks" of inner divs which have class a. First div in each block has class first, and last div has class last. Each block is in one parent div (block cannot span on 2 or more parent divs).

Say I click on one of the inner divs which has class a. Is that possible to select only the divs which are in the same block with the clicked div ?

How would you do this ? (If possible, using jQuery.)

+4  A: 

This will give you all siblings of the current div:

$("div.a").click(function() {
     var siblings = $(this).siblings("div");
})

If you just want the ones from each .first to .last block then you want something like:

$("div.a").click(function() {
    var clicked = $(this);
    var siblings = clicked.prevUntil(":not(div.a)")
                          .andSelf()
                          .add(clicked.nextUntil(":not(div.a)"));
})

(This assumes they will always be consecutive. It gets a lot more complicated if they're not. It will also not work correctly if there are two consecutive groups without separation. It should be fairly easy to modify it to work in these situations.)

Edit: This should work in all situations

$("div.a").click(function() {
    var clicked = $(this);
    var siblings = clicked.prevUntil(":not(.a:not(.last))")
                          .andSelf()
                          .add(clicked.nextUntil(":not(.a:not(.first))"));
    $("#output").html(siblings.length);
});​

http://jsfiddle.net/ZL6rw/2/

Bennor McCarthy
This will choose not only the desired block `div`s.
Misha Moroshko
I initially mis-read the question. I've updated it to solve the actual problem. My solution doesn't require the 'first' and 'last' classes, so you could remove them if you don't otherwise need them.
Bennor McCarthy
Had to re-edit because it still wasn't quite right (was using prevAll, instead of prevUntil)
Bennor McCarthy
Your solution assumes that a parent has a single first and a single last element, but that's not the case.
Jesse Dhillon
Yeah, I realised and fixed it.
Bennor McCarthy
Thanks for your effort! The use **first** and **last** classes is required because otherwise if you had 2 consecutive blocks you would think it is 1 block.
Misha Moroshko
Cool. I've updated it now with what should work in all situations, i.e. two consecutive blocks should now work.
Bennor McCarthy
Looks perfect now ! Thanks a lot !
Misha Moroshko
A: 
function allDivs(sender)
{
   var allAs = $(sender).parent().children();

   //Do other things
}

Bind every Div's onclick event having "a" as class to this function passing "this" as parameter

Umair Ashraf
This will choose not only the desired block `div`s.
Misha Moroshko
this will! you need to bind this function with each 'div' passing "this" keyword
Umair Ashraf
+1  A: 

Something like this should work

$('div.a').click(function()
{
    $(this).siblings();
});

You can also do something similar like this :

$('div a').click(function()
{
    $(this).siblings('div.a');
});

That will select only the divs with a class of "a" etc.

EDIT : Ok. I see what you want to do.

$(div.a).click(function()
{
    var CurrentNode = $(this).prev('div.first');
    while(true)
    {

        //Do whatever to the node here. Bind events etc

        //Check if the current node is the last. 
        if(CurrentNode.hasClass('last'))
            break;

        //Get the next node. 
        var CurrentNode = CurrentNode.next('div');
    }
});

That should do it. Ofcourse you need to be doing something to the nodes as you iterate through them. Not the most elegant of solutions (Probably something better out there), but it should work.

In future though, just try and articulate your question better instead of downvoting everyone.

Pyronaut
You probably didn't understand what "block" is.
Misha Moroshko
@Misha - Downvoting everyone answering is missing the point...you ever think the problem lies in your articulation of the question and *not* the answers, since they all thought the same thing reading your question? That's a good way to get no answers in the future.
Nick Craver
After re-reading the question, this is a fairly easy solve. If you weren't going ahead and downvoting everyone, you would probably get a answer faster.
Pyronaut
He pretty clearly said "a block is...", but you looked at the HTML and assumed that by block he meant something else. Downvoting is not appropriate though.
Jesse Dhillon
Would be good if someone would remove the down vote from my correct answer...
Bennor McCarthy
@Bennor - Not my downvote, that was the OP...but your answer still isn't correct, it's making an assumption that blocks will never be back to back, I'm not sure that's a safe assumption.
Nick Craver
Yeah, I've realised that. Because the question was so misleading I based my answer entirely on the markup. I still think based on his edit to the question that the blocks will always be separated, or else they're considered the same block. Under those circumstances, my solution works.
Bennor McCarthy
OK Nick, got you.
Misha Moroshko
A: 

Other answerers don't realize that you are asking about getting all siblings between a "first" and "last" element, not just all siblings. To facilitate this, you should wrap each block in a div like so:

<div class="block">
  <div class="first">
    <div class="a">something</div>
  </div>
  <div class="block">
    <div class="a">something</div>
    <div class="a">something</div>
  </div>
  <div class="last">
    <div class="a">something</div>
  </div>
</div>

Now if one of the .block .a elements is clicked, you can get all of its siblings by simply doing

$(".block .a").click(function() {
  var siblings = $(this).siblings(".a");
})

siblings will be all the div.a elements which are contained by the same parent.

Jesse Dhillon
Wrapping with another div this is not really what I want to do...
Misha Moroshko
You should learn how to write semantic markup.
Jesse Dhillon
A: 

'last + *' is to include the closing element. This will select the first and last div for the same 'block'.

if($(this).hasClass('first')){
  $(this).nextUntil('.last + *').andSelf().css('background-color','red');
}
else{
  $(this).prevUntil(':not(div.a)').css('background-color','red');
  $(this).nextUntil('.last + *').andSelf().css('background-color','red');
}
SteD