skip to Main Content

I want dropdown list to disappear when mouse leaves #navbarHint div element.

let flag2 = true;

document.getElementById('navbarHint').addEventListener('mouseleave',
  function() {
    flag2 = false;
    menuClick();
  });

document.getElementById('navbtn').addEventListener('click', menuClick);

function menuClick() {
  let menu = document.querySelector('.dropdown:hover .dropdown-content');
  if (flag2) {
    menu.style.visibility = 'visible';
    flag2 = false
  } else {
    menu.style.visibility = 'hidden';
    flag2 = true;
  }
}
#navbarHint {
  position: absolute;
  height: 8rem;
  width: 100%;
  z-index: 3;
  background-color: grey;
}

.dropdown-content {
  right: 0;
  visibility: hidden;
  position: absolute;
  background-color: #000000;
  min-width: max-content;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  transform: translateX(-3rem) translateY(2.5rem);
  z-index: 2;
}

.dropdown-content p {
  margin-inline: 0.25rem;
  margin-block: 0.5rem;
}

#navbtn {
  width: 3rem;
  height: 3rem;
  z-index: 2;
  background-color: red;
  position: absolute;
  right: 1rem;
  top: 1rem;
  cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>Hello, world!</title>
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <meta name="description" content="" />
</head>

<body>
  <div id="navbarHint">
    <div id="navbtn" class="dropdown">
      <div class="dropdown-content">
        <p>Hello World!</p>
      </div>
    </div>
  </div>
</body>

</html>

So the list should disappear when I leave certain area on the page. But it doesn’t. It raises Uncaught TypeError: Cannot read properties of null (reading 'style') exception, although it works perfectly when menuClick function is called from click event. For some reason it does matter which event is calling the function.

I also tried this with document.getElementById('navbtn').addEventListener('mouseleave', menuClick); – and it doesn’t work as well.

2

Answers


  1. As I already suspected in the comment this is a conflict between the :hover selector and the area you attached mouseleave to. The leave event fires when wou leave navbarHint but by that time you are no longer hovering over .dropdown so document.querySelector('.dropdown:hover .dropdown-content')returns null resulting in Uncaught TypeError: Cannot read properties of null (reading 'style').

    Try removing :hover or if it’s required please explain why.

    let flag2 = true;
    
    document.getElementById('navbarHint').addEventListener('mouseleave',
      function() {
        flag2 = false;
        menuClick();
      });
    
    document.getElementById('navbtn').addEventListener('click', menuClick);
    
    function menuClick() {
      let menu = document.querySelector('.dropdown .dropdown-content');
      if (flag2) {
        menu.style.visibility = 'visible';
        flag2 = false
      } else {
        menu.style.visibility = 'hidden';
        flag2 = true;
      }
    }
    #navbarHint {
      position: absolute;
      height: 8rem;
      width: 100%;
      z-index: 3;
      background-color: grey;
    }
    
    .dropdown-content {
      right: 0;
      visibility: hidden;
      position: absolute;
      background-color: #000000;
      min-width: max-content;
      box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
      transform: translateX(-3rem) translateY(2.5rem);
      z-index: 2;
    }
    
    .dropdown-content p {
      margin-inline: 0.25rem;
      margin-block: 0.5rem;
    }
    
    #navbtn {
      width: 3rem;
      height: 3rem;
      z-index: 2;
      background-color: red;
      position: absolute;
      right: 1rem;
      top: 1rem;
      cursor: pointer;
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <title>Hello, world!</title>
      <meta name="viewport" content="width=device-width,initial-scale=1" />
      <meta name="description" content="" />
    </head>
    
    <body>
      <div id="navbarHint">
        <div id="navbtn" class="dropdown">
          <div class="dropdown-content">
            <p>Hello World!</p>
          </div>
        </div>
      </div>
    </body>
    
    </html>
    Login or Signup to reply.
  2. Replace your js with below. The function menuClick takes an argument – the event – from which you can access the target element you wish to hide:

    let flag2 = true;
    
    function init() {
      document.getElementById('navbarHint').addEventListener('mouseleave', 
      (ev) => { 
          flag2 = false;
          menuClick(ev);
      });
      
      document.getElementById('navbtn').addEventListener('click', (ev) => menuClick(ev));
     
    }
    
    function menuClick(ev)
    {
        const content = ev.target.querySelector('.dropdown .dropdown-content');
        console.log(content);
        if (flag2)
        {
            content.style.visibility = 'visible';
            flag2 = false
        }
        else
        {
            content.style.visibility = 'hidden';
            flag2 = true;
        }
    }
    
    init();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search