doghouse_menu-3.0.x-dev/js/src/Menu.js
js/src/Menu.js
let $ = jQuery;
function whichTransitionEvent(){
var t;
var el = document.createElement('fakeelement');
var animEndEventNames = {
'WebkitAnimation' : 'webkitAnimationEnd',
'OAnimation' : 'oAnimationEnd',
'msAnimation' : 'MSAnimationEnd',
'animation' : 'animationend'
};
for(t in animEndEventNames){
if( el.style[t] !== undefined ){
return animEndEventNames[t];
}
}
}
function onEndAnimation( el, callback ) {
var animationEvent = whichTransitionEvent();
var onEndCallbackFn = function( ev ) {
if( ev.target != this ) {
return;
}
this.removeEventListener( animationEvent, onEndCallbackFn );
if( callback && typeof callback === 'function' ) {
callback.call();
}
};
el.addEventListener( animationEvent, onEndCallbackFn);
};
class SlideMenu {
constructor(options) {
this.options = Object.assign(this.defaults, options);
this.$el = this.options.el;
this.menus = this.$el.find(`.${this.options.classes.level}`);
this.links = this.$el.find(`.${this.options.classes.link}`);
this.nav = this.$el.find(`.${this.options.classes.nav}`)
this.activeTree = [
{
name: 'All',
link: 'main'
}
];
let $current = $('[data-menu="main"]').addClass(`${this.options.classes.level}--current`);
$(`.${this.options.classes.wrap}`).height($current.height())
this.clickListener();
this.addNavHandler();
}
clickListener() {
var self = this;
this.links.click(function(e) {
if( self.isAnimating ) {
return false;
}
var $clicked = $(this);
var $level = $clicked.closest(`.${self.options.classes.level}`);
var pos = $level.find('.menu__link').index($clicked);
var submenu = $clicked.attr('data-submenu');
var $submenu = $("[data-menu='" + submenu + "']");
var name = $clicked.text();
if ($submenu.length) {
e.preventDefault();
self.isAnimating = true;
self.slideOut(pos);
self.slideIn($submenu, pos);
self.updateTree(name, submenu);
}
});
}
slideOut(clickPosition, back = false) {
var self = this;
var $currentMenu = $(`.${this.options.classes.level}--current`);
var $menuItems = $currentMenu.find(`.${this.options.classes.item}`);
$menuItems.each(function(index, item) {
var delay = parseInt(Math.abs(clickPosition - index) * self.options.itemsDelayInterval) + 'ms';
$(item).css({
'WebkitAnimationDelay': delay,
'animationDelay': delay
});
});
if( !back ) {
$currentMenu.addClass(self.options.classes.AnimateOutLeft);
}
else {
$currentMenu.addClass(self.options.classes.AnimateOutRight);
}
}
slideIn($submenu, clickPosition, back = false) {
var self = this;
var $menuItems = $submenu.find(`.${this.options.classes.item}`);
var menuItemsTotal = $menuItems.length;
var $currentMenu = $(`.${this.options.classes.level}--current`);
$(`.${this.options.classes.wrap}`).height($submenu.height())
$menuItems.each(function(index, item) {
var delay = parseInt(Math.abs(clickPosition - index) * self.options.itemsDelayInterval) + 'ms';
$(item).css({
'WebkitAnimationDelay': delay,
'animationDelay': delay
});
var farthestIdx = clickPosition <= menuItemsTotal/2 ? menuItemsTotal - 1 : 0;
if( index === farthestIdx ) {
onEndAnimation(item, function() {
if( !back ) {
$currentMenu.removeClass(self.options.classes.AnimateOutLeft);
$submenu.removeClass(self.options.classes.AnimateInRight);
}
else {
$currentMenu.removeClass(self.options.classes.AnimateOutRight);
$submenu.removeClass(self.options.classes.AnimateInLeft);
}
$currentMenu.removeClass(`${self.options.classes.level}--current`);
$submenu.addClass(`${self.options.classes.level}--current`);
self.isAnimating = false;
});
}
});
if( !back ) {
$submenu.addClass(self.options.classes.AnimateInRight);
}
else {
$submenu.addClass(self.options.classes.AnimateInLeft);
}
}
addCrumb(name, link) {
this.activeTree.push({
name: name,
link: link,
});
this.updateCrumbs();
}
updateTree(name, link) {
this.activeTree.push({
name: name,
link: link,
});
this.nav.attr('data-active-tree', this.activeTree.length - 1);
}
addNavHandler() {
var self = this;
self.nav.click(function(e) {
if (self.isAnimating) {
return false;
}
if (self.activeTree.length > 1) {
var i = self.activeTree.length - 2;
var $submenu = $('[data-menu="' + self.activeTree[i].link + '"]');
self.isAnimating = true;
self.slideOut(0, true);
self.slideIn($submenu, 0, true);
self.activeTree.length -= 1;
self.nav.attr('data-active-tree', self.activeTree.length - 1);
}
});
}
updateCrumbs() {
var self = this;
var $crumbs = $('.doghouse-menu__breadcrumbs');
var html = this.activeTree.map(function(crumb){
var link = $('<a>').attr('data-crumbmenu', crumb.link).text(crumb.name);
return link;
});
html.forEach(function(v, i) {
$(v).click(function(e) {
if (i == html.length - 1 || self.isAnimating) {
return false;
}
self.activeTree.length = i+1;
var $submenu = $('[data-menu="' + self.activeTree[i].link + '"]');
self.slideOut(0, true);
self.slideIn($submenu, 0, true);
self.updateCrumbs();
});
});
$crumbs.html(html);
}
}
SlideMenu.prototype.defaults = {
itemsDelayInterval : 60,
classes: {
level: 'doghouse-menu__level',
item: 'doghouse-menu__item',
link: 'doghouse-menu__link',
nav: 'doghouse-menu__nav',
wrap: 'doghouse-menu__wrap',
AnimateInLeft: 'doghouse-menu-animate--in-left',
AnimateOutLeft: 'doghouse-menu-animate--out-left',
AnimateInRight: 'doghouse-menu-animate--in-right',
AnimateOutRight: 'doghouse-menu-animate--out-right',
}
};
class AccordionMenu {
constructor(options) {
this.options = Object.assign(this.defaults, options);
this.$el = this.options.el;
$('.toggle', this.$el).click(function(e) {
$(this)
.toggleClass('open')
.next('.menu').slideToggle()
})
}
}
AccordionMenu.prototype.defaults = {};
export {
SlideMenu,
AccordionMenu
}
