Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
/*** --------------------------------------------------------------------------* Bootstrap (v4.6.2): collapse.js* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)* --------------------------------------------------------------------------*/import $ from 'jquery'import Util from './util'/*** Constants*/const NAME = 'collapse'const VERSION = '4.6.2'const DATA_KEY = 'bs.collapse'const EVENT_KEY = `.${DATA_KEY}`const DATA_API_KEY = '.data-api'const JQUERY_NO_CONFLICT = $.fn[NAME]const CLASS_NAME_SHOW = 'show'const CLASS_NAME_COLLAPSE = 'collapse'const CLASS_NAME_COLLAPSING = 'collapsing'const CLASS_NAME_COLLAPSED = 'collapsed'const DIMENSION_WIDTH = 'width'const DIMENSION_HEIGHT = 'height'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 SELECTOR_ACTIVES = '.show, .collapsing'const SELECTOR_DATA_TOGGLE = '[data-toggle="collapse"]'const Default = {toggle: true,parent: ''}const DefaultType = {toggle: 'boolean',parent: '(string|element)'}/*** Class definition*/class Collapse {constructor(element, config) {this._isTransitioning = falsethis._element = elementthis._config = this._getConfig(config)this._triggerArray = [].slice.call(document.querySelectorAll(`[data-toggle="collapse"][href="#${element.id}"],` +`[data-toggle="collapse"][data-target="#${element.id}"]`))const toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))for (let i = 0, len = toggleList.length; i < len; i++) {const elem = toggleList[i]const selector = Util.getSelectorFromElement(elem)const filterElement = [].slice.call(document.querySelectorAll(selector)).filter(foundElem => foundElem === element)if (selector !== null && filterElement.length > 0) {this._selector = selectorthis._triggerArray.push(elem)}}this._parent = this._config.parent ? this._getParent() : nullif (!this._config.parent) {this._addAriaAndCollapsedClass(this._element, this._triggerArray)}if (this._config.toggle) {this.toggle()}}// Gettersstatic get VERSION() {return VERSION}static get Default() {return Default}// Publictoggle() {if ($(this._element).hasClass(CLASS_NAME_SHOW)) {this.hide()} else {this.show()}}show() {if (this._isTransitioning ||$(this._element).hasClass(CLASS_NAME_SHOW)) {return}let activeslet activesDataif (this._parent) {actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES)).filter(elem => {if (typeof this._config.parent === 'string') {return elem.getAttribute('data-parent') === this._config.parent}return elem.classList.contains(CLASS_NAME_COLLAPSE)})if (actives.length === 0) {actives = null}}if (actives) {activesData = $(actives).not(this._selector).data(DATA_KEY)if (activesData && activesData._isTransitioning) {return}}const startEvent = $.Event(EVENT_SHOW)$(this._element).trigger(startEvent)if (startEvent.isDefaultPrevented()) {return}if (actives) {Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')if (!activesData) {$(actives).data(DATA_KEY, null)}}const dimension = this._getDimension()$(this._element).removeClass(CLASS_NAME_COLLAPSE).addClass(CLASS_NAME_COLLAPSING)this._element.style[dimension] = 0if (this._triggerArray.length) {$(this._triggerArray).removeClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', true)}this.setTransitioning(true)const complete = () => {$(this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)this._element.style[dimension] = ''this.setTransitioning(false)$(this._element).trigger(EVENT_SHOWN)}const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)const scrollSize = `scroll${capitalizedDimension}`const transitionDuration = Util.getTransitionDurationFromElement(this._element)$(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration)this._element.style[dimension] = `${this._element[scrollSize]}px`}hide() {if (this._isTransitioning ||!$(this._element).hasClass(CLASS_NAME_SHOW)) {return}const startEvent = $.Event(EVENT_HIDE)$(this._element).trigger(startEvent)if (startEvent.isDefaultPrevented()) {return}const dimension = this._getDimension()this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`Util.reflow(this._element)$(this._element).addClass(CLASS_NAME_COLLAPSING).removeClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)const triggerArrayLength = this._triggerArray.lengthif (triggerArrayLength > 0) {for (let i = 0; i < triggerArrayLength; i++) {const trigger = this._triggerArray[i]const selector = Util.getSelectorFromElement(trigger)if (selector !== null) {const $elem = $([].slice.call(document.querySelectorAll(selector)))if (!$elem.hasClass(CLASS_NAME_SHOW)) {$(trigger).addClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', false)}}}}this.setTransitioning(true)const complete = () => {this.setTransitioning(false)$(this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE).trigger(EVENT_HIDDEN)}this._element.style[dimension] = ''const transitionDuration = Util.getTransitionDurationFromElement(this._element)$(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration)}setTransitioning(isTransitioning) {this._isTransitioning = isTransitioning}dispose() {$.removeData(this._element, DATA_KEY)this._config = nullthis._parent = nullthis._element = nullthis._triggerArray = nullthis._isTransitioning = null}// Private_getConfig(config) {config = {...Default,...config}config.toggle = Boolean(config.toggle) // Coerce string valuesUtil.typeCheckConfig(NAME, config, DefaultType)return config}_getDimension() {const hasWidth = $(this._element).hasClass(DIMENSION_WIDTH)return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT}_getParent() {let parentif (Util.isElement(this._config.parent)) {parent = this._config.parent// It's a jQuery objectif (typeof this._config.parent.jquery !== 'undefined') {parent = this._config.parent[0]}} else {parent = document.querySelector(this._config.parent)}const selector = `[data-toggle="collapse"][data-parent="${this._config.parent}"]`const children = [].slice.call(parent.querySelectorAll(selector))$(children).each((i, element) => {this._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element),[element])})return parent}_addAriaAndCollapsedClass(element, triggerArray) {const isOpen = $(element).hasClass(CLASS_NAME_SHOW)if (triggerArray.length) {$(triggerArray).toggleClass(CLASS_NAME_COLLAPSED, !isOpen).attr('aria-expanded', isOpen)}}// Staticstatic _getTargetFromElement(element) {const selector = Util.getSelectorFromElement(element)return selector ? document.querySelector(selector) : null}static _jQueryInterface(config) {return this.each(function () {const $element = $(this)let data = $element.data(DATA_KEY)const _config = {...Default,...$element.data(),...(typeof config === 'object' && config ? config : {})}if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {_config.toggle = false}if (!data) {data = new Collapse(this, _config)$element.data(DATA_KEY, data)}if (typeof config === 'string') {if (typeof data[config] === 'undefined') {throw new TypeError(`No method named "${config}"`)}data[config]()}})}}/*** Data API implementation*/$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {// preventDefault only for <a> elements (which change the URL) not inside the collapsible elementif (event.currentTarget.tagName === 'A') {event.preventDefault()}const $trigger = $(this)const selector = Util.getSelectorFromElement(this)const selectors = [].slice.call(document.querySelectorAll(selector))$(selectors).each(function () {const $target = $(this)const data = $target.data(DATA_KEY)const config = data ? 'toggle' : $trigger.data()Collapse._jQueryInterface.call($target, config)})})/*** jQuery*/$.fn[NAME] = Collapse._jQueryInterface$.fn[NAME].Constructor = Collapse$.fn[NAME].noConflict = () => {$.fn[NAME] = JQUERY_NO_CONFLICTreturn Collapse._jQueryInterface}export default Collapse