最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to show dropdown menu when clicked - Stack Overflow

programmeradmin1浏览0评论

js

const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')

dropDown.forEach(element => {
 element.addEventListener('click',()=>{
     {
         navItems.forEach(nav =>{
             nav.classList.toggle('drop')
         })
     }
         
 })
})

HTML

   <ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
</ul>

CSS

   .navbar{
  position: relative;
}

.navbar__items{
  position: absolute;
  display: none;
}

.drop{ 
  display: block;
}

I have a navbar and each of these navbar items have dropdown items. I want to show these dropdown items when I click on the 'dropdown' class. But the problem is when I click on one of them all the dropdowns are visible. How do I show only the list I've clicked on?

js

const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')

dropDown.forEach(element => {
 element.addEventListener('click',()=>{
     {
         navItems.forEach(nav =>{
             nav.classList.toggle('drop')
         })
     }
         
 })
})

HTML

   <ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
</ul>

CSS

   .navbar{
  position: relative;
}

.navbar__items{
  position: absolute;
  display: none;
}

.drop{ 
  display: block;
}

I have a navbar and each of these navbar items have dropdown items. I want to show these dropdown items when I click on the 'dropdown' class. But the problem is when I click on one of them all the dropdowns are visible. How do I show only the list I've clicked on?

Share Improve this question edited Aug 26, 2021 at 4:59 Aanshumaan Shrijai 1191 gold badge1 silver badge11 bronze badges asked Aug 26, 2021 at 4:24 Gaurav TamangGaurav Tamang 1192 silver badges10 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 3

Enter the below code

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
  background-color: #3498DB;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropbtn:hover, .dropbtn:focus {
  background-color: #2980B9;
}

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

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  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: #ddd;}

.show {display: block;}
</style>
</head>
<body>



<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Click</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#home">Clicked</a>
    <a href="#about">Clicked</a>
    <a href="#contact">Clicked</a>
  </div>
</div>

<script>
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

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');
      }
    }
  }
}
</script>

</body>
</html>

As mentioned in ments it is better to use Event Delegation technique.

The algorithm is quite simple:

  1. Add listener on the parent element
  2. On click check if dropdown-opener was clicked
  3. Get drop-down which I need to open
  4. Close other dropdowns
  5. Open dropdown from 3.

const allDropdowns = document.querySelectorAll('.navbar__items')
const DROP_CLASS = 'drop';
const navbar = document.querySelector('.navbar');


navbar.addEventListener('click', ({target}) => {
    if (!target.classList.contains('dropdown')) return;
  
  const parent = target.parentNode;
  const navItems = parent
    .querySelector('.navbar__items');

  allDropdowns.forEach(el => el !== navItems && el.classList.remove(DROP_CLASS));
  
  if (navItems) {
    navItems.classList.toggle(DROP_CLASS);  
  }
});
.navbar{
  position: relative;
}

.navbar__items{
  position: absolute;
  left: 80px;
  display: none;
}

.drop{ 
  display: block;
}
   <ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  </ul>

Use the event target to get the parentNode, then use the parentNode to query the hidden element as all your elements are grouped in the same parent/child grouping. Also you can set an initial class for hidden, display: none; in each element and add it on click. A forEach loop sets each elements display to none using the hidden class on click.

const navItems = document.querySelectorAll('.navbar__items')
const dropDown =  document.querySelectorAll('.dropdown') 

// callback function that passes in the event => e from your listener
function showDropdown (e){
  // set each navbar__items element display: none using hidden class
  navItems.forEach(el => el.classList.add('hidden'))
  // query the specific .navbar__items in the event.targets group 
  let dd = e.target.parentNode.querySelector('.navbar__items') 
  // remove the hidden class a nd show the dropdown for this event.target
  dd.classList.remove('hidden')  
}

// iterate over the dropdown element 
dropDown.forEach(element => {
  // function showDropdown on click
  element.addEventListener('click', showDropdown)
})
.navbar {
  position: relative;
}

.navbar__items {
  position: absolute;
  left: 75px;
}

.hidden {  
  display: none;
}
<ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 1</a></li>
      <li><a href="#">clicked 1</a></li>
      <li><a href="#">clicked 1</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 2</a></li>
      <li><a href="#">clicked 2</a></li>
      <li><a href="#">clicked 2</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 3</a></li>
      <li><a href="#">clicked 3</a></li>
      <li><a href="#">clicked 3</a></li>
    </ul>
  </li>
</ul>

Rather than using addEventlistener you should add onclick method in html to every drop-down with same method name but change the ul class name with for each drop-down and then pass class name in method and then toggle the drop-down with parameter class name.

For example,

 function onClick(item) {
    if (document.getElementsByClassName(item).classList.contains('hidden')) {
        document.getElementsByClassName('dropdown').classList.remove('hidden');
    }
    if (!document.getElementsByClassName(item)[0].classList.contains('hidden')) {
        document.getElementsByClassName('dropdown').classList.add('hidden');
    }
}
<ul class="navbar">
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items1')">click</div>
        <ul class="navbar__items1 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items2')">click</div>
        <ul class="navbar__items2 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items3')">click</div>
        <ul class="navbar__items3 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
</ul>

发布评论

评论列表(0)

  1. 暂无评论