Home > Blockchain >  Close Dropdown Menu when clicking outside
Close Dropdown Menu when clicking outside

Time:04-04

The dropdown menu should open when the button is clicked.

And if you click outside the dropdown it should close again.

I tried this by adding an event listener to the body when the dropdown menu is active and then checking if the click happened outside the dropdown.

How can I write the following code without timeout function and make the dropdown close when clicked outside and not inside?

    <div >
      Open Dropdown

      <div >
        <a >Link Text</a>
        <a >Link Text</a>
        <a >Link Text</a>
        <a >Link Text</a>
      </div>
    </div>
.dropdown {
  position: relative;
  cursor: pointer;
  user-select: none;
  &__window {
    position: absolute;
    background: $background-alt;
    width: 100%;
    max-width: 260px;
    top: 45px;
    z-index: 12;
    overflow: hidden;
    display: none;
    visibility: hidden;
    &--active {
      display: block;
      visibility: visible;
    }
    > * {
      width: 100%;
      display: block;
      color: $white;
      white-space: nowrap;
      &:hover {
        background: $background;
        color: currentColor;
      }
    }
  }
}
let dropdownBtn = document.querySelectorAll('.dropdown__open')

dropdownBtn.forEach((el) => {
  let dropdownWindow = el.querySelector('.dropdown__window')

  el.addEventListener('click', function () {
    dropdownWindow.classList.toggle('dropdown__window--active')

    window.setTimeout(function () {
      if (dropdownWindow.classList.contains('dropdown__window--active')) {
        let clickListener = document.body.addEventListener(
          'click',
          function (event) {
            if (event.target.classList != 'dropdown__link') {
              dropdownWindow.classList.remove('dropdown__window--active')
              // Buggy clickListener.removeEventListener()
            }
          }
        )
      }
    }, 1000)
  })
})

OR https://codepen.io/Salala2/pen/RwxjOzW

CodePudding user response:

You can use the window.onclick. And if you don't want your dropdown to close when each of the dropdown items is clicked, you can specify that as a condition too.

const dropDownButton = document.querySelector('.dropdown__open')
const dropDownWindow = document.querySelector('.dropdown__window')

dropDownButton.addEventListener('click', 
   ()=> dropDownWindow.classList.toggle('dropdown__window--active'))

window.onclick = function(e){
   if (!e.target.matches('.dropdown__open') && 
         dropDownWindow.classList.contains('dropdown__window--active')){
       dropDownWindow.classList.remove('dropdown__window--active')
  }
}

CodePudding user response:

You can use onBlur(). But in order to do that you need to add tabindex="0" to the invoking element i.e the element which is invoking dropdown to display.

const dropdown = document.querySelector('.dropdown');
const dropdownWindow = document.querySelector('.dropdown__window')

dropdown.addEventListener('click', (event) => {
  dropdownWindow.classList.toggle('dropdown__window--active');
});

dropdown.addEventListener('blur', (event) => {
  dropdownWindow.classList.remove('dropdown__window--active');
});
.dropdown {
  position: relative;
  cursor: pointer;
  user-select: none;
  max-width: 260px;
}

.dropdown__window {
  position: absolute;
  background: #ccc;
  box-shadow: 0 10px 40px #1d2021;
  width: 100%;
  max-width: 260px;
  top: 45px;
  z-index: 12;
  overflow: hidden;
  display: none;
  visibility: hidden;
}

.dropdown__window--active {
  display: block;
  visibility: visible;
}

.dropdown__window>* {
  font-size: 14px;
  cursor: pointer;
  display: block;
  padding: 1rem 0 1rem 1rem;
  font-weight: 400;
  text-align: left;
  line-height: 1.42857143;
  color: #fff;
  white-space: nowrap;
}
<div  tabindex="0">
  Open Dropdown

  <div >
    <a >Link Text</a>
    <a >Link Text</a>
    <a >Link Text</a>
    <a >Link Text</a>
  </div>
</div>

CodePudding user response:

//Dropdowns
let dropdownBtn = document.querySelectorAll('.dropdown__open')[0]
let dropdownWindow = document.querySelector('.dropdown__window')

dropdownBtn.addEventListener('click', function (event) {
    dropdownWindow.classList.toggle('dropdown__window--active')
  })

    
  document.addEventListener('click', function(event) {
  var isClickInsideElement = dropdownBtn.contains(event.target);
   if (!isClickInsideElement) {
       dropdownWindow.classList.remove('dropdown__window--active')
    }
})

Try out this approach, hope it helps.

  • Related