2

I have a dropdown menu and I am trying to toggle the display:block class on the ul child of the button, once that dropdown button is clicked. Currently the ul is set to display:none until the main button parent is clicked. So only the parent is shown on the screen currently.

I am having a hard time setting up these loops properly. I can set it up so when one button is clicked all the ul's for every project are shown but I only want the one under the corresponding button.

HTML:

                               <div class="dropdown">
                                <div class="project">
                                 <button>website 1<i class="fas fa-caret-down"></i></button>
                                    <ul class="drop-list">
                                        <li><a href="#">Live Website</a></li>
                                        <li><a href="#">Resources</a></li>
                                    </ul>
                                </div>

                                <div class="project">
                                    <button>Website 2<i class="fas fa-caret-down"></i></button>
                                    <ul class="drop-list">
                                        <li><a href="#">Live Website</a></li>
                                        <li><a href="#">Resources</a></li>
                                    </ul>
                                </div>
                            </div>

JAVASCRIPT:

const projects = document.querySelectorAll('.project')
const dropdown_lists = document.querySelectorAll('.drop-list')


projects.forEach(button => button.addEventListener('click', function(){
    // Feel like I need a forEach loop here to loop through the dropdown_lists or a reg for loop
   // for(i=0;i<dropdown_lists.length;i++) - maybe something like this
   // then I need to classList.toggle('active') on this ul
   // I'm getting stuck on how to make this in sync with the corresponding project button
}))

CSS:

.drop-list {
    display: none;
}

.active {
   display: block;
}

What I need is when projects[0] is clicked that toggles the class of 'active' to dropdown_lists[0] from the list. When projects[1] is clicked that toggles the class of 'active' to dropdown_lists[1] from the list.

Again, I can set up the code so when I click one button all the ul dropdown-lists toggle the class 'active' but I only want the first button to go with the first ul and second button with the second ul.

I'm just not sure how to go about this, either make a boolean if dropdown lists === 2 and project === 2 than toggle the class. I just cant think of the best practice to do this easily.

Appreciate the help.

Thanks

DOBS
  • 89
  • 6

3 Answers3

1

I applied the toggle() method, together with the method of forEach(). In which you need to declare the variable of the current button - projects_current.

Next, .active class is assigned to <ul class="drop-list">...</ul> according to the index:

dropdown_lists[index]

const projects = document.querySelectorAll('.project')
const dropdown_lists = document.querySelectorAll('.drop-list')

projects.forEach(function (projects_current, index) {
    projects_current.addEventListener('click', function () {
        dropdown_lists[index].classList.toggle('active');
    });
});
.drop-list {
    display: none;
}

.active {
   display: block;
}
<div class="dropdown">
   <div class="project">
      <button>website 1<i class="fas fa-caret-down"></i></button>
      <ul class="drop-list">
         <li><a href="#">Live Website</a></li>
         <li><a href="#">Resources</a></li>
      </ul>
   </div>
   <div class="project">
      <button>Website 2<i class="fas fa-caret-down"></i></button>
      <ul class="drop-list">
         <li><a href="#">Live Website</a></li>
         <li><a href="#">Resources</a></li>
      </ul>
   </div>
</div>
s.kuznetsov
  • 14,870
  • 3
  • 10
  • 25
  • Thanks so much @s.kuznetsov. Thanks for the great reply works great. I can't believe I couldn't get it but I really appreciate you taking the time to answer this for me! Works perfect! – DOBS Jan 15 '21 at 04:03
  • 1
    @DOBS, no problem. – s.kuznetsov Jan 15 '21 at 04:05
1

You could use "event delegation" to achieve the result without multiple event listeners. The basic idea is to use a click event listener on a common parent (div.dropdown) to check if a button was clicked, and if so, toggle the active class of the next sibling element.

A minimal event listener would then read like what you want to achieve:

document.querySelector(".dropdown").addEventListener( "click", event => {
    if( event.target.tagName == "BUTTON") {
        event.target.nextElementSibling.classList.toggle("active");
       }
});
traktor
  • 17,588
  • 4
  • 32
  • 53
  • Great call this works as well. Thanks a lot. I am going to practice both ways over the new few days to get them down. Thanks a lot and this code is very understandable. – DOBS Jan 15 '21 at 04:04
0

You can put an id in the dropdown to use it in the onclick of the buttons

const toggleDropdow = (dropdown) =>
  document.getElementById(dropdown).classList.toggle("active");
.drop-list {
    display: none;
}

.active {
   display: block;
}
<div class="dropdown">
    <div class="project">
        <button onclick="toggleDropdow('dropdown1')">Website 1</button>
        <ul id="dropdown1" class="drop-list">
            <li><a href="#">Live Website</a></li>
            <li><a href="#">Resources</a></li>
        </ul>
    </div>

    <div class="project">
        <button onclick="toggleDropdow('dropdown2')">Website 2</button>
        <ul id="dropdown2" class="drop-list">
            <li><a href="#">Live Website</a></li>
            <li><a href="#">Resources</a></li>
        </ul>
    </div>
</div>
francoMG
  • 36
  • 1
  • 3