Bluest_Cube
Bluest_Cube

Reputation: 98

Selecting multiple divs individually

I have this markup:

<h3 id="btn-1">Content Title</h3>
<ul><li>Some Content</li></ul>
...stuff here and further down the page... 
<h3 id="btn-2">Content Title 2</h3>
<ul><li>Some content 22</li></ul>

The content in the unordered list is supposed to drop down when "h3" is clicked and also append a class to h3 so as to create a style based on the open/close state. So I have this which is working as I want:

    $("#btn-1, #btn-2").attr('class','inactive');
    $("#btn-1").click(function (){
    if ($("#btn-1 + ul").is(":hidden")) {
            $("#btn-1 + ul").slideDown("slow"),$("#btn-1").attr('class','active');
                } else {
            $("#btn-1 + ul").slideUp('slow'),$("#btn-1").attr('class','inactive');
        }
    }); 


    $("#btn-2").click(function (){
        if ($("#btn-2 + ul").is(":hidden")) {
            $("#btn-2 + ul").slideDown("slow"),$("#btn-2").attr('class','active');
                } else {
            $("#btn-2 + ul").slideUp('slow'),$("#btn-2").attr('class','inactive');
        }
    }); 

I was looking for a more efficient way to write the code and I came up with this but it applies the animation to all the containers at the same time.

    $("h3[id^='btn-']").attr('class','inactive');
    $("h3[id^='btn-']").click(function (index){
        if ($("h3[id^='btn-'] + ul").is(":hidden")) {
            $("h3[id^='btn-'] + ul").slideDown("slow"),$("h3[id^='btn-']").attr('class','active');
                } else {
            $("h3[id^='btn-'] + ul").slideUp('slow'),$("h3[id^='btn-']").attr('class','inactive');
        }
    }); 

So my question is, is there a better way to reduce the code in the first working solution? Thanks.

Upvotes: 2

Views: 258

Answers (3)

missaghi
missaghi

Reputation: 5090

While not that readable, you asked for efficient, here it is in one line:

//hide content then only slide up other visible things 
$("h3[id^='btn-']").next("ul").hide().end().click(function (){ $("h3[id^='btn-']").next("ul").not(  $(this).next("ul").slideDown("slow").end().next("ul")).slideUp("slow"); });

And a more readable formatting:

//hide content then only slide up other visible things 
$("h3[id^='btn-']").next("ul").hide().end().click(function() {
    $("h3[id^='btn-']").next("ul").not(
    $(this).next("ul").slideDown("slow").end().next("ul")).slideUp("slow");
});​

Try it: http://jsfiddle.net/t4JF4/

Upvotes: 0

Jasper
Jasper

Reputation: 75993

Use this inside your callback function to refer to the element which is having the event fire on it:

$("h3[id^='btn-']").attr('class','inactive').click(function (index){
    $(this).toggleClass('inactive active').next().slideToggle("slow");
}); 

You can see that this simplifies your code even further by using toggle functions:

Here is a demo: http://jsfiddle.net/jasper/a692n/3/

Update

The RegExp selector you're using works but it has to look-up every element in the DOM to see if that element has the specified attribute and if that attribute value matches. I recommend adding a class to the <h3> elements because when you select by class jQuery uses getElementByClass where it's available (which is a fast way to select elements):

HTML --

<h3 class="h3-title" id="btn-1">Content Title</h3>
<ul><li>Some Content</li></ul>
...stuff here and further down the page... 
<h3 class="h3-title" id="btn-2">Content Title 2</h3>
<ul><li>Some content 22</li></ul>

JS --

$(".h3-title").attr('class','inactive').click(function (index){
    $(this).toggleClass('inactive active').next().slideToggle("slow");
}); 

Upvotes: 3

gen_Eric
gen_Eric

Reputation: 227190

Inside your click handler, you can use this to get the element clicked on (instead of using $("h3[id^='btn-']"), this gets all the <h3>s), and then get the <ul> next to it.

$("h3[id^='btn-']").attr('class','inactive');

$("h3[id^='btn-']").click(function (index){
    if ($(this).next('ul').is(":hidden")) {
        $(this).next('ul').slideDown("slow");
        $(this).attr('class','active');
    }
    else {
        $(this).next('ul').slideUp('slow');
        $(this).attr('class','inactive');
    }
});

DEMO: http://jsfiddle.net/8cFeF/1/

Upvotes: 3

Related Questions