2017-08-07 01:01:49 +08:00
|
|
|
/**
|
|
|
|
* Dropdown
|
|
|
|
* Provides some simple logic to create simple dropdown menus.
|
|
|
|
*/
|
|
|
|
class DropDown {
|
|
|
|
|
|
|
|
constructor(elem) {
|
|
|
|
this.container = elem;
|
2019-05-05 21:43:26 +08:00
|
|
|
this.menu = elem.querySelector('.dropdown-menu, [dropdown-menu]');
|
|
|
|
this.moveMenu = elem.hasAttribute('dropdown-move-menu');
|
2017-08-07 01:01:49 +08:00
|
|
|
this.toggle = elem.querySelector('[dropdown-toggle]');
|
2019-05-05 21:43:26 +08:00
|
|
|
this.body = document.body;
|
2017-08-07 01:01:49 +08:00
|
|
|
this.setupListeners();
|
|
|
|
}
|
|
|
|
|
2019-05-05 21:43:26 +08:00
|
|
|
show(event) {
|
2019-05-07 00:59:17 +08:00
|
|
|
this.hideAll();
|
2019-05-05 21:43:26 +08:00
|
|
|
|
2017-08-07 01:01:49 +08:00
|
|
|
this.menu.style.display = 'block';
|
|
|
|
this.menu.classList.add('anim', 'menuIn');
|
2019-05-05 21:43:26 +08:00
|
|
|
|
|
|
|
if (this.moveMenu) {
|
|
|
|
// Move to body to prevent being trapped within scrollable sections
|
|
|
|
this.rect = this.menu.getBoundingClientRect();
|
|
|
|
this.body.appendChild(this.menu);
|
|
|
|
this.menu.style.position = 'fixed';
|
|
|
|
this.menu.style.left = `${this.rect.left}px`;
|
|
|
|
this.menu.style.top = `${this.rect.top}px`;
|
|
|
|
this.menu.style.width = `${this.rect.width}px`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set listener to hide on mouse leave or window click
|
|
|
|
this.menu.addEventListener('mouseleave', this.hide.bind(this));
|
|
|
|
window.addEventListener('click', event => {
|
|
|
|
if (!this.menu.contains(event.target)) {
|
|
|
|
this.hide();
|
|
|
|
}
|
|
|
|
});
|
2017-08-07 01:01:49 +08:00
|
|
|
|
|
|
|
// Focus on first input if existing
|
|
|
|
let input = this.menu.querySelector('input');
|
|
|
|
if (input !== null) input.focus();
|
2019-05-05 21:43:26 +08:00
|
|
|
|
|
|
|
event.stopPropagation();
|
2017-08-07 01:01:49 +08:00
|
|
|
}
|
|
|
|
|
2019-05-07 00:59:17 +08:00
|
|
|
hideAll() {
|
|
|
|
for (let dropdown of window.components.dropdown) {
|
|
|
|
dropdown.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-07 01:01:49 +08:00
|
|
|
hide() {
|
|
|
|
this.menu.style.display = 'none';
|
|
|
|
this.menu.classList.remove('anim', 'menuIn');
|
2019-05-05 21:43:26 +08:00
|
|
|
if (this.moveMenu) {
|
|
|
|
this.menu.style.position = '';
|
|
|
|
this.menu.style.left = '';
|
|
|
|
this.menu.style.top = '';
|
|
|
|
this.menu.style.width = '';
|
|
|
|
this.container.appendChild(this.menu);
|
|
|
|
}
|
2017-08-07 01:01:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
setupListeners() {
|
|
|
|
// Hide menu on option click
|
|
|
|
this.container.addEventListener('click', event => {
|
|
|
|
let possibleChildren = Array.from(this.menu.querySelectorAll('a'));
|
|
|
|
if (possibleChildren.indexOf(event.target) !== -1) this.hide();
|
|
|
|
});
|
|
|
|
// Show dropdown on toggle click
|
|
|
|
this.toggle.addEventListener('click', this.show.bind(this));
|
|
|
|
// Hide menu on enter press
|
|
|
|
this.container.addEventListener('keypress', event => {
|
|
|
|
if (event.keyCode !== 13) return true;
|
|
|
|
event.preventDefault();
|
|
|
|
this.hide();
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-10 05:17:35 +08:00
|
|
|
export default DropDown;
|