110 lines
3.4 KiB
JavaScript
110 lines
3.4 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
/**
|
|
*
|
|
* Asidenav Utility
|
|
* Correctly positions hovered asidenav submenus and handles the favorites button on mobile
|
|
*
|
|
* Attribute: uw-asidenav
|
|
*
|
|
* Example usage:
|
|
* <div uw-asidenav>
|
|
* <div .asidenav>
|
|
* <div .asidenav__box>
|
|
* <ul .asidenav__list.list--iconless>
|
|
* <li .asidenav__list-item>
|
|
* <a .asidenav__link-wrapper href="#">
|
|
* <div .asidenav__link-shorthand>EIP
|
|
* <div .asidenav__link-label>Einführung in die Programmierung
|
|
* <div .asidenav__nested-list-wrapper>
|
|
* <ul .asidenav__nested-list.list--iconless>
|
|
* Übungsblätter
|
|
* ...
|
|
*
|
|
*/
|
|
|
|
var ASIDENAV_UTIL_NAME = 'asidenav';
|
|
var ASIDENAV_UTIL_SELECTOR = '[uw-asidenav]';
|
|
|
|
var FAVORITES_BTN_CLASS = 'navbar__list-item--favorite';
|
|
var FAVORITES_BTN_ACTIVE_CLASS = 'navbar__list-item--active';
|
|
var ASIDENAV_INITIALIZED_CLASS = 'asidenav--initialized';
|
|
var ASIDENAV_EXPANDED_CLASS = 'main__aside--expanded';
|
|
var ASIDENAV_LIST_ITEM_CLASS = 'asidenav__list-item';
|
|
var ASIDENAV_SUBMENU_CLASS = 'asidenav__nested-list-wrapper';
|
|
|
|
var asidenavUtil = function(element) {
|
|
|
|
function init() {
|
|
if (!element) {
|
|
throw new Error('Asidenav utility cannot be setup without an element!');
|
|
}
|
|
|
|
if (element.classList.contains(ASIDENAV_INITIALIZED_CLASS)) {
|
|
return false;
|
|
}
|
|
|
|
initFavoritesButton();
|
|
initAsidenavSubmenus();
|
|
|
|
// mark initialized
|
|
element.classList.add(ASIDENAV_INITIALIZED_CLASS);
|
|
|
|
return {
|
|
name: ASIDENAV_UTIL_NAME,
|
|
element: element,
|
|
destroy: function() {},
|
|
};
|
|
}
|
|
|
|
function initFavoritesButton() {
|
|
var favoritesBtn = document.querySelector('.' + FAVORITES_BTN_CLASS);
|
|
favoritesBtn.addEventListener('click', function(event) {
|
|
favoritesBtn.classList.toggle(FAVORITES_BTN_ACTIVE_CLASS);
|
|
element.classList.toggle(ASIDENAV_EXPANDED_CLASS);
|
|
event.preventDefault();
|
|
}, true);
|
|
}
|
|
|
|
function initAsidenavSubmenus() {
|
|
var asidenavLinksWithSubmenus = Array.from(element.querySelectorAll('.' + ASIDENAV_LIST_ITEM_CLASS))
|
|
.map(function(listItem) {
|
|
var submenu = listItem.querySelector('.' + ASIDENAV_SUBMENU_CLASS);
|
|
return { listItem, submenu };
|
|
}).filter(function(union) {
|
|
return union.submenu !== null;
|
|
});
|
|
|
|
asidenavLinksWithSubmenus.forEach(function(union) {
|
|
union.listItem.addEventListener('mouseover', createMouseoverHandler(union));
|
|
});
|
|
}
|
|
|
|
function createMouseoverHandler(union) {
|
|
return function mouseoverHanlder(event) {
|
|
var rectListItem = union.listItem.getBoundingClientRect();
|
|
var rectSubMenu = union.submenu.getBoundingClientRect();
|
|
|
|
union.submenu.style.left = (rectListItem.left + rectListItem.width) + 'px';
|
|
if (window.innerHeight - rectListItem.top < rectSubMenu.height) {
|
|
union.submenu.style.top = (rectListItem.top + rectListItem.height - rectSubMenu.height) + 'px';
|
|
} else {
|
|
union.submenu.style.top = rectListItem.top + 'px';
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
return init();
|
|
};
|
|
|
|
if (UtilRegistry) {
|
|
UtilRegistry.register({
|
|
name: ASIDENAV_UTIL_NAME,
|
|
selector: ASIDENAV_UTIL_SELECTOR,
|
|
setup: asidenavUtil,
|
|
});
|
|
}
|
|
})();
|