Переключение видимости меню
Вы можете сохранить последнее открытое меню в переменной opened
вне функции.Затем, если щелкнуть меню, если opened
не равно null
, оно переключит opened
(т. Е. Скроет последнее открытое меню) и переключит выбранный элемент.
let opened = null
function testFunc(el) {
// gets the <ul> element of the clicked menu item
const menu = el.parentElement.lastChild.previousSibling;
if (!opened) {
// no menu item is shown
opened = menu
opened.classList.toggle('show');
} else if (menu == opened) {
// the clicked item is already showing
menu.classList.toggle('show')
opened = null
} else {
// the clicked item is hiddden but another one is showing
opened.classList.toggle('show')
opened = menu
opened.classList.toggle('show')
}
}
Вот код:
let opened = null
function testFunc(el) {
const menu = el.parentElement.lastChild.previousSibling;
if(!opened) {
opened = menu
opened.classList.toggle('show');
} else if(menu == opened) {
menu.classList.toggle('show')
opened = null
} else {
opened.classList.toggle('show')
opened = menu
opened.classList.toggle('show')
}
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul li {
width: 100px;
float: left;
background: #dbdbdb;
line-height: 2em;
text-align: center;
margin: 0 5px;
cursor: pointer;
}
ul li span {
display: block;
}
ul li ul {
display: none;
}
.show {
display: block;
}
<ul>
<li>
<span onclick="testFunc(this)">Item 1</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span onclick="testFunc(this)">Item 2</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span onclick="testFunc(this)">Item 3</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span onclick="testFunc(this)">Item 4</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
</ul>
Вариант с синтаксисом ES6
Вот вариант с некоторым синтаксисом ES6, обратите внимание, что я изменил HTMLструктура имен для лучшего обслуживания кода, вызов элементов по имени класса позволяет
Вот код JavaScript:
let opened = null
const toggleVisibility = e => e.classList.toggle('show')
const toggleDropDown = e => {
const clickedItem = e.target.parentElement.lastChild.previousSibling
toggleVisibility(clickedItem);
if (!opened) {
opened = clickedItem
} else if (opened == clickedItem) {
opened = null
} else {
toggleVisibility(opened);
opened = clickedItem
}
}
[...document.querySelectorAll('.dropDown')].forEach(dropDown => dropDown.addEventListener('click', toggleDropDown))
let opened = null
const toggleVisibility = e => e.classList.toggle('show')
const toggleDropDown = e => {
const clickedItem = e.target.parentElement.lastChild.previousSibling
toggleVisibility(clickedItem);
if (!opened) {
opened = clickedItem
} else if (opened == clickedItem) {
opened = null
} else {
toggleVisibility(opened);
opened = clickedItem
}
}
[...document.querySelectorAll('.dropDown')].forEach(dropDown => dropDown.addEventListener('click', toggleDropDown))
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul li {
width: 100px;
float: left;
background: #dbdbdb;
line-height: 2em;
text-align: center;
margin: 0 5px;
cursor: pointer;
}
ul li span {
display: block;
}
ul li ul {
display: none;
}
.show {
display: block;
}
<ul>
<li>
<span class="dropDown">Item 1</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 2</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 3</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 4</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
</ul>
Переключение видимости меню + закрытие при нажатии в другом месте
Если вы хотите закрыть любое открытое меню, если пользователь щелкаетза пределами меню вам понадобится прослушиватель событий для самого документа.Таким образом, вместо одного прослушивателя событий для каждой кнопки меню, вы будете следить за каждым щелчком, происходящим в документе.он запустит обработчик меню.В противном случае закроется последний открытый элемент меню.
Код JavaScript:
let opened = null
const toggleVisibility = e => e.classList.toggle('show')
const handleDropdown = e => {
const clickedItem = e.parentElement.lastChild.previousSibling
toggleVisibility(clickedItem)
if (!opened) {
opened = clickedItem
} else if (opened == clickedItem) {
opened = null
} else {
toggleVisibility(opened)
opened = clickedItem
}
}
const handleClick = e => {
if (e.target.className.includes('dropDown')) {
handleDropdown(e.target)
} else if (opened) {
toggleVisibility(opened)
opened = null
}
}
document.addEventListener('click', handleClick)
Вот полный код:
let opened = null
const toggleVisibility = e => e.classList.toggle('show')
const handleDropdown = e => {
const clickedItem = e.parentElement.lastChild.previousSibling
toggleVisibility(clickedItem)
if (!opened) {
opened = clickedItem
} else if (opened == clickedItem) {
opened = null
} else {
toggleVisibility(opened)
opened = clickedItem
}
}
const handleClick = e => {
if (e.target.className.includes('dropDown')) {
handleDropdown(e.target)
} else if (opened) {
toggleVisibility(opened)
opened = null
}
}
document.addEventListener('click', handleClick)
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul li {
width: 100px;
float: left;
background: #dbdbdb;
line-height: 2em;
text-align: center;
margin: 0 5px;
cursor: pointer;
}
ul li span {
display: block;
}
ul li ul {
display: none;
}
.show {
display: block;
}
<ul>
<li>
<span class="dropDown">Item 1</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 2</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 3</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
<li>
<span class="dropDown">Item 4</span>
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
</ul>