tags:

views:

647

answers:

2

Hi, I have a question about some functionality I'm trying to add to my jQuery to enable a button or text to expand/contract all the divs on click... and I'd like to figure out how to keep the first div open when the page loads.

Here is the jQuery:

(document).ready(function(){

//Hides containers on load
$(".toggle_container").hide(); 

//Switch "Open" and "Close" state on click
$("h2.trigger").toggle(function(){
    $(this).addClass("active");
    }, function () {
    $(this).removeClass("active");
});

//Slide up and down on click
$("h2.trigger").click(function(){
    $(this).next(".toggle_container").slideToggle("slow");
    });
});

And the css:

// uses a background image with an on (+) and off (-) state stacked on top of each other
h2.trigger { background: url(buttonBG.gif) no-repeat;height: 46px;line-height: 46px;width: 300px;font-size: 2em;font-weight: normal;}
h2.trigger a {color: #fff;text-decoration: none; display: block;}
h2.active {background-position: left bottom;}
.toggle_container { overflow: hidden; }
.toggle_container .block {padding: 20px;}

And the html

<h2 class="trigger"><a href="#">Heading</a></h2> 
<div class="toggle_container"> 
  <div class="block">Stuff goes here</div> 
</div>

<h2 class="trigger"><a href="#">Heading 2</a></h2> 
<div class="toggle_container"> 
  <div class="block">Stuff goes here</div> 
</div>

So it works great and looks great. However, when I try to get it to keep the first instance open, the background image that should adjust show the (-) state doesn't change. The code I used to this was:

$(".toggle_container:first").show();

So, my question is, does anyone know of an easier way to show the first instance of this as open without having to created specials rules/class for the first item? Also, any ideas about how to make an open all/close all link?

Thanks!

+2  A: 

You can change all your jQuery to this:

$(".toggle_container:not(:first)").hide(); 
$("h2.trigger:first").addClass("active");

$("h2.trigger").click(function(){
  $(this).toggleClass("active");
  $(this).next(".toggle_container").slideToggle("slow");
});

This hides all but the first .toggle_container, applies the class="active" to it's matching <h2>, and the toggle() is just simpler, a click now toggles the class...so we can just add active to match it being open on page load and it'll behave correctly.

Also, a open/close all would look like this:

<a href="#" id="openCloseAll">Open All</a>

jQuery like this:

$("#openCloseAll").toggle(function() {
  $(this).text("Close All");
  $(".toggle_container:hidden").prev(".trigger").click();
}, function() {
  $(this).text("Open All");
  $(".toggle_container:visible").prev(".trigger").click();
});

This opens all closed on the first click, changes it's text to accurately describe what the next click will do, and closes all open on the next click, then switches back, rinse, repeat.

Nick Craver
Exactly what I was thinking ( and writing ).
Atømix
@hollyb - You're on the right track with IE, most likely invalid markup...paste your markup in the validator here and check it out: http://validator.w3.org/ For the reversal, easy enough, just swap the toggle function backwards and change the initial text to "Close all" and you're all set.
Nick Craver
I got the open/close swapped. Thanks for that. I've stripped down css/html to barebones, valid HTML. I still can't get the dang thing to open the first instance in IE. As I mentioned, the background is swapped to the minus state, which is good, but the div isn't expanded. I'm at a loss...? Any other ideas?
@hollyb - If you comment out the `$(".toggle_container:not(:first)").hide();` is it still hidden in IE?
Nick Craver
After commenting it out all divs appear in the open state in IE.
@hollyby - Try uncommenting, and putting `$(".toggle_container:first").show();` after it, that fix IE? Very strange it's not working correctly.
Nick Craver
That did it! Thank you so much for all your help Nick. You really went above and beyond.
@hollyb - Welcome :) Glad you got it working
Nick Craver
A: 

Further to what Nick posted you will also need to do the sliding.

$("h2.trigger").click(function(){
    $(this).toggleClass("active");
    $(this).next(".toggle_container").slideToggle("slow"); // added 
});
Atømix
I'm not sure what you mean? This seems to be in Nick's code, unless I'm missing something?