Я работаю над каким-то гамбургер-меню, на одной странице может быть более 1 гамбургер-меню, поэтому, если я щелкну любой из div, он должен открыть для меня меню.
Например на той же странице, если я нажму на кнопку один, он должен открыть меню для меня, если я могу нажать на кнопку два, он должен открыть меню для меня и так далее...
Пока я пробовал это, это сработало только для первого div, а остальная часть div не работает, помогите, пожалуйста?
var kebab = document.querySelectorAll('.kebab'),
dropdown = document.querySelector('.dropdown');
kebab.forEach(element => {
element.addEventListener('click', function() {
dropdown.classList.toggle('hidden');
dropdown.classList.remove('block');
})
})
Мой html-код
Поэтому у каждого родительского div есть .kebab, если я нажму на .kebab div, он должен открыть .dropdown div и так далее...
<div class = "1">
<div class = "kebab">
<div class = "dropdown hidden">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
<div class = "1">
<div class = "kebab">
<div class = "dropdown hidden">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
@MohammadMahdiMohajer, не могли бы вы исправить код, я пробовал все, но не работает. чем ты.
Это действительно зависит от логики. Не знаю, что вы на самом деле пытаетесь сделать.
Вы пытаетесь открыть одно и то же меню с помощью нескольких кнопок или разные меню для каждой кнопки? Кроме того, удаление блока класса может быть проблемой, потому что вы не получите его обратно, как в случае toggle.
@ Гэри, я просто обновляю вопрос
@MohammadMahdiMohajer, я просто обновляю вопрос, не могли бы вы взглянуть на него сейчас.
Вы используете querySelectorAll, чтобы получить все .kebab элементы, но только querySelector, чтобы найти первый .dropdown. Вам нужно подключить dropwdon к кнопке.
Как уже упоминалось @ppower, вы нацеливаете все меню гамбургеров на одно раскрывающееся меню. В вашей вложенной структуре вы можете переписать код следующим образом:
var kebab = document.querySelectorAll(".kebab");
kebab.forEach((element) => {
element.addEventListener("click", function () {
var dropdown = element.querySelector(".dropdown");
dropdown.classList.toggle("hidden");
dropdown.classList.remove("block");
});
});
Он найдет раскрывающийся список внутри этого конкретного щелкнутого .kebab и переключит его. Надеюсь это поможет. демо codeandbox
Отвечая на ваш вопрос о том, как закрыть раскрывающийся список по клику снаружи — я бы использовал общий прослушиватель кликов на странице и вычислил, является ли его цель или родитель бургер-меню или нет.
document.addEventListener("click", handleDocumentClick);
function handleDocumentClick(event) {
const clickedElement = event.target;
const isKebabClick = clickedElement.matches(".kebab");
if (isKebabClick) {
const dropdown = clickedElement.querySelector(".dropdown");
dropdown.classList.toggle("hidden");
return;
}
// close all dropdowns if the click happens outside kebab
if (!clickedElement.closest(".kebab")) {
const allDropdowns = document.querySelectorAll(".dropdown");
allDropdowns.forEach((dropdown) => {
dropdown.classList.add("hidden");
});
}
}
Большое спасибо за помощь, это именно то, что я искал, можно ли закрыть div, щелкнув за пределами div, например, модель, когда вы нажимаете на что-либо за пределами модального окна, оно закрывается.
Этот фрагмент может проиллюстрировать суть.
var kebab = document.querySelectorAll('.kebab');
kebab.forEach(element => {
element.addEventListener('click', function(evt) {
evt.currentTarget.firstElementChild.classList.toggle('hidden');
})
})
.hidden {
display: none;
}
.kebab {
width: 200px;
height: 50px;
background-color: rgb(200, 200, 200);
margin: 50px;
padding: 10px;
}
.kebab>.dropdown {
border: 1px solid black;
}
<div class = "1">
<div class = "kebab">
<div class = "dropdown">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
<div class = "1">
<div class = "kebab">
<div class = "dropdown">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
Кроме того, хотя вы не спрашиваете об этом, вам не нужно иметь слушателя на каждой кнопке меню. В этом фрагменте показан один из способов уменьшить количество слушателей. Поначалу это может показаться немного странным, но когда у вас появляется много активных элементов со слушателями, этот подход может оказаться полезным. Этот ответ на один из моих старых вопросов может дать лучшее объяснение.
// This can be on any parent element; doesn't have to
// be as high up the DOM as the body element.
document.body.addEventListener('click', handleClick, false)
function handleClick(event) {
let evt = event.target;
if (evt.matches('.kebab, .kebab *')) {
while (evt && !evt.matches('.kebab')) {
evt = evt.parentNode;
}
showMenu(evt.firstElementChild);
} else if ( evt.matches('.otherClass') ) {
/* test and invoke another function to handle specific event. */
}
}
function showMenu(menu) {
menu.classList.toggle('hidden');
}
.hidden {
display: none;
}
.kebab {
width: 200px;
height: 50px;
background-color: rgb(200, 200, 200);
margin: 50px;
padding: 10px;
}
.kebab>.dropdown {
border: 1px solid black;
}
<div class = "1">
<div class = "kebab">
<div class = "dropdown">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
<div class = "1">
<div class = "kebab">
<div class = "dropdown">
<div class = "kebabmenu ">
<a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>
Я думаю, что проблема кроется в вашей логике. Для каждого из элементов, к которым вы добавляете прослушиватель, вы манипулируете раскрывающейся переменной, которая каждый раз является одним и тем же элементом.