bremen_short_url/BackEnd/assets/vendor/stacked-menu/stacked-menu.js

533 lines
15 KiB
JavaScript

/**
* StackedMenu v1.1.12
* A flexible stacked navigation menu.
* Author: Beni Arisandi <bent10@stilearning.com>
*
* https://bent10.gitlab.io/stacked-menu/
*
* Copyright MIT
**/
var StackedMenu = (function () {
'use strict';
var StackedMenu = function StackedMenu(options) {
this.options = {
compact: false,
hoverable: false,
closeOther: true,
align: 'right',
selector: '#stacked-menu',
selectorClass: 'stacked-menu'
};
this.options = this._extend({}, this.options, options);
this.selector = document.querySelector(this.options.selector);
this.items = this.selector ? this.selector.querySelectorAll('.menu-item') : null;
if (!Array.prototype.forEach) {
Array.prototype.forEach = function forEach(cb, arg) {
if(typeof cb !== 'function') { throw new TypeError((cb + " is not a function")) }
var array = this;
arg = arg || this;
for(var i = 0; i < array.length; i++) {
cb.call(arg, array[i], i, array);
}
};
}
this.each = Array.prototype.forEach;
this.classes = {
alignLeft: this.options.selectorClass + '-has-left',
compact: this.options.selectorClass + '-has-compact',
collapsible: this.options.selectorClass + '-has-collapsible',
hoverable: this.options.selectorClass + '-has-hoverable',
hasChild: 'has-child',
hasActive: 'has-active',
hasOpen: 'has-open'
};
this.active = null;
this.open = [];
this.turbolinksAvailable = typeof window.Turbolinks === 'object' && window.Turbolinks.supported;
this.handlerClickDoc = [];
this.handlerOver = [];
this.handlerOut = [];
this.handlerClick = [];
this.init();
};
StackedMenu.prototype._onReady = function _onReady (handler) {
if(document.readyState != 'loading') {
handler();
} else {
document.addEventListener('DOMContentLoaded', handler, false);
}
};
StackedMenu.prototype._handleNavigation = function _handleNavigation (self) {
self.each.call(this.items, function (el) {
self._on(el, 'click', function(e) {
e.stopPropagation();
self.turbolinksAvailable ? e.preventDefault() : null;
if (self._hasChild(el)) {
self.turbolinksAvailable ? null : e.preventDefault();
} else {
self.turbolinksAvailable ? window.Turbolinks.visit(el.firstElementChild.href) : null;
}
});
});
};
StackedMenu.prototype._extend = function _extend (obj) {
obj = obj || {};
var args = arguments;
for (var i = 1; i < args.length; i++) {
if (!args[i]) { continue }
for (var key in args[i]) {
if (args[i].hasOwnProperty(key))
{ obj[key] = args[i][key]; }
}
}
return obj
};
StackedMenu.prototype._emit = function _emit (type, data) {
var e;
if (document.createEvent) {
e = document.createEvent('Event');
e.initEvent(type, true, true);
} else {
e = document.createEventObject();
e.eventType = type;
}
e.eventName = type;
e.data = data || this;
document.createEvent
? this.selector.dispatchEvent(e)
: this.selector.fireEvent('on' + type, e);
};
StackedMenu.prototype._hover = function _hover (el, handlerOver, handlerOut) {
if (el.tagName === 'A') {
this._on(el, 'focus', handlerOver);
this._on(el, 'blur', handlerOut);
} else {
this._on(el, 'mouseover', handlerOver);
this._on(el, 'mouseout', handlerOut);
}
};
StackedMenu.prototype._on = function _on (el, type, handler) {
var types = type.split(' ');
for (var i = 0; i < types.length; i++) {
el[window.addEventListener ? 'addEventListener' : 'attachEvent']( window.addEventListener ? types[i] : ("on" + (types[i])) , handler, false);
}
};
StackedMenu.prototype._off = function _off (el, type, handler) {
var types = type.split(' ');
for (var i = 0; i < types.length; i++) {
el[window.removeEventListener ? 'removeEventListener' : 'detachEvent']( window.removeEventListener ? types[i] : ("on" + (types[i])) , handler, false);
}
};
StackedMenu.prototype._addClass = function _addClass (el, className) {
var classes = className.split(' ');
for (var i = 0; i < classes.length; i++) {
if (el.classList) { el.classList.add(classes[i]); }
else { el.classes[i] += ' ' + classes[i]; }
}
};
StackedMenu.prototype._removeClass = function _removeClass (el, className) {
var classes = className.split(' ');
for (var i = 0; i < classes.length; i++) {
if (el.classList) { el.classList.remove(classes[i]); }
else { el.classes[i] = el.classes[i].replace(new RegExp('(^|\\b)' + classes[i].split(' ').join('|') + '(\\b|$)', 'gi'), ' '); }
}
};
StackedMenu.prototype._hasClass = function _hasClass (el, className) {
if (el.classList) { return el.classList.contains(className) }
return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className)
};
StackedMenu.prototype._hasChild = function _hasChild (el) {
return this._hasClass(el, this.classes.hasChild)
};
StackedMenu.prototype._hasActive = function _hasActive (el) {
return this._hasClass(el, this.classes.hasActive)
};
StackedMenu.prototype._hasOpen = function _hasOpen (el) {
return this._hasClass(el, this.classes.hasOpen)
};
StackedMenu.prototype._isLevelMenu = function _isLevelMenu (el) {
return this._hasClass(el.parentNode.parentNode, this.options.selectorClass)
};
StackedMenu.prototype._menuTrigger = function _menuTrigger (el, index) {
var elHover = el.querySelector('a');
this._off(el, 'mouseover', this.handlerOver[index]);
this._off(el, 'mouseout', this.handlerOut[index]);
this._off(elHover, 'focus', this.handlerOver[index]);
this._off(elHover, 'blur', this.handlerOut[index]);
this._off(el, 'click', this.handlerClick[index]);
this.handlerOver[index] = this.openMenu.bind(this, el);
this.handlerOut[index] = this.closeMenu.bind(this, el);
this.handlerClick[index] = this.toggleMenu.bind(this, el);
if (this.isHoverable()) {
if (this._hasChild(el)) {
this._hover(el, this.handlerOver[index], this.handlerOut[index]);
this._hover(elHover, this.handlerOver[index], this.handlerOut[index]);
}
} else {
this._on(el, 'click', this.handlerClick[index]);
}
};
StackedMenu.prototype._handleInteractions = function _handleInteractions (items) {
var self = this;
this.each.call(items, function (el, i) {
if (self._hasChild(el)) {
self._menuTrigger(el, i);
}
if(self._hasActive(el)) { self.active =el; }
});
};
StackedMenu.prototype._getSubhead = function _getSubhead (el) {
return el.querySelector('.menu-text').textContent
};
StackedMenu.prototype._generateSubhead = function _generateSubhead () {
var self = this;
var menus = this.selector.children;
var link, menu, subhead, label;
this.each.call(menus, function (el) {
self.each.call(el.children, function (child) {
if (self._hasChild(child)) {
self.each.call(child.children, function (cc) {
if(self._hasClass(cc, 'menu-link')) { link = cc; }
});
menu = link.nextElementSibling;
subhead = document.createElement('li');
label = document.createTextNode(self._getSubhead(link));
subhead.appendChild(label);
self._addClass(subhead, 'menu-subhead');
menu.insertBefore(subhead, menu.firstChild);
}
});
});
};
StackedMenu.prototype._handleTabIndex = function _handleTabIndex () {
var self = this;
this.each.call(this.items, function (el) {
var container = el.parentNode.parentNode;
if (!self._isLevelMenu(el)) {
el.querySelector('a').setAttribute('tabindex', '-1');
}
if (self._hasActive(container) || self._hasOpen(container)) {
el.querySelector('a').removeAttribute('tabindex');
}
});
};
StackedMenu.prototype._slide = function _slide (el, direction, speed, easing) {
speed = speed || 300;
easing = easing || 'ease';
var self = this;
var menu = el.querySelector('.menu');
var es = window.getComputedStyle(el)['height'];
var walkSpeed = speed + 50;
var clearSpeed = walkSpeed + 100;
menu.style.transition = "height " + speed + "ms " + easing + ", opacity " + (speed/2) + "ms " + easing + ", visibility " + (speed/2) + "ms " + easing;
if (direction === 'down') {
el.style.overflow = 'hidden';
el.style.height = es;
menu.style.height = 'auto';
var height = window.getComputedStyle(menu)['height'];
menu.style.height = 0;
menu.style.visibility = 'hidden';
menu.style.opacity = 0;
el.style.overflow = '';
el.style.height = '';
setTimeout(function() {
menu.style.height = height;
menu.style.opacity = 1;
menu.style.visibility = 'visible';
}, 0);
} else if (direction === 'up') {
var height$1 = window.getComputedStyle(menu)['height'];
menu.style.height = height$1;
menu.style.visibility = 'visible';
menu.style.opacity = 1;
setTimeout(function() {
menu.style.height = 0;
menu.style.visibility = 'hidden';
menu.style.opacity = 0;
}, 0);
}
var done = new Promise(function(resolve) {
setTimeout(function() {
resolve(el);
self._emit('menu:slide' + direction);
}, walkSpeed);
});
setTimeout(function() {
menu.removeAttribute('style');
}, clearSpeed);
return done
};
StackedMenu.prototype.init = function init () {
var self = this;
var opts = this.options;
this._addClass(this.selector, opts.selectorClass);
this._generateSubhead();
this.compact(opts.compact);
this.hoverable(opts.hoverable);
this._handleTabIndex();
this._handleNavigation(self);
this._on(document.body, 'click', function () {
if (!self.isHoverable() && self.isCompact()) {
self.closeAllMenu();
}
});
this._onReady(function () {
self._emit('menu:init');
});
};
StackedMenu.prototype.openMenu = function openMenu (el, emiter) {
if ( emiter === void 0 ) emiter = true;
if(this._hasActive(el) && !this.isCompact()) { return }
var self = this;
var blockedSlide = this._isLevelMenu(el) && this.isCompact();
if (this.isHoverable() || blockedSlide) {
this._addClass(el, this.classes.hasOpen);
this._handleTabIndex();
} else {
this._slide(el, 'down', 150, 'linear').then(function() {
self._addClass(el, self.classes.hasOpen);
self._handleTabIndex();
});
}
this.open.push(el);
if (this.isHoverable() || (this.isCompact() && !this.hoverable())) {
var clientHeight = document.documentElement.clientHeight;
var child = el.querySelector('.menu');
var pos = child.getBoundingClientRect();
var tolerance = pos.height - 20;
var bottom = clientHeight - pos.top;
var transformOriginX = this.options.align === 'left' ? '100%' : '0px';
if (pos.top >= 500 || tolerance >= bottom) {
child.style.top = 'auto';
child.style.bottom = 0;
child.style.transformOrigin = transformOriginX + " 100% 0";
}
}
if (emiter) {
this._emit('menu:open');
}
return this
};
StackedMenu.prototype.closeMenu = function closeMenu (el, emiter) {
if ( emiter === void 0 ) emiter = true;
var self = this;
var blockedSlide = this._isLevelMenu(el) && this.isCompact();
if (this.isHoverable() || blockedSlide) {
this._removeClass(el, this.classes.hasOpen);
this._handleTabIndex();
} else {
if (!this._hasActive(el)) {
this._slide(el, 'up', 150, 'linear').then(function() {
self._removeClass(el, self.classes.hasOpen);
self._handleTabIndex();
});
}
}
this.each.call(this.open, function (v, i) {
if (el == v) { self.open.splice(i, 1); }
});
if (this.isHoverable() || (this.isCompact() && !this.hoverable())) {
var child = el.querySelector('.menu');
child.style.top = '';
child.style.bottom = '';
child.style.transformOrigin = '';
}
if (emiter) {
this._emit('menu:close');
}
return this
};
StackedMenu.prototype.closeAllMenu = function closeAllMenu () {
var self = this;
this.each.call(this.items, function (el) {
if (self._hasOpen(el)) {
self.closeMenu(el, false);
}
});
return this
};
StackedMenu.prototype.toggleMenu = function toggleMenu (el) {
var method = this._hasOpen(el) ? 'closeMenu': 'openMenu';
var self = this;
var itemParent, elParent;
this.each.call(this.items, function (item) {
itemParent = item.parentNode.parentNode;
itemParent = self._hasClass(itemParent, 'menu-item') ? itemParent : itemParent.parentNode;
elParent = el.parentNode.parentNode;
elParent = self._hasClass(elParent, 'menu-item') ? elParent : elParent.parentNode;
if(!self._hasOpen(elParent) && self._hasChild(itemParent)) {
if (self.options.closeOther || (!self.options.closeOther && self.isCompact())) {
if (self._hasOpen(itemParent)) {
self.closeMenu(itemParent, false);
}
}
}
});
if (this._hasChild(el)) { this[method](el); }
return this
};
StackedMenu.prototype.align = function align (position) {
var method = (position === 'left') ? '_addClass': '_removeClass';
var classes = this.classes;
this[method](this.selector, classes.alignLeft);
this.options.align = position;
this._emit('menu:align');
return this
};
StackedMenu.prototype.isCompact = function isCompact () {
return this.options.compact
};
StackedMenu.prototype.compact = function compact (isCompact) {
var method = (isCompact) ? '_addClass': '_removeClass';
var classes = this.classes;
this[method](this.selector, classes.compact);
this.options.compact = isCompact;
this._handleInteractions(this.items);
this._emit('menu:compact');
return this
};
StackedMenu.prototype.isHoverable = function isHoverable () {
return this.options.hoverable
};
StackedMenu.prototype.hoverable = function hoverable (isHoverable) {
var classes = this.classes;
if (isHoverable) {
this._addClass(this.selector, classes.hoverable);
this._removeClass(this.selector, classes.collapsible);
} else {
this._addClass(this.selector, classes.collapsible);
this._removeClass(this.selector, classes.hoverable);
}
this.options.hoverable = isHoverable;
this._handleInteractions(this.items);
this._emit('menu:hoverable');
return this
};
return StackedMenu;
}());
/* Touch me on Twitter! @stilearningTwit */
//# sourceMappingURL=stacked-menu.js.map