UNPKG

16.8 kBJavaScriptView Raw
1/* eslint no-param-reassign: "off" */
2import { getDocument } from 'ssr-window';
3import $ from '../shared/dom.js';
4import { extend, now, deleteProps } from '../shared/utils.js';
5import { getSupport } from '../shared/get-support.js';
6import { getDevice } from '../shared/get-device.js';
7import { getBrowser } from '../shared/get-browser.js';
8import Resize from './modules/resize/resize.js';
9import Observer from './modules/observer/observer.js';
10import eventsEmitter from './events-emitter.js';
11import update from './update/index.js';
12import translate from './translate/index.js';
13import transition from './transition/index.js';
14import slide from './slide/index.js';
15import loop from './loop/index.js';
16import grabCursor from './grab-cursor/index.js';
17import events from './events/index.js';
18import breakpoints from './breakpoints/index.js';
19import classes from './classes/index.js';
20import images from './images/index.js';
21import checkOverflow from './check-overflow/index.js';
22import defaults from './defaults.js';
23import moduleExtendParams from './moduleExtendParams.js';
24const prototypes = {
25 eventsEmitter,
26 update,
27 translate,
28 transition,
29 slide,
30 loop,
31 grabCursor,
32 events,
33 breakpoints,
34 checkOverflow,
35 classes,
36 images
37};
38const extendedDefaults = {};
39
40class Swiper {
41 constructor() {
42 let el;
43 let params;
44
45 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
46 args[_key] = arguments[_key];
47 }
48
49 if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') {
50 params = args[0];
51 } else {
52 [el, params] = args;
53 }
54
55 if (!params) params = {};
56 params = extend({}, params);
57 if (el && !params.el) params.el = el;
58
59 if (params.el && $(params.el).length > 1) {
60 const swipers = [];
61 $(params.el).each(containerEl => {
62 const newParams = extend({}, params, {
63 el: containerEl
64 });
65 swipers.push(new Swiper(newParams));
66 });
67 return swipers;
68 } // Swiper Instance
69
70
71 const swiper = this;
72 swiper.__swiper__ = true;
73 swiper.support = getSupport();
74 swiper.device = getDevice({
75 userAgent: params.userAgent
76 });
77 swiper.browser = getBrowser();
78 swiper.eventsListeners = {};
79 swiper.eventsAnyListeners = [];
80 swiper.modules = [...swiper.__modules__];
81
82 if (params.modules && Array.isArray(params.modules)) {
83 swiper.modules.push(...params.modules);
84 }
85
86 const allModulesParams = {};
87 swiper.modules.forEach(mod => {
88 mod({
89 swiper,
90 extendParams: moduleExtendParams(params, allModulesParams),
91 on: swiper.on.bind(swiper),
92 once: swiper.once.bind(swiper),
93 off: swiper.off.bind(swiper),
94 emit: swiper.emit.bind(swiper)
95 });
96 }); // Extend defaults with modules params
97
98 const swiperParams = extend({}, defaults, allModulesParams); // Extend defaults with passed params
99
100 swiper.params = extend({}, swiperParams, extendedDefaults, params);
101 swiper.originalParams = extend({}, swiper.params);
102 swiper.passedParams = extend({}, params); // add event listeners
103
104 if (swiper.params && swiper.params.on) {
105 Object.keys(swiper.params.on).forEach(eventName => {
106 swiper.on(eventName, swiper.params.on[eventName]);
107 });
108 }
109
110 if (swiper.params && swiper.params.onAny) {
111 swiper.onAny(swiper.params.onAny);
112 } // Save Dom lib
113
114
115 swiper.$ = $; // Extend Swiper
116
117 Object.assign(swiper, {
118 enabled: swiper.params.enabled,
119 el,
120 // Classes
121 classNames: [],
122 // Slides
123 slides: $(),
124 slidesGrid: [],
125 snapGrid: [],
126 slidesSizesGrid: [],
127
128 // isDirection
129 isHorizontal() {
130 return swiper.params.direction === 'horizontal';
131 },
132
133 isVertical() {
134 return swiper.params.direction === 'vertical';
135 },
136
137 // Indexes
138 activeIndex: 0,
139 realIndex: 0,
140 //
141 isBeginning: true,
142 isEnd: false,
143 // Props
144 translate: 0,
145 previousTranslate: 0,
146 progress: 0,
147 velocity: 0,
148 animating: false,
149 // Locks
150 allowSlideNext: swiper.params.allowSlideNext,
151 allowSlidePrev: swiper.params.allowSlidePrev,
152 // Touch Events
153 touchEvents: function touchEvents() {
154 const touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];
155 const desktop = ['pointerdown', 'pointermove', 'pointerup'];
156 swiper.touchEventsTouch = {
157 start: touch[0],
158 move: touch[1],
159 end: touch[2],
160 cancel: touch[3]
161 };
162 swiper.touchEventsDesktop = {
163 start: desktop[0],
164 move: desktop[1],
165 end: desktop[2]
166 };
167 return swiper.support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;
168 }(),
169 touchEventsData: {
170 isTouched: undefined,
171 isMoved: undefined,
172 allowTouchCallbacks: undefined,
173 touchStartTime: undefined,
174 isScrolling: undefined,
175 currentTranslate: undefined,
176 startTranslate: undefined,
177 allowThresholdMove: undefined,
178 // Form elements to match
179 focusableElements: swiper.params.focusableElements,
180 // Last click time
181 lastClickTime: now(),
182 clickTimeout: undefined,
183 // Velocities
184 velocities: [],
185 allowMomentumBounce: undefined,
186 isTouchEvent: undefined,
187 startMoving: undefined
188 },
189 // Clicks
190 allowClick: true,
191 // Touches
192 allowTouchMove: swiper.params.allowTouchMove,
193 touches: {
194 startX: 0,
195 startY: 0,
196 currentX: 0,
197 currentY: 0,
198 diff: 0
199 },
200 // Images
201 imagesToLoad: [],
202 imagesLoaded: 0
203 });
204 swiper.emit('_swiper'); // Init
205
206 if (swiper.params.init) {
207 swiper.init();
208 } // Return app instance
209
210
211 return swiper;
212 }
213
214 enable() {
215 const swiper = this;
216 if (swiper.enabled) return;
217 swiper.enabled = true;
218
219 if (swiper.params.grabCursor) {
220 swiper.setGrabCursor();
221 }
222
223 swiper.emit('enable');
224 }
225
226 disable() {
227 const swiper = this;
228 if (!swiper.enabled) return;
229 swiper.enabled = false;
230
231 if (swiper.params.grabCursor) {
232 swiper.unsetGrabCursor();
233 }
234
235 swiper.emit('disable');
236 }
237
238 setProgress(progress, speed) {
239 const swiper = this;
240 progress = Math.min(Math.max(progress, 0), 1);
241 const min = swiper.minTranslate();
242 const max = swiper.maxTranslate();
243 const current = (max - min) * progress + min;
244 swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed);
245 swiper.updateActiveIndex();
246 swiper.updateSlidesClasses();
247 }
248
249 emitContainerClasses() {
250 const swiper = this;
251 if (!swiper.params._emitClasses || !swiper.el) return;
252 const cls = swiper.el.className.split(' ').filter(className => {
253 return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0;
254 });
255 swiper.emit('_containerClasses', cls.join(' '));
256 }
257
258 getSlideClasses(slideEl) {
259 const swiper = this;
260 return slideEl.className.split(' ').filter(className => {
261 return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0;
262 }).join(' ');
263 }
264
265 emitSlidesClasses() {
266 const swiper = this;
267 if (!swiper.params._emitClasses || !swiper.el) return;
268 const updates = [];
269 swiper.slides.each(slideEl => {
270 const classNames = swiper.getSlideClasses(slideEl);
271 updates.push({
272 slideEl,
273 classNames
274 });
275 swiper.emit('_slideClass', slideEl, classNames);
276 });
277 swiper.emit('_slideClasses', updates);
278 }
279
280 slidesPerViewDynamic(view, exact) {
281 if (view === void 0) {
282 view = 'current';
283 }
284
285 if (exact === void 0) {
286 exact = false;
287 }
288
289 const swiper = this;
290 const {
291 params,
292 slides,
293 slidesGrid,
294 slidesSizesGrid,
295 size: swiperSize,
296 activeIndex
297 } = swiper;
298 let spv = 1;
299
300 if (params.centeredSlides) {
301 let slideSize = slides[activeIndex].swiperSlideSize;
302 let breakLoop;
303
304 for (let i = activeIndex + 1; i < slides.length; i += 1) {
305 if (slides[i] && !breakLoop) {
306 slideSize += slides[i].swiperSlideSize;
307 spv += 1;
308 if (slideSize > swiperSize) breakLoop = true;
309 }
310 }
311
312 for (let i = activeIndex - 1; i >= 0; i -= 1) {
313 if (slides[i] && !breakLoop) {
314 slideSize += slides[i].swiperSlideSize;
315 spv += 1;
316 if (slideSize > swiperSize) breakLoop = true;
317 }
318 }
319 } else {
320 // eslint-disable-next-line
321 if (view === 'current') {
322 for (let i = activeIndex + 1; i < slides.length; i += 1) {
323 const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;
324
325 if (slideInView) {
326 spv += 1;
327 }
328 }
329 } else {
330 // previous
331 for (let i = activeIndex - 1; i >= 0; i -= 1) {
332 const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;
333
334 if (slideInView) {
335 spv += 1;
336 }
337 }
338 }
339 }
340
341 return spv;
342 }
343
344 update() {
345 const swiper = this;
346 if (!swiper || swiper.destroyed) return;
347 const {
348 snapGrid,
349 params
350 } = swiper; // Breakpoints
351
352 if (params.breakpoints) {
353 swiper.setBreakpoint();
354 }
355
356 swiper.updateSize();
357 swiper.updateSlides();
358 swiper.updateProgress();
359 swiper.updateSlidesClasses();
360
361 function setTranslate() {
362 const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
363 const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
364 swiper.setTranslate(newTranslate);
365 swiper.updateActiveIndex();
366 swiper.updateSlidesClasses();
367 }
368
369 let translated;
370
371 if (swiper.params.freeMode && swiper.params.freeMode.enabled) {
372 setTranslate();
373
374 if (swiper.params.autoHeight) {
375 swiper.updateAutoHeight();
376 }
377 } else {
378 if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
379 translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
380 } else {
381 translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
382 }
383
384 if (!translated) {
385 setTranslate();
386 }
387 }
388
389 if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
390 swiper.checkOverflow();
391 }
392
393 swiper.emit('update');
394 }
395
396 changeDirection(newDirection, needUpdate) {
397 if (needUpdate === void 0) {
398 needUpdate = true;
399 }
400
401 const swiper = this;
402 const currentDirection = swiper.params.direction;
403
404 if (!newDirection) {
405 // eslint-disable-next-line
406 newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
407 }
408
409 if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {
410 return swiper;
411 }
412
413 swiper.$el.removeClass(`${swiper.params.containerModifierClass}${currentDirection}`).addClass(`${swiper.params.containerModifierClass}${newDirection}`);
414 swiper.emitContainerClasses();
415 swiper.params.direction = newDirection;
416 swiper.slides.each(slideEl => {
417 if (newDirection === 'vertical') {
418 slideEl.style.width = '';
419 } else {
420 slideEl.style.height = '';
421 }
422 });
423 swiper.emit('changeDirection');
424 if (needUpdate) swiper.update();
425 return swiper;
426 }
427
428 mount(el) {
429 const swiper = this;
430 if (swiper.mounted) return true; // Find el
431
432 const $el = $(el || swiper.params.el);
433 el = $el[0];
434
435 if (!el) {
436 return false;
437 }
438
439 el.swiper = swiper;
440
441 const getWrapperSelector = () => {
442 return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`;
443 };
444
445 const getWrapper = () => {
446 if (el && el.shadowRoot && el.shadowRoot.querySelector) {
447 const res = $(el.shadowRoot.querySelector(getWrapperSelector())); // Children needs to return slot items
448
449 res.children = options => $el.children(options);
450
451 return res;
452 }
453
454 return $el.children(getWrapperSelector());
455 }; // Find Wrapper
456
457
458 let $wrapperEl = getWrapper();
459
460 if ($wrapperEl.length === 0 && swiper.params.createElements) {
461 const document = getDocument();
462 const wrapper = document.createElement('div');
463 $wrapperEl = $(wrapper);
464 wrapper.className = swiper.params.wrapperClass;
465 $el.append(wrapper);
466 $el.children(`.${swiper.params.slideClass}`).each(slideEl => {
467 $wrapperEl.append(slideEl);
468 });
469 }
470
471 Object.assign(swiper, {
472 $el,
473 el,
474 $wrapperEl,
475 wrapperEl: $wrapperEl[0],
476 mounted: true,
477 // RTL
478 rtl: el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl',
479 rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
480 wrongRTL: $wrapperEl.css('display') === '-webkit-box'
481 });
482 return true;
483 }
484
485 init(el) {
486 const swiper = this;
487 if (swiper.initialized) return swiper;
488 const mounted = swiper.mount(el);
489 if (mounted === false) return swiper;
490 swiper.emit('beforeInit'); // Set breakpoint
491
492 if (swiper.params.breakpoints) {
493 swiper.setBreakpoint();
494 } // Add Classes
495
496
497 swiper.addClasses(); // Create loop
498
499 if (swiper.params.loop) {
500 swiper.loopCreate();
501 } // Update size
502
503
504 swiper.updateSize(); // Update slides
505
506 swiper.updateSlides();
507
508 if (swiper.params.watchOverflow) {
509 swiper.checkOverflow();
510 } // Set Grab Cursor
511
512
513 if (swiper.params.grabCursor && swiper.enabled) {
514 swiper.setGrabCursor();
515 }
516
517 if (swiper.params.preloadImages) {
518 swiper.preloadImages();
519 } // Slide To Initial Slide
520
521
522 if (swiper.params.loop) {
523 swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit, false, true);
524 } else {
525 swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
526 } // Attach events
527
528
529 swiper.attachEvents(); // Init Flag
530
531 swiper.initialized = true; // Emit
532
533 swiper.emit('init');
534 swiper.emit('afterInit');
535 return swiper;
536 }
537
538 destroy(deleteInstance, cleanStyles) {
539 if (deleteInstance === void 0) {
540 deleteInstance = true;
541 }
542
543 if (cleanStyles === void 0) {
544 cleanStyles = true;
545 }
546
547 const swiper = this;
548 const {
549 params,
550 $el,
551 $wrapperEl,
552 slides
553 } = swiper;
554
555 if (typeof swiper.params === 'undefined' || swiper.destroyed) {
556 return null;
557 }
558
559 swiper.emit('beforeDestroy'); // Init Flag
560
561 swiper.initialized = false; // Detach events
562
563 swiper.detachEvents(); // Destroy loop
564
565 if (params.loop) {
566 swiper.loopDestroy();
567 } // Cleanup styles
568
569
570 if (cleanStyles) {
571 swiper.removeClasses();
572 $el.removeAttr('style');
573 $wrapperEl.removeAttr('style');
574
575 if (slides && slides.length) {
576 slides.removeClass([params.slideVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass].join(' ')).removeAttr('style').removeAttr('data-swiper-slide-index');
577 }
578 }
579
580 swiper.emit('destroy'); // Detach emitter events
581
582 Object.keys(swiper.eventsListeners).forEach(eventName => {
583 swiper.off(eventName);
584 });
585
586 if (deleteInstance !== false) {
587 swiper.$el[0].swiper = null;
588 deleteProps(swiper);
589 }
590
591 swiper.destroyed = true;
592 return null;
593 }
594
595 static extendDefaults(newDefaults) {
596 extend(extendedDefaults, newDefaults);
597 }
598
599 static get extendedDefaults() {
600 return extendedDefaults;
601 }
602
603 static get defaults() {
604 return defaults;
605 }
606
607 static installModule(mod) {
608 if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = [];
609 const modules = Swiper.prototype.__modules__;
610
611 if (typeof mod === 'function' && modules.indexOf(mod) < 0) {
612 modules.push(mod);
613 }
614 }
615
616 static use(module) {
617 if (Array.isArray(module)) {
618 module.forEach(m => Swiper.installModule(m));
619 return Swiper;
620 }
621
622 Swiper.installModule(module);
623 return Swiper;
624 }
625
626}
627
628Object.keys(prototypes).forEach(prototypeGroup => {
629 Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => {
630 Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
631 });
632});
633Swiper.use([Resize, Observer]);
634export default Swiper;
\No newline at end of file