Archi Patel
Archi Patel

Reputation: 173

Clickable dropdown menu should not close when clicking inside menu list

I'm making clickable dropdown menu so

  1. when user clicks on green dropdown menu button, menu will open
  2. and when user clicks again on green button, menu will close.
  3. but when dropdown menu is open and user clicks outside of dropdown menu anywhere on page, menu will again close.

I have setup all this 3 steps and working fine but I want is, when dropdown menu is open, and user clicks inside menu area (red background color area) then menu should NOT CLOSE. I need ONLY JAVASCRIPT CODE FOR SAME. Even if you can do it with total new JAVASCRIPT code it will be helpful.

/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {

    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}
.dropbtn {
  background-color: #4CAF50;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  overflow: auto;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown a:hover {
  background-color: #f1f1f1
}

.show {
  display: block;
}
<p>Click on the button to open the dropdown menu.</p>
<p>when click here menu will close</p>

<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content" style="background:red;">
    <p>when click here menu should not close</p>
    <div id="test1">
      <p>when click here menu should not close</p>
    </div>
    <div id="test2">
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
    </div>
  </div>
</div>
<p>when click here menu will close</p>

Upvotes: 2

Views: 2496

Answers (2)

Roko C. Buljan
Roko C. Buljan

Reputation: 206121

That's the smallest JavaScript I could come up with... ;-)

.dropdown {
  position: relative;
  display: inline-block;
  outline: none;            /* add */
}

.dropbtn {
  background-color: #4CAF50;
  color: white;
  padding: 16px;
  cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
  background-color: #3e8e41;
}

.dropdown .dropdown-content {
  position: absolute;
  top:100%;            /* add */
  background-color: #f9f9f9;
  min-width: 160px;
  overflow: auto;
  box-shadow: 0px 8px 16px rgba(0,0,0, 0.2);
  
  transition: 0.3s;    /* add */
  visibility: hidden;  /* add */
  opacity:0;           /* add */
}

.dropdown:focus .dropdown-content { /* add all */
  outline: none;
  visibility: visible;
  opacity:1;
  transform: translateY(10px);
}
<p>Click on the button to open the dropdown menu.</p>

<div class="dropdown" tabindex="1"> <!-- set tabindex -->
  <a class="dropbtn">Dropdown</a> <!-- Don't use Button -->
  <div class="dropdown-content">
    <p>when click here menu should not close</p>
    <div id="test1">
      <p>when click here menu should not close</p>
    </div>
    <div id="test2">
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
    </div>
  </div>
</div>

Ups!.. there's no JS at all
So basically use tabindex, don't use <button> and use the CSS :focus

Upvotes: 1

VTr
VTr

Reputation: 718

You just add click event on your dropdown and stop the propagation to prevent event bubble up to window. So, when use click in the dropdown, the window object never catch click event.

// Prevent event bubble up to window.
document.getElementById("myDropdown").addEventListener('click', function (event) {
    event.stopPropagation();
});

// Inline event also working well, if you prefer this style.
<div id="myDropdown" onclick="event.stopPropagation()" class="dropdown-content" style="background:red;">

/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction() {
    document.getElementById("myDropdown").classList.toggle("show");
}

// Prevent event bubble up to window.
document.getElementById("myDropdown").addEventListener('click', function (event) {
  event.stopPropagation();
});

// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {

    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}
.dropbtn {
    background-color: #4CAF50;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
}

.dropbtn:hover, .dropbtn:focus {
    background-color: #3e8e41;
}

.dropdown {
    position: relative;
    display: inline-block;
}

.dropdown-content {
    display: none;
    position: absolute;
    background-color: #f9f9f9;
    min-width: 160px;
    overflow: auto;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}

.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}

.dropdown a:hover {background-color: #f1f1f1}

.show {display:block;}
<p>Click on the button to open the dropdown menu.</p>
<p>when click here menu will close</p>
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content" style="background:red;">
    
    <p>when click here menu should not close</p>
    <div id="test1">
      <p>when click here menu should not close</p>
    </div>
    <div id="test2">
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
      <div id="subtest1">
        <p>when click here menu should not close</p>
      </div>
    </div>
  </div>
</div>
<p>when click here menu will close</p>

Upvotes: 1

Related Questions