Многоуровневое меню

Многоуровневое меню

От автора: простое многоуровневое меню с легкой анимацией при переходе между пунктами и «хлебными крошками» с кнопкой возврата назад.

скачать исходникидемо

Сегодня у нас проект по созданию многоуровневого меню с анимацией. Основная задача – анимировать каждый пункт меню при переходе на новый уровень. Анимация начинается с пункта, на который был совершен клик, и потом с легкой задержкой распространяется на остальные пункты меню. На внутренних уровнях анимация работает по таким же принципам. Мы самостоятельно добавили так называемые хлебные крошки и кнопку назад (в нашем демо скрыта). Подуровни связаны между собой с помощью атрибута data-. Для мобильных устройств мы добавили несколько медиа запросов, а также специальную кнопку для возвращения меню в прежнее состояние.

В демо использованы иконки Organic Food от Wojciech Zasina и Feather icon set от Cole Bemis. Пожалуйста, обратите внимание на то, что мы используем несколько современных свойств CSS, которые поддерживаются только в современных браузерах.

HTML

<!—Основной контейнер -->
<div class="container">
 <!-- кнопка раскрытия меню на мобильных устройствах -->
 <button class="action action--open" aria-label="Open Menu"><span class="icon icon--menu"></span></button>
 <!-- Меню -->
 <nav id="ml-menu" class="menu">
  <!-- Кнопка закрытия меню на мобильных устройствах -->
  <button class="action action--close" aria-label="Close Menu"><span class="icon icon--cross"></span></button>
  <div class="menu__wrap">
 <ul data-menu="main" class="menu__level">
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-1" href="#">Vegetables</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-2" href="#">Fruits</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-3" href="#">Grains</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-4" href="#">Mylk & Drinks</a></li>
 </ul>
 <!-- Подменю 1 -->
 <ul data-menu="submenu-1" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Stalk Vegetables</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Roots & Seeds</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Cabbages</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Salad Greens</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Mushrooms</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-1-1" href="#">Sale %</a></li>
 </ul>
 <!-- Подменю 1-1 -->
 <ul data-menu="submenu-1-1" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Fair Trade Roots</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Dried Veggies</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Our Brand</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Homemade</a></li>
 </ul>
 <!-- Подменю 2 -->
 <ul data-menu="submenu-2" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Citrus Fruits</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Berries</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-2-1" href="#">Special Selection</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Tropical Fruits</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Melons</a></li>
 </ul>
 <!-- Подменю 2-1 -->
 <ul data-menu="submenu-2-1" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Exotic Mixes</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Wild Pick</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Vitamin Boosters</a></li>
 </ul>
 <!-- Подменю 3 -->
 <ul data-menu="submenu-3" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Buckwheat</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Millet</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Quinoa</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Wild Rice</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Durum Wheat</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-3-1" href="#">Promo Packs</a></li>
 </ul>
 <!-- Подменю 3-1 -->
 <ul data-menu="submenu-3-1" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Starter Kit</a></li>
 <li class="menu__item"><a class="menu__link" href="#">The Essential 8</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Bolivian Secrets</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Flour Packs</a></li>
 </ul>
 <!-- Подменю 4 -->
 <ul data-menu="submenu-4" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Grain Mylks</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Seed Mylks</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Nut Mylks</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Nutri Drinks</a></li>
 <li class="menu__item"><a class="menu__link" data-submenu="submenu-4-1" href="#">Selection</a></li>
 </ul>
 <!-- Подменю 4-1 -->
 <ul data-menu="submenu-4-1" class="menu__level">
 <li class="menu__item"><a class="menu__link" href="#">Nut Mylk Packs</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Amino Acid Heaven</a></li>
 <li class="menu__item"><a class="menu__link" href="#">Allergy Free</a></li>
 </ul>
  </div>
 </nav>
 <div class="content">
  <p class="info">Please choose a category</p>
  <!—контент, загруженный через Ajax -->
 </div>
</div>
<!-- /вид -->
<script src="js/classie.js"></script>
<script src="js/dummydata.js"></script>
<script src="js/main.js"></script>
<script>
(function() {
 var menuEl = document.getElementById('ml-menu'),
  mlmenu = new MLMenu(menuEl, {
 // breadcrumbsCtrl : true, // отображает хлебные крошки
 // initialBreadcrumb : 'all', // инициализирует текст хлебных крошек
 backCtrl : false, // отображает кнопку назад
 // itemsDelayInterval : 60, // задержка между анимацией каждого пункта меню
 onItemClick: loadDummyData // колбек: при клике по пункту без подменю - onItemClick([событие], [inner HTML кликнутого пункта меню])
  });

 // переключатель меню на мобильном устройстве
 var openMenuCtrl = document.querySelector('.action--open'),
  closeMenuCtrl = document.querySelector('.action--close');

 openMenuCtrl.addEventListener('click', openMenu);
 closeMenuCtrl.addEventListener('click', closeMenu);

 function openMenu() {
  classie.add(menuEl, 'menu--open');
 }

 function closeMenu() {
  classie.remove(menuEl, 'menu--open');
 }

 // симуляция загрузки сетки
 var gridWrapper = document.querySelector('.content');

 function loadDummyData(ev, itemName) {
  ev.preventDefault();

  closeMenu();
  gridWrapper.innerHTML = '';
  classie.add(gridWrapper, 'content--loading');
  setTimeout(function() {
 classie.remove(gridWrapper, 'content--loading');
 gridWrapper.innerHTML = '<ul class="products">' + dummyData[itemName] + '<ul>';
  }, 700);
 }
})();
</script>

CSS

/* Icons (made with Icomoon.io) */
/* Feather Icons by Cole Bemis */
@font-face {
 font-family: 'feather';
 font-weight: normal;
 font-style: normal;
 src: url('../fonts/feather/feather.eot?1gafuo');
 src: url('../fonts/feather/feather.eot?1gafuo#iefix') format('embedded-opentype'), url('../fonts/feather/feather.woff2?1gafuo') format('woff2'), url('../fonts/feather/feather.ttf?1gafuo') format('truetype'), url('../fonts/feather/feather.woff?1gafuo') format('woff'), url('../fonts/feather/feather.svg?1gafuo#feather') format('svg');
}

.icon {
 font-family: 'feather';
 font-weight: normal;
 font-style: normal;
 font-variant: normal;
 line-height: 1;
 text-transform: none;
 /* Better Font Rendering =========== */
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 speak: none;
}

.icon--arrow-left:before {
 content: '\e901';
}

.icon--menu:before {
 content: '\e903';
}

.icon--cross:before {
 content: '\e117';
} 


/* Стили меню */

.menu {
 position: fixed;
 top: 120px;
 left: 0;
 width: 300px;
 height: calc(100vh - 120px);
 background: #1c1d22;
}

.menu__wrap {
 position: absolute;
 top: 3.5em;
 bottom: 0;
 overflow: hidden;
 width: 100%;
}

.menu__level {
 position: absolute;
 top: 0;
 left: 0;
 visibility: hidden;
 overflow: hidden;
 overflow-y: scroll;
 width: calc(100% + 50px);
 height: 100%;
 margin: 0;
 padding: 0;
 list-style-type: none;
}

.menu__level--current {
 visibility: visible;
}

.menu__item {
 display: block;
 width: calc(100% - 50px);
}

.menu__link {
 font-weight: 600;
 position: relative;
 display: block;
 padding: 1em 2.5em 1em 1.5em;
 color: #bdbdbd;
 -webkit-transition: color 0.1s;
 transition: color 0.1s;
}

.menu__link[data-submenu]::after {
 content: '\e904';
 font-family: 'feather';
 position: absolute;
 right: 0;
 padding: 0.25em 1.25em;
 color: #2a2b30;
}

.menu__link:hover,
.menu__link[data-submenu]:hover::after {
 color: #5c5edc;
}

.menu__link--current::before {
 content: '\00B7';
 font-size: 1.5em;
 line-height: 0;
 position: absolute;
 top: 50%;
 left: 0.5em;
 height: 4px;
 color: #5c5edc;
}

[class^='animate-'],
[class*=' animate-'] {
 visibility: visible;
}

.animate-outToRight .menu__item {
 -webkit-animation: outToRight 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
 animation: outToRight 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
}

@-webkit-keyframes outToRight {
 to {
  opacity: 0;
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0);
 }
}

@keyframes outToRight {
 to {
  opacity: 0;
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0);
 }
}

.animate-outToLeft .menu__item {
 -webkit-animation: outToLeft 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
 animation: outToLeft 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
}

@-webkit-keyframes outToLeft {
 to {
  opacity: 0;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0);
 }
}

@keyframes outToLeft {
 to {
  opacity: 0;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0);
 }
}

.animate-inFromLeft .menu__item {
 -webkit-animation: inFromLeft 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
 animation: inFromLeft 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
}

@-webkit-keyframes inFromLeft {
 from {
  opacity: 0;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0);
 }
 to {
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
 }
}

@keyframes inFromLeft {
 from {
  opacity: 0;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0);
 }
 to {
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
 }
}

.animate-inFromRight .menu__item {
 -webkit-animation: inFromRight 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
 animation: inFromRight 0.6s both cubic-bezier(0.7, 0, 0.3, 1);
}

@-webkit-keyframes inFromRight {
 from {
  opacity: 0;
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0);
 }
 to {
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
 }
}

@keyframes inFromRight {
 from {
  opacity: 0;
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0);
 }
 to {
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
 }
}

.menu__breadcrumbs {
 font-size: 0.65em;
 line-height: 1;
 position: relative;
 padding: 2.5em 3.75em 1.5em 2.5em;
}

.menu__breadcrumbs a {
 font-weight: bold;
 display: inline-block;
 cursor: pointer;
 vertical-align: middle;
 letter-spacing: 1px;
 text-transform: uppercase;
 color: #5c5edc;
}

.menu__breadcrumbs a:last-child {
 pointer-events: none;
}

.menu__breadcrumbs a:hover {
 color: #8182e0;
}

.menu__breadcrumbs a:not(:last-child)::after {
 content: '\e902';
 font-family: 'feather';
 display: inline-block;
 padding: 0 0.5em;
 color: #33353e;
}

.menu__breadcrumbs a:not(:last-child):hover::after {
 color: #33353e;
}

.menu__back {
 font-size: 1.05em;
 position: absolute;
 z-index: 100;
 top: 0;
 right: 2.25em;
 margin: 0;
 padding: 1.365em 0.65em 0 0;
 cursor: pointer;
 color: #2a2b30;
 border: none;
 background: none;
}

.menu__back--hidden {
 pointer-events: none;
 opacity: 0;
}

.menu__back:hover,
.menu__back:focus {
 color: #fff;
 outline: none;
}


/* Кнопки открытия и закрытия */
 
.action {
 position: absolute;
 display: block;
 margin: 0;
 padding: 0;
 cursor: pointer;
 border: none;
 background: none;
}

.action:focus {
 outline: none;
}

.action--open {
 font-size: 1.5em;
 top: 1em;
 left: 1em;
 display: none;
 color: #fff;
 position: fixed;
 z-index: 1000;
}

.action--close {
 font-size: 1.1em;
 top: 1.25em;
 right: 1em;
 display: none;
 color: #45464e;
}

/* Пример медиа запроса */
@media screen and (max-width: 40em) {
 .action--open,
 .action--close {
  display: block;
 }
 .menu {
  z-index: 1000;
  top: 0;
  width: 100%;
  height: 100vh;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0);
  -webkit-transition: -webkit-transform 0.3s;
  transition: transform 0.3s;
 }
 .menu--open {
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
 }
}

JavaScript

/**
 * main.js
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2015, Codrops
 * http://www.codrops.com
 */
;(function(window) {

 'use strict';

 var support = { animations : Modernizr.cssanimations },
  animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' },
  animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
  onEndAnimation = function( el, callback ) {
 var onEndCallbackFn = function( ev ) {
 if( support.animations ) {
 if( ev.target != this ) return;
 this.removeEventListener( animEndEventName, onEndCallbackFn );
 }
 if( callback && typeof callback === 'function' ) { callback.call(); }
 };
 if( support.animations ) {
 el.addEventListener( animEndEventName, onEndCallbackFn );
 }
 else {
 onEndCallbackFn();
 }
  };

 function extend( a, b ) {
  for( var key in b ) { 
 if( b.hasOwnProperty( key ) ) {
 a[key] = b[key];
 }
  }
  return a;
 }

 function MLMenu(el, options) {
  this.el = el;
  this.options = extend( {}, this.options );
  extend( this.options, options );
 
  // меню 
  this.menus = [].slice.call(this.el.querySelectorAll('.menu__level'));
  // индекс текущего уровня меню
  this.current = 0;

  this._init();
 }

 MLMenu.prototype.options = {
  // показываем хлебные крошки
  breadcrumbsCtrl : true,
  // задаем текст хлебных крошек
  initialBreadcrumb : 'all',
  // отображаем кнопку назад
  backCtrl : true,
  // задержка анимации между каждым пунктом меню
  itemsDelayInterval : 60, 
  // направление 
  direction : 'r2l',
  // колбек: клик по пункту меню без подменю
  // onItemClick([событие], [inner HTML кликнутого пункта меню])
  onItemClick : function(ev, itemName) { return false; }
 };

 MLMenu.prototype._init = function() {
  // проходимся по всем существующим меню и создаем массив, массив объектов, в объектах содержится информация о всех элементах меню и их подменю
  this.menusArr = [];
  var self = this;
  this.menus.forEach(function(menuEl, pos) {
 var menu = {menuEl : menuEl, menuItems : [].slice.call(menuEl.querySelectorAll('.menu__item'))};
 self.menusArr.push(menu);

 // задаем пункту меню класс текущего
 if( pos === self.current ) {
 classie.add(menuEl, 'menu__level--current');
 }
  });

  // создаем кнопку назад
  if( this.options.backCtrl ) {
 this.backCtrl = document.createElement('button');
 this.backCtrl.className = 'menu__back menu__back--hidden';
 this.backCtrl.setAttribute('aria-label', 'Go back');
 this.backCtrl.innerHTML = '';
 this.el.insertBefore(this.backCtrl, this.el.firstChild);
  }
 
 
  // создаем хлебные крошки
  if( self.options.breadcrumbsCtrl ) {
 this.breadcrumbsCtrl = document.createElement('nav');
 this.breadcrumbsCtrl.className = 'menu__breadcrumbs';
 this.el.insertBefore(this.breadcrumbsCtrl, this.el.firstChild);
 // инициализация хлебных крошек
 this._addBreadcrumb(0);
  }

  // вызов события
  this._initEvents();
 };

 MLMenu.prototype._initEvents = function() {
  var self = this;

  for(var i = 0, len = this.menusArr.length; i < len; ++i) {
 this.menusArr.menuItems.forEach(function(item, pos) {
 item.querySelector('a').addEventListener('click', function(ev) { 
 var submenu = ev.target.getAttribute('data-submenu'),
 itemName = ev.target.innerHTML,
 subMenuEl = self.el.querySelector('ul[data-menu="' + submenu + '"]');

 // проверяем, есть подменю у данного пункта
 if( submenu && subMenuEl ) {
 ev.preventDefault();
 // открываем подменю
 self._openSubMenu(subMenuEl, pos, itemName);
 }
 else {
 // добавляем меню класс текущего меню
 var currentlink = self.el.querySelector('.menu__link--current');
 if( currentlink ) {
 classie.remove(self.el.querySelector('.menu__link--current'), 'menu__link--current');
 }
 classie.add(ev.target, 'menu__link--current');
 
 // колбек
 self.options.onItemClick(ev, itemName);
 }
 });
 });
  }
 
  // обратная навигация
  if( this.options.backCtrl ) {
 this.backCtrl.addEventListener('click', function() {
 self._back();
 });
  }
 };

 MLMenu.prototype._openSubMenu = function(subMenuEl, clickPosition, subMenuName) {
  if( this.isAnimating ) {
 return false;
  }
  this.isAnimating = true;
 
  // сохраняем индекс родительского меню для возврата 
  this.menusArr[this.menus.indexOf(subMenuEl)].backIdx = this.current;
  // сохраняем имя родительского меню
  this.menusArr[this.menus.indexOf(subMenuEl)].name = subMenuName;
  // убираем текущее меню
  this._menuOut(clickPosition);
  // плавно показываем подменю
  this._menuIn(subMenuEl, clickPosition);
 };

 MLMenu.prototype._back = function() {
  if( this.isAnimating ) {
 return false;
  }
  this.isAnimating = true;

  // текущее меню плавно уходит
  this._menuOut();
  // предыдущее меню плавно появляется
  var backMenu = this.menusArr[this.menusArr[this.current].backIdx].menuEl;
  this._menuIn(backMenu);

  // удаляем предыдущие хлебные крошки
  if( this.options.breadcrumbsCtrl ) {
 this.breadcrumbsCtrl.removeChild(this.breadcrumbsCtrl.lastElementChild);
  }
 };

 MLMenu.prototype._menuOut = function(clickPosition) {
  // текущее меню
  var self = this,
 currentMenu = this.menusArr[this.current].menuEl,
 isBackNavigation = typeof clickPosition == 'undefined' ? true : false;

  // пункты текущего меню плавно уезжают, сначала задаем задержку для пунктов меню
  this.menusArr[this.current].menuItems.forEach(function(item, pos) {
 item.style.WebkitAnimationDelay = item.style.animationDelay = isBackNavigation ? parseInt(pos * self.options.itemsDelayInterval) + 'ms' : parseInt(Math.abs(clickPosition - pos) * self.options.itemsDelayInterval) + 'ms';
  });
  // класс анимации 
  if( this.options.direction === 'r2l' ) {
 classie.add(currentMenu, !isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
  }
  else {
 classie.add(currentMenu, isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight'); 
  }
 };

 MLMenu.prototype._menuIn = function(nextMenuEl, clickPosition) {
  var self = this,
 // текущее меню
 currentMenu = this.menusArr[this.current].menuEl,
 isBackNavigation = typeof clickPosition == 'undefined' ? true : false,
 // индекс nextMenuEl
 nextMenuIdx = this.menus.indexOf(nextMenuEl),

 nextMenuItems = this.menusArr[nextMenuIdx].menuItems,
 nextMenuItemsTotal = nextMenuItems.length;

  // плавно показываем пункты следующего меню – устанавливаем задержку для пунктов
  nextMenuItems.forEach(function(item, pos) {
 item.style.WebkitAnimationDelay = item.style.animationDelay = isBackNavigation ? parseInt(pos * self.options.itemsDelayInterval) + 'ms' : parseInt(Math.abs(clickPosition - pos) * self.options.itemsDelayInterval) + 'ms';

 // после завершения анимации последнего пункта меню, сбрасываем классы
 // последний пункт самый дальний от кликнутого
 // вычислим индекс дальнего элемента
 var farthestIdx = clickPosition <= nextMenuItemsTotal/2 || isBackNavigation ? nextMenuItemsTotal - 1 : 0;

 if( pos === farthestIdx ) {
 onEndAnimation(item, function() {
 // сбрасываем классы
 if( self.options.direction === 'r2l' ) {
 classie.remove(currentMenu, !isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
 classie.remove(nextMenuEl, !isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
 }
 else {
 classie.remove(currentMenu, isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
 classie.remove(nextMenuEl, isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
 }
 classie.remove(currentMenu, 'menu__level--current');
 classie.add(nextMenuEl, 'menu__level--current');

 //сброс текущего меню
 self.current = nextMenuIdx;

 // проверяем кнопку назад и хлебные крошки
 if( !isBackNavigation ) {
 // показываем кнопку назад
 if( self.options.backCtrl ) {
 classie.remove(self.backCtrl, 'menu__back--hidden');
 }
 
 // добавляем хлебные крошки
 self._addBreadcrumb(nextMenuIdx);
 }
 else if( self.current === 0 && self.options.backCtrl ) {
 // прячем кнопку назад
 classie.add(self.backCtrl, 'menu__back--hidden');
 }

 // we can navigate again..
 self.isAnimating = false;
 });
 }
  }); 
 
  // класс анимации
  if( this.options.direction === 'r2l' ) {
 classie.add(nextMenuEl, !isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
  }
  else {
 classie.add(nextMenuEl, isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
  }
 };

 MLMenu.prototype._addBreadcrumb = function(idx) {
  if( !this.options.breadcrumbsCtrl ) {
 return false;
  }

  var bc = document.createElement('a');
  bc.innerHTML = idx ? this.menusArr[idx].name : this.options.initialBreadcrumb;
  this.breadcrumbsCtrl.appendChild(bc);

  var self = this;
  bc.addEventListener('click', function(ev) {
 ev.preventDefault();

 // если хлебные крошки последние в списке, не делаем ничего
 if( !bc.nextSibling || self.isAnimating ) {
 return false;
 }
 self.isAnimating = true;
 
 // текущее меню плавно уходит
 self._menuOut();
 // появляется следующее меню
 var nextMenu = self.menusArr[idx].menuEl;
 self._menuIn(nextMenu);

 // удаляем передние хлебные крошки
 var siblingNode;
 while (siblingNode = bc.nextSibling) {
 self.breadcrumbsCtrl.removeChild(siblingNode);
 }
  });
 };

 window.MLMenu = MLMenu;

})(window);

Проект на GitHub


Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Автор: Mary Lou

Источник: http://tympanus.net/

Редакция: Команда webformyself.

Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Фреймворк Bootstrap - верстаем адаптивно, просто, быстро!

Получите видеокурс по основам Bootstrap

Получить

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (1)

  1. Частица Бога

    В контент вставляю фотогалерею, а она не работает. В чем может быть причина?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree