Home > Enterprise >  Toggle menu by clicking anywhere on the screen
Toggle menu by clicking anywhere on the screen

Time:09-16

I want to close the custom drop-down menu when a user clicks anywhere on the screen but the JavaScript code is not working for that which I have written. I need little help to fix this issue.

I have written a JS code to fix this problem but it is not working properly, please take a look at this code. I have used the "classList.contains" in IF section to check whether the "toggle" class is present or not but it's not working.

const select = document.querySelectorAll('.selectBtn');
const hideList = document.querySelector('.selectDropdown');
const option = document.querySelectorAll('.option');
let index = 1;

select.forEach(a => {
    a.addEventListener('click', b => {
        const next = b.target.nextElementSibling;
        next.classList.toggle('toggle');
        next.style.zIndex = index  ;
    })
})

option.forEach(a => {
    a.addEventListener('click', b => {
        b.target.parentElement.classList.remove('toggle');
        const parent = b.target.closest('.select').children[0];
        parent.setAttribute('data-type', b.target.getAttribute('data-type'));
        parent.innerText = b.target.innerText;
    })
})


/*------ This Code Is Not Working ------*//*

if (hideList.classList.contains('toggle')) {

  document.addEventListener('click', ()=> {
    hideList.classList.remove('toggle');
  });

}else {

  document.addEventListener('click', ()=> {
    hideList.classList.add('toggle');
  });
  
}

/*------ This Code Is Not Working ------*/
.select {
  position: relative;
  margin-bottom: 15px;
  width: 200px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.select .selectBtn {
  background: var(--bg1);
  padding: 10px;
  box-sizing: border-box;
  border-radius: 3px;
  width: 100%;
  cursor: pointer;
  position: relative;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  background: #fff;
}
.select .selectBtn:after {
  content: "";
  position: absolute;
  top: 45%;
  right: 15px;
  width: 6px;
  height: 6px;
  -webkit-transform: translateY(-50%) rotate(45deg);
          transform: translateY(-50%) rotate(45deg);
  border-right: 2px solid #666;
  border-bottom: 2px solid #666;
  transition: 0.2s ease;
}
.select .selectBtn.toggle {
  border-radius: 3px 3px 0 0;
}
.select .selectBtn.toggle:after {
  -webkit-transform: translateY(-50%) rotate(-135deg);
          transform: translateY(-50%) rotate(-135deg);
}
.select .selectDropdown {
  position: absolute;
  top: 100%;
  width: 100%;
  border-radius: 0 0 3px 3px;
  overflow: hidden;
  background: var(--bg1);
  border-top: 1px solid #eee;
  z-index: 1;
  background: #fff;
  -webkit-transform: scale(1, 0);
          transform: scale(1, 0);
  -webkit-transform-origin: top center;
          transform-origin: top center;
  visibility: hidden;
  transition: 0.2s ease;
  box-shadow: 0 3px 3px rgba(0, 0, 0, 0.2);
}
.select .selectDropdown .option {
  padding: 10px;
  box-sizing: border-box;
  cursor: pointer;
}
.select .selectDropdown .option:hover {
  background: #f8f8f8;
}
.select .selectDropdown.toggle {
  visibility: visible;
  -webkit-transform: scale(1, 1);
          transform: scale(1, 1);
}
  <div >
    <div  data-type="filter">Filter</div>
      <div >
        <div  data-type="firstOption">First option</div>
        <div  data-type="secondOption">Second option</div>
        <div  data-type="thirdOption">Third option</div>
        <div  data-type="fourthOption">Fourth option</div>
        <div  data-type="fifthOption">Fifth option</div>
      </div>
  </div>

CodePudding user response:

I've made a couple of changes to the following script, which I believe works as intended.

const select = document.querySelectorAll('.selectBtn');
const hideList = document.querySelector('.selectDropdown');
const option = document.querySelectorAll('.option');
let index = 1;

select.forEach(a => {
  a.addEventListener('click', (b) => {

    //Add stopPropagation to prevent the second click of the  select dropdown
    b.stopPropagation();
    
    const next = b.target.nextElementSibling;
    next.classList.toggle('toggle');
    next.style.zIndex = index  ;
  })
})

option.forEach(a => {
  a.addEventListener('click', b => {
    b.target.parentElement.classList.remove('toggle');
    const parent = b.target.closest('.select').children[0];
    parent.setAttribute('data-type', b.target.getAttribute('data-type'));
    parent.innerText = b.target.innerText;
  })
})

// Click the body element and if the select dropdown has the toggle class set, remove it
document.body.addEventListener('click', () => {
  if (hideList.classList.contains('toggle')) {
    hideList.classList.remove('toggle');
  }
});

Essentially all I've done is add stopPropagation to the event for the select click listener to prevent the second click.

Then, swapped out your "This Code Is Not Working" block for a simple click anywhere on the body element.

CodePudding user response:

This does it. Check to see if the element you're clicking on to trigger the toggle class has the class of "selectBtn". If it doesn't have that class, then you can close the dropdown by removing to "toggle" class from hideList.

const select = document.querySelectorAll('.selectBtn');
    const hideList = document.querySelector('.selectDropdown');
    const option = document.querySelectorAll('.option');
    let index = 1;

    select.forEach(a => {
        a.addEventListener('click', b => {
            const next = b.target.nextElementSibling;
            next.classList.toggle('toggle');
            next.style.zIndex = index  ;
        })
    })

    option.forEach(a => {
        a.addEventListener('click', b => {
            b.target.parentElement.classList.remove('toggle');
            const parent = b.target.closest('.select').children[0];
            parent.setAttribute('data-type', b.target.getAttribute('data-type'));
            parent.innerText = b.target.innerText;
        })
    })

 
  document.addEventListener("click", (e)=> {
     if (hideList.classList.contains("toggle"))  {
      if ( !e.target.classList.contains("selectBtn") ) {
        console.log("you're clicking outside the dropdown");
        hideList.classList.remove("toggle");
      }
     } 
  });
.select {
      position: relative;
      margin-bottom: 15px;
      width: 200px;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }
    .select .selectBtn {
      background: var(--bg1);
      padding: 10px;
      box-sizing: border-box;
      border-radius: 3px;
      width: 100%;
      cursor: pointer;
      position: relative;
      -webkit-user-select: none;
         -moz-user-select: none;
          -ms-user-select: none;
              user-select: none;
      background: #fff;
    }
    .select .selectBtn:after {
      content: "";
      position: absolute;
      top: 45%;
      right: 15px;
      width: 6px;
      height: 6px;
      -webkit-transform: translateY(-50%) rotate(45deg);
              transform: translateY(-50%) rotate(45deg);
      border-right: 2px solid #666;
      border-bottom: 2px solid #666;
      transition: 0.2s ease;
    }
    .select .selectBtn.toggle {
      border-radius: 3px 3px 0 0;
    }
    .select .selectBtn.toggle:after {
      -webkit-transform: translateY(-50%) rotate(-135deg);
              transform: translateY(-50%) rotate(-135deg);
    }
    .select .selectDropdown {
      position: absolute;
      top: 100%;
      width: 100%;
      border-radius: 0 0 3px 3px;
      overflow: hidden;
      background: var(--bg1);
      border-top: 1px solid #eee;
      z-index: 1;
      background: #fff;
      -webkit-transform: scale(1, 0);
              transform: scale(1, 0);
      -webkit-transform-origin: top center;
              transform-origin: top center;
      visibility: hidden;
      transition: 0.2s ease;
      box-shadow: 0 3px 3px rgba(0, 0, 0, 0.2);
    }
    .select .selectDropdown .option {
      padding: 10px;
      box-sizing: border-box;
      cursor: pointer;
    }
    .select .selectDropdown .option:hover {
      background: #f8f8f8;
    }
    .select .selectDropdown.toggle {
      visibility: visible;
      -webkit-transform: scale(1, 1);
              transform: scale(1, 1);
    }
    <div  id="select-wrap">
        <div  data-type="filter" id="select-wrap">Filter</div>
          <div >
            <div  data-type="firstOption">First option</div>
            <div  data-type="secondOption">Second option</div>
            <div  data-type="thirdOption">Third option</div>
            <div  data-type="fourthOption">Fourth option</div>
            <div  data-type="fifthOption">Fifth option</div>
          </div>
      </div>

  • Related