/*! * Bootstrap collapse.js v5.0.0-beta3 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) : typeof define === 'function' && define.amd ? define(['./dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Collapse = factory(global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base)); }(this, (function (Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data); var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.0-beta3): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const MILLISECONDS_MULTIPLIER = 1000; const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const toType = obj => { if (obj === null || obj === undefined) { return `${obj}`; } return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); }; const getSelector = element => { let selector = element.getAttribute('data-bs-target'); if (!selector || selector === '#') { let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, // so everything starting with `#` or `.`. If a "real" URL is used as the selector, // `document.querySelector` will rightfully complain it is invalid. // See https://github.com/twbs/bootstrap/issues/32273 if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) { return null; } // Just in case some CMS puts out a full URL with the anchor appended if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) { hrefAttr = '#' + hrefAttr.split('#')[1]; } selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null; } return selector; }; const getSelectorFromElement = element => { const selector = getSelector(element); if (selector) { return document.querySelector(selector) ? selector : null; } return null; }; const getElementFromSelector = element => { const selector = getSelector(element); return selector ? document.querySelector(selector) : null; }; const getTransitionDurationFromElement = element => { if (!element) { return 0; } // Get transition-duration of the element let { transitionDuration, transitionDelay } = window.getComputedStyle(element); const floatTransitionDuration = Number.parseFloat(transitionDuration); const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found if (!floatTransitionDuration && !floatTransitionDelay) { return 0; } // If multiple durations are defined, take the first transitionDuration = transitionDuration.split(',')[0]; transitionDelay = transitionDelay.split(',')[0]; return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; }; const triggerTransitionEnd = element => { element.dispatchEvent(new Event(TRANSITION_END)); }; const isElement = obj => (obj[0] || obj).nodeType; const emulateTransitionEnd = (element, duration) => { let called = false; const durationPadding = 5; const emulatedDuration = duration + durationPadding; function listener() { called = true; element.removeEventListener(TRANSITION_END, listener); } element.addEventListener(TRANSITION_END, listener); setTimeout(() => { if (!called) { triggerTransitionEnd(element); } }, emulatedDuration); }; const typeCheckConfig = (componentName, config, configTypes) => { Object.keys(configTypes).forEach(property => { const expectedTypes = configTypes[property]; const value = config[property]; const valueType = value && isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new TypeError(`${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + `but expected type "${expectedTypes}".`); } }); }; const reflow = element => element.offsetHeight; const getjQuery = () => { const { jQuery } = window; if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { return jQuery; } return null; }; const onDOMContentLoaded = callback => { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', callback); } else { callback(); } }; const defineJQueryPlugin = (name, plugin) => { onDOMContentLoaded(() => { const $ = getjQuery(); /* istanbul ignore if */ if ($) { const JQUERY_NO_CONFLICT = $.fn[name]; $.fn[name] = plugin.jQueryInterface; $.fn[name].Constructor = plugin; $.fn[name].noConflict = () => { $.fn[name] = JQUERY_NO_CONFLICT; return plugin.jQueryInterface; }; } }); }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.0-beta3): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME = 'collapse'; const DATA_KEY = 'bs.collapse'; const EVENT_KEY = `.${DATA_KEY}`; const DATA_API_KEY = '.data-api'; const Default = { toggle: true, parent: '' }; const DefaultType = { toggle: 'boolean', parent: '(string|element)' }; const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_HIDE = `hide${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSED = 'collapsed'; const WIDTH = 'width'; const HEIGHT = 'height'; const SELECTOR_ACTIVES = '.show, .collapsing'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Collapse extends BaseComponent__default['default'] { constructor(element, config) { super(element); this._isTransitioning = false; this._config = this._getConfig(config); this._triggerArray = SelectorEngine__default['default'].find(`${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` + `${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`); const toggleList = SelectorEngine__default['default'].find(SELECTOR_DATA_TOGGLE); for (let i = 0, len = toggleList.length; i < len; i++) { const elem = toggleList[i]; const selector = getSelectorFromElement(elem); const filterElement = SelectorEngine__default['default'].find(selector).filter(foundElem => foundElem === this._element); if (selector !== null && filterElement.length) { this._selector = selector; this._triggerArray.push(elem); } } this._parent = this._config.parent ? this._getParent() : null; if (!this._config.parent) { this._addAriaAndCollapsedClass(this._element, this._triggerArray); } if (this._config.toggle) { this.toggle(); } } // Getters static get Default() { return Default; } static get DATA_KEY() { return DATA_KEY; } // Public toggle() { if (this._element.classList.contains(CLASS_NAME_SHOW)) { this.hide(); } else { this.show(); } } show() { if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) { return; } let actives; let activesData; if (this._parent) { actives = SelectorEngine__default['default'].find(SELECTOR_ACTIVES, this._parent).filter(elem => { if (typeof this._config.parent === 'string') { return elem.getAttribute('data-bs-parent') === this._config.parent; } return elem.classList.contains(CLASS_NAME_COLLAPSE); }); if (actives.length === 0) { actives = null; } } const container = SelectorEngine__default['default'].findOne(this._selector); if (actives) { const tempActiveData = actives.find(elem => container !== elem); activesData = tempActiveData ? Data__default['default'].get(tempActiveData, DATA_KEY) : null; if (activesData && activesData._isTransitioning) { return; } } const startEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW); if (startEvent.defaultPrevented) { return; } if (actives) { actives.forEach(elemActive => { if (container !== elemActive) { Collapse.collapseInterface(elemActive, 'hide'); } if (!activesData) { Data__default['default'].set(elemActive, DATA_KEY, null); } }); } const dimension = this._getDimension(); this._element.classList.remove(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.style[dimension] = 0; if (this._triggerArray.length) { this._triggerArray.forEach(element => { element.classList.remove(CLASS_NAME_COLLAPSED); element.setAttribute('aria-expanded', true); }); } this.setTransitioning(true); const complete = () => { this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.style[dimension] = ''; this.setTransitioning(false); EventHandler__default['default'].trigger(this._element, EVENT_SHOWN); }; const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); const scrollSize = `scroll${capitalizedDimension}`; const transitionDuration = getTransitionDurationFromElement(this._element); EventHandler__default['default'].one(this._element, 'transitionend', complete); emulateTransitionEnd(this._element, transitionDuration); this._element.style[dimension] = `${this._element[scrollSize]}px`; } hide() { if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) { return; } const startEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); if (startEvent.defaultPrevented) { return; } const dimension = this._getDimension(); this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; reflow(this._element); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); const triggerArrayLength = this._triggerArray.length; if (triggerArrayLength > 0) { for (let i = 0; i < triggerArrayLength; i++) { const trigger = this._triggerArray[i]; const elem = getElementFromSelector(trigger); if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { trigger.classList.add(CLASS_NAME_COLLAPSED); trigger.setAttribute('aria-expanded', false); } } } this.setTransitioning(true); const complete = () => { this.setTransitioning(false); this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE); EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); }; this._element.style[dimension] = ''; const transitionDuration = getTransitionDurationFromElement(this._element); EventHandler__default['default'].one(this._element, 'transitionend', complete); emulateTransitionEnd(this._element, transitionDuration); } setTransitioning(isTransitioning) { this._isTransitioning = isTransitioning; } dispose() { super.dispose(); this._config = null; this._parent = null; this._triggerArray = null; this._isTransitioning = null; } // Private _getConfig(config) { config = { ...Default, ...config }; config.toggle = Boolean(config.toggle); // Coerce string values typeCheckConfig(NAME, config, DefaultType); return config; } _getDimension() { return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT; } _getParent() { let { parent } = this._config; if (isElement(parent)) { // it's a jQuery object if (typeof parent.jquery !== 'undefined' || typeof parent[0] !== 'undefined') { parent = parent[0]; } } else { parent = SelectorEngine__default['default'].findOne(parent); } const selector = `${SELECTOR_DATA_TOGGLE}[data-bs-parent="${parent}"]`; SelectorEngine__default['default'].find(selector, parent).forEach(element => { const selected = getElementFromSelector(element); this._addAriaAndCollapsedClass(selected, [element]); }); return parent; } _addAriaAndCollapsedClass(element, triggerArray) { if (!element || !triggerArray.length) { return; } const isOpen = element.classList.contains(CLASS_NAME_SHOW); triggerArray.forEach(elem => { if (isOpen) { elem.classList.remove(CLASS_NAME_COLLAPSED); } else { elem.classList.add(CLASS_NAME_COLLAPSED); } elem.setAttribute('aria-expanded', isOpen); }); } // Static static collapseInterface(element, config) { let data = Data__default['default'].get(element, DATA_KEY); const _config = { ...Default, ...Manipulator__default['default'].getDataAttributes(element), ...(typeof config === 'object' && config ? config : {}) }; if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) { _config.toggle = false; } if (!data) { data = new Collapse(element, _config); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } } static jQueryInterface(config) { return this.each(function () { Collapse.collapseInterface(this, config); }); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { event.preventDefault(); } const triggerData = Manipulator__default['default'].getDataAttributes(this); const selector = getSelectorFromElement(this); const selectorElements = SelectorEngine__default['default'].find(selector); selectorElements.forEach(element => { const data = Data__default['default'].get(element, DATA_KEY); let config; if (data) { // update parent attribute if (data._parent === null && typeof triggerData.parent === 'string') { data._config.parent = triggerData.parent; data._parent = data._getParent(); } config = 'toggle'; } else { config = triggerData; } Collapse.collapseInterface(element, config); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Collapse to jQuery only if jQuery is present */ defineJQueryPlugin(NAME, Collapse); return Collapse; }))); //# sourceMappingURL=collapse.js.map