0

I create a website that is not using jquery library just plain javascript.

Most of the users have low internet bandwidth and I try to keep it as clean as possible.

I'm using just few functions and that's why I decided not to use jquery.

I have created this collapsing menu that opens and close the container when user clicks on it. I want also to close it when the user clicks outside of it. I am not so experienced with javascript and if someone can give some idea I would really appreciate it.

Thank you

function myFunction() {
    var x = document.getElementById("Demo");
    if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
    } else { 
        x.className = x.className.replace(" w3-show", "");
    }
}
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet"/>
<div class="w3-container">
  <h2>Clickable Dropdown</h2>
  <p>Click on the button to open the dropdown menu.</p>
  <div class="w3-dropdown-click">
    <button onclick="myFunction()" class="w3-button w3-black">Click Me!</button>
    <div id="Demo" class="w3-dropdown-content w3-bar-block w3-border">
      <a href="#" class="w3-bar-item w3-button">Link 1</a>
      <a href="#" class="w3-bar-item w3-button">Link 2</a>
      <a href="#" class="w3-bar-item w3-button">Link 3</a>
    </div>
  </div>
</div>
John
  • 13
  • 5
  • http://stackoverflow.com/questions/152975/how-do-i-detect-a-click-outside-an-element – scraaappy Apr 11 '17 at 21:19
  • You can simplify your logic using [Element.classList](https://developer.mozilla.org/en/docs/Web/API/Element/classList). – Mikey Apr 11 '17 at 21:27

1 Answers1

0

To detect click outside of the element you need to catch clicks on body itself:

function myFunction(t) {
    var x = document.getElementById("Demo");
    if (t && x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
    } else { 
        x.className = x.className.replace(" w3-show", "");
    }
    event.stopPropagation();
}
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet"/>
<body onclick="myFunction()">
<div class="w3-container">
  <h2>Clickable Dropdown</h2>
  <p>Click on the button to open the dropdown menu.</p>
  <div class="w3-dropdown-click">
    <button onclick="myFunction(true)" class="w3-button w3-black">Click Me!</button>
    <div id="Demo" class="w3-dropdown-content w3-bar-block w3-border">
      <a href="#" class="w3-bar-item w3-button">Link 1</a>
      <a href="#" class="w3-bar-item w3-button">Link 2</a>
      <a href="#" class="w3-bar-item w3-button">Link 3</a>
    </div>
  </div>
</div>
</body>

Note: I've introduced argument "T" to indicate whether I want to "toggle" menu or hide it always.

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
  • did you intend for this to close when you clicked on a submenu option? – larz Apr 11 '17 at 21:26
  • @larz it is because of event propagation, you can disable it – Iłya Bursov Apr 11 '17 at 21:29
  • @Lashane Thank you it works and accepted your answer – John Apr 11 '17 at 21:38
  • @Lashane after I tested the solution you suggested I got other functions not working. I read this https://css-tricks.com/dangers-stopping-event-propagation/ and it seems to be not a good practice to stop event propagation – John Apr 12 '17 at 08:54
  • @John solution is to detect click on body, event propagation is another problem, declare global handler and detect clicks in it – Iłya Bursov Apr 12 '17 at 14:18