@materializecss/materialize 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/Gruntfile.js +722 -712
  2. package/LICENSE +21 -21
  3. package/README.md +91 -91
  4. package/dist/css/materialize.css +68 -135
  5. package/dist/css/materialize.min.css +12 -12
  6. package/dist/js/materialize.js +1112 -1112
  7. package/dist/js/materialize.min.js +6 -6
  8. package/extras/noUiSlider/nouislider.css +403 -403
  9. package/extras/noUiSlider/nouislider.js +2147 -2147
  10. package/js/anime.min.js +34 -34
  11. package/js/autocomplete.js +479 -479
  12. package/js/buttons.js +354 -354
  13. package/js/cards.js +40 -40
  14. package/js/carousel.js +732 -732
  15. package/js/cash.js +960 -960
  16. package/js/characterCounter.js +136 -136
  17. package/js/chips.js +486 -486
  18. package/js/collapsible.js +275 -275
  19. package/js/component.js +44 -44
  20. package/js/datepicker.js +983 -983
  21. package/js/dropdown.js +669 -669
  22. package/js/forms.js +285 -285
  23. package/js/global.js +428 -428
  24. package/js/materialbox.js +453 -453
  25. package/js/modal.js +382 -382
  26. package/js/parallax.js +138 -138
  27. package/js/pushpin.js +148 -148
  28. package/js/range.js +263 -263
  29. package/js/scrollspy.js +295 -295
  30. package/js/select.js +391 -391
  31. package/js/sidenav.js +583 -583
  32. package/js/slider.js +359 -359
  33. package/js/tabs.js +402 -402
  34. package/js/tapTarget.js +315 -315
  35. package/js/timepicker.js +712 -712
  36. package/js/toasts.js +325 -325
  37. package/js/tooltip.js +320 -320
  38. package/js/waves.js +614 -614
  39. package/package.json +87 -84
  40. package/sass/_style.scss +929 -929
  41. package/sass/components/_badges.scss +55 -55
  42. package/sass/components/_buttons.scss +322 -322
  43. package/sass/components/_cards.scss +195 -195
  44. package/sass/components/_carousel.scss +90 -90
  45. package/sass/components/_chips.scss +96 -96
  46. package/sass/components/_collapsible.scss +91 -91
  47. package/sass/components/_collection.scss +106 -106
  48. package/sass/components/_color-classes.scss +32 -32
  49. package/sass/components/_color-variables.scss +370 -370
  50. package/sass/components/_datepicker.scss +191 -191
  51. package/sass/components/_dropdown.scss +84 -84
  52. package/sass/components/_global.scss +646 -646
  53. package/sass/components/_grid.scss +158 -158
  54. package/sass/components/_icons-material-design.scss +5 -5
  55. package/sass/components/_materialbox.scss +42 -42
  56. package/sass/components/_modal.scss +97 -97
  57. package/sass/components/_navbar.scss +208 -208
  58. package/sass/components/_normalize.scss +447 -447
  59. package/sass/components/_preloader.scss +334 -334
  60. package/sass/components/_pulse.scss +34 -34
  61. package/sass/components/_sidenav.scss +214 -214
  62. package/sass/components/_slider.scss +91 -91
  63. package/sass/components/_table_of_contents.scss +33 -33
  64. package/sass/components/_tabs.scss +99 -99
  65. package/sass/components/_tapTarget.scss +103 -103
  66. package/sass/components/_timepicker.scss +199 -199
  67. package/sass/components/_toast.scss +58 -58
  68. package/sass/components/_tooltip.scss +32 -32
  69. package/sass/components/_transitions.scss +12 -12
  70. package/sass/components/_typography.scss +62 -62
  71. package/sass/components/_variables.scss +352 -352
  72. package/sass/components/_waves.scss +187 -187
  73. package/sass/components/forms/_checkboxes.scss +200 -200
  74. package/sass/components/forms/_file-input.scss +44 -44
  75. package/sass/components/forms/_forms.scss +22 -22
  76. package/sass/components/forms/_input-fields.scss +388 -388
  77. package/sass/components/forms/_radio-buttons.scss +115 -115
  78. package/sass/components/forms/_range.scss +161 -161
  79. package/sass/components/forms/_select.scss +199 -199
  80. package/sass/components/forms/_switches.scss +91 -91
  81. package/sass/ghpages-materialize.scss +7 -7
  82. package/sass/materialize.scss +42 -42
package/js/carousel.js CHANGED
@@ -1,732 +1,732 @@
1
- (function($) {
2
- 'use strict';
3
-
4
- let _defaults = {
5
- duration: 200, // ms
6
- dist: -100, // zoom scale TODO: make this more intuitive as an option
7
- shift: 0, // spacing for center image
8
- padding: 0, // Padding between non center items
9
- numVisible: 5, // Number of visible items in carousel
10
- fullWidth: false, // Change to full width styles
11
- indicators: false, // Toggle indicators
12
- noWrap: false, // Don't wrap around and cycle through items.
13
- onCycleTo: null // Callback for when a new slide is cycled to.
14
- };
15
-
16
- /**
17
- * @class
18
- *
19
- */
20
- class Carousel extends Component {
21
- /**
22
- * Construct Carousel instance
23
- * @constructor
24
- * @param {Element} el
25
- * @param {Object} options
26
- */
27
- constructor(el, options) {
28
- super(Carousel, el, options);
29
-
30
- this.el.M_Carousel = this;
31
-
32
- /**
33
- * Options for the carousel
34
- * @member Carousel#options
35
- * @prop {Number} duration
36
- * @prop {Number} dist
37
- * @prop {Number} shift
38
- * @prop {Number} padding
39
- * @prop {Number} numVisible
40
- * @prop {Boolean} fullWidth
41
- * @prop {Boolean} indicators
42
- * @prop {Boolean} noWrap
43
- * @prop {Function} onCycleTo
44
- */
45
- this.options = $.extend({}, Carousel.defaults, options);
46
-
47
- // Setup
48
- this.hasMultipleSlides = this.$el.find('.carousel-item').length > 1;
49
- this.showIndicators = this.options.indicators && this.hasMultipleSlides;
50
- this.noWrap = this.options.noWrap || !this.hasMultipleSlides;
51
- this.pressed = false;
52
- this.dragged = false;
53
- this.offset = this.target = 0;
54
- this.images = [];
55
- this.itemWidth = this.$el
56
- .find('.carousel-item')
57
- .first()
58
- .innerWidth();
59
- this.itemHeight = this.$el
60
- .find('.carousel-item')
61
- .first()
62
- .innerHeight();
63
- this.dim = this.itemWidth * 2 + this.options.padding || 1; // Make sure dim is non zero for divisions.
64
- this._autoScrollBound = this._autoScroll.bind(this);
65
- this._trackBound = this._track.bind(this);
66
-
67
- // Full Width carousel setup
68
- if (this.options.fullWidth) {
69
- this.options.dist = 0;
70
- this._setCarouselHeight();
71
-
72
- // Offset fixed items when indicators.
73
- if (this.showIndicators) {
74
- this.$el.find('.carousel-fixed-item').addClass('with-indicators');
75
- }
76
- }
77
-
78
- // Iterate through slides
79
- this.$indicators = $('<ul class="indicators"></ul>');
80
- this.$el.find('.carousel-item').each((el, i) => {
81
- this.images.push(el);
82
- if (this.showIndicators) {
83
- let $indicator = $('<li class="indicator-item"></li>');
84
-
85
- // Add active to first by default.
86
- if (i === 0) {
87
- $indicator[0].classList.add('active');
88
- }
89
-
90
- this.$indicators.append($indicator);
91
- }
92
- });
93
- if (this.showIndicators) {
94
- this.$el.append(this.$indicators);
95
- }
96
- this.count = this.images.length;
97
-
98
- // Cap numVisible at count
99
- this.options.numVisible = Math.min(this.count, this.options.numVisible);
100
-
101
- // Setup cross browser string
102
- this.xform = 'transform';
103
- ['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
104
- var e = prefix + 'Transform';
105
- if (typeof document.body.style[e] !== 'undefined') {
106
- this.xform = e;
107
- return false;
108
- }
109
- return true;
110
- });
111
-
112
- this._setupEventHandlers();
113
- this._scroll(this.offset);
114
- }
115
-
116
- static get defaults() {
117
- return _defaults;
118
- }
119
-
120
- static init(els, options) {
121
- return super.init(this, els, options);
122
- }
123
-
124
- /**
125
- * Get Instance
126
- */
127
- static getInstance(el) {
128
- let domElem = !!el.jquery ? el[0] : el;
129
- return domElem.M_Carousel;
130
- }
131
-
132
- /**
133
- * Teardown component
134
- */
135
- destroy() {
136
- this._removeEventHandlers();
137
- this.el.M_Carousel = undefined;
138
- }
139
-
140
- /**
141
- * Setup Event Handlers
142
- */
143
- _setupEventHandlers() {
144
- this._handleCarouselTapBound = this._handleCarouselTap.bind(this);
145
- this._handleCarouselDragBound = this._handleCarouselDrag.bind(this);
146
- this._handleCarouselReleaseBound = this._handleCarouselRelease.bind(this);
147
- this._handleCarouselClickBound = this._handleCarouselClick.bind(this);
148
-
149
- if (typeof window.ontouchstart !== 'undefined') {
150
- this.el.addEventListener('touchstart', this._handleCarouselTapBound);
151
- this.el.addEventListener('touchmove', this._handleCarouselDragBound);
152
- this.el.addEventListener('touchend', this._handleCarouselReleaseBound);
153
- }
154
-
155
- this.el.addEventListener('mousedown', this._handleCarouselTapBound);
156
- this.el.addEventListener('mousemove', this._handleCarouselDragBound);
157
- this.el.addEventListener('mouseup', this._handleCarouselReleaseBound);
158
- this.el.addEventListener('mouseleave', this._handleCarouselReleaseBound);
159
- this.el.addEventListener('click', this._handleCarouselClickBound);
160
-
161
- if (this.showIndicators && this.$indicators) {
162
- this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
163
- this.$indicators.find('.indicator-item').each((el, i) => {
164
- el.addEventListener('click', this._handleIndicatorClickBound);
165
- });
166
- }
167
-
168
- // Resize
169
- let throttledResize = M.throttle(this._handleResize, 200);
170
- this._handleThrottledResizeBound = throttledResize.bind(this);
171
-
172
- window.addEventListener('resize', this._handleThrottledResizeBound);
173
- }
174
-
175
- /**
176
- * Remove Event Handlers
177
- */
178
- _removeEventHandlers() {
179
- if (typeof window.ontouchstart !== 'undefined') {
180
- this.el.removeEventListener('touchstart', this._handleCarouselTapBound);
181
- this.el.removeEventListener('touchmove', this._handleCarouselDragBound);
182
- this.el.removeEventListener('touchend', this._handleCarouselReleaseBound);
183
- }
184
- this.el.removeEventListener('mousedown', this._handleCarouselTapBound);
185
- this.el.removeEventListener('mousemove', this._handleCarouselDragBound);
186
- this.el.removeEventListener('mouseup', this._handleCarouselReleaseBound);
187
- this.el.removeEventListener('mouseleave', this._handleCarouselReleaseBound);
188
- this.el.removeEventListener('click', this._handleCarouselClickBound);
189
-
190
- if (this.showIndicators && this.$indicators) {
191
- this.$indicators.find('.indicator-item').each((el, i) => {
192
- el.removeEventListener('click', this._handleIndicatorClickBound);
193
- });
194
- }
195
-
196
- window.removeEventListener('resize', this._handleThrottledResizeBound);
197
- }
198
-
199
- /**
200
- * Handle Carousel Tap
201
- * @param {Event} e
202
- */
203
- _handleCarouselTap(e) {
204
- // Fixes firefox draggable image bug
205
- if (e.type === 'mousedown' && $(e.target).is('img')) {
206
- e.preventDefault();
207
- }
208
- this.pressed = true;
209
- this.dragged = false;
210
- this.verticalDragged = false;
211
- this.reference = this._xpos(e);
212
- this.referenceY = this._ypos(e);
213
-
214
- this.velocity = this.amplitude = 0;
215
- this.frame = this.offset;
216
- this.timestamp = Date.now();
217
- clearInterval(this.ticker);
218
- this.ticker = setInterval(this._trackBound, 100);
219
- }
220
-
221
- /**
222
- * Handle Carousel Drag
223
- * @param {Event} e
224
- */
225
- _handleCarouselDrag(e) {
226
- let x, y, delta, deltaY;
227
- if (this.pressed) {
228
- x = this._xpos(e);
229
- y = this._ypos(e);
230
- delta = this.reference - x;
231
- deltaY = Math.abs(this.referenceY - y);
232
- if (deltaY < 30 && !this.verticalDragged) {
233
- // If vertical scrolling don't allow dragging.
234
- if (delta > 2 || delta < -2) {
235
- this.dragged = true;
236
- this.reference = x;
237
- this._scroll(this.offset + delta);
238
- }
239
- } else if (this.dragged) {
240
- // If dragging don't allow vertical scroll.
241
- e.preventDefault();
242
- e.stopPropagation();
243
- return false;
244
- } else {
245
- // Vertical scrolling.
246
- this.verticalDragged = true;
247
- }
248
- }
249
-
250
- if (this.dragged) {
251
- // If dragging don't allow vertical scroll.
252
- e.preventDefault();
253
- e.stopPropagation();
254
- return false;
255
- }
256
- }
257
-
258
- /**
259
- * Handle Carousel Release
260
- * @param {Event} e
261
- */
262
- _handleCarouselRelease(e) {
263
- if (this.pressed) {
264
- this.pressed = false;
265
- } else {
266
- return;
267
- }
268
-
269
- clearInterval(this.ticker);
270
- this.target = this.offset;
271
- if (this.velocity > 10 || this.velocity < -10) {
272
- this.amplitude = 0.9 * this.velocity;
273
- this.target = this.offset + this.amplitude;
274
- }
275
- this.target = Math.round(this.target / this.dim) * this.dim;
276
-
277
- // No wrap of items.
278
- if (this.noWrap) {
279
- if (this.target >= this.dim * (this.count - 1)) {
280
- this.target = this.dim * (this.count - 1);
281
- } else if (this.target < 0) {
282
- this.target = 0;
283
- }
284
- }
285
- this.amplitude = this.target - this.offset;
286
- this.timestamp = Date.now();
287
- requestAnimationFrame(this._autoScrollBound);
288
-
289
- if (this.dragged) {
290
- e.preventDefault();
291
- e.stopPropagation();
292
- }
293
- return false;
294
- }
295
-
296
- /**
297
- * Handle Carousel Click
298
- * @param {Event} e
299
- */
300
- _handleCarouselClick(e) {
301
- // Disable clicks if carousel was dragged.
302
- if (this.dragged) {
303
- e.preventDefault();
304
- e.stopPropagation();
305
- return false;
306
- } else if (!this.options.fullWidth) {
307
- let clickedIndex = $(e.target)
308
- .closest('.carousel-item')
309
- .index();
310
- let diff = this._wrap(this.center) - clickedIndex;
311
-
312
- // Disable clicks if carousel was shifted by click
313
- if (diff !== 0) {
314
- e.preventDefault();
315
- e.stopPropagation();
316
- }
317
-
318
- // fixes https://github.com/materializecss/materialize/issues/180
319
- if (clickedIndex < 0) {
320
- // relative X position > center of carousel = clicked at the right part of the carousel
321
- if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
322
- this.next();
323
- } else {
324
- this.prev();
325
- }
326
- } else {
327
- this._cycleTo(clickedIndex);
328
- }
329
- }
330
- }
331
-
332
- /**
333
- * Handle Indicator CLick
334
- * @param {Event} e
335
- */
336
- _handleIndicatorClick(e) {
337
- e.stopPropagation();
338
-
339
- let indicator = $(e.target).closest('.indicator-item');
340
- if (indicator.length) {
341
- this._cycleTo(indicator.index());
342
- }
343
- }
344
-
345
- /**
346
- * Handle Throttle Resize
347
- * @param {Event} e
348
- */
349
- _handleResize(e) {
350
- if (this.options.fullWidth) {
351
- this.itemWidth = this.$el
352
- .find('.carousel-item')
353
- .first()
354
- .innerWidth();
355
- this.imageHeight = this.$el.find('.carousel-item.active').height();
356
- this.dim = this.itemWidth * 2 + this.options.padding;
357
- this.offset = this.center * 2 * this.itemWidth;
358
- this.target = this.offset;
359
- this._setCarouselHeight(true);
360
- } else {
361
- this._scroll();
362
- }
363
- }
364
-
365
- /**
366
- * Set carousel height based on first slide
367
- * @param {Booleam} imageOnly - true for image slides
368
- */
369
- _setCarouselHeight(imageOnly) {
370
- let firstSlide = this.$el.find('.carousel-item.active').length
371
- ? this.$el.find('.carousel-item.active').first()
372
- : this.$el.find('.carousel-item').first();
373
- let firstImage = firstSlide.find('img').first();
374
- if (firstImage.length) {
375
- if (firstImage[0].complete) {
376
- // If image won't trigger the load event
377
- let imageHeight = firstImage.height();
378
- if (imageHeight > 0) {
379
- this.$el.css('height', imageHeight + 'px');
380
- } else {
381
- // If image still has no height, use the natural dimensions to calculate
382
- let naturalWidth = firstImage[0].naturalWidth;
383
- let naturalHeight = firstImage[0].naturalHeight;
384
- let adjustedHeight = (this.$el.width() / naturalWidth) * naturalHeight;
385
- this.$el.css('height', adjustedHeight + 'px');
386
- }
387
- } else {
388
- // Get height when image is loaded normally
389
- firstImage.one('load', (el, i) => {
390
- this.$el.css('height', el.offsetHeight + 'px');
391
- });
392
- }
393
- } else if (!imageOnly) {
394
- let slideHeight = firstSlide.height();
395
- this.$el.css('height', slideHeight + 'px');
396
- }
397
- }
398
-
399
- /**
400
- * Get x position from event
401
- * @param {Event} e
402
- */
403
- _xpos(e) {
404
- // touch event
405
- if (e.targetTouches && e.targetTouches.length >= 1) {
406
- return e.targetTouches[0].clientX;
407
- }
408
-
409
- // mouse event
410
- return e.clientX;
411
- }
412
-
413
- /**
414
- * Get y position from event
415
- * @param {Event} e
416
- */
417
- _ypos(e) {
418
- // touch event
419
- if (e.targetTouches && e.targetTouches.length >= 1) {
420
- return e.targetTouches[0].clientY;
421
- }
422
-
423
- // mouse event
424
- return e.clientY;
425
- }
426
-
427
- /**
428
- * Wrap index
429
- * @param {Number} x
430
- */
431
- _wrap(x) {
432
- return x >= this.count
433
- ? x % this.count
434
- : x < 0
435
- ? this._wrap(this.count + (x % this.count))
436
- : x;
437
- }
438
-
439
- /**
440
- * Tracks scrolling information
441
- */
442
- _track() {
443
- let now, elapsed, delta, v;
444
-
445
- now = Date.now();
446
- elapsed = now - this.timestamp;
447
- this.timestamp = now;
448
- delta = this.offset - this.frame;
449
- this.frame = this.offset;
450
-
451
- v = (1000 * delta) / (1 + elapsed);
452
- this.velocity = 0.8 * v + 0.2 * this.velocity;
453
- }
454
-
455
- /**
456
- * Auto scrolls to nearest carousel item.
457
- */
458
- _autoScroll() {
459
- let elapsed, delta;
460
-
461
- if (this.amplitude) {
462
- elapsed = Date.now() - this.timestamp;
463
- delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
464
- if (delta > 2 || delta < -2) {
465
- this._scroll(this.target - delta);
466
- requestAnimationFrame(this._autoScrollBound);
467
- } else {
468
- this._scroll(this.target);
469
- }
470
- }
471
- }
472
-
473
- /**
474
- * Scroll to target
475
- * @param {Number} x
476
- */
477
- _scroll(x) {
478
- // Track scrolling state
479
- if (!this.$el.hasClass('scrolling')) {
480
- this.el.classList.add('scrolling');
481
- }
482
- if (this.scrollingTimeout != null) {
483
- window.clearTimeout(this.scrollingTimeout);
484
- }
485
- this.scrollingTimeout = window.setTimeout(() => {
486
- this.$el.removeClass('scrolling');
487
- }, this.options.duration);
488
-
489
- // Start actual scroll
490
- let i,
491
- half,
492
- delta,
493
- dir,
494
- tween,
495
- el,
496
- alignment,
497
- zTranslation,
498
- tweenedOpacity,
499
- centerTweenedOpacity;
500
- let lastCenter = this.center;
501
- let numVisibleOffset = 1 / this.options.numVisible;
502
-
503
- this.offset = typeof x === 'number' ? x : this.offset;
504
- this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
505
- delta = this.offset - this.center * this.dim;
506
- dir = delta < 0 ? 1 : -1;
507
- tween = (-dir * delta * 2) / this.dim;
508
- half = this.count >> 1;
509
-
510
- if (this.options.fullWidth) {
511
- alignment = 'translateX(0)';
512
- centerTweenedOpacity = 1;
513
- } else {
514
- alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
515
- alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
516
- centerTweenedOpacity = 1 - numVisibleOffset * tween;
517
- }
518
-
519
- // Set indicator active
520
- if (this.showIndicators) {
521
- let diff = this.center % this.count;
522
- let activeIndicator = this.$indicators.find('.indicator-item.active');
523
- if (activeIndicator.index() !== diff) {
524
- activeIndicator.removeClass('active');
525
- this.$indicators
526
- .find('.indicator-item')
527
- .eq(diff)[0]
528
- .classList.add('active');
529
- }
530
- }
531
-
532
- // center
533
- // Don't show wrapped items.
534
- if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
535
- el = this.images[this._wrap(this.center)];
536
-
537
- // Add active class to center item.
538
- if (!$(el).hasClass('active')) {
539
- this.$el.find('.carousel-item').removeClass('active');
540
- el.classList.add('active');
541
- }
542
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
543
- this.options.shift *
544
- tween *
545
- i}px) translateZ(${this.options.dist * tween}px)`;
546
- this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
547
- }
548
-
549
- for (i = 1; i <= half; ++i) {
550
- // right side
551
- if (this.options.fullWidth) {
552
- zTranslation = this.options.dist;
553
- tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
554
- } else {
555
- zTranslation = this.options.dist * (i * 2 + tween * dir);
556
- tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
557
- }
558
- // Don't show wrapped items.
559
- if (!this.noWrap || this.center + i < this.count) {
560
- el = this.images[this._wrap(this.center + i)];
561
- let transformString = `${alignment} translateX(${this.options.shift +
562
- (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
563
- this._updateItemStyle(el, tweenedOpacity, -i, transformString);
564
- }
565
-
566
- // left side
567
- if (this.options.fullWidth) {
568
- zTranslation = this.options.dist;
569
- tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
570
- } else {
571
- zTranslation = this.options.dist * (i * 2 - tween * dir);
572
- tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
573
- }
574
- // Don't show wrapped items.
575
- if (!this.noWrap || this.center - i >= 0) {
576
- el = this.images[this._wrap(this.center - i)];
577
- let transformString = `${alignment} translateX(${-this.options.shift +
578
- (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
579
- this._updateItemStyle(el, tweenedOpacity, -i, transformString);
580
- }
581
- }
582
-
583
- // center
584
- // Don't show wrapped items.
585
- if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
586
- el = this.images[this._wrap(this.center)];
587
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
588
- this.options.shift *
589
- tween}px) translateZ(${this.options.dist * tween}px)`;
590
- this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
591
- }
592
-
593
- // onCycleTo callback
594
- let $currItem = this.$el.find('.carousel-item').eq(this._wrap(this.center));
595
- if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
596
- this.options.onCycleTo.call(this, $currItem[0], this.dragged);
597
- }
598
-
599
- // One time callback
600
- if (typeof this.oneTimeCallback === 'function') {
601
- this.oneTimeCallback.call(this, $currItem[0], this.dragged);
602
- this.oneTimeCallback = null;
603
- }
604
- }
605
-
606
- /**
607
- * Cycle to target
608
- * @param {Element} el
609
- * @param {Number} opacity
610
- * @param {Number} zIndex
611
- * @param {String} transform
612
- */
613
- _updateItemStyle(el, opacity, zIndex, transform) {
614
- el.style[this.xform] = transform;
615
- el.style.zIndex = zIndex;
616
- el.style.opacity = opacity;
617
- el.style.visibility = 'visible';
618
- }
619
-
620
- /**
621
- * Cycle to target
622
- * @param {Number} n
623
- * @param {Function} callback
624
- */
625
- _cycleTo(n, callback) {
626
- let diff = (this.center % this.count) - n;
627
-
628
- // Account for wraparound.
629
- if (!this.noWrap) {
630
- if (diff < 0) {
631
- if (Math.abs(diff + this.count) < Math.abs(diff)) {
632
- diff += this.count;
633
- }
634
- } else if (diff > 0) {
635
- if (Math.abs(diff - this.count) < diff) {
636
- diff -= this.count;
637
- }
638
- }
639
- }
640
-
641
- this.target = this.dim * Math.round(this.offset / this.dim);
642
- // Next
643
- if (diff < 0) {
644
- this.target += this.dim * Math.abs(diff);
645
-
646
- // Prev
647
- } else if (diff > 0) {
648
- this.target -= this.dim * diff;
649
- }
650
-
651
- // Set one time callback
652
- if (typeof callback === 'function') {
653
- this.oneTimeCallback = callback;
654
- }
655
-
656
- // Scroll
657
- if (this.offset !== this.target) {
658
- this.amplitude = this.target - this.offset;
659
- this.timestamp = Date.now();
660
- requestAnimationFrame(this._autoScrollBound);
661
- }
662
- }
663
-
664
- /**
665
- * Cycle to next item
666
- * @param {Number} [n]
667
- */
668
- next(n) {
669
- if (n === undefined || isNaN(n)) {
670
- n = 1;
671
- }
672
-
673
- let index = this.center + n;
674
- if (index >= this.count || index < 0) {
675
- if (this.noWrap) {
676
- return;
677
- }
678
-
679
- index = this._wrap(index);
680
- }
681
- this._cycleTo(index);
682
- }
683
-
684
- /**
685
- * Cycle to previous item
686
- * @param {Number} [n]
687
- */
688
- prev(n) {
689
- if (n === undefined || isNaN(n)) {
690
- n = 1;
691
- }
692
-
693
- let index = this.center - n;
694
- if (index >= this.count || index < 0) {
695
- if (this.noWrap) {
696
- return;
697
- }
698
-
699
- index = this._wrap(index);
700
- }
701
-
702
- this._cycleTo(index);
703
- }
704
-
705
- /**
706
- * Cycle to nth item
707
- * @param {Number} [n]
708
- * @param {Function} callback
709
- */
710
- set(n, callback) {
711
- if (n === undefined || isNaN(n)) {
712
- n = 0;
713
- }
714
-
715
- if (n > this.count || n < 0) {
716
- if (this.noWrap) {
717
- return;
718
- }
719
-
720
- n = this._wrap(n);
721
- }
722
-
723
- this._cycleTo(n, callback);
724
- }
725
- }
726
-
727
- M.Carousel = Carousel;
728
-
729
- if (M.jQueryLoaded) {
730
- M.initializeJqueryWrapper(Carousel, 'carousel', 'M_Carousel');
731
- }
732
- })(cash);
1
+ (function($) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ duration: 200, // ms
6
+ dist: -100, // zoom scale TODO: make this more intuitive as an option
7
+ shift: 0, // spacing for center image
8
+ padding: 0, // Padding between non center items
9
+ numVisible: 5, // Number of visible items in carousel
10
+ fullWidth: false, // Change to full width styles
11
+ indicators: false, // Toggle indicators
12
+ noWrap: false, // Don't wrap around and cycle through items.
13
+ onCycleTo: null // Callback for when a new slide is cycled to.
14
+ };
15
+
16
+ /**
17
+ * @class
18
+ *
19
+ */
20
+ class Carousel extends Component {
21
+ /**
22
+ * Construct Carousel instance
23
+ * @constructor
24
+ * @param {Element} el
25
+ * @param {Object} options
26
+ */
27
+ constructor(el, options) {
28
+ super(Carousel, el, options);
29
+
30
+ this.el.M_Carousel = this;
31
+
32
+ /**
33
+ * Options for the carousel
34
+ * @member Carousel#options
35
+ * @prop {Number} duration
36
+ * @prop {Number} dist
37
+ * @prop {Number} shift
38
+ * @prop {Number} padding
39
+ * @prop {Number} numVisible
40
+ * @prop {Boolean} fullWidth
41
+ * @prop {Boolean} indicators
42
+ * @prop {Boolean} noWrap
43
+ * @prop {Function} onCycleTo
44
+ */
45
+ this.options = $.extend({}, Carousel.defaults, options);
46
+
47
+ // Setup
48
+ this.hasMultipleSlides = this.$el.find('.carousel-item').length > 1;
49
+ this.showIndicators = this.options.indicators && this.hasMultipleSlides;
50
+ this.noWrap = this.options.noWrap || !this.hasMultipleSlides;
51
+ this.pressed = false;
52
+ this.dragged = false;
53
+ this.offset = this.target = 0;
54
+ this.images = [];
55
+ this.itemWidth = this.$el
56
+ .find('.carousel-item')
57
+ .first()
58
+ .innerWidth();
59
+ this.itemHeight = this.$el
60
+ .find('.carousel-item')
61
+ .first()
62
+ .innerHeight();
63
+ this.dim = this.itemWidth * 2 + this.options.padding || 1; // Make sure dim is non zero for divisions.
64
+ this._autoScrollBound = this._autoScroll.bind(this);
65
+ this._trackBound = this._track.bind(this);
66
+
67
+ // Full Width carousel setup
68
+ if (this.options.fullWidth) {
69
+ this.options.dist = 0;
70
+ this._setCarouselHeight();
71
+
72
+ // Offset fixed items when indicators.
73
+ if (this.showIndicators) {
74
+ this.$el.find('.carousel-fixed-item').addClass('with-indicators');
75
+ }
76
+ }
77
+
78
+ // Iterate through slides
79
+ this.$indicators = $('<ul class="indicators"></ul>');
80
+ this.$el.find('.carousel-item').each((el, i) => {
81
+ this.images.push(el);
82
+ if (this.showIndicators) {
83
+ let $indicator = $('<li class="indicator-item"></li>');
84
+
85
+ // Add active to first by default.
86
+ if (i === 0) {
87
+ $indicator[0].classList.add('active');
88
+ }
89
+
90
+ this.$indicators.append($indicator);
91
+ }
92
+ });
93
+ if (this.showIndicators) {
94
+ this.$el.append(this.$indicators);
95
+ }
96
+ this.count = this.images.length;
97
+
98
+ // Cap numVisible at count
99
+ this.options.numVisible = Math.min(this.count, this.options.numVisible);
100
+
101
+ // Setup cross browser string
102
+ this.xform = 'transform';
103
+ ['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
104
+ var e = prefix + 'Transform';
105
+ if (typeof document.body.style[e] !== 'undefined') {
106
+ this.xform = e;
107
+ return false;
108
+ }
109
+ return true;
110
+ });
111
+
112
+ this._setupEventHandlers();
113
+ this._scroll(this.offset);
114
+ }
115
+
116
+ static get defaults() {
117
+ return _defaults;
118
+ }
119
+
120
+ static init(els, options) {
121
+ return super.init(this, els, options);
122
+ }
123
+
124
+ /**
125
+ * Get Instance
126
+ */
127
+ static getInstance(el) {
128
+ let domElem = !!el.jquery ? el[0] : el;
129
+ return domElem.M_Carousel;
130
+ }
131
+
132
+ /**
133
+ * Teardown component
134
+ */
135
+ destroy() {
136
+ this._removeEventHandlers();
137
+ this.el.M_Carousel = undefined;
138
+ }
139
+
140
+ /**
141
+ * Setup Event Handlers
142
+ */
143
+ _setupEventHandlers() {
144
+ this._handleCarouselTapBound = this._handleCarouselTap.bind(this);
145
+ this._handleCarouselDragBound = this._handleCarouselDrag.bind(this);
146
+ this._handleCarouselReleaseBound = this._handleCarouselRelease.bind(this);
147
+ this._handleCarouselClickBound = this._handleCarouselClick.bind(this);
148
+
149
+ if (typeof window.ontouchstart !== 'undefined') {
150
+ this.el.addEventListener('touchstart', this._handleCarouselTapBound);
151
+ this.el.addEventListener('touchmove', this._handleCarouselDragBound);
152
+ this.el.addEventListener('touchend', this._handleCarouselReleaseBound);
153
+ }
154
+
155
+ this.el.addEventListener('mousedown', this._handleCarouselTapBound);
156
+ this.el.addEventListener('mousemove', this._handleCarouselDragBound);
157
+ this.el.addEventListener('mouseup', this._handleCarouselReleaseBound);
158
+ this.el.addEventListener('mouseleave', this._handleCarouselReleaseBound);
159
+ this.el.addEventListener('click', this._handleCarouselClickBound);
160
+
161
+ if (this.showIndicators && this.$indicators) {
162
+ this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
163
+ this.$indicators.find('.indicator-item').each((el, i) => {
164
+ el.addEventListener('click', this._handleIndicatorClickBound);
165
+ });
166
+ }
167
+
168
+ // Resize
169
+ let throttledResize = M.throttle(this._handleResize, 200);
170
+ this._handleThrottledResizeBound = throttledResize.bind(this);
171
+
172
+ window.addEventListener('resize', this._handleThrottledResizeBound);
173
+ }
174
+
175
+ /**
176
+ * Remove Event Handlers
177
+ */
178
+ _removeEventHandlers() {
179
+ if (typeof window.ontouchstart !== 'undefined') {
180
+ this.el.removeEventListener('touchstart', this._handleCarouselTapBound);
181
+ this.el.removeEventListener('touchmove', this._handleCarouselDragBound);
182
+ this.el.removeEventListener('touchend', this._handleCarouselReleaseBound);
183
+ }
184
+ this.el.removeEventListener('mousedown', this._handleCarouselTapBound);
185
+ this.el.removeEventListener('mousemove', this._handleCarouselDragBound);
186
+ this.el.removeEventListener('mouseup', this._handleCarouselReleaseBound);
187
+ this.el.removeEventListener('mouseleave', this._handleCarouselReleaseBound);
188
+ this.el.removeEventListener('click', this._handleCarouselClickBound);
189
+
190
+ if (this.showIndicators && this.$indicators) {
191
+ this.$indicators.find('.indicator-item').each((el, i) => {
192
+ el.removeEventListener('click', this._handleIndicatorClickBound);
193
+ });
194
+ }
195
+
196
+ window.removeEventListener('resize', this._handleThrottledResizeBound);
197
+ }
198
+
199
+ /**
200
+ * Handle Carousel Tap
201
+ * @param {Event} e
202
+ */
203
+ _handleCarouselTap(e) {
204
+ // Fixes firefox draggable image bug
205
+ if (e.type === 'mousedown' && $(e.target).is('img')) {
206
+ e.preventDefault();
207
+ }
208
+ this.pressed = true;
209
+ this.dragged = false;
210
+ this.verticalDragged = false;
211
+ this.reference = this._xpos(e);
212
+ this.referenceY = this._ypos(e);
213
+
214
+ this.velocity = this.amplitude = 0;
215
+ this.frame = this.offset;
216
+ this.timestamp = Date.now();
217
+ clearInterval(this.ticker);
218
+ this.ticker = setInterval(this._trackBound, 100);
219
+ }
220
+
221
+ /**
222
+ * Handle Carousel Drag
223
+ * @param {Event} e
224
+ */
225
+ _handleCarouselDrag(e) {
226
+ let x, y, delta, deltaY;
227
+ if (this.pressed) {
228
+ x = this._xpos(e);
229
+ y = this._ypos(e);
230
+ delta = this.reference - x;
231
+ deltaY = Math.abs(this.referenceY - y);
232
+ if (deltaY < 30 && !this.verticalDragged) {
233
+ // If vertical scrolling don't allow dragging.
234
+ if (delta > 2 || delta < -2) {
235
+ this.dragged = true;
236
+ this.reference = x;
237
+ this._scroll(this.offset + delta);
238
+ }
239
+ } else if (this.dragged) {
240
+ // If dragging don't allow vertical scroll.
241
+ e.preventDefault();
242
+ e.stopPropagation();
243
+ return false;
244
+ } else {
245
+ // Vertical scrolling.
246
+ this.verticalDragged = true;
247
+ }
248
+ }
249
+
250
+ if (this.dragged) {
251
+ // If dragging don't allow vertical scroll.
252
+ e.preventDefault();
253
+ e.stopPropagation();
254
+ return false;
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Handle Carousel Release
260
+ * @param {Event} e
261
+ */
262
+ _handleCarouselRelease(e) {
263
+ if (this.pressed) {
264
+ this.pressed = false;
265
+ } else {
266
+ return;
267
+ }
268
+
269
+ clearInterval(this.ticker);
270
+ this.target = this.offset;
271
+ if (this.velocity > 10 || this.velocity < -10) {
272
+ this.amplitude = 0.9 * this.velocity;
273
+ this.target = this.offset + this.amplitude;
274
+ }
275
+ this.target = Math.round(this.target / this.dim) * this.dim;
276
+
277
+ // No wrap of items.
278
+ if (this.noWrap) {
279
+ if (this.target >= this.dim * (this.count - 1)) {
280
+ this.target = this.dim * (this.count - 1);
281
+ } else if (this.target < 0) {
282
+ this.target = 0;
283
+ }
284
+ }
285
+ this.amplitude = this.target - this.offset;
286
+ this.timestamp = Date.now();
287
+ requestAnimationFrame(this._autoScrollBound);
288
+
289
+ if (this.dragged) {
290
+ e.preventDefault();
291
+ e.stopPropagation();
292
+ }
293
+ return false;
294
+ }
295
+
296
+ /**
297
+ * Handle Carousel Click
298
+ * @param {Event} e
299
+ */
300
+ _handleCarouselClick(e) {
301
+ // Disable clicks if carousel was dragged.
302
+ if (this.dragged) {
303
+ e.preventDefault();
304
+ e.stopPropagation();
305
+ return false;
306
+ } else if (!this.options.fullWidth) {
307
+ let clickedIndex = $(e.target)
308
+ .closest('.carousel-item')
309
+ .index();
310
+ let diff = this._wrap(this.center) - clickedIndex;
311
+
312
+ // Disable clicks if carousel was shifted by click
313
+ if (diff !== 0) {
314
+ e.preventDefault();
315
+ e.stopPropagation();
316
+ }
317
+
318
+ // fixes https://github.com/materializecss/materialize/issues/180
319
+ if (clickedIndex < 0) {
320
+ // relative X position > center of carousel = clicked at the right part of the carousel
321
+ if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
322
+ this.next();
323
+ } else {
324
+ this.prev();
325
+ }
326
+ } else {
327
+ this._cycleTo(clickedIndex);
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Handle Indicator CLick
334
+ * @param {Event} e
335
+ */
336
+ _handleIndicatorClick(e) {
337
+ e.stopPropagation();
338
+
339
+ let indicator = $(e.target).closest('.indicator-item');
340
+ if (indicator.length) {
341
+ this._cycleTo(indicator.index());
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Handle Throttle Resize
347
+ * @param {Event} e
348
+ */
349
+ _handleResize(e) {
350
+ if (this.options.fullWidth) {
351
+ this.itemWidth = this.$el
352
+ .find('.carousel-item')
353
+ .first()
354
+ .innerWidth();
355
+ this.imageHeight = this.$el.find('.carousel-item.active').height();
356
+ this.dim = this.itemWidth * 2 + this.options.padding;
357
+ this.offset = this.center * 2 * this.itemWidth;
358
+ this.target = this.offset;
359
+ this._setCarouselHeight(true);
360
+ } else {
361
+ this._scroll();
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Set carousel height based on first slide
367
+ * @param {Booleam} imageOnly - true for image slides
368
+ */
369
+ _setCarouselHeight(imageOnly) {
370
+ let firstSlide = this.$el.find('.carousel-item.active').length
371
+ ? this.$el.find('.carousel-item.active').first()
372
+ : this.$el.find('.carousel-item').first();
373
+ let firstImage = firstSlide.find('img').first();
374
+ if (firstImage.length) {
375
+ if (firstImage[0].complete) {
376
+ // If image won't trigger the load event
377
+ let imageHeight = firstImage.height();
378
+ if (imageHeight > 0) {
379
+ this.$el.css('height', imageHeight + 'px');
380
+ } else {
381
+ // If image still has no height, use the natural dimensions to calculate
382
+ let naturalWidth = firstImage[0].naturalWidth;
383
+ let naturalHeight = firstImage[0].naturalHeight;
384
+ let adjustedHeight = (this.$el.width() / naturalWidth) * naturalHeight;
385
+ this.$el.css('height', adjustedHeight + 'px');
386
+ }
387
+ } else {
388
+ // Get height when image is loaded normally
389
+ firstImage.one('load', (el, i) => {
390
+ this.$el.css('height', el.offsetHeight + 'px');
391
+ });
392
+ }
393
+ } else if (!imageOnly) {
394
+ let slideHeight = firstSlide.height();
395
+ this.$el.css('height', slideHeight + 'px');
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Get x position from event
401
+ * @param {Event} e
402
+ */
403
+ _xpos(e) {
404
+ // touch event
405
+ if (e.targetTouches && e.targetTouches.length >= 1) {
406
+ return e.targetTouches[0].clientX;
407
+ }
408
+
409
+ // mouse event
410
+ return e.clientX;
411
+ }
412
+
413
+ /**
414
+ * Get y position from event
415
+ * @param {Event} e
416
+ */
417
+ _ypos(e) {
418
+ // touch event
419
+ if (e.targetTouches && e.targetTouches.length >= 1) {
420
+ return e.targetTouches[0].clientY;
421
+ }
422
+
423
+ // mouse event
424
+ return e.clientY;
425
+ }
426
+
427
+ /**
428
+ * Wrap index
429
+ * @param {Number} x
430
+ */
431
+ _wrap(x) {
432
+ return x >= this.count
433
+ ? x % this.count
434
+ : x < 0
435
+ ? this._wrap(this.count + (x % this.count))
436
+ : x;
437
+ }
438
+
439
+ /**
440
+ * Tracks scrolling information
441
+ */
442
+ _track() {
443
+ let now, elapsed, delta, v;
444
+
445
+ now = Date.now();
446
+ elapsed = now - this.timestamp;
447
+ this.timestamp = now;
448
+ delta = this.offset - this.frame;
449
+ this.frame = this.offset;
450
+
451
+ v = (1000 * delta) / (1 + elapsed);
452
+ this.velocity = 0.8 * v + 0.2 * this.velocity;
453
+ }
454
+
455
+ /**
456
+ * Auto scrolls to nearest carousel item.
457
+ */
458
+ _autoScroll() {
459
+ let elapsed, delta;
460
+
461
+ if (this.amplitude) {
462
+ elapsed = Date.now() - this.timestamp;
463
+ delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
464
+ if (delta > 2 || delta < -2) {
465
+ this._scroll(this.target - delta);
466
+ requestAnimationFrame(this._autoScrollBound);
467
+ } else {
468
+ this._scroll(this.target);
469
+ }
470
+ }
471
+ }
472
+
473
+ /**
474
+ * Scroll to target
475
+ * @param {Number} x
476
+ */
477
+ _scroll(x) {
478
+ // Track scrolling state
479
+ if (!this.$el.hasClass('scrolling')) {
480
+ this.el.classList.add('scrolling');
481
+ }
482
+ if (this.scrollingTimeout != null) {
483
+ window.clearTimeout(this.scrollingTimeout);
484
+ }
485
+ this.scrollingTimeout = window.setTimeout(() => {
486
+ this.$el.removeClass('scrolling');
487
+ }, this.options.duration);
488
+
489
+ // Start actual scroll
490
+ let i,
491
+ half,
492
+ delta,
493
+ dir,
494
+ tween,
495
+ el,
496
+ alignment,
497
+ zTranslation,
498
+ tweenedOpacity,
499
+ centerTweenedOpacity;
500
+ let lastCenter = this.center;
501
+ let numVisibleOffset = 1 / this.options.numVisible;
502
+
503
+ this.offset = typeof x === 'number' ? x : this.offset;
504
+ this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
505
+ delta = this.offset - this.center * this.dim;
506
+ dir = delta < 0 ? 1 : -1;
507
+ tween = (-dir * delta * 2) / this.dim;
508
+ half = this.count >> 1;
509
+
510
+ if (this.options.fullWidth) {
511
+ alignment = 'translateX(0)';
512
+ centerTweenedOpacity = 1;
513
+ } else {
514
+ alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
515
+ alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
516
+ centerTweenedOpacity = 1 - numVisibleOffset * tween;
517
+ }
518
+
519
+ // Set indicator active
520
+ if (this.showIndicators) {
521
+ let diff = this.center % this.count;
522
+ let activeIndicator = this.$indicators.find('.indicator-item.active');
523
+ if (activeIndicator.index() !== diff) {
524
+ activeIndicator.removeClass('active');
525
+ this.$indicators
526
+ .find('.indicator-item')
527
+ .eq(diff)[0]
528
+ .classList.add('active');
529
+ }
530
+ }
531
+
532
+ // center
533
+ // Don't show wrapped items.
534
+ if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
535
+ el = this.images[this._wrap(this.center)];
536
+
537
+ // Add active class to center item.
538
+ if (!$(el).hasClass('active')) {
539
+ this.$el.find('.carousel-item').removeClass('active');
540
+ el.classList.add('active');
541
+ }
542
+ let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
543
+ this.options.shift *
544
+ tween *
545
+ i}px) translateZ(${this.options.dist * tween}px)`;
546
+ this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
547
+ }
548
+
549
+ for (i = 1; i <= half; ++i) {
550
+ // right side
551
+ if (this.options.fullWidth) {
552
+ zTranslation = this.options.dist;
553
+ tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
554
+ } else {
555
+ zTranslation = this.options.dist * (i * 2 + tween * dir);
556
+ tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
557
+ }
558
+ // Don't show wrapped items.
559
+ if (!this.noWrap || this.center + i < this.count) {
560
+ el = this.images[this._wrap(this.center + i)];
561
+ let transformString = `${alignment} translateX(${this.options.shift +
562
+ (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
563
+ this._updateItemStyle(el, tweenedOpacity, -i, transformString);
564
+ }
565
+
566
+ // left side
567
+ if (this.options.fullWidth) {
568
+ zTranslation = this.options.dist;
569
+ tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
570
+ } else {
571
+ zTranslation = this.options.dist * (i * 2 - tween * dir);
572
+ tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
573
+ }
574
+ // Don't show wrapped items.
575
+ if (!this.noWrap || this.center - i >= 0) {
576
+ el = this.images[this._wrap(this.center - i)];
577
+ let transformString = `${alignment} translateX(${-this.options.shift +
578
+ (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
579
+ this._updateItemStyle(el, tweenedOpacity, -i, transformString);
580
+ }
581
+ }
582
+
583
+ // center
584
+ // Don't show wrapped items.
585
+ if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
586
+ el = this.images[this._wrap(this.center)];
587
+ let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
588
+ this.options.shift *
589
+ tween}px) translateZ(${this.options.dist * tween}px)`;
590
+ this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
591
+ }
592
+
593
+ // onCycleTo callback
594
+ let $currItem = this.$el.find('.carousel-item').eq(this._wrap(this.center));
595
+ if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
596
+ this.options.onCycleTo.call(this, $currItem[0], this.dragged);
597
+ }
598
+
599
+ // One time callback
600
+ if (typeof this.oneTimeCallback === 'function') {
601
+ this.oneTimeCallback.call(this, $currItem[0], this.dragged);
602
+ this.oneTimeCallback = null;
603
+ }
604
+ }
605
+
606
+ /**
607
+ * Cycle to target
608
+ * @param {Element} el
609
+ * @param {Number} opacity
610
+ * @param {Number} zIndex
611
+ * @param {String} transform
612
+ */
613
+ _updateItemStyle(el, opacity, zIndex, transform) {
614
+ el.style[this.xform] = transform;
615
+ el.style.zIndex = zIndex;
616
+ el.style.opacity = opacity;
617
+ el.style.visibility = 'visible';
618
+ }
619
+
620
+ /**
621
+ * Cycle to target
622
+ * @param {Number} n
623
+ * @param {Function} callback
624
+ */
625
+ _cycleTo(n, callback) {
626
+ let diff = (this.center % this.count) - n;
627
+
628
+ // Account for wraparound.
629
+ if (!this.noWrap) {
630
+ if (diff < 0) {
631
+ if (Math.abs(diff + this.count) < Math.abs(diff)) {
632
+ diff += this.count;
633
+ }
634
+ } else if (diff > 0) {
635
+ if (Math.abs(diff - this.count) < diff) {
636
+ diff -= this.count;
637
+ }
638
+ }
639
+ }
640
+
641
+ this.target = this.dim * Math.round(this.offset / this.dim);
642
+ // Next
643
+ if (diff < 0) {
644
+ this.target += this.dim * Math.abs(diff);
645
+
646
+ // Prev
647
+ } else if (diff > 0) {
648
+ this.target -= this.dim * diff;
649
+ }
650
+
651
+ // Set one time callback
652
+ if (typeof callback === 'function') {
653
+ this.oneTimeCallback = callback;
654
+ }
655
+
656
+ // Scroll
657
+ if (this.offset !== this.target) {
658
+ this.amplitude = this.target - this.offset;
659
+ this.timestamp = Date.now();
660
+ requestAnimationFrame(this._autoScrollBound);
661
+ }
662
+ }
663
+
664
+ /**
665
+ * Cycle to next item
666
+ * @param {Number} [n]
667
+ */
668
+ next(n) {
669
+ if (n === undefined || isNaN(n)) {
670
+ n = 1;
671
+ }
672
+
673
+ let index = this.center + n;
674
+ if (index >= this.count || index < 0) {
675
+ if (this.noWrap) {
676
+ return;
677
+ }
678
+
679
+ index = this._wrap(index);
680
+ }
681
+ this._cycleTo(index);
682
+ }
683
+
684
+ /**
685
+ * Cycle to previous item
686
+ * @param {Number} [n]
687
+ */
688
+ prev(n) {
689
+ if (n === undefined || isNaN(n)) {
690
+ n = 1;
691
+ }
692
+
693
+ let index = this.center - n;
694
+ if (index >= this.count || index < 0) {
695
+ if (this.noWrap) {
696
+ return;
697
+ }
698
+
699
+ index = this._wrap(index);
700
+ }
701
+
702
+ this._cycleTo(index);
703
+ }
704
+
705
+ /**
706
+ * Cycle to nth item
707
+ * @param {Number} [n]
708
+ * @param {Function} callback
709
+ */
710
+ set(n, callback) {
711
+ if (n === undefined || isNaN(n)) {
712
+ n = 0;
713
+ }
714
+
715
+ if (n > this.count || n < 0) {
716
+ if (this.noWrap) {
717
+ return;
718
+ }
719
+
720
+ n = this._wrap(n);
721
+ }
722
+
723
+ this._cycleTo(n, callback);
724
+ }
725
+ }
726
+
727
+ M.Carousel = Carousel;
728
+
729
+ if (M.jQueryLoaded) {
730
+ M.initializeJqueryWrapper(Carousel, 'carousel', 'M_Carousel');
731
+ }
732
+ })(cash);