function getMenu() { let menu = {}; let topMenuStructure = document.querySelectorAll('.menu_leftmenu > li'); topMenuStructure.forEach((item, i) => { if (item.querySelector('a')) { menu['menuitem-' + i] = { name: item.querySelector('a').innerText.trim(), link: item.querySelector('a').getAttribute("href") } } let subMenuStructure = item.querySelectorAll('ul > li'); if (subMenuStructure.length === 1) { menu['menuitem-' + i] = { name: subMenuStructure[0].innerText.trim(), link: subMenuStructure[0].querySelector('a').getAttribute("href"), active: false } if (subMenuStructure[0].classList.contains('active')) { menu['menuitem-' + i].active = true; } } else { subMenuStructure.forEach((subitem, j) => { menu['menuitem-' + i]['subitem-' + j] = { name: subitem.innerText.trim(), link: subitem.querySelector('a').getAttribute("href"), active: false } if (subitem.classList.contains('active')) { menu['menuitem-' + i]['subitem-' + j].active = true; } }); } }); return JSON.stringify(menu) } function buildMenu() { const menuStructure = JSON.parse(getMenu()); if (JSON.stringify(menuStructure) === '{}') { document.querySelector('.__menu-button').remove(); document.querySelector('.__menu').remove(); return false; } let menuWrapper = document.querySelector('.__menu__top'); menuWrapper.innerHTML = ''; let listWrapper = document.createElement('ul'); listWrapper.classList.add('__menu__list'); menuWrapper.appendChild(listWrapper); for (let key in menuStructure) { let topLevelItem = document.createElement('li'); topLevelItem.classList.add('__menu__list__item'); if (menuStructure[key].link) { topLevelItem.setAttribute('data-__menu-bullet', menuStructure[key].name.toLowerCase()); let topMenuListName = document.createElement('a'); topMenuListName.innerText = menuStructure[key].name; topMenuListName.setAttribute('data-title', menuStructure[key].name.toLowerCase()); topMenuListName.setAttribute('href', menuStructure[key].link); topMenuListName.classList.add('__menu__link'); topLevelItem.appendChild(topMenuListName); } else { let topMenuListName = document.createElement('div'); topMenuListName.innerText = menuStructure[key].name; topLevelItem.appendChild(topMenuListName); } listWrapper.appendChild(topLevelItem); let subMenu = document.createElement('ul'); subMenu.classList.add('__menu__list'); subMenu.classList.add('__menu__list_sub'); topLevelItem.appendChild(subMenu); for (let item in menuStructure[key]) { if (!menuStructure[key][item].hasOwnProperty('link')) { continue; } let subLevelItem = document.createElement('li'); subLevelItem.classList.add('__menu__list__item'); subLevelItem.classList.add('__menu__list__item_sub'); subMenu.appendChild(subLevelItem); if (menuStructure[key][item].active === true) { subLevelItem.classList.add('__menu__list__item_permanent'); } let subLevelItemLink = document.createElement('a'); subLevelItemLink.classList.add('__menu__link'); subLevelItemLink.classList.add('__menu__link_sub'); subLevelItem.appendChild(subLevelItemLink); let menuLink = document.createAttribute('href'); menuLink.value = menuStructure[key][item].link; subLevelItemLink.setAttributeNode(menuLink); let linkAttribute = document.createAttribute('data-title'); linkAttribute.value = menuStructure[key][item].name.toLowerCase(); subLevelItemLink.setAttributeNode(linkAttribute) subLevelItemLink.innerText = menuStructure[key][item].name; let liAttribute = document.createAttribute('data-__menu-bullet'); liAttribute.value = menuStructure[key][item].name.toLowerCase(); subLevelItem.setAttributeNode(liAttribute); } } } document.querySelector('button.__menu-button').style.zIndex = 10001; document.querySelector('.__menu').style.zIndex = 10000; ~ function() { const menu = document.querySelector('[data-__menu]') if (!menu) return console.error('Меню не найдено') const menu_inner = document.querySelector('[data-__menu-inner]') if (!menu_inner) return console.error('Внутренности меню не найдены') const menu_toggle = document.querySelector('[data-__menu-toggle]') if (!menu_toggle) return console.error('Кнопка меню не найдена') const menu_toggle_active_class = menu_toggle.dataset.__menuToggle // console.log(menu); const header_selector = menu.dataset.__menuOffset const bullet_permanent_class = menu.dataset.__menuBulletPermanentClass const target_permanet_class = menu.dataset.__menuTargetPermanentClass const target_active_class = menu.dataset.__menuTargetActiveClass const menu_active_class = menu.dataset.__menuActiveClass const current_page = menu.dataset.__menuCurrentPage.toLowerCase() const header = document.querySelector(header_selector) let is_mobile = false let active = false const lowerMenu = [...document.querySelectorAll('[data-__menu-target]')].forEach(menuItem => { menuItem.dataset.__menuTarget = menuItem.dataset.__menuTarget.toLowerCase() }); const bullets = [...menu.querySelectorAll('[data-__menu-bullet]')].map(bullet => { const target_name = bullet.dataset.__menuBullet.toLowerCase() const target = menu.querySelector(`[data-__menu-target="${target_name}"]`) if (!target) console.error('Нету таргета под названием "' + target_name + '"') const active = current_page == target_name return { node: bullet, target, active, } }) bullets.forEach(bullet => { if (bullet.active) { bullet.node.classList.add(bullet_permanent_class) bullet.target.classList.add(target_permanet_class) } bullet.node.addEventListener('mouseenter', () => { bullet.target.classList.add(target_active_class) }) bullet.node.addEventListener('mouseleave', () => { bullet.target.classList.remove(target_active_class) }) }) resize() if (header) new ResizeObserver(resize).observe(header) else window.addEventListener('resize', resize) let outside_listener menu_toggle.addEventListener('click', () => { if (outside_listener) outside_listener() menu_toggle.classList.toggle(menu_toggle_active_class) menu.classList.toggle(menu_active_class) const disableScroll = () => { active = true document.body.style.overflow = 'hidden' document.body.style.touchAction = 'none' } const enableScroll = () => { active = false document.body.style.overflow = '' document.body.style.touchAction = '' } if (is_mobile && !active) disableScroll() else if (is_mobile && active) enableScroll() outside_listener = listenOutside(menu_inner, () => { menu_toggle.classList.remove(menu_toggle_active_class) menu.classList.remove(menu_active_class) active = false document.body.style.overflow = '' document.body.style.touchAction = '' }) }) function resize() { if (header) document.body.style.setProperty('--__header-height', header.offsetHeight + 'px') is_mobile = isMobile() } function isMobile() { return /Mobi|Android/i.test(navigator.userAgent) } function on(elements, events, callback) { const se = events.split(' ') se.forEach(event => elements.forEach(element => element.addEventListener(event, callback))) return () => se.forEach(event => elements.forEach(element => { element.removeEventListener(event, callback) })) } function listenOutside(containers, callback) { if (!Array.isArray(containers)) { containers = [containers] } let click_listener let esc_listener setTimeout(() => { click_listener = on([window], 'click', e => { containers.forEach(c => { if (!c.contains(e.target)) { callback() click_listener() esc_listener() return } }) }) esc_listener = on([window], 'keydown', e => { if (e.key === 'Escape') { callback() click_listener() esc_listener() } }) }, 0) return () => { click_listener() esc_listener() } } }() document.addEventListener("DOMContentLoaded", function () { buildMenu() });