1/* ========================================================== 2 * bootstrap-carousel.js v2.3.1 3 * http://twitter.github.com/bootstrap/javascript.html#carousel 4 * ========================================================== 5 * Copyright 2012 Twitter, Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * ========================================================== */ 19 20 21!function ($) { 22 23 "use strict"; // jshint ;_; 24 25 26 /* CAROUSEL CLASS DEFINITION 27 * ========================= */ 28 29 var Carousel = function (element, options) { 30 this.$element = $(element) 31 this.$indicators = this.$element.find('.carousel-indicators') 32 this.options = options 33 this.options.pause == 'hover' && this.$element 34 .on('mouseenter', $.proxy(this.pause, this)) 35 .on('mouseleave', $.proxy(this.cycle, this)) 36 } 37 38 Carousel.prototype = { 39 40 cycle: function (e) { 41 if (!e) this.paused = false 42 if (this.interval) clearInterval(this.interval); 43 this.options.interval 44 && !this.paused 45 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 46 return this 47 } 48 49 , getActiveIndex: function () { 50 this.$active = this.$element.find('.item.active') 51 this.$items = this.$active.parent().children() 52 return this.$items.index(this.$active) 53 } 54 55 , to: function (pos) { 56 var activeIndex = this.getActiveIndex() 57 , that = this 58 59 if (pos > (this.$items.length - 1) || pos < 0) return 60 61 if (this.sliding) { 62 return this.$element.one('slid', function () { 63 that.to(pos) 64 }) 65 } 66 67 if (activeIndex == pos) { 68 return this.pause().cycle() 69 } 70 71 return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) 72 } 73 74 , pause: function (e) { 75 if (!e) this.paused = true 76 if (this.$element.find('.next, .prev').length && $.support.transition.end) { 77 this.$element.trigger($.support.transition.end) 78 this.cycle(true) 79 } 80 clearInterval(this.interval) 81 this.interval = null 82 return this 83 } 84 85 , next: function () { 86 if (this.sliding) return 87 return this.slide('next') 88 } 89 90 , prev: function () { 91 if (this.sliding) return 92 return this.slide('prev') 93 } 94 95 , slide: function (type, next) { 96 var $active = this.$element.find('.item.active') 97 , $next = next || $active[type]() 98 , isCycling = this.interval 99 , direction = type == 'next' ? 'left' : 'right' 100 , fallback = type == 'next' ? 'first' : 'last' 101 , that = this 102 , e 103 104 this.sliding = true 105 106 isCycling && this.pause() 107 108 $next = $next.length ? $next : this.$element.find('.item')[fallback]() 109 110 e = $.Event('slide', { 111 relatedTarget: $next[0] 112 , direction: direction 113 }) 114 115 if ($next.hasClass('active')) return 116 117 if (this.$indicators.length) { 118 this.$indicators.find('.active').removeClass('active') 119 this.$element.one('slid', function () { 120 var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) 121 $nextIndicator && $nextIndicator.addClass('active') 122 }) 123 } 124 125 if ($.support.transition && this.$element.hasClass('slide')) { 126 this.$element.trigger(e) 127 if (e.isDefaultPrevented()) return 128 $next.addClass(type) 129 $next[0].offsetWidth // force reflow 130 $active.addClass(direction) 131 $next.addClass(direction) 132 this.$element.one($.support.transition.end, function () { 133 $next.removeClass([type, direction].join(' ')).addClass('active') 134 $active.removeClass(['active', direction].join(' ')) 135 that.sliding = false 136 setTimeout(function () { that.$element.trigger('slid') }, 0) 137 }) 138 } else { 139 this.$element.trigger(e) 140 if (e.isDefaultPrevented()) return 141 $active.removeClass('active') 142 $next.addClass('active') 143 this.sliding = false 144 this.$element.trigger('slid') 145 } 146 147 isCycling && this.cycle() 148 149 return this 150 } 151 152 } 153 154 155 /* CAROUSEL PLUGIN DEFINITION 156 * ========================== */ 157 158 var old = $.fn.carousel 159 160 $.fn.carousel = function (option) { 161 return this.each(function () { 162 var $this = $(this) 163 , data = $this.data('carousel') 164 , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) 165 , action = typeof option == 'string' ? option : options.slide 166 if (!data) $this.data('carousel', (data = new Carousel(this, options))) 167 if (typeof option == 'number') data.to(option) 168 else if (action) data[action]() 169 else if (options.interval) data.pause().cycle() 170 }) 171 } 172 173 $.fn.carousel.defaults = { 174 interval: 5000 175 , pause: 'hover' 176 } 177 178 $.fn.carousel.Constructor = Carousel 179 180 181 /* CAROUSEL NO CONFLICT 182 * ==================== */ 183 184 $.fn.carousel.noConflict = function () { 185 $.fn.carousel = old 186 return this 187 } 188 189 /* CAROUSEL DATA-API 190 * ================= */ 191 192 $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { 193 var $this = $(this), href 194 , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 195 , options = $.extend({}, $target.data(), $this.data()) 196 , slideIndex 197 198 $target.carousel(options) 199 200 if (slideIndex = $this.attr('data-slide-to')) { 201 $target.data('carousel').pause().to(slideIndex).cycle() 202 } 203 204 e.preventDefault() 205 }) 206 207}(window.jQuery);