У меня небольшая проблема со следующим оформлением аккордеона/табуляции:
https://jsfiddle.net/drj3m5tg/
Как вы увидите, на мобильном телефоне значок "+" справа отображается как значок "-" при открытии и закрытии других вкладок. А на рабочем столе на вкладках иногда нужно дважды щелкнуть, чтобы отобразить содержимое ниже. Я проверил в хромовом инспекторе и вижу, что активный класс не удаляется, пока не щелкнет снова. Есть ли способ исправить это поведение с помощью JS?
const accordion = document.getElementsByClassName("accordion");
const panel = document.getElementsByClassName("panel");
for(let i = 0; i < accordion.length; i++){
accordion[i].addEventListener('click', function(){
removeOpen();
// add active class to clicked element and open class to next slibling
const toggleResult = this.classList.toggle('active');
this.nextElementSibling.classList.toggle('panel-open', toggleResult);
});
};
// remove open class for all elements
function removeOpen (){
for(let i = 0; i < panel.length; i++) {
panel[i].classList.remove('panel-open');
}
};
Это потому, что вам нужно удалить active
класс с других кнопок accordion
. Когда вы это сделаете, вы попадете в другую проблему, которая заключается в том, что переключение больше не работает. Поэтому я предлагаю вам подойти так (рефакторинг всего этого):
(function() { // not really necessary (just to hide our variables from the outside scope)
const accordion = document.getElementsByClassName("accordion"); // the .accordion buttons (no need for panels, we can get them using nextElementSibling)
let current = -1; // the index of the current active accordion element (-1 indicate that currently no element is active)
for (let i = 0; i < accordion.length; i++) {
accordion[i].addEventListener('click', function() { // when clicking a .accordion element
if (i !== current && current !== -1) { // if this is not the currently active element (i !== current), and if there is a currently active element (current !== -1)
accordion[current].classList.remove('active'); // then desactivate the currently active element
accordion[current].nextElementSibling.classList.remove('panel-open'); // ...
}
this.nextElementSibling.classList.toggle('panel-open'); // now toggle the current element
current = this.classList.toggle('active') ? i : -1; // ... (if this element is toggled on, then set current to be this element, if it is toggled off then set current to -1 as there will be no active elements)
});
};
})();
РЕДАКТИРОВАТЬ:
current
имеет значение, которое является индексом текущего accordion
элемента, который имеет active
класс. Итак, 0 <= current < accordion.length
. Не может быть активного элемента (все элементы accordion
закрыты), поэтому нам нужно значение, чтобы указать это. Значение не должно находиться в вышеупомянутом диапазоне. Это может быть что угодно: null
, false
, "oompa loompa"
,... Поскольку универсально использовать -1
(поскольку indexOf
делает для указания на неспособность), я тоже выбрал его.
Почему мы это используем? Ну, вместо того, чтобы удалять активные классы из всех элементов при каждом щелчке элемента, мы просто отслеживаем активный элемент, и каждый раз, когда нажимаем другой элемент, мы удаляем их только из одного элемента (индекс которого хранится в current
). Поскольку ток также указывает, что нет элемента, мы должны сначала проверить (current !== -1
).
Когда элемент кликается, мы также хотим проверить, не является ли он активным элементом (i !== -1
). Потому что, если мы этого не сделаем, мы удалим активные классы внутри if
и toggle
добавит их обратно. Таким образом, без этого теста при нажатии активного элемента он останется активным.