corrade-http-templates – Blame information for rev 61
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
61 | office | 1 | import $ from 'jquery' |
2 | import Util from './util' |
||
3 | |||
4 | /** |
||
5 | * -------------------------------------------------------------------------- |
||
6 | * Bootstrap (v4.1.3): carousel.js |
||
7 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
||
8 | * -------------------------------------------------------------------------- |
||
9 | */ |
||
10 | |||
11 | const Carousel = (($) => { |
||
12 | /** |
||
13 | * ------------------------------------------------------------------------ |
||
14 | * Constants |
||
15 | * ------------------------------------------------------------------------ |
||
16 | */ |
||
17 | |||
18 | const NAME = 'carousel' |
||
19 | const VERSION = '4.1.3' |
||
20 | const DATA_KEY = 'bs.carousel' |
||
21 | const EVENT_KEY = `.${DATA_KEY}` |
||
22 | const DATA_API_KEY = '.data-api' |
||
23 | const JQUERY_NO_CONFLICT = $.fn[NAME] |
||
24 | const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key |
||
25 | const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key |
||
26 | const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch |
||
27 | |||
28 | const Default = { |
||
29 | interval : 5000, |
||
30 | keyboard : true, |
||
31 | slide : false, |
||
32 | pause : 'hover', |
||
33 | wrap : true |
||
34 | } |
||
35 | |||
36 | const DefaultType = { |
||
37 | interval : '(number|boolean)', |
||
38 | keyboard : 'boolean', |
||
39 | slide : '(boolean|string)', |
||
40 | pause : '(string|boolean)', |
||
41 | wrap : 'boolean' |
||
42 | } |
||
43 | |||
44 | const Direction = { |
||
45 | NEXT : 'next', |
||
46 | PREV : 'prev', |
||
47 | LEFT : 'left', |
||
48 | RIGHT : 'right' |
||
49 | } |
||
50 | |||
51 | const Event = { |
||
52 | SLIDE : `slide${EVENT_KEY}`, |
||
53 | SLID : `slid${EVENT_KEY}`, |
||
54 | KEYDOWN : `keydown${EVENT_KEY}`, |
||
55 | MOUSEENTER : `mouseenter${EVENT_KEY}`, |
||
56 | MOUSELEAVE : `mouseleave${EVENT_KEY}`, |
||
57 | TOUCHEND : `touchend${EVENT_KEY}`, |
||
58 | LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`, |
||
59 | CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` |
||
60 | } |
||
61 | |||
62 | const ClassName = { |
||
63 | CAROUSEL : 'carousel', |
||
64 | ACTIVE : 'active', |
||
65 | SLIDE : 'slide', |
||
66 | RIGHT : 'carousel-item-right', |
||
67 | LEFT : 'carousel-item-left', |
||
68 | NEXT : 'carousel-item-next', |
||
69 | PREV : 'carousel-item-prev', |
||
70 | ITEM : 'carousel-item' |
||
71 | } |
||
72 | |||
73 | const Selector = { |
||
74 | ACTIVE : '.active', |
||
75 | ACTIVE_ITEM : '.active.carousel-item', |
||
76 | ITEM : '.carousel-item', |
||
77 | NEXT_PREV : '.carousel-item-next, .carousel-item-prev', |
||
78 | INDICATORS : '.carousel-indicators', |
||
79 | DATA_SLIDE : '[data-slide], [data-slide-to]', |
||
80 | DATA_RIDE : '[data-ride="carousel"]' |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * ------------------------------------------------------------------------ |
||
85 | * Class Definition |
||
86 | * ------------------------------------------------------------------------ |
||
87 | */ |
||
88 | |||
89 | class Carousel { |
||
90 | constructor(element, config) { |
||
91 | this._items = null |
||
92 | this._interval = null |
||
93 | this._activeElement = null |
||
94 | |||
95 | this._isPaused = false |
||
96 | this._isSliding = false |
||
97 | |||
98 | this.touchTimeout = null |
||
99 | |||
100 | this._config = this._getConfig(config) |
||
101 | this._element = $(element)[0] |
||
102 | this._indicatorsElement = this._element.querySelector(Selector.INDICATORS) |
||
103 | |||
104 | this._addEventListeners() |
||
105 | } |
||
106 | |||
107 | // Getters |
||
108 | |||
109 | static get VERSION() { |
||
110 | return VERSION |
||
111 | } |
||
112 | |||
113 | static get Default() { |
||
114 | return Default |
||
115 | } |
||
116 | |||
117 | // Public |
||
118 | |||
119 | next() { |
||
120 | if (!this._isSliding) { |
||
121 | this._slide(Direction.NEXT) |
||
122 | } |
||
123 | } |
||
124 | |||
125 | nextWhenVisible() { |
||
126 | // Don't call next when the page isn't visible |
||
127 | // or the carousel or its parent isn't visible |
||
128 | if (!document.hidden && |
||
129 | ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) { |
||
130 | this.next() |
||
131 | } |
||
132 | } |
||
133 | |||
134 | prev() { |
||
135 | if (!this._isSliding) { |
||
136 | this._slide(Direction.PREV) |
||
137 | } |
||
138 | } |
||
139 | |||
140 | pause(event) { |
||
141 | if (!event) { |
||
142 | this._isPaused = true |
||
143 | } |
||
144 | |||
145 | if (this._element.querySelector(Selector.NEXT_PREV)) { |
||
146 | Util.triggerTransitionEnd(this._element) |
||
147 | this.cycle(true) |
||
148 | } |
||
149 | |||
150 | clearInterval(this._interval) |
||
151 | this._interval = null |
||
152 | } |
||
153 | |||
154 | cycle(event) { |
||
155 | if (!event) { |
||
156 | this._isPaused = false |
||
157 | } |
||
158 | |||
159 | if (this._interval) { |
||
160 | clearInterval(this._interval) |
||
161 | this._interval = null |
||
162 | } |
||
163 | |||
164 | if (this._config.interval && !this._isPaused) { |
||
165 | this._interval = setInterval( |
||
166 | (document.visibilityState ? this.nextWhenVisible : this.next).bind(this), |
||
167 | this._config.interval |
||
168 | ) |
||
169 | } |
||
170 | } |
||
171 | |||
172 | to(index) { |
||
173 | this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) |
||
174 | |||
175 | const activeIndex = this._getItemIndex(this._activeElement) |
||
176 | |||
177 | if (index > this._items.length - 1 || index < 0) { |
||
178 | return |
||
179 | } |
||
180 | |||
181 | if (this._isSliding) { |
||
182 | $(this._element).one(Event.SLID, () => this.to(index)) |
||
183 | return |
||
184 | } |
||
185 | |||
186 | if (activeIndex === index) { |
||
187 | this.pause() |
||
188 | this.cycle() |
||
189 | return |
||
190 | } |
||
191 | |||
192 | const direction = index > activeIndex |
||
193 | ? Direction.NEXT |
||
194 | : Direction.PREV |
||
195 | |||
196 | this._slide(direction, this._items[index]) |
||
197 | } |
||
198 | |||
199 | dispose() { |
||
200 | $(this._element).off(EVENT_KEY) |
||
201 | $.removeData(this._element, DATA_KEY) |
||
202 | |||
203 | this._items = null |
||
204 | this._config = null |
||
205 | this._element = null |
||
206 | this._interval = null |
||
207 | this._isPaused = null |
||
208 | this._isSliding = null |
||
209 | this._activeElement = null |
||
210 | this._indicatorsElement = null |
||
211 | } |
||
212 | |||
213 | // Private |
||
214 | |||
215 | _getConfig(config) { |
||
216 | config = { |
||
217 | ...Default, |
||
218 | ...config |
||
219 | } |
||
220 | Util.typeCheckConfig(NAME, config, DefaultType) |
||
221 | return config |
||
222 | } |
||
223 | |||
224 | _addEventListeners() { |
||
225 | if (this._config.keyboard) { |
||
226 | $(this._element) |
||
227 | .on(Event.KEYDOWN, (event) => this._keydown(event)) |
||
228 | } |
||
229 | |||
230 | if (this._config.pause === 'hover') { |
||
231 | $(this._element) |
||
232 | .on(Event.MOUSEENTER, (event) => this.pause(event)) |
||
233 | .on(Event.MOUSELEAVE, (event) => this.cycle(event)) |
||
234 | if ('ontouchstart' in document.documentElement) { |
||
235 | // If it's a touch-enabled device, mouseenter/leave are fired as |
||
236 | // part of the mouse compatibility events on first tap - the carousel |
||
237 | // would stop cycling until user tapped out of it; |
||
238 | // here, we listen for touchend, explicitly pause the carousel |
||
239 | // (as if it's the second time we tap on it, mouseenter compat event |
||
240 | // is NOT fired) and after a timeout (to allow for mouse compatibility |
||
241 | // events to fire) we explicitly restart cycling |
||
242 | $(this._element).on(Event.TOUCHEND, () => { |
||
243 | this.pause() |
||
244 | if (this.touchTimeout) { |
||
245 | clearTimeout(this.touchTimeout) |
||
246 | } |
||
247 | this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) |
||
248 | }) |
||
249 | } |
||
250 | } |
||
251 | } |
||
252 | |||
253 | _keydown(event) { |
||
254 | if (/input|textarea/i.test(event.target.tagName)) { |
||
255 | return |
||
256 | } |
||
257 | |||
258 | switch (event.which) { |
||
259 | case ARROW_LEFT_KEYCODE: |
||
260 | event.preventDefault() |
||
261 | this.prev() |
||
262 | break |
||
263 | case ARROW_RIGHT_KEYCODE: |
||
264 | event.preventDefault() |
||
265 | this.next() |
||
266 | break |
||
267 | default: |
||
268 | } |
||
269 | } |
||
270 | |||
271 | _getItemIndex(element) { |
||
272 | this._items = element && element.parentNode |
||
273 | ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) |
||
274 | : [] |
||
275 | return this._items.indexOf(element) |
||
276 | } |
||
277 | |||
278 | _getItemByDirection(direction, activeElement) { |
||
279 | const isNextDirection = direction === Direction.NEXT |
||
280 | const isPrevDirection = direction === Direction.PREV |
||
281 | const activeIndex = this._getItemIndex(activeElement) |
||
282 | const lastItemIndex = this._items.length - 1 |
||
283 | const isGoingToWrap = isPrevDirection && activeIndex === 0 || |
||
284 | isNextDirection && activeIndex === lastItemIndex |
||
285 | |||
286 | if (isGoingToWrap && !this._config.wrap) { |
||
287 | return activeElement |
||
288 | } |
||
289 | |||
290 | const delta = direction === Direction.PREV ? -1 : 1 |
||
291 | const itemIndex = (activeIndex + delta) % this._items.length |
||
292 | |||
293 | return itemIndex === -1 |
||
294 | ? this._items[this._items.length - 1] : this._items[itemIndex] |
||
295 | } |
||
296 | |||
297 | _triggerSlideEvent(relatedTarget, eventDirectionName) { |
||
298 | const targetIndex = this._getItemIndex(relatedTarget) |
||
299 | const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)) |
||
300 | const slideEvent = $.Event(Event.SLIDE, { |
||
301 | relatedTarget, |
||
302 | direction: eventDirectionName, |
||
303 | from: fromIndex, |
||
304 | to: targetIndex |
||
305 | }) |
||
306 | |||
307 | $(this._element).trigger(slideEvent) |
||
308 | |||
309 | return slideEvent |
||
310 | } |
||
311 | |||
312 | _setActiveIndicatorElement(element) { |
||
313 | if (this._indicatorsElement) { |
||
314 | const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)) |
||
315 | $(indicators) |
||
316 | .removeClass(ClassName.ACTIVE) |
||
317 | |||
318 | const nextIndicator = this._indicatorsElement.children[ |
||
319 | this._getItemIndex(element) |
||
320 | ] |
||
321 | |||
322 | if (nextIndicator) { |
||
323 | $(nextIndicator).addClass(ClassName.ACTIVE) |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | |||
328 | _slide(direction, element) { |
||
329 | const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) |
||
330 | const activeElementIndex = this._getItemIndex(activeElement) |
||
331 | const nextElement = element || activeElement && |
||
332 | this._getItemByDirection(direction, activeElement) |
||
333 | const nextElementIndex = this._getItemIndex(nextElement) |
||
334 | const isCycling = Boolean(this._interval) |
||
335 | |||
336 | let directionalClassName |
||
337 | let orderClassName |
||
338 | let eventDirectionName |
||
339 | |||
340 | if (direction === Direction.NEXT) { |
||
341 | directionalClassName = ClassName.LEFT |
||
342 | orderClassName = ClassName.NEXT |
||
343 | eventDirectionName = Direction.LEFT |
||
344 | } else { |
||
345 | directionalClassName = ClassName.RIGHT |
||
346 | orderClassName = ClassName.PREV |
||
347 | eventDirectionName = Direction.RIGHT |
||
348 | } |
||
349 | |||
350 | if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { |
||
351 | this._isSliding = false |
||
352 | return |
||
353 | } |
||
354 | |||
355 | const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName) |
||
356 | if (slideEvent.isDefaultPrevented()) { |
||
357 | return |
||
358 | } |
||
359 | |||
360 | if (!activeElement || !nextElement) { |
||
361 | // Some weirdness is happening, so we bail |
||
362 | return |
||
363 | } |
||
364 | |||
365 | this._isSliding = true |
||
366 | |||
367 | if (isCycling) { |
||
368 | this.pause() |
||
369 | } |
||
370 | |||
371 | this._setActiveIndicatorElement(nextElement) |
||
372 | |||
373 | const slidEvent = $.Event(Event.SLID, { |
||
374 | relatedTarget: nextElement, |
||
375 | direction: eventDirectionName, |
||
376 | from: activeElementIndex, |
||
377 | to: nextElementIndex |
||
378 | }) |
||
379 | |||
380 | if ($(this._element).hasClass(ClassName.SLIDE)) { |
||
381 | $(nextElement).addClass(orderClassName) |
||
382 | |||
383 | Util.reflow(nextElement) |
||
384 | |||
385 | $(activeElement).addClass(directionalClassName) |
||
386 | $(nextElement).addClass(directionalClassName) |
||
387 | |||
388 | const transitionDuration = Util.getTransitionDurationFromElement(activeElement) |
||
389 | |||
390 | $(activeElement) |
||
391 | .one(Util.TRANSITION_END, () => { |
||
392 | $(nextElement) |
||
393 | .removeClass(`${directionalClassName} ${orderClassName}`) |
||
394 | .addClass(ClassName.ACTIVE) |
||
395 | |||
396 | $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`) |
||
397 | |||
398 | this._isSliding = false |
||
399 | |||
400 | setTimeout(() => $(this._element).trigger(slidEvent), 0) |
||
401 | }) |
||
402 | .emulateTransitionEnd(transitionDuration) |
||
403 | } else { |
||
404 | $(activeElement).removeClass(ClassName.ACTIVE) |
||
405 | $(nextElement).addClass(ClassName.ACTIVE) |
||
406 | |||
407 | this._isSliding = false |
||
408 | $(this._element).trigger(slidEvent) |
||
409 | } |
||
410 | |||
411 | if (isCycling) { |
||
412 | this.cycle() |
||
413 | } |
||
414 | } |
||
415 | |||
416 | // Static |
||
417 | |||
418 | static _jQueryInterface(config) { |
||
419 | return this.each(function () { |
||
420 | let data = $(this).data(DATA_KEY) |
||
421 | let _config = { |
||
422 | ...Default, |
||
423 | ...$(this).data() |
||
424 | } |
||
425 | |||
426 | if (typeof config === 'object') { |
||
427 | _config = { |
||
428 | ..._config, |
||
429 | ...config |
||
430 | } |
||
431 | } |
||
432 | |||
433 | const action = typeof config === 'string' ? config : _config.slide |
||
434 | |||
435 | if (!data) { |
||
436 | data = new Carousel(this, _config) |
||
437 | $(this).data(DATA_KEY, data) |
||
438 | } |
||
439 | |||
440 | if (typeof config === 'number') { |
||
441 | data.to(config) |
||
442 | } else if (typeof action === 'string') { |
||
443 | if (typeof data[action] === 'undefined') { |
||
444 | throw new TypeError(`No method named "${action}"`) |
||
445 | } |
||
446 | data[action]() |
||
447 | } else if (_config.interval) { |
||
448 | data.pause() |
||
449 | data.cycle() |
||
450 | } |
||
451 | }) |
||
452 | } |
||
453 | |||
454 | static _dataApiClickHandler(event) { |
||
455 | const selector = Util.getSelectorFromElement(this) |
||
456 | |||
457 | if (!selector) { |
||
458 | return |
||
459 | } |
||
460 | |||
461 | const target = $(selector)[0] |
||
462 | |||
463 | if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { |
||
464 | return |
||
465 | } |
||
466 | |||
467 | const config = { |
||
468 | ...$(target).data(), |
||
469 | ...$(this).data() |
||
470 | } |
||
471 | const slideIndex = this.getAttribute('data-slide-to') |
||
472 | |||
473 | if (slideIndex) { |
||
474 | config.interval = false |
||
475 | } |
||
476 | |||
477 | Carousel._jQueryInterface.call($(target), config) |
||
478 | |||
479 | if (slideIndex) { |
||
480 | $(target).data(DATA_KEY).to(slideIndex) |
||
481 | } |
||
482 | |||
483 | event.preventDefault() |
||
484 | } |
||
485 | } |
||
486 | |||
487 | /** |
||
488 | * ------------------------------------------------------------------------ |
||
489 | * Data Api implementation |
||
490 | * ------------------------------------------------------------------------ |
||
491 | */ |
||
492 | |||
493 | $(document) |
||
494 | .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler) |
||
495 | |||
496 | $(window).on(Event.LOAD_DATA_API, () => { |
||
497 | const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)) |
||
498 | for (let i = 0, len = carousels.length; i < len; i++) { |
||
499 | const $carousel = $(carousels[i]) |
||
500 | Carousel._jQueryInterface.call($carousel, $carousel.data()) |
||
501 | } |
||
502 | }) |
||
503 | |||
504 | /** |
||
505 | * ------------------------------------------------------------------------ |
||
506 | * jQuery |
||
507 | * ------------------------------------------------------------------------ |
||
508 | */ |
||
509 | |||
510 | $.fn[NAME] = Carousel._jQueryInterface |
||
511 | $.fn[NAME].Constructor = Carousel |
||
512 | $.fn[NAME].noConflict = function () { |
||
513 | $.fn[NAME] = JQUERY_NO_CONFLICT |
||
514 | return Carousel._jQueryInterface |
||
515 | } |
||
516 | |||
517 | return Carousel |
||
518 | })($) |
||
519 | |||
520 | export default Carousel |