Проблема с dropdown
При разработке дропдауна столкнулся со следующей проблемой. Идея в том, чтобы при клике на кнопку открывать дропдаун. Если дропдаун открыт, то при клике на любой элемент кроме его - закрывать дропдаун. Пишу код на чистом JS.
Вызов дропдауна.
<button class="header__btn header__services">услуги</button>
<ul class="header__submenu-1">
<li class="header__subitem-1">
<a href="#" class="header__item-link header__subitem-link">Проектирование</a>
</li>
</ul>
let btnServices = document.querySelector('.header__services'),
blockSubmenu1 = document.querySelector('.header__submenu-1');
btnServices.addEventListener('click', () => {
blockSubmenu1.classList.add('header__submenu-1_active');
setTimeout(hideSubmenu1, 400);
});
Закрытие дропдауна.
function hideSubmenu1(){
document.body.addEventListener('click', (e) => {
if(e.target !== blockSubmenu1) {
blockSubmenu1.classList.remove('header__submenu-1_active');
}
});
}
При загрузке страницы и клике на кнопку btnServices дропдаун открывается. При клике на любое место закрывается, но не учитывается условие игноррирования закрытия при клике на blockSubmenu1. К тому же после выполнения данных действий повторно dropdown не открывается.
Ответы (2 шт):
Автор решения: Andrei
→ Ссылка
Попробуйте вот такой способ:
let btnServices = document.querySelector('.header__services'),
blockSubmenu1 = document.querySelector('.header__submenu-1'),
submenuItem = document.querySelector('.header__subitem-1'),
submenuLink = document.querySelector('.header__item-link');
function toggleDropduwn(e) {
if (e.target === btnServices) {
if (blockSubmenu1.classList.contains('header__submenu-1_active')) {
blockSubmenu1.classList.remove('header__submenu-1_active');
return;
} else {
blockSubmenu1.classList.add('header__submenu-1_active');
return;
}
}
if (e.target !== blockSubmenu1 && e.target !== submenuItem && e.target !== btnServices && e.target !== submenuLink) {
blockSubmenu1.classList.remove('header__submenu-1_active');
}
}
document.body.addEventListener('click', (e) => toggleDropduwn(e));
body {
min-height: 100vh;
margin: 0;
}
ul {
background-color: lightgray;
padding: 20px;
list-style: none;
display: none;
}
.header__submenu-1_active {
display: block;
}
<button class="header__btn header__services">услуги</button>
<ul class="header__submenu-1">
<li class="header__subitem-1">
<a href="#" class="header__item-link header__subitem-link">Проектирование</a>
</li>
</ul>
Автор решения: 4efirrr
→ Ссылка
document.addEventListener('DOMContentLoaded', function() {
let btnServices = document.querySelector('.header__services');
let blockSubmenu1 = document.querySelector('.header__submenu-1');
function toggleSubmenu1() {
blockSubmenu1.classList.toggle('header__submenu-1_active');
// отображаем элементы (для наглядности)
blockSubmenu1.style.display = 'block';
if (blockSubmenu1.classList.contains('header__submenu-1_active')) {
document.addEventListener('click', hideSubmenu1);
} else {
document.removeEventListener('click', hideSubmenu1);
}
}
function hideSubmenu1(e) {
if (!blockSubmenu1.contains(e.target) && e.target !== btnServices) {
blockSubmenu1.classList.remove('header__submenu-1_active');
// Скрываем элементы (для наглядности)
blockSubmenu1.style.display = 'none';
document.removeEventListener('click', hideSubmenu1);
}
}
btnServices.addEventListener('click', toggleSubmenu1);
});
<button class="header__btn header__services">услуги</button>
<ul class="header__submenu-1">
<li class="header__subitem-1">
<a href="#" class="header__item-link header__subitem-link">Проектирование</a>
</li>
</ul>
<style>
.header__submenu-1{
display: none;
}
.header__submenu-1_active {
display: block;
}
</style>
Но я бы упростил код т.о.:
function toggleSubmenu1() {
const btnServices = document.querySelector('.header__services');
const blockSubmenu1 = document.querySelector('.header__submenu-1');
const isActive = blockSubmenu1.classList.toggle('header__submenu-1_active');
blockSubmenu1.style.display = isActive ? 'block' : 'none';
if (isActive) {
document.addEventListener('click', hideSubmenu1);
} else {
document.removeEventListener('click', hideSubmenu1);
}
}
const hideSubmenu1 = (e) => {
const btnServices = document.querySelector('.header__services');
const blockSubmenu1 = document.querySelector('.header__submenu-1');
if (!blockSubmenu1.contains(e.target) && e.target !== btnServices) {
blockSubmenu1.classList.remove('header__submenu-1_active');
blockSubmenu1.style.display = 'none';
document.removeEventListener('click', hideSubmenu1);
}
};
document.querySelector('.header__services').addEventListener('click', toggleSubmenu1);