diff options
| author | fat <[email protected]> | 2015-05-06 13:34:14 -0700 |
|---|---|---|
| committer | fat <[email protected]> | 2015-05-06 13:34:14 -0700 |
| commit | d1fbe200f46002431cdeebf965c4b789ef7ed267 (patch) | |
| tree | 43a7cc7667492e519b906f8a428935da2972ac14 /js/carousel.js | |
| parent | 09fb80568a52af6c440db971cdc6fd88eab8f8b5 (diff) | |
| download | bootstrap-d1fbe200f46002431cdeebf965c4b789ef7ed267.tar.xz bootstrap-d1fbe200f46002431cdeebf965c4b789ef7ed267.zip | |
remove closureness from plugins
Diffstat (limited to 'js/carousel.js')
| -rw-r--r-- | js/carousel.js | 669 |
1 files changed, 165 insertions, 504 deletions
diff --git a/js/carousel.js b/js/carousel.js index 8f33f4860..a38ef14d0 100644 --- a/js/carousel.js +++ b/js/carousel.js @@ -1,576 +1,237 @@ -/** ======================================================================= - * Bootstrap: carousel.js v4.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) - * ======================================================================== - * @fileoverview - Bootstrap's carousel. A slideshow component for cycling - * through elements, like a carousel. Nested carousels are not supported. - * - * Public Methods & Properties: - * - * + $.carousel - * + $.carousel.noConflict - * + $.carousel.Constructor - * + $.carousel.Constructor.VERSION - * + $.carousel.Constructor.Defaults - * + $.carousel.Constructor.Defaults.interval - * + $.carousel.Constructor.Defaults.pause - * + $.carousel.Constructor.Defaults.wrap - * + $.carousel.Constructor.Defaults.keyboard - * + $.carousel.Constructor.Defaults.slide - * + $.carousel.Constructor.prototype.next - * + $.carousel.Constructor.prototype.prev - * + $.carousel.Constructor.prototype.pause - * + $.carousel.Constructor.prototype.cycle - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our carousel class. - * @param {Element!} element - * @param {Object=} opt_config - * @constructor - */ -var Carousel = function (element, opt_config) { - - /** @private {Element} */ - this._element = $(element)[0] - - /** @private {Element} */ - this._indicatorsElement = $(this._element).find(Carousel._Selector.INDICATORS)[0] - - /** @private {?Object} */ - this._config = opt_config || null - - /** @private {boolean} */ - this._isPaused = false - - /** @private {boolean} */ - this._isSliding = false - - /** @private {?number} */ - this._interval = null - - /** @private {?Element} */ - this._activeElement = null - - /** @private {?Array} */ - this._items = null - - this._addEventListeners() - -} - - -/** - * @const - * @type {string} - */ -Carousel['VERSION'] = '4.0.0' - - -/** - * @const - * @type {Object} - */ -Carousel['Defaults'] = { - 'interval' : 5000, - 'pause' : 'hover', - 'wrap' : true, - 'keyboard' : true, - 'slide' : false -} - - -/** - * @const - * @type {string} - * @private - */ -Carousel._NAME = 'carousel' - - -/** - * @const - * @type {string} - * @private - */ -Carousel._DATA_KEY = 'bs.carousel' - - -/** - * @const - * @type {number} - * @private - */ -Carousel._TRANSITION_DURATION = 600 - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Direction = { - NEXT : 'next', - PREVIOUS : 'prev' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Event = { - SLIDE : 'slide.bs.carousel', - SLID : 'slid.bs.carousel' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._ClassName = { - CAROUSEL : 'carousel', - ACTIVE : 'active', - SLIDE : 'slide', - RIGHT : 'right', - LEFT : 'left', - ITEM : 'carousel-item' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Selector = { - ACTIVE : '.active', - ACTIVE_ITEM : '.active.carousel-item', - ITEM : '.carousel-item', - NEXT_PREV : '.next, .prev', - INDICATORS : '.carousel-indicators' -} - - -/** - * @const - * @type {Function} - * @private - */ -Carousel._JQUERY_NO_CONFLICT = $.fn[Carousel._NAME] - - -/** - * @param {Object=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Carousel._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(Carousel._DATA_KEY) - var config = $.extend({}, Carousel['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config) - var action = typeof opt_config == 'string' ? opt_config : config.slide - - if (!data) { - data = new Carousel(this, config) - $(this).data(Carousel._DATA_KEY, data) - } - - if (typeof opt_config == 'number') { - data.to(opt_config) - - } else if (action) { - data[action]() - - } else if (config.interval) { - data['pause']() - data['cycle']() - } - }) -} + * ======================================================================== */ -/** - * Click handler for data api - * @param {Event} event - * @this {Element} - * @private - */ -Carousel._dataApiClickHandler = function (event) { - var selector = Bootstrap.getSelectorFromElement(this) ++function ($) { + 'use strict'; - if (!selector) { - return - } - - var target = $(selector)[0] - - if (!target || !$(target).hasClass(Carousel._ClassName.CAROUSEL)) { - return - } + // CAROUSEL CLASS DEFINITION + // ========================= - var config = $.extend({}, $(target).data(), $(this).data()) + 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 - var slideIndex = this.getAttribute('data-slide-to') - if (slideIndex) { - config.interval = false - } - - Carousel._jQueryInterface.call($(target), config) + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - if (slideIndex) { - $(target).data(Carousel._DATA_KEY).to(slideIndex) + 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)) } - event.preventDefault() -} - - -/** - * Advance the carousel to the next slide - */ -Carousel.prototype['next'] = function () { - if (!this._isSliding) { - this._slide(Carousel._Direction.NEXT) - } -} + Carousel.VERSION = '3.3.4' + Carousel.TRANSITION_DURATION = 600 -/** - * Return the carousel to the previous slide - */ -Carousel.prototype['prev'] = function () { - if (!this._isSliding) { - this._slide(Carousel._Direction.PREVIOUS) + 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 + } -/** - * Pause the carousel cycle - * @param {Event=} opt_event - */ -Carousel.prototype['pause'] = function (opt_event) { - if (!opt_event) { - this._isPaused = true + e.preventDefault() } - if ($(this._element).find(Carousel._Selector.NEXT_PREV)[0] && Bootstrap.transition) { - $(this._element).trigger(Bootstrap.transition.end) - this['cycle'](true) - } + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) - clearInterval(this._interval) - this._interval = null -} + this.interval && clearInterval(this.interval) + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) -/** - * Cycle to the next carousel item - * @param {Event|boolean=} opt_event - */ -Carousel.prototype['cycle'] = function (opt_event) { - if (!opt_event) { - this._isPaused = false + return this } - if (this._interval) { - clearInterval(this._interval) - this._interval = null + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) } - if (this._config['interval'] && !this._isPaused) { - this._interval = setInterval(this['next'].bind(this), this._config['interval']) + 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) } -} - -/** - * @return {Object} - */ -Carousel.prototype['getConfig'] = function () { - return this._config -} + 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 -/** - * Move active carousel item to specified index - * @param {number} index - */ -Carousel.prototype.to = function (index) { - this._activeElement = $(this._element).find(Carousel._Selector.ACTIVE_ITEM)[0] + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() - var activeIndex = this._getItemIndex(this._activeElement) - - if (index > (this._items.length - 1) || index < 0) { - return - } - - if (this._isSliding) { - $(this._element).one(Carousel._Event.SLID, function () { this.to(index) }.bind(this)) - return + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } - if (activeIndex == index) { - this['pause']() - this['cycle']() - return - } + Carousel.prototype.pause = function (e) { + e || (this.paused = true) - var direction = index > activeIndex ? - Carousel._Direction.NEXT : - Carousel._Direction.PREVIOUS - - this._slide(direction, this._items[index]) -} + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + this.interval = clearInterval(this.interval) -/** - * Add event listeners to root element - * @private - */ -Carousel.prototype._addEventListeners = function () { - if (this._config['keyboard']) { - $(this._element).on('keydown.bs.carousel', this._keydown.bind(this)) + return this } - if (this._config['pause'] == 'hover' && !('ontouchstart' in document.documentElement)) { - $(this._element) - .on('mouseenter.bs.carousel', this['pause'].bind(this)) - .on('mouseleave.bs.carousel', this['cycle'].bind(this)) + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') } -} - - -/** - * Keydown handler - * @param {Event} event - * @private - */ -Carousel.prototype._keydown = function (event) { - event.preventDefault() - if (/input|textarea/i.test(event.target.tagName)) return - - switch (event.which) { - case 37: this['prev'](); break - case 39: this['next'](); break - default: return - } -} - - -/** - * Get item index - * @param {Element} element - * @return {number} - * @private - */ -Carousel.prototype._getItemIndex = function (element) { - this._items = $.makeArray($(element).parent().find(Carousel._Selector.ITEM)) - - return this._items.indexOf(element) -} - - -/** - * Get next displayed item based on direction - * @param {Carousel._Direction} direction - * @param {Element} activeElement - * @return {Element} - * @private - */ -Carousel.prototype._getItemByDirection = function (direction, activeElement) { - var activeIndex = this._getItemIndex(activeElement) - var isGoingToWrap = (direction === Carousel._Direction.PREVIOUS && activeIndex === 0) || - (direction === Carousel._Direction.NEXT && activeIndex == (this._items.length - 1)) - - if (isGoingToWrap && !this._config['wrap']) { - return activeElement + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') } - var delta = direction == Carousel._Direction.PREVIOUS ? -1 : 1 - var itemIndex = (activeIndex + delta) % this._items.length - - return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex] -} - + 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 -/** - * Trigger slide event on element - * @param {Element} relatedTarget - * @param {Carousel._ClassName} directionalClassname - * @return {$.Event} - * @private - */ -Carousel.prototype._triggerSlideEvent = function (relatedTarget, directionalClassname) { - var slideEvent = $.Event(Carousel._Event.SLIDE, { - relatedTarget: relatedTarget, - direction: directionalClassname - }) - - $(this._element).trigger(slideEvent) + if ($next.hasClass('active')) return (this.sliding = false) - return slideEvent -} + 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 -/** - * Set the active indicator if available - * @param {Element} element - * @private - */ -Carousel.prototype._setActiveIndicatorElement = function (element) { - if (this._indicatorsElement) { - $(this._indicatorsElement) - .find(Carousel._Selector.ACTIVE) - .removeClass(Carousel._ClassName.ACTIVE) + isCycling && this.pause() - var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)] - if (nextIndicator) { - $(nextIndicator).addClass(Carousel._ClassName.ACTIVE) + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') } - } -} - -/** - * Slide the carousel element in a direction - * @param {Carousel._Direction} direction - * @param {Element=} opt_nextElement - */ -Carousel.prototype._slide = function (direction, opt_nextElement) { - var activeElement = $(this._element).find(Carousel._Selector.ACTIVE_ITEM)[0] - var nextElement = opt_nextElement || activeElement && this._getItemByDirection(direction, activeElement) - - var isCycling = !!this._interval + 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) + } - var directionalClassName = direction == Carousel._Direction.NEXT ? - Carousel._ClassName.LEFT : - Carousel._ClassName.RIGHT + isCycling && this.cycle() - if (nextElement && $(nextElement).hasClass(Carousel._ClassName.ACTIVE)) { - this._isSliding = false - return + return this } - var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName) - if (slideEvent.isDefaultPrevented()) { - return - } - if (!activeElement || !nextElement) { - // some weirdness is happening, so we bail (maybe throw exception here alerting user that they're dom is off - return - } + // CAROUSEL PLUGIN DEFINITION + // ========================== - this._isSliding = true + 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 (isCycling) { - this['pause']() + 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() + }) } - this._setActiveIndicatorElement(nextElement) + var old = $.fn.carousel - var slidEvent = $.Event(Carousel._Event.SLID, { relatedTarget: nextElement, direction: directionalClassName }) + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel - if (Bootstrap.transition && $(this._element).hasClass(Carousel._ClassName.SLIDE)) { - $(nextElement).addClass(direction) - Bootstrap.reflow(nextElement) + // CAROUSEL NO CONFLICT + // ==================== - $(activeElement).addClass(directionalClassName) - $(nextElement).addClass(directionalClassName) - - $(activeElement) - .one(Bootstrap.TRANSITION_END, function () { - $(nextElement) - .removeClass(directionalClassName) - .removeClass(direction) - - $(nextElement).addClass(Carousel._ClassName.ACTIVE) - - $(activeElement) - .removeClass(Carousel._ClassName.ACTIVE) - .removeClass(direction) - .removeClass(directionalClassName) - - this._isSliding = false - - setTimeout(function () { - $(this._element).trigger(slidEvent) - }.bind(this), 0) - }.bind(this)) - .emulateTransitionEnd(Carousel._TRANSITION_DURATION) - - } else { - $(activeElement).removeClass(Carousel._ClassName.ACTIVE) - $(nextElement).addClass(Carousel._ClassName.ACTIVE) - - this._isSliding = false - $(this._element).trigger(slidEvent) + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this } - if (isCycling) { - this['cycle']() - } -} + // CAROUSEL DATA-API + // ================= -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + 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 -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME] = Carousel._jQueryInterface - - -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME]['Constructor'] = Carousel - - -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME]['noConflict'] = function () { - $.fn[Carousel._NAME] = Carousel._JQUERY_NO_CONFLICT - return this -} + Plugin.call($target, options) + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + e.preventDefault() + } -$(document) - .on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', Carousel._dataApiClickHandler) + $(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) - Carousel._jQueryInterface.call($carousel, /** @type {Object} */ ($carousel.data())) + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) }) -}) + +}(jQuery); |
