0
votes

I'm trying to make a menu that collapses, markup is below:

Whenever a .cat_menu_header is clicked, the ul below it should expand and all expanded ul's should collapse. So we start with everything collapsed and only the .cat_menu_header elements visible, with max 1 .submenu being expanded at one time.

<ul id='sidebarNav'>
  <li class='cat_menu_header'><a class='collapsed' href='#'>Link 1
    <ul class='submenu'>
      <li><a href='#'>text 1</a></li>
      <li><a href='#'>text 2</a></li>
    </ul>
  </li>
  <li class='cat_menu_header'><a class='collapsed' href='#'>Link 2
    <ul class='submenu'>
      <li><a href='#'>text 3</a></li>
      <li><a href='#'>text 4</a></li>
    </ul>
  </li>
</ul>

The follow js makes each .submenu expand and collapse but I can't figure out how to select all expanded ul's and collapse them. I added the .collapsed class which could be changed to .expanded with toggleClass.

I know I'm close ...

    $(document).ready(function(){   
    //sidebar collapsible menu
    $("#sidebarNav > li > ul").hide();

    $("#sidebarNav a.collapsed").click(function() {
        $(this).toggleClass("expanded").toggleClass("collapsed").find("+ ul").slideToggle("fast");
        return false;
    });
});
4

4 Answers

1
votes

First, your "li.cat_menu_header a" tag are not closed.

<ul id="sidebarNav">
    <li class="cat_menu_header collapsed">
        <a href="#">Link 1</a>
        <ul class="submenu">
            <li><a href="#">text 1</a></li>
            <li><a href="#">text 2</a></li>
        </ul>
    </li>

    <li class="cat_menu_header collasped">
        <a href="#">Link 2</a>
        <ul class="submenu">
            <li><a href="#">text 1</a></li>
            <li><a href="#">text 2</a></li>
        </ul>
    </li>
</ul>

It is easier to flag the li.cat_menu_header with the collasped or expanded class in order to use siblings() function. That is useful if you want to keep your actions relative to the context, for instance if you initialize this event for more than one sidebar.

jQuery( function()
{
    $("#sidebarNav ul.submenu").hide();

    $("#sidebarNav li.cat_menu_header > a").click( function()
    {
        $(this).parent().siblings( ".expanded" ).addClass( "collapsed" ).slideUp( "fast" );
        $(this).parent().addClass( "expanded" ).removeClass( "collapsed" );
        $(this).next().slideDown( "fast" );
    } );
} );

This example make the "li.cat_menu_header a" just expand its "submenu".

0
votes

So what I do for this is make a reference to the CURRENT clicked item:

var $this = $(this);

Then close ALL links:

$('.submenu').hide();

Then open the one you want:

$this.show()

This should get you moving in the right direction. It's also probable that for this kind of operation you should NOT be using "toggle" as it will be a major PITA. Just use click(), close everything, open the clicked one after everything has been closed.

0
votes
function helper(ele) {
    ele.toggleClass("expanded")
       .toggleClass("collapsed")
       .find("+ ul")
       .slideToggle("fast");
}
$("#sidebarNav a.collapsed").live("click", function() {
    //just close the ones which are open
    helper($("ul#sidebarNav a.expanded"));
    helper($(this));
    return false;
});
-1
votes

Bear with me as my brain is a bit fried and I can't think of the specific code, but I'd be inclined to hide/collapse all elements and then only expand $(this) when 'a.collapsed' is clicked. Hope that makes sense :)

$(document).ready(function(){       
//sidebar collapsible menu
$("#sidebarNav > li > ul").hide();

$("#sidebarNav a.collapsed").click(function() {
    $("#sidebarNav > li > ul").slideUp('fast'); // Slide them all up
    $(this).toggleClass("expanded").toggleClass("collapsed").find("+ ul").slideToggle("fast");
    return false;
});

});