jQuery Dropdown Panels

A couple of recent projects have needed a means of displaying dropdown panels that could serve as menus, forms and lists. To remind myself how to build the interface, I’m going to document the jQuery code that makes it all work.

HTML

The code applies the same class name to each nav-item where each has a child with a class of panel. The panel class can be a ul element or a form element or a div or any block-level element.

              <nav role="navigation" class="main-nav">
  <ul class="menu">
    <li id="nav-about" class="nav-item">
      <a href="#" id="menu-item">Menu</a>
      <ul class="panel">
        <li><a href="#">Item 1</a></li>
        <li><a href="#">Item 2</a></li>
        <li><a href="#">Item 3</a></li>
        <li><a href="#">Item 4</a></li>
        <li><a href="#">Item 5</a></li>
      </ul>
    </li>
    <li id="utility-nav">
      <ul>
        <li id="nav-search" class="nav-item">
          <a href="#">Search</a>
          <form class="panel form-fields" id="form-search">
            <fieldset class="fields-search">
              <input type="text" id="search-terms" placeholder="Enter keywords..." />
              <input type="submit" value="Search" class="submit-search" />
            </fieldset>
          </form>
        </li>
        <li id="nav-directory" class="nav-item">
          <a href="#" id="nav-directory-item"><b>A-Z</b> Directory</a>
          <div class="panel" id="panel-directory">
            <p>Find resources alphabetically</p>
            <ul id="alpha">
              <li><a href="#a" rel="A">A</a></li>
              <li><a href="#b" rel="B">B</a></li>
              <li><a href="#c" rel="C">C</a></li>
              <li><a href="#d" rel="D">D</a></li>
              <li><a href="#e" rel="E">E</a></li>
              <li><a href="#f" rel="F">F</a></li>
              <li><a href="#g" rel="G">G</a></li>
              <li><a href="#h" rel="H">H</a></li>
              <li><a href="#i" rel="I">I</a></li>
              <li><a href="#j" rel="J">J</a></li>
              <li><a href="#k" rel="K">K</a></li>
              <li><a href="#l" rel="L">L</a></li>
              <li><a href="#m" rel="M">M</a></li>
              <li><a href="#n" rel="N">N</a></li>
              <li><a href="#o" rel="O">O</a></li>
              <li><a href="#p" rel="P">P</a></li>
              <li><a href="#q" rel="Q">Q</a></li>
              <li><a href="#r" rel="R">R</a></li>
              <li><a href="#s" rel="S">S</a></li>
              <li><a href="#t" rel="T">T</a></li>
              <li><a href="#u" rel="U">U</a></li>
              <li><a href="#v" rel="V">V</a></li>
              <li><a href="#w" rel="W">W</a></li>
              <li><a href="#x" rel="X">X</a></li>
              <li><a href="#y" rel="Y">Y</a></li>
              <li><a href="#z" rel="Z">Z</a></li>
              <li><a href="##" rel="#">#</a></li>
            </ul>
          </div>
        </li>
        <li id="nav-contact"><a href="#">Contact</a></li>
      </ul>
    </li>
  </ul>
</nav>

            

JavaScript

The jQuery code checks that the document is loaded. Then, on a click event on a navigation item, a jQuery selector finds each nav-item and first removes the open class from all nav-item elements except for the item that triggered the onclick event. This item can then be toggled open and closed. A click event is added to the html element to add a “click outside” event to close all panels when the mouse clicks on anything other than a nav-item. But the “click outside” event will close the panels when the items are clicked. So, the stopPropagation method is added to the click event for the panel class.

              $(document).ready(function(){

  // Display global navigation panels on click
  $('.nav-item').click(function(event){
    event.stopPropagation(); // Stop propagation of the click outside event
    $('.open').not($(this)).removeClass("open");
    $(this).toggleClass("open");
  });

  // Hide search menu panels when clicking outside
  $("html").click(function() {
    $(".open").removeClass("open");
  });

  // Keep panels open when clicked
  $(".panel").click(function(event){
    event.stopPropagation();
  });

});

            

CSS

The styles for the panels allow for a fallback to display the panels on hover when JavaScript is not running, as Modernizr is being used to test that availability of JavaScript. Otherwise, the open class will be used to toggle the display of the dropdown panel.

              .nav-item .panel {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  z-index: 20;
  width: auto;
}

.no-js .nav-item:hover .panel,
.nav-item.open .panel {
  display: block;
}