|
1 /* ======================================================================== |
|
2 * Bootstrap: carousel.js v3.3.5 |
|
3 * http://getbootstrap.com/javascript/#carousel |
|
4 * ======================================================================== |
|
5 * Copyright 2011-2015 Twitter, Inc. |
|
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
|
7 * ======================================================================== */ |
|
8 |
|
9 |
|
10 +function ($) { |
|
11 'use strict'; |
|
12 |
|
13 // CAROUSEL CLASS DEFINITION |
|
14 // ========================= |
|
15 |
|
16 var Carousel = function (element, options) { |
|
17 this.$element = $(element) |
|
18 this.$indicators = this.$element.find('.carousel-indicators') |
|
19 this.options = options |
|
20 this.paused = null |
|
21 this.sliding = null |
|
22 this.interval = null |
|
23 this.$active = null |
|
24 this.$items = null |
|
25 |
|
26 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) |
|
27 |
|
28 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element |
|
29 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) |
|
30 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) |
|
31 } |
|
32 |
|
33 Carousel.VERSION = '3.3.5' |
|
34 |
|
35 Carousel.TRANSITION_DURATION = 600 |
|
36 |
|
37 Carousel.DEFAULTS = { |
|
38 interval: 5000, |
|
39 pause: 'hover', |
|
40 wrap: true, |
|
41 keyboard: true |
|
42 } |
|
43 |
|
44 Carousel.prototype.keydown = function (e) { |
|
45 if (/input|textarea/i.test(e.target.tagName)) return |
|
46 switch (e.which) { |
|
47 case 37: this.prev(); break |
|
48 case 39: this.next(); break |
|
49 default: return |
|
50 } |
|
51 |
|
52 e.preventDefault() |
|
53 } |
|
54 |
|
55 Carousel.prototype.cycle = function (e) { |
|
56 e || (this.paused = false) |
|
57 |
|
58 this.interval && clearInterval(this.interval) |
|
59 |
|
60 this.options.interval |
|
61 && !this.paused |
|
62 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) |
|
63 |
|
64 return this |
|
65 } |
|
66 |
|
67 Carousel.prototype.getItemIndex = function (item) { |
|
68 this.$items = item.parent().children('.item') |
|
69 return this.$items.index(item || this.$active) |
|
70 } |
|
71 |
|
72 Carousel.prototype.getItemForDirection = function (direction, active) { |
|
73 var activeIndex = this.getItemIndex(active) |
|
74 var willWrap = (direction == 'prev' && activeIndex === 0) |
|
75 || (direction == 'next' && activeIndex == (this.$items.length - 1)) |
|
76 if (willWrap && !this.options.wrap) return active |
|
77 var delta = direction == 'prev' ? -1 : 1 |
|
78 var itemIndex = (activeIndex + delta) % this.$items.length |
|
79 return this.$items.eq(itemIndex) |
|
80 } |
|
81 |
|
82 Carousel.prototype.to = function (pos) { |
|
83 var that = this |
|
84 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) |
|
85 |
|
86 if (pos > (this.$items.length - 1) || pos < 0) return |
|
87 |
|
88 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" |
|
89 if (activeIndex == pos) return this.pause().cycle() |
|
90 |
|
91 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) |
|
92 } |
|
93 |
|
94 Carousel.prototype.pause = function (e) { |
|
95 e || (this.paused = true) |
|
96 |
|
97 if (this.$element.find('.next, .prev').length && $.support.transition) { |
|
98 this.$element.trigger($.support.transition.end) |
|
99 this.cycle(true) |
|
100 } |
|
101 |
|
102 this.interval = clearInterval(this.interval) |
|
103 |
|
104 return this |
|
105 } |
|
106 |
|
107 Carousel.prototype.next = function () { |
|
108 if (this.sliding) return |
|
109 return this.slide('next') |
|
110 } |
|
111 |
|
112 Carousel.prototype.prev = function () { |
|
113 if (this.sliding) return |
|
114 return this.slide('prev') |
|
115 } |
|
116 |
|
117 Carousel.prototype.slide = function (type, next) { |
|
118 var $active = this.$element.find('.item.active') |
|
119 var $next = next || this.getItemForDirection(type, $active) |
|
120 var isCycling = this.interval |
|
121 var direction = type == 'next' ? 'left' : 'right' |
|
122 var that = this |
|
123 |
|
124 if ($next.hasClass('active')) return (this.sliding = false) |
|
125 |
|
126 var relatedTarget = $next[0] |
|
127 var slideEvent = $.Event('slide.bs.carousel', { |
|
128 relatedTarget: relatedTarget, |
|
129 direction: direction |
|
130 }) |
|
131 this.$element.trigger(slideEvent) |
|
132 if (slideEvent.isDefaultPrevented()) return |
|
133 |
|
134 this.sliding = true |
|
135 |
|
136 isCycling && this.pause() |
|
137 |
|
138 if (this.$indicators.length) { |
|
139 this.$indicators.find('.active').removeClass('active') |
|
140 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) |
|
141 $nextIndicator && $nextIndicator.addClass('active') |
|
142 } |
|
143 |
|
144 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" |
|
145 if ($.support.transition && this.$element.hasClass('slide')) { |
|
146 $next.addClass(type) |
|
147 $next[0].offsetWidth // force reflow |
|
148 $active.addClass(direction) |
|
149 $next.addClass(direction) |
|
150 $active |
|
151 .one('bsTransitionEnd', function () { |
|
152 $next.removeClass([type, direction].join(' ')).addClass('active') |
|
153 $active.removeClass(['active', direction].join(' ')) |
|
154 that.sliding = false |
|
155 setTimeout(function () { |
|
156 that.$element.trigger(slidEvent) |
|
157 }, 0) |
|
158 }) |
|
159 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) |
|
160 } else { |
|
161 $active.removeClass('active') |
|
162 $next.addClass('active') |
|
163 this.sliding = false |
|
164 this.$element.trigger(slidEvent) |
|
165 } |
|
166 |
|
167 isCycling && this.cycle() |
|
168 |
|
169 return this |
|
170 } |
|
171 |
|
172 |
|
173 // CAROUSEL PLUGIN DEFINITION |
|
174 // ========================== |
|
175 |
|
176 function Plugin(option) { |
|
177 return this.each(function () { |
|
178 var $this = $(this) |
|
179 var data = $this.data('bs.carousel') |
|
180 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) |
|
181 var action = typeof option == 'string' ? option : options.slide |
|
182 |
|
183 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) |
|
184 if (typeof option == 'number') data.to(option) |
|
185 else if (action) data[action]() |
|
186 else if (options.interval) data.pause().cycle() |
|
187 }) |
|
188 } |
|
189 |
|
190 var old = $.fn.carousel |
|
191 |
|
192 $.fn.carousel = Plugin |
|
193 $.fn.carousel.Constructor = Carousel |
|
194 |
|
195 |
|
196 // CAROUSEL NO CONFLICT |
|
197 // ==================== |
|
198 |
|
199 $.fn.carousel.noConflict = function () { |
|
200 $.fn.carousel = old |
|
201 return this |
|
202 } |
|
203 |
|
204 |
|
205 // CAROUSEL DATA-API |
|
206 // ================= |
|
207 |
|
208 var clickHandler = function (e) { |
|
209 var href |
|
210 var $this = $(this) |
|
211 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 |
|
212 if (!$target.hasClass('carousel')) return |
|
213 var options = $.extend({}, $target.data(), $this.data()) |
|
214 var slideIndex = $this.attr('data-slide-to') |
|
215 if (slideIndex) options.interval = false |
|
216 |
|
217 Plugin.call($target, options) |
|
218 |
|
219 if (slideIndex) { |
|
220 $target.data('bs.carousel').to(slideIndex) |
|
221 } |
|
222 |
|
223 e.preventDefault() |
|
224 } |
|
225 |
|
226 $(document) |
|
227 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) |
|
228 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) |
|
229 |
|
230 $(window).on('load', function () { |
|
231 $('[data-ride="carousel"]').each(function () { |
|
232 var $carousel = $(this) |
|
233 Plugin.call($carousel, $carousel.data()) |
|
234 }) |
|
235 }) |
|
236 |
|
237 }(jQuery); |