Search code examples
javascriptmulti-levelexpandablecollapsable

Javascript three-level collapsible menu


I am a complete amateur to coding; I want to have a three-level collapsible menu, which will expand when clicked. I have found some existing code to use, but it is designed for a two-level menu only. I cannot work out how to alter the script so that the third level will open when clicked too. Any ideas would be most appreciated!

Here is the existing script:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
   <!-- <script type="text/javascript" language="javascript" charset="utf-8" src="nav.js"></script> -->
<!--[if lt IE 9]>
  <script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->


  <script>
  $(document).ready(function(){
  $("#nav > li > a").on("click", function(e){
    if($(this).parent().has("ul")) {
      e.preventDefault();
    }

    if(!$(this).hasClass("open")) {
      // hide any open menus and remove all other classes
      $("#nav li ul").slideUp(350);
      $("#nav li a").removeClass("open");
      
      // open our new menu and add the open class
      $(this).next("ul").slideDown(350);
      $(this).addClass("open");
    }
    
    else if($(this).hasClass("open")) {
      $(this).removeClass("open");
      $(this).next("ul").slideUp(350);
    }
  });
});
</script>


Solution

  • You can achieve the same outcome with relatively little code compared to what you have there.

    Using css to handle the display is arguably easier to manage, with javascript simply toggling a class that you can target in your css. It also means that you can have as many levels as you wish.

    It works through the use of the next sibling selector in css +

    $('.menu-trigger').click(function(){
      $(this).toggleClass('active')
      
      // if you really wish to keep the jquery animation you can do this
      // $(this).next('ul').slideToggle()
    })
    /* you can use the sibling selector '+' to target the list */
    .menu-trigger + ul {
      display: none;
    }
    
    .menu-trigger.active + ul {
      display: block;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <ul>
      <li>
        <a class="menu-trigger">parent</a>
        <ul>
          <li>
            <a class="menu-trigger">child</a>
            <ul>
              <li>
                <a class="menu-trigger">grandchild</a>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>