aboutsummaryrefslogtreecommitdiff
path: root/js/collapse.js
diff options
context:
space:
mode:
authorfat <[email protected]>2015-01-03 13:58:44 -0800
committerfat <[email protected]>2015-02-11 11:29:43 -0800
commit834220ea20ce5b7cd31edfb624a28b4bf8b29a6a (patch)
tree19bfdadb0c140df437e7b7034e5e1f5ce58343cc /js/collapse.js
parentaed1cd31218113d67d2eca3296edf5d1700b19b8 (diff)
downloadbootstrap-834220ea20ce5b7cd31edfb624a28b4bf8b29a6a.tar.xz
bootstrap-834220ea20ce5b7cd31edfb624a28b4bf8b29a6a.zip
bootstrap onto closure
Diffstat (limited to 'js/collapse.js')
-rw-r--r--js/collapse.js526
1 files changed, 385 insertions, 141 deletions
diff --git a/js/collapse.js b/js/collapse.js
index 2bc30e7ba..156163e3f 100644
--- a/js/collapse.js
+++ b/js/collapse.js
@@ -1,211 +1,455 @@
-/* ========================================================================
- * Bootstrap: collapse.js v3.3.2
+/** =======================================================================
+ * Bootstrap: collapse.js v4.0.0
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
+ * ========================================================================
+ * @fileoverview - Bootstrap's collapse plugin. Flexible support for
+ * collapsible components like accordions and navigation.
+ *
+ * Public Methods & Properties:
+ *
+ * + $.carousel
+ * + $.carousel.noConflict
+ * + $.carousel.Constructor
+ * + $.carousel.Constructor.VERSION
+ * + $.carousel.Constructor.Defaults
+ * + $.carousel.Constructor.Defaults.toggle
+ * + $.carousel.Constructor.Defaults.trigger
+ * + $.carousel.Constructor.Defaults.parent
+ * + $.carousel.Constructor.prototype.toggle
+ * + $.carousel.Constructor.prototype.show
+ * + $.carousel.Constructor.prototype.hide
+ *
+ * ========================================================================
+ */
+'use strict';
-+function ($) {
- 'use strict';
- // COLLAPSE PUBLIC CLASS DEFINITION
- // ================================
+/**
+ * Our collapse class.
+ * @param {Element!} element
+ * @param {Object=} opt_config
+ * @constructor
+ */
+var Collapse = function (element, opt_config) {
- var Collapse = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Collapse.DEFAULTS, options)
- this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
- this.transitioning = null
+ /** @private {Element} */
+ this._element = element
- if (this.options.parent) {
- this.$parent = this.getParent()
- } else {
- this.addAriaAndCollapsedClass(this.$element, this.$trigger)
- }
+ /** @private {Object} */
+ this._config = $.extend({}, Collapse['Defaults'], opt_config)
- if (this.options.toggle) this.toggle()
- }
+ /** @private {Element} */
+ this._trigger = typeof this._config['trigger'] == 'string' ?
+ $(this._config['trigger'])[0] : this._config['trigger']
- Collapse.VERSION = '3.3.2'
+ /** @private {boolean} */
+ this._isTransitioning = false
- Collapse.TRANSITION_DURATION = 350
+ /** @private {?Element} */
+ this._parent = this._config['parent'] ? this._getParent() : null
- Collapse.DEFAULTS = {
- toggle: true,
- trigger: '[data-toggle="collapse"]'
+ if (!this._config['parent']) {
+ this._addAriaAndCollapsedClass(this._element, this._trigger)
}
- Collapse.prototype.dimension = function () {
- var hasWidth = this.$element.hasClass('width')
- return hasWidth ? 'width' : 'height'
+ if (this._config['toggle']) {
+ this['toggle']()
}
- Collapse.prototype.show = function () {
- if (this.transitioning || this.$element.hasClass('in')) return
-
- var activesData
- var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+}
+
+
+/**
+ * @const
+ * @type {string}
+ */
+Collapse['VERSION'] = '4.0.0'
+
+
+/**
+ * @const
+ * @type {Object}
+ */
+Collapse['Defaults'] = {
+ 'toggle' : true,
+ 'trigger' : '[data-toggle="collapse"]',
+ 'parent' : null
+}
+
+
+/**
+ * @const
+ * @type {string}
+ * @private
+ */
+Collapse._NAME = 'collapse'
+
+
+/**
+ * @const
+ * @type {string}
+ * @private
+ */
+Collapse._DATA_KEY = 'bs.collapse'
+
+
+/**
+ * @const
+ * @type {number}
+ * @private
+ */
+Collapse._TRANSITION_DURATION = 600
+
+
+/**
+ * @const
+ * @type {Function}
+ * @private
+ */
+Collapse._JQUERY_NO_CONFLICT = $.fn[Collapse._NAME]
+
+
+/**
+ * @const
+ * @enum {string}
+ * @private
+ */
+Collapse._Event = {
+ SHOW : 'show.bs.collapse',
+ SHOWN : 'shown.bs.collapse',
+ HIDE : 'hide.bs.collapse',
+ HIDDEN : 'hidden.bs.collapse'
+}
+
+
+/**
+ * @const
+ * @enum {string}
+ * @private
+ */
+Collapse._ClassName = {
+ IN : 'in',
+ COLLAPSE : 'collapse',
+ COLLAPSING : 'collapsing',
+ COLLAPSED : 'collapsed'
+}
+
+
+/**
+ * @const
+ * @enum {string}
+ * @private
+ */
+Collapse._Dimension = {
+ WIDTH : 'width',
+ HEIGHT : 'height'
+}
+
+
+/**
+ * @const
+ * @enum {string}
+ * @private
+ */
+Collapse._Selector = {
+ ACTIVES : '.panel > .in, .panel > .collapsing'
+}
+
+
+/**
+ * Provides the jQuery Interface for the alert component.
+ * @param {Object|string=} opt_config
+ * @this {jQuery}
+ * @return {jQuery}
+ * @private
+ */
+Collapse._jQueryInterface = function (opt_config) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data(Collapse._DATA_KEY)
+ var config = $.extend({}, Collapse['Defaults'], $this.data(), typeof opt_config == 'object' && opt_config)
- if (actives && actives.length) {
- activesData = actives.data('bs.collapse')
- if (activesData && activesData.transitioning) return
+ if (!data && config['toggle'] && opt_config == 'show') {
+ config['toggle'] = false
}
- var startEvent = $.Event('show.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
+ if (!data) {
+ data = new Collapse(this, config)
+ $this.data(Collapse._DATA_KEY, data)
+ }
- if (actives && actives.length) {
- Plugin.call(actives, 'hide')
- activesData || actives.data('bs.collapse', null)
+ if (typeof opt_config == 'string') {
+ data[opt_config]()
}
+ })
+}
+
+
+/**
+ * Function for getting target element from element
+ * @return {Element}
+ * @private
+ */
+Collapse._getTargetFromElement = function (element) {
+ var selector = Bootstrap.getSelectorFromElement(element)
+
+ return selector ? $(selector)[0] : null
+}
+
- var dimension = this.dimension()
+/**
+ * Toggles the collapse element based on the presence of the 'in' class
+ */
+Collapse.prototype['toggle'] = function () {
+ if ($(this._element).hasClass(Collapse._ClassName.IN)) {
+ this['hide']()
+ } else {
+ this['show']()
+ }
+}
- this.$element
- .removeClass('collapse')
- .addClass('collapsing')[dimension](0)
- .attr('aria-expanded', true)
- this.$trigger
- .removeClass('collapsed')
- .attr('aria-expanded', true)
+/**
+ * Show's the collapsing element
+ */
+Collapse.prototype['show'] = function () {
+ if (this._isTransitioning || $(this._element).hasClass(Collapse._ClassName.IN)) {
+ return
+ }
- this.transitioning = 1
+ var activesData, actives
- var complete = function () {
- this.$element
- .removeClass('collapsing')
- .addClass('collapse in')[dimension]('')
- this.transitioning = 0
- this.$element
- .trigger('shown.bs.collapse')
+ if (this._parent) {
+ actives = $.makeArray($(Collapse._Selector.ACTIVES))
+ if (!actives.length) {
+ actives = null
}
+ }
- if (!$.support.transition) return complete.call(this)
+ if (actives) {
+ activesData = $(actives).data(Collapse._DATA_KEY)
+ if (activesData && activesData._isTransitioning) {
+ return
+ }
+ }
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+ var startEvent = $.Event(Collapse._Event.SHOW)
+ $(this._element).trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) {
+ return
+ }
- this.$element
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ if (actives) {
+ Collapse._jQueryInterface.call($(actives), 'hide')
+ if (!activesData) {
+ $(actives).data(Collapse._DATA_KEY, null)
+ }
}
- Collapse.prototype.hide = function () {
- if (this.transitioning || !this.$element.hasClass('in')) return
+ var dimension = this._getDimension()
- var startEvent = $.Event('hide.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
+ $(this._element)
+ .removeClass(Collapse._ClassName.COLLAPSE)
+ .addClass(Collapse._ClassName.COLLAPSING)
- var dimension = this.dimension()
+ this._element.style[dimension] = 0
+ this._element.setAttribute('aria-expanded', true)
- this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+ if (this._trigger) {
+ $(this._trigger).removeClass(Collapse._ClassName.COLLAPSED)
+ this._trigger.setAttribute('aria-expanded', true)
+ }
- this.$element
- .addClass('collapsing')
- .removeClass('collapse in')
- .attr('aria-expanded', false)
+ this['setTransitioning'](true)
- this.$trigger
- .addClass('collapsed')
- .attr('aria-expanded', false)
+ var complete = function () {
+ $(this._element)
+ .removeClass(Collapse._ClassName.COLLAPSING)
+ .addClass(Collapse._ClassName.COLLAPSE)
+ .addClass(Collapse._ClassName.IN)
- this.transitioning = 1
+ this._element.style[dimension] = ''
- var complete = function () {
- this.transitioning = 0
- this.$element
- .removeClass('collapsing')
- .addClass('collapse')
- .trigger('hidden.bs.collapse')
- }
+ this['setTransitioning'](false)
- if (!$.support.transition) return complete.call(this)
+ $(this._element).trigger(Collapse._Event.SHOWN)
+ }.bind(this)
- this.$element
- [dimension](0)
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ if (!Bootstrap.transition) {
+ complete()
+ return
}
- Collapse.prototype.toggle = function () {
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ var scrollSize = 'scroll' + (dimension[0].toUpperCase() + dimension.slice(1))
+
+ $(this._element)
+ .one(Bootstrap.TRANSITION_END, complete)
+ .emulateTransitionEnd(Collapse._TRANSITION_DURATION)
+
+ this._element.style[dimension] = this._element[scrollSize] + 'px'
+}
+
+
+/**
+ * Hides's the collapsing element
+ */
+Collapse.prototype['hide'] = function () {
+ if (this._isTransitioning || !$(this._element).hasClass(Collapse._ClassName.IN)) {
+ return
}
- Collapse.prototype.getParent = function () {
- return $(this.options.parent)
- .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
- .each($.proxy(function (i, element) {
- var $element = $(element)
- this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
- }, this))
- .end()
+ var startEvent = $.Event(Collapse._Event.HIDE)
+ $(this._element).trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this._getDimension()
+ var offsetDimension = dimension === Collapse._Dimension.WIDTH ?
+ 'offsetWidth' : 'offsetHeight'
+
+ this._element.style[dimension] = this._element[offsetDimension] + 'px'
+
+ Bootstrap.reflow(this._element)
+
+ $(this._element)
+ .addClass(Collapse._ClassName.COLLAPSING)
+ .removeClass(Collapse._ClassName.COLLAPSE)
+ .removeClass(Collapse._ClassName.IN)
+
+ this._element.setAttribute('aria-expanded', false)
+
+ if (this._trigger) {
+ $(this._trigger).addClass(Collapse._ClassName.COLLAPSED)
+ this._trigger.setAttribute('aria-expanded', false)
}
- Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
- var isOpen = $element.hasClass('in')
+ this['setTransitioning'](true)
+
+ var complete = function () {
+ this['setTransitioning'](false)
+ $(this._element)
+ .removeClass(Collapse._ClassName.COLLAPSING)
+ .addClass(Collapse._ClassName.COLLAPSE)
+ .trigger(Collapse._Event.HIDDEN)
+
+ }.bind(this)
- $element.attr('aria-expanded', isOpen)
- $trigger
- .toggleClass('collapsed', !isOpen)
- .attr('aria-expanded', isOpen)
+ this._element.style[dimension] = 0
+
+ if (!Bootstrap.transition) {
+ return complete()
}
- function getTargetFromTrigger($trigger) {
- var href
- var target = $trigger.attr('data-target')
- || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+ $(this._element)
+ .one(Bootstrap.TRANSITION_END, complete)
+ .emulateTransitionEnd(Collapse._TRANSITION_DURATION)
+}
+
+
- return $(target)
+/**
+ * @param {boolean} isTransitioning
+ */
+Collapse.prototype['setTransitioning'] = function (isTransitioning) {
+ this._isTransitioning = isTransitioning
+}
+
+
+/**
+ * Returns the collapsing dimension
+ * @return {string}
+ * @private
+ */
+Collapse.prototype._getDimension = function () {
+ var hasWidth = $(this._element).hasClass(Collapse._Dimension.WIDTH)
+ return hasWidth ? Collapse._Dimension.WIDTH : Collapse._Dimension.HEIGHT
+}
+
+
+/**
+ * Returns the parent element
+ * @return {Element}
+ * @private
+ */
+Collapse.prototype._getParent = function () {
+ var selector = '[data-toggle="collapse"][data-parent="' + this._config['parent'] + '"]'
+ var parent = $(this._config['parent'])[0]
+ var elements = /** @type {Array.<Element>} */ ($.makeArray($(parent).find(selector)))
+
+ for (var i = 0; i < elements.length; i++) {
+ this._addAriaAndCollapsedClass(Collapse._getTargetFromElement(elements[i]), elements[i])
}
+ return parent
+}
- // COLLAPSE PLUGIN DEFINITION
- // ==========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.collapse')
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+/**
+ * Returns the parent element
+ * @param {Element} element
+ * @param {Element} trigger
+ * @private
+ */
+Collapse.prototype._addAriaAndCollapsedClass = function (element, trigger) {
+ if (element) {
+ var isOpen = $(element).hasClass(Collapse._ClassName.IN)
+ element.setAttribute('aria-expanded', isOpen)
- if (!data && options.toggle && option == 'show') options.toggle = false
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
- if (typeof option == 'string') data[option]()
- })
+ if (trigger) {
+ trigger.setAttribute('aria-expanded', isOpen)
+ $(trigger).toggleClass(Collapse._ClassName.COLLAPSED, !isOpen)
+ }
}
+}
- var old = $.fn.collapse
- $.fn.collapse = Plugin
- $.fn.collapse.Constructor = Collapse
+/**
+ * ------------------------------------------------------------------------
+ * jQuery Interface + noConflict implementaiton
+ * ------------------------------------------------------------------------
+ */
- // COLLAPSE NO CONFLICT
- // ====================
+/**
+ * @const
+ * @type {Function}
+ */
+$.fn[Collapse._NAME] = Collapse._jQueryInterface
- $.fn.collapse.noConflict = function () {
- $.fn.collapse = old
- return this
- }
+/**
+ * @const
+ * @type {Function}
+ */
+$.fn[Collapse._NAME]['Constructor'] = Collapse
- // COLLAPSE DATA-API
- // =================
- $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
- var $this = $(this)
+/**
+ * @const
+ * @type {Function}
+ */
+$.fn[Collapse._NAME]['noConflict'] = function () {
+ $.fn[Collapse._NAME] = Collapse._JQUERY_NO_CONFLICT
+ return this
+}
- if (!$this.attr('data-target')) e.preventDefault()
- var $target = getTargetFromTrigger($this)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
+/**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
- Plugin.call($target, option)
- })
+$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (event) {
+ event.preventDefault()
+
+ var target = Collapse._getTargetFromElement(this)
+
+ var data = $(target).data(Collapse._DATA_KEY)
+ var config = data ? 'toggle' : $.extend({}, $(this).data(), { trigger: this })
-}(jQuery);
+ Collapse._jQueryInterface.call($(target), config)
+})