Home > Net >  How to remove dropdown when clicking out of the dropdown on the body?
How to remove dropdown when clicking out of the dropdown on the body?

Time:06-05

I want it when dropdown.menu has a "show" class when clicked anywhere in the body or window, dropdown.menu.show miss the show class. The show class is added and removed before using the code (window.onclick = function (event){}), but when I add this code to the end of the JavaScript code, the show class is not added at all. Thank you in advance for your cooperation.

function toggleClass(elem, className) {
  if (elem.className.indexOf(className) !== -1) {
    elem.className = elem.className.replace(className, '');
  } else {
    elem.className = elem.className.replace(/\s /g, ' ')   ' '   className;
  }

  return elem;
}

function toggleDisplay(elem) {
  const curDisplayStyle = elem.style.display;

  if (curDisplayStyle === 'none' || curDisplayStyle === '') {
    elem.style.display = 'block';
  } else {
    elem.style.display = 'none';
  }
}

function toggleMenuDisplay(e) {
  const dropdown = e.currentTarget.parentNode;
  const menu = dropdown.querySelector('.menu');
  toggleClass(menu, 'show');
}

function handleOptionSelected(e) {
  toggleClass(e.target.parentNode, 'show');
  const id = e.target.id;
  const newValue = e.target.textContent   ' ';
  const titleElem = document.querySelector('.dropdown .dropdown--title');
  titleElem.textContent = newValue;
}


const dropdownTitle = document.querySelector('.dropdown .dropdown--title');
const dropdownOptions = document.querySelectorAll('.dropdown .menu.categories a');
dropdownTitle.addEventListener('click', toggleMenuDisplay);
dropdownOptions.forEach(item => item.addEventListener('click', handleOptionSelected));

//this section is not work!!!
window.onclick = function(event) {
  const titleElem = document.querySelector('.dropdown .dropdown--title');

  const menu = document.querySelector('.menu');
  if (!(event.target == titleElem.nextElementSibling.classList.contains('show'))) {
    titleElem.nextElementSibling.classList.remove('show');
  }
}
.dropdown {
  position: relative;
}

.dropdown::before {
  content: " ";
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  top: 15px;
  right: 0;
  color: var(--cbl);
}

.dropdown .dropdown--title {
  padding: 0.75rem;
  width: 100%;
  cursor: pointer;
}

.dropdown .menu {
  cursor: pointer;
  max-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: absolute;
  z-index: 12;
  width: 100%;
  top: 45px;
  right: 0;
  background-color: var(--cwh);
  transition: max-height 0.3s;
  -webkit-transition: max-height 0.3s;
  -moz-transition: max-height 0.3s;
  -ms-transition: max-height 0.3s;
  -o-transition: max-height 0.3s;
  box-shadow: 0 3px 20px #ccc;
  -webkit-box-shadow: 0 3px 20px #ccc;
  -moz-box-shadow: 0 3px 20px #ccc;
}

.dropdown .menu.show {
  max-height: 20em !important;
}

.dropdown .menu.show a {
  color: var(--cbl);
  opacity: 1;
  transition: all 0.3s;
  -webkit-transition: all 0.3s;
  -moz-transition: all 0.3s;
  -ms-transition: all 0.3s;
  -o-transition: all 0.3s;
  transform: translateX(0);
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
}

.dropdown .menu a {
  padding: 1rem;
  opacity: 0;
  color: var(--cbl);
  transform: translateX(100%);
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  -o-transform: translateX(100%);
}

.dropdown .menu a:nth-child(1) {
  transition-delay: 0.2s;
}

.dropdown .menu a:nth-child(2) {
  transition-delay: 0.15s;
}

.dropdown .menu a:nth-child(3) {
  transition-delay: 0.1s;
}

.dropdown .menu a:nth-child(4) {
  transition-delay: 0.05s;
}

.dropdown .menu a:nth-child(5) {
  transition-delay: 0s;
}

.dropdown .menu a:not(:last-child) {
  border-bottom: 1px solid var(--cblo40);
}

.dropdown .menu a:hover {
  background: rgba(0, 0, 0, 0.2);
}
<div >
  <div >Choose category</div>
  <div >
    <a href="#" data-category="[15,16,26,27]" >All</a>
    <a href="http://localhost/discount/product-category/other/" data-category="15">Other</a>
    <a href="http://localhost/discount/product-category/electronics/" data-category="16">Electronics</a>
    <a href="http://localhost/discount/product-category/sports/" data-category="26">Sports</a>
    <a href="http://localhost/discount/product-category/toys/" data-category="27">Toys &amp; Games</a>
  </div>
</div>

CodePudding user response:

I have used jquery with this it becomes easy to handle the dom. Rest all (html, css) remain same.

$(document).ready(function() {
  $(document).on('click', function() {
    $('.categories.menu').toggleClass('show');
  });
});
.dropdown {
  position: relative;
}

.dropdown::before {
  content: " ";
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  top: 15px;
  right: 0;
  color: var(--cbl);
}

.dropdown .dropdown--title {
  padding: 0.75rem;
  width: 100%;
  cursor: pointer;
}

.dropdown .menu {
  cursor: pointer;
  max-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: absolute;
  z-index: 12;
  width: 100%;
  top: 45px;
  right: 0;
  background-color: var(--cwh);
  transition: max-height 0.3s;
  -webkit-transition: max-height 0.3s;
  -moz-transition: max-height 0.3s;
  -ms-transition: max-height 0.3s;
  -o-transition: max-height 0.3s;
  box-shadow: 0 3px 20px #ccc;
  -webkit-box-shadow: 0 3px 20px #ccc;
  -moz-box-shadow: 0 3px 20px #ccc;
}

.dropdown .menu.show {
  max-height: 20em !important;
}

.dropdown .menu.show a {
  color: var(--cbl);
  opacity: 1;
  transition: all 0.3s;
  -webkit-transition: all 0.3s;
  -moz-transition: all 0.3s;
  -ms-transition: all 0.3s;
  -o-transition: all 0.3s;
  transform: translateX(0);
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
}

.dropdown .menu a {
  padding: 1rem;
  opacity: 0;
  color: var(--cbl);
  transform: translateX(100%);
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  -o-transform: translateX(100%);
}

.dropdown .menu a:nth-child(1) {
  transition-delay: 0.2s;
}

.dropdown .menu a:nth-child(2) {
  transition-delay: 0.15s;
}

.dropdown .menu a:nth-child(3) {
  transition-delay: 0.1s;
}

.dropdown .menu a:nth-child(4) {
  transition-delay: 0.05s;
}

.dropdown .menu a:nth-child(5) {
  transition-delay: 0s;
}

.dropdown .menu a:not(:last-child) {
  border-bottom: 1px solid var(--cblo40);
}

.dropdown .menu a:hover {
  background: rgba(0, 0, 0, 0.2);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <div >Choose category</div>
  <div >
    <a href="#" data-category="[15,16,26,27]" >All</a>
    <a href="http://localhost/discount/product-category/other/" data-category="15">Other</a>
    <a href="http://localhost/discount/product-category/electronics/" data-category="16">Electronics</a>
    <a href="http://localhost/discount/product-category/sports/" data-category="26">Sports</a>
    <a href="http://localhost/discount/product-category/toys/" data-category="27">Toys &amp; Games</a>
  </div>
</div>

CodePudding user response:

I added a new attribute data-before to the dropdown element and made reference to it from the css part content: attr(data-before);

      function toggleClass(elem, className) {
        if (elem.className.indexOf(className) !== -1) {
          elem.className = elem.className.replace(className, "");
        } else {
          elem.className = elem.className.replace(/\s /g, " ")   " "   className;
        }
        return elem;
      }

      function toggleDisplay(elem) {
        const curDisplayStyle = elem.style.display;
        if (curDisplayStyle === "none" || curDisplayStyle === "") {
          elem.style.display = "block";
        } else {
          elem.style.display = "none";
        }
      }

      function toggleMenuDisplay(e) {
        const dropdown = e.currentTarget.parentNode;
        const menu = dropdown.querySelector(".menu");
        menu.classList.toggle("show");
        menu.classList.contains("show")
          ? dropdown.setAttribute("data-before", "-")
          : dropdown.setAttribute("data-before", " ");
      }

      function handleOptionSelected(e) {
        //toggleClass(e.target.parentNode, "show");
        const id = e.target.id;
        const newValue = e.target.textContent   " ";
        const titleElem = document.querySelector(".dropdown .dropdown--title");
        titleElem.textContent = newValue;
      }

      const dropdownTitle = document.querySelector(".dropdown .dropdown--title");
      const dropdownOptions = document.querySelectorAll(".dropdown .menu.categories a");
      dropdownTitle.addEventListener("click", toggleMenuDisplay);
      dropdownOptions.forEach((item) => item.addEventListener("click", handleOptionSelected));

      document.onclick = function (event) {
      
        if (document.getElementsByClassName("categories menu show").length == 1 && event.target.localName !== "div") {
          document.querySelector(".categories.menu").classList.toggle("show");
          document.querySelector(".dropdown").setAttribute("data-before", " ");
        }
      };
.dropdown {
  position: relative;
}

.dropdown::before {
  content: attr(data-before);
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  top: 15px;
  right: 0;
  color: var(--cbl);
}

.dropdown .dropdown--title {
  padding: 0.75rem;
  width: 100%;
  cursor: pointer;
}

.dropdown .menu {
  cursor: pointer;
  max-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: absolute;
  z-index: 12;
  width: 100%;
  top: 45px;
  right: 0;
  background-color: var(--cwh);
  transition: max-height 0.3s;
  -webkit-transition: max-height 0.3s;
  -moz-transition: max-height 0.3s;
  -ms-transition: max-height 0.3s;
  -o-transition: max-height 0.3s;
  box-shadow: 0 3px 20px #ccc;
  -webkit-box-shadow: 0 3px 20px #ccc;
  -moz-box-shadow: 0 3px 20px #ccc;
}

.dropdown .menu.show {
  max-height: 20em !important;
}

.dropdown .menu.show a {
  color: var(--cbl);
  opacity: 1;
  transition: all 0.3s;
  -webkit-transition: all 0.3s;
  -moz-transition: all 0.3s;
  -ms-transition: all 0.3s;
  -o-transition: all 0.3s;
  transform: translateX(0);
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
}

.dropdown .menu a {
  padding: 1rem;
  opacity: 0;
  color: var(--cbl);
  transform: translateX(100%);
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  -o-transform: translateX(100%);
}

.dropdown .menu a:nth-child(1) {
  transition-delay: 0.2s;
}

.dropdown .menu a:nth-child(2) {
  transition-delay: 0.15s;
}

.dropdown .menu a:nth-child(3) {
  transition-delay: 0.1s;
}

.dropdown .menu a:nth-child(4) {
  transition-delay: 0.05s;
}

.dropdown .menu a:nth-child(5) {
  transition-delay: 0s;
}

.dropdown .menu a:not(:last-child) {
  border-bottom: 1px solid var(--cblo40);
}

.dropdown .menu a:hover {
  background: rgba(0, 0, 0, 0.2);
}
<div  data-before=" ">
  <div >Choose category</div>
  <div >
    <a href="#" data-category="[15,16,26,27]" >All</a>
    <a href="http://localhost/discount/product-category/other/" data-category="15">Other</a>
    <a href="http://localhost/discount/product-category/electronics/" data-category="16">Electronics</a>
    <a href="http://localhost/discount/product-category/sports/" data-category="26">Sports</a>
    <a href="http://localhost/discount/product-category/toys/" data-category="27">Toys &amp; Games</a>
  </div>
</div>

  • Related