Самый простой способ. Оборачиваем всё в див и ставим на него прослушку кликов. Если клик не по кнопке - выходим из функции. Задаём дата атрибуты у кнопок и списков. По клику на кнопку проверяем не открыт ли список, относящийся к ней. Если открыт - закрываем его и выходим из функции. Если закрыт, проверяем, нет ли открытых списков, если есть - закрываем. Открываем список, относящийся к кнопке. Списки разместил рядом с кнопками только чтобы было видно, что открываются и закрываются нужные. Разметку можно делать какую требуется, главное, чтобы кнопки и списки совпадали по дата атрибутам и находились внутри корневого элемента. Если нужно выносить кнопки в другие части документа, можно исправить поиск элементов на поиск по всему документу. В последнем варианте, если таких блоков на странице может быть несколько, можно добавить дополнительные дата атрибуты или префиксы к существующим.
Код
Pug
.lists-app
- const lists = new Array(10)
- const items = new Array(3)
each i, idx in lists
button(
data-list-toggle=`${idx}`
) open #{idx + 1}
ul.lists-app__list(
data-list=`${idx}`
)
each i, idx in items
li list elem #{idx + 1}
SASS
.lists-app
&__list
display: none
&--open
display: block
JS
const rootClass = 'lists-app'
const openClass = 'lists-app__list--open'
const $listsRoot = document.querySelector(`.${rootClass}`)
const findList = idx => {
return $listsRoot.querySelector(`[data-list='${idx}']`)
}
const closeList = $el => {
$el.classList.remove(openClass)
}
const openList = $el => {
$el.classList.add(openClass)
}
const isOpen = $el => $el.classList.contains(openClass)
const getOpenList = () => {
return $listsRoot.querySelector(`.${openClass}`)
}
$listsRoot.addEventListener('click', e => {
if (!e.target.hasAttribute('data-list-toggle')) {
return
}
const idx = e.target.dataset.listToggle
const $list = findList(idx)
if (isOpen($list)) {
closeList($list)
return
}
const $openList = getOpenList()
$openList ? closeList($openList) : null
openList($list)
})