Author: | Michal Niewitala |
---|---|
Views Total: | 896 views |
Official Page: | Go to website |
Last Update: | November 11, 2017 |
License: | MIT |
Preview:

Description:
Last Navigation is a vanilla JavaScript responsive navigation system which transforms the regular horizontal menu into a togglable fullscreen menu on mobile devices.
How to use it:
Create the header navigation with nested menu items.
<header id="header"> <nav class="nav container" id="nav"> <ul class="menu"> <li class="menu-item"><a href="">Home</a> </li> <li class="menu-item"><a href="">Templates</a> <ul class="sub-menu"> <li><a href="">Gallery</a> <ul class="sub-menu"> <li><a href="">One</a></li> <li><a href="">Wwo</a></li> </ul> </li> <li><a href="">Post</a> </li> </ul> </li> <li class="menu-item"><a href="">About</a> </li> <li class="menu-item"><a href="">Portfolio</a> <ul class="sub-menu"> <li><a href="">Best_project</a> </li> <li><a href="">Second</a> </li> <li><a href="">Last</a> <ul class="sub-menu"> <li><a href="">Showcase</a></li> </ul> </li> </ul> </li> <li class="menu-item"><a href="">Contact</a> </li> </ul> </nav> </header>
The main JavaScript.
(function() { var block, i, j, len, len1, ref, ref1, responsiveMenu, slideToggler, trigger, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; slideToggler = (function() { function slideToggler(el1) { this.el = el1; this.toggle = bind(this.toggle, this); this.getHeight = bind(this.getHeight, this); if (!this.el) { return; } window.addEventListener('resize', this.getHeight); } slideToggler.prototype.getHeight = function() { var clone; clone = this.el.cloneNode(true); clone.style.cssText = 'visibility: hidden; display: block; margin: -999px 0'; this.height = (this.el.parentNode.appendChild(clone)).clientHeight; this.el.parentNode.removeChild(clone); return this.height; }; slideToggler.prototype.toggle = function(time) { var currHeight, disp, el, end, init, ref, repeat, start; this.getHeight(); time || (time = this.height / 3 + 150); currHeight = this.el.clientHeight * (getComputedStyle(this.el).display !== 'none'); ref = currHeight > this.height / 2 ? [this.height, 0] : [0, this.height], start = ref[0], end = ref[1]; disp = end - start; el = this.el; this.el.classList[end === 0 ? 'remove' : 'add']('open'); this.el.style.cssText = "overflow: hidden; display: block;"; init = (new Date).getTime(); repeat = function() { var i, instance, ref1, repeatLoop, results, step; instance = (new Date).getTime() - init; step = start + disp * instance / time; if (instance <= time) { el.style.height = step + 'px'; } else { el.style.cssText = "display: " + (end === 0 ? 'none' : 'block'); } repeatLoop = requestAnimationFrame(repeat); if (ref1 = Math.floor(step), indexOf.call((function() { results = []; for (var i = start; start <= end ? i <= end : i >= end; start <= end ? i++ : i--){ results.push(i); } return results; }).apply(this), ref1) < 0) { return cancelAnimationFrame(repeatLoop); } }; return repeat(); }; return slideToggler; })(); ref = document.querySelectorAll('.block'); for (i = 0, len = ref.length; i < len; i++) { block = ref[i]; block.toggler = new slideToggler(block); } ref1 = document.querySelectorAll('button'); for (j = 0, len1 = ref1.length; j < len1; j++) { trigger = ref1[j]; trigger.addEventListener('click', function() { var ref2; return (ref2 = this.parentNode.querySelector('.block').toggler) != null ? ref2.toggle() : void 0; }); } responsiveMenu = (function() { function responsiveMenu(nav, opt) { var base, k, l, len2, len3, len4, m, menu, menuToggle, ref2, ref3, ref4, sub, subMenu, subMenuToggle; this.opt = opt; this.breaking = bind(this.breaking, this); this.createToggle = bind(this.createToggle, this); (base = this.opt).breaking || (base.breaking = '640px'); this.opt.maxBreaking = parseInt(this.opt.maxBreaking) || 1040; menu = nav.querySelector('.menu'); if (!slideToggler) { slideToggler = (function() { function slideToggler(el1) { this.el = el1; this.toggle = bind(this.toggle, this); if (!this.el) { return; } } slideToggler.prototype.toggle = function() { this.el.classList.toggle('open'); return this.el.style.cssText = "display: " + (this.el.classList.contains('open') ? 'block' : 'none'); }; return slideToggler; })(); } ref2 = menu.querySelectorAll('ul'); for (k = 0, len2 = ref2.length; k < len2; k++) { sub = ref2[k]; sub.toggler = new slideToggler(sub); } menuToggle = this.createToggle(nav, 'menu-toggle', 'Menu'); menuToggle.addEventListener('click', function() { document.documentElement.classList.toggle('nav-open'); return menuToggle.menu.classList.toggle('open', document.documentElement.classList.contains('nav-open')); }); ref3 = menu.querySelectorAll('ul'); for (l = 0, len3 = ref3.length; l < len3; l++) { subMenu = ref3[l]; subMenu.parentNode.classList.add('has-children'); subMenuToggle = this.createToggle(subMenu, 'sub-menu-toggle', '+'); subMenuToggle.addEventListener('click', function() { var len4, m, open, ref4, results; this.menu.toggler.toggle(); ref4 = this.parentNode.parentNode.querySelectorAll('ul.open'); results = []; for (m = 0, len4 = ref4.length; m < len4; m++) { open = ref4[m]; if (open !== this.menu) { results.push(open.toggler.toggle()); } else { results.push(void 0); } } return results; }); } ref4 = menu.querySelectorAll('.has-children[class*=current] > ul'); for (m = 0, len4 = ref4.length; m < len4; m++) { sub = ref4[m]; sub.classList.add('open'); } document.addEventListener('DOMContentLoaded', this.breaking); window.addEventListener('resize', this.breaking); setTimeout(this.breaking, 3000); } responsiveMenu.prototype.createToggle = function(menu, klass, label) { var toggle; toggle = menu.parentNode.querySelector("." + klass) || document.createElement("button"); toggle.classList.add(klass); toggle.appendChild(document.createTextNode(label)); toggle.menu = menu.nodeName === 'UL' ? menu : menu.querySelector('.menu'); return menu.parentNode.insertBefore(toggle, menu.nextSibling); }; responsiveMenu.prototype.breaking = function() { var div, el, isMobile, k, len2, ref2, windowWidth; document.body.classList.remove('menu-mobile'); document.body.classList.add('menu-desktop'); div = document.createElement('div'); div.style.cssText = "position: absolute; width: " + this.opt.breaking; document.body.appendChild(div); this.menuBreak = div.clientWidth || 0; document.body.removeChild(div); ref2 = document.querySelectorAll("" + this.opt.breaking); for (k = 0, len2 = ref2.length; k < len2; k++) { el = ref2[k]; this.menuBreak += this.getWidth(el); } isMobile = (windowWidth = document.body.clientWidth) <= Math.min(this.menuBreak, this.opt.maxBreaking); document.body.classList.toggle('menu-mobile', isMobile); document.body.classList.toggle('menu-desktop', !isMobile); if (!isMobile) { return document.documentElement.classList.remove('nav-open'); } }; responsiveMenu.prototype.getWidth = function(el) { var clone, width; if (el.clientWidth > 0) { return el.clientWidth; } clone = el.cloneNode(true); clone.style.cssText = 'position: absolute; visibility: hidden; display: block;'; el.parentNode.appendChild(clone); width = clone.clientWidth; el.parentNode.removeChild(clone); return width; }; return responsiveMenu; })(); new responsiveMenu(document.querySelector('#nav'), { breaking: '.logo, .tagline, .menu' }); }).call(this);