LeeTee
LeeTee

Reputation: 6601

JQuery click event not working on links with # - need to show / hide submenus on mobile

I have a left hand menu that has a flyout submenu on hover. On tablet / mobile I have the menu collapsing with a toggle button. This all works fine.

The problem is the click event does not work on the menu items that have a submenu. I need to show / hide the submenus on click on mobile. So nothing happens when Item 1 is clicked but item 2 works and the submenu links work. Could it be the ones with links work and the ones with # don't?

   $(function() {
//behaviours depending on screensize
function checkScreenSize() {
  var width = $(window).width();

  /*MOBILE*/
  if (width < 991.98) {
    $('#primary-menu li').click(function() {
      console.log('test 1');
      $(this).children('.sub-menu').slideToggle();
    });
    //does not work

    $('#primary-menu > li').on('click', function() {
      console.log('test 2');
      $(this).children('.sub-menu').slideToggle();
    });
    //does not work

    //show submenu 
    $('#primary-menu  li').on('click', function() {
      console.log('test 3');
      var submenu = $(this).children('.sub-menu');
      $(submenu).show();

    });
    //does not work

    $('#primary-menu li > .sub-menu').parent().click(function() {
      console.log('test 4');
      var submenu = $(this).children('.sub-menu');
      var current = $(this).hasClass("current-menu-item");
      $(submenu).show();

    });
    //this works

  } else {
    /*DESKTOP*/
    // ....this all works....
  }


  checkScreenSize();
  $(window).resize(checkScreenSize);
});
.sub-menu {display:none}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="primary-menu" class="menu nav-menu">
  <li id="menu-item-4793" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4793">
    <a href="#" class="menu-image-title-after menu-image-not-hovered"><img width="1" height="1" src="/wp-content/uploads/2021/12/copie.svg" class="menu-image menu-image-title-after" alt="" loading="lazy"><span class="menu-image-title-after menu-image-title">Item 1</span></a>
    <ul class="sub-menu" style="display: table;">
      <li id="menu-item-4908" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4908">
        <a href="/subitem1/">SUBItem1</a>
      </li>
      <li id="menu-item-4892" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4892">
        <a href="/subitem2/">SUBItem2</a>
      </li>
    </ul>
  </li>
  <li id="menu-item-4794" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-4794">
    <a href="/item2/" aria-current="page" class="menu-image-title-after menu-image-not-hovered">
      <img width="1" height="1" src="https://staging.heuristic-hypatia.91-134-228-53.plesk.page/wp-content/uploads/2021/12/Plan-de-travail-1.svg" class="menu-image menu-image-title-after" alt="" loading="lazy">
      <span class="menu-image-title-after menu-image-title">Item 2</span>
    </a>
  </li>
</ul>

Upvotes: 5

Views: 729

Answers (3)

Elias
Elias

Reputation: 90

Can't you just add two class to target directly your <li> (or work with your ids) ? I just add class menu-item-toggler to the first item and menu-item-redirect the the second one. Then I work with these classes.

I don't know if this is what you are looking for

$(function() {
  function mobileInit() {
    $('.menu-item-toggler').click(e => {
        e.preventDefault();
        console.log("Click Event on Top Level");
        $('.menu-item-toggler>.sub-menu').toggle();
        return false;
    })
    $('.menu-item-redirect').click(e => {
        console.log("Click Event on Sub Level");
        e.stopPropagation();
        return false;
    })
  };
  function desktopInit() {}

  //behaviours depending on screensize
  function checkScreenSize() {
    if ($(window).width() < 991.98) {
      console.log("Mobile");
      mobileInit();
    } else {
      console.log("Desktop");
      desktopInit();
    }
  }

  checkScreenSize();
  $(window).resize(checkScreenSize);
});
.sub-menu {
  display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="primary-menu" class="menu nav-menu">
  <li id="menu-item-4793" class="menu-item-toggler menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4793">
    <a href="#" class="menu-image-title-after menu-image-not-hovered"><img width="1" height="1" src="/wp-content/uploads/2021/12/copie.svg" class="menu-image menu-image-title-after" alt="" loading="lazy"><span class="menu-image-title-after menu-image-title">Item 1</span></a>
    <ul class="sub-menu">
      <li id="menu-item-4908" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4908">
        <a href="/subitem1/">SUBItem1</a>
      </li>
      <li id="menu-item-4892" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4892">
        <a href="/subitem2/">SUBItem2</a>
      </li>
    </ul>
  </li>
  <li id="menu-item-4794" class="menu-item-redirect menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-4794">
    <a href="/item2/" aria-current="page" class="menu-image-title-after menu-image-not-hovered">
      <img width="1" height="1" src="https://staging.heuristic-hypatia.91-134-228-53.plesk.page/wp-content/uploads/2021/12/Plan-de-travail-1.svg" class="menu-image menu-image-title-after" alt="" loading="lazy">
      <span class="menu-image-title-after menu-image-title">Item 2</span>
    </a>
  </li>
</ul>

*I worked with Twisty's code

Upvotes: 0

btargac
btargac

Reputation: 402

Maybe you should try event delegation method, for example something like this;

$('#primary-menu).on('click', '.submenu > .menu-item', function (e) {
  // avoid the event to propagate and avoid running the other event listeners added to parent element(s)
  e.stopPropagation();
  // do the stuff you want to do with sub menus
  var submenu = $(this).children('.sub-menu');
  $(submenu).show();
})

$('#primary-menu).on('click', '.menu-item.menu-item-has-children', function (e) {
  // avoid the event to propagate and avoid running the other event listeners added to child element(s)
  e.stopPropagation();
  // do the stuff you want to do with menu items that has sub menus
  $(this).children('.sub-menu').slideToggle();
})

Upvotes: 0

Twisty
Twisty

Reputation: 30893

Consider the following.

$(function() {
  function mobileInit() {
    $('li.menu-item').off("click").click(function(e) {
      if ($(this).parent("ul").is("#primary-menu")) {
        e.preventDefault();
        console.log("Click Event on Top Level");
        $(".sub-menu", this).toggle();
        return false;
      } else {
        console.log("Click Event on Sub Level");
        e.stopPropagation();
        return false;
      }
    });
  }

  function desktopInit() {}

  //behaviours depending on screensize
  function checkScreenSize() {
    if ($(window).width() < 991.98) {
      console.log("Mobile");
      mobileInit();
    } else {
      console.log("Desktop");
      desktopInit();
    }
  }

  checkScreenSize();
  $(window).resize(checkScreenSize);
});
.sub-menu {
  display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="primary-menu" class="menu nav-menu">
  <li id="menu-item-4793" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4793">
    <a href="#" class="menu-image-title-after menu-image-not-hovered"><img width="1" height="1" src="/wp-content/uploads/2021/12/copie.svg" class="menu-image menu-image-title-after" alt="" loading="lazy"><span class="menu-image-title-after menu-image-title">Item 1</span></a>
    <ul class="sub-menu">
      <li id="menu-item-4908" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4908">
        <a href="/subitem1/">SUBItem1</a>
      </li>
      <li id="menu-item-4892" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4892">
        <a href="/subitem2/">SUBItem2</a>
      </li>
    </ul>
  </li>
  <li id="menu-item-4794" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-4794">
    <a href="/item2/" aria-current="page" class="menu-image-title-after menu-image-not-hovered">
      <img width="1" height="1" src="https://staging.heuristic-hypatia.91-134-228-53.plesk.page/wp-content/uploads/2021/12/Plan-de-travail-1.svg" class="menu-image menu-image-title-after" alt="" loading="lazy">
      <span class="menu-image-title-after menu-image-title">Item 2</span>
    </a>
  </li>
</ul>

This assumes the User will click on all the menu-item elements and we want to do different things depending on their location in the hierarchy.

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, see the preventDefault() method. It also does not prevent immediate propagation to other event-handlers. If you want to stop those, see stopImmediatePropagation().

Update

You had a Style, display: table on your element. Removing this allows CSS to Show and Hide it as needed. Switching to .toggle() will do this.

Upvotes: 1

Related Questions