From 8bab38bb7176d2716b72664dbafcc326824a2ee9 Mon Sep 17 00:00:00 2001 From: fat Date: Sat, 9 May 2015 23:00:59 -0700 Subject: [PATCH] add collapse --- Gruntfile.js | 1 + js/carousel.js | 237 ----------------------- js/collapse.js | 211 --------------------- js/dist/alert.js.map | Bin 7128 -> 7116 bytes js/dist/button.js.map | Bin 7558 -> 7557 bytes js/dist/carousel.js | 10 +- js/dist/carousel.js.map | Bin 21004 -> 20977 bytes js/dist/collapse.js | 322 +++++++++++++++++++++++++++++++ js/dist/collapse.js.map | Bin 0 -> 16655 bytes js/src/alert.js | 2 +- js/src/collapse.js | 345 ++++++++++++++++++++++++++++++++++ js/tests/index.html | 2 +- js/tests/unit/collapse.js | 4 +- js/tests/visual/collapse.html | 4 +- 14 files changed, 679 insertions(+), 459 deletions(-) delete mode 100644 js/carousel.js delete mode 100644 js/collapse.js create mode 100644 js/dist/collapse.js create mode 100644 js/dist/collapse.js.map create mode 100644 js/src/collapse.js diff --git a/Gruntfile.js b/Gruntfile.js index b058bf3a0..ffc660958 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -67,6 +67,7 @@ module.exports = function (grunt) { 'js/dist/alert.js': 'js/src/alert.js', 'js/dist/button.js': 'js/src/button.js', 'js/dist/carousel.js': 'js/src/carousel.js', + 'js/dist/collapse.js': 'js/src/collapse.js', } } }, diff --git a/js/carousel.js b/js/carousel.js deleted file mode 100644 index a38ef14d0..000000000 --- a/js/carousel.js +++ /dev/null @@ -1,237 +0,0 @@ -/* ======================================================================== - * Bootstrap: carousel.js v3.3.4 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = null - this.sliding = null - this.interval = null - this.$active = null - this.$items = null - - this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - - this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element - .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) - .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) - } - - Carousel.VERSION = '3.3.4' - - Carousel.TRANSITION_DURATION = 600 - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true, - keyboard: true - } - - Carousel.prototype.keydown = function (e) { - if (/input|textarea/i.test(e.target.tagName)) return - switch (e.which) { - case 37: this.prev(); break - case 39: this.next(); break - default: return - } - - e.preventDefault() - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getItemIndex = function (item) { - this.$items = item.parent().children('.item') - return this.$items.index(item || this.$active) - } - - Carousel.prototype.getItemForDirection = function (direction, active) { - var activeIndex = this.getItemIndex(active) - var willWrap = (direction == 'prev' && activeIndex === 0) - || (direction == 'next' && activeIndex == (this.$items.length - 1)) - if (willWrap && !this.options.wrap) return active - var delta = direction == 'prev' ? -1 : 1 - var itemIndex = (activeIndex + delta) % this.$items.length - return this.$items.eq(itemIndex) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || this.getItemForDirection(type, $active) - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var that = this - - if ($next.hasClass('active')) return (this.sliding = false) - - var relatedTarget = $next[0] - var slideEvent = $.Event('slide.bs.carousel', { - relatedTarget: relatedTarget, - direction: direction - }) - this.$element.trigger(slideEvent) - if (slideEvent.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) - $nextIndicator && $nextIndicator.addClass('active') - } - - var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one('bsTransitionEnd', function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { - that.$element.trigger(slidEvent) - }, 0) - }) - .emulateTransitionEnd(Carousel.TRANSITION_DURATION) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger(slidEvent) - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - var old = $.fn.carousel - - $.fn.carousel = Plugin - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - var clickHandler = function (e) { - var href - var $this = $(this) - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 - if (!$target.hasClass('carousel')) return - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - Plugin.call($target, options) - - if (slideIndex) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - } - - $(document) - .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) - .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Plugin.call($carousel, $carousel.data()) - }) - }) - -}(jQuery); diff --git a/js/collapse.js b/js/collapse.js deleted file mode 100644 index 954513c5e..000000000 --- a/js/collapse.js +++ /dev/null @@ -1,211 +0,0 @@ -/* ======================================================================== - * Bootstrap: collapse.js v3.3.4 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.4' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - 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') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - 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() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // 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) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); diff --git a/js/dist/alert.js.map b/js/dist/alert.js.map index 4d8c6173e5393c3617b9ecedd346f92f3ed8cc9e..a313bd08536d4a7b2d0289c861ac2b723da2cbbf 100644 GIT binary patch delta 113 zcmca%e#U%57!!}bj;o`itF?)fqg&SIB&KX834cdNZ=GOA$6y_2M@MHJZx9#Aa^L)( zMUa`>7or|0W4W1|LzZ(grwI3E6TxC8(F8q}YUiB9;$pwV+*CbBAJ?Fe+Jwz}gxQ%l J9}yE_1ppohAQ1on delta 109 zcmX?Oe#3l27!yyRj;o`itF?)fqg&4AB&KX8K4(WqXB~G(M|UtW`67!jqx0scEP~A3 z{t&f5dHv0d9I~8@_M7Dd>zG8<_0$!#6`XSti;Mjdb5r#keO!Y=Hg6PWX9lX+Atu5K E0EyNejsO4v diff --git a/js/dist/button.js.map b/js/dist/button.js.map index ac111ccf4335bb53b1d378dafecfc34f8b216ad4..2ba0e11c7d5387085f1f81827b4ea31777dd235a 100644 GIT binary patch delta 29 kcmZp(ZnfT!&(7_uYVGLgY`M9LT}oi{RPm3j0Ed1FBme*a delta 31 mcmZp*ZnNHy&(7_yYVGLgtiQR6T}pt_e)AOZkE{TeLkU{| diff --git a/js/dist/carousel.js b/js/dist/carousel.js index 55fd16024..026e74316 100644 --- a/js/dist/carousel.js +++ b/js/dist/carousel.js @@ -26,11 +26,11 @@ var Carousel = (function ($) { var TRANSITION_DURATION = 600; var Defaults = { - 'interval': 5000, - 'keyboard': true, - 'slide': false, - 'pause': 'hover', - 'wrap': true + interval: 5000, + keyboard: true, + slide: false, + pause: 'hover', + wrap: true }; var Direction = { diff --git a/js/dist/carousel.js.map b/js/dist/carousel.js.map index 12b48721a09c5cc84ef8f3a9363c5e3a55ce44a0..f0565e167ec8ceb4b0084ca52e8f261ed608e158 100644 GIT binary patch delta 391 zcmeBK!uWA9qtk(Kpj^{M|T}hM@LU&G#6MnRt9b3SF&DoE+V%Hp{YXXW|BHbp`2)*nFR@kr7#7@_jbF z%`-VFczOLH`m90fsy54sX>kZbjRFc-I_ac3I{Hrz=4pm=XlvuF&r`Ar!&6{t&i;V^}-+m*E{CZM>Pwcp}T@Ip!X$o1fYk zF;A9oXxTj1A(mOFR_)J{KlDQ@@ZRDM!(4)ZN(>>yC_c%G?m_5=F-Hn J`KO04Cjh}CdRqVh delta 447 zcmeykn6YOGKEJ^{1mlTzz!o-VnGE-93K}xI?(h_ru;SvRj zrNuA_^^E+o)FO45p7Nr^0`<*rwRSQxDr{b+W5vX1zxjb)FOZs?Ygo&uF!`0?9WdK? z^G~CREI>tF<{qp->XMBSGf;xXp#{k4aEN6Bs%T`PlEyg diff --git a/js/dist/collapse.js b/js/dist/collapse.js new file mode 100644 index 000000000..a537f426e --- /dev/null +++ b/js/dist/collapse.js @@ -0,0 +1,322 @@ +'use strict'; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0): collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +var Collapse = (function ($) { + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + var NAME = 'collapse'; + var VERSION = '4.0.0'; + var DATA_KEY = 'bs.collapse'; + var JQUERY_NO_CONFLICT = $.fn[NAME]; + var TRANSITION_DURATION = 600; + + var Defaults = { + toggle: true, + parent: null + }; + + var Event = { + SHOW: 'show.bs.collapse', + SHOWN: 'shown.bs.collapse', + HIDE: 'hide.bs.collapse', + HIDDEN: 'hidden.bs.collapse', + CLICK: 'click.bs.collapse.data-api' + }; + + var ClassName = { + IN: 'in', + COLLAPSE: 'collapse', + COLLAPSING: 'collapsing', + COLLAPSED: 'collapsed' + }; + + var Dimension = { + WIDTH: 'width', + HEIGHT: 'height' + }; + + var Selector = { + ACTIVES: '.panel > .in, .panel > .collapsing', + DATA_TOGGLE: '[data-toggle="collapse"]' + }; + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + var Collapse = (function () { + function Collapse(element, config) { + _classCallCheck(this, Collapse); + + this._isTransitioning = false; + this._element = element; + this._config = $.extend({}, Defaults, config); + this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]'))); + + this._parent = this._config.parent ? this._getParent() : null; + + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray); + } + + if (this._config.toggle) { + this.toggle(); + } + } + + _createClass(Collapse, [{ + key: 'toggle', + + // public + + value: function toggle() { + if ($(this._element).hasClass(ClassName.IN)) { + this.hide(); + } else { + this.show(); + } + } + }, { + key: 'show', + value: function show() { + var _this = this; + + if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) { + return; + } + + var activesData = undefined; + var actives = undefined; + + if (this._parent) { + actives = $.makeArray($(Selector.ACTIVES)); + if (!actives.length) { + actives = null; + } + } + + if (actives) { + activesData = $(actives).data(DATA_KEY); + if (activesData && activesData._isTransitioning) { + return; + } + } + + var startEvent = $.Event(Event.SHOW); + $(this._element).trigger(startEvent); + if (startEvent.isDefaultPrevented()) { + return; + } + + if (actives) { + Collapse._jQueryInterface.call($(actives), 'hide'); + if (!activesData) { + $(actives).data(DATA_KEY, null); + } + } + + var dimension = this._getDimension(); + + $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); + + this._element.style[dimension] = 0; + this._element.setAttribute('aria-expanded', true); + + if (this._triggerArray.length) { + $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); + } + + this.setTransitioning(true); + + var complete = function complete() { + $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN); + + _this._element.style[dimension] = ''; + + _this.setTransitioning(false); + + $(_this._element).trigger(Event.SHOWN); + }; + + if (!Util.supportsTransitionEnd()) { + complete(); + return; + } + + var scrollSize = 'scroll' + (dimension[0].toUpperCase() + dimension.slice(1)); + + $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); + + this._element.style[dimension] = this._element[scrollSize] + 'px'; + } + }, { + key: 'hide', + value: function hide() { + var _this2 = this; + + if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) { + return; + } + + var startEvent = $.Event(Event.HIDE); + $(this._element).trigger(startEvent); + if (startEvent.isDefaultPrevented()) { + return; + } + + var dimension = this._getDimension(); + var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight'; + + this._element.style[dimension] = this._element[offsetDimension] + 'px'; + + Util.reflow(this._element); + + $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN); + + this._element.setAttribute('aria-expanded', false); + + if (this._triggerArray.length) { + $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + } + + this.setTransitioning(true); + + var complete = function complete() { + _this2.setTransitioning(false); + $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); + }; + + this._element.style[dimension] = 0; + + if (!Util.supportsTransitionEnd()) { + return complete(); + } + + $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); + } + }, { + key: 'setTransitioning', + value: function setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning; + } + }, { + key: '_getDimension', + + // private + + value: function _getDimension() { + var hasWidth = $(this._element).hasClass(Dimension.WIDTH); + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; + } + }, { + key: '_getParent', + value: function _getParent() { + var _this3 = this; + + var parent = $(this._config.parent)[0]; + var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]'; + + $(parent).find(selector).each(function (i, element) { + _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); + }); + + return parent; + } + }, { + key: '_addAriaAndCollapsedClass', + value: function _addAriaAndCollapsedClass(element, triggerArray) { + if (element) { + var isOpen = $(element).hasClass(ClassName.IN); + element.setAttribute('aria-expanded', isOpen); + + if (triggerArray.length) { + $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); + } + } + } + }], [{ + key: '_getTargetFromElement', + + // static + + value: function _getTargetFromElement(element) { + var selector = Util.getSelectorFromElement(element); + return selector ? $(selector)[0] : null; + } + }, { + key: '_jQueryInterface', + value: function _jQueryInterface(config) { + return this.each(function () { + var $this = $(this); + var data = $this.data(DATA_KEY); + var _config = $.extend({}, Defaults, $this.data(), typeof config === 'object' && 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') { + data[config](); + } + }); + } + }]); + + return Collapse; + })(); + + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + $(document).on(Event.CLICK, Selector.DATA_TOGGLE, function (event) { + event.preventDefault(); + + var target = Collapse._getTargetFromElement(this); + + var data = $(target).data(DATA_KEY); + var config = data ? 'toggle' : $(this).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; +})(jQuery); +//# sourceMappingURL=collapse.js.map \ No newline at end of file diff --git a/js/dist/collapse.js.map b/js/dist/collapse.js.map new file mode 100644 index 0000000000000000000000000000000000000000..fbd44455489f7901759250cb0bf76b4267764f15 GIT binary patch literal 16655 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 { } if (!parent) { - parent = $(element).closest('.' + ClassName.ALERT)[0] + parent = $(element).closest(`.${ClassName.ALERT}`)[0] } return parent diff --git a/js/src/collapse.js b/js/src/collapse.js new file mode 100644 index 000000000..00ae29097 --- /dev/null +++ b/js/src/collapse.js @@ -0,0 +1,345 @@ +import Util from './util' + + +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0): collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +const Collapse = (($) => { + + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'collapse' + const VERSION = '4.0.0' + const DATA_KEY = 'bs.collapse' + const JQUERY_NO_CONFLICT = $.fn[NAME] + const TRANSITION_DURATION = 600 + + const Defaults = { + toggle : true, + parent : null + } + + const Event = { + SHOW : 'show.bs.collapse', + SHOWN : 'shown.bs.collapse', + HIDE : 'hide.bs.collapse', + HIDDEN : 'hidden.bs.collapse', + CLICK : 'click.bs.collapse.data-api' + } + + const ClassName = { + IN : 'in', + COLLAPSE : 'collapse', + COLLAPSING : 'collapsing', + COLLAPSED : 'collapsed' + } + + const Dimension = { + WIDTH : 'width', + HEIGHT : 'height' + } + + const Selector = { + ACTIVES : '.panel > .in, .panel > .collapsing', + DATA_TOGGLE : '[data-toggle="collapse"]' + } + + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class Collapse { + + constructor(element, config) { + + this._isTransitioning = false + this._element = element + this._config = $.extend({}, Defaults, config) + this._triggerArray = $.makeArray($( + `[data-toggle="collapse"][href="#${element.id}"],` + + `[data-toggle="collapse"][data-target="#${element.id}"]` + )) + + this._parent = this._config.parent ? this._getParent() : null + + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray) + } + + if (this._config.toggle) { + this.toggle() + } + + } + + // public + + toggle() { + if ($(this._element).hasClass(ClassName.IN)) { + this.hide() + } else { + this.show() + } + } + + show() { + if (this._isTransitioning || + $(this._element).hasClass(ClassName.IN)) { + return + } + + let activesData + let actives + + if (this._parent) { + actives = $.makeArray($(Selector.ACTIVES)) + if (!actives.length) { + actives = null + } + } + + if (actives) { + activesData = $(actives).data(DATA_KEY) + if (activesData && activesData._isTransitioning) { + return + } + } + + let startEvent = $.Event(Event.SHOW) + $(this._element).trigger(startEvent) + if (startEvent.isDefaultPrevented()) { + return + } + + if (actives) { + Collapse._jQueryInterface.call($(actives), 'hide') + if (!activesData) { + $(actives).data(DATA_KEY, null) + } + } + + let dimension = this._getDimension() + + $(this._element) + .removeClass(ClassName.COLLAPSE) + .addClass(ClassName.COLLAPSING) + + this._element.style[dimension] = 0 + this._element.setAttribute('aria-expanded', true) + + if (this._triggerArray.length) { + $(this._triggerArray) + .removeClass(ClassName.COLLAPSED) + .attr('aria-expanded', true) + } + + this.setTransitioning(true) + + let complete = () => { + $(this._element) + .removeClass(ClassName.COLLAPSING) + .addClass(ClassName.COLLAPSE) + .addClass(ClassName.IN) + + this._element.style[dimension] = '' + + this.setTransitioning(false) + + $(this._element).trigger(Event.SHOWN) + } + + if (!Util.supportsTransitionEnd()) { + complete() + return + } + + let scrollSize = 'scroll' + + (dimension[0].toUpperCase() + + dimension.slice(1)) + + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(TRANSITION_DURATION) + + this._element.style[dimension] = this._element[scrollSize] + 'px' + } + + hide() { + if (this._isTransitioning || + !$(this._element).hasClass(ClassName.IN)) { + return + } + + let startEvent = $.Event(Event.HIDE) + $(this._element).trigger(startEvent) + if (startEvent.isDefaultPrevented()) { + return + } + + let dimension = this._getDimension() + let offsetDimension = dimension === Dimension.WIDTH ? + 'offsetWidth' : 'offsetHeight' + + this._element.style[dimension] = this._element[offsetDimension] + 'px' + + Util.reflow(this._element) + + $(this._element) + .addClass(ClassName.COLLAPSING) + .removeClass(ClassName.COLLAPSE) + .removeClass(ClassName.IN) + + this._element.setAttribute('aria-expanded', false) + + if (this._triggerArray.length) { + $(this._triggerArray) + .addClass(ClassName.COLLAPSED) + .attr('aria-expanded', false) + } + + this.setTransitioning(true) + + let complete = () => { + this.setTransitioning(false) + $(this._element) + .removeClass(ClassName.COLLAPSING) + .addClass(ClassName.COLLAPSE) + .trigger(Event.HIDDEN) + } + + this._element.style[dimension] = 0 + + if (!Util.supportsTransitionEnd()) { + return complete() + } + + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(TRANSITION_DURATION) + } + + setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning + } + + + // private + + _getDimension() { + let hasWidth = $(this._element).hasClass(Dimension.WIDTH) + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT + } + + _getParent() { + let parent = $(this._config.parent)[0] + let selector = + `[data-toggle="collapse"][data-parent="${this._config.parent}"]` + + $(parent).find(selector).each((i, element) => { + this._addAriaAndCollapsedClass( + Collapse._getTargetFromElement(element), + [element] + ) + }) + + return parent + } + + _addAriaAndCollapsedClass(element, triggerArray) { + if (element) { + let isOpen = $(element).hasClass(ClassName.IN) + element.setAttribute('aria-expanded', isOpen) + + if (triggerArray.length) { + $(triggerArray) + .toggleClass(ClassName.COLLAPSED, !isOpen) + .attr('aria-expanded', isOpen) + } + } + } + + + // static + + static _getTargetFromElement(element) { + let selector = Util.getSelectorFromElement(element) + return selector ? $(selector)[0] : null + } + + static _jQueryInterface(config) { + return this.each(function () { + let $this = $(this) + let data = $this.data(DATA_KEY) + let _config = $.extend( + {}, + Defaults, + $this.data(), + typeof config === 'object' && 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') { + data[config]() + } + }) + } + + } + + + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + $(document).on(Event.CLICK, Selector.DATA_TOGGLE, function (event) { + event.preventDefault() + + let target = Collapse._getTargetFromElement(this) + + let data = $(target).data(DATA_KEY) + let config = data ? 'toggle' : $(this).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 + +})(jQuery) + +export default Collapse diff --git a/js/tests/index.html b/js/tests/index.html index 0ba54e802..cc008152f 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -134,9 +134,9 @@ + - diff --git a/js/tests/unit/collapse.js b/js/tests/unit/collapse.js index 0efa65400..78fafc6c2 100644 --- a/js/tests/unit/collapse.js +++ b/js/tests/unit/collapse.js @@ -355,7 +355,7 @@ $(function () { $('