Как сделать, чтобы работали все кнопки, с помощью querySelectorAll и forEach?
Подскажите, пожалуйста, как сделать, чтобы работали все выпадающие списки, а не только первый? Насколько я понимаю, нужно перебрать все с помощью forEach, но у меня не получается.
И второй вопрос. Как сделать, чтобы выпадающий список скрыть не только при клике на кнопку, но и если кликаешь в любое место вне выпадающего списка?
let drop = document.querySelector('.dropdown');
let dropBtn = document.querySelector('.dropdown .drop-btn');
let drops = document.querySelectorAll('.dropdown');
let dropBtns = document.querySelectorAll('.dropdown .drop-btn');
dropBtn.addEventListener('click', function() {
drop.classList.toggle('active');
});
html, body {
margin: 0;
padding: 0;
font-family: "Tahoma";
}
h1, h2, h3, h4, h5, h6, ul, li, span, div, p, a {
margin: 0;
padding: 0;
font-size: 14px;
color: #000;
list-style: none;
text-decoration: none;
font-weight: normal;
}
body {
padding: 50px;
}
.dropdown {
display: inline-block;
position: relative;
}
.dropdown.active .drop-menu {
opacity: 1;
visibility: visible;
transform: translateY(10px);
}
.dropdown .drop-btn {
background-color: #2980b9;
color: #fff;
display: inline-block;
padding: 12px 32px 12px 20px;
user-select: none;
border: none;
outline: none;
border-radius: 3px;
cursor: pointer;
background-image: url(../img/down-arrow.svg);
background-size: 16px;
background-repeat: no-repeat;
background-position: right 10px center;
}
.dropdown .drop-menu {
position: absolute;
z-index: 100;
left: 0;
top: 115%;
background-color: #fff;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
width: 100%;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.dropdown .drop-menu ul li a {
border-bottom: 1px solid #eee;
padding: 12px 20px;
display: block;
}
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
Исходник кода на codepen здесь. Заранее всем большое спасибо!
Ответы (1 шт):
Автор решения: UModeL
→ Ссылка
Чтобы назначить обработчики каждому выпадающему списку, мы получаем их коллекцию с помощью:
let drops = document.querySelectorAll('.dropdown');
При существующей разметке и требуемой логике, больше ничего получать не требуется.
Далее комментарии в коде:
// Получаем коллекцию списков
let drops = document.querySelectorAll('.dropdown');
/* Перебираем списки */
drops.forEach(function(el) {
/* Назначаем обработчик текущему списку */
el.addEventListener('click', function(ev) {
// Прерываем всплытие события,
// чтобы не срабатывал обработчик,
// который мы добавим к document или body
ev.stopPropagation();
// Переключаем класс у текущего списка
this.classList.toggle('active');
});
});
/* Назначаем обработчик нажатия вне списков */
document.addEventListener('click', function() {
/* Перебираем все списки и удаляем у них класс active */
drops.forEach(el => el.classList.toggle('active', false));
});
html,body {
margin: 0;
padding: 0;
font-family: "Tahoma";
}
h1,h2,h3,h4,h5,h6,ul,li,span,div,p,a {
margin: 0;
padding: 0;
font-size: 14px;
color: #000;
list-style: none;
text-decoration: none;
font-weight: normal;
}
body {
padding: 50px;
}
.dropdown {
display: inline-block;
position: relative;
}
.dropdown.active .drop-menu {
opacity: 1;
visibility: visible;
transform: translateY(10px);
}
.dropdown .drop-btn {
background-color: #2980b9;
color: #fff;
display: inline-block;
padding: 12px 32px 12px 20px;
user-select: none;
border: none;
outline: none;
border-radius: 3px;
cursor: pointer;
background-image: url(../img/down-arrow.svg);
background-size: 16px;
background-repeat: no-repeat;
background-position: right 10px center;
}
.dropdown .drop-menu {
position: absolute;
z-index: 100;
left: 0;
top: 115%;
background-color: #fff;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
width: 100%;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.dropdown .drop-menu ul li a {
border-bottom: 1px solid #eee;
padding: 12px 20px;
display: block;
}
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
Чтобы был только один открытый список:
// Получаем коллекцию списков
let drops = document.querySelectorAll('.dropdown');
/* Перебираем списки */
drops.forEach(function(el) {
/* Назначаем обработчик текущему списку */
el.addEventListener('click', function(ev) {
// Прерываем всплытие события,
// чтобы не срабатывал обработчик,
// который мы добавим к document или body
ev.stopPropagation();
/* Убираем класс active у всех списков, кроме текущего */
drops.forEach(el => { if (el != this) { el.classList.remove('active') }; });
// Переключаем класс у текущего списка
this.classList.toggle('active');
});
});
/* Назначаем обработчик нажатия вне списков */
document.addEventListener('click', function() {
/* Перебираем все списки и удаляем у них класс active */
drops.forEach(el => el.classList.toggle('active', false));
});
html,body {
margin: 0;
padding: 0;
font-family: "Tahoma";
}
h1,h2,h3,h4,h5,h6,ul,li,span,div,p,a {
margin: 0;
padding: 0;
font-size: 14px;
color: #000;
list-style: none;
text-decoration: none;
font-weight: normal;
}
body {
padding: 50px;
}
.dropdown {
display: inline-block;
position: relative;
}
.dropdown.active .drop-menu {
opacity: 1;
visibility: visible;
transform: translateY(10px);
}
.dropdown .drop-btn {
background-color: #2980b9;
color: #fff;
display: inline-block;
padding: 12px 32px 12px 20px;
user-select: none;
border: none;
outline: none;
border-radius: 3px;
cursor: pointer;
background-image: url(../img/down-arrow.svg);
background-size: 16px;
background-repeat: no-repeat;
background-position: right 10px center;
}
.dropdown .drop-menu {
position: absolute;
z-index: 100;
left: 0;
top: 115%;
background-color: #fff;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
width: 100%;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.dropdown .drop-menu ul li a {
border-bottom: 1px solid #eee;
padding: 12px 20px;
display: block;
}
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>
<div class="dropdown">
<button class="drop-btn">Dropdown</button>
<div class="drop-menu">
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>
</div>
</div>