kmaterialize 2.0.0
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.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/css/materialize.css +9067 -0
- package/dist/css/materialize.min.css +13 -0
- package/dist/js/materialize.js +12374 -0
- package/dist/js/materialize.min.js +6 -0
- package/extras/noUiSlider/nouislider.css +406 -0
- package/extras/noUiSlider/nouislider.js +2147 -0
- package/extras/noUiSlider/nouislider.min.js +1 -0
- package/js/anime.min.js +34 -0
- package/js/autocomplete.js +448 -0
- package/js/buttons.js +354 -0
- package/js/cards.js +40 -0
- package/js/carousel.js +717 -0
- package/js/cash.js +960 -0
- package/js/characterCounter.js +136 -0
- package/js/chips.js +481 -0
- package/js/collapsible.js +275 -0
- package/js/component.js +44 -0
- package/js/datepicker.js +975 -0
- package/js/dropdown.js +635 -0
- package/js/forms.js +275 -0
- package/js/global.js +444 -0
- package/js/materialbox.js +453 -0
- package/js/modal.js +382 -0
- package/js/parallax.js +138 -0
- package/js/pushpin.js +148 -0
- package/js/range.js +263 -0
- package/js/scrollspy.js +295 -0
- package/js/select.js +450 -0
- package/js/sidenav.js +580 -0
- package/js/slider.js +359 -0
- package/js/tabs.js +402 -0
- package/js/tapTarget.js +314 -0
- package/js/timepicker.js +647 -0
- package/js/toasts.js +310 -0
- package/js/tooltip.js +303 -0
- package/js/waves.js +335 -0
- package/package.json +62 -0
package/js/carousel.js
ADDED
|
@@ -0,0 +1,717 @@
|
|
|
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
|
+
this._cycleTo(clickedIndex);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Handle Indicator CLick
|
|
323
|
+
* @param {Event} e
|
|
324
|
+
*/
|
|
325
|
+
_handleIndicatorClick(e) {
|
|
326
|
+
e.stopPropagation();
|
|
327
|
+
|
|
328
|
+
let indicator = $(e.target).closest('.indicator-item');
|
|
329
|
+
if (indicator.length) {
|
|
330
|
+
this._cycleTo(indicator.index());
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Handle Throttle Resize
|
|
336
|
+
* @param {Event} e
|
|
337
|
+
*/
|
|
338
|
+
_handleResize(e) {
|
|
339
|
+
if (this.options.fullWidth) {
|
|
340
|
+
this.itemWidth = this.$el
|
|
341
|
+
.find('.carousel-item')
|
|
342
|
+
.first()
|
|
343
|
+
.innerWidth();
|
|
344
|
+
this.imageHeight = this.$el.find('.carousel-item.active').height();
|
|
345
|
+
this.dim = this.itemWidth * 2 + this.options.padding;
|
|
346
|
+
this.offset = this.center * 2 * this.itemWidth;
|
|
347
|
+
this.target = this.offset;
|
|
348
|
+
this._setCarouselHeight(true);
|
|
349
|
+
} else {
|
|
350
|
+
this._scroll();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Set carousel height based on first slide
|
|
356
|
+
* @param {Booleam} imageOnly - true for image slides
|
|
357
|
+
*/
|
|
358
|
+
_setCarouselHeight(imageOnly) {
|
|
359
|
+
let firstSlide = this.$el.find('.carousel-item.active').length
|
|
360
|
+
? this.$el.find('.carousel-item.active').first()
|
|
361
|
+
: this.$el.find('.carousel-item').first();
|
|
362
|
+
let firstImage = firstSlide.find('img').first();
|
|
363
|
+
if (firstImage.length) {
|
|
364
|
+
if (firstImage[0].complete) {
|
|
365
|
+
// If image won't trigger the load event
|
|
366
|
+
let imageHeight = firstImage.height();
|
|
367
|
+
if (imageHeight > 0) {
|
|
368
|
+
this.$el.css('height', imageHeight + 'px');
|
|
369
|
+
} else {
|
|
370
|
+
// If image still has no height, use the natural dimensions to calculate
|
|
371
|
+
let naturalWidth = firstImage[0].naturalWidth;
|
|
372
|
+
let naturalHeight = firstImage[0].naturalHeight;
|
|
373
|
+
let adjustedHeight = this.$el.width() / naturalWidth * naturalHeight;
|
|
374
|
+
this.$el.css('height', adjustedHeight + 'px');
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
// Get height when image is loaded normally
|
|
378
|
+
firstImage.one('load', (el, i) => {
|
|
379
|
+
this.$el.css('height', el.offsetHeight + 'px');
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
} else if (!imageOnly) {
|
|
383
|
+
let slideHeight = firstSlide.height();
|
|
384
|
+
this.$el.css('height', slideHeight + 'px');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Get x position from event
|
|
390
|
+
* @param {Event} e
|
|
391
|
+
*/
|
|
392
|
+
_xpos(e) {
|
|
393
|
+
// touch event
|
|
394
|
+
if (e.targetTouches && e.targetTouches.length >= 1) {
|
|
395
|
+
return e.targetTouches[0].clientX;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// mouse event
|
|
399
|
+
return e.clientX;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get y position from event
|
|
404
|
+
* @param {Event} e
|
|
405
|
+
*/
|
|
406
|
+
_ypos(e) {
|
|
407
|
+
// touch event
|
|
408
|
+
if (e.targetTouches && e.targetTouches.length >= 1) {
|
|
409
|
+
return e.targetTouches[0].clientY;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// mouse event
|
|
413
|
+
return e.clientY;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Wrap index
|
|
418
|
+
* @param {Number} x
|
|
419
|
+
*/
|
|
420
|
+
_wrap(x) {
|
|
421
|
+
return x >= this.count ? x % this.count : x < 0 ? this._wrap(this.count + x % this.count) : x;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Tracks scrolling information
|
|
426
|
+
*/
|
|
427
|
+
_track() {
|
|
428
|
+
let now, elapsed, delta, v;
|
|
429
|
+
|
|
430
|
+
now = Date.now();
|
|
431
|
+
elapsed = now - this.timestamp;
|
|
432
|
+
this.timestamp = now;
|
|
433
|
+
delta = this.offset - this.frame;
|
|
434
|
+
this.frame = this.offset;
|
|
435
|
+
|
|
436
|
+
v = 1000 * delta / (1 + elapsed);
|
|
437
|
+
this.velocity = 0.8 * v + 0.2 * this.velocity;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Auto scrolls to nearest carousel item.
|
|
442
|
+
*/
|
|
443
|
+
_autoScroll() {
|
|
444
|
+
let elapsed, delta;
|
|
445
|
+
|
|
446
|
+
if (this.amplitude) {
|
|
447
|
+
elapsed = Date.now() - this.timestamp;
|
|
448
|
+
delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
|
|
449
|
+
if (delta > 2 || delta < -2) {
|
|
450
|
+
this._scroll(this.target - delta);
|
|
451
|
+
requestAnimationFrame(this._autoScrollBound);
|
|
452
|
+
} else {
|
|
453
|
+
this._scroll(this.target);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Scroll to target
|
|
460
|
+
* @param {Number} x
|
|
461
|
+
*/
|
|
462
|
+
_scroll(x) {
|
|
463
|
+
// Track scrolling state
|
|
464
|
+
if (!this.$el.hasClass('scrolling')) {
|
|
465
|
+
this.el.classList.add('scrolling');
|
|
466
|
+
}
|
|
467
|
+
if (this.scrollingTimeout != null) {
|
|
468
|
+
window.clearTimeout(this.scrollingTimeout);
|
|
469
|
+
}
|
|
470
|
+
this.scrollingTimeout = window.setTimeout(() => {
|
|
471
|
+
this.$el.removeClass('scrolling');
|
|
472
|
+
}, this.options.duration);
|
|
473
|
+
|
|
474
|
+
// Start actual scroll
|
|
475
|
+
let i,
|
|
476
|
+
half,
|
|
477
|
+
delta,
|
|
478
|
+
dir,
|
|
479
|
+
tween,
|
|
480
|
+
el,
|
|
481
|
+
alignment,
|
|
482
|
+
zTranslation,
|
|
483
|
+
tweenedOpacity,
|
|
484
|
+
centerTweenedOpacity;
|
|
485
|
+
let lastCenter = this.center;
|
|
486
|
+
let numVisibleOffset = 1 / this.options.numVisible;
|
|
487
|
+
|
|
488
|
+
this.offset = typeof x === 'number' ? x : this.offset;
|
|
489
|
+
this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
|
|
490
|
+
delta = this.offset - this.center * this.dim;
|
|
491
|
+
dir = delta < 0 ? 1 : -1;
|
|
492
|
+
tween = -dir * delta * 2 / this.dim;
|
|
493
|
+
half = this.count >> 1;
|
|
494
|
+
|
|
495
|
+
if (this.options.fullWidth) {
|
|
496
|
+
alignment = 'translateX(0)';
|
|
497
|
+
centerTweenedOpacity = 1;
|
|
498
|
+
} else {
|
|
499
|
+
alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
|
|
500
|
+
alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
|
|
501
|
+
centerTweenedOpacity = 1 - numVisibleOffset * tween;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Set indicator active
|
|
505
|
+
if (this.showIndicators) {
|
|
506
|
+
let diff = this.center % this.count;
|
|
507
|
+
let activeIndicator = this.$indicators.find('.indicator-item.active');
|
|
508
|
+
if (activeIndicator.index() !== diff) {
|
|
509
|
+
activeIndicator.removeClass('active');
|
|
510
|
+
this.$indicators
|
|
511
|
+
.find('.indicator-item')
|
|
512
|
+
.eq(diff)[0]
|
|
513
|
+
.classList.add('active');
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// center
|
|
518
|
+
// Don't show wrapped items.
|
|
519
|
+
if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
|
|
520
|
+
el = this.images[this._wrap(this.center)];
|
|
521
|
+
|
|
522
|
+
// Add active class to center item.
|
|
523
|
+
if (!$(el).hasClass('active')) {
|
|
524
|
+
this.$el.find('.carousel-item').removeClass('active');
|
|
525
|
+
el.classList.add('active');
|
|
526
|
+
}
|
|
527
|
+
let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
|
|
528
|
+
this.options.shift *
|
|
529
|
+
tween *
|
|
530
|
+
i}px) translateZ(${this.options.dist * tween}px)`;
|
|
531
|
+
this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
for (i = 1; i <= half; ++i) {
|
|
535
|
+
// right side
|
|
536
|
+
if (this.options.fullWidth) {
|
|
537
|
+
zTranslation = this.options.dist;
|
|
538
|
+
tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
|
|
539
|
+
} else {
|
|
540
|
+
zTranslation = this.options.dist * (i * 2 + tween * dir);
|
|
541
|
+
tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
|
|
542
|
+
}
|
|
543
|
+
// Don't show wrapped items.
|
|
544
|
+
if (!this.noWrap || this.center + i < this.count) {
|
|
545
|
+
el = this.images[this._wrap(this.center + i)];
|
|
546
|
+
let transformString = `${alignment} translateX(${this.options.shift +
|
|
547
|
+
(this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
|
548
|
+
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// left side
|
|
552
|
+
if (this.options.fullWidth) {
|
|
553
|
+
zTranslation = this.options.dist;
|
|
554
|
+
tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
|
|
555
|
+
} else {
|
|
556
|
+
zTranslation = this.options.dist * (i * 2 - tween * dir);
|
|
557
|
+
tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
|
|
558
|
+
}
|
|
559
|
+
// Don't show wrapped items.
|
|
560
|
+
if (!this.noWrap || this.center - i >= 0) {
|
|
561
|
+
el = this.images[this._wrap(this.center - i)];
|
|
562
|
+
let transformString = `${alignment} translateX(${-this.options.shift +
|
|
563
|
+
(-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
|
564
|
+
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// center
|
|
569
|
+
// Don't show wrapped items.
|
|
570
|
+
if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
|
|
571
|
+
el = this.images[this._wrap(this.center)];
|
|
572
|
+
let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
|
|
573
|
+
this.options.shift *
|
|
574
|
+
tween}px) translateZ(${this.options.dist * tween}px)`;
|
|
575
|
+
this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// onCycleTo callback
|
|
579
|
+
let $currItem = this.$el.find('.carousel-item').eq(this._wrap(this.center));
|
|
580
|
+
if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
|
|
581
|
+
this.options.onCycleTo.call(this, $currItem[0], this.dragged);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// One time callback
|
|
585
|
+
if (typeof this.oneTimeCallback === 'function') {
|
|
586
|
+
this.oneTimeCallback.call(this, $currItem[0], this.dragged);
|
|
587
|
+
this.oneTimeCallback = null;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Cycle to target
|
|
593
|
+
* @param {Element} el
|
|
594
|
+
* @param {Number} opacity
|
|
595
|
+
* @param {Number} zIndex
|
|
596
|
+
* @param {String} transform
|
|
597
|
+
*/
|
|
598
|
+
_updateItemStyle(el, opacity, zIndex, transform) {
|
|
599
|
+
el.style[this.xform] = transform;
|
|
600
|
+
el.style.zIndex = zIndex;
|
|
601
|
+
el.style.opacity = opacity;
|
|
602
|
+
el.style.visibility = 'visible';
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Cycle to target
|
|
607
|
+
* @param {Number} n
|
|
608
|
+
* @param {Function} callback
|
|
609
|
+
*/
|
|
610
|
+
_cycleTo(n, callback) {
|
|
611
|
+
let diff = this.center % this.count - n;
|
|
612
|
+
|
|
613
|
+
// Account for wraparound.
|
|
614
|
+
if (!this.noWrap) {
|
|
615
|
+
if (diff < 0) {
|
|
616
|
+
if (Math.abs(diff + this.count) < Math.abs(diff)) {
|
|
617
|
+
diff += this.count;
|
|
618
|
+
}
|
|
619
|
+
} else if (diff > 0) {
|
|
620
|
+
if (Math.abs(diff - this.count) < diff) {
|
|
621
|
+
diff -= this.count;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
this.target = this.dim * Math.round(this.offset / this.dim);
|
|
627
|
+
// Next
|
|
628
|
+
if (diff < 0) {
|
|
629
|
+
this.target += this.dim * Math.abs(diff);
|
|
630
|
+
|
|
631
|
+
// Prev
|
|
632
|
+
} else if (diff > 0) {
|
|
633
|
+
this.target -= this.dim * diff;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Set one time callback
|
|
637
|
+
if (typeof callback === 'function') {
|
|
638
|
+
this.oneTimeCallback = callback;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Scroll
|
|
642
|
+
if (this.offset !== this.target) {
|
|
643
|
+
this.amplitude = this.target - this.offset;
|
|
644
|
+
this.timestamp = Date.now();
|
|
645
|
+
requestAnimationFrame(this._autoScrollBound);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Cycle to next item
|
|
651
|
+
* @param {Number} [n]
|
|
652
|
+
*/
|
|
653
|
+
next(n) {
|
|
654
|
+
if (n === undefined || isNaN(n)) {
|
|
655
|
+
n = 1;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
let index = this.center + n;
|
|
659
|
+
if (index >= this.count || index < 0) {
|
|
660
|
+
if (this.noWrap) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
index = this._wrap(index);
|
|
665
|
+
}
|
|
666
|
+
this._cycleTo(index);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Cycle to previous item
|
|
671
|
+
* @param {Number} [n]
|
|
672
|
+
*/
|
|
673
|
+
prev(n) {
|
|
674
|
+
if (n === undefined || isNaN(n)) {
|
|
675
|
+
n = 1;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
let index = this.center - n;
|
|
679
|
+
if (index >= this.count || index < 0) {
|
|
680
|
+
if (this.noWrap) {
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
index = this._wrap(index);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
this._cycleTo(index);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Cycle to nth item
|
|
692
|
+
* @param {Number} [n]
|
|
693
|
+
* @param {Function} callback
|
|
694
|
+
*/
|
|
695
|
+
set(n, callback) {
|
|
696
|
+
if (n === undefined || isNaN(n)) {
|
|
697
|
+
n = 0;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (n > this.count || n < 0) {
|
|
701
|
+
if (this.noWrap) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
n = this._wrap(n);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
this._cycleTo(n, callback);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
M.Carousel = Carousel;
|
|
713
|
+
|
|
714
|
+
if (M.jQueryLoaded) {
|
|
715
|
+
M.initializeJqueryWrapper(Carousel, 'carousel', 'M_Carousel');
|
|
716
|
+
}
|
|
717
|
+
})(cash);
|