text: import $ from 'jquery'
  import Util from './util'
  
  /**
   * --------------------------------------------------------------------------
   * Bootstrap (v4.1.3): collapse.js
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   * --------------------------------------------------------------------------
   */
  
  const Collapse = (($) => {
    /**
     * ------------------------------------------------------------------------
     * Constants
     * ------------------------------------------------------------------------
     */
  
    const NAME                = 'collapse'
    const VERSION             = '4.1.3'
    const DATA_KEY            = 'bs.collapse'
    const EVENT_KEY           = `.${DATA_KEY}`
    const DATA_API_KEY        = '.data-api'
    const JQUERY_NO_CONFLICT  = $.fn[NAME]
  
    const Default = {
      toggle : true,
      parent : ''
    }
  
    const DefaultType = {
      toggle : 'boolean',
      parent : '(string|element)'
    }
  
    const Event = {
      SHOW           : `show${EVENT_KEY}`,
      SHOWN          : `shown${EVENT_KEY}`,
      HIDE           : `hide${EVENT_KEY}`,
      HIDDEN         : `hidden${EVENT_KEY}`,
      CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
    }
  
    const ClassName = {
      SHOW       : 'show',
      COLLAPSE   : 'collapse',
      COLLAPSING : 'collapsing',
      COLLAPSED  : 'collapsed'
    }
  
    const Dimension = {
      WIDTH  : 'width',
      HEIGHT : 'height'
    }
  
    const Selector = {
      ACTIVES     : '.show, .collapsing',
      DATA_TOGGLE : '[data-toggle="collapse"]'
    }
  
    /**
     * ------------------------------------------------------------------------
     * Class Definition
     * ------------------------------------------------------------------------
     */
  
    class Collapse {
      constructor(element, config) {
        this._isTransitioning = false
        this._element         = element
        this._config          = this._getConfig(config)
        this._triggerArray    = $.makeArray(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 = 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 VERSION() {
        return VERSION
      }
  
      static get Default() {
        return Default
      }
  
      // Public
  
      toggle() {
        if ($(this._element).hasClass(ClassName.SHOW)) {
          this.hide()
        } else {
          this.show()
        }
      }
  
      show() {
        if (this._isTransitioning ||
          $(this._element).hasClass(ClassName.SHOW)) {
          return
        }
  
        let actives
        let activesData
  
        if (this._parent) {
          actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))
            .filter((elem) => elem.getAttribute('data-parent') === this._config.parent)
  
          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(ClassName.COLLAPSE)
          .addClass(ClassName.COLLAPSING)
  
        this._element.style[dimension] = 0
  
        if (this._triggerArray.length) {
          $(this._triggerArray)
            .removeClass(ClassName.COLLAPSED)
            .attr('aria-expanded', true)
        }
  
        this.setTransitioning(true)
  
        const complete = () => {
          $(this._element)
            .removeClass(ClassName.COLLAPSING)
            .addClass(ClassName.COLLAPSE)
            .addClass(ClassName.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(ClassName.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(ClassName.COLLAPSING)
          .removeClass(ClassName.COLLAPSE)
          .removeClass(ClassName.SHOW)
  
        const triggerArrayLength = this._triggerArray.length
        if (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(ClassName.SHOW)) {
                $(trigger).addClass(ClassName.COLLAPSED)
                  .attr('aria-expanded', false)
              }
            }
          }
        }
  
        this.setTransitioning(true)
  
        const complete = () => {
          this.setTransitioning(false)
          $(this._element)
            .removeClass(ClassName.COLLAPSING)
            .addClass(ClassName.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          = null
        this._parent          = null
        this._element         = null
        this._triggerArray    = null
        this._isTransitioning = null
      }
  
      // Private
  
      _getConfig(config) {
        config = {
          ...Default,
          ...config
        }
        config.toggle = Boolean(config.toggle) // Coerce string values
        Util.typeCheckConfig(NAME, config, DefaultType)
        return config
      }
  
      _getDimension() {
        const hasWidth = $(this._element).hasClass(Dimension.WIDTH)
        return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT
      }
  
      _getParent() {
        let parent = null
        if (Util.isElement(this._config.parent)) {
          parent = this._config.parent
  
          // It's a jQuery object
          if (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) {
        if (element) {
          const isOpen = $(element).hasClass(ClassName.SHOW)
  
          if (triggerArray.length) {
            $(triggerArray)
              .toggleClass(ClassName.COLLAPSED, !isOpen)
              .attr('aria-expanded', isOpen)
          }
        }
      }
  
      // Static
  
      static _getTargetFromElement(element) {
        const selector = Util.getSelectorFromElement(element)
        return selector ? document.querySelector(selector) : null
      }
  
      static _jQueryInterface(config) {
        return this.each(function () {
          const $this   = $(this)
          let data      = $this.data(DATA_KEY)
          const _config = {
            ...Default,
            ...$this.data(),
            ...typeof config === 'object' && config ? config : {}
          }
  
          if (!data && _config.toggle && /show|hide/.test(config)) {
            _config.toggle = false
          }
  
          if (!data) {
            data = new Collapse(this, _config)
            $this.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 element
      if (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 = function () {
      $.fn[NAME] = JQUERY_NO_CONFLICT
      return Collapse._jQueryInterface
    }
  
    return Collapse
  })($)
  
  export default Collapse
  