|
|
@ -1,5 +1,5 @@
|
|
|
|
/*!
|
|
|
|
/*!
|
|
|
|
* Native JavaScript for Bootstrap v4.1.0 (https://thednp.github.io/bootstrap.native/)
|
|
|
|
* Native JavaScript for Bootstrap v4.1.2 (https://thednp.github.io/bootstrap.native/)
|
|
|
|
* Copyright 2015-2022 © dnp_theme
|
|
|
|
* Copyright 2015-2022 © dnp_theme
|
|
|
|
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
|
|
|
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@ -545,7 +545,7 @@
|
|
|
|
return normalOps;
|
|
|
|
return normalOps;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var version = "4.1.0";
|
|
|
|
var version = "4.1.2";
|
|
|
|
|
|
|
|
|
|
|
|
const Version = version;
|
|
|
|
const Version = version;
|
|
|
|
|
|
|
|
|
|
|
@ -2814,6 +2814,29 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* This is a shortie for `document.createElement` method
|
|
|
|
|
|
|
|
* which allows you to create a new `HTMLElement` for a given `tagName`
|
|
|
|
|
|
|
|
* or based on an object with specific non-readonly attributes:
|
|
|
|
|
|
|
|
* `id`, `className`, `textContent`, `style`, etc.
|
|
|
|
|
|
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param {Record<string, string> | string} param `tagName` or object
|
|
|
|
|
|
|
|
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
function createElement(param) {
|
|
|
|
|
|
|
|
if (typeof param === 'string') {
|
|
|
|
|
|
|
|
return getDocument().createElement(param);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { tagName } = param;
|
|
|
|
|
|
|
|
const attr = { ...param };
|
|
|
|
|
|
|
|
const newElement = createElement(tagName);
|
|
|
|
|
|
|
|
delete attr.tagName;
|
|
|
|
|
|
|
|
ObjectAssign(newElement, attr);
|
|
|
|
|
|
|
|
return newElement;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {string} */
|
|
|
|
/** @type {string} */
|
|
|
|
const offcanvasString = 'offcanvas';
|
|
|
|
const offcanvasString = 'offcanvas';
|
|
|
|
|
|
|
|
|
|
|
@ -2824,7 +2847,7 @@
|
|
|
|
const offcanvasActiveSelector = `.${offcanvasString}.${showClass}`;
|
|
|
|
const offcanvasActiveSelector = `.${offcanvasString}.${showClass}`;
|
|
|
|
|
|
|
|
|
|
|
|
// any document would suffice
|
|
|
|
// any document would suffice
|
|
|
|
const overlay = getDocument().createElement('div');
|
|
|
|
const overlay = createElement('div');
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Returns the current active modal / offcancas element.
|
|
|
|
* Returns the current active modal / offcancas element.
|
|
|
@ -2863,8 +2886,10 @@
|
|
|
|
* Shows the overlay to the user.
|
|
|
|
* Shows the overlay to the user.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function showOverlay() {
|
|
|
|
function showOverlay() {
|
|
|
|
addClass(overlay, showClass);
|
|
|
|
if (!hasClass(overlay, showClass)) {
|
|
|
|
reflow(overlay);
|
|
|
|
addClass(overlay, showClass);
|
|
|
|
|
|
|
|
reflow(overlay);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -2949,7 +2974,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
if (!modalOverflow && scrollbarWidth) {
|
|
|
|
if (!modalOverflow && scrollbarWidth) {
|
|
|
|
const pad = isRTL(element) ? 'paddingLeft' : 'paddingRight';
|
|
|
|
const pad = isRTL(element) ? 'paddingLeft' : 'paddingRight';
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore -- cannot use `setElementStyle`
|
|
|
|
element.style[pad] = `${scrollbarWidth}px`;
|
|
|
|
element.style[pad] = `${scrollbarWidth}px`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setScrollbar(element, (modalOverflow || clientHeight !== scrollHeight));
|
|
|
|
setScrollbar(element, (modalOverflow || clientHeight !== scrollHeight));
|
|
|
@ -2989,15 +3014,16 @@
|
|
|
|
* @param {Modal} self the `Modal` instance
|
|
|
|
* @param {Modal} self the `Modal` instance
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function afterModalHide(self) {
|
|
|
|
function afterModalHide(self) {
|
|
|
|
const { triggers, element } = self;
|
|
|
|
const { triggers, element, relatedTarget } = self;
|
|
|
|
removeOverlay(element);
|
|
|
|
removeOverlay(element);
|
|
|
|
// @ts-ignore
|
|
|
|
setElementStyle(element, { paddingRight: '' });
|
|
|
|
element.style.paddingRight = '';
|
|
|
|
toggleModalDismiss(self);
|
|
|
|
|
|
|
|
|
|
|
|
if (triggers.length) {
|
|
|
|
const focusElement = showModalEvent.relatedTarget || triggers.find(isVisible);
|
|
|
|
const visibleTrigger = triggers.find((x) => isVisible(x));
|
|
|
|
if (focusElement) focus(focusElement);
|
|
|
|
if (visibleTrigger) focus(visibleTrigger);
|
|
|
|
|
|
|
|
}
|
|
|
|
hiddenModalEvent.relatedTarget = relatedTarget;
|
|
|
|
|
|
|
|
dispatchEvent(element, hiddenModalEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -3019,12 +3045,11 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function beforeModalShow(self) {
|
|
|
|
function beforeModalShow(self) {
|
|
|
|
const { element, hasFade } = self;
|
|
|
|
const { element, hasFade } = self;
|
|
|
|
// @ts-ignore
|
|
|
|
setElementStyle(element, { display: 'block' });
|
|
|
|
element.style.display = 'block';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setModalScrollbar(self);
|
|
|
|
setModalScrollbar(self);
|
|
|
|
if (!getCurrentOpen(element)) {
|
|
|
|
if (!getCurrentOpen(element)) {
|
|
|
|
getDocumentBody(element).style.overflow = 'hidden';
|
|
|
|
setElementStyle(getDocumentBody(element), { overflow: 'hidden' });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addClass(element, showClass);
|
|
|
|
addClass(element, showClass);
|
|
|
@ -3042,11 +3067,10 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function beforeModalHide(self, force) {
|
|
|
|
function beforeModalHide(self, force) {
|
|
|
|
const {
|
|
|
|
const {
|
|
|
|
element, options, relatedTarget, hasFade,
|
|
|
|
element, options, hasFade,
|
|
|
|
} = self;
|
|
|
|
} = self;
|
|
|
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
setElementStyle(element, { display: '' });
|
|
|
|
element.style.display = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// force can also be the transitionEvent object, we wanna make sure it's not
|
|
|
|
// force can also be the transitionEvent object, we wanna make sure it's not
|
|
|
|
// call is not forced and overlay is visible
|
|
|
|
// call is not forced and overlay is visible
|
|
|
@ -3057,11 +3081,6 @@
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
afterModalHide(self);
|
|
|
|
afterModalHide(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toggleModalDismiss(self);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hiddenModalEvent.relatedTarget = relatedTarget;
|
|
|
|
|
|
|
|
dispatchEvent(element, hiddenModalEvent);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MODAL EVENT HANDLERS
|
|
|
|
// MODAL EVENT HANDLERS
|
|
|
@ -3243,14 +3262,15 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (backdrop) {
|
|
|
|
if (backdrop) {
|
|
|
|
if (!currentOpen && !hasClass(overlay, showClass)) {
|
|
|
|
if (!container.contains(overlay)) {
|
|
|
|
appendOverlay(container, hasFade, true);
|
|
|
|
appendOverlay(container, hasFade, true);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
toggleOverlayType(true);
|
|
|
|
toggleOverlayType(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
overlayDelay = getElementTransitionDuration(overlay);
|
|
|
|
overlayDelay = getElementTransitionDuration(overlay);
|
|
|
|
|
|
|
|
|
|
|
|
if (!hasClass(overlay, showClass)) showOverlay();
|
|
|
|
showOverlay();
|
|
|
|
setTimeout(() => beforeModalShow(self), overlayDelay);
|
|
|
|
setTimeout(() => beforeModalShow(self), overlayDelay);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
beforeModalShow(self);
|
|
|
|
beforeModalShow(self);
|
|
|
@ -3398,13 +3418,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
if (!options.scroll) {
|
|
|
|
if (!options.scroll) {
|
|
|
|
setOffCanvasScrollbar(self);
|
|
|
|
setOffCanvasScrollbar(self);
|
|
|
|
getDocumentBody(element).style.overflow = 'hidden';
|
|
|
|
setElementStyle(getDocumentBody(element), { overflow: 'hidden' });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addClass(element, offcanvasTogglingClass);
|
|
|
|
addClass(element, offcanvasTogglingClass);
|
|
|
|
addClass(element, showClass);
|
|
|
|
addClass(element, showClass);
|
|
|
|
// @ts-ignore
|
|
|
|
setElementStyle(element, { visibility: 'visible' });
|
|
|
|
element.style.visibility = 'visible';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emulateTransitionEnd(element, () => showOffcanvasComplete(self));
|
|
|
|
emulateTransitionEnd(element, () => showOffcanvasComplete(self));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3509,17 +3528,13 @@
|
|
|
|
* @param {Offcanvas} self the `Offcanvas` instance
|
|
|
|
* @param {Offcanvas} self the `Offcanvas` instance
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function showOffcanvasComplete(self) {
|
|
|
|
function showOffcanvasComplete(self) {
|
|
|
|
const { element, triggers } = self;
|
|
|
|
const { element } = self;
|
|
|
|
removeClass(element, offcanvasTogglingClass);
|
|
|
|
removeClass(element, offcanvasTogglingClass);
|
|
|
|
|
|
|
|
|
|
|
|
removeAttribute(element, ariaHidden);
|
|
|
|
removeAttribute(element, ariaHidden);
|
|
|
|
setAttribute(element, ariaModal, 'true');
|
|
|
|
setAttribute(element, ariaModal, 'true');
|
|
|
|
setAttribute(element, 'role', 'dialog');
|
|
|
|
setAttribute(element, 'role', 'dialog');
|
|
|
|
|
|
|
|
|
|
|
|
if (triggers.length) {
|
|
|
|
|
|
|
|
triggers.forEach((btn) => setAttribute(btn, ariaExpanded, 'true'));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dispatchEvent(element, shownOffcanvasEvent);
|
|
|
|
dispatchEvent(element, shownOffcanvasEvent);
|
|
|
|
|
|
|
|
|
|
|
|
toggleOffCanvasDismiss(self, true);
|
|
|
|
toggleOffCanvasDismiss(self, true);
|
|
|
@ -3537,14 +3552,10 @@
|
|
|
|
setAttribute(element, ariaHidden, 'true');
|
|
|
|
setAttribute(element, ariaHidden, 'true');
|
|
|
|
removeAttribute(element, ariaModal);
|
|
|
|
removeAttribute(element, ariaModal);
|
|
|
|
removeAttribute(element, 'role');
|
|
|
|
removeAttribute(element, 'role');
|
|
|
|
// @ts-ignore
|
|
|
|
setElementStyle(element, { visibility: '' });
|
|
|
|
element.style.visibility = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (triggers.length) {
|
|
|
|
const visibleTrigger = showOffcanvasEvent.relatedTarget || triggers.find((x) => isVisible(x));
|
|
|
|
triggers.forEach((btn) => setAttribute(btn, ariaExpanded, 'false'));
|
|
|
|
if (visibleTrigger) focus(visibleTrigger);
|
|
|
|
const visibleTrigger = triggers.find((x) => isVisible(x));
|
|
|
|
|
|
|
|
if (visibleTrigger) focus(visibleTrigger);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeOverlay(element);
|
|
|
|
removeOverlay(element);
|
|
|
|
|
|
|
|
|
|
|
@ -3634,13 +3645,14 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (options.backdrop) {
|
|
|
|
if (options.backdrop) {
|
|
|
|
if (!currentOpen) {
|
|
|
|
if (!container.contains(overlay)) {
|
|
|
|
appendOverlay(container, true);
|
|
|
|
appendOverlay(container, true);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
toggleOverlayType();
|
|
|
|
toggleOverlayType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
overlayDelay = getElementTransitionDuration(overlay);
|
|
|
|
overlayDelay = getElementTransitionDuration(overlay);
|
|
|
|
if (!hasClass(overlay, showClass)) showOverlay();
|
|
|
|
showOverlay();
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => beforeOffcanvasShow(self), overlayDelay);
|
|
|
|
setTimeout(() => beforeOffcanvasShow(self), overlayDelay);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -4055,7 +4067,8 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
const mousehoverEvent = 'hover';
|
|
|
|
const mousehoverEvent = 'hover';
|
|
|
|
|
|
|
|
|
|
|
|
let elementUID = 1;
|
|
|
|
let elementUID = 0;
|
|
|
|
|
|
|
|
let elementMapUID = 0;
|
|
|
|
const elementIDMap = new Map();
|
|
|
|
const elementIDMap = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -4066,27 +4079,25 @@
|
|
|
|
* @returns {number} an existing or new unique ID
|
|
|
|
* @returns {number} an existing or new unique ID
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function getUID(element, key) {
|
|
|
|
function getUID(element, key) {
|
|
|
|
elementUID += 1;
|
|
|
|
let result = key ? elementUID : elementMapUID;
|
|
|
|
let elMap = elementIDMap.get(element);
|
|
|
|
|
|
|
|
let result = elementUID;
|
|
|
|
if (key) {
|
|
|
|
|
|
|
|
const elID = getUID(element);
|
|
|
|
if (key && key.length) {
|
|
|
|
const elMap = elementIDMap.get(elID) || new Map();
|
|
|
|
if (elMap) {
|
|
|
|
if (!elementIDMap.has(elID)) {
|
|
|
|
const elMapId = elMap.get(key);
|
|
|
|
elementIDMap.set(elID, elMap);
|
|
|
|
if (!Number.isNaN(elMapId)) {
|
|
|
|
|
|
|
|
result = elMapId;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
elMap.set(key, result);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
elementIDMap.set(element, new Map());
|
|
|
|
|
|
|
|
elMap = elementIDMap.get(element);
|
|
|
|
|
|
|
|
elMap.set(key, result);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!Number.isNaN(elMap)) {
|
|
|
|
if (!elMap.has(key)) {
|
|
|
|
result = elMap;
|
|
|
|
elMap.set(key, result);
|
|
|
|
|
|
|
|
elementUID += 1;
|
|
|
|
|
|
|
|
} else result = elMap.get(key);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
elementIDMap.set(element, result);
|
|
|
|
const elkey = element.id || element;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!elementIDMap.has(elkey)) {
|
|
|
|
|
|
|
|
elementIDMap.set(elkey, result);
|
|
|
|
|
|
|
|
elementMapUID += 1;
|
|
|
|
|
|
|
|
} else result = elementIDMap.get(elkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -5098,6 +5109,8 @@
|
|
|
|
const hiddenTabEvent = OriginalEvent(`hidden.bs.${tabString}`);
|
|
|
|
const hiddenTabEvent = OriginalEvent(`hidden.bs.${tabString}`);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Stores the current active tab and its content
|
|
|
|
|
|
|
|
* for a given `.nav` element.
|
|
|
|
* @type {Map<(HTMLElement | Element), any>}
|
|
|
|
* @type {Map<(HTMLElement | Element), any>}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
const tabPrivate = new Map();
|
|
|
|
const tabPrivate = new Map();
|
|
|
@ -5111,7 +5124,7 @@
|
|
|
|
function triggerTabEnd(self) {
|
|
|
|
function triggerTabEnd(self) {
|
|
|
|
const { tabContent, nav } = self;
|
|
|
|
const { tabContent, nav } = self;
|
|
|
|
|
|
|
|
|
|
|
|
if (tabContent) {
|
|
|
|
if (tabContent && hasClass(tabContent, collapsingClass)) {
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
tabContent.style.height = '';
|
|
|
|
tabContent.style.height = '';
|
|
|
|
removeClass(tabContent, collapsingClass);
|
|
|
|
removeClass(tabContent, collapsingClass);
|
|
|
@ -5125,11 +5138,13 @@
|
|
|
|
* @param {Tab} self the `Tab` instance
|
|
|
|
* @param {Tab} self the `Tab` instance
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function triggerTabShow(self) {
|
|
|
|
function triggerTabShow(self) {
|
|
|
|
const { element, tabContent, nav } = self;
|
|
|
|
const {
|
|
|
|
const { currentHeight, nextHeight } = tabPrivate.get(element);
|
|
|
|
element, tabContent, content: nextContent, nav,
|
|
|
|
|
|
|
|
} = self;
|
|
|
|
const { tab } = nav && tabPrivate.get(nav);
|
|
|
|
const { tab } = nav && tabPrivate.get(nav);
|
|
|
|
|
|
|
|
|
|
|
|
if (tabContent) { // height animation
|
|
|
|
if (tabContent && hasClass(nextContent, fadeClass)) { // height animation
|
|
|
|
|
|
|
|
const { currentHeight, nextHeight } = tabPrivate.get(element);
|
|
|
|
if (currentHeight === nextHeight) {
|
|
|
|
if (currentHeight === nextHeight) {
|
|
|
|
triggerTabEnd(self);
|
|
|
|
triggerTabEnd(self);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -5141,6 +5156,7 @@
|
|
|
|
}, 50);
|
|
|
|
}, 50);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (nav) Timer.clear(nav);
|
|
|
|
} else if (nav) Timer.clear(nav);
|
|
|
|
|
|
|
|
|
|
|
|
shownTabEvent.relatedTarget = tab;
|
|
|
|
shownTabEvent.relatedTarget = tab;
|
|
|
|
dispatchEvent(element, shownTabEvent);
|
|
|
|
dispatchEvent(element, shownTabEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -5156,9 +5172,11 @@
|
|
|
|
const { tab, content } = nav && tabPrivate.get(nav);
|
|
|
|
const { tab, content } = nav && tabPrivate.get(nav);
|
|
|
|
let currentHeight = 0;
|
|
|
|
let currentHeight = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (tabContent) {
|
|
|
|
if (tabContent && hasClass(nextContent, fadeClass)) {
|
|
|
|
[content, nextContent].forEach((c) => addClass(c, 'overflow-hidden'));
|
|
|
|
[content, nextContent].forEach((c) => {
|
|
|
|
currentHeight = content.scrollHeight;
|
|
|
|
addClass(c, 'overflow-hidden');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
currentHeight = content.scrollHeight || 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// update relatedTarget and dispatch event
|
|
|
|
// update relatedTarget and dispatch event
|
|
|
@ -5170,7 +5188,7 @@
|
|
|
|
addClass(nextContent, activeClass);
|
|
|
|
addClass(nextContent, activeClass);
|
|
|
|
removeClass(content, activeClass);
|
|
|
|
removeClass(content, activeClass);
|
|
|
|
|
|
|
|
|
|
|
|
if (tabContent) {
|
|
|
|
if (tabContent && hasClass(nextContent, fadeClass)) {
|
|
|
|
const nextHeight = nextContent.scrollHeight;
|
|
|
|
const nextHeight = nextContent.scrollHeight;
|
|
|
|
tabPrivate.set(element, { currentHeight, nextHeight });
|
|
|
|
tabPrivate.set(element, { currentHeight, nextHeight });
|
|
|
|
|
|
|
|
|
|
|
@ -5178,7 +5196,9 @@
|
|
|
|
// @ts-ignore -- height animation
|
|
|
|
// @ts-ignore -- height animation
|
|
|
|
tabContent.style.height = `${currentHeight}px`;
|
|
|
|
tabContent.style.height = `${currentHeight}px`;
|
|
|
|
reflow(tabContent);
|
|
|
|
reflow(tabContent);
|
|
|
|
[content, nextContent].forEach((c) => removeClass(c, 'overflow-hidden'));
|
|
|
|
[content, nextContent].forEach((c) => {
|
|
|
|
|
|
|
|
removeClass(c, 'overflow-hidden');
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (nextContent && hasClass(nextContent, fadeClass)) {
|
|
|
|
if (nextContent && hasClass(nextContent, fadeClass)) {
|
|
|
@ -5187,8 +5207,11 @@
|
|
|
|
emulateTransitionEnd(nextContent, () => {
|
|
|
|
emulateTransitionEnd(nextContent, () => {
|
|
|
|
triggerTabShow(self);
|
|
|
|
triggerTabShow(self);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}, 17);
|
|
|
|
}, 1);
|
|
|
|
} else { triggerTabShow(self); }
|
|
|
|
} else {
|
|
|
|
|
|
|
|
addClass(nextContent, showClass);
|
|
|
|
|
|
|
|
triggerTabShow(self);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dispatchEvent(tab, hiddenTabEvent);
|
|
|
|
dispatchEvent(tab, hiddenTabEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -5217,6 +5240,16 @@
|
|
|
|
return { tab, content };
|
|
|
|
return { tab, content };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Returns a parent dropdown.
|
|
|
|
|
|
|
|
* @param {HTMLElement | Element} element the `Tab` element
|
|
|
|
|
|
|
|
* @returns {(HTMLElement | Element)?} the parent dropdown
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
function getParentDropdown(element) {
|
|
|
|
|
|
|
|
const dropdown = closest(element, `.${dropdownMenuClasses.join(',.')}`);
|
|
|
|
|
|
|
|
return dropdown ? querySelector(`.${dropdownMenuClasses[0]}-toggle`, dropdown) : null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Toggles on/off the `click` event listener.
|
|
|
|
* Toggles on/off the `click` event listener.
|
|
|
|
* @param {Tab} self the `Tab` instance
|
|
|
|
* @param {Tab} self the `Tab` instance
|
|
|
@ -5273,7 +5306,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
// event targets
|
|
|
|
// event targets
|
|
|
|
/** @type {(HTMLElement | Element)?} */
|
|
|
|
/** @type {(HTMLElement | Element)?} */
|
|
|
|
self.dropdown = nav && querySelector(`.${dropdownMenuClasses[0]}-toggle`, nav);
|
|
|
|
self.dropdown = getParentDropdown(element);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// show first Tab instance of none is shown
|
|
|
|
|
|
|
|
// suggested on #432
|
|
|
|
|
|
|
|
const { tab } = getActiveTab(self);
|
|
|
|
|
|
|
|
if (nav && !tab) {
|
|
|
|
|
|
|
|
const firstTab = querySelector(tabSelector, nav);
|
|
|
|
|
|
|
|
const firstTabContent = firstTab && getTargetElement(firstTab);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (firstTabContent) {
|
|
|
|
|
|
|
|
addClass(firstTab, activeClass);
|
|
|
|
|
|
|
|
addClass(firstTabContent, showClass);
|
|
|
|
|
|
|
|
addClass(firstTabContent, activeClass);
|
|
|
|
|
|
|
|
setAttribute(element, ariaSelected, 'true');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// add event listener
|
|
|
|
// add event listener
|
|
|
|
toggleTabHandler(self, true);
|
|
|
|
toggleTabHandler(self, true);
|
|
|
@ -5301,20 +5349,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
// update relatedTarget and dispatch
|
|
|
|
// update relatedTarget and dispatch
|
|
|
|
hideTabEvent.relatedTarget = element;
|
|
|
|
hideTabEvent.relatedTarget = element;
|
|
|
|
|
|
|
|
|
|
|
|
dispatchEvent(tab, hideTabEvent);
|
|
|
|
dispatchEvent(tab, hideTabEvent);
|
|
|
|
if (hideTabEvent.defaultPrevented) return;
|
|
|
|
if (hideTabEvent.defaultPrevented) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (nav) Timer.set(nav, () => {}, 17);
|
|
|
|
|
|
|
|
removeClass(tab, activeClass);
|
|
|
|
|
|
|
|
setAttribute(tab, ariaSelected, 'false');
|
|
|
|
|
|
|
|
addClass(element, activeClass);
|
|
|
|
addClass(element, activeClass);
|
|
|
|
setAttribute(element, ariaSelected, 'true');
|
|
|
|
setAttribute(element, ariaSelected, 'true');
|
|
|
|
|
|
|
|
|
|
|
|
if (dropdown) {
|
|
|
|
const activeDropdown = getParentDropdown(tab);
|
|
|
|
// @ts-ignore
|
|
|
|
if (activeDropdown && hasClass(activeDropdown, activeClass)) {
|
|
|
|
if (!hasClass(element.parentNode, dropdownMenuClass)) {
|
|
|
|
removeClass(activeDropdown, activeClass);
|
|
|
|
if (hasClass(dropdown, activeClass)) removeClass(dropdown, activeClass);
|
|
|
|
}
|
|
|
|
} else if (!hasClass(dropdown, activeClass)) addClass(dropdown, activeClass);
|
|
|
|
|
|
|
|
|
|
|
|
if (nav) {
|
|
|
|
|
|
|
|
Timer.set(nav, () => {
|
|
|
|
|
|
|
|
removeClass(tab, activeClass);
|
|
|
|
|
|
|
|
setAttribute(tab, ariaSelected, 'false');
|
|
|
|
|
|
|
|
if (dropdown && !hasClass(dropdown, activeClass)) addClass(dropdown, activeClass);
|
|
|
|
|
|
|
|
}, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (hasClass(content, fadeClass)) {
|
|
|
|
if (hasClass(content, fadeClass)) {
|
|
|
|