Home > Software engineering >  How to apply a class to a clicked element in a dropdown menu?
How to apply a class to a clicked element in a dropdown menu?

Time:10-22

In the snippet below, I'm trying to show the dropdown menu with the currently displayed content having an underline below the list item (an active class). If the other list item is clicked, then move the active class to that clicked element. I've gotten most of the way there, but I can't seem to toggle the list items when clicked.

How do I toggle the active class between clicked menu items?

let dropdown = document.querySelector('.dropdown-select');
let dropdownItem = document.querySelectorAll('.dropdown-select .menu li');

dropdown.addEventListener('click', (e) => {
  if (dropdown.classList.contains('closed')) {
    dropdown.classList.remove('closed');
    dropdown.classList.add('open');
  } else {
    dropdown.classList.add('closed');
    dropdown.classList.remove('open');
  }
});

for (let i = 0; i < dropdownItem.length; i  ) {
  dropdownItem[i].addEventListener('click', function() {
    let dropdownItemClicked = document.querySelector('.menu li.active');
    if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
    this.parentNode.classList.add('active');
  })
}

const options = document.querySelectorAll('.menu li')

const results = document.querySelectorAll('.tabbed-content div')
options.forEach(e => e.addEventListener('click', function() {
  results.forEach(f => f.style.display = f.id == e.dataset.target ? "block" : "none")
}))
.dropdown-select {
  transition: all 0.2s ease;
  overflow: hidden;
  cursor: pointer;
  border-top: 1px solid #E0E5EC;
  padding-bottom: 10px;
  width: 100%;
}
@media (min-width: 768px) {
  .dropdown-select {
    display: flex;
    align-items: center;
    cursor: default;
  }
}
.dropdown-select.open {
  box-shadow: 0px 8px 24px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
  .dropdown-select.open {
    box-shadow: unset;
  }
}
.dropdown-select__title {
  display: flex;
  align-items: center;
  padding-top: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid #E0E5EC;
}
.dropdown-select__title h6 {
  font-size: 0.75rem;
  line-height: 0.75rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  pointer-events: none;
}
.dropdown-select__title img {
  width: 1.312rem;
  height: 0.656rem;
  margin-left: auto;
  transition: all 0.2s ease;
}
@media (min-width: 768px) {
  .dropdown-select__title img {
    display: none;
  }
}
.dropdown-select ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.dropdown-select .menu li {
  font-size: 1rem;
  line-height: 1.5rem;
  padding: 1rem 0;
  font-weight: 800;
  color: #6D7582;
}
@media (min-width: 768px) {
  .dropdown-select .menu li {
    padding: 0;
    cursor: pointer;
  }
  .dropdown-select .menu li:first-child {
    margin-right: 2rem;
  }
}
.dropdown-select .menu li.active {
  color: #005fec;
}
@media (min-width: 768px) {
  .dropdown-select .menu li.active {
    border-bottom: 4px solid #005fec;
  }
}
.dropdown-select__title,
.dropdown-select .menu {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}
@media (min-width: 768px) {
  .dropdown-select__title,
.dropdown-select .menu {
    display: flex;
    align-items: center;
    padding-left: 0;
    padding-right: 0;
    margin-right: 3.875rem;
  }
}
.dropdown-select.closed .menu {
  height: 0;
}
.dropdown-select.closed img {
  transform: rotate(180deg);
}

.tabbed-content div {
  display: none;
}
  <main>
    <div class="dropdown-select closed">
      <div class="dropdown-select__title">
        <h6>Other Releases</h6>
        <img src="https://cdn-icons-png.flaticon.com/24/25/25243.png" alt="down caret ">
      </div>
      <ul class="menu">
        <li data-target="1" class="active">Fall 2021</li>
        <li data-target="2">Summer 2021</li>
      </ul>
    </div>
    <div class="tabbed-content">
      <div id="1" style="display: block;">Fall 2021</div>
      <div id="2">Summer 2021</div>
    </div>
  </main>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

So, to solve your problem, you should be targetting the specific element to which the click event was performed. And add the active class to it. As shown on the code snippet. I only modified this event listener to receive the event and then add the active class to the target

dropdownItem[i].addEventListener('click', function(event) {
  let dropdownItemClicked = document.querySelector('.menu li.active');
  if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
  event.target.classList.add('active');
})

I believe that solves your problem.

let dropdown = document.querySelector('.dropdown-select');
let dropdownItem = document.querySelectorAll('.dropdown-select .menu li');

dropdown.addEventListener('click', (e) => {
  if (dropdown.classList.contains('closed')) {
    dropdown.classList.remove('closed');
    dropdown.classList.add('open');
  } else {
    dropdown.classList.add('closed');
    dropdown.classList.remove('open');
  }
});

for (let i = 0; i < dropdownItem.length; i  ) {
  dropdownItem[i].addEventListener('click', function(event) {
    let dropdownItemClicked = document.querySelector('.menu li.active');
    if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
    event.target.classList.add('active');
  })
}

const options = document.querySelectorAll('.menu li')

const results = document.querySelectorAll('.tabbed-content div')
options.forEach(e => e.addEventListener('click', function() {
  results.forEach(f => f.style.display = f.id == e.dataset.target ? "block" : "none")
}))
.dropdown-select {
  transition: all 0.2s ease;
  overflow: hidden;
  cursor: pointer;
  border-top: 1px solid #E0E5EC;
  padding-bottom: 10px;
  width: 100%;
}
@media (min-width: 768px) {
  .dropdown-select {
    display: flex;
    align-items: center;
    cursor: default;
  }
}
.dropdown-select.open {
  box-shadow: 0px 8px 24px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
  .dropdown-select.open {
    box-shadow: unset;
  }
}
.dropdown-select__title {
  display: flex;
  align-items: center;
  padding-top: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid #E0E5EC;
}
.dropdown-select__title h6 {
  font-size: 0.75rem;
  line-height: 0.75rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  pointer-events: none;
}
.dropdown-select__title img {
  width: 1.312rem;
  height: 0.656rem;
  margin-left: auto;
  transition: all 0.2s ease;
}
@media (min-width: 768px) {
  .dropdown-select__title img {
    display: none;
  }
}
.dropdown-select ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.dropdown-select .menu li {
  font-size: 1rem;
  line-height: 1.5rem;
  padding: 1rem 0;
  font-weight: 800;
  color: #6D7582;
}
@media (min-width: 768px) {
  .dropdown-select .menu li {
    padding: 0;
    cursor: pointer;
  }
  .dropdown-select .menu li:first-child {
    margin-right: 2rem;
  }
}
.dropdown-select .menu li.active {
  color: #005fec;
}
@media (min-width: 768px) {
  .dropdown-select .menu li.active {
    border-bottom: 4px solid #005fec;
  }
}
.dropdown-select__title,
.dropdown-select .menu {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}
@media (min-width: 768px) {
  .dropdown-select__title,
.dropdown-select .menu {
    display: flex;
    align-items: center;
    padding-left: 0;
    padding-right: 0;
    margin-right: 3.875rem;
  }
}
.dropdown-select.closed .menu {
  height: 0;
}
.dropdown-select.closed img {
  transform: rotate(180deg);
}

.tabbed-content div {
  display: none;
}
  <main>
    <div class="dropdown-select closed">
      <div class="dropdown-select__title">
        <h6>Other Releases</h6>
        <img src="https://cdn-icons-png.flaticon.com/24/25/25243.png" alt="down caret ">
      </div>
      <ul class="menu">
        <li data-target="1" class="active">Fall 2021</li>
        <li data-target="2">Summer 2021</li>
      </ul>
    </div>
    <div class="tabbed-content">
      <div id="1" style="display: block;">Fall 2021</div>
      <div id="2">Summer 2021</div>
    </div>
  </main>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You are very close to achieving the effect you are after.

If we look at the lines below, we can see that we are trying to adjust the classes. As is, we successfully remove the active class, but are unable to add it where needed. This is due to the fact the class is trying to be added to the wrong element, a parent element and not the siblings.

    if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
this.parentNode.classList.add('active');

By changing the one line we can add the class to the correct element as seen below.

        if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
    dropdownItem[i].classList.add('active');

let dropdown = document.querySelector('.dropdown-select');
let dropdownItem = document.querySelectorAll('.dropdown-select .menu li');

dropdown.addEventListener('click', (e) => {
  if (dropdown.classList.contains('closed')) {
    dropdown.classList.remove('closed');
    dropdown.classList.add('open');
  } else {
    dropdown.classList.add('closed');
    dropdown.classList.remove('open');
  }
});

for (let i = 0; i < dropdownItem.length; i  ) {
  dropdownItem[i].addEventListener('click', function() {
    let dropdownItemClicked = document.querySelector('.menu li.active');
    if (dropdownItemClicked) dropdownItemClicked.classList.remove('active');
    dropdownItem[i].classList.add('active');
  })
}

const options = document.querySelectorAll('.menu li')

const results = document.querySelectorAll('.tabbed-content div')
options.forEach(e => e.addEventListener('click', function() {
  results.forEach(f => f.style.display = f.id == e.dataset.target ? "block" : "none")
}))
.dropdown-select {
  transition: all 0.2s ease;
  overflow: hidden;
  cursor: pointer;
  border-top: 1px solid #E0E5EC;
  padding-bottom: 10px;
  width: 100%;
}
@media (min-width: 768px) {
  .dropdown-select {
    display: flex;
    align-items: center;
    cursor: default;
  }
}
.dropdown-select.open {
  box-shadow: 0px 8px 24px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
  .dropdown-select.open {
    box-shadow: unset;
  }
}
.dropdown-select__title {
  display: flex;
  align-items: center;
  padding-top: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid #E0E5EC;
}
.dropdown-select__title h6 {
  font-size: 0.75rem;
  line-height: 0.75rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  pointer-events: none;
}
.dropdown-select__title img {
  width: 1.312rem;
  height: 0.656rem;
  margin-left: auto;
  transition: all 0.2s ease;
}
@media (min-width: 768px) {
  .dropdown-select__title img {
    display: none;
  }
}
.dropdown-select ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.dropdown-select .menu li {
  font-size: 1rem;
  line-height: 1.5rem;
  padding: 1rem 0;
  font-weight: 800;
  color: #6D7582;
}
@media (min-width: 768px) {
  .dropdown-select .menu li {
    padding: 0;
    cursor: pointer;
  }
  .dropdown-select .menu li:first-child {
    margin-right: 2rem;
  }
}
.dropdown-select .menu li.active {
  color: #005fec;
}
@media (min-width: 768px) {
  .dropdown-select .menu li.active {
    border-bottom: 4px solid #005fec;
  }
}
.dropdown-select__title,
.dropdown-select .menu {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}
@media (min-width: 768px) {
  .dropdown-select__title,
.dropdown-select .menu {
    display: flex;
    align-items: center;
    padding-left: 0;
    padding-right: 0;
    margin-right: 3.875rem;
  }
}
.dropdown-select.closed .menu {
  height: 0;
}
.dropdown-select.closed img {
  transform: rotate(180deg);
}

.tabbed-content div {
  display: none;
}
  <main>
    <div class="dropdown-select closed">
      <div class="dropdown-select__title">
        <h6>Other Releases</h6>
        <img src="https://cdn-icons-png.flaticon.com/24/25/25243.png" alt="down caret ">
      </div>
      <ul class="menu">
        <li data-target="1" class="active">Fall 2021</li>
        <li data-target="2">Summer 2021</li>
      </ul>
    </div>
    <div class="tabbed-content">
      <div id="1" style="display: block;">Fall 2021</div>
      <div id="2">Summer 2021</div>
    </div>
  </main>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related