Is there a Javascript function to capture mouse click?

Asked

Viewed 351 times

2

This is my first post and I have a question. I am working on a dropdown menu that acts based on user click. This way, when clicking on one of the menu items, it descends presenting more information, and when you click again it is closed (the codes are at the end of the post).


1: The first problem is that I want the menu to be closed by clicking anywhere on the page, and not just by clicking again on the menu button. So he wanted some function that captured the mouse click on the page. I don’t know if that’s the best solution, if not, let me know how I can do it.

2: The other problem would be the fact that the dropdown menu that is inserted in the first menu item and only works after the first click, that is, only subsequent clicks cause it to close and open the menu correctly. What I thought was that Javascript with the variable that captures the information is not updating until the moment of the first click, so it only works from the second. I don’t know if I’m right, I looked for a way to execute the code only when everything was loaded, I got to the function document.onload(), but it didn’t work for me. I don’t know if I made a mistake or if that wasn’t the solution. Anyway, these are my two doubts. I will thank you very much if someone can help, it will greatly enhance my learning.

var elem = document.getElementsByClassName('sub-menu');

function fclick(){
  if(elem[0].style.display == "none"){
      elem[0].style.display = "block";
  }else{
      elem[0].style.display = "none";
  }
}
*{color: #fff; margin: 0; padding: 0;}
body{background-color: #f5f5f5;}
a{text-decoration: none;}
li{list-style: none;}

#navbar{
  background-color: #2C353B;
  height: 3em;
}
.menu{
  display: block;
}

.menu li{
  float: left;
  padding: 13px 10px;
}

.sub-menu{
  position: absolute;
  display: none;
  top: 47px;
  left: 0;
}

.sub-menu li{
  float: none;
  padding: 13px 10px;
  background-color: #2C353B;
}
<!DOCTYPE html>
<html lang="pt-BR" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="style.css">
    <title>clickable-menu</title>
  </head>
  <body>
    <nav id="navbar">
      <ul class="menu">
      <li>
        <a href="#" onclick="fclick()">Some-item</a>
        <ul class="sub-menu">
          <li><a href="#">Some-item</a></li>
          <li><a href="#">Some-item</a></li>
          <li><a href="#">Some-item</a></li>
        </ul>
      </li>
      <li><a href="#">Some-item</a></li>
      <li><a href="#">Some-item</a></li>
      </ul>
    </nav>
    <script type="text/javascript" src="script.js"></script>
  </body>
</html>

1 answer

1


At setting display: none in CSS, it does not mean that the element has this property in Javascript. CSS does not change the properties of the element, it just changes or defines the visual behavior. So, at the first click, the if assumes the else and changes the property style.display for none; in the second click, there you will be with none and starts to work.

How the element starts with the property style.display empty, just insert one more condition into the if checking whether, in addition to being none, the display is empty:

if(elem[0].style.display == "none" || !elem[0].style.display){

To close the submenu by clicking anywhere on the page, simply create a Event Handler for the object document, which is the whole document:

document.onclick = function(){

   elem[0].style.display = "none";

}

But we also need to cancel the Bubbling by clicking on the menu item that opens the submenu, as it is also part of the document. For this you need to pass the event when calling the function in the onclick and use event.stopPropagation();. Include the term event as a function argument:

onclick="fclick(event)"

And in function you use:

function fclick(event){

   event.stopPropagation();
   // resto do código
}

Everything will be like this:

var elem = document.getElementsByClassName('sub-menu');

function fclick(event){

   event.stopPropagation();

   if(elem[0].style.display == "none" || !elem[0].style.display){
      elem[0].style.display = "block";
   }else{
      elem[0].style.display = "none";
   }
}

document.onclick = function(){
   
   elem[0].style.display = "none";
   
}
*{color: #fff; margin: 0; padding: 0;}
body{background-color: #f5f5f5;}
a{text-decoration: none;}
li{list-style: none;}

#navbar{
  background-color: #2C353B;
  height: 3em;
}
.menu{
  display: block;
}

.menu li{
  float: left;
  padding: 13px 10px;
}

.sub-menu{
  position: absolute;
  display: none;
  top: 47px;
  left: 0;
}

.sub-menu li{
  float: none;
  padding: 13px 10px;
  background-color: #2C353B;
}
<nav id="navbar">
<ul class="menu">
<li>
  <a href="#" onclick="fclick(event)">Some-item</a>
  <ul class="sub-menu">
    <li><a href="#">Some-item</a></li>
    <li><a href="#">Some-item</a></li>
    <li><a href="#">Some-item</a></li>
  </ul>
</li>
<li><a href="#">Some-item</a></li>
<li><a href="#">Some-item</a></li>
</ul>
</nav>

  • Very good, I could understand, so even though I can manipulate the css by javascript, it doesn’t mean that it already has the feature that I’m changing by default changed, I need to flag this in the code, very cool, I didn’t know these details, your reply was very conclusive, I will take advantage and study on these details you mentioned mainly on the function stopPropagation() that I did not know, very grateful now I can re-edit and improve my code.

  • Cool! But it’s the other way around: CSS cannot change element properties, Javascript can.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.