Home > Enterprise >  JS logic: Open / close menu on click or replace with another
JS logic: Open / close menu on click or replace with another

Time:04-02

I have a menu which opens up a submenu on click.

If a link has a dropdown menu (has class header--has-submenu), then on click, I'm making another element (.header__subContainer) appear.

The issue I'm having is with the logic. For example, in my demo, I have two links, what we deliver and about us, both have submenus.

I want a user to be able to click onto a link to open it and then click on the same link to close it (standard UX).

However, I also want the user to be able to click on one link (let's say 'what we deliver) and then click onto about usto show that menus dropdown (then the user can click theabout us` link again to close the menu).

I've tried toggleClass but this causes issues with the last scenario above.

Here's a demo:

  $(".header--has-submenu a.header__parentLink").click(function(e) {
    e.preventDefault();
    
    console.log("click");

    var id = $(this).attr('data-menu');

    // add active state styles to link to showcase which menu is open
    $("li.header--has-submenu").removeClass("header--has-submenu--active");
    $(this).parent().addClass("header--has-submenu--active");


    // open subContainer (black div that contains all submenus)
    if ( $(".header__subContainer-menu").hasClass("header__subContainer-menu--active") ){
      $(".header__subContainer").removeClass("header__subContainer--active");
    } else {
      $(".header__subContainer").addClass("header__subContainer--active");
    }


    // remove active class from submenu, so only one menu is open at one time
    $(".header__subContainer-menu").removeClass("header__subContainer-menu--active");

    // open the relevant menu
    $(this).closest(".header__subContainer").addClass("header__subContainer--active");
    $(".header__subContainer-menu[data-menu='" id "']").toggleClass("header__subContainer-menu--active");

  });
.header {
  padding: 30px 0;
}
.header__parentUl * {
  color: #FFFFFF;
}
.header__li {
  margin: 0 20px;
}
.header__subContainer {
  display: none;
}
.header__subContainer--active {
  display: block;
}
.header__subContainer-menu {
  display: none;
}
.header__subContainer-menu--active {
  display: block;
}
.header--has-submenu--active a {
  color: green;
}

.background--black {
  background: #000000;
}

.reset-list {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

.color--white {
  color: #FFFFFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP u1T9qYdvdihz0PPSiiqn/ /3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<header >

  <div >
    <div >
      <nav >
        <ul >

          <li >
            <a  href="#" data-menu="what-we-deliver">What we deliver</a>
          </li>

          <li >
            <a  href="#" data-menu="about-us">About us</a>
          </li>

        </ul>
      </nav>
    </div>
  </div>

  <div >
    <div >
      <div >

        <nav  data-menu="what-we-deliver">
          <ul >
            <li >
              <a  href="#">Link 1</a>
            </li>
            <li >
              <a  href="#">Link 2</a>
            </li>
          </ul>
        </nav>

        <nav  data-menu="about-us">
          <ul >
            <li >
              <a  href="#">Link 3</a>
            </li>
            <li >
              <a  href="#">Link 4</a>
            </li>
          </ul>
        </nav>

      </div>
    </div>
  </div>

</header>

CodePudding user response:

Something like this should work:

$(".header--has-submenu a.header__parentLink").click(function(e) {
  e.preventDefault();

  let id = $(this).attr('data-menu');
  
  // Check if link already active
  let wasOpen = $(this).parent().hasClass("header--has-submenu--active");

  // remove all active classes
  $(".header--has-submenu").removeClass("header--has-submenu--active");
  $(".header__subContainer-menu").removeClass("header__subContainer-menu--active");
  $(".header__subContainer").removeClass("header__subContainer--active");

  if(!wasOpen){
    // the clicked link was not open
    // add active classes to the 3 elements
    
    $(this).parent().addClass("header--has-submenu--active");
    $('.header__subContainer').addClass('header__subContainer--active');
    $(".header__subContainer-menu[data-menu='" id "']").addClass("header__subContainer-menu--active");

  }
});
  • Related