Mobile version of the main menu
import {toggleButton} from 'utils'
class Menu {
constructor() {
// default nodes
this._container = document.querySelector('.js-menu')
this._container.btn = this._container.querySelector('.js-menu-btn')
this._container.toggle = this._container.querySelector('.js-menu-toggle')
this._container.contents = this._container.querySelector('.js-menu-contents')
this._container.output = this._container.querySelector('.js-menu-output')
this._container.elTitle = this._container.querySelector('.js-menu-title')
this._container.textTitle = this._container.elTitle.textContent
this._container.btnClose = this._container.querySelector('.js-menu-close')
// default options
this._options = {
animation: false
}
}
get container() {
return this._container
}
set container(el) {
this._container = el
}
get options() {
return this._options
}
set options(props) {
this._options = Object.assign({}, this._options, props)
}
// init user options
init() {
if(this.options.animation) {
this.container.output.style.transition = 'left .4s cubic-bezier(.25, .8, .25, 1)'
this.container.toggle.style.transition = 'top .8s cubic-bezier(.25, .8, .25, 1)'
}
}
toggle({el, target, className}, add = true) {
if(!this.container || !target) return
el.classList.add(className)
target.classList.remove(className)
let percent = 100
percent = percent * Array.prototype.indexOf.call(this.container.output.children, target)
this.container.output.style.left = '-'+ percent +'%'
// hide prev menu after animation
el.classList.add(className)
// map menu
if(add) {
if(!this.container.prevMenu) this.container.prevMenu = []
this.container.prevMenu.push({
el: el,
target: target
})
// change title
this._changeTitle(el)
}
else {
// change title on default
this._changeTitle(target, true)
}
// prev btn
if(!this.container.btnPrev) this._defineBtnPrev({el, target, className})
this.toggleBtnPrev(this.container.prevMenu.slice(-1).pop().el)
}
_changeTitle(el, prev = false) {
if(!el.previousElementSibling && prev) {
this.container.elTitle.innerHTML = this.container.textTitle
return
}
const icon = el.querySelector('.js-menu-icon').cloneNode()
let text = prev ? this.container.prevMenu[this.container.prevMenu.length - 2].el.querySelector('.js-menu-text'): el.querySelector('.js-menu-text')
icon.classList.remove('menu__icon')
this.container.elTitle.innerHTML = icon.outerHTML + text.textContent
}
_defineBtnPrev(props) {
this.container.btnPrev = this.container.querySelector('.js-menu-prev')
// add anim to prev btn if animation true
if(this.options.animation) this.container.btnPrev.style.transition = 'left .2s linear'
// prev to menu
this.container.btnPrev.addEventListener('click', e => {
const lastMenu = this.container.prevMenu.slice(-1).pop()
this.toggle({
el: lastMenu.target,
target: lastMenu.el,
className: props.className
}, false)
this.toggleBtnPrev(lastMenu.target)
// remove last menu
this.container.prevMenu.pop()
})
}
toggleBtnPrev(el) {
if(!el.previousElementSibling) {
this.container.btnPrev.classList.toggle('menu__prev--hidden')
}
}
}
export default new Menu()
import Menu from 'Menu'
import {toggleButton} from 'utils'
document.addEventListener('DOMContentLoaded', () => {
/*============================
= Menu =
============================*/
Menu.options = {
animation: true
}
Menu.init()
// open menu
Menu.container.btn.addEventListener('click', e => {
toggleButton({
current: e.target,
target: Menu.container.toggle,
targetClassName: 'menu__wrapper--hidden'
})
})
// close menu
Menu.container.btnClose.addEventListener('click', e => {
toggleButton({
current: e.target,
target: Menu.container.toggle,
targetClassName: 'menu__wrapper--hidden'
})
})
Menu.container.toggle.addEventListener('click', e => {
if(!e.target.classList.contains('js-menu-toggle')) return
toggleButton({
current: e.target,
target: Menu.container.toggle,
targetClassName: 'menu__wrapper--hidden'
})
})
Menu.container.toggle.addEventListener('click', e => {
const el = e.target.classList.contains('js-show-child-menu') ? e.target : e.target.closest('.js-show-child-menu')
if(!el) return
Menu.toggle({
el: el.closest('.js-menu-content'),
target: Menu.container.toggle.querySelector('[data-child="'+ el.getAttribute('data-context') +'"]'),
className: 'menu__content--hidden'
})
})
/*===== End of Menu ======*/
});
/**
*
* @param {object} els (current, target, className)
* @param {function} callback
*
*/
export const toggleButton = (els, callback) => {
if(els.className) els.current.classList.toggle(els.className);
els.target.classList.toggle(els.targetClassName ? els.targetClassName : 'hidden');
if(typeof callback === 'function') {
callback()
}
}