简体   繁体   中英

Submenu does not work as I want

I have a problem with my submenu. The submenu reacts on click, but I have a problem, that I click on submenu <li> , content is removed and I don't want this. And is there any error with that, it write this error "Uncaught TypeError: Cannot read property 'classList' of null".

Can help me someone?

 /* Added .main class to parent <ul> || By adding the eventListener to the || parent of multiple clickable nodes || and using e.target property to find || the exact node actually clicked, we || have just needed the <ul> to listen || rather than 3 separate <li> || This is part of Event Delagation */ var main = document.querySelector('.main'); main.addEventListener('click', accordion, false); function accordion(e) { // Stop <a> from jumping e.preventDefault(); /* Gather all .dropdown-menu to a NodeList || then covert it to an array */ var dropArray = Array.from(document.querySelectorAll('.dropdown-menu')); /* if the clicked node (e.target) is NOT the || node listening for event (e.currentTarget || ul.main) then... */ if (e.target !== e.currentTarget) { /* Assign e.target to var || Find tgr next sibling (.dropdown-menu) || Iterate through dropArray wth a || for...of loop || Remove .show and add .hide on || each .dropdown-menu in dropArray || Then add .show and remove .hide || on tgt || Finally stop the click event from || bubbling, thereby preventing anything || else from being triggered. */ var tgr = e.target; var tgt = tgr.nextElementSibling; for (let drop of dropArray) { drop.classList.remove('show'); drop.classList.add('hide'); } tgt.classList.add('show'); tgt.classList.remove('hide'); } e.stopPropagation(); } 
 ul { list-style: none } .dropdown a { text-decoration: none; } .dropdown [data-toggle="dropdown"] { position: relative; display: block; color: black; padding: 10px; } .dropdown .dropdown-menu { max-height: 0; overflow: hidden; } .dropdown .dropdown-menu li { padding: 0; } .dropdown .dropdown-menu li a { display: block; padding: 10px 10px; } .dropdown .show { display: block; max-height: 9999px; margin-left: 50px; } .dropdown .hide { max-height: 0; } 
 <div class="container"> <ul class='main'> <li class="dropdown"> <a href="#" data-toggle="dropdown">First Menu</a> <ul class="dropdown-menu"> <li><a href="#">Home</a></li> <li><a href="#">About Us</a></li> <li><a href="#">Services</a></li> <li><a href="#">Contact</a></li> </ul> </li> <li class="dropdown"> <a href="#" data-toggle="dropdown">Second Menu</a> <ul class="dropdown-menu"> <li><a href="#">Home</a></li> <li><a href="#">About Us</a></li> <li><a href="#">Services</a></li> <li><a href="#">Contact</a></li> </ul> </li> <li class="dropdown"> <a href="#" data-toggle="dropdown">Third Menu </a> <ul class="dropdown-menu"> <li><a href="#">Home</a></li> <li><a href="#">About Us</a></li> <li><a href="#">Services</a></li> <li><a href="#">Contact</a></li> </ul> </li> </ul> </div> 

That is because 'tgt' ends up being null when you click on the leaves. You should check for this to avoid the error:

if (tgt) {
    for (let drop of dropArray) {
      drop.classList.remove('show');
      drop.classList.add('hide');
    }
    tgt.classList.add('show');
    tgt.classList.remove('hide');
}

If you don't want the submenu to be closed after picking subitem:

function accordion(e) {
  e.preventDefault();    
  if (e.target.tagName === 'A' && e.target !== e.currentTarget) { 
    var dropArray = Array.from(document.querySelectorAll('.dropdown-menu'));
    var tgt = e.target.nextElementSibling;
    if(tgt) {
      for (let drop of dropArray) {
        drop.classList.remove('show');
      }
      tgt.classList.add('show');
      tgt.classList.remove('hide');
    }
  }
  e.stopPropagation();
}

This also fixes "Cannot read property 'classList' of null" error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM