Разворачивающееся меню на jquery
Не могу решить возникшую проблему, поэтому прошу знающих людей подсказать в чем дело. Ниже я написал задачу, которая уже решена за исключением возникшей проблемы. Проблему описал после задачи.
Дано: Шапка с меню. Некоторые пункты меню имеют подменю.
Шапка можеn быть двух видов:
- Обычная - при размере экрана меньше 800px меню становится вертикальным и при клике на пункты меню, имеющие подменю оно (подменю) разворачивается, а остальные подменю сворачиваются если были открыты на момент клика. При повторном клике по пункту - подменю сворачивается.
- Шапка слева - имеет класс-модификатор .header--aside. Меню в такой шапке вертикальное при любом размере экрана. При клике по ссылкам (.menu__link) пунктов меню имеющим подменю оно (подменю) ведет себя так же как и подменю в обычной шапке при размере экрана меньше 800px.
При размере экрана менее 800px у ссылок меню (.menu__link) имеющих подменю удаляется класс .test-class. Также класс .test-class удаляется у ссылок имеющих подменю при любом размере экрана если шапка имеет класс-модификатор .header--aside.
При загрузке страницы:
- Если шапка имеет класс-модификатор .header--aside или размер экрана менее 800px, у ссылок (.menu__link) имеющих подменю удаляется класс .test-class и добавляется обработчик, который разворачивает/сворачивает подменю.
- Если у элемента списка (.menu__item) есть класс .active, то у дочерней ссылки (.menu__link) удаляется класс .test-class
При событии resize у окна:
- Если шапка НЕ ИМЕЕТ класс-модификатор .header--aside и размер экрана менее 800px, у ссылок (.menu__link) имеющих подменю удаляется класс .test-class и добавляется обработчик, который разворачивает/сворачивает подменю.
- Если шапка НЕ ИМЕЕТ класс-модификатор .header--aside и размер экрана больше или равен 800px, у ссылок (.menu__link) имеющих подменю добавляется класс .test-class и удаляется обработчик, который разворачивает/сворачивает подменю.
ПРОБЛЕМА:
После ресайза страницы при клике по ссылке (.menu__link) подменю разворачивается и сворачивается несколько раз. При загрузке страницы все работает нормально. Почему подменю себя так ведет? Если кому-то удобнее codepen
<div class="header header--aside">
<nav class="header__menu menu">
<ul class="menu__list">
<li class="menu__item active">
<a href="http://yandex.ru" class="menu__link test-class" target="_blank">text 1</a>
<ul class="menu__dropdown">
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
</ul>
</li>
<li class="menu__item">
<a href="http://yandex.ru" class="menu__link test-class" target="_blank">text 2</a>
<ul class="menu__dropdown">
<li class="menu__dropdown-item"><a href="">text</a></li>
<li class="menu__dropdown-item"><a href="">text</a></li>
<li class="menu__dropdown-item"><a href="">text</a></li>
</ul>
</li>
<li class="menu__item">
<a href="#" class="menu__link test-class">text 3</a>
<ul class="menu__dropdown">
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
<li class="menu__dropdown-item"><a href="">lorem ipsum</a></li>
</ul>
</li>
<li class="menu__item"><a href="#" class="menu__link test-class">text 4</a></li>
<li class="menu__item"><a href="#" class="menu__link test-class">text 5</a></li>
</ul>
</nav>
</div>
<style>
.menu__list {
list-style: none;
margin: 0;
padding: 0;
}
.menu__dropdown {
display: none;
list-style: none;
margin: 0;
padding: 0 0 0 20px;
}
.menu__dropdown-item {
font-size: 14px;
}
.menu__item {
margin-bottom: 6px;
font-size: 18px;
}
.menu__item.active a {
color: red;
}
.menu .test-class {
position: relative;
}
.menu .test-class::after {
content: "";
position: absolute;
top: 50%;
right: -20px;
width: 10px;
height: 1px;
background-color: red;
}
.menu a {
color: #000;
text-decoration: none;
font-family: Arial, sans-serif;
text-transform: uppercase;
}
.header__toggle {
display: none;
}
@media screen and (min-width: 800px) {
.header:not(.header--aside) .menu__list {
display: flex;
}
.header:not(.header--aside) .menu__item {
position: relative;
margin-right: 40px;
}
.header:not(.header--aside) .menu__dropdown {
position: absolute;
left: 0;
bottom: 0;
display: none;
width: 200px;
padding: 20px;
transform: translateY(100%);
background-color: #f7f7f7;
}
.header:not(.header--aside) .menu__dropdown:hover {
display: block;
}
.header:not(.header--aside) .menu__link:hover + .header:not(.header--aside) .menu__dropdown {
display: block;
}
}
</style>
<script>
const menu = $('.menu');
const menuLinks = $('.menu__link');
const isAside = $('.header').hasClass('header--aside');
const breakpoint = 800;
changeClass();
chageHandlerState();
function changeClass() {
let width = $(window).width();
menuLinks.each(function() {
const link = $(this);
const parent = link.parent();
const hasNext = link.next().length !== 0;
if ( ((isAside || width < breakpoint) && hasNext) || parent.hasClass('active')) {
link.removeClass('test-class');
} else if (!isAside && width >= breakpoint && !parent.hasClass('active')) {
link.addClass('test-class');
}
});
}
function openMobile(evt) {
evt.preventDefault();
const target = $(evt.target).closest('.menu__link');
const item = $(evt.target).closest('.menu__item');
const dropdown = target.next();
if (dropdown.length !== 0) {
const siblings = item.siblings();
siblings.find('.menu__dropdown').slideUp(300);
dropdown.slideToggle(300);
}
}
function chageHandlerState() {
if ($(window).width() < breakpoint || isAside) {
menu.on('click', openMobile);
} else if ($(window).width() >= breakpoint && !isAside) {
menu.off('click', openMobile);
}
}
$(window).on('resize', function() {
changeClass();
chageHandlerState();
});
</script>