minsky-kit
Version:
Kit of components for MINSKY web agency
139 lines (111 loc) • 3.76 kB
JavaScript
// imports
import Component from 'minsky-kit/js/components/Component';
import tippy from 'tippy.js';
// class definition
export default class NavOverflow extends Component {
// constructor
constructor (args = {}, objectName = 'NavOverflow') {
// super
super(args, objectName);
this.items = Array.from(this.$el.querySelectorAll('.menu__item'));
this.$menuList = this.$el.querySelector('.menu__list');
this.$overlapEl = args.$overlapEl;
// list
this.overflowList = document.createElement('ul');
this.overflowList.classList.add('menu__overflow-list');
this.$moreEl = this.$el.querySelector('.menu__item--more');
// tippy
this.tippy = tippy(this.$moreEl, {
trigger: 'mouseenter focus focusin',
content: this.overflowList,
placement: 'bottom-start',
interactive: true,
});
this.overflowItems = [];
// first init
this.update();
}
// methods
destroy () {
this.$el.classList.remove('menu--main--show-more');
if (this.overflowItems.length) {
this.overflowItems.reverse();
this.overflowItems.forEach(($oi) => {
this.$menuList.insertBefore($oi, this.$moreEl);
});
}
super.destroy();
}
update () {
// calculate overflow items
if (this.hasOverlap()) {
this.cut();
}
else {
if (this.canShift()) {
this.shift();
}
}
}
cut () {
const overflowItems = [];
if (!this.overflowItems.length) {
overflowItems.push(this.items[this.items.length - 2]);
overflowItems.push(this.items[this.items.length - 3]);
}
else {
overflowItems.push(this.items[this.items.length - (this.overflowItems.length + 1)]);
}
// add them to list
overflowItems.forEach(($oi) => {
$oi.dataset.originalWidth = $oi.offsetWidth;
this.overflowList.insertBefore($oi, this.overflowList.firstChild);
});
this.overflowItems.push(...overflowItems);
// add active class
if (this.overflowItems.length) {
this.$el.classList.add('menu--main--show-more');
}
else {
this.$el.classList.remove('menu--main--show-more');
}
if (this.hasOverlap()) {
this.cut();
}
}
shift () {
this.$menuList.insertBefore(this.overflowItems.pop(), this.$moreEl);
// add active class
if (this.overflowItems.length) {
this.$el.classList.add('menu--main--show-more');
}
else {
this.$el.classList.remove('menu--main--show-more');
}
if (this.canShift()) {
this.shift();
}
}
hasOverlap () {
const overlapDimensions = this.$overlapEl.getBoundingClientRect();
const menuDimensions = this.$el.getBoundingClientRect();
return overlapDimensions.x <= menuDimensions.right;
}
canShift () {
const overlapDimensions = this.$overlapEl.getBoundingClientRect();
const menuDimensions = this.$el.getBoundingClientRect();
// check for next el to pop
if (this.overflowItems.length) {
const $nextEl = this.overflowItems[0];
if ((overlapDimensions.x - menuDimensions.right) > (Number($nextEl.dataset.originalWidth) * 2)) {
return true;
}
return false;
}
return false;
}
// getters & setters
static get version () { return VERSION; }
}
// Utils
// Event handlers