Как изменить класс иконки у текущего дропдауна?

144
23 января 2020, 09:30

Всем привет у меня есть мини-задание.

Мне нужно изменить класс у иконки в дропдауне. Проблема в том что меняется класс у всех дропдаунов. Как сделать чтобы менялась текущая иконка у дропдауна, а все остальные не менялись. Ссылка на мини -задание: https://jsbin.com/raqiwulewe/1/edit?html,css,js,output

Answer 1

Если не делать кардинальных правок в Вашем коде, то можно сделать вот так:

const menu = document.querySelector('.menu'); 
const items = menu.querySelectorAll('.dropdown-item'); 
 
items.forEach(item => item.addEventListener("click", e => { 
  // Текущее меню 
  const currentMenu = item.querySelector(".dropdown-menu"); 
  // Находим все меню 
  menu.querySelectorAll('.dropdown-menu').forEach(element => { 
    const icon = element.parentNode.querySelector('i'); 
    if (element !== currentMenu) { 
      // Схлопываем все меню, кроме текущего 
      // И делаем правильную иконку 
      element.classList.toggle("d-none", true); 
      icon.classList.toggle("fa-minus", false); 
      icon.classList.toggle("fa-plus", true); 
    } else { 
      // Переключаем текущее меню и его иконку 
      element.classList.toggle("d-none"); 
      icon.classList.toggle("fa-minus"); 
      icon.classList.toggle("fa-plus"); 
    } 
  }); 
 
}));
.d-none { 
  display: none; 
} 
 
.dropdown-item { 
  cursor: pointer; 
}
<!DOCTYPE html> 
<html> 
 
<head> 
  <meta charset="utf-8"> 
  <meta name="viewport" content="width=device-width"> 
  <title>JS Bin</title> 
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> 
</head> 
 
<body> 
  <ul class="menu"> 
    <li class="dropdown-item"> 
      <i class="fas fa-plus icon"></i> 
      <span>Dropdown menu item</span> 
      <div class="dropdown-menu d-none"> 
        <ul class="dropdown-list"> 
          <li>Dropdown item 1</li> 
          <li>Dropdown item 2</li> 
        </ul> 
        <!-- / .dropdown-list --> 
      </div> 
      <!-- / .dropdown-menu --> 
    </li> 
    <!-- / .dropdown-item --> 
    <li> 
      <span>Menu item</span> 
    </li> 
    <!-- / li --> 
    <li class="dropdown-item"> 
      <i class="fas fa-plus icon"></i> 
      <span>Dropdown menu item 2</span> 
      <div class="dropdown-menu d-none"> 
        <ul class="dropdown-list"> 
          <li>Second Dropdown item 1</li> 
          <li>Second Dropdown item 2</li> 
        </ul> 
        <!-- / .dropdown-list --> 
      </div> 
      <!-- / .dropdown-menu --> 
    </li> 
    <!-- / .dropdown-item --> 
  </ul> 
</body> 
 
</html>

Answer 2

Можно так.

class Dropdown { 
  constructor(node) { 
    this.node = node; 
 
    if (!this.node) return; 
 
    this.onListClick = this.onListClick.bind(this); 
 
    this.node.addEventListener("click", this.onListClick, false); 
  } 
 
  isOpen(item) { 
    return item.classList.contains("dropdown-item_open"); 
  } 
 
  onListClick(event) { 
    const item = event.target.closest(".dropdown-item"); 
 
    if (!item) return; 
 
    this.isOpen(item) ? this.close() : this.open(item); 
  } 
 
  open(item) { 
    this.close(); 
 
    const icon = item.querySelector(".fas"); 
 
    item.classList.add("dropdown-item_open"); 
    icon.classList.remove("fa-plus"); 
    icon.classList.add("fa-minus"); 
  } 
 
  close() { 
    [...this.node.querySelectorAll(".dropdown-item")].forEach(node => node.classList.remove("dropdown-item_open")); 
    [...this.node.querySelectorAll(".fas")].forEach(node => { 
      node.classList.remove("fa-minus"); 
      node.classList.add("fa-plus"); 
    }); 
  } 
} 
 
new Dropdown(document.querySelector(".menu"));
.dropdown-item { 
  cursor: pointer; 
} 
 
.dropdown-menu { 
  display: none; 
} 
 
.dropdown-item_open .dropdown-menu { 
  display: block; 
}
<!DOCTYPE html> 
<html> 
 
<head> 
  <meta charset="utf-8"> 
  <meta name="viewport" content="width=device-width"> 
  <title>JS Bin</title> 
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> 
</head> 
 
<body> 
  <ul class="menu"> 
    <li class="dropdown-item"> 
      <i class="fas fa-plus icon"></i> 
      <span>Dropdown menu item</span> 
      <div class="dropdown-menu"> 
        <ul class="dropdown-list"> 
          <li>Dropdown item 1</li> 
          <li>Dropdown item 2</li> 
        </ul> 
        <!-- / .dropdown-list --> 
      </div> 
      <!-- / .dropdown-menu --> 
    </li> 
    <!-- / .dropdown-item --> 
    <li> 
      <span>Menu item</span> 
    </li> 
    <!-- / li --> 
    <li class="dropdown-item"> 
      <i class="fas fa-plus icon"></i> 
      <span>Dropdown menu item 2</span> 
      <div class="dropdown-menu"> 
        <ul class="dropdown-list"> 
          <li>Second Dropdown item 1</li> 
          <li>Second Dropdown item 2</li> 
        </ul> 
        <!-- / .dropdown-list --> 
      </div> 
      <!-- / .dropdown-menu --> 
    </li> 
    <!-- / .dropdown-item --> 
  </ul> 
</body> 
 
</html>

READ ALSO
Nuxt VueJS There are multiple modules with names that only differ in casing

Nuxt VueJS There are multiple modules with names that only differ in casing

осваиваю nuxtJS при компиляции возникает ошибка гугл не помог, написано что при объявлении Заглавных букв возникает, однако у меня ошибка воздникает...

237
Миграция c Vuex standart mode → Vuex module [Длинно-пост]

Миграция c Vuex standart mode → Vuex module [Длинно-пост]

Ребят, будет длинно-пост, ибо пригорело что-тоБуду рад если вы не пройдете мимо или скажете что я не прав и херню наворотил :)

146
Воспроизведение аудио потока в плеере plyr

Воспроизведение аудио потока в плеере plyr

Столкнулся с проблемой воспроизведения потокаПереношу ссылку из отдельного блока, вставляю ее в плеер и передаю воспроизведение, но плеер...

142