Question

BACKGROUND

I've got a layout consisting of four absolutely-positioned div "quadrants", like so:

div.quadrant#one    |     div.quadrant#two
height: 25%;        |     height: 25%;
width: 25%;         |     width: 25%;
                    |
__________________________________________

div.quadrant#three  |    div.quadrant#four
height: 25%;        |    height: 25%;
width: 25%;         |    width: 25%;
                    |

HTML

<div class="quadrant" id="one"></div>
<div class="quadrant" id="two"></div>
<div class="quadrant" id="three"></div>
<div class="quadrant" id="four"></div>

I'm using jQuery to add classes of .open or .closed to the quadrants when one is clicked so the quadrant.open grows to 95% width and 100% height and the quadrant.closed shrink to 5% width and 33.33% height. Here's that code:

$( 'div.quadrant' ).click(function() {  
  $(this).addClass('open'); 
  $(this).parent().children('div.quadrant').not('.open').addClass('closed');  
});

I've got that piece working no problem. Here's where I'm stumped:

THE PROBLEM

I'm also trying to use .addClass to add another class to the three div.closed elements depending on whether they're the first div.closed, the second, or the third. If a div is the first with class "closed", I'd like to also add .top; if the second, I'd like to add .middle; if the third, I'd like to add .bottom.

I've tried to get this working by using :eq(1), :eq(2), and :eq(3). However, it only works if div#one or div#two are clicked, then the div.closed quadrants after that don't seem to be affected. Here's that code:

$(this).parent().children('div.quadrant').not('.open').addClass('closed');
$(this).parent().children('div.quadrant:eq(1)').not('.open').addClass('top');
$(this).parent().children('div.quadrant:eq(2)').not('.open').addClass('middle');
$(this).parent().children('div.quadrant:eq(3)').not('.open').addClass('bottom');

Here's a JS Bin: http://jsbin.com/UJopeTo/1/edit?html,css,js,output

Is there something wrong with the way I've chained these functions? Any help is appreciated!

Was it helpful?

Solution 2

You can create the jQuery object and then carry out different operations on different items in the jQuery object like this.

It also looks to me like you need to clean up the previous state (prior open, closed, top, middle, bottom) too like this:

$( '.quadrant' ).click(function() {  
    var self = $(this);

    // clear prior state
    var all = self.parent().find(".quadrant").removeClass("open closed top middle bottom");

    // mark the clicked on one as open
    self.addClass("open");

    // mark all other ones as closed
    var closed = all.not(this).addClass("closed");

    // now mark each closed one separately
    closed.eq(0).addClass("top");
    closed.eq(1).addClass("middle");
    closed.eq(2).addClass("bottom");
});

OTHER TIPS

The problem that you're running into is that you aren't correctly understanding what the :eq() selector and the .not() function are doing.

$(this).parent().children('div.quadrant:eq(1)').not('.open').addClass('top');
$(this).parent().children('div.quadrant:eq(2)').not('.open').addClass('middle');
$(this).parent().children('div.quadrant:eq(3)').not('.open').addClass('bottom');

What this is doing in the code you provided in the jsbin link is

  1. Select the second div.quadrant element within the tag (which is #two)
  2. If its class is not .open, add the .top class to it
  3. Select the third div.quadrant element within the tag (which is #three)
  4. If its class is not .open, add the .middle class to it
  5. Select the fourth div.quadrant element within the tag (which is #four)
  6. If its class is not .open, add the .bottom class to it

I see what you were trying to do, but that's not the best method. The best solution to this problem would be to approach the problem in a repeatable, more object oriented approach, like what jfriend00 suggested.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top