@materializecss/materialize 1.1.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 (83) hide show
  1. package/Gruntfile.js +38 -24
  2. package/LICENSE +21 -21
  3. package/README.md +91 -97
  4. package/dist/css/materialize.css +8608 -8631
  5. package/dist/css/materialize.min.css +12 -12
  6. package/dist/js/materialize.js +12816 -12669
  7. package/dist/js/materialize.min.js +6 -6
  8. package/extras/noUiSlider/nouislider.css +404 -406
  9. package/extras/noUiSlider/nouislider.js +2147 -2147
  10. package/extras/noUiSlider/nouislider.min.js +0 -0
  11. package/js/anime.min.js +34 -34
  12. package/js/autocomplete.js +479 -479
  13. package/js/buttons.js +354 -354
  14. package/js/cards.js +40 -40
  15. package/js/carousel.js +732 -732
  16. package/js/cash.js +960 -960
  17. package/js/characterCounter.js +136 -136
  18. package/js/chips.js +486 -486
  19. package/js/collapsible.js +275 -275
  20. package/js/component.js +44 -44
  21. package/js/datepicker.js +983 -983
  22. package/js/dropdown.js +669 -669
  23. package/js/forms.js +285 -275
  24. package/js/global.js +428 -424
  25. package/js/materialbox.js +453 -453
  26. package/js/modal.js +382 -382
  27. package/js/parallax.js +138 -138
  28. package/js/pushpin.js +148 -148
  29. package/js/range.js +263 -263
  30. package/js/scrollspy.js +295 -295
  31. package/js/select.js +391 -310
  32. package/js/sidenav.js +583 -583
  33. package/js/slider.js +359 -359
  34. package/js/tabs.js +402 -402
  35. package/js/tapTarget.js +315 -315
  36. package/js/timepicker.js +712 -648
  37. package/js/toasts.js +325 -322
  38. package/js/tooltip.js +320 -320
  39. package/js/waves.js +614 -614
  40. package/package.json +87 -82
  41. package/sass/_style.scss +929 -929
  42. package/sass/components/_badges.scss +55 -55
  43. package/sass/components/_buttons.scss +322 -322
  44. package/sass/components/_cards.scss +195 -195
  45. package/sass/components/_carousel.scss +90 -90
  46. package/sass/components/_chips.scss +96 -96
  47. package/sass/components/_collapsible.scss +91 -91
  48. package/sass/components/_collection.scss +106 -106
  49. package/sass/components/_color-classes.scss +32 -32
  50. package/sass/components/_color-variables.scss +370 -370
  51. package/sass/components/_datepicker.scss +191 -191
  52. package/sass/components/_dropdown.scss +84 -84
  53. package/sass/components/_global.scss +646 -642
  54. package/sass/components/_grid.scss +158 -158
  55. package/sass/components/_icons-material-design.scss +5 -5
  56. package/sass/components/_materialbox.scss +42 -42
  57. package/sass/components/_modal.scss +97 -97
  58. package/sass/components/_navbar.scss +208 -208
  59. package/sass/components/_normalize.scss +447 -447
  60. package/sass/components/_preloader.scss +334 -334
  61. package/sass/components/_pulse.scss +34 -34
  62. package/sass/components/_sidenav.scss +214 -214
  63. package/sass/components/_slider.scss +91 -91
  64. package/sass/components/_table_of_contents.scss +33 -33
  65. package/sass/components/_tabs.scss +99 -99
  66. package/sass/components/_tapTarget.scss +103 -103
  67. package/sass/components/_timepicker.scss +199 -183
  68. package/sass/components/_toast.scss +58 -58
  69. package/sass/components/_tooltip.scss +32 -32
  70. package/sass/components/_transitions.scss +12 -12
  71. package/sass/components/_typography.scss +62 -62
  72. package/sass/components/_variables.scss +352 -352
  73. package/sass/components/_waves.scss +187 -187
  74. package/sass/components/forms/_checkboxes.scss +200 -200
  75. package/sass/components/forms/_file-input.scss +44 -44
  76. package/sass/components/forms/_forms.scss +22 -22
  77. package/sass/components/forms/_input-fields.scss +388 -379
  78. package/sass/components/forms/_radio-buttons.scss +115 -115
  79. package/sass/components/forms/_range.scss +161 -161
  80. package/sass/components/forms/_select.scss +199 -199
  81. package/sass/components/forms/_switches.scss +91 -91
  82. package/sass/ghpages-materialize.scss +7 -7
  83. 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);