2020-08-30 16:30:50 +08:00
|
|
|
/*!
|
|
|
|
* Native JavaScript for Bootstrap v3.0.10 (https://thednp.github.io/bootstrap.native/)
|
|
|
|
* Copyright 2015-2020 © dnp_theme
|
|
|
|
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
|
|
|
*/
|
|
|
|
|
2020-10-01 17:10:40 +08:00
|
|
|
(doc => {
|
|
|
|
const setFocus = element => element.focus ? element.focus() : element.setActive();
|
2020-08-30 16:30:50 +08:00
|
|
|
|
2020-10-01 17:10:40 +08:00
|
|
|
this.BSN = {
|
2020-09-02 03:50:17 +08:00
|
|
|
Dropdown: function(element) {
|
|
|
|
let menu, menuItems = [];
|
|
|
|
const self = this,
|
|
|
|
parent = element.parentNode,
|
|
|
|
preventEmptyAnchor = e => {
|
|
|
|
const t = e.target, href = t.href || (t.parentNode && t.parentNode.href);
|
|
|
|
(href && href.slice(-1) === '#') && e.preventDefault();
|
|
|
|
},
|
2021-02-19 04:06:19 +08:00
|
|
|
open = bool => {
|
|
|
|
menu && menu.classList.toggle('show', bool);
|
|
|
|
parent.classList.toggle('show', bool);
|
|
|
|
element.setAttribute('aria-expanded', bool);
|
|
|
|
element.open = bool;
|
|
|
|
if (bool) {
|
|
|
|
element.removeEventListener('click',clickHandler);
|
|
|
|
} else {
|
|
|
|
setTimeout(() => element.addEventListener('click',clickHandler), 1);
|
|
|
|
}
|
|
|
|
},
|
2020-09-02 03:50:17 +08:00
|
|
|
toggleEvents = () => {
|
2020-10-01 17:10:40 +08:00
|
|
|
let action = (element.open ? 'add' : 'remove') + 'EventListener';
|
|
|
|
doc[action]('click',dismissHandler);
|
|
|
|
doc[action]('keydown',preventScroll);
|
|
|
|
doc[action]('keyup',keyHandler);
|
|
|
|
doc[action]('focus',dismissHandler);
|
2020-09-02 03:50:17 +08:00
|
|
|
},
|
|
|
|
dismissHandler = e => {
|
|
|
|
let eventTarget = e.target,
|
|
|
|
inside = menu.contains(eventTarget),
|
2020-10-12 21:04:11 +08:00
|
|
|
hasData = eventTarget && (
|
|
|
|
(eventTarget.getAttribute && eventTarget.getAttribute('data-toggle'))
|
2020-09-02 03:50:17 +08:00
|
|
|
|| (eventTarget.parentNode && eventTarget.parentNode.getAttribute('data-toggle')));
|
2020-10-01 17:10:40 +08:00
|
|
|
if (!(hasData && inside)
|
|
|
|
&& !(e.type === 'focus' && (inside || eventTarget === element))
|
2020-09-02 03:50:17 +08:00
|
|
|
) {
|
2020-10-01 17:10:40 +08:00
|
|
|
self.hide();
|
|
|
|
preventEmptyAnchor(e);
|
2020-09-02 03:50:17 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
clickHandler = e => {
|
|
|
|
self.show();
|
|
|
|
preventEmptyAnchor(e);
|
|
|
|
},
|
2020-10-01 17:10:40 +08:00
|
|
|
preventScroll = e => (e.key === 'ArrowUp' || e.key === 'ArrowDown') && e.preventDefault(),
|
2020-09-02 03:50:17 +08:00
|
|
|
keyHandler = e => {
|
2020-10-26 21:34:59 +08:00
|
|
|
if (e.key === 'Escape') {
|
2020-09-02 03:50:17 +08:00
|
|
|
self.toggle();
|
2020-10-26 21:34:59 +08:00
|
|
|
} else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
|
|
let activeItem = doc.activeElement,
|
|
|
|
isMenuButton = activeItem === element,
|
|
|
|
idx = isMenuButton ? 0 : menuItems.indexOf(activeItem);
|
|
|
|
if (parent.contains(activeItem)) {
|
|
|
|
if (!isMenuButton) {
|
|
|
|
idx = e.key === 'ArrowUp' ? (idx > 1 ? idx-1 : 0)
|
|
|
|
: e.key === 'ArrowDown' ? (idx < menuItems.length-1 ? idx+1 : idx) : idx;
|
|
|
|
}
|
|
|
|
menuItems[idx] && setFocus(menuItems[idx]);
|
|
|
|
} else {
|
|
|
|
console.log('activeElement not in menu');
|
|
|
|
}
|
2020-09-02 03:50:17 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
self.show = () => {
|
|
|
|
menu = parent.querySelector('.dropdown-menu');
|
2020-10-26 21:34:59 +08:00
|
|
|
menuItems = [...menu.querySelectorAll('A')].filter(item => 'none' != item.parentNode.style.display);
|
2020-09-02 03:50:17 +08:00
|
|
|
!('tabindex' in menu) && menu.setAttribute('tabindex', '0');
|
2021-02-19 04:06:19 +08:00
|
|
|
open(true);
|
2020-09-02 03:50:17 +08:00
|
|
|
setTimeout(() => {
|
|
|
|
setFocus( menu.getElementsByTagName('INPUT')[0] || element );
|
|
|
|
toggleEvents();
|
|
|
|
},1);
|
2020-08-30 22:17:36 +08:00
|
|
|
};
|
2020-09-02 03:50:17 +08:00
|
|
|
self.hide = () => {
|
2021-02-19 04:06:19 +08:00
|
|
|
open(false);
|
2020-08-30 22:17:36 +08:00
|
|
|
toggleEvents();
|
2020-09-02 03:50:17 +08:00
|
|
|
setFocus(element);
|
|
|
|
};
|
2020-10-26 21:34:59 +08:00
|
|
|
self.toggle = () => element.open ? self.hide() : self.show();
|
2021-02-19 04:06:19 +08:00
|
|
|
open(false);
|
2020-09-02 03:50:17 +08:00
|
|
|
element.Dropdown = self;
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-01 17:10:40 +08:00
|
|
|
})(document);
|