UNPKG

319 kBJavaScriptView Raw
1/**
2 * Swiper 7.0.7
3 * Most modern mobile touch slider and framework with hardware accelerated transitions
4 * https://swiperjs.com
5 *
6 * Copyright 2014-2021 Vladimir Kharlampidi
7 *
8 * Released under the MIT License
9 *
10 * Released on: September 29, 2021
11 */
12
13(function (global, factory) {
14 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
15 typeof define === 'function' && define.amd ? define(factory) :
16 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Swiper = factory());
17}(this, (function () { 'use strict';
18
19 /**
20 * SSR Window 4.0.0
21 * Better handling for window object in SSR environment
22 * https://github.com/nolimits4web/ssr-window
23 *
24 * Copyright 2021, Vladimir Kharlampidi
25 *
26 * Licensed under MIT
27 *
28 * Released on: August 25, 2021
29 */
30
31 /* eslint-disable no-param-reassign */
32 function isObject$1(obj) {
33 return obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object;
34 }
35
36 function extend$1(target = {}, src = {}) {
37 Object.keys(src).forEach(key => {
38 if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject$1(src[key]) && isObject$1(target[key]) && Object.keys(src[key]).length > 0) {
39 extend$1(target[key], src[key]);
40 }
41 });
42 }
43
44 const ssrDocument = {
45 body: {},
46
47 addEventListener() {},
48
49 removeEventListener() {},
50
51 activeElement: {
52 blur() {},
53
54 nodeName: ''
55 },
56
57 querySelector() {
58 return null;
59 },
60
61 querySelectorAll() {
62 return [];
63 },
64
65 getElementById() {
66 return null;
67 },
68
69 createEvent() {
70 return {
71 initEvent() {}
72
73 };
74 },
75
76 createElement() {
77 return {
78 children: [],
79 childNodes: [],
80 style: {},
81
82 setAttribute() {},
83
84 getElementsByTagName() {
85 return [];
86 }
87
88 };
89 },
90
91 createElementNS() {
92 return {};
93 },
94
95 importNode() {
96 return null;
97 },
98
99 location: {
100 hash: '',
101 host: '',
102 hostname: '',
103 href: '',
104 origin: '',
105 pathname: '',
106 protocol: '',
107 search: ''
108 }
109 };
110
111 function getDocument() {
112 const doc = typeof document !== 'undefined' ? document : {};
113 extend$1(doc, ssrDocument);
114 return doc;
115 }
116
117 const ssrWindow = {
118 document: ssrDocument,
119 navigator: {
120 userAgent: ''
121 },
122 location: {
123 hash: '',
124 host: '',
125 hostname: '',
126 href: '',
127 origin: '',
128 pathname: '',
129 protocol: '',
130 search: ''
131 },
132 history: {
133 replaceState() {},
134
135 pushState() {},
136
137 go() {},
138
139 back() {}
140
141 },
142 CustomEvent: function CustomEvent() {
143 return this;
144 },
145
146 addEventListener() {},
147
148 removeEventListener() {},
149
150 getComputedStyle() {
151 return {
152 getPropertyValue() {
153 return '';
154 }
155
156 };
157 },
158
159 Image() {},
160
161 Date() {},
162
163 screen: {},
164
165 setTimeout() {},
166
167 clearTimeout() {},
168
169 matchMedia() {
170 return {};
171 },
172
173 requestAnimationFrame(callback) {
174 if (typeof setTimeout === 'undefined') {
175 callback();
176 return null;
177 }
178
179 return setTimeout(callback, 0);
180 },
181
182 cancelAnimationFrame(id) {
183 if (typeof setTimeout === 'undefined') {
184 return;
185 }
186
187 clearTimeout(id);
188 }
189
190 };
191
192 function getWindow() {
193 const win = typeof window !== 'undefined' ? window : {};
194 extend$1(win, ssrWindow);
195 return win;
196 }
197
198 /**
199 * Dom7 4.0.0
200 * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API
201 * https://framework7.io/docs/dom7.html
202 *
203 * Copyright 2021, Vladimir Kharlampidi
204 *
205 * Licensed under MIT
206 *
207 * Released on: August 25, 2021
208 */
209 /* eslint-disable no-proto */
210
211 function makeReactive(obj) {
212 const proto = obj.__proto__;
213 Object.defineProperty(obj, '__proto__', {
214 get() {
215 return proto;
216 },
217
218 set(value) {
219 proto.__proto__ = value;
220 }
221
222 });
223 }
224
225 class Dom7 extends Array {
226 constructor(items) {
227 super(...(items || []));
228 makeReactive(this);
229 }
230
231 }
232
233 function arrayFlat(arr = []) {
234 const res = [];
235 arr.forEach(el => {
236 if (Array.isArray(el)) {
237 res.push(...arrayFlat(el));
238 } else {
239 res.push(el);
240 }
241 });
242 return res;
243 }
244
245 function arrayFilter(arr, callback) {
246 return Array.prototype.filter.call(arr, callback);
247 }
248
249 function arrayUnique(arr) {
250 const uniqueArray = [];
251
252 for (let i = 0; i < arr.length; i += 1) {
253 if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]);
254 }
255
256 return uniqueArray;
257 }
258
259
260 function qsa(selector, context) {
261 if (typeof selector !== 'string') {
262 return [selector];
263 }
264
265 const a = [];
266 const res = context.querySelectorAll(selector);
267
268 for (let i = 0; i < res.length; i += 1) {
269 a.push(res[i]);
270 }
271
272 return a;
273 }
274
275 function $(selector, context) {
276 const window = getWindow();
277 const document = getDocument();
278 let arr = [];
279
280 if (!context && selector instanceof Dom7) {
281 return selector;
282 }
283
284 if (!selector) {
285 return new Dom7(arr);
286 }
287
288 if (typeof selector === 'string') {
289 const html = selector.trim();
290
291 if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
292 let toCreate = 'div';
293 if (html.indexOf('<li') === 0) toCreate = 'ul';
294 if (html.indexOf('<tr') === 0) toCreate = 'tbody';
295 if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr';
296 if (html.indexOf('<tbody') === 0) toCreate = 'table';
297 if (html.indexOf('<option') === 0) toCreate = 'select';
298 const tempParent = document.createElement(toCreate);
299 tempParent.innerHTML = html;
300
301 for (let i = 0; i < tempParent.childNodes.length; i += 1) {
302 arr.push(tempParent.childNodes[i]);
303 }
304 } else {
305 arr = qsa(selector.trim(), context || document);
306 } // arr = qsa(selector, document);
307
308 } else if (selector.nodeType || selector === window || selector === document) {
309 arr.push(selector);
310 } else if (Array.isArray(selector)) {
311 if (selector instanceof Dom7) return selector;
312 arr = selector;
313 }
314
315 return new Dom7(arrayUnique(arr));
316 }
317
318 $.fn = Dom7.prototype; // eslint-disable-next-line
319
320 function addClass(...classes) {
321 const classNames = arrayFlat(classes.map(c => c.split(' ')));
322 this.forEach(el => {
323 el.classList.add(...classNames);
324 });
325 return this;
326 }
327
328 function removeClass(...classes) {
329 const classNames = arrayFlat(classes.map(c => c.split(' ')));
330 this.forEach(el => {
331 el.classList.remove(...classNames);
332 });
333 return this;
334 }
335
336 function toggleClass(...classes) {
337 const classNames = arrayFlat(classes.map(c => c.split(' ')));
338 this.forEach(el => {
339 classNames.forEach(className => {
340 el.classList.toggle(className);
341 });
342 });
343 }
344
345 function hasClass(...classes) {
346 const classNames = arrayFlat(classes.map(c => c.split(' ')));
347 return arrayFilter(this, el => {
348 return classNames.filter(className => el.classList.contains(className)).length > 0;
349 }).length > 0;
350 }
351
352 function attr(attrs, value) {
353 if (arguments.length === 1 && typeof attrs === 'string') {
354 // Get attr
355 if (this[0]) return this[0].getAttribute(attrs);
356 return undefined;
357 } // Set attrs
358
359
360 for (let i = 0; i < this.length; i += 1) {
361 if (arguments.length === 2) {
362 // String
363 this[i].setAttribute(attrs, value);
364 } else {
365 // Object
366 for (const attrName in attrs) {
367 this[i][attrName] = attrs[attrName];
368 this[i].setAttribute(attrName, attrs[attrName]);
369 }
370 }
371 }
372
373 return this;
374 }
375
376 function removeAttr(attr) {
377 for (let i = 0; i < this.length; i += 1) {
378 this[i].removeAttribute(attr);
379 }
380
381 return this;
382 }
383
384 function transform(transform) {
385 for (let i = 0; i < this.length; i += 1) {
386 this[i].style.transform = transform;
387 }
388
389 return this;
390 }
391
392 function transition$1(duration) {
393 for (let i = 0; i < this.length; i += 1) {
394 this[i].style.transitionDuration = typeof duration !== 'string' ? `${duration}ms` : duration;
395 }
396
397 return this;
398 }
399
400 function on(...args) {
401 let [eventType, targetSelector, listener, capture] = args;
402
403 if (typeof args[1] === 'function') {
404 [eventType, listener, capture] = args;
405 targetSelector = undefined;
406 }
407
408 if (!capture) capture = false;
409
410 function handleLiveEvent(e) {
411 const target = e.target;
412 if (!target) return;
413 const eventData = e.target.dom7EventData || [];
414
415 if (eventData.indexOf(e) < 0) {
416 eventData.unshift(e);
417 }
418
419 if ($(target).is(targetSelector)) listener.apply(target, eventData);else {
420 const parents = $(target).parents(); // eslint-disable-line
421
422 for (let k = 0; k < parents.length; k += 1) {
423 if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData);
424 }
425 }
426 }
427
428 function handleEvent(e) {
429 const eventData = e && e.target ? e.target.dom7EventData || [] : [];
430
431 if (eventData.indexOf(e) < 0) {
432 eventData.unshift(e);
433 }
434
435 listener.apply(this, eventData);
436 }
437
438 const events = eventType.split(' ');
439 let j;
440
441 for (let i = 0; i < this.length; i += 1) {
442 const el = this[i];
443
444 if (!targetSelector) {
445 for (j = 0; j < events.length; j += 1) {
446 const event = events[j];
447 if (!el.dom7Listeners) el.dom7Listeners = {};
448 if (!el.dom7Listeners[event]) el.dom7Listeners[event] = [];
449 el.dom7Listeners[event].push({
450 listener,
451 proxyListener: handleEvent
452 });
453 el.addEventListener(event, handleEvent, capture);
454 }
455 } else {
456 // Live events
457 for (j = 0; j < events.length; j += 1) {
458 const event = events[j];
459 if (!el.dom7LiveListeners) el.dom7LiveListeners = {};
460 if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = [];
461 el.dom7LiveListeners[event].push({
462 listener,
463 proxyListener: handleLiveEvent
464 });
465 el.addEventListener(event, handleLiveEvent, capture);
466 }
467 }
468 }
469
470 return this;
471 }
472
473 function off(...args) {
474 let [eventType, targetSelector, listener, capture] = args;
475
476 if (typeof args[1] === 'function') {
477 [eventType, listener, capture] = args;
478 targetSelector = undefined;
479 }
480
481 if (!capture) capture = false;
482 const events = eventType.split(' ');
483
484 for (let i = 0; i < events.length; i += 1) {
485 const event = events[i];
486
487 for (let j = 0; j < this.length; j += 1) {
488 const el = this[j];
489 let handlers;
490
491 if (!targetSelector && el.dom7Listeners) {
492 handlers = el.dom7Listeners[event];
493 } else if (targetSelector && el.dom7LiveListeners) {
494 handlers = el.dom7LiveListeners[event];
495 }
496
497 if (handlers && handlers.length) {
498 for (let k = handlers.length - 1; k >= 0; k -= 1) {
499 const handler = handlers[k];
500
501 if (listener && handler.listener === listener) {
502 el.removeEventListener(event, handler.proxyListener, capture);
503 handlers.splice(k, 1);
504 } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {
505 el.removeEventListener(event, handler.proxyListener, capture);
506 handlers.splice(k, 1);
507 } else if (!listener) {
508 el.removeEventListener(event, handler.proxyListener, capture);
509 handlers.splice(k, 1);
510 }
511 }
512 }
513 }
514 }
515
516 return this;
517 }
518
519 function trigger(...args) {
520 const window = getWindow();
521 const events = args[0].split(' ');
522 const eventData = args[1];
523
524 for (let i = 0; i < events.length; i += 1) {
525 const event = events[i];
526
527 for (let j = 0; j < this.length; j += 1) {
528 const el = this[j];
529
530 if (window.CustomEvent) {
531 const evt = new window.CustomEvent(event, {
532 detail: eventData,
533 bubbles: true,
534 cancelable: true
535 });
536 el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0);
537 el.dispatchEvent(evt);
538 el.dom7EventData = [];
539 delete el.dom7EventData;
540 }
541 }
542 }
543
544 return this;
545 }
546
547 function transitionEnd$1(callback) {
548 const dom = this;
549
550 function fireCallBack(e) {
551 if (e.target !== this) return;
552 callback.call(this, e);
553 dom.off('transitionend', fireCallBack);
554 }
555
556 if (callback) {
557 dom.on('transitionend', fireCallBack);
558 }
559
560 return this;
561 }
562
563 function outerWidth(includeMargins) {
564 if (this.length > 0) {
565 if (includeMargins) {
566 const styles = this.styles();
567 return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
568 }
569
570 return this[0].offsetWidth;
571 }
572
573 return null;
574 }
575
576 function outerHeight(includeMargins) {
577 if (this.length > 0) {
578 if (includeMargins) {
579 const styles = this.styles();
580 return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
581 }
582
583 return this[0].offsetHeight;
584 }
585
586 return null;
587 }
588
589 function offset() {
590 if (this.length > 0) {
591 const window = getWindow();
592 const document = getDocument();
593 const el = this[0];
594 const box = el.getBoundingClientRect();
595 const body = document.body;
596 const clientTop = el.clientTop || body.clientTop || 0;
597 const clientLeft = el.clientLeft || body.clientLeft || 0;
598 const scrollTop = el === window ? window.scrollY : el.scrollTop;
599 const scrollLeft = el === window ? window.scrollX : el.scrollLeft;
600 return {
601 top: box.top + scrollTop - clientTop,
602 left: box.left + scrollLeft - clientLeft
603 };
604 }
605
606 return null;
607 }
608
609 function styles() {
610 const window = getWindow();
611 if (this[0]) return window.getComputedStyle(this[0], null);
612 return {};
613 }
614
615 function css(props, value) {
616 const window = getWindow();
617 let i;
618
619 if (arguments.length === 1) {
620 if (typeof props === 'string') {
621 // .css('width')
622 if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);
623 } else {
624 // .css({ width: '100px' })
625 for (i = 0; i < this.length; i += 1) {
626 for (const prop in props) {
627 this[i].style[prop] = props[prop];
628 }
629 }
630
631 return this;
632 }
633 }
634
635 if (arguments.length === 2 && typeof props === 'string') {
636 // .css('width', '100px')
637 for (i = 0; i < this.length; i += 1) {
638 this[i].style[props] = value;
639 }
640
641 return this;
642 }
643
644 return this;
645 }
646
647 function each(callback) {
648 if (!callback) return this;
649 this.forEach((el, index) => {
650 callback.apply(el, [el, index]);
651 });
652 return this;
653 }
654
655 function filter(callback) {
656 const result = arrayFilter(this, callback);
657 return $(result);
658 }
659
660 function html(html) {
661 if (typeof html === 'undefined') {
662 return this[0] ? this[0].innerHTML : null;
663 }
664
665 for (let i = 0; i < this.length; i += 1) {
666 this[i].innerHTML = html;
667 }
668
669 return this;
670 }
671
672 function text(text) {
673 if (typeof text === 'undefined') {
674 return this[0] ? this[0].textContent.trim() : null;
675 }
676
677 for (let i = 0; i < this.length; i += 1) {
678 this[i].textContent = text;
679 }
680
681 return this;
682 }
683
684 function is(selector) {
685 const window = getWindow();
686 const document = getDocument();
687 const el = this[0];
688 let compareWith;
689 let i;
690 if (!el || typeof selector === 'undefined') return false;
691
692 if (typeof selector === 'string') {
693 if (el.matches) return el.matches(selector);
694 if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);
695 if (el.msMatchesSelector) return el.msMatchesSelector(selector);
696 compareWith = $(selector);
697
698 for (i = 0; i < compareWith.length; i += 1) {
699 if (compareWith[i] === el) return true;
700 }
701
702 return false;
703 }
704
705 if (selector === document) {
706 return el === document;
707 }
708
709 if (selector === window) {
710 return el === window;
711 }
712
713 if (selector.nodeType || selector instanceof Dom7) {
714 compareWith = selector.nodeType ? [selector] : selector;
715
716 for (i = 0; i < compareWith.length; i += 1) {
717 if (compareWith[i] === el) return true;
718 }
719
720 return false;
721 }
722
723 return false;
724 }
725
726 function index() {
727 let child = this[0];
728 let i;
729
730 if (child) {
731 i = 0; // eslint-disable-next-line
732
733 while ((child = child.previousSibling) !== null) {
734 if (child.nodeType === 1) i += 1;
735 }
736
737 return i;
738 }
739
740 return undefined;
741 }
742
743 function eq(index) {
744 if (typeof index === 'undefined') return this;
745 const length = this.length;
746
747 if (index > length - 1) {
748 return $([]);
749 }
750
751 if (index < 0) {
752 const returnIndex = length + index;
753 if (returnIndex < 0) return $([]);
754 return $([this[returnIndex]]);
755 }
756
757 return $([this[index]]);
758 }
759
760 function append(...els) {
761 let newChild;
762 const document = getDocument();
763
764 for (let k = 0; k < els.length; k += 1) {
765 newChild = els[k];
766
767 for (let i = 0; i < this.length; i += 1) {
768 if (typeof newChild === 'string') {
769 const tempDiv = document.createElement('div');
770 tempDiv.innerHTML = newChild;
771
772 while (tempDiv.firstChild) {
773 this[i].appendChild(tempDiv.firstChild);
774 }
775 } else if (newChild instanceof Dom7) {
776 for (let j = 0; j < newChild.length; j += 1) {
777 this[i].appendChild(newChild[j]);
778 }
779 } else {
780 this[i].appendChild(newChild);
781 }
782 }
783 }
784
785 return this;
786 }
787
788 function prepend(newChild) {
789 const document = getDocument();
790 let i;
791 let j;
792
793 for (i = 0; i < this.length; i += 1) {
794 if (typeof newChild === 'string') {
795 const tempDiv = document.createElement('div');
796 tempDiv.innerHTML = newChild;
797
798 for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {
799 this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
800 }
801 } else if (newChild instanceof Dom7) {
802 for (j = 0; j < newChild.length; j += 1) {
803 this[i].insertBefore(newChild[j], this[i].childNodes[0]);
804 }
805 } else {
806 this[i].insertBefore(newChild, this[i].childNodes[0]);
807 }
808 }
809
810 return this;
811 }
812
813 function next(selector) {
814 if (this.length > 0) {
815 if (selector) {
816 if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {
817 return $([this[0].nextElementSibling]);
818 }
819
820 return $([]);
821 }
822
823 if (this[0].nextElementSibling) return $([this[0].nextElementSibling]);
824 return $([]);
825 }
826
827 return $([]);
828 }
829
830 function nextAll(selector) {
831 const nextEls = [];
832 let el = this[0];
833 if (!el) return $([]);
834
835 while (el.nextElementSibling) {
836 const next = el.nextElementSibling; // eslint-disable-line
837
838 if (selector) {
839 if ($(next).is(selector)) nextEls.push(next);
840 } else nextEls.push(next);
841
842 el = next;
843 }
844
845 return $(nextEls);
846 }
847
848 function prev(selector) {
849 if (this.length > 0) {
850 const el = this[0];
851
852 if (selector) {
853 if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {
854 return $([el.previousElementSibling]);
855 }
856
857 return $([]);
858 }
859
860 if (el.previousElementSibling) return $([el.previousElementSibling]);
861 return $([]);
862 }
863
864 return $([]);
865 }
866
867 function prevAll(selector) {
868 const prevEls = [];
869 let el = this[0];
870 if (!el) return $([]);
871
872 while (el.previousElementSibling) {
873 const prev = el.previousElementSibling; // eslint-disable-line
874
875 if (selector) {
876 if ($(prev).is(selector)) prevEls.push(prev);
877 } else prevEls.push(prev);
878
879 el = prev;
880 }
881
882 return $(prevEls);
883 }
884
885 function parent(selector) {
886 const parents = []; // eslint-disable-line
887
888 for (let i = 0; i < this.length; i += 1) {
889 if (this[i].parentNode !== null) {
890 if (selector) {
891 if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);
892 } else {
893 parents.push(this[i].parentNode);
894 }
895 }
896 }
897
898 return $(parents);
899 }
900
901 function parents(selector) {
902 const parents = []; // eslint-disable-line
903
904 for (let i = 0; i < this.length; i += 1) {
905 let parent = this[i].parentNode; // eslint-disable-line
906
907 while (parent) {
908 if (selector) {
909 if ($(parent).is(selector)) parents.push(parent);
910 } else {
911 parents.push(parent);
912 }
913
914 parent = parent.parentNode;
915 }
916 }
917
918 return $(parents);
919 }
920
921 function closest(selector) {
922 let closest = this; // eslint-disable-line
923
924 if (typeof selector === 'undefined') {
925 return $([]);
926 }
927
928 if (!closest.is(selector)) {
929 closest = closest.parents(selector).eq(0);
930 }
931
932 return closest;
933 }
934
935 function find(selector) {
936 const foundElements = [];
937
938 for (let i = 0; i < this.length; i += 1) {
939 const found = this[i].querySelectorAll(selector);
940
941 for (let j = 0; j < found.length; j += 1) {
942 foundElements.push(found[j]);
943 }
944 }
945
946 return $(foundElements);
947 }
948
949 function children(selector) {
950 const children = []; // eslint-disable-line
951
952 for (let i = 0; i < this.length; i += 1) {
953 const childNodes = this[i].children;
954
955 for (let j = 0; j < childNodes.length; j += 1) {
956 if (!selector || $(childNodes[j]).is(selector)) {
957 children.push(childNodes[j]);
958 }
959 }
960 }
961
962 return $(children);
963 }
964
965 function remove() {
966 for (let i = 0; i < this.length; i += 1) {
967 if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);
968 }
969
970 return this;
971 }
972
973 const Methods = {
974 addClass,
975 removeClass,
976 hasClass,
977 toggleClass,
978 attr,
979 removeAttr,
980 transform,
981 transition: transition$1,
982 on,
983 off,
984 trigger,
985 transitionEnd: transitionEnd$1,
986 outerWidth,
987 outerHeight,
988 styles,
989 offset,
990 css,
991 each,
992 html,
993 text,
994 is,
995 index,
996 eq,
997 append,
998 prepend,
999 next,
1000 nextAll,
1001 prev,
1002 prevAll,
1003 parent,
1004 parents,
1005 closest,
1006 find,
1007 children,
1008 filter,
1009 remove
1010 };
1011 Object.keys(Methods).forEach(methodName => {
1012 Object.defineProperty($.fn, methodName, {
1013 value: Methods[methodName],
1014 writable: true
1015 });
1016 });
1017
1018 function deleteProps(obj) {
1019 const object = obj;
1020 Object.keys(object).forEach(key => {
1021 try {
1022 object[key] = null;
1023 } catch (e) {// no getter for object
1024 }
1025
1026 try {
1027 delete object[key];
1028 } catch (e) {// something got wrong
1029 }
1030 });
1031 }
1032
1033 function nextTick(callback, delay = 0) {
1034 return setTimeout(callback, delay);
1035 }
1036
1037 function now() {
1038 return Date.now();
1039 }
1040
1041 function getComputedStyle$1(el) {
1042 const window = getWindow();
1043 let style;
1044
1045 if (window.getComputedStyle) {
1046 style = window.getComputedStyle(el, null);
1047 }
1048
1049 if (!style && el.currentStyle) {
1050 style = el.currentStyle;
1051 }
1052
1053 if (!style) {
1054 style = el.style;
1055 }
1056
1057 return style;
1058 }
1059
1060 function getTranslate(el, axis = 'x') {
1061 const window = getWindow();
1062 let matrix;
1063 let curTransform;
1064 let transformMatrix;
1065 const curStyle = getComputedStyle$1(el);
1066
1067 if (window.WebKitCSSMatrix) {
1068 curTransform = curStyle.transform || curStyle.webkitTransform;
1069
1070 if (curTransform.split(',').length > 6) {
1071 curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');
1072 } // Some old versions of Webkit choke when 'none' is passed; pass
1073 // empty string instead in this case
1074
1075
1076 transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
1077 } else {
1078 transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
1079 matrix = transformMatrix.toString().split(',');
1080 }
1081
1082 if (axis === 'x') {
1083 // Latest Chrome and webkits Fix
1084 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41; // Crazy IE10 Matrix
1085 else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); // Normal Browsers
1086 else curTransform = parseFloat(matrix[4]);
1087 }
1088
1089 if (axis === 'y') {
1090 // Latest Chrome and webkits Fix
1091 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42; // Crazy IE10 Matrix
1092 else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); // Normal Browsers
1093 else curTransform = parseFloat(matrix[5]);
1094 }
1095
1096 return curTransform || 0;
1097 }
1098
1099 function isObject(o) {
1100 return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';
1101 }
1102
1103 function isNode(node) {
1104 // eslint-disable-next-line
1105 if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {
1106 return node instanceof HTMLElement;
1107 }
1108
1109 return node && (node.nodeType === 1 || node.nodeType === 11);
1110 }
1111
1112 function extend(...args) {
1113 const to = Object(args[0]);
1114 const noExtend = ['__proto__', 'constructor', 'prototype'];
1115
1116 for (let i = 1; i < args.length; i += 1) {
1117 const nextSource = args[i];
1118
1119 if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {
1120 const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);
1121
1122 for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
1123 const nextKey = keysArray[nextIndex];
1124 const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
1125
1126 if (desc !== undefined && desc.enumerable) {
1127 if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
1128 if (nextSource[nextKey].__swiper__) {
1129 to[nextKey] = nextSource[nextKey];
1130 } else {
1131 extend(to[nextKey], nextSource[nextKey]);
1132 }
1133 } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
1134 to[nextKey] = {};
1135
1136 if (nextSource[nextKey].__swiper__) {
1137 to[nextKey] = nextSource[nextKey];
1138 } else {
1139 extend(to[nextKey], nextSource[nextKey]);
1140 }
1141 } else {
1142 to[nextKey] = nextSource[nextKey];
1143 }
1144 }
1145 }
1146 }
1147 }
1148
1149 return to;
1150 }
1151
1152 function setCSSProperty(el, varName, varValue) {
1153 el.style.setProperty(varName, varValue);
1154 }
1155
1156 function animateCSSModeScroll({
1157 swiper,
1158 targetPosition,
1159 side
1160 }) {
1161 const window = getWindow();
1162 const startPosition = -swiper.translate;
1163 let startTime = null;
1164 let time;
1165 const duration = swiper.params.speed;
1166 swiper.wrapperEl.style.scrollSnapType = 'none';
1167 window.cancelAnimationFrame(swiper.cssModeFrameID);
1168 const dir = targetPosition > startPosition ? 'next' : 'prev';
1169
1170 const isOutOfBound = (current, target) => {
1171 return dir === 'next' && current >= target || dir === 'prev' && current <= target;
1172 };
1173
1174 const animate = () => {
1175 time = new Date().getTime();
1176
1177 if (startTime === null) {
1178 startTime = time;
1179 }
1180
1181 const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
1182 const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;
1183 let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);
1184
1185 if (isOutOfBound(currentPosition, targetPosition)) {
1186 currentPosition = targetPosition;
1187 }
1188
1189 swiper.wrapperEl.scrollTo({
1190 [side]: currentPosition
1191 });
1192
1193 if (isOutOfBound(currentPosition, targetPosition)) {
1194 swiper.wrapperEl.style.overflow = 'hidden';
1195 swiper.wrapperEl.style.scrollSnapType = '';
1196 setTimeout(() => {
1197 swiper.wrapperEl.style.overflow = '';
1198 swiper.wrapperEl.scrollTo({
1199 [side]: currentPosition
1200 });
1201 });
1202 window.cancelAnimationFrame(swiper.cssModeFrameID);
1203 return;
1204 }
1205
1206 swiper.cssModeFrameID = window.requestAnimationFrame(animate);
1207 };
1208
1209 animate();
1210 }
1211
1212 let support;
1213
1214 function calcSupport() {
1215 const window = getWindow();
1216 const document = getDocument();
1217 return {
1218 smoothScroll: document.documentElement && 'scrollBehavior' in document.documentElement.style,
1219 touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch),
1220 passiveListener: function checkPassiveListener() {
1221 let supportsPassive = false;
1222
1223 try {
1224 const opts = Object.defineProperty({}, 'passive', {
1225 // eslint-disable-next-line
1226 get() {
1227 supportsPassive = true;
1228 }
1229
1230 });
1231 window.addEventListener('testPassiveListener', null, opts);
1232 } catch (e) {// No support
1233 }
1234
1235 return supportsPassive;
1236 }(),
1237 gestures: function checkGestures() {
1238 return 'ongesturestart' in window;
1239 }()
1240 };
1241 }
1242
1243 function getSupport() {
1244 if (!support) {
1245 support = calcSupport();
1246 }
1247
1248 return support;
1249 }
1250
1251 let deviceCached;
1252
1253 function calcDevice({
1254 userAgent
1255 } = {}) {
1256 const support = getSupport();
1257 const window = getWindow();
1258 const platform = window.navigator.platform;
1259 const ua = userAgent || window.navigator.userAgent;
1260 const device = {
1261 ios: false,
1262 android: false
1263 };
1264 const screenWidth = window.screen.width;
1265 const screenHeight = window.screen.height;
1266 const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
1267
1268 let ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
1269 const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
1270 const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
1271 const windows = platform === 'Win32';
1272 let macos = platform === 'MacIntel'; // iPadOs 13 fix
1273
1274 const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810'];
1275
1276 if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) {
1277 ipad = ua.match(/(Version)\/([\d.]+)/);
1278 if (!ipad) ipad = [0, 1, '13_0_0'];
1279 macos = false;
1280 } // Android
1281
1282
1283 if (android && !windows) {
1284 device.os = 'android';
1285 device.android = true;
1286 }
1287
1288 if (ipad || iphone || ipod) {
1289 device.os = 'ios';
1290 device.ios = true;
1291 } // Export object
1292
1293
1294 return device;
1295 }
1296
1297 function getDevice(overrides = {}) {
1298 if (!deviceCached) {
1299 deviceCached = calcDevice(overrides);
1300 }
1301
1302 return deviceCached;
1303 }
1304
1305 let browser;
1306
1307 function calcBrowser() {
1308 const window = getWindow();
1309
1310 function isSafari() {
1311 const ua = window.navigator.userAgent.toLowerCase();
1312 return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0;
1313 }
1314
1315 return {
1316 isSafari: isSafari(),
1317 isWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent)
1318 };
1319 }
1320
1321 function getBrowser() {
1322 if (!browser) {
1323 browser = calcBrowser();
1324 }
1325
1326 return browser;
1327 }
1328
1329 function Resize({
1330 swiper,
1331 on,
1332 emit
1333 }) {
1334 const window = getWindow();
1335 let observer = null;
1336
1337 const resizeHandler = () => {
1338 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1339 emit('beforeResize');
1340 emit('resize');
1341 };
1342
1343 const createObserver = () => {
1344 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1345 observer = new ResizeObserver(entries => {
1346 const {
1347 width,
1348 height
1349 } = swiper;
1350 let newWidth = width;
1351 let newHeight = height;
1352 entries.forEach(({
1353 contentBoxSize,
1354 contentRect,
1355 target
1356 }) => {
1357 if (target && target !== swiper.el) return;
1358 newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize;
1359 newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize;
1360 });
1361
1362 if (newWidth !== width || newHeight !== height) {
1363 resizeHandler();
1364 }
1365 });
1366 observer.observe(swiper.el);
1367 };
1368
1369 const removeObserver = () => {
1370 if (observer && observer.unobserve && swiper.el) {
1371 observer.unobserve(swiper.el);
1372 observer = null;
1373 }
1374 };
1375
1376 const orientationChangeHandler = () => {
1377 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1378 emit('orientationchange');
1379 };
1380
1381 on('init', () => {
1382 if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') {
1383 createObserver();
1384 return;
1385 }
1386
1387 window.addEventListener('resize', resizeHandler);
1388 window.addEventListener('orientationchange', orientationChangeHandler);
1389 });
1390 on('destroy', () => {
1391 removeObserver();
1392 window.removeEventListener('resize', resizeHandler);
1393 window.removeEventListener('orientationchange', orientationChangeHandler);
1394 });
1395 }
1396
1397 function Observer({
1398 swiper,
1399 extendParams,
1400 on,
1401 emit
1402 }) {
1403 const observers = [];
1404 const window = getWindow();
1405
1406 const attach = (target, options = {}) => {
1407 const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
1408 const observer = new ObserverFunc(mutations => {
1409 // The observerUpdate event should only be triggered
1410 // once despite the number of mutations. Additional
1411 // triggers are redundant and are very costly
1412 if (mutations.length === 1) {
1413 emit('observerUpdate', mutations[0]);
1414 return;
1415 }
1416
1417 const observerUpdate = function observerUpdate() {
1418 emit('observerUpdate', mutations[0]);
1419 };
1420
1421 if (window.requestAnimationFrame) {
1422 window.requestAnimationFrame(observerUpdate);
1423 } else {
1424 window.setTimeout(observerUpdate, 0);
1425 }
1426 });
1427 observer.observe(target, {
1428 attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
1429 childList: typeof options.childList === 'undefined' ? true : options.childList,
1430 characterData: typeof options.characterData === 'undefined' ? true : options.characterData
1431 });
1432 observers.push(observer);
1433 };
1434
1435 const init = () => {
1436 if (!swiper.params.observer) return;
1437
1438 if (swiper.params.observeParents) {
1439 const containerParents = swiper.$el.parents();
1440
1441 for (let i = 0; i < containerParents.length; i += 1) {
1442 attach(containerParents[i]);
1443 }
1444 } // Observe container
1445
1446
1447 attach(swiper.$el[0], {
1448 childList: swiper.params.observeSlideChildren
1449 }); // Observe wrapper
1450
1451 attach(swiper.$wrapperEl[0], {
1452 attributes: false
1453 });
1454 };
1455
1456 const destroy = () => {
1457 observers.forEach(observer => {
1458 observer.disconnect();
1459 });
1460 observers.splice(0, observers.length);
1461 };
1462
1463 extendParams({
1464 observer: false,
1465 observeParents: false,
1466 observeSlideChildren: false
1467 });
1468 on('init', init);
1469 on('destroy', destroy);
1470 }
1471
1472 /* eslint-disable no-underscore-dangle */
1473 var eventsEmitter = {
1474 on(events, handler, priority) {
1475 const self = this;
1476 if (typeof handler !== 'function') return self;
1477 const method = priority ? 'unshift' : 'push';
1478 events.split(' ').forEach(event => {
1479 if (!self.eventsListeners[event]) self.eventsListeners[event] = [];
1480 self.eventsListeners[event][method](handler);
1481 });
1482 return self;
1483 },
1484
1485 once(events, handler, priority) {
1486 const self = this;
1487 if (typeof handler !== 'function') return self;
1488
1489 function onceHandler(...args) {
1490 self.off(events, onceHandler);
1491
1492 if (onceHandler.__emitterProxy) {
1493 delete onceHandler.__emitterProxy;
1494 }
1495
1496 handler.apply(self, args);
1497 }
1498
1499 onceHandler.__emitterProxy = handler;
1500 return self.on(events, onceHandler, priority);
1501 },
1502
1503 onAny(handler, priority) {
1504 const self = this;
1505 if (typeof handler !== 'function') return self;
1506 const method = priority ? 'unshift' : 'push';
1507
1508 if (self.eventsAnyListeners.indexOf(handler) < 0) {
1509 self.eventsAnyListeners[method](handler);
1510 }
1511
1512 return self;
1513 },
1514
1515 offAny(handler) {
1516 const self = this;
1517 if (!self.eventsAnyListeners) return self;
1518 const index = self.eventsAnyListeners.indexOf(handler);
1519
1520 if (index >= 0) {
1521 self.eventsAnyListeners.splice(index, 1);
1522 }
1523
1524 return self;
1525 },
1526
1527 off(events, handler) {
1528 const self = this;
1529 if (!self.eventsListeners) return self;
1530 events.split(' ').forEach(event => {
1531 if (typeof handler === 'undefined') {
1532 self.eventsListeners[event] = [];
1533 } else if (self.eventsListeners[event]) {
1534 self.eventsListeners[event].forEach((eventHandler, index) => {
1535 if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) {
1536 self.eventsListeners[event].splice(index, 1);
1537 }
1538 });
1539 }
1540 });
1541 return self;
1542 },
1543
1544 emit(...args) {
1545 const self = this;
1546 if (!self.eventsListeners) return self;
1547 let events;
1548 let data;
1549 let context;
1550
1551 if (typeof args[0] === 'string' || Array.isArray(args[0])) {
1552 events = args[0];
1553 data = args.slice(1, args.length);
1554 context = self;
1555 } else {
1556 events = args[0].events;
1557 data = args[0].data;
1558 context = args[0].context || self;
1559 }
1560
1561 data.unshift(context);
1562 const eventsArray = Array.isArray(events) ? events : events.split(' ');
1563 eventsArray.forEach(event => {
1564 if (self.eventsAnyListeners && self.eventsAnyListeners.length) {
1565 self.eventsAnyListeners.forEach(eventHandler => {
1566 eventHandler.apply(context, [event, ...data]);
1567 });
1568 }
1569
1570 if (self.eventsListeners && self.eventsListeners[event]) {
1571 self.eventsListeners[event].forEach(eventHandler => {
1572 eventHandler.apply(context, data);
1573 });
1574 }
1575 });
1576 return self;
1577 }
1578
1579 };
1580
1581 function updateSize() {
1582 const swiper = this;
1583 let width;
1584 let height;
1585 const $el = swiper.$el;
1586
1587 if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) {
1588 width = swiper.params.width;
1589 } else {
1590 width = $el[0].clientWidth;
1591 }
1592
1593 if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) {
1594 height = swiper.params.height;
1595 } else {
1596 height = $el[0].clientHeight;
1597 }
1598
1599 if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) {
1600 return;
1601 } // Subtract paddings
1602
1603
1604 width = width - parseInt($el.css('padding-left') || 0, 10) - parseInt($el.css('padding-right') || 0, 10);
1605 height = height - parseInt($el.css('padding-top') || 0, 10) - parseInt($el.css('padding-bottom') || 0, 10);
1606 if (Number.isNaN(width)) width = 0;
1607 if (Number.isNaN(height)) height = 0;
1608 Object.assign(swiper, {
1609 width,
1610 height,
1611 size: swiper.isHorizontal() ? width : height
1612 });
1613 }
1614
1615 function updateSlides() {
1616 const swiper = this;
1617
1618 function getDirectionLabel(property) {
1619 if (swiper.isHorizontal()) {
1620 return property;
1621 } // prettier-ignore
1622
1623
1624 return {
1625 'width': 'height',
1626 'margin-top': 'margin-left',
1627 'margin-bottom ': 'margin-right',
1628 'margin-left': 'margin-top',
1629 'margin-right': 'margin-bottom',
1630 'padding-left': 'padding-top',
1631 'padding-right': 'padding-bottom',
1632 'marginRight': 'marginBottom'
1633 }[property];
1634 }
1635
1636 function getDirectionPropertyValue(node, label) {
1637 return parseFloat(node.getPropertyValue(getDirectionLabel(label)) || 0);
1638 }
1639
1640 const params = swiper.params;
1641 const {
1642 $wrapperEl,
1643 size: swiperSize,
1644 rtlTranslate: rtl,
1645 wrongRTL
1646 } = swiper;
1647 const isVirtual = swiper.virtual && params.virtual.enabled;
1648 const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
1649 const slides = $wrapperEl.children(`.${swiper.params.slideClass}`);
1650 const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
1651 let snapGrid = [];
1652 const slidesGrid = [];
1653 const slidesSizesGrid = [];
1654 let offsetBefore = params.slidesOffsetBefore;
1655
1656 if (typeof offsetBefore === 'function') {
1657 offsetBefore = params.slidesOffsetBefore.call(swiper);
1658 }
1659
1660 let offsetAfter = params.slidesOffsetAfter;
1661
1662 if (typeof offsetAfter === 'function') {
1663 offsetAfter = params.slidesOffsetAfter.call(swiper);
1664 }
1665
1666 const previousSnapGridLength = swiper.snapGrid.length;
1667 const previousSlidesGridLength = swiper.slidesGrid.length;
1668 let spaceBetween = params.spaceBetween;
1669 let slidePosition = -offsetBefore;
1670 let prevSlideSize = 0;
1671 let index = 0;
1672
1673 if (typeof swiperSize === 'undefined') {
1674 return;
1675 }
1676
1677 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
1678 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;
1679 }
1680
1681 swiper.virtualSize = -spaceBetween; // reset margins
1682
1683 if (rtl) slides.css({
1684 marginLeft: '',
1685 marginBottom: '',
1686 marginTop: ''
1687 });else slides.css({
1688 marginRight: '',
1689 marginBottom: '',
1690 marginTop: ''
1691 }); // reset cssMode offsets
1692
1693 if (params.centeredSlides && params.cssMode) {
1694 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', '');
1695 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', '');
1696 }
1697
1698 const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;
1699
1700 if (gridEnabled) {
1701 swiper.grid.initSlides(slidesLength);
1702 } // Calc slides
1703
1704
1705 let slideSize;
1706 const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {
1707 return typeof params.breakpoints[key].slidesPerView !== 'undefined';
1708 }).length > 0;
1709
1710 for (let i = 0; i < slidesLength; i += 1) {
1711 slideSize = 0;
1712 const slide = slides.eq(i);
1713
1714 if (gridEnabled) {
1715 swiper.grid.updateSlide(i, slide, slidesLength, getDirectionLabel);
1716 }
1717
1718 if (slide.css('display') === 'none') continue; // eslint-disable-line
1719
1720 if (params.slidesPerView === 'auto') {
1721 if (shouldResetSlideSize) {
1722 slides[i].style[getDirectionLabel('width')] = ``;
1723 }
1724
1725 const slideStyles = getComputedStyle(slide[0]);
1726 const currentTransform = slide[0].style.transform;
1727 const currentWebKitTransform = slide[0].style.webkitTransform;
1728
1729 if (currentTransform) {
1730 slide[0].style.transform = 'none';
1731 }
1732
1733 if (currentWebKitTransform) {
1734 slide[0].style.webkitTransform = 'none';
1735 }
1736
1737 if (params.roundLengths) {
1738 slideSize = swiper.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);
1739 } else {
1740 // eslint-disable-next-line
1741 const width = getDirectionPropertyValue(slideStyles, 'width');
1742 const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');
1743 const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
1744 const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
1745 const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
1746 const boxSizing = slideStyles.getPropertyValue('box-sizing');
1747
1748 if (boxSizing && boxSizing === 'border-box') {
1749 slideSize = width + marginLeft + marginRight;
1750 } else {
1751 const {
1752 clientWidth,
1753 offsetWidth
1754 } = slide[0];
1755 slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
1756 }
1757 }
1758
1759 if (currentTransform) {
1760 slide[0].style.transform = currentTransform;
1761 }
1762
1763 if (currentWebKitTransform) {
1764 slide[0].style.webkitTransform = currentWebKitTransform;
1765 }
1766
1767 if (params.roundLengths) slideSize = Math.floor(slideSize);
1768 } else {
1769 slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;
1770 if (params.roundLengths) slideSize = Math.floor(slideSize);
1771
1772 if (slides[i]) {
1773 slides[i].style[getDirectionLabel('width')] = `${slideSize}px`;
1774 }
1775 }
1776
1777 if (slides[i]) {
1778 slides[i].swiperSlideSize = slideSize;
1779 }
1780
1781 slidesSizesGrid.push(slideSize);
1782
1783 if (params.centeredSlides) {
1784 slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
1785 if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1786 if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1787 if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
1788 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1789 if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1790 slidesGrid.push(slidePosition);
1791 } else {
1792 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1793 if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1794 slidesGrid.push(slidePosition);
1795 slidePosition = slidePosition + slideSize + spaceBetween;
1796 }
1797
1798 swiper.virtualSize += slideSize + spaceBetween;
1799 prevSlideSize = slideSize;
1800 index += 1;
1801 }
1802
1803 swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
1804
1805 if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
1806 $wrapperEl.css({
1807 width: `${swiper.virtualSize + params.spaceBetween}px`
1808 });
1809 }
1810
1811 if (params.setWrapperSize) {
1812 $wrapperEl.css({
1813 [getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`
1814 });
1815 }
1816
1817 if (gridEnabled) {
1818 swiper.grid.updateWrapperSize(slideSize, snapGrid, getDirectionLabel);
1819 } // Remove last grid elements depending on width
1820
1821
1822 if (!params.centeredSlides) {
1823 const newSlidesGrid = [];
1824
1825 for (let i = 0; i < snapGrid.length; i += 1) {
1826 let slidesGridItem = snapGrid[i];
1827 if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
1828
1829 if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
1830 newSlidesGrid.push(slidesGridItem);
1831 }
1832 }
1833
1834 snapGrid = newSlidesGrid;
1835
1836 if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
1837 snapGrid.push(swiper.virtualSize - swiperSize);
1838 }
1839 }
1840
1841 if (snapGrid.length === 0) snapGrid = [0];
1842
1843 if (params.spaceBetween !== 0) {
1844 const key = swiper.isHorizontal() && rtl ? 'marginLeft' : getDirectionLabel('marginRight');
1845 slides.filter((_, slideIndex) => {
1846 if (!params.cssMode) return true;
1847
1848 if (slideIndex === slides.length - 1) {
1849 return false;
1850 }
1851
1852 return true;
1853 }).css({
1854 [key]: `${spaceBetween}px`
1855 });
1856 }
1857
1858 if (params.centeredSlides && params.centeredSlidesBounds) {
1859 let allSlidesSize = 0;
1860 slidesSizesGrid.forEach(slideSizeValue => {
1861 allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
1862 });
1863 allSlidesSize -= params.spaceBetween;
1864 const maxSnap = allSlidesSize - swiperSize;
1865 snapGrid = snapGrid.map(snap => {
1866 if (snap < 0) return -offsetBefore;
1867 if (snap > maxSnap) return maxSnap + offsetAfter;
1868 return snap;
1869 });
1870 }
1871
1872 if (params.centerInsufficientSlides) {
1873 let allSlidesSize = 0;
1874 slidesSizesGrid.forEach(slideSizeValue => {
1875 allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
1876 });
1877 allSlidesSize -= params.spaceBetween;
1878
1879 if (allSlidesSize < swiperSize) {
1880 const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
1881 snapGrid.forEach((snap, snapIndex) => {
1882 snapGrid[snapIndex] = snap - allSlidesOffset;
1883 });
1884 slidesGrid.forEach((snap, snapIndex) => {
1885 slidesGrid[snapIndex] = snap + allSlidesOffset;
1886 });
1887 }
1888 }
1889
1890 Object.assign(swiper, {
1891 slides,
1892 snapGrid,
1893 slidesGrid,
1894 slidesSizesGrid
1895 });
1896
1897 if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) {
1898 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`);
1899 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`);
1900 const addToSnapGrid = -swiper.snapGrid[0];
1901 const addToSlidesGrid = -swiper.slidesGrid[0];
1902 swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);
1903 swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);
1904 }
1905
1906 if (slidesLength !== previousSlidesLength) {
1907 swiper.emit('slidesLengthChange');
1908 }
1909
1910 if (snapGrid.length !== previousSnapGridLength) {
1911 if (swiper.params.watchOverflow) swiper.checkOverflow();
1912 swiper.emit('snapGridLengthChange');
1913 }
1914
1915 if (slidesGrid.length !== previousSlidesGridLength) {
1916 swiper.emit('slidesGridLengthChange');
1917 }
1918
1919 if (params.watchSlidesProgress) {
1920 swiper.updateSlidesOffset();
1921 }
1922 }
1923
1924 function updateAutoHeight(speed) {
1925 const swiper = this;
1926 const activeSlides = [];
1927 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
1928 let newHeight = 0;
1929 let i;
1930
1931 if (typeof speed === 'number') {
1932 swiper.setTransition(speed);
1933 } else if (speed === true) {
1934 swiper.setTransition(swiper.params.speed);
1935 }
1936
1937 const getSlideByIndex = index => {
1938 if (isVirtual) {
1939 return swiper.slides.filter(el => parseInt(el.getAttribute('data-swiper-slide-index'), 10) === index)[0];
1940 }
1941
1942 return swiper.slides.eq(index)[0];
1943 }; // Find slides currently in view
1944
1945
1946 if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
1947 if (swiper.params.centeredSlides) {
1948 swiper.visibleSlides.each(slide => {
1949 activeSlides.push(slide);
1950 });
1951 } else {
1952 for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
1953 const index = swiper.activeIndex + i;
1954 if (index > swiper.slides.length && !isVirtual) break;
1955 activeSlides.push(getSlideByIndex(index));
1956 }
1957 }
1958 } else {
1959 activeSlides.push(getSlideByIndex(swiper.activeIndex));
1960 } // Find new height from highest slide in view
1961
1962
1963 for (i = 0; i < activeSlides.length; i += 1) {
1964 if (typeof activeSlides[i] !== 'undefined') {
1965 const height = activeSlides[i].offsetHeight;
1966 newHeight = height > newHeight ? height : newHeight;
1967 }
1968 } // Update Height
1969
1970
1971 if (newHeight) swiper.$wrapperEl.css('height', `${newHeight}px`);
1972 }
1973
1974 function updateSlidesOffset() {
1975 const swiper = this;
1976 const slides = swiper.slides;
1977
1978 for (let i = 0; i < slides.length; i += 1) {
1979 slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;
1980 }
1981 }
1982
1983 function updateSlidesProgress(translate = this && this.translate || 0) {
1984 const swiper = this;
1985 const params = swiper.params;
1986 const {
1987 slides,
1988 rtlTranslate: rtl
1989 } = swiper;
1990 if (slides.length === 0) return;
1991 if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
1992 let offsetCenter = -translate;
1993 if (rtl) offsetCenter = translate; // Visible Slides
1994
1995 slides.removeClass(params.slideVisibleClass);
1996 swiper.visibleSlidesIndexes = [];
1997 swiper.visibleSlides = [];
1998
1999 for (let i = 0; i < slides.length; i += 1) {
2000 const slide = slides[i];
2001 let slideOffset = slide.swiperSlideOffset;
2002
2003 if (params.cssMode && params.centeredSlides) {
2004 slideOffset -= slides[0].swiperSlideOffset;
2005 }
2006
2007 const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + params.spaceBetween);
2008 const slideBefore = -(offsetCenter - slideOffset);
2009 const slideAfter = slideBefore + swiper.slidesSizesGrid[i];
2010 const isVisible = slideBefore >= 0 && slideBefore < swiper.size - 1 || slideAfter > 1 && slideAfter <= swiper.size || slideBefore <= 0 && slideAfter >= swiper.size;
2011
2012 if (isVisible) {
2013 swiper.visibleSlides.push(slide);
2014 swiper.visibleSlidesIndexes.push(i);
2015 slides.eq(i).addClass(params.slideVisibleClass);
2016 }
2017
2018 slide.progress = rtl ? -slideProgress : slideProgress;
2019 }
2020
2021 swiper.visibleSlides = $(swiper.visibleSlides);
2022 }
2023
2024 function updateProgress(translate) {
2025 const swiper = this;
2026
2027 if (typeof translate === 'undefined') {
2028 const multiplier = swiper.rtlTranslate ? -1 : 1; // eslint-disable-next-line
2029
2030 translate = swiper && swiper.translate && swiper.translate * multiplier || 0;
2031 }
2032
2033 const params = swiper.params;
2034 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
2035 let {
2036 progress,
2037 isBeginning,
2038 isEnd
2039 } = swiper;
2040 const wasBeginning = isBeginning;
2041 const wasEnd = isEnd;
2042
2043 if (translatesDiff === 0) {
2044 progress = 0;
2045 isBeginning = true;
2046 isEnd = true;
2047 } else {
2048 progress = (translate - swiper.minTranslate()) / translatesDiff;
2049 isBeginning = progress <= 0;
2050 isEnd = progress >= 1;
2051 }
2052
2053 Object.assign(swiper, {
2054 progress,
2055 isBeginning,
2056 isEnd
2057 });
2058 if (params.watchSlidesProgress || params.centeredSlides && params.autoHeight) swiper.updateSlidesProgress(translate);
2059
2060 if (isBeginning && !wasBeginning) {
2061 swiper.emit('reachBeginning toEdge');
2062 }
2063
2064 if (isEnd && !wasEnd) {
2065 swiper.emit('reachEnd toEdge');
2066 }
2067
2068 if (wasBeginning && !isBeginning || wasEnd && !isEnd) {
2069 swiper.emit('fromEdge');
2070 }
2071
2072 swiper.emit('progress', progress);
2073 }
2074
2075 function updateSlidesClasses() {
2076 const swiper = this;
2077 const {
2078 slides,
2079 params,
2080 $wrapperEl,
2081 activeIndex,
2082 realIndex
2083 } = swiper;
2084 const isVirtual = swiper.virtual && params.virtual.enabled;
2085 slides.removeClass(`${params.slideActiveClass} ${params.slideNextClass} ${params.slidePrevClass} ${params.slideDuplicateActiveClass} ${params.slideDuplicateNextClass} ${params.slideDuplicatePrevClass}`);
2086 let activeSlide;
2087
2088 if (isVirtual) {
2089 activeSlide = swiper.$wrapperEl.find(`.${params.slideClass}[data-swiper-slide-index="${activeIndex}"]`);
2090 } else {
2091 activeSlide = slides.eq(activeIndex);
2092 } // Active classes
2093
2094
2095 activeSlide.addClass(params.slideActiveClass);
2096
2097 if (params.loop) {
2098 // Duplicate to all looped slides
2099 if (activeSlide.hasClass(params.slideDuplicateClass)) {
2100 $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${realIndex}"]`).addClass(params.slideDuplicateActiveClass);
2101 } else {
2102 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${realIndex}"]`).addClass(params.slideDuplicateActiveClass);
2103 }
2104 } // Next Slide
2105
2106
2107 let nextSlide = activeSlide.nextAll(`.${params.slideClass}`).eq(0).addClass(params.slideNextClass);
2108
2109 if (params.loop && nextSlide.length === 0) {
2110 nextSlide = slides.eq(0);
2111 nextSlide.addClass(params.slideNextClass);
2112 } // Prev Slide
2113
2114
2115 let prevSlide = activeSlide.prevAll(`.${params.slideClass}`).eq(0).addClass(params.slidePrevClass);
2116
2117 if (params.loop && prevSlide.length === 0) {
2118 prevSlide = slides.eq(-1);
2119 prevSlide.addClass(params.slidePrevClass);
2120 }
2121
2122 if (params.loop) {
2123 // Duplicate to all looped slides
2124 if (nextSlide.hasClass(params.slideDuplicateClass)) {
2125 $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${nextSlide.attr('data-swiper-slide-index')}"]`).addClass(params.slideDuplicateNextClass);
2126 } else {
2127 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${nextSlide.attr('data-swiper-slide-index')}"]`).addClass(params.slideDuplicateNextClass);
2128 }
2129
2130 if (prevSlide.hasClass(params.slideDuplicateClass)) {
2131 $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${prevSlide.attr('data-swiper-slide-index')}"]`).addClass(params.slideDuplicatePrevClass);
2132 } else {
2133 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${prevSlide.attr('data-swiper-slide-index')}"]`).addClass(params.slideDuplicatePrevClass);
2134 }
2135 }
2136
2137 swiper.emitSlidesClasses();
2138 }
2139
2140 function updateActiveIndex(newActiveIndex) {
2141 const swiper = this;
2142 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
2143 const {
2144 slidesGrid,
2145 snapGrid,
2146 params,
2147 activeIndex: previousIndex,
2148 realIndex: previousRealIndex,
2149 snapIndex: previousSnapIndex
2150 } = swiper;
2151 let activeIndex = newActiveIndex;
2152 let snapIndex;
2153
2154 if (typeof activeIndex === 'undefined') {
2155 for (let i = 0; i < slidesGrid.length; i += 1) {
2156 if (typeof slidesGrid[i + 1] !== 'undefined') {
2157 if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) {
2158 activeIndex = i;
2159 } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {
2160 activeIndex = i + 1;
2161 }
2162 } else if (translate >= slidesGrid[i]) {
2163 activeIndex = i;
2164 }
2165 } // Normalize slideIndex
2166
2167
2168 if (params.normalizeSlideIndex) {
2169 if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;
2170 }
2171 }
2172
2173 if (snapGrid.indexOf(translate) >= 0) {
2174 snapIndex = snapGrid.indexOf(translate);
2175 } else {
2176 const skip = Math.min(params.slidesPerGroupSkip, activeIndex);
2177 snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup);
2178 }
2179
2180 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
2181
2182 if (activeIndex === previousIndex) {
2183 if (snapIndex !== previousSnapIndex) {
2184 swiper.snapIndex = snapIndex;
2185 swiper.emit('snapIndexChange');
2186 }
2187
2188 return;
2189 } // Get real index
2190
2191
2192 const realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);
2193 Object.assign(swiper, {
2194 snapIndex,
2195 realIndex,
2196 previousIndex,
2197 activeIndex
2198 });
2199 swiper.emit('activeIndexChange');
2200 swiper.emit('snapIndexChange');
2201
2202 if (previousRealIndex !== realIndex) {
2203 swiper.emit('realIndexChange');
2204 }
2205
2206 if (swiper.initialized || swiper.params.runCallbacksOnInit) {
2207 swiper.emit('slideChange');
2208 }
2209 }
2210
2211 function updateClickedSlide(e) {
2212 const swiper = this;
2213 const params = swiper.params;
2214 const slide = $(e.target).closest(`.${params.slideClass}`)[0];
2215 let slideFound = false;
2216 let slideIndex;
2217
2218 if (slide) {
2219 for (let i = 0; i < swiper.slides.length; i += 1) {
2220 if (swiper.slides[i] === slide) {
2221 slideFound = true;
2222 slideIndex = i;
2223 break;
2224 }
2225 }
2226 }
2227
2228 if (slide && slideFound) {
2229 swiper.clickedSlide = slide;
2230
2231 if (swiper.virtual && swiper.params.virtual.enabled) {
2232 swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);
2233 } else {
2234 swiper.clickedIndex = slideIndex;
2235 }
2236 } else {
2237 swiper.clickedSlide = undefined;
2238 swiper.clickedIndex = undefined;
2239 return;
2240 }
2241
2242 if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {
2243 swiper.slideToClickedSlide();
2244 }
2245 }
2246
2247 var update = {
2248 updateSize,
2249 updateSlides,
2250 updateAutoHeight,
2251 updateSlidesOffset,
2252 updateSlidesProgress,
2253 updateProgress,
2254 updateSlidesClasses,
2255 updateActiveIndex,
2256 updateClickedSlide
2257 };
2258
2259 function getSwiperTranslate(axis = this.isHorizontal() ? 'x' : 'y') {
2260 const swiper = this;
2261 const {
2262 params,
2263 rtlTranslate: rtl,
2264 translate,
2265 $wrapperEl
2266 } = swiper;
2267
2268 if (params.virtualTranslate) {
2269 return rtl ? -translate : translate;
2270 }
2271
2272 if (params.cssMode) {
2273 return translate;
2274 }
2275
2276 let currentTranslate = getTranslate($wrapperEl[0], axis);
2277 if (rtl) currentTranslate = -currentTranslate;
2278 return currentTranslate || 0;
2279 }
2280
2281 function setTranslate(translate, byController) {
2282 const swiper = this;
2283 const {
2284 rtlTranslate: rtl,
2285 params,
2286 $wrapperEl,
2287 wrapperEl,
2288 progress
2289 } = swiper;
2290 let x = 0;
2291 let y = 0;
2292 const z = 0;
2293
2294 if (swiper.isHorizontal()) {
2295 x = rtl ? -translate : translate;
2296 } else {
2297 y = translate;
2298 }
2299
2300 if (params.roundLengths) {
2301 x = Math.floor(x);
2302 y = Math.floor(y);
2303 }
2304
2305 if (params.cssMode) {
2306 wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
2307 } else if (!params.virtualTranslate) {
2308 $wrapperEl.transform(`translate3d(${x}px, ${y}px, ${z}px)`);
2309 }
2310
2311 swiper.previousTranslate = swiper.translate;
2312 swiper.translate = swiper.isHorizontal() ? x : y; // Check if we need to update progress
2313
2314 let newProgress;
2315 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
2316
2317 if (translatesDiff === 0) {
2318 newProgress = 0;
2319 } else {
2320 newProgress = (translate - swiper.minTranslate()) / translatesDiff;
2321 }
2322
2323 if (newProgress !== progress) {
2324 swiper.updateProgress(translate);
2325 }
2326
2327 swiper.emit('setTranslate', swiper.translate, byController);
2328 }
2329
2330 function minTranslate() {
2331 return -this.snapGrid[0];
2332 }
2333
2334 function maxTranslate() {
2335 return -this.snapGrid[this.snapGrid.length - 1];
2336 }
2337
2338 function translateTo(translate = 0, speed = this.params.speed, runCallbacks = true, translateBounds = true, internal) {
2339 const swiper = this;
2340 const {
2341 params,
2342 wrapperEl
2343 } = swiper;
2344
2345 if (swiper.animating && params.preventInteractionOnTransition) {
2346 return false;
2347 }
2348
2349 const minTranslate = swiper.minTranslate();
2350 const maxTranslate = swiper.maxTranslate();
2351 let newTranslate;
2352 if (translateBounds && translate > minTranslate) newTranslate = minTranslate;else if (translateBounds && translate < maxTranslate) newTranslate = maxTranslate;else newTranslate = translate; // Update progress
2353
2354 swiper.updateProgress(newTranslate);
2355
2356 if (params.cssMode) {
2357 const isH = swiper.isHorizontal();
2358
2359 if (speed === 0) {
2360 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;
2361 } else {
2362 if (!swiper.support.smoothScroll) {
2363 animateCSSModeScroll({
2364 swiper,
2365 targetPosition: -newTranslate,
2366 side: isH ? 'left' : 'top'
2367 });
2368 return true;
2369 }
2370
2371 wrapperEl.scrollTo({
2372 [isH ? 'left' : 'top']: -newTranslate,
2373 behavior: 'smooth'
2374 });
2375 }
2376
2377 return true;
2378 }
2379
2380 if (speed === 0) {
2381 swiper.setTransition(0);
2382 swiper.setTranslate(newTranslate);
2383
2384 if (runCallbacks) {
2385 swiper.emit('beforeTransitionStart', speed, internal);
2386 swiper.emit('transitionEnd');
2387 }
2388 } else {
2389 swiper.setTransition(speed);
2390 swiper.setTranslate(newTranslate);
2391
2392 if (runCallbacks) {
2393 swiper.emit('beforeTransitionStart', speed, internal);
2394 swiper.emit('transitionStart');
2395 }
2396
2397 if (!swiper.animating) {
2398 swiper.animating = true;
2399
2400 if (!swiper.onTranslateToWrapperTransitionEnd) {
2401 swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) {
2402 if (!swiper || swiper.destroyed) return;
2403 if (e.target !== this) return;
2404 swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
2405 swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);
2406 swiper.onTranslateToWrapperTransitionEnd = null;
2407 delete swiper.onTranslateToWrapperTransitionEnd;
2408
2409 if (runCallbacks) {
2410 swiper.emit('transitionEnd');
2411 }
2412 };
2413 }
2414
2415 swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
2416 swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);
2417 }
2418 }
2419
2420 return true;
2421 }
2422
2423 var translate = {
2424 getTranslate: getSwiperTranslate,
2425 setTranslate,
2426 minTranslate,
2427 maxTranslate,
2428 translateTo
2429 };
2430
2431 function setTransition(duration, byController) {
2432 const swiper = this;
2433
2434 if (!swiper.params.cssMode) {
2435 swiper.$wrapperEl.transition(duration);
2436 }
2437
2438 swiper.emit('setTransition', duration, byController);
2439 }
2440
2441 function transitionEmit({
2442 swiper,
2443 runCallbacks,
2444 direction,
2445 step
2446 }) {
2447 const {
2448 activeIndex,
2449 previousIndex
2450 } = swiper;
2451 let dir = direction;
2452
2453 if (!dir) {
2454 if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset';
2455 }
2456
2457 swiper.emit(`transition${step}`);
2458
2459 if (runCallbacks && activeIndex !== previousIndex) {
2460 if (dir === 'reset') {
2461 swiper.emit(`slideResetTransition${step}`);
2462 return;
2463 }
2464
2465 swiper.emit(`slideChangeTransition${step}`);
2466
2467 if (dir === 'next') {
2468 swiper.emit(`slideNextTransition${step}`);
2469 } else {
2470 swiper.emit(`slidePrevTransition${step}`);
2471 }
2472 }
2473 }
2474
2475 function transitionStart(runCallbacks = true, direction) {
2476 const swiper = this;
2477 const {
2478 params
2479 } = swiper;
2480 if (params.cssMode) return;
2481
2482 if (params.autoHeight) {
2483 swiper.updateAutoHeight();
2484 }
2485
2486 transitionEmit({
2487 swiper,
2488 runCallbacks,
2489 direction,
2490 step: 'Start'
2491 });
2492 }
2493
2494 function transitionEnd(runCallbacks = true, direction) {
2495 const swiper = this;
2496 const {
2497 params
2498 } = swiper;
2499 swiper.animating = false;
2500 if (params.cssMode) return;
2501 swiper.setTransition(0);
2502 transitionEmit({
2503 swiper,
2504 runCallbacks,
2505 direction,
2506 step: 'End'
2507 });
2508 }
2509
2510 var transition = {
2511 setTransition,
2512 transitionStart,
2513 transitionEnd
2514 };
2515
2516 function slideTo(index = 0, speed = this.params.speed, runCallbacks = true, internal, initial) {
2517 if (typeof index !== 'number' && typeof index !== 'string') {
2518 throw new Error(`The 'index' argument cannot have type other than 'number' or 'string'. [${typeof index}] given.`);
2519 }
2520
2521 if (typeof index === 'string') {
2522 /**
2523 * The `index` argument converted from `string` to `number`.
2524 * @type {number}
2525 */
2526 const indexAsNumber = parseInt(index, 10);
2527 /**
2528 * Determines whether the `index` argument is a valid `number`
2529 * after being converted from the `string` type.
2530 * @type {boolean}
2531 */
2532
2533 const isValidNumber = isFinite(indexAsNumber);
2534
2535 if (!isValidNumber) {
2536 throw new Error(`The passed-in 'index' (string) couldn't be converted to 'number'. [${index}] given.`);
2537 } // Knowing that the converted `index` is a valid number,
2538 // we can update the original argument's value.
2539
2540
2541 index = indexAsNumber;
2542 }
2543
2544 const swiper = this;
2545 let slideIndex = index;
2546 if (slideIndex < 0) slideIndex = 0;
2547 const {
2548 params,
2549 snapGrid,
2550 slidesGrid,
2551 previousIndex,
2552 activeIndex,
2553 rtlTranslate: rtl,
2554 wrapperEl,
2555 enabled
2556 } = swiper;
2557
2558 if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial) {
2559 return false;
2560 }
2561
2562 const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
2563 let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
2564 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
2565
2566 if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {
2567 swiper.emit('beforeSlideChangeStart');
2568 }
2569
2570 const translate = -snapGrid[snapIndex]; // Update progress
2571
2572 swiper.updateProgress(translate); // Normalize slideIndex
2573
2574 if (params.normalizeSlideIndex) {
2575 for (let i = 0; i < slidesGrid.length; i += 1) {
2576 const normalizedTranslate = -Math.floor(translate * 100);
2577 const normalizedGrid = Math.floor(slidesGrid[i] * 100);
2578 const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100);
2579
2580 if (typeof slidesGrid[i + 1] !== 'undefined') {
2581 if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) {
2582 slideIndex = i;
2583 } else if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext) {
2584 slideIndex = i + 1;
2585 }
2586 } else if (normalizedTranslate >= normalizedGrid) {
2587 slideIndex = i;
2588 }
2589 }
2590 } // Directions locks
2591
2592
2593 if (swiper.initialized && slideIndex !== activeIndex) {
2594 if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {
2595 return false;
2596 }
2597
2598 if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
2599 if ((activeIndex || 0) !== slideIndex) return false;
2600 }
2601 }
2602
2603 let direction;
2604 if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset'; // Update Index
2605
2606 if (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate) {
2607 swiper.updateActiveIndex(slideIndex); // Update Height
2608
2609 if (params.autoHeight) {
2610 swiper.updateAutoHeight();
2611 }
2612
2613 swiper.updateSlidesClasses();
2614
2615 if (params.effect !== 'slide') {
2616 swiper.setTranslate(translate);
2617 }
2618
2619 if (direction !== 'reset') {
2620 swiper.transitionStart(runCallbacks, direction);
2621 swiper.transitionEnd(runCallbacks, direction);
2622 }
2623
2624 return false;
2625 }
2626
2627 if (params.cssMode) {
2628 const isH = swiper.isHorizontal();
2629 const t = rtl ? translate : -translate;
2630
2631 if (speed === 0) {
2632 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
2633
2634 if (isVirtual) {
2635 swiper.wrapperEl.style.scrollSnapType = 'none';
2636 }
2637
2638 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
2639
2640 if (isVirtual) {
2641 requestAnimationFrame(() => {
2642 swiper.wrapperEl.style.scrollSnapType = '';
2643 });
2644 }
2645 } else {
2646 if (!swiper.support.smoothScroll) {
2647 animateCSSModeScroll({
2648 swiper,
2649 targetPosition: t,
2650 side: isH ? 'left' : 'top'
2651 });
2652 return true;
2653 }
2654
2655 wrapperEl.scrollTo({
2656 [isH ? 'left' : 'top']: t,
2657 behavior: 'smooth'
2658 });
2659 }
2660
2661 return true;
2662 }
2663
2664 if (speed === 0) {
2665 swiper.setTransition(0);
2666 swiper.setTranslate(translate);
2667 swiper.updateActiveIndex(slideIndex);
2668 swiper.updateSlidesClasses();
2669 swiper.emit('beforeTransitionStart', speed, internal);
2670 swiper.transitionStart(runCallbacks, direction);
2671 swiper.transitionEnd(runCallbacks, direction);
2672 } else {
2673 swiper.setTransition(speed);
2674 swiper.setTranslate(translate);
2675 swiper.updateActiveIndex(slideIndex);
2676 swiper.updateSlidesClasses();
2677 swiper.emit('beforeTransitionStart', speed, internal);
2678 swiper.transitionStart(runCallbacks, direction);
2679
2680 if (!swiper.animating) {
2681 swiper.animating = true;
2682
2683 if (!swiper.onSlideToWrapperTransitionEnd) {
2684 swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {
2685 if (!swiper || swiper.destroyed) return;
2686 if (e.target !== this) return;
2687 swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
2688 swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
2689 swiper.onSlideToWrapperTransitionEnd = null;
2690 delete swiper.onSlideToWrapperTransitionEnd;
2691 swiper.transitionEnd(runCallbacks, direction);
2692 };
2693 }
2694
2695 swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
2696 swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
2697 }
2698 }
2699
2700 return true;
2701 }
2702
2703 function slideToLoop(index = 0, speed = this.params.speed, runCallbacks = true, internal) {
2704 const swiper = this;
2705 let newIndex = index;
2706
2707 if (swiper.params.loop) {
2708 newIndex += swiper.loopedSlides;
2709 }
2710
2711 return swiper.slideTo(newIndex, speed, runCallbacks, internal);
2712 }
2713
2714 /* eslint no-unused-vars: "off" */
2715 function slideNext(speed = this.params.speed, runCallbacks = true, internal) {
2716 const swiper = this;
2717 const {
2718 animating,
2719 enabled,
2720 params
2721 } = swiper;
2722 if (!enabled) return swiper;
2723 let perGroup = params.slidesPerGroup;
2724
2725 if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
2726 perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
2727 }
2728
2729 const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;
2730
2731 if (params.loop) {
2732 if (animating && params.loopPreventsSlide) return false;
2733 swiper.loopFix(); // eslint-disable-next-line
2734
2735 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
2736 }
2737
2738 return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
2739 }
2740
2741 /* eslint no-unused-vars: "off" */
2742 function slidePrev(speed = this.params.speed, runCallbacks = true, internal) {
2743 const swiper = this;
2744 const {
2745 params,
2746 animating,
2747 snapGrid,
2748 slidesGrid,
2749 rtlTranslate,
2750 enabled
2751 } = swiper;
2752 if (!enabled) return swiper;
2753
2754 if (params.loop) {
2755 if (animating && params.loopPreventsSlide) return false;
2756 swiper.loopFix(); // eslint-disable-next-line
2757
2758 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
2759 }
2760
2761 const translate = rtlTranslate ? swiper.translate : -swiper.translate;
2762
2763 function normalize(val) {
2764 if (val < 0) return -Math.floor(Math.abs(val));
2765 return Math.floor(val);
2766 }
2767
2768 const normalizedTranslate = normalize(translate);
2769 const normalizedSnapGrid = snapGrid.map(val => normalize(val));
2770 let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
2771
2772 if (typeof prevSnap === 'undefined' && params.cssMode) {
2773 let prevSnapIndex;
2774 snapGrid.forEach((snap, snapIndex) => {
2775 if (normalizedTranslate >= snap) {
2776 // prevSnap = snap;
2777 prevSnapIndex = snapIndex;
2778 }
2779 });
2780
2781 if (typeof prevSnapIndex !== 'undefined') {
2782 prevSnap = snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
2783 }
2784 }
2785
2786 let prevIndex = 0;
2787
2788 if (typeof prevSnap !== 'undefined') {
2789 prevIndex = slidesGrid.indexOf(prevSnap);
2790 if (prevIndex < 0) prevIndex = swiper.activeIndex - 1;
2791
2792 if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
2793 prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1;
2794 prevIndex = Math.max(prevIndex, 0);
2795 }
2796 }
2797
2798 return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2799 }
2800
2801 /* eslint no-unused-vars: "off" */
2802 function slideReset(speed = this.params.speed, runCallbacks = true, internal) {
2803 const swiper = this;
2804 return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
2805 }
2806
2807 /* eslint no-unused-vars: "off" */
2808 function slideToClosest(speed = this.params.speed, runCallbacks = true, internal, threshold = 0.5) {
2809 const swiper = this;
2810 let index = swiper.activeIndex;
2811 const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
2812 const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
2813 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
2814
2815 if (translate >= swiper.snapGrid[snapIndex]) {
2816 // The current translate is on or after the current snap index, so the choice
2817 // is between the current index and the one after it.
2818 const currentSnap = swiper.snapGrid[snapIndex];
2819 const nextSnap = swiper.snapGrid[snapIndex + 1];
2820
2821 if (translate - currentSnap > (nextSnap - currentSnap) * threshold) {
2822 index += swiper.params.slidesPerGroup;
2823 }
2824 } else {
2825 // The current translate is before the current snap index, so the choice
2826 // is between the current index and the one before it.
2827 const prevSnap = swiper.snapGrid[snapIndex - 1];
2828 const currentSnap = swiper.snapGrid[snapIndex];
2829
2830 if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) {
2831 index -= swiper.params.slidesPerGroup;
2832 }
2833 }
2834
2835 index = Math.max(index, 0);
2836 index = Math.min(index, swiper.slidesGrid.length - 1);
2837 return swiper.slideTo(index, speed, runCallbacks, internal);
2838 }
2839
2840 function slideToClickedSlide() {
2841 const swiper = this;
2842 const {
2843 params,
2844 $wrapperEl
2845 } = swiper;
2846 const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
2847 let slideToIndex = swiper.clickedIndex;
2848 let realIndex;
2849
2850 if (params.loop) {
2851 if (swiper.animating) return;
2852 realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);
2853
2854 if (params.centeredSlides) {
2855 if (slideToIndex < swiper.loopedSlides - slidesPerView / 2 || slideToIndex > swiper.slides.length - swiper.loopedSlides + slidesPerView / 2) {
2856 swiper.loopFix();
2857 slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index="${realIndex}"]:not(.${params.slideDuplicateClass})`).eq(0).index();
2858 nextTick(() => {
2859 swiper.slideTo(slideToIndex);
2860 });
2861 } else {
2862 swiper.slideTo(slideToIndex);
2863 }
2864 } else if (slideToIndex > swiper.slides.length - slidesPerView) {
2865 swiper.loopFix();
2866 slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index="${realIndex}"]:not(.${params.slideDuplicateClass})`).eq(0).index();
2867 nextTick(() => {
2868 swiper.slideTo(slideToIndex);
2869 });
2870 } else {
2871 swiper.slideTo(slideToIndex);
2872 }
2873 } else {
2874 swiper.slideTo(slideToIndex);
2875 }
2876 }
2877
2878 var slide = {
2879 slideTo,
2880 slideToLoop,
2881 slideNext,
2882 slidePrev,
2883 slideReset,
2884 slideToClosest,
2885 slideToClickedSlide
2886 };
2887
2888 function loopCreate() {
2889 const swiper = this;
2890 const document = getDocument();
2891 const {
2892 params,
2893 $wrapperEl
2894 } = swiper; // Remove duplicated slides
2895
2896 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}`).remove();
2897 let slides = $wrapperEl.children(`.${params.slideClass}`);
2898
2899 if (params.loopFillGroupWithBlank) {
2900 const blankSlidesNum = params.slidesPerGroup - slides.length % params.slidesPerGroup;
2901
2902 if (blankSlidesNum !== params.slidesPerGroup) {
2903 for (let i = 0; i < blankSlidesNum; i += 1) {
2904 const blankNode = $(document.createElement('div')).addClass(`${params.slideClass} ${params.slideBlankClass}`);
2905 $wrapperEl.append(blankNode);
2906 }
2907
2908 slides = $wrapperEl.children(`.${params.slideClass}`);
2909 }
2910 }
2911
2912 if (params.slidesPerView === 'auto' && !params.loopedSlides) params.loopedSlides = slides.length;
2913 swiper.loopedSlides = Math.ceil(parseFloat(params.loopedSlides || params.slidesPerView, 10));
2914 swiper.loopedSlides += params.loopAdditionalSlides;
2915
2916 if (swiper.loopedSlides > slides.length) {
2917 swiper.loopedSlides = slides.length;
2918 }
2919
2920 const prependSlides = [];
2921 const appendSlides = [];
2922 slides.each((el, index) => {
2923 const slide = $(el);
2924
2925 if (index < swiper.loopedSlides) {
2926 appendSlides.push(el);
2927 }
2928
2929 if (index < slides.length && index >= slides.length - swiper.loopedSlides) {
2930 prependSlides.push(el);
2931 }
2932
2933 slide.attr('data-swiper-slide-index', index);
2934 });
2935
2936 for (let i = 0; i < appendSlides.length; i += 1) {
2937 $wrapperEl.append($(appendSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));
2938 }
2939
2940 for (let i = prependSlides.length - 1; i >= 0; i -= 1) {
2941 $wrapperEl.prepend($(prependSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));
2942 }
2943 }
2944
2945 function loopFix() {
2946 const swiper = this;
2947 swiper.emit('beforeLoopFix');
2948 const {
2949 activeIndex,
2950 slides,
2951 loopedSlides,
2952 allowSlidePrev,
2953 allowSlideNext,
2954 snapGrid,
2955 rtlTranslate: rtl
2956 } = swiper;
2957 let newIndex;
2958 swiper.allowSlidePrev = true;
2959 swiper.allowSlideNext = true;
2960 const snapTranslate = -snapGrid[activeIndex];
2961 const diff = snapTranslate - swiper.getTranslate(); // Fix For Negative Oversliding
2962
2963 if (activeIndex < loopedSlides) {
2964 newIndex = slides.length - loopedSlides * 3 + activeIndex;
2965 newIndex += loopedSlides;
2966 const slideChanged = swiper.slideTo(newIndex, 0, false, true);
2967
2968 if (slideChanged && diff !== 0) {
2969 swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
2970 }
2971 } else if (activeIndex >= slides.length - loopedSlides) {
2972 // Fix For Positive Oversliding
2973 newIndex = -slides.length + activeIndex + loopedSlides;
2974 newIndex += loopedSlides;
2975 const slideChanged = swiper.slideTo(newIndex, 0, false, true);
2976
2977 if (slideChanged && diff !== 0) {
2978 swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
2979 }
2980 }
2981
2982 swiper.allowSlidePrev = allowSlidePrev;
2983 swiper.allowSlideNext = allowSlideNext;
2984 swiper.emit('loopFix');
2985 }
2986
2987 function loopDestroy() {
2988 const swiper = this;
2989 const {
2990 $wrapperEl,
2991 params,
2992 slides
2993 } = swiper;
2994 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass},.${params.slideClass}.${params.slideBlankClass}`).remove();
2995 slides.removeAttr('data-swiper-slide-index');
2996 }
2997
2998 var loop = {
2999 loopCreate,
3000 loopFix,
3001 loopDestroy
3002 };
3003
3004 function setGrabCursor(moving) {
3005 const swiper = this;
3006 if (swiper.support.touch || !swiper.params.simulateTouch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) return;
3007 const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl;
3008 el.style.cursor = 'move';
3009 el.style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';
3010 el.style.cursor = moving ? '-moz-grabbin' : '-moz-grab';
3011 el.style.cursor = moving ? 'grabbing' : 'grab';
3012 }
3013
3014 function unsetGrabCursor() {
3015 const swiper = this;
3016
3017 if (swiper.support.touch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) {
3018 return;
3019 }
3020
3021 swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = '';
3022 }
3023
3024 var grabCursor = {
3025 setGrabCursor,
3026 unsetGrabCursor
3027 };
3028
3029 function closestElement(selector, base = this) {
3030 function __closestFrom(el) {
3031 if (!el || el === getDocument() || el === getWindow()) return null;
3032 if (el.assignedSlot) el = el.assignedSlot;
3033 const found = el.closest(selector);
3034 return found || __closestFrom(el.getRootNode().host);
3035 }
3036
3037 return __closestFrom(base);
3038 }
3039
3040 function onTouchStart(event) {
3041 const swiper = this;
3042 const document = getDocument();
3043 const window = getWindow();
3044 const data = swiper.touchEventsData;
3045 const {
3046 params,
3047 touches,
3048 enabled
3049 } = swiper;
3050 if (!enabled) return;
3051
3052 if (swiper.animating && params.preventInteractionOnTransition) {
3053 return;
3054 }
3055
3056 if (!swiper.animating && params.cssMode && params.loop) {
3057 swiper.loopFix();
3058 }
3059
3060 let e = event;
3061 if (e.originalEvent) e = e.originalEvent;
3062 let $targetEl = $(e.target);
3063
3064 if (params.touchEventsTarget === 'wrapper') {
3065 if (!$targetEl.closest(swiper.wrapperEl).length) return;
3066 }
3067
3068 data.isTouchEvent = e.type === 'touchstart';
3069 if (!data.isTouchEvent && 'which' in e && e.which === 3) return;
3070 if (!data.isTouchEvent && 'button' in e && e.button > 0) return;
3071 if (data.isTouched && data.isMoved) return; // change target el for shadow root component
3072
3073 const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
3074
3075 if (swipingClassHasValue && e.target && e.target.shadowRoot && event.path && event.path[0]) {
3076 $targetEl = $(event.path[0]);
3077 }
3078
3079 const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;
3080 const isTargetShadow = !!(e.target && e.target.shadowRoot); // use closestElement for shadow root element to get the actual closest for nested shadow root element
3081
3082 if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, e.target) : $targetEl.closest(noSwipingSelector)[0])) {
3083 swiper.allowClick = true;
3084 return;
3085 }
3086
3087 if (params.swipeHandler) {
3088 if (!$targetEl.closest(params.swipeHandler)[0]) return;
3089 }
3090
3091 touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
3092 touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
3093 const startX = touches.currentX;
3094 const startY = touches.currentY; // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore
3095
3096 const edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;
3097 const edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;
3098
3099 if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) {
3100 if (edgeSwipeDetection === 'prevent') {
3101 event.preventDefault();
3102 } else {
3103 return;
3104 }
3105 }
3106
3107 Object.assign(data, {
3108 isTouched: true,
3109 isMoved: false,
3110 allowTouchCallbacks: true,
3111 isScrolling: undefined,
3112 startMoving: undefined
3113 });
3114 touches.startX = startX;
3115 touches.startY = startY;
3116 data.touchStartTime = now();
3117 swiper.allowClick = true;
3118 swiper.updateSize();
3119 swiper.swipeDirection = undefined;
3120 if (params.threshold > 0) data.allowThresholdMove = false;
3121
3122 if (e.type !== 'touchstart') {
3123 let preventDefault = true;
3124 if ($targetEl.is(data.focusableElements)) preventDefault = false;
3125
3126 if (document.activeElement && $(document.activeElement).is(data.focusableElements) && document.activeElement !== $targetEl[0]) {
3127 document.activeElement.blur();
3128 }
3129
3130 const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
3131
3132 if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !$targetEl[0].isContentEditable) {
3133 e.preventDefault();
3134 }
3135 }
3136
3137 swiper.emit('touchStart', e);
3138 }
3139
3140 function onTouchMove(event) {
3141 const document = getDocument();
3142 const swiper = this;
3143 const data = swiper.touchEventsData;
3144 const {
3145 params,
3146 touches,
3147 rtlTranslate: rtl,
3148 enabled
3149 } = swiper;
3150 if (!enabled) return;
3151 let e = event;
3152 if (e.originalEvent) e = e.originalEvent;
3153
3154 if (!data.isTouched) {
3155 if (data.startMoving && data.isScrolling) {
3156 swiper.emit('touchMoveOpposite', e);
3157 }
3158
3159 return;
3160 }
3161
3162 if (data.isTouchEvent && e.type !== 'touchmove') return;
3163 const targetTouch = e.type === 'touchmove' && e.targetTouches && (e.targetTouches[0] || e.changedTouches[0]);
3164 const pageX = e.type === 'touchmove' ? targetTouch.pageX : e.pageX;
3165 const pageY = e.type === 'touchmove' ? targetTouch.pageY : e.pageY;
3166
3167 if (e.preventedByNestedSwiper) {
3168 touches.startX = pageX;
3169 touches.startY = pageY;
3170 return;
3171 }
3172
3173 if (!swiper.allowTouchMove) {
3174 // isMoved = true;
3175 swiper.allowClick = false;
3176
3177 if (data.isTouched) {
3178 Object.assign(touches, {
3179 startX: pageX,
3180 startY: pageY,
3181 currentX: pageX,
3182 currentY: pageY
3183 });
3184 data.touchStartTime = now();
3185 }
3186
3187 return;
3188 }
3189
3190 if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {
3191 if (swiper.isVertical()) {
3192 // Vertical
3193 if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {
3194 data.isTouched = false;
3195 data.isMoved = false;
3196 return;
3197 }
3198 } else if (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate()) {
3199 return;
3200 }
3201 }
3202
3203 if (data.isTouchEvent && document.activeElement) {
3204 if (e.target === document.activeElement && $(e.target).is(data.focusableElements)) {
3205 data.isMoved = true;
3206 swiper.allowClick = false;
3207 return;
3208 }
3209 }
3210
3211 if (data.allowTouchCallbacks) {
3212 swiper.emit('touchMove', e);
3213 }
3214
3215 if (e.targetTouches && e.targetTouches.length > 1) return;
3216 touches.currentX = pageX;
3217 touches.currentY = pageY;
3218 const diffX = touches.currentX - touches.startX;
3219 const diffY = touches.currentY - touches.startY;
3220 if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return;
3221
3222 if (typeof data.isScrolling === 'undefined') {
3223 let touchAngle;
3224
3225 if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX === touches.startX) {
3226 data.isScrolling = false;
3227 } else {
3228 // eslint-disable-next-line
3229 if (diffX * diffX + diffY * diffY >= 25) {
3230 touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI;
3231 data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params.touchAngle;
3232 }
3233 }
3234 }
3235
3236 if (data.isScrolling) {
3237 swiper.emit('touchMoveOpposite', e);
3238 }
3239
3240 if (typeof data.startMoving === 'undefined') {
3241 if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
3242 data.startMoving = true;
3243 }
3244 }
3245
3246 if (data.isScrolling) {
3247 data.isTouched = false;
3248 return;
3249 }
3250
3251 if (!data.startMoving) {
3252 return;
3253 }
3254
3255 swiper.allowClick = false;
3256
3257 if (!params.cssMode && e.cancelable) {
3258 e.preventDefault();
3259 }
3260
3261 if (params.touchMoveStopPropagation && !params.nested) {
3262 e.stopPropagation();
3263 }
3264
3265 if (!data.isMoved) {
3266 if (params.loop && !params.cssMode) {
3267 swiper.loopFix();
3268 }
3269
3270 data.startTranslate = swiper.getTranslate();
3271 swiper.setTransition(0);
3272
3273 if (swiper.animating) {
3274 swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');
3275 }
3276
3277 data.allowMomentumBounce = false; // Grab Cursor
3278
3279 if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
3280 swiper.setGrabCursor(true);
3281 }
3282
3283 swiper.emit('sliderFirstMove', e);
3284 }
3285
3286 swiper.emit('sliderMove', e);
3287 data.isMoved = true;
3288 let diff = swiper.isHorizontal() ? diffX : diffY;
3289 touches.diff = diff;
3290 diff *= params.touchRatio;
3291 if (rtl) diff = -diff;
3292 swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
3293 data.currentTranslate = diff + data.startTranslate;
3294 let disableParentSwiper = true;
3295 let resistanceRatio = params.resistanceRatio;
3296
3297 if (params.touchReleaseOnEdges) {
3298 resistanceRatio = 0;
3299 }
3300
3301 if (diff > 0 && data.currentTranslate > swiper.minTranslate()) {
3302 disableParentSwiper = false;
3303 if (params.resistance) data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio;
3304 } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {
3305 disableParentSwiper = false;
3306 if (params.resistance) data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio;
3307 }
3308
3309 if (disableParentSwiper) {
3310 e.preventedByNestedSwiper = true;
3311 } // Directions locks
3312
3313
3314 if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
3315 data.currentTranslate = data.startTranslate;
3316 }
3317
3318 if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
3319 data.currentTranslate = data.startTranslate;
3320 }
3321
3322 if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {
3323 data.currentTranslate = data.startTranslate;
3324 } // Threshold
3325
3326
3327 if (params.threshold > 0) {
3328 if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
3329 if (!data.allowThresholdMove) {
3330 data.allowThresholdMove = true;
3331 touches.startX = touches.currentX;
3332 touches.startY = touches.currentY;
3333 data.currentTranslate = data.startTranslate;
3334 touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;
3335 return;
3336 }
3337 } else {
3338 data.currentTranslate = data.startTranslate;
3339 return;
3340 }
3341 }
3342
3343 if (!params.followFinger || params.cssMode) return; // Update active index in free mode
3344
3345 if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {
3346 swiper.updateActiveIndex();
3347 swiper.updateSlidesClasses();
3348 }
3349
3350 if (swiper.params.freeMode && params.freeMode.enabled && swiper.freeMode) {
3351 swiper.freeMode.onTouchMove();
3352 } // Update progress
3353
3354
3355 swiper.updateProgress(data.currentTranslate); // Update translate
3356
3357 swiper.setTranslate(data.currentTranslate);
3358 }
3359
3360 function onTouchEnd(event) {
3361 const swiper = this;
3362 const data = swiper.touchEventsData;
3363 const {
3364 params,
3365 touches,
3366 rtlTranslate: rtl,
3367 slidesGrid,
3368 enabled
3369 } = swiper;
3370 if (!enabled) return;
3371 let e = event;
3372 if (e.originalEvent) e = e.originalEvent;
3373
3374 if (data.allowTouchCallbacks) {
3375 swiper.emit('touchEnd', e);
3376 }
3377
3378 data.allowTouchCallbacks = false;
3379
3380 if (!data.isTouched) {
3381 if (data.isMoved && params.grabCursor) {
3382 swiper.setGrabCursor(false);
3383 }
3384
3385 data.isMoved = false;
3386 data.startMoving = false;
3387 return;
3388 } // Return Grab Cursor
3389
3390
3391 if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
3392 swiper.setGrabCursor(false);
3393 } // Time diff
3394
3395
3396 const touchEndTime = now();
3397 const timeDiff = touchEndTime - data.touchStartTime; // Tap, doubleTap, Click
3398
3399 if (swiper.allowClick) {
3400 swiper.updateClickedSlide(e);
3401 swiper.emit('tap click', e);
3402
3403 if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) {
3404 swiper.emit('doubleTap doubleClick', e);
3405 }
3406 }
3407
3408 data.lastClickTime = now();
3409 nextTick(() => {
3410 if (!swiper.destroyed) swiper.allowClick = true;
3411 });
3412
3413 if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
3414 data.isTouched = false;
3415 data.isMoved = false;
3416 data.startMoving = false;
3417 return;
3418 }
3419
3420 data.isTouched = false;
3421 data.isMoved = false;
3422 data.startMoving = false;
3423 let currentPos;
3424
3425 if (params.followFinger) {
3426 currentPos = rtl ? swiper.translate : -swiper.translate;
3427 } else {
3428 currentPos = -data.currentTranslate;
3429 }
3430
3431 if (params.cssMode) {
3432 return;
3433 }
3434
3435 if (swiper.params.freeMode && params.freeMode.enabled) {
3436 swiper.freeMode.onTouchEnd({
3437 currentPos
3438 });
3439 return;
3440 } // Find current slide
3441
3442
3443 let stopIndex = 0;
3444 let groupSize = swiper.slidesSizesGrid[0];
3445
3446 for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) {
3447 const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
3448
3449 if (typeof slidesGrid[i + increment] !== 'undefined') {
3450 if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {
3451 stopIndex = i;
3452 groupSize = slidesGrid[i + increment] - slidesGrid[i];
3453 }
3454 } else if (currentPos >= slidesGrid[i]) {
3455 stopIndex = i;
3456 groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
3457 }
3458 } // Find current slide size
3459
3460
3461 const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
3462 const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
3463
3464 if (timeDiff > params.longSwipesMs) {
3465 // Long touches
3466 if (!params.longSwipes) {
3467 swiper.slideTo(swiper.activeIndex);
3468 return;
3469 }
3470
3471 if (swiper.swipeDirection === 'next') {
3472 if (ratio >= params.longSwipesRatio) swiper.slideTo(stopIndex + increment);else swiper.slideTo(stopIndex);
3473 }
3474
3475 if (swiper.swipeDirection === 'prev') {
3476 if (ratio > 1 - params.longSwipesRatio) swiper.slideTo(stopIndex + increment);else swiper.slideTo(stopIndex);
3477 }
3478 } else {
3479 // Short swipes
3480 if (!params.shortSwipes) {
3481 swiper.slideTo(swiper.activeIndex);
3482 return;
3483 }
3484
3485 const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
3486
3487 if (!isNavButtonTarget) {
3488 if (swiper.swipeDirection === 'next') {
3489 swiper.slideTo(stopIndex + increment);
3490 }
3491
3492 if (swiper.swipeDirection === 'prev') {
3493 swiper.slideTo(stopIndex);
3494 }
3495 } else if (e.target === swiper.navigation.nextEl) {
3496 swiper.slideTo(stopIndex + increment);
3497 } else {
3498 swiper.slideTo(stopIndex);
3499 }
3500 }
3501 }
3502
3503 function onResize() {
3504 const swiper = this;
3505 const {
3506 params,
3507 el
3508 } = swiper;
3509 if (el && el.offsetWidth === 0) return; // Breakpoints
3510
3511 if (params.breakpoints) {
3512 swiper.setBreakpoint();
3513 } // Save locks
3514
3515
3516 const {
3517 allowSlideNext,
3518 allowSlidePrev,
3519 snapGrid
3520 } = swiper; // Disable locks on resize
3521
3522 swiper.allowSlideNext = true;
3523 swiper.allowSlidePrev = true;
3524 swiper.updateSize();
3525 swiper.updateSlides();
3526 swiper.updateSlidesClasses();
3527
3528 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {
3529 swiper.slideTo(swiper.slides.length - 1, 0, false, true);
3530 } else {
3531 swiper.slideTo(swiper.activeIndex, 0, false, true);
3532 }
3533
3534 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
3535 swiper.autoplay.run();
3536 } // Return locks after resize
3537
3538
3539 swiper.allowSlidePrev = allowSlidePrev;
3540 swiper.allowSlideNext = allowSlideNext;
3541
3542 if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
3543 swiper.checkOverflow();
3544 }
3545 }
3546
3547 function onClick(e) {
3548 const swiper = this;
3549 if (!swiper.enabled) return;
3550
3551 if (!swiper.allowClick) {
3552 if (swiper.params.preventClicks) e.preventDefault();
3553
3554 if (swiper.params.preventClicksPropagation && swiper.animating) {
3555 e.stopPropagation();
3556 e.stopImmediatePropagation();
3557 }
3558 }
3559 }
3560
3561 function onScroll() {
3562 const swiper = this;
3563 const {
3564 wrapperEl,
3565 rtlTranslate,
3566 enabled
3567 } = swiper;
3568 if (!enabled) return;
3569 swiper.previousTranslate = swiper.translate;
3570
3571 if (swiper.isHorizontal()) {
3572 swiper.translate = -wrapperEl.scrollLeft;
3573 } else {
3574 swiper.translate = -wrapperEl.scrollTop;
3575 } // eslint-disable-next-line
3576
3577
3578 if (swiper.translate === -0) swiper.translate = 0;
3579 swiper.updateActiveIndex();
3580 swiper.updateSlidesClasses();
3581 let newProgress;
3582 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
3583
3584 if (translatesDiff === 0) {
3585 newProgress = 0;
3586 } else {
3587 newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff;
3588 }
3589
3590 if (newProgress !== swiper.progress) {
3591 swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate);
3592 }
3593
3594 swiper.emit('setTranslate', swiper.translate, false);
3595 }
3596
3597 let dummyEventAttached = false;
3598
3599 function dummyEventListener() {}
3600
3601 const events = (swiper, method) => {
3602 const document = getDocument();
3603 const {
3604 params,
3605 touchEvents,
3606 el,
3607 wrapperEl,
3608 device,
3609 support
3610 } = swiper;
3611 const capture = !!params.nested;
3612 const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
3613 const swiperMethod = method; // Touch Events
3614
3615 if (!support.touch) {
3616 el[domMethod](touchEvents.start, swiper.onTouchStart, false);
3617 document[domMethod](touchEvents.move, swiper.onTouchMove, capture);
3618 document[domMethod](touchEvents.end, swiper.onTouchEnd, false);
3619 } else {
3620 const passiveListener = touchEvents.start === 'touchstart' && support.passiveListener && params.passiveListeners ? {
3621 passive: true,
3622 capture: false
3623 } : false;
3624 el[domMethod](touchEvents.start, swiper.onTouchStart, passiveListener);
3625 el[domMethod](touchEvents.move, swiper.onTouchMove, support.passiveListener ? {
3626 passive: false,
3627 capture
3628 } : capture);
3629 el[domMethod](touchEvents.end, swiper.onTouchEnd, passiveListener);
3630
3631 if (touchEvents.cancel) {
3632 el[domMethod](touchEvents.cancel, swiper.onTouchEnd, passiveListener);
3633 }
3634 } // Prevent Links Clicks
3635
3636
3637 if (params.preventClicks || params.preventClicksPropagation) {
3638 el[domMethod]('click', swiper.onClick, true);
3639 }
3640
3641 if (params.cssMode) {
3642 wrapperEl[domMethod]('scroll', swiper.onScroll);
3643 } // Resize handler
3644
3645
3646 if (params.updateOnWindowResize) {
3647 swiper[swiperMethod](device.ios || device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate', onResize, true);
3648 } else {
3649 swiper[swiperMethod]('observerUpdate', onResize, true);
3650 }
3651 };
3652
3653 function attachEvents() {
3654 const swiper = this;
3655 const document = getDocument();
3656 const {
3657 params,
3658 support
3659 } = swiper;
3660 swiper.onTouchStart = onTouchStart.bind(swiper);
3661 swiper.onTouchMove = onTouchMove.bind(swiper);
3662 swiper.onTouchEnd = onTouchEnd.bind(swiper);
3663
3664 if (params.cssMode) {
3665 swiper.onScroll = onScroll.bind(swiper);
3666 }
3667
3668 swiper.onClick = onClick.bind(swiper);
3669
3670 if (support.touch && !dummyEventAttached) {
3671 document.addEventListener('touchstart', dummyEventListener);
3672 dummyEventAttached = true;
3673 }
3674
3675 events(swiper, 'on');
3676 }
3677
3678 function detachEvents() {
3679 const swiper = this;
3680 events(swiper, 'off');
3681 }
3682
3683 var events$1 = {
3684 attachEvents,
3685 detachEvents
3686 };
3687
3688 const isGridEnabled = (swiper, params) => {
3689 return swiper.grid && params.grid && params.grid.rows > 1;
3690 };
3691
3692 function setBreakpoint() {
3693 const swiper = this;
3694 const {
3695 activeIndex,
3696 initialized,
3697 loopedSlides = 0,
3698 params,
3699 $el
3700 } = swiper;
3701 const breakpoints = params.breakpoints;
3702 if (!breakpoints || breakpoints && Object.keys(breakpoints).length === 0) return; // Get breakpoint for window width and update parameters
3703
3704 const breakpoint = swiper.getBreakpoint(breakpoints, swiper.params.breakpointsBase, swiper.el);
3705 if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;
3706 const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
3707 const breakpointParams = breakpointOnlyParams || swiper.originalParams;
3708 const wasMultiRow = isGridEnabled(swiper, params);
3709 const isMultiRow = isGridEnabled(swiper, breakpointParams);
3710 const wasEnabled = params.enabled;
3711
3712 if (wasMultiRow && !isMultiRow) {
3713 $el.removeClass(`${params.containerModifierClass}grid ${params.containerModifierClass}grid-column`);
3714 swiper.emitContainerClasses();
3715 } else if (!wasMultiRow && isMultiRow) {
3716 $el.addClass(`${params.containerModifierClass}grid`);
3717
3718 if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {
3719 $el.addClass(`${params.containerModifierClass}grid-column`);
3720 }
3721
3722 swiper.emitContainerClasses();
3723 }
3724
3725 const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
3726 const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
3727
3728 if (directionChanged && initialized) {
3729 swiper.changeDirection();
3730 }
3731
3732 extend(swiper.params, breakpointParams);
3733 const isEnabled = swiper.params.enabled;
3734 Object.assign(swiper, {
3735 allowTouchMove: swiper.params.allowTouchMove,
3736 allowSlideNext: swiper.params.allowSlideNext,
3737 allowSlidePrev: swiper.params.allowSlidePrev
3738 });
3739
3740 if (wasEnabled && !isEnabled) {
3741 swiper.disable();
3742 } else if (!wasEnabled && isEnabled) {
3743 swiper.enable();
3744 }
3745
3746 swiper.currentBreakpoint = breakpoint;
3747 swiper.emit('_beforeBreakpoint', breakpointParams);
3748
3749 if (needsReLoop && initialized) {
3750 swiper.loopDestroy();
3751 swiper.loopCreate();
3752 swiper.updateSlides();
3753 swiper.slideTo(activeIndex - loopedSlides + swiper.loopedSlides, 0, false);
3754 }
3755
3756 swiper.emit('breakpoint', breakpointParams);
3757 }
3758
3759 function getBreakpoint(breakpoints, base = 'window', containerEl) {
3760 if (!breakpoints || base === 'container' && !containerEl) return undefined;
3761 let breakpoint = false;
3762 const window = getWindow();
3763 const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight;
3764 const points = Object.keys(breakpoints).map(point => {
3765 if (typeof point === 'string' && point.indexOf('@') === 0) {
3766 const minRatio = parseFloat(point.substr(1));
3767 const value = currentHeight * minRatio;
3768 return {
3769 value,
3770 point
3771 };
3772 }
3773
3774 return {
3775 value: point,
3776 point
3777 };
3778 });
3779 points.sort((a, b) => parseInt(a.value, 10) - parseInt(b.value, 10));
3780
3781 for (let i = 0; i < points.length; i += 1) {
3782 const {
3783 point,
3784 value
3785 } = points[i];
3786
3787 if (base === 'window') {
3788 if (window.matchMedia(`(min-width: ${value}px)`).matches) {
3789 breakpoint = point;
3790 }
3791 } else if (value <= containerEl.clientWidth) {
3792 breakpoint = point;
3793 }
3794 }
3795
3796 return breakpoint || 'max';
3797 }
3798
3799 var breakpoints = {
3800 setBreakpoint,
3801 getBreakpoint
3802 };
3803
3804 function prepareClasses(entries, prefix) {
3805 const resultClasses = [];
3806 entries.forEach(item => {
3807 if (typeof item === 'object') {
3808 Object.keys(item).forEach(classNames => {
3809 if (item[classNames]) {
3810 resultClasses.push(prefix + classNames);
3811 }
3812 });
3813 } else if (typeof item === 'string') {
3814 resultClasses.push(prefix + item);
3815 }
3816 });
3817 return resultClasses;
3818 }
3819
3820 function addClasses() {
3821 const swiper = this;
3822 const {
3823 classNames,
3824 params,
3825 rtl,
3826 $el,
3827 device,
3828 support
3829 } = swiper; // prettier-ignore
3830
3831 const suffixes = prepareClasses(['initialized', params.direction, {
3832 'pointer-events': !support.touch
3833 }, {
3834 'free-mode': swiper.params.freeMode && params.freeMode.enabled
3835 }, {
3836 'autoheight': params.autoHeight
3837 }, {
3838 'rtl': rtl
3839 }, {
3840 'grid': params.grid && params.grid.rows > 1
3841 }, {
3842 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'
3843 }, {
3844 'android': device.android
3845 }, {
3846 'ios': device.ios
3847 }, {
3848 'css-mode': params.cssMode
3849 }, {
3850 'centered': params.cssMode && params.centeredSlides
3851 }], params.containerModifierClass);
3852 classNames.push(...suffixes);
3853 $el.addClass([...classNames].join(' '));
3854 swiper.emitContainerClasses();
3855 }
3856
3857 function removeClasses() {
3858 const swiper = this;
3859 const {
3860 $el,
3861 classNames
3862 } = swiper;
3863 $el.removeClass(classNames.join(' '));
3864 swiper.emitContainerClasses();
3865 }
3866
3867 var classes = {
3868 addClasses,
3869 removeClasses
3870 };
3871
3872 function loadImage(imageEl, src, srcset, sizes, checkForComplete, callback) {
3873 const window = getWindow();
3874 let image;
3875
3876 function onReady() {
3877 if (callback) callback();
3878 }
3879
3880 const isPicture = $(imageEl).parent('picture')[0];
3881
3882 if (!isPicture && (!imageEl.complete || !checkForComplete)) {
3883 if (src) {
3884 image = new window.Image();
3885 image.onload = onReady;
3886 image.onerror = onReady;
3887
3888 if (sizes) {
3889 image.sizes = sizes;
3890 }
3891
3892 if (srcset) {
3893 image.srcset = srcset;
3894 }
3895
3896 if (src) {
3897 image.src = src;
3898 }
3899 } else {
3900 onReady();
3901 }
3902 } else {
3903 // image already loaded...
3904 onReady();
3905 }
3906 }
3907
3908 function preloadImages() {
3909 const swiper = this;
3910 swiper.imagesToLoad = swiper.$el.find('img');
3911
3912 function onReady() {
3913 if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) return;
3914 if (swiper.imagesLoaded !== undefined) swiper.imagesLoaded += 1;
3915
3916 if (swiper.imagesLoaded === swiper.imagesToLoad.length) {
3917 if (swiper.params.updateOnImagesReady) swiper.update();
3918 swiper.emit('imagesReady');
3919 }
3920 }
3921
3922 for (let i = 0; i < swiper.imagesToLoad.length; i += 1) {
3923 const imageEl = swiper.imagesToLoad[i];
3924 swiper.loadImage(imageEl, imageEl.currentSrc || imageEl.getAttribute('src'), imageEl.srcset || imageEl.getAttribute('srcset'), imageEl.sizes || imageEl.getAttribute('sizes'), true, onReady);
3925 }
3926 }
3927
3928 var images = {
3929 loadImage,
3930 preloadImages
3931 };
3932
3933 function checkOverflow() {
3934 const swiper = this;
3935 const {
3936 isLocked: wasLocked,
3937 params
3938 } = swiper;
3939 const {
3940 slidesOffsetBefore
3941 } = params;
3942
3943 if (slidesOffsetBefore) {
3944 const lastSlideIndex = swiper.slides.length - 1;
3945 const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] + slidesOffsetBefore * 2;
3946 swiper.isLocked = swiper.size > lastSlideRightEdge;
3947 } else {
3948 swiper.isLocked = swiper.snapGrid.length === 1;
3949 }
3950
3951 if (params.allowSlideNext === true) {
3952 swiper.allowSlideNext = !swiper.isLocked;
3953 }
3954
3955 if (params.allowSlidePrev === true) {
3956 swiper.allowSlidePrev = !swiper.isLocked;
3957 }
3958
3959 if (wasLocked && wasLocked !== swiper.isLocked) {
3960 swiper.isEnd = false;
3961 }
3962
3963 if (wasLocked !== swiper.isLocked) {
3964 swiper.emit(swiper.isLocked ? 'lock' : 'unlock');
3965 }
3966 }
3967
3968 var checkOverflow$1 = {
3969 checkOverflow
3970 };
3971
3972 var defaults = {
3973 init: true,
3974 direction: 'horizontal',
3975 touchEventsTarget: 'wrapper',
3976 initialSlide: 0,
3977 speed: 300,
3978 cssMode: false,
3979 updateOnWindowResize: true,
3980 resizeObserver: true,
3981 nested: false,
3982 createElements: false,
3983 enabled: true,
3984 focusableElements: 'input, select, option, textarea, button, video, label',
3985 // Overrides
3986 width: null,
3987 height: null,
3988 //
3989 preventInteractionOnTransition: false,
3990 // ssr
3991 userAgent: null,
3992 url: null,
3993 // To support iOS's swipe-to-go-back gesture (when being used in-app).
3994 edgeSwipeDetection: false,
3995 edgeSwipeThreshold: 20,
3996 // Autoheight
3997 autoHeight: false,
3998 // Set wrapper width
3999 setWrapperSize: false,
4000 // Virtual Translate
4001 virtualTranslate: false,
4002 // Effects
4003 effect: 'slide',
4004 // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
4005 // Breakpoints
4006 breakpoints: undefined,
4007 breakpointsBase: 'window',
4008 // Slides grid
4009 spaceBetween: 0,
4010 slidesPerView: 1,
4011 slidesPerGroup: 1,
4012 slidesPerGroupSkip: 0,
4013 slidesPerGroupAuto: false,
4014 centeredSlides: false,
4015 centeredSlidesBounds: false,
4016 slidesOffsetBefore: 0,
4017 // in px
4018 slidesOffsetAfter: 0,
4019 // in px
4020 normalizeSlideIndex: true,
4021 centerInsufficientSlides: false,
4022 // Disable swiper and hide navigation when container not overflow
4023 watchOverflow: true,
4024 // Round length
4025 roundLengths: false,
4026 // Touches
4027 touchRatio: 1,
4028 touchAngle: 45,
4029 simulateTouch: true,
4030 shortSwipes: true,
4031 longSwipes: true,
4032 longSwipesRatio: 0.5,
4033 longSwipesMs: 300,
4034 followFinger: true,
4035 allowTouchMove: true,
4036 threshold: 0,
4037 touchMoveStopPropagation: false,
4038 touchStartPreventDefault: true,
4039 touchStartForcePreventDefault: false,
4040 touchReleaseOnEdges: false,
4041 // Unique Navigation Elements
4042 uniqueNavElements: true,
4043 // Resistance
4044 resistance: true,
4045 resistanceRatio: 0.85,
4046 // Progress
4047 watchSlidesProgress: false,
4048 // Cursor
4049 grabCursor: false,
4050 // Clicks
4051 preventClicks: true,
4052 preventClicksPropagation: true,
4053 slideToClickedSlide: false,
4054 // Images
4055 preloadImages: true,
4056 updateOnImagesReady: true,
4057 // loop
4058 loop: false,
4059 loopAdditionalSlides: 0,
4060 loopedSlides: null,
4061 loopFillGroupWithBlank: false,
4062 loopPreventsSlide: true,
4063 // Swiping/no swiping
4064 allowSlidePrev: true,
4065 allowSlideNext: true,
4066 swipeHandler: null,
4067 // '.swipe-handler',
4068 noSwiping: true,
4069 noSwipingClass: 'swiper-no-swiping',
4070 noSwipingSelector: null,
4071 // Passive Listeners
4072 passiveListeners: true,
4073 // NS
4074 containerModifierClass: 'swiper-',
4075 // NEW
4076 slideClass: 'swiper-slide',
4077 slideBlankClass: 'swiper-slide-invisible-blank',
4078 slideActiveClass: 'swiper-slide-active',
4079 slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
4080 slideVisibleClass: 'swiper-slide-visible',
4081 slideDuplicateClass: 'swiper-slide-duplicate',
4082 slideNextClass: 'swiper-slide-next',
4083 slideDuplicateNextClass: 'swiper-slide-duplicate-next',
4084 slidePrevClass: 'swiper-slide-prev',
4085 slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
4086 wrapperClass: 'swiper-wrapper',
4087 // Callbacks
4088 runCallbacksOnInit: true,
4089 // Internals
4090 _emitClasses: false
4091 };
4092
4093 function moduleExtendParams(params, allModulesParams) {
4094 return function extendParams(obj = {}) {
4095 const moduleParamName = Object.keys(obj)[0];
4096 const moduleParams = obj[moduleParamName];
4097
4098 if (typeof moduleParams !== 'object' || moduleParams === null) {
4099 extend(allModulesParams, obj);
4100 return;
4101 }
4102
4103 if (['navigation', 'pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] === true) {
4104 params[moduleParamName] = {
4105 auto: true
4106 };
4107 }
4108
4109 if (!(moduleParamName in params && 'enabled' in moduleParams)) {
4110 extend(allModulesParams, obj);
4111 return;
4112 }
4113
4114 if (params[moduleParamName] === true) {
4115 params[moduleParamName] = {
4116 enabled: true
4117 };
4118 }
4119
4120 if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) {
4121 params[moduleParamName].enabled = true;
4122 }
4123
4124 if (!params[moduleParamName]) params[moduleParamName] = {
4125 enabled: false
4126 };
4127 extend(allModulesParams, obj);
4128 };
4129 }
4130
4131 /* eslint no-param-reassign: "off" */
4132 const prototypes = {
4133 eventsEmitter,
4134 update,
4135 translate,
4136 transition,
4137 slide,
4138 loop,
4139 grabCursor,
4140 events: events$1,
4141 breakpoints,
4142 checkOverflow: checkOverflow$1,
4143 classes,
4144 images
4145 };
4146 const extendedDefaults = {};
4147
4148 class Swiper {
4149 constructor(...args) {
4150 let el;
4151 let params;
4152
4153 if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') {
4154 params = args[0];
4155 } else {
4156 [el, params] = args;
4157 }
4158
4159 if (!params) params = {};
4160 params = extend({}, params);
4161 if (el && !params.el) params.el = el;
4162
4163 if (params.el && $(params.el).length > 1) {
4164 const swipers = [];
4165 $(params.el).each(containerEl => {
4166 const newParams = extend({}, params, {
4167 el: containerEl
4168 });
4169 swipers.push(new Swiper(newParams));
4170 });
4171 return swipers;
4172 } // Swiper Instance
4173
4174
4175 const swiper = this;
4176 swiper.__swiper__ = true;
4177 swiper.support = getSupport();
4178 swiper.device = getDevice({
4179 userAgent: params.userAgent
4180 });
4181 swiper.browser = getBrowser();
4182 swiper.eventsListeners = {};
4183 swiper.eventsAnyListeners = [];
4184 swiper.modules = [...swiper.__modules__];
4185
4186 if (params.modules && Array.isArray(params.modules)) {
4187 swiper.modules.push(...params.modules);
4188 }
4189
4190 const allModulesParams = {};
4191 swiper.modules.forEach(mod => {
4192 mod({
4193 swiper,
4194 extendParams: moduleExtendParams(params, allModulesParams),
4195 on: swiper.on.bind(swiper),
4196 once: swiper.once.bind(swiper),
4197 off: swiper.off.bind(swiper),
4198 emit: swiper.emit.bind(swiper)
4199 });
4200 }); // Extend defaults with modules params
4201
4202 const swiperParams = extend({}, defaults, allModulesParams); // Extend defaults with passed params
4203
4204 swiper.params = extend({}, swiperParams, extendedDefaults, params);
4205 swiper.originalParams = extend({}, swiper.params);
4206 swiper.passedParams = extend({}, params); // add event listeners
4207
4208 if (swiper.params && swiper.params.on) {
4209 Object.keys(swiper.params.on).forEach(eventName => {
4210 swiper.on(eventName, swiper.params.on[eventName]);
4211 });
4212 }
4213
4214 if (swiper.params && swiper.params.onAny) {
4215 swiper.onAny(swiper.params.onAny);
4216 } // Save Dom lib
4217
4218
4219 swiper.$ = $; // Extend Swiper
4220
4221 Object.assign(swiper, {
4222 enabled: swiper.params.enabled,
4223 el,
4224 // Classes
4225 classNames: [],
4226 // Slides
4227 slides: $(),
4228 slidesGrid: [],
4229 snapGrid: [],
4230 slidesSizesGrid: [],
4231
4232 // isDirection
4233 isHorizontal() {
4234 return swiper.params.direction === 'horizontal';
4235 },
4236
4237 isVertical() {
4238 return swiper.params.direction === 'vertical';
4239 },
4240
4241 // Indexes
4242 activeIndex: 0,
4243 realIndex: 0,
4244 //
4245 isBeginning: true,
4246 isEnd: false,
4247 // Props
4248 translate: 0,
4249 previousTranslate: 0,
4250 progress: 0,
4251 velocity: 0,
4252 animating: false,
4253 // Locks
4254 allowSlideNext: swiper.params.allowSlideNext,
4255 allowSlidePrev: swiper.params.allowSlidePrev,
4256 // Touch Events
4257 touchEvents: function touchEvents() {
4258 const touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];
4259 const desktop = ['pointerdown', 'pointermove', 'pointerup'];
4260 swiper.touchEventsTouch = {
4261 start: touch[0],
4262 move: touch[1],
4263 end: touch[2],
4264 cancel: touch[3]
4265 };
4266 swiper.touchEventsDesktop = {
4267 start: desktop[0],
4268 move: desktop[1],
4269 end: desktop[2]
4270 };
4271 return swiper.support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;
4272 }(),
4273 touchEventsData: {
4274 isTouched: undefined,
4275 isMoved: undefined,
4276 allowTouchCallbacks: undefined,
4277 touchStartTime: undefined,
4278 isScrolling: undefined,
4279 currentTranslate: undefined,
4280 startTranslate: undefined,
4281 allowThresholdMove: undefined,
4282 // Form elements to match
4283 focusableElements: swiper.params.focusableElements,
4284 // Last click time
4285 lastClickTime: now(),
4286 clickTimeout: undefined,
4287 // Velocities
4288 velocities: [],
4289 allowMomentumBounce: undefined,
4290 isTouchEvent: undefined,
4291 startMoving: undefined
4292 },
4293 // Clicks
4294 allowClick: true,
4295 // Touches
4296 allowTouchMove: swiper.params.allowTouchMove,
4297 touches: {
4298 startX: 0,
4299 startY: 0,
4300 currentX: 0,
4301 currentY: 0,
4302 diff: 0
4303 },
4304 // Images
4305 imagesToLoad: [],
4306 imagesLoaded: 0
4307 });
4308 swiper.emit('_swiper'); // Init
4309
4310 if (swiper.params.init) {
4311 swiper.init();
4312 } // Return app instance
4313
4314
4315 return swiper;
4316 }
4317
4318 enable() {
4319 const swiper = this;
4320 if (swiper.enabled) return;
4321 swiper.enabled = true;
4322
4323 if (swiper.params.grabCursor) {
4324 swiper.setGrabCursor();
4325 }
4326
4327 swiper.emit('enable');
4328 }
4329
4330 disable() {
4331 const swiper = this;
4332 if (!swiper.enabled) return;
4333 swiper.enabled = false;
4334
4335 if (swiper.params.grabCursor) {
4336 swiper.unsetGrabCursor();
4337 }
4338
4339 swiper.emit('disable');
4340 }
4341
4342 setProgress(progress, speed) {
4343 const swiper = this;
4344 progress = Math.min(Math.max(progress, 0), 1);
4345 const min = swiper.minTranslate();
4346 const max = swiper.maxTranslate();
4347 const current = (max - min) * progress + min;
4348 swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed);
4349 swiper.updateActiveIndex();
4350 swiper.updateSlidesClasses();
4351 }
4352
4353 emitContainerClasses() {
4354 const swiper = this;
4355 if (!swiper.params._emitClasses || !swiper.el) return;
4356 const cls = swiper.el.className.split(' ').filter(className => {
4357 return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0;
4358 });
4359 swiper.emit('_containerClasses', cls.join(' '));
4360 }
4361
4362 getSlideClasses(slideEl) {
4363 const swiper = this;
4364 return slideEl.className.split(' ').filter(className => {
4365 return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0;
4366 }).join(' ');
4367 }
4368
4369 emitSlidesClasses() {
4370 const swiper = this;
4371 if (!swiper.params._emitClasses || !swiper.el) return;
4372 const updates = [];
4373 swiper.slides.each(slideEl => {
4374 const classNames = swiper.getSlideClasses(slideEl);
4375 updates.push({
4376 slideEl,
4377 classNames
4378 });
4379 swiper.emit('_slideClass', slideEl, classNames);
4380 });
4381 swiper.emit('_slideClasses', updates);
4382 }
4383
4384 slidesPerViewDynamic(view = 'current', exact = false) {
4385 const swiper = this;
4386 const {
4387 params,
4388 slides,
4389 slidesGrid,
4390 slidesSizesGrid,
4391 size: swiperSize,
4392 activeIndex
4393 } = swiper;
4394 let spv = 1;
4395
4396 if (params.centeredSlides) {
4397 let slideSize = slides[activeIndex].swiperSlideSize;
4398 let breakLoop;
4399
4400 for (let i = activeIndex + 1; i < slides.length; i += 1) {
4401 if (slides[i] && !breakLoop) {
4402 slideSize += slides[i].swiperSlideSize;
4403 spv += 1;
4404 if (slideSize > swiperSize) breakLoop = true;
4405 }
4406 }
4407
4408 for (let i = activeIndex - 1; i >= 0; i -= 1) {
4409 if (slides[i] && !breakLoop) {
4410 slideSize += slides[i].swiperSlideSize;
4411 spv += 1;
4412 if (slideSize > swiperSize) breakLoop = true;
4413 }
4414 }
4415 } else {
4416 // eslint-disable-next-line
4417 if (view === 'current') {
4418 for (let i = activeIndex + 1; i < slides.length; i += 1) {
4419 const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;
4420
4421 if (slideInView) {
4422 spv += 1;
4423 }
4424 }
4425 } else {
4426 // previous
4427 for (let i = activeIndex - 1; i >= 0; i -= 1) {
4428 const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;
4429
4430 if (slideInView) {
4431 spv += 1;
4432 }
4433 }
4434 }
4435 }
4436
4437 return spv;
4438 }
4439
4440 update() {
4441 const swiper = this;
4442 if (!swiper || swiper.destroyed) return;
4443 const {
4444 snapGrid,
4445 params
4446 } = swiper; // Breakpoints
4447
4448 if (params.breakpoints) {
4449 swiper.setBreakpoint();
4450 }
4451
4452 swiper.updateSize();
4453 swiper.updateSlides();
4454 swiper.updateProgress();
4455 swiper.updateSlidesClasses();
4456
4457 function setTranslate() {
4458 const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
4459 const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
4460 swiper.setTranslate(newTranslate);
4461 swiper.updateActiveIndex();
4462 swiper.updateSlidesClasses();
4463 }
4464
4465 let translated;
4466
4467 if (swiper.params.freeMode && swiper.params.freeMode.enabled) {
4468 setTranslate();
4469
4470 if (swiper.params.autoHeight) {
4471 swiper.updateAutoHeight();
4472 }
4473 } else {
4474 if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
4475 translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
4476 } else {
4477 translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
4478 }
4479
4480 if (!translated) {
4481 setTranslate();
4482 }
4483 }
4484
4485 if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
4486 swiper.checkOverflow();
4487 }
4488
4489 swiper.emit('update');
4490 }
4491
4492 changeDirection(newDirection, needUpdate = true) {
4493 const swiper = this;
4494 const currentDirection = swiper.params.direction;
4495
4496 if (!newDirection) {
4497 // eslint-disable-next-line
4498 newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
4499 }
4500
4501 if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {
4502 return swiper;
4503 }
4504
4505 swiper.$el.removeClass(`${swiper.params.containerModifierClass}${currentDirection}`).addClass(`${swiper.params.containerModifierClass}${newDirection}`);
4506 swiper.emitContainerClasses();
4507 swiper.params.direction = newDirection;
4508 swiper.slides.each(slideEl => {
4509 if (newDirection === 'vertical') {
4510 slideEl.style.width = '';
4511 } else {
4512 slideEl.style.height = '';
4513 }
4514 });
4515 swiper.emit('changeDirection');
4516 if (needUpdate) swiper.update();
4517 return swiper;
4518 }
4519
4520 mount(el) {
4521 const swiper = this;
4522 if (swiper.mounted) return true; // Find el
4523
4524 const $el = $(el || swiper.params.el);
4525 el = $el[0];
4526
4527 if (!el) {
4528 return false;
4529 }
4530
4531 el.swiper = swiper;
4532
4533 const getWrapperSelector = () => {
4534 return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`;
4535 };
4536
4537 const getWrapper = () => {
4538 if (el && el.shadowRoot && el.shadowRoot.querySelector) {
4539 const res = $(el.shadowRoot.querySelector(getWrapperSelector())); // Children needs to return slot items
4540
4541 res.children = options => $el.children(options);
4542
4543 return res;
4544 }
4545
4546 return $el.children(getWrapperSelector());
4547 }; // Find Wrapper
4548
4549
4550 let $wrapperEl = getWrapper();
4551
4552 if ($wrapperEl.length === 0 && swiper.params.createElements) {
4553 const document = getDocument();
4554 const wrapper = document.createElement('div');
4555 $wrapperEl = $(wrapper);
4556 wrapper.className = swiper.params.wrapperClass;
4557 $el.append(wrapper);
4558 $el.children(`.${swiper.params.slideClass}`).each(slideEl => {
4559 $wrapperEl.append(slideEl);
4560 });
4561 }
4562
4563 Object.assign(swiper, {
4564 $el,
4565 el,
4566 $wrapperEl,
4567 wrapperEl: $wrapperEl[0],
4568 mounted: true,
4569 // RTL
4570 rtl: el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl',
4571 rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
4572 wrongRTL: $wrapperEl.css('display') === '-webkit-box'
4573 });
4574 return true;
4575 }
4576
4577 init(el) {
4578 const swiper = this;
4579 if (swiper.initialized) return swiper;
4580 const mounted = swiper.mount(el);
4581 if (mounted === false) return swiper;
4582 swiper.emit('beforeInit'); // Set breakpoint
4583
4584 if (swiper.params.breakpoints) {
4585 swiper.setBreakpoint();
4586 } // Add Classes
4587
4588
4589 swiper.addClasses(); // Create loop
4590
4591 if (swiper.params.loop) {
4592 swiper.loopCreate();
4593 } // Update size
4594
4595
4596 swiper.updateSize(); // Update slides
4597
4598 swiper.updateSlides();
4599
4600 if (swiper.params.watchOverflow) {
4601 swiper.checkOverflow();
4602 } // Set Grab Cursor
4603
4604
4605 if (swiper.params.grabCursor && swiper.enabled) {
4606 swiper.setGrabCursor();
4607 }
4608
4609 if (swiper.params.preloadImages) {
4610 swiper.preloadImages();
4611 } // Slide To Initial Slide
4612
4613
4614 if (swiper.params.loop) {
4615 swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit, false, true);
4616 } else {
4617 swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
4618 } // Attach events
4619
4620
4621 swiper.attachEvents(); // Init Flag
4622
4623 swiper.initialized = true; // Emit
4624
4625 swiper.emit('init');
4626 swiper.emit('afterInit');
4627 return swiper;
4628 }
4629
4630 destroy(deleteInstance = true, cleanStyles = true) {
4631 const swiper = this;
4632 const {
4633 params,
4634 $el,
4635 $wrapperEl,
4636 slides
4637 } = swiper;
4638
4639 if (typeof swiper.params === 'undefined' || swiper.destroyed) {
4640 return null;
4641 }
4642
4643 swiper.emit('beforeDestroy'); // Init Flag
4644
4645 swiper.initialized = false; // Detach events
4646
4647 swiper.detachEvents(); // Destroy loop
4648
4649 if (params.loop) {
4650 swiper.loopDestroy();
4651 } // Cleanup styles
4652
4653
4654 if (cleanStyles) {
4655 swiper.removeClasses();
4656 $el.removeAttr('style');
4657 $wrapperEl.removeAttr('style');
4658
4659 if (slides && slides.length) {
4660 slides.removeClass([params.slideVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass].join(' ')).removeAttr('style').removeAttr('data-swiper-slide-index');
4661 }
4662 }
4663
4664 swiper.emit('destroy'); // Detach emitter events
4665
4666 Object.keys(swiper.eventsListeners).forEach(eventName => {
4667 swiper.off(eventName);
4668 });
4669
4670 if (deleteInstance !== false) {
4671 swiper.$el[0].swiper = null;
4672 deleteProps(swiper);
4673 }
4674
4675 swiper.destroyed = true;
4676 return null;
4677 }
4678
4679 static extendDefaults(newDefaults) {
4680 extend(extendedDefaults, newDefaults);
4681 }
4682
4683 static get extendedDefaults() {
4684 return extendedDefaults;
4685 }
4686
4687 static get defaults() {
4688 return defaults;
4689 }
4690
4691 static installModule(mod) {
4692 if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = [];
4693 const modules = Swiper.prototype.__modules__;
4694
4695 if (typeof mod === 'function' && modules.indexOf(mod) < 0) {
4696 modules.push(mod);
4697 }
4698 }
4699
4700 static use(module) {
4701 if (Array.isArray(module)) {
4702 module.forEach(m => Swiper.installModule(m));
4703 return Swiper;
4704 }
4705
4706 Swiper.installModule(module);
4707 return Swiper;
4708 }
4709
4710 }
4711
4712 Object.keys(prototypes).forEach(prototypeGroup => {
4713 Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => {
4714 Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
4715 });
4716 });
4717 Swiper.use([Resize, Observer]);
4718
4719 function Virtual({
4720 swiper,
4721 extendParams,
4722 on
4723 }) {
4724 extendParams({
4725 virtual: {
4726 enabled: false,
4727 slides: [],
4728 cache: true,
4729 renderSlide: null,
4730 renderExternal: null,
4731 renderExternalUpdate: true,
4732 addSlidesBefore: 0,
4733 addSlidesAfter: 0
4734 }
4735 });
4736 swiper.virtual = {
4737 cache: {},
4738 from: undefined,
4739 to: undefined,
4740 slides: [],
4741 offset: 0,
4742 slidesGrid: []
4743 };
4744
4745 function renderSlide(slide, index) {
4746 const params = swiper.params.virtual;
4747
4748 if (params.cache && swiper.virtual.cache[index]) {
4749 return swiper.virtual.cache[index];
4750 }
4751
4752 const $slideEl = params.renderSlide ? $(params.renderSlide.call(swiper, slide, index)) : $(`<div class="${swiper.params.slideClass}" data-swiper-slide-index="${index}">${slide}</div>`);
4753 if (!$slideEl.attr('data-swiper-slide-index')) $slideEl.attr('data-swiper-slide-index', index);
4754 if (params.cache) swiper.virtual.cache[index] = $slideEl;
4755 return $slideEl;
4756 }
4757
4758 function update(force) {
4759 const {
4760 slidesPerView,
4761 slidesPerGroup,
4762 centeredSlides
4763 } = swiper.params;
4764 const {
4765 addSlidesBefore,
4766 addSlidesAfter
4767 } = swiper.params.virtual;
4768 const {
4769 from: previousFrom,
4770 to: previousTo,
4771 slides,
4772 slidesGrid: previousSlidesGrid,
4773 offset: previousOffset
4774 } = swiper.virtual;
4775 swiper.updateActiveIndex();
4776 const activeIndex = swiper.activeIndex || 0;
4777 let offsetProp;
4778 if (swiper.rtlTranslate) offsetProp = 'right';else offsetProp = swiper.isHorizontal() ? 'left' : 'top';
4779 let slidesAfter;
4780 let slidesBefore;
4781
4782 if (centeredSlides) {
4783 slidesAfter = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesAfter;
4784 slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;
4785 } else {
4786 slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesAfter;
4787 slidesBefore = slidesPerGroup + addSlidesBefore;
4788 }
4789
4790 const from = Math.max((activeIndex || 0) - slidesBefore, 0);
4791 const to = Math.min((activeIndex || 0) + slidesAfter, slides.length - 1);
4792 const offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
4793 Object.assign(swiper.virtual, {
4794 from,
4795 to,
4796 offset,
4797 slidesGrid: swiper.slidesGrid
4798 });
4799
4800 function onRendered() {
4801 swiper.updateSlides();
4802 swiper.updateProgress();
4803 swiper.updateSlidesClasses();
4804
4805 if (swiper.lazy && swiper.params.lazy.enabled) {
4806 swiper.lazy.load();
4807 }
4808 }
4809
4810 if (previousFrom === from && previousTo === to && !force) {
4811 if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
4812 swiper.slides.css(offsetProp, `${offset}px`);
4813 }
4814
4815 swiper.updateProgress();
4816 return;
4817 }
4818
4819 if (swiper.params.virtual.renderExternal) {
4820 swiper.params.virtual.renderExternal.call(swiper, {
4821 offset,
4822 from,
4823 to,
4824 slides: function getSlides() {
4825 const slidesToRender = [];
4826
4827 for (let i = from; i <= to; i += 1) {
4828 slidesToRender.push(slides[i]);
4829 }
4830
4831 return slidesToRender;
4832 }()
4833 });
4834
4835 if (swiper.params.virtual.renderExternalUpdate) {
4836 onRendered();
4837 }
4838
4839 return;
4840 }
4841
4842 const prependIndexes = [];
4843 const appendIndexes = [];
4844
4845 if (force) {
4846 swiper.$wrapperEl.find(`.${swiper.params.slideClass}`).remove();
4847 } else {
4848 for (let i = previousFrom; i <= previousTo; i += 1) {
4849 if (i < from || i > to) {
4850 swiper.$wrapperEl.find(`.${swiper.params.slideClass}[data-swiper-slide-index="${i}"]`).remove();
4851 }
4852 }
4853 }
4854
4855 for (let i = 0; i < slides.length; i += 1) {
4856 if (i >= from && i <= to) {
4857 if (typeof previousTo === 'undefined' || force) {
4858 appendIndexes.push(i);
4859 } else {
4860 if (i > previousTo) appendIndexes.push(i);
4861 if (i < previousFrom) prependIndexes.push(i);
4862 }
4863 }
4864 }
4865
4866 appendIndexes.forEach(index => {
4867 swiper.$wrapperEl.append(renderSlide(slides[index], index));
4868 });
4869 prependIndexes.sort((a, b) => b - a).forEach(index => {
4870 swiper.$wrapperEl.prepend(renderSlide(slides[index], index));
4871 });
4872 swiper.$wrapperEl.children('.swiper-slide').css(offsetProp, `${offset}px`);
4873 onRendered();
4874 }
4875
4876 function appendSlide(slides) {
4877 if (typeof slides === 'object' && 'length' in slides) {
4878 for (let i = 0; i < slides.length; i += 1) {
4879 if (slides[i]) swiper.virtual.slides.push(slides[i]);
4880 }
4881 } else {
4882 swiper.virtual.slides.push(slides);
4883 }
4884
4885 update(true);
4886 }
4887
4888 function prependSlide(slides) {
4889 const activeIndex = swiper.activeIndex;
4890 let newActiveIndex = activeIndex + 1;
4891 let numberOfNewSlides = 1;
4892
4893 if (Array.isArray(slides)) {
4894 for (let i = 0; i < slides.length; i += 1) {
4895 if (slides[i]) swiper.virtual.slides.unshift(slides[i]);
4896 }
4897
4898 newActiveIndex = activeIndex + slides.length;
4899 numberOfNewSlides = slides.length;
4900 } else {
4901 swiper.virtual.slides.unshift(slides);
4902 }
4903
4904 if (swiper.params.virtual.cache) {
4905 const cache = swiper.virtual.cache;
4906 const newCache = {};
4907 Object.keys(cache).forEach(cachedIndex => {
4908 const $cachedEl = cache[cachedIndex];
4909 const cachedElIndex = $cachedEl.attr('data-swiper-slide-index');
4910
4911 if (cachedElIndex) {
4912 $cachedEl.attr('data-swiper-slide-index', parseInt(cachedElIndex, 10) + 1);
4913 }
4914
4915 newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = $cachedEl;
4916 });
4917 swiper.virtual.cache = newCache;
4918 }
4919
4920 update(true);
4921 swiper.slideTo(newActiveIndex, 0);
4922 }
4923
4924 function removeSlide(slidesIndexes) {
4925 if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return;
4926 let activeIndex = swiper.activeIndex;
4927
4928 if (Array.isArray(slidesIndexes)) {
4929 for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) {
4930 swiper.virtual.slides.splice(slidesIndexes[i], 1);
4931
4932 if (swiper.params.virtual.cache) {
4933 delete swiper.virtual.cache[slidesIndexes[i]];
4934 }
4935
4936 if (slidesIndexes[i] < activeIndex) activeIndex -= 1;
4937 activeIndex = Math.max(activeIndex, 0);
4938 }
4939 } else {
4940 swiper.virtual.slides.splice(slidesIndexes, 1);
4941
4942 if (swiper.params.virtual.cache) {
4943 delete swiper.virtual.cache[slidesIndexes];
4944 }
4945
4946 if (slidesIndexes < activeIndex) activeIndex -= 1;
4947 activeIndex = Math.max(activeIndex, 0);
4948 }
4949
4950 update(true);
4951 swiper.slideTo(activeIndex, 0);
4952 }
4953
4954 function removeAllSlides() {
4955 swiper.virtual.slides = [];
4956
4957 if (swiper.params.virtual.cache) {
4958 swiper.virtual.cache = {};
4959 }
4960
4961 update(true);
4962 swiper.slideTo(0, 0);
4963 }
4964
4965 on('beforeInit', () => {
4966 if (!swiper.params.virtual.enabled) return;
4967 swiper.virtual.slides = swiper.params.virtual.slides;
4968 swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`);
4969 swiper.params.watchSlidesProgress = true;
4970 swiper.originalParams.watchSlidesProgress = true;
4971
4972 if (!swiper.params.initialSlide) {
4973 update();
4974 }
4975 });
4976 on('setTranslate', () => {
4977 if (!swiper.params.virtual.enabled) return;
4978 update();
4979 });
4980 on('init update resize', () => {
4981 if (!swiper.params.virtual.enabled) return;
4982
4983 if (swiper.params.cssMode) {
4984 setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`);
4985 }
4986 });
4987 Object.assign(swiper.virtual, {
4988 appendSlide,
4989 prependSlide,
4990 removeSlide,
4991 removeAllSlides,
4992 update
4993 });
4994 }
4995
4996 /* eslint-disable consistent-return */
4997 function Keyboard({
4998 swiper,
4999 extendParams,
5000 on,
5001 emit
5002 }) {
5003 const document = getDocument();
5004 const window = getWindow();
5005 swiper.keyboard = {
5006 enabled: false
5007 };
5008 extendParams({
5009 keyboard: {
5010 enabled: false,
5011 onlyInViewport: true,
5012 pageUpDown: true
5013 }
5014 });
5015
5016 function handle(event) {
5017 if (!swiper.enabled) return;
5018 const {
5019 rtlTranslate: rtl
5020 } = swiper;
5021 let e = event;
5022 if (e.originalEvent) e = e.originalEvent; // jquery fix
5023
5024 const kc = e.keyCode || e.charCode;
5025 const pageUpDown = swiper.params.keyboard.pageUpDown;
5026 const isPageUp = pageUpDown && kc === 33;
5027 const isPageDown = pageUpDown && kc === 34;
5028 const isArrowLeft = kc === 37;
5029 const isArrowRight = kc === 39;
5030 const isArrowUp = kc === 38;
5031 const isArrowDown = kc === 40; // Directions locks
5032
5033 if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) {
5034 return false;
5035 }
5036
5037 if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) {
5038 return false;
5039 }
5040
5041 if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
5042 return undefined;
5043 }
5044
5045 if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) {
5046 return undefined;
5047 }
5048
5049 if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) {
5050 let inView = false; // Check that swiper should be inside of visible area of window
5051
5052 if (swiper.$el.parents(`.${swiper.params.slideClass}`).length > 0 && swiper.$el.parents(`.${swiper.params.slideActiveClass}`).length === 0) {
5053 return undefined;
5054 }
5055
5056 const $el = swiper.$el;
5057 const swiperWidth = $el[0].clientWidth;
5058 const swiperHeight = $el[0].clientHeight;
5059 const windowWidth = window.innerWidth;
5060 const windowHeight = window.innerHeight;
5061 const swiperOffset = swiper.$el.offset();
5062 if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;
5063 const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiperWidth, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiperHeight], [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight]];
5064
5065 for (let i = 0; i < swiperCoord.length; i += 1) {
5066 const point = swiperCoord[i];
5067
5068 if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) {
5069 if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line
5070
5071 inView = true;
5072 }
5073 }
5074
5075 if (!inView) return undefined;
5076 }
5077
5078 if (swiper.isHorizontal()) {
5079 if (isPageUp || isPageDown || isArrowLeft || isArrowRight) {
5080 if (e.preventDefault) e.preventDefault();else e.returnValue = false;
5081 }
5082
5083 if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext();
5084 if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev();
5085 } else {
5086 if (isPageUp || isPageDown || isArrowUp || isArrowDown) {
5087 if (e.preventDefault) e.preventDefault();else e.returnValue = false;
5088 }
5089
5090 if (isPageDown || isArrowDown) swiper.slideNext();
5091 if (isPageUp || isArrowUp) swiper.slidePrev();
5092 }
5093
5094 emit('keyPress', kc);
5095 return undefined;
5096 }
5097
5098 function enable() {
5099 if (swiper.keyboard.enabled) return;
5100 $(document).on('keydown', handle);
5101 swiper.keyboard.enabled = true;
5102 }
5103
5104 function disable() {
5105 if (!swiper.keyboard.enabled) return;
5106 $(document).off('keydown', handle);
5107 swiper.keyboard.enabled = false;
5108 }
5109
5110 on('init', () => {
5111 if (swiper.params.keyboard.enabled) {
5112 enable();
5113 }
5114 });
5115 on('destroy', () => {
5116 if (swiper.keyboard.enabled) {
5117 disable();
5118 }
5119 });
5120 Object.assign(swiper.keyboard, {
5121 enable,
5122 disable
5123 });
5124 }
5125
5126 /* eslint-disable consistent-return */
5127 function Mousewheel({
5128 swiper,
5129 extendParams,
5130 on,
5131 emit
5132 }) {
5133 const window = getWindow();
5134 extendParams({
5135 mousewheel: {
5136 enabled: false,
5137 releaseOnEdges: false,
5138 invert: false,
5139 forceToAxis: false,
5140 sensitivity: 1,
5141 eventsTarget: 'container',
5142 thresholdDelta: null,
5143 thresholdTime: null
5144 }
5145 });
5146 swiper.mousewheel = {
5147 enabled: false
5148 };
5149 let timeout;
5150 let lastScrollTime = now();
5151 let lastEventBeforeSnap;
5152 const recentWheelEvents = [];
5153
5154 function normalize(e) {
5155 // Reasonable defaults
5156 const PIXEL_STEP = 10;
5157 const LINE_HEIGHT = 40;
5158 const PAGE_HEIGHT = 800;
5159 let sX = 0;
5160 let sY = 0; // spinX, spinY
5161
5162 let pX = 0;
5163 let pY = 0; // pixelX, pixelY
5164 // Legacy
5165
5166 if ('detail' in e) {
5167 sY = e.detail;
5168 }
5169
5170 if ('wheelDelta' in e) {
5171 sY = -e.wheelDelta / 120;
5172 }
5173
5174 if ('wheelDeltaY' in e) {
5175 sY = -e.wheelDeltaY / 120;
5176 }
5177
5178 if ('wheelDeltaX' in e) {
5179 sX = -e.wheelDeltaX / 120;
5180 } // side scrolling on FF with DOMMouseScroll
5181
5182
5183 if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
5184 sX = sY;
5185 sY = 0;
5186 }
5187
5188 pX = sX * PIXEL_STEP;
5189 pY = sY * PIXEL_STEP;
5190
5191 if ('deltaY' in e) {
5192 pY = e.deltaY;
5193 }
5194
5195 if ('deltaX' in e) {
5196 pX = e.deltaX;
5197 }
5198
5199 if (e.shiftKey && !pX) {
5200 // if user scrolls with shift he wants horizontal scroll
5201 pX = pY;
5202 pY = 0;
5203 }
5204
5205 if ((pX || pY) && e.deltaMode) {
5206 if (e.deltaMode === 1) {
5207 // delta in LINE units
5208 pX *= LINE_HEIGHT;
5209 pY *= LINE_HEIGHT;
5210 } else {
5211 // delta in PAGE units
5212 pX *= PAGE_HEIGHT;
5213 pY *= PAGE_HEIGHT;
5214 }
5215 } // Fall-back if spin cannot be determined
5216
5217
5218 if (pX && !sX) {
5219 sX = pX < 1 ? -1 : 1;
5220 }
5221
5222 if (pY && !sY) {
5223 sY = pY < 1 ? -1 : 1;
5224 }
5225
5226 return {
5227 spinX: sX,
5228 spinY: sY,
5229 pixelX: pX,
5230 pixelY: pY
5231 };
5232 }
5233
5234 function handleMouseEnter() {
5235 if (!swiper.enabled) return;
5236 swiper.mouseEntered = true;
5237 }
5238
5239 function handleMouseLeave() {
5240 if (!swiper.enabled) return;
5241 swiper.mouseEntered = false;
5242 }
5243
5244 function animateSlider(newEvent) {
5245 if (swiper.params.mousewheel.thresholdDelta && newEvent.delta < swiper.params.mousewheel.thresholdDelta) {
5246 // Prevent if delta of wheel scroll delta is below configured threshold
5247 return false;
5248 }
5249
5250 if (swiper.params.mousewheel.thresholdTime && now() - lastScrollTime < swiper.params.mousewheel.thresholdTime) {
5251 // Prevent if time between scrolls is below configured threshold
5252 return false;
5253 } // If the movement is NOT big enough and
5254 // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider):
5255 // Don't go any further (avoid insignificant scroll movement).
5256
5257
5258 if (newEvent.delta >= 6 && now() - lastScrollTime < 60) {
5259 // Return false as a default
5260 return true;
5261 } // If user is scrolling towards the end:
5262 // If the slider hasn't hit the latest slide or
5263 // if the slider is a loop and
5264 // if the slider isn't moving right now:
5265 // Go to next slide and
5266 // emit a scroll event.
5267 // Else (the user is scrolling towards the beginning) and
5268 // if the slider hasn't hit the first slide or
5269 // if the slider is a loop and
5270 // if the slider isn't moving right now:
5271 // Go to prev slide and
5272 // emit a scroll event.
5273
5274
5275 if (newEvent.direction < 0) {
5276 if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
5277 swiper.slideNext();
5278 emit('scroll', newEvent.raw);
5279 }
5280 } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
5281 swiper.slidePrev();
5282 emit('scroll', newEvent.raw);
5283 } // If you got here is because an animation has been triggered so store the current time
5284
5285
5286 lastScrollTime = new window.Date().getTime(); // Return false as a default
5287
5288 return false;
5289 }
5290
5291 function releaseScroll(newEvent) {
5292 const params = swiper.params.mousewheel;
5293
5294 if (newEvent.direction < 0) {
5295 if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) {
5296 // Return true to animate scroll on edges
5297 return true;
5298 }
5299 } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) {
5300 // Return true to animate scroll on edges
5301 return true;
5302 }
5303
5304 return false;
5305 }
5306
5307 function handle(event) {
5308 let e = event;
5309 let disableParentSwiper = true;
5310 if (!swiper.enabled) return;
5311 const params = swiper.params.mousewheel;
5312
5313 if (swiper.params.cssMode) {
5314 e.preventDefault();
5315 }
5316
5317 let target = swiper.$el;
5318
5319 if (swiper.params.mousewheel.eventsTarget !== 'container') {
5320 target = $(swiper.params.mousewheel.eventsTarget);
5321 }
5322
5323 if (!swiper.mouseEntered && !target[0].contains(e.target) && !params.releaseOnEdges) return true;
5324 if (e.originalEvent) e = e.originalEvent; // jquery fix
5325
5326 let delta = 0;
5327 const rtlFactor = swiper.rtlTranslate ? -1 : 1;
5328 const data = normalize(e);
5329
5330 if (params.forceToAxis) {
5331 if (swiper.isHorizontal()) {
5332 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true;
5333 } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true;
5334 } else {
5335 delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
5336 }
5337
5338 if (delta === 0) return true;
5339 if (params.invert) delta = -delta; // Get the scroll positions
5340
5341 let positions = swiper.getTranslate() + delta * params.sensitivity;
5342 if (positions >= swiper.minTranslate()) positions = swiper.minTranslate();
5343 if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate(); // When loop is true:
5344 // the disableParentSwiper will be true.
5345 // When loop is false:
5346 // if the scroll positions is not on edge,
5347 // then the disableParentSwiper will be true.
5348 // if the scroll on edge positions,
5349 // then the disableParentSwiper will be false.
5350
5351 disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate());
5352 if (disableParentSwiper && swiper.params.nested) e.stopPropagation();
5353
5354 if (!swiper.params.freeMode || !swiper.params.freeMode.enabled) {
5355 // Register the new event in a variable which stores the relevant data
5356 const newEvent = {
5357 time: now(),
5358 delta: Math.abs(delta),
5359 direction: Math.sign(delta),
5360 raw: event
5361 }; // Keep the most recent events
5362
5363 if (recentWheelEvents.length >= 2) {
5364 recentWheelEvents.shift(); // only store the last N events
5365 }
5366
5367 const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
5368 recentWheelEvents.push(newEvent); // If there is at least one previous recorded event:
5369 // If direction has changed or
5370 // if the scroll is quicker than the previous one:
5371 // Animate the slider.
5372 // Else (this is the first time the wheel is moved):
5373 // Animate the slider.
5374
5375 if (prevEvent) {
5376 if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) {
5377 animateSlider(newEvent);
5378 }
5379 } else {
5380 animateSlider(newEvent);
5381 } // If it's time to release the scroll:
5382 // Return now so you don't hit the preventDefault.
5383
5384
5385 if (releaseScroll(newEvent)) {
5386 return true;
5387 }
5388 } else {
5389 // Freemode or scrollContainer:
5390 // If we recently snapped after a momentum scroll, then ignore wheel events
5391 // to give time for the deceleration to finish. Stop ignoring after 500 msecs
5392 // or if it's a new scroll (larger delta or inverse sign as last event before
5393 // an end-of-momentum snap).
5394 const newEvent = {
5395 time: now(),
5396 delta: Math.abs(delta),
5397 direction: Math.sign(delta)
5398 };
5399 const ignoreWheelEvents = lastEventBeforeSnap && newEvent.time < lastEventBeforeSnap.time + 500 && newEvent.delta <= lastEventBeforeSnap.delta && newEvent.direction === lastEventBeforeSnap.direction;
5400
5401 if (!ignoreWheelEvents) {
5402 lastEventBeforeSnap = undefined;
5403
5404 if (swiper.params.loop) {
5405 swiper.loopFix();
5406 }
5407
5408 let position = swiper.getTranslate() + delta * params.sensitivity;
5409 const wasBeginning = swiper.isBeginning;
5410 const wasEnd = swiper.isEnd;
5411 if (position >= swiper.minTranslate()) position = swiper.minTranslate();
5412 if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();
5413 swiper.setTransition(0);
5414 swiper.setTranslate(position);
5415 swiper.updateProgress();
5416 swiper.updateActiveIndex();
5417 swiper.updateSlidesClasses();
5418
5419 if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) {
5420 swiper.updateSlidesClasses();
5421 }
5422
5423 if (swiper.params.freeMode.sticky) {
5424 // When wheel scrolling starts with sticky (aka snap) enabled, then detect
5425 // the end of a momentum scroll by storing recent (N=15?) wheel events.
5426 // 1. do all N events have decreasing or same (absolute value) delta?
5427 // 2. did all N events arrive in the last M (M=500?) msecs?
5428 // 3. does the earliest event have an (absolute value) delta that's
5429 // at least P (P=1?) larger than the most recent event's delta?
5430 // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels?
5431 // If 1-4 are "yes" then we're near the end of a momentum scroll deceleration.
5432 // Snap immediately and ignore remaining wheel events in this scroll.
5433 // See comment above for "remaining wheel events in this scroll" determination.
5434 // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event.
5435 clearTimeout(timeout);
5436 timeout = undefined;
5437
5438 if (recentWheelEvents.length >= 15) {
5439 recentWheelEvents.shift(); // only store the last N events
5440 }
5441
5442 const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
5443 const firstEvent = recentWheelEvents[0];
5444 recentWheelEvents.push(newEvent);
5445
5446 if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) {
5447 // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log.
5448 recentWheelEvents.splice(0);
5449 } else if (recentWheelEvents.length >= 15 && newEvent.time - firstEvent.time < 500 && firstEvent.delta - newEvent.delta >= 1 && newEvent.delta <= 6) {
5450 // We're at the end of the deceleration of a momentum scroll, so there's no need
5451 // to wait for more events. Snap ASAP on the next tick.
5452 // Also, because there's some remaining momentum we'll bias the snap in the
5453 // direction of the ongoing scroll because it's better UX for the scroll to snap
5454 // in the same direction as the scroll instead of reversing to snap. Therefore,
5455 // if it's already scrolled more than 20% in the current direction, keep going.
5456 const snapToThreshold = delta > 0 ? 0.8 : 0.2;
5457 lastEventBeforeSnap = newEvent;
5458 recentWheelEvents.splice(0);
5459 timeout = nextTick(() => {
5460 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
5461 }, 0); // no delay; move on next tick
5462 }
5463
5464 if (!timeout) {
5465 // if we get here, then we haven't detected the end of a momentum scroll, so
5466 // we'll consider a scroll "complete" when there haven't been any wheel events
5467 // for 500ms.
5468 timeout = nextTick(() => {
5469 const snapToThreshold = 0.5;
5470 lastEventBeforeSnap = newEvent;
5471 recentWheelEvents.splice(0);
5472 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
5473 }, 500);
5474 }
5475 } // Emit event
5476
5477
5478 if (!ignoreWheelEvents) emit('scroll', e); // Stop autoplay
5479
5480 if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) swiper.autoplay.stop(); // Return page scroll on edge positions
5481
5482 if (position === swiper.minTranslate() || position === swiper.maxTranslate()) return true;
5483 }
5484 }
5485
5486 if (e.preventDefault) e.preventDefault();else e.returnValue = false;
5487 return false;
5488 }
5489
5490 function events(method) {
5491 let target = swiper.$el;
5492
5493 if (swiper.params.mousewheel.eventsTarget !== 'container') {
5494 target = $(swiper.params.mousewheel.eventsTarget);
5495 }
5496
5497 target[method]('mouseenter', handleMouseEnter);
5498 target[method]('mouseleave', handleMouseLeave);
5499 target[method]('wheel', handle);
5500 }
5501
5502 function enable() {
5503 if (swiper.params.cssMode) {
5504 swiper.wrapperEl.removeEventListener('wheel', handle);
5505 return true;
5506 }
5507
5508 if (swiper.mousewheel.enabled) return false;
5509 events('on');
5510 swiper.mousewheel.enabled = true;
5511 return true;
5512 }
5513
5514 function disable() {
5515 if (swiper.params.cssMode) {
5516 swiper.wrapperEl.addEventListener(event, handle);
5517 return true;
5518 }
5519
5520 if (!swiper.mousewheel.enabled) return false;
5521 events('off');
5522 swiper.mousewheel.enabled = false;
5523 return true;
5524 }
5525
5526 on('init', () => {
5527 if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
5528 disable();
5529 }
5530
5531 if (swiper.params.mousewheel.enabled) enable();
5532 });
5533 on('destroy', () => {
5534 if (swiper.params.cssMode) {
5535 enable();
5536 }
5537
5538 if (swiper.mousewheel.enabled) disable();
5539 });
5540 Object.assign(swiper.mousewheel, {
5541 enable,
5542 disable
5543 });
5544 }
5545
5546 function createElementIfNotDefined(swiper, originalParams, params, checkProps) {
5547 const document = getDocument();
5548
5549 if (swiper.params.createElements) {
5550 Object.keys(checkProps).forEach(key => {
5551 if (!params[key] && params.auto === true) {
5552 let element = swiper.$el.children(`.${checkProps[key]}`)[0];
5553
5554 if (!element) {
5555 element = document.createElement('div');
5556 element.className = checkProps[key];
5557 swiper.$el.append(element);
5558 }
5559
5560 params[key] = element;
5561 originalParams[key] = element;
5562 }
5563 });
5564 }
5565
5566 return params;
5567 }
5568
5569 function Navigation({
5570 swiper,
5571 extendParams,
5572 on,
5573 emit
5574 }) {
5575 extendParams({
5576 navigation: {
5577 nextEl: null,
5578 prevEl: null,
5579 hideOnClick: false,
5580 disabledClass: 'swiper-button-disabled',
5581 hiddenClass: 'swiper-button-hidden',
5582 lockClass: 'swiper-button-lock'
5583 }
5584 });
5585 swiper.navigation = {
5586 nextEl: null,
5587 $nextEl: null,
5588 prevEl: null,
5589 $prevEl: null
5590 };
5591
5592 function getEl(el) {
5593 let $el;
5594
5595 if (el) {
5596 $el = $(el);
5597
5598 if (swiper.params.uniqueNavElements && typeof el === 'string' && $el.length > 1 && swiper.$el.find(el).length === 1) {
5599 $el = swiper.$el.find(el);
5600 }
5601 }
5602
5603 return $el;
5604 }
5605
5606 function toggleEl($el, disabled) {
5607 const params = swiper.params.navigation;
5608
5609 if ($el && $el.length > 0) {
5610 $el[disabled ? 'addClass' : 'removeClass'](params.disabledClass);
5611 if ($el[0] && $el[0].tagName === 'BUTTON') $el[0].disabled = disabled;
5612
5613 if (swiper.params.watchOverflow && swiper.enabled) {
5614 $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
5615 }
5616 }
5617 }
5618
5619 function update() {
5620 // Update Navigation Buttons
5621 if (swiper.params.loop) return;
5622 const {
5623 $nextEl,
5624 $prevEl
5625 } = swiper.navigation;
5626 toggleEl($prevEl, swiper.isBeginning);
5627 toggleEl($nextEl, swiper.isEnd);
5628 }
5629
5630 function onPrevClick(e) {
5631 e.preventDefault();
5632 if (swiper.isBeginning && !swiper.params.loop) return;
5633 swiper.slidePrev();
5634 }
5635
5636 function onNextClick(e) {
5637 e.preventDefault();
5638 if (swiper.isEnd && !swiper.params.loop) return;
5639 swiper.slideNext();
5640 }
5641
5642 function init() {
5643 const params = swiper.params.navigation;
5644 swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, {
5645 nextEl: 'swiper-button-next',
5646 prevEl: 'swiper-button-prev'
5647 });
5648 if (!(params.nextEl || params.prevEl)) return;
5649 const $nextEl = getEl(params.nextEl);
5650 const $prevEl = getEl(params.prevEl);
5651
5652 if ($nextEl && $nextEl.length > 0) {
5653 $nextEl.on('click', onNextClick);
5654 }
5655
5656 if ($prevEl && $prevEl.length > 0) {
5657 $prevEl.on('click', onPrevClick);
5658 }
5659
5660 Object.assign(swiper.navigation, {
5661 $nextEl,
5662 nextEl: $nextEl && $nextEl[0],
5663 $prevEl,
5664 prevEl: $prevEl && $prevEl[0]
5665 });
5666
5667 if (!swiper.enabled) {
5668 if ($nextEl) $nextEl.addClass(params.lockClass);
5669 if ($prevEl) $prevEl.addClass(params.lockClass);
5670 }
5671 }
5672
5673 function destroy() {
5674 const {
5675 $nextEl,
5676 $prevEl
5677 } = swiper.navigation;
5678
5679 if ($nextEl && $nextEl.length) {
5680 $nextEl.off('click', onNextClick);
5681 $nextEl.removeClass(swiper.params.navigation.disabledClass);
5682 }
5683
5684 if ($prevEl && $prevEl.length) {
5685 $prevEl.off('click', onPrevClick);
5686 $prevEl.removeClass(swiper.params.navigation.disabledClass);
5687 }
5688 }
5689
5690 on('init', () => {
5691 init();
5692 update();
5693 });
5694 on('toEdge fromEdge lock unlock', () => {
5695 update();
5696 });
5697 on('destroy', () => {
5698 destroy();
5699 });
5700 on('enable disable', () => {
5701 const {
5702 $nextEl,
5703 $prevEl
5704 } = swiper.navigation;
5705
5706 if ($nextEl) {
5707 $nextEl[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.navigation.lockClass);
5708 }
5709
5710 if ($prevEl) {
5711 $prevEl[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.navigation.lockClass);
5712 }
5713 });
5714 on('click', (_s, e) => {
5715 const {
5716 $nextEl,
5717 $prevEl
5718 } = swiper.navigation;
5719 const targetEl = e.target;
5720
5721 if (swiper.params.navigation.hideOnClick && !$(targetEl).is($prevEl) && !$(targetEl).is($nextEl)) {
5722 if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
5723 let isHidden;
5724
5725 if ($nextEl) {
5726 isHidden = $nextEl.hasClass(swiper.params.navigation.hiddenClass);
5727 } else if ($prevEl) {
5728 isHidden = $prevEl.hasClass(swiper.params.navigation.hiddenClass);
5729 }
5730
5731 if (isHidden === true) {
5732 emit('navigationShow');
5733 } else {
5734 emit('navigationHide');
5735 }
5736
5737 if ($nextEl) {
5738 $nextEl.toggleClass(swiper.params.navigation.hiddenClass);
5739 }
5740
5741 if ($prevEl) {
5742 $prevEl.toggleClass(swiper.params.navigation.hiddenClass);
5743 }
5744 }
5745 });
5746 Object.assign(swiper.navigation, {
5747 update,
5748 init,
5749 destroy
5750 });
5751 }
5752
5753 function classesToSelector(classes = '') {
5754 return `.${classes.trim().replace(/([\.:!\/])/g, '\\$1') // eslint-disable-line
5755 .replace(/ /g, '.')}`;
5756 }
5757
5758 function Pagination({
5759 swiper,
5760 extendParams,
5761 on,
5762 emit
5763 }) {
5764 const pfx = 'swiper-pagination';
5765 extendParams({
5766 pagination: {
5767 el: null,
5768 bulletElement: 'span',
5769 clickable: false,
5770 hideOnClick: false,
5771 renderBullet: null,
5772 renderProgressbar: null,
5773 renderFraction: null,
5774 renderCustom: null,
5775 progressbarOpposite: false,
5776 type: 'bullets',
5777 // 'bullets' or 'progressbar' or 'fraction' or 'custom'
5778 dynamicBullets: false,
5779 dynamicMainBullets: 1,
5780 formatFractionCurrent: number => number,
5781 formatFractionTotal: number => number,
5782 bulletClass: `${pfx}-bullet`,
5783 bulletActiveClass: `${pfx}-bullet-active`,
5784 modifierClass: `${pfx}-`,
5785 currentClass: `${pfx}-current`,
5786 totalClass: `${pfx}-total`,
5787 hiddenClass: `${pfx}-hidden`,
5788 progressbarFillClass: `${pfx}-progressbar-fill`,
5789 progressbarOppositeClass: `${pfx}-progressbar-opposite`,
5790 clickableClass: `${pfx}-clickable`,
5791 lockClass: `${pfx}-lock`,
5792 horizontalClass: `${pfx}-horizontal`,
5793 verticalClass: `${pfx}-vertical`
5794 }
5795 });
5796 swiper.pagination = {
5797 el: null,
5798 $el: null,
5799 bullets: []
5800 };
5801 let bulletSize;
5802 let dynamicBulletIndex = 0;
5803
5804 function isPaginationDisabled() {
5805 return !swiper.params.pagination.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0;
5806 }
5807
5808 function setSideBullets($bulletEl, position) {
5809 const {
5810 bulletActiveClass
5811 } = swiper.params.pagination;
5812 $bulletEl[position]().addClass(`${bulletActiveClass}-${position}`)[position]().addClass(`${bulletActiveClass}-${position}-${position}`);
5813 }
5814
5815 function update() {
5816 // Render || Update Pagination bullets/items
5817 const rtl = swiper.rtl;
5818 const params = swiper.params.pagination;
5819 if (isPaginationDisabled()) return;
5820 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
5821 const $el = swiper.pagination.$el; // Current/Total
5822
5823 let current;
5824 const total = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
5825
5826 if (swiper.params.loop) {
5827 current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
5828
5829 if (current > slidesLength - 1 - swiper.loopedSlides * 2) {
5830 current -= slidesLength - swiper.loopedSlides * 2;
5831 }
5832
5833 if (current > total - 1) current -= total;
5834 if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
5835 } else if (typeof swiper.snapIndex !== 'undefined') {
5836 current = swiper.snapIndex;
5837 } else {
5838 current = swiper.activeIndex || 0;
5839 } // Types
5840
5841
5842 if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
5843 const bullets = swiper.pagination.bullets;
5844 let firstIndex;
5845 let lastIndex;
5846 let midIndex;
5847
5848 if (params.dynamicBullets) {
5849 bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
5850 $el.css(swiper.isHorizontal() ? 'width' : 'height', `${bulletSize * (params.dynamicMainBullets + 4)}px`);
5851
5852 if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
5853 dynamicBulletIndex += current - swiper.previousIndex;
5854
5855 if (dynamicBulletIndex > params.dynamicMainBullets - 1) {
5856 dynamicBulletIndex = params.dynamicMainBullets - 1;
5857 } else if (dynamicBulletIndex < 0) {
5858 dynamicBulletIndex = 0;
5859 }
5860 }
5861
5862 firstIndex = current - dynamicBulletIndex;
5863 lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
5864 midIndex = (lastIndex + firstIndex) / 2;
5865 }
5866
5867 bullets.removeClass(['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`).join(' '));
5868
5869 if ($el.length > 1) {
5870 bullets.each(bullet => {
5871 const $bullet = $(bullet);
5872 const bulletIndex = $bullet.index();
5873
5874 if (bulletIndex === current) {
5875 $bullet.addClass(params.bulletActiveClass);
5876 }
5877
5878 if (params.dynamicBullets) {
5879 if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
5880 $bullet.addClass(`${params.bulletActiveClass}-main`);
5881 }
5882
5883 if (bulletIndex === firstIndex) {
5884 setSideBullets($bullet, 'prev');
5885 }
5886
5887 if (bulletIndex === lastIndex) {
5888 setSideBullets($bullet, 'next');
5889 }
5890 }
5891 });
5892 } else {
5893 const $bullet = bullets.eq(current);
5894 const bulletIndex = $bullet.index();
5895 $bullet.addClass(params.bulletActiveClass);
5896
5897 if (params.dynamicBullets) {
5898 const $firstDisplayedBullet = bullets.eq(firstIndex);
5899 const $lastDisplayedBullet = bullets.eq(lastIndex);
5900
5901 for (let i = firstIndex; i <= lastIndex; i += 1) {
5902 bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
5903 }
5904
5905 if (swiper.params.loop) {
5906 if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
5907 for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
5908 bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
5909 }
5910
5911 bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(`${params.bulletActiveClass}-prev`);
5912 } else {
5913 setSideBullets($firstDisplayedBullet, 'prev');
5914 setSideBullets($lastDisplayedBullet, 'next');
5915 }
5916 } else {
5917 setSideBullets($firstDisplayedBullet, 'prev');
5918 setSideBullets($lastDisplayedBullet, 'next');
5919 }
5920 }
5921 }
5922
5923 if (params.dynamicBullets) {
5924 const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
5925 const bulletsOffset = (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;
5926 const offsetProp = rtl ? 'right' : 'left';
5927 bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
5928 }
5929 }
5930
5931 if (params.type === 'fraction') {
5932 $el.find(classesToSelector(params.currentClass)).text(params.formatFractionCurrent(current + 1));
5933 $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));
5934 }
5935
5936 if (params.type === 'progressbar') {
5937 let progressbarDirection;
5938
5939 if (params.progressbarOpposite) {
5940 progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
5941 } else {
5942 progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
5943 }
5944
5945 const scale = (current + 1) / total;
5946 let scaleX = 1;
5947 let scaleY = 1;
5948
5949 if (progressbarDirection === 'horizontal') {
5950 scaleX = scale;
5951 } else {
5952 scaleY = scale;
5953 }
5954
5955 $el.find(classesToSelector(params.progressbarFillClass)).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);
5956 }
5957
5958 if (params.type === 'custom' && params.renderCustom) {
5959 $el.html(params.renderCustom(swiper, current + 1, total));
5960 emit('paginationRender', $el[0]);
5961 } else {
5962 emit('paginationUpdate', $el[0]);
5963 }
5964
5965 if (swiper.params.watchOverflow && swiper.enabled) {
5966 $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
5967 }
5968 }
5969
5970 function render() {
5971 // Render Container
5972 const params = swiper.params.pagination;
5973 if (isPaginationDisabled()) return;
5974 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
5975 const $el = swiper.pagination.$el;
5976 let paginationHTML = '';
5977
5978 if (params.type === 'bullets') {
5979 let numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
5980
5981 if (swiper.params.freeMode && swiper.params.freeMode.enabled && !swiper.params.loop && numberOfBullets > slidesLength) {
5982 numberOfBullets = slidesLength;
5983 }
5984
5985 for (let i = 0; i < numberOfBullets; i += 1) {
5986 if (params.renderBullet) {
5987 paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
5988 } else {
5989 paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
5990 }
5991 }
5992
5993 $el.html(paginationHTML);
5994 swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));
5995 }
5996
5997 if (params.type === 'fraction') {
5998 if (params.renderFraction) {
5999 paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
6000 } else {
6001 paginationHTML = `<span class="${params.currentClass}"></span>` + ' / ' + `<span class="${params.totalClass}"></span>`;
6002 }
6003
6004 $el.html(paginationHTML);
6005 }
6006
6007 if (params.type === 'progressbar') {
6008 if (params.renderProgressbar) {
6009 paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
6010 } else {
6011 paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
6012 }
6013
6014 $el.html(paginationHTML);
6015 }
6016
6017 if (params.type !== 'custom') {
6018 emit('paginationRender', swiper.pagination.$el[0]);
6019 }
6020 }
6021
6022 function init() {
6023 swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, {
6024 el: 'swiper-pagination'
6025 });
6026 const params = swiper.params.pagination;
6027 if (!params.el) return;
6028 let $el = $(params.el);
6029 if ($el.length === 0) return;
6030
6031 if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1) {
6032 $el = swiper.$el.find(params.el); // check if it belongs to another nested Swiper
6033
6034 if ($el.length > 1) {
6035 $el = $el.filter(el => {
6036 if ($(el).parents('.swiper')[0] !== swiper.el) return false;
6037 return true;
6038 });
6039 }
6040 }
6041
6042 if (params.type === 'bullets' && params.clickable) {
6043 $el.addClass(params.clickableClass);
6044 }
6045
6046 $el.addClass(params.modifierClass + params.type);
6047 $el.addClass(params.modifierClass + swiper.params.direction);
6048
6049 if (params.type === 'bullets' && params.dynamicBullets) {
6050 $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
6051 dynamicBulletIndex = 0;
6052
6053 if (params.dynamicMainBullets < 1) {
6054 params.dynamicMainBullets = 1;
6055 }
6056 }
6057
6058 if (params.type === 'progressbar' && params.progressbarOpposite) {
6059 $el.addClass(params.progressbarOppositeClass);
6060 }
6061
6062 if (params.clickable) {
6063 $el.on('click', classesToSelector(params.bulletClass), function onClick(e) {
6064 e.preventDefault();
6065 let index = $(this).index() * swiper.params.slidesPerGroup;
6066 if (swiper.params.loop) index += swiper.loopedSlides;
6067 swiper.slideTo(index);
6068 });
6069 }
6070
6071 Object.assign(swiper.pagination, {
6072 $el,
6073 el: $el[0]
6074 });
6075
6076 if (!swiper.enabled) {
6077 $el.addClass(params.lockClass);
6078 }
6079 }
6080
6081 function destroy() {
6082 const params = swiper.params.pagination;
6083 if (isPaginationDisabled()) return;
6084 const $el = swiper.pagination.$el;
6085 $el.removeClass(params.hiddenClass);
6086 $el.removeClass(params.modifierClass + params.type);
6087 $el.removeClass(params.modifierClass + swiper.params.direction);
6088 if (swiper.pagination.bullets && swiper.pagination.bullets.removeClass) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
6089
6090 if (params.clickable) {
6091 $el.off('click', classesToSelector(params.bulletClass));
6092 }
6093 }
6094
6095 on('init', () => {
6096 init();
6097 render();
6098 update();
6099 });
6100 on('activeIndexChange', () => {
6101 if (swiper.params.loop) {
6102 update();
6103 } else if (typeof swiper.snapIndex === 'undefined') {
6104 update();
6105 }
6106 });
6107 on('snapIndexChange', () => {
6108 if (!swiper.params.loop) {
6109 update();
6110 }
6111 });
6112 on('slidesLengthChange', () => {
6113 if (swiper.params.loop) {
6114 render();
6115 update();
6116 }
6117 });
6118 on('snapGridLengthChange', () => {
6119 if (!swiper.params.loop) {
6120 render();
6121 update();
6122 }
6123 });
6124 on('destroy', () => {
6125 destroy();
6126 });
6127 on('enable disable', () => {
6128 const {
6129 $el
6130 } = swiper.pagination;
6131
6132 if ($el) {
6133 $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.pagination.lockClass);
6134 }
6135 });
6136 on('lock unlock', () => {
6137 update();
6138 });
6139 on('click', (_s, e) => {
6140 const targetEl = e.target;
6141 const {
6142 $el
6143 } = swiper.pagination;
6144
6145 if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && $el.length > 0 && !$(targetEl).hasClass(swiper.params.pagination.bulletClass)) {
6146 if (swiper.navigation && (swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl || swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl)) return;
6147 const isHidden = $el.hasClass(swiper.params.pagination.hiddenClass);
6148
6149 if (isHidden === true) {
6150 emit('paginationShow');
6151 } else {
6152 emit('paginationHide');
6153 }
6154
6155 $el.toggleClass(swiper.params.pagination.hiddenClass);
6156 }
6157 });
6158 Object.assign(swiper.pagination, {
6159 render,
6160 update,
6161 init,
6162 destroy
6163 });
6164 }
6165
6166 function Scrollbar({
6167 swiper,
6168 extendParams,
6169 on,
6170 emit
6171 }) {
6172 const document = getDocument();
6173 let isTouched = false;
6174 let timeout = null;
6175 let dragTimeout = null;
6176 let dragStartPos;
6177 let dragSize;
6178 let trackSize;
6179 let divider;
6180 extendParams({
6181 scrollbar: {
6182 el: null,
6183 dragSize: 'auto',
6184 hide: false,
6185 draggable: false,
6186 snapOnRelease: true,
6187 lockClass: 'swiper-scrollbar-lock',
6188 dragClass: 'swiper-scrollbar-drag'
6189 }
6190 });
6191 swiper.scrollbar = {
6192 el: null,
6193 dragEl: null,
6194 $el: null,
6195 $dragEl: null
6196 };
6197
6198 function setTranslate() {
6199 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
6200 const {
6201 scrollbar,
6202 rtlTranslate: rtl,
6203 progress
6204 } = swiper;
6205 const {
6206 $dragEl,
6207 $el
6208 } = scrollbar;
6209 const params = swiper.params.scrollbar;
6210 let newSize = dragSize;
6211 let newPos = (trackSize - dragSize) * progress;
6212
6213 if (rtl) {
6214 newPos = -newPos;
6215
6216 if (newPos > 0) {
6217 newSize = dragSize - newPos;
6218 newPos = 0;
6219 } else if (-newPos + dragSize > trackSize) {
6220 newSize = trackSize + newPos;
6221 }
6222 } else if (newPos < 0) {
6223 newSize = dragSize + newPos;
6224 newPos = 0;
6225 } else if (newPos + dragSize > trackSize) {
6226 newSize = trackSize - newPos;
6227 }
6228
6229 if (swiper.isHorizontal()) {
6230 $dragEl.transform(`translate3d(${newPos}px, 0, 0)`);
6231 $dragEl[0].style.width = `${newSize}px`;
6232 } else {
6233 $dragEl.transform(`translate3d(0px, ${newPos}px, 0)`);
6234 $dragEl[0].style.height = `${newSize}px`;
6235 }
6236
6237 if (params.hide) {
6238 clearTimeout(timeout);
6239 $el[0].style.opacity = 1;
6240 timeout = setTimeout(() => {
6241 $el[0].style.opacity = 0;
6242 $el.transition(400);
6243 }, 1000);
6244 }
6245 }
6246
6247 function setTransition(duration) {
6248 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
6249 swiper.scrollbar.$dragEl.transition(duration);
6250 }
6251
6252 function updateSize() {
6253 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
6254 const {
6255 scrollbar
6256 } = swiper;
6257 const {
6258 $dragEl,
6259 $el
6260 } = scrollbar;
6261 $dragEl[0].style.width = '';
6262 $dragEl[0].style.height = '';
6263 trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;
6264 divider = swiper.size / (swiper.virtualSize + swiper.params.slidesOffsetBefore - (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0));
6265
6266 if (swiper.params.scrollbar.dragSize === 'auto') {
6267 dragSize = trackSize * divider;
6268 } else {
6269 dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
6270 }
6271
6272 if (swiper.isHorizontal()) {
6273 $dragEl[0].style.width = `${dragSize}px`;
6274 } else {
6275 $dragEl[0].style.height = `${dragSize}px`;
6276 }
6277
6278 if (divider >= 1) {
6279 $el[0].style.display = 'none';
6280 } else {
6281 $el[0].style.display = '';
6282 }
6283
6284 if (swiper.params.scrollbar.hide) {
6285 $el[0].style.opacity = 0;
6286 }
6287
6288 if (swiper.params.watchOverflow && swiper.enabled) {
6289 scrollbar.$el[swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);
6290 }
6291 }
6292
6293 function getPointerPosition(e) {
6294 if (swiper.isHorizontal()) {
6295 return e.type === 'touchstart' || e.type === 'touchmove' ? e.targetTouches[0].clientX : e.clientX;
6296 }
6297
6298 return e.type === 'touchstart' || e.type === 'touchmove' ? e.targetTouches[0].clientY : e.clientY;
6299 }
6300
6301 function setDragPosition(e) {
6302 const {
6303 scrollbar,
6304 rtlTranslate: rtl
6305 } = swiper;
6306 const {
6307 $el
6308 } = scrollbar;
6309 let positionRatio;
6310 positionRatio = (getPointerPosition(e) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top'] - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
6311 positionRatio = Math.max(Math.min(positionRatio, 1), 0);
6312
6313 if (rtl) {
6314 positionRatio = 1 - positionRatio;
6315 }
6316
6317 const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio;
6318 swiper.updateProgress(position);
6319 swiper.setTranslate(position);
6320 swiper.updateActiveIndex();
6321 swiper.updateSlidesClasses();
6322 }
6323
6324 function onDragStart(e) {
6325 const params = swiper.params.scrollbar;
6326 const {
6327 scrollbar,
6328 $wrapperEl
6329 } = swiper;
6330 const {
6331 $el,
6332 $dragEl
6333 } = scrollbar;
6334 isTouched = true;
6335 dragStartPos = e.target === $dragEl[0] || e.target === $dragEl ? getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
6336 e.preventDefault();
6337 e.stopPropagation();
6338 $wrapperEl.transition(100);
6339 $dragEl.transition(100);
6340 setDragPosition(e);
6341 clearTimeout(dragTimeout);
6342 $el.transition(0);
6343
6344 if (params.hide) {
6345 $el.css('opacity', 1);
6346 }
6347
6348 if (swiper.params.cssMode) {
6349 swiper.$wrapperEl.css('scroll-snap-type', 'none');
6350 }
6351
6352 emit('scrollbarDragStart', e);
6353 }
6354
6355 function onDragMove(e) {
6356 const {
6357 scrollbar,
6358 $wrapperEl
6359 } = swiper;
6360 const {
6361 $el,
6362 $dragEl
6363 } = scrollbar;
6364 if (!isTouched) return;
6365 if (e.preventDefault) e.preventDefault();else e.returnValue = false;
6366 setDragPosition(e);
6367 $wrapperEl.transition(0);
6368 $el.transition(0);
6369 $dragEl.transition(0);
6370 emit('scrollbarDragMove', e);
6371 }
6372
6373 function onDragEnd(e) {
6374 const params = swiper.params.scrollbar;
6375 const {
6376 scrollbar,
6377 $wrapperEl
6378 } = swiper;
6379 const {
6380 $el
6381 } = scrollbar;
6382 if (!isTouched) return;
6383 isTouched = false;
6384
6385 if (swiper.params.cssMode) {
6386 swiper.$wrapperEl.css('scroll-snap-type', '');
6387 $wrapperEl.transition('');
6388 }
6389
6390 if (params.hide) {
6391 clearTimeout(dragTimeout);
6392 dragTimeout = nextTick(() => {
6393 $el.css('opacity', 0);
6394 $el.transition(400);
6395 }, 1000);
6396 }
6397
6398 emit('scrollbarDragEnd', e);
6399
6400 if (params.snapOnRelease) {
6401 swiper.slideToClosest();
6402 }
6403 }
6404
6405 function events(method) {
6406 const {
6407 scrollbar,
6408 touchEventsTouch,
6409 touchEventsDesktop,
6410 params,
6411 support
6412 } = swiper;
6413 const $el = scrollbar.$el;
6414 const target = $el[0];
6415 const activeListener = support.passiveListener && params.passiveListeners ? {
6416 passive: false,
6417 capture: false
6418 } : false;
6419 const passiveListener = support.passiveListener && params.passiveListeners ? {
6420 passive: true,
6421 capture: false
6422 } : false;
6423 if (!target) return;
6424 const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
6425
6426 if (!support.touch) {
6427 target[eventMethod](touchEventsDesktop.start, onDragStart, activeListener);
6428 document[eventMethod](touchEventsDesktop.move, onDragMove, activeListener);
6429 document[eventMethod](touchEventsDesktop.end, onDragEnd, passiveListener);
6430 } else {
6431 target[eventMethod](touchEventsTouch.start, onDragStart, activeListener);
6432 target[eventMethod](touchEventsTouch.move, onDragMove, activeListener);
6433 target[eventMethod](touchEventsTouch.end, onDragEnd, passiveListener);
6434 }
6435 }
6436
6437 function enableDraggable() {
6438 if (!swiper.params.scrollbar.el) return;
6439 events('on');
6440 }
6441
6442 function disableDraggable() {
6443 if (!swiper.params.scrollbar.el) return;
6444 events('off');
6445 }
6446
6447 function init() {
6448 const {
6449 scrollbar,
6450 $el: $swiperEl
6451 } = swiper;
6452 swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, {
6453 el: 'swiper-scrollbar'
6454 });
6455 const params = swiper.params.scrollbar;
6456 if (!params.el) return;
6457 let $el = $(params.el);
6458
6459 if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {
6460 $el = $swiperEl.find(params.el);
6461 }
6462
6463 let $dragEl = $el.find(`.${swiper.params.scrollbar.dragClass}`);
6464
6465 if ($dragEl.length === 0) {
6466 $dragEl = $(`<div class="${swiper.params.scrollbar.dragClass}"></div>`);
6467 $el.append($dragEl);
6468 }
6469
6470 Object.assign(scrollbar, {
6471 $el,
6472 el: $el[0],
6473 $dragEl,
6474 dragEl: $dragEl[0]
6475 });
6476
6477 if (params.draggable) {
6478 enableDraggable();
6479 }
6480
6481 if ($el) {
6482 $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.scrollbar.lockClass);
6483 }
6484 }
6485
6486 function destroy() {
6487 disableDraggable();
6488 }
6489
6490 on('init', () => {
6491 init();
6492 updateSize();
6493 setTranslate();
6494 });
6495 on('update resize observerUpdate lock unlock', () => {
6496 updateSize();
6497 });
6498 on('setTranslate', () => {
6499 setTranslate();
6500 });
6501 on('setTransition', (_s, duration) => {
6502 setTransition(duration);
6503 });
6504 on('enable disable', () => {
6505 const {
6506 $el
6507 } = swiper.scrollbar;
6508
6509 if ($el) {
6510 $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.scrollbar.lockClass);
6511 }
6512 });
6513 on('destroy', () => {
6514 destroy();
6515 });
6516 Object.assign(swiper.scrollbar, {
6517 updateSize,
6518 setTranslate,
6519 init,
6520 destroy
6521 });
6522 }
6523
6524 function Parallax({
6525 swiper,
6526 extendParams,
6527 on
6528 }) {
6529 extendParams({
6530 parallax: {
6531 enabled: false
6532 }
6533 });
6534
6535 const setTransform = (el, progress) => {
6536 const {
6537 rtl
6538 } = swiper;
6539 const $el = $(el);
6540 const rtlFactor = rtl ? -1 : 1;
6541 const p = $el.attr('data-swiper-parallax') || '0';
6542 let x = $el.attr('data-swiper-parallax-x');
6543 let y = $el.attr('data-swiper-parallax-y');
6544 const scale = $el.attr('data-swiper-parallax-scale');
6545 const opacity = $el.attr('data-swiper-parallax-opacity');
6546
6547 if (x || y) {
6548 x = x || '0';
6549 y = y || '0';
6550 } else if (swiper.isHorizontal()) {
6551 x = p;
6552 y = '0';
6553 } else {
6554 y = p;
6555 x = '0';
6556 }
6557
6558 if (x.indexOf('%') >= 0) {
6559 x = `${parseInt(x, 10) * progress * rtlFactor}%`;
6560 } else {
6561 x = `${x * progress * rtlFactor}px`;
6562 }
6563
6564 if (y.indexOf('%') >= 0) {
6565 y = `${parseInt(y, 10) * progress}%`;
6566 } else {
6567 y = `${y * progress}px`;
6568 }
6569
6570 if (typeof opacity !== 'undefined' && opacity !== null) {
6571 const currentOpacity = opacity - (opacity - 1) * (1 - Math.abs(progress));
6572 $el[0].style.opacity = currentOpacity;
6573 }
6574
6575 if (typeof scale === 'undefined' || scale === null) {
6576 $el.transform(`translate3d(${x}, ${y}, 0px)`);
6577 } else {
6578 const currentScale = scale - (scale - 1) * (1 - Math.abs(progress));
6579 $el.transform(`translate3d(${x}, ${y}, 0px) scale(${currentScale})`);
6580 }
6581 };
6582
6583 const setTranslate = () => {
6584 const {
6585 $el,
6586 slides,
6587 progress,
6588 snapGrid
6589 } = swiper;
6590 $el.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(el => {
6591 setTransform(el, progress);
6592 });
6593 slides.each((slideEl, slideIndex) => {
6594 let slideProgress = slideEl.progress;
6595
6596 if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {
6597 slideProgress += Math.ceil(slideIndex / 2) - progress * (snapGrid.length - 1);
6598 }
6599
6600 slideProgress = Math.min(Math.max(slideProgress, -1), 1);
6601 $(slideEl).find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(el => {
6602 setTransform(el, slideProgress);
6603 });
6604 });
6605 };
6606
6607 const setTransition = (duration = swiper.params.speed) => {
6608 const {
6609 $el
6610 } = swiper;
6611 $el.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(parallaxEl => {
6612 const $parallaxEl = $(parallaxEl);
6613 let parallaxDuration = parseInt($parallaxEl.attr('data-swiper-parallax-duration'), 10) || duration;
6614 if (duration === 0) parallaxDuration = 0;
6615 $parallaxEl.transition(parallaxDuration);
6616 });
6617 };
6618
6619 on('beforeInit', () => {
6620 if (!swiper.params.parallax.enabled) return;
6621 swiper.params.watchSlidesProgress = true;
6622 swiper.originalParams.watchSlidesProgress = true;
6623 });
6624 on('init', () => {
6625 if (!swiper.params.parallax.enabled) return;
6626 setTranslate();
6627 });
6628 on('setTranslate', () => {
6629 if (!swiper.params.parallax.enabled) return;
6630 setTranslate();
6631 });
6632 on('setTransition', (_swiper, duration) => {
6633 if (!swiper.params.parallax.enabled) return;
6634 setTransition(duration);
6635 });
6636 }
6637
6638 function Zoom({
6639 swiper,
6640 extendParams,
6641 on,
6642 emit
6643 }) {
6644 const window = getWindow();
6645 extendParams({
6646 zoom: {
6647 enabled: false,
6648 maxRatio: 3,
6649 minRatio: 1,
6650 toggle: true,
6651 containerClass: 'swiper-zoom-container',
6652 zoomedSlideClass: 'swiper-slide-zoomed'
6653 }
6654 });
6655 swiper.zoom = {
6656 enabled: false
6657 };
6658 let currentScale = 1;
6659 let isScaling = false;
6660 let gesturesEnabled;
6661 let fakeGestureTouched;
6662 let fakeGestureMoved;
6663 const gesture = {
6664 $slideEl: undefined,
6665 slideWidth: undefined,
6666 slideHeight: undefined,
6667 $imageEl: undefined,
6668 $imageWrapEl: undefined,
6669 maxRatio: 3
6670 };
6671 const image = {
6672 isTouched: undefined,
6673 isMoved: undefined,
6674 currentX: undefined,
6675 currentY: undefined,
6676 minX: undefined,
6677 minY: undefined,
6678 maxX: undefined,
6679 maxY: undefined,
6680 width: undefined,
6681 height: undefined,
6682 startX: undefined,
6683 startY: undefined,
6684 touchesStart: {},
6685 touchesCurrent: {}
6686 };
6687 const velocity = {
6688 x: undefined,
6689 y: undefined,
6690 prevPositionX: undefined,
6691 prevPositionY: undefined,
6692 prevTime: undefined
6693 };
6694 let scale = 1;
6695 Object.defineProperty(swiper.zoom, 'scale', {
6696 get() {
6697 return scale;
6698 },
6699
6700 set(value) {
6701 if (scale !== value) {
6702 const imageEl = gesture.$imageEl ? gesture.$imageEl[0] : undefined;
6703 const slideEl = gesture.$slideEl ? gesture.$slideEl[0] : undefined;
6704 emit('zoomChange', value, imageEl, slideEl);
6705 }
6706
6707 scale = value;
6708 }
6709
6710 });
6711
6712 function getDistanceBetweenTouches(e) {
6713 if (e.targetTouches.length < 2) return 1;
6714 const x1 = e.targetTouches[0].pageX;
6715 const y1 = e.targetTouches[0].pageY;
6716 const x2 = e.targetTouches[1].pageX;
6717 const y2 = e.targetTouches[1].pageY;
6718 const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
6719 return distance;
6720 } // Events
6721
6722
6723 function onGestureStart(e) {
6724 const support = swiper.support;
6725 const params = swiper.params.zoom;
6726 fakeGestureTouched = false;
6727 fakeGestureMoved = false;
6728
6729 if (!support.gestures) {
6730 if (e.type !== 'touchstart' || e.type === 'touchstart' && e.targetTouches.length < 2) {
6731 return;
6732 }
6733
6734 fakeGestureTouched = true;
6735 gesture.scaleStart = getDistanceBetweenTouches(e);
6736 }
6737
6738 if (!gesture.$slideEl || !gesture.$slideEl.length) {
6739 gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);
6740 if (gesture.$slideEl.length === 0) gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
6741 gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('img, svg, canvas, picture, .swiper-zoom-target');
6742 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
6743 gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
6744
6745 if (gesture.$imageWrapEl.length === 0) {
6746 gesture.$imageEl = undefined;
6747 return;
6748 }
6749 }
6750
6751 if (gesture.$imageEl) {
6752 gesture.$imageEl.transition(0);
6753 }
6754
6755 isScaling = true;
6756 }
6757
6758 function onGestureChange(e) {
6759 const support = swiper.support;
6760 const params = swiper.params.zoom;
6761 const zoom = swiper.zoom;
6762
6763 if (!support.gestures) {
6764 if (e.type !== 'touchmove' || e.type === 'touchmove' && e.targetTouches.length < 2) {
6765 return;
6766 }
6767
6768 fakeGestureMoved = true;
6769 gesture.scaleMove = getDistanceBetweenTouches(e);
6770 }
6771
6772 if (!gesture.$imageEl || gesture.$imageEl.length === 0) {
6773 if (e.type === 'gesturechange') onGestureStart(e);
6774 return;
6775 }
6776
6777 if (support.gestures) {
6778 zoom.scale = e.scale * currentScale;
6779 } else {
6780 zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale;
6781 }
6782
6783 if (zoom.scale > gesture.maxRatio) {
6784 zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5;
6785 }
6786
6787 if (zoom.scale < params.minRatio) {
6788 zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5;
6789 }
6790
6791 gesture.$imageEl.transform(`translate3d(0,0,0) scale(${zoom.scale})`);
6792 }
6793
6794 function onGestureEnd(e) {
6795 const device = swiper.device;
6796 const support = swiper.support;
6797 const params = swiper.params.zoom;
6798 const zoom = swiper.zoom;
6799
6800 if (!support.gestures) {
6801 if (!fakeGestureTouched || !fakeGestureMoved) {
6802 return;
6803 }
6804
6805 if (e.type !== 'touchend' || e.type === 'touchend' && e.changedTouches.length < 2 && !device.android) {
6806 return;
6807 }
6808
6809 fakeGestureTouched = false;
6810 fakeGestureMoved = false;
6811 }
6812
6813 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6814 zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
6815 gesture.$imageEl.transition(swiper.params.speed).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
6816 currentScale = zoom.scale;
6817 isScaling = false;
6818 if (zoom.scale === 1) gesture.$slideEl = undefined;
6819 }
6820
6821 function onTouchStart(e) {
6822 const device = swiper.device;
6823 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6824 if (image.isTouched) return;
6825 if (device.android && e.cancelable) e.preventDefault();
6826 image.isTouched = true;
6827 image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
6828 image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
6829 }
6830
6831 function onTouchMove(e) {
6832 const zoom = swiper.zoom;
6833 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6834 swiper.allowClick = false;
6835 if (!image.isTouched || !gesture.$slideEl) return;
6836
6837 if (!image.isMoved) {
6838 image.width = gesture.$imageEl[0].offsetWidth;
6839 image.height = gesture.$imageEl[0].offsetHeight;
6840 image.startX = getTranslate(gesture.$imageWrapEl[0], 'x') || 0;
6841 image.startY = getTranslate(gesture.$imageWrapEl[0], 'y') || 0;
6842 gesture.slideWidth = gesture.$slideEl[0].offsetWidth;
6843 gesture.slideHeight = gesture.$slideEl[0].offsetHeight;
6844 gesture.$imageWrapEl.transition(0);
6845 } // Define if we need image drag
6846
6847
6848 const scaledWidth = image.width * zoom.scale;
6849 const scaledHeight = image.height * zoom.scale;
6850 if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) return;
6851 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
6852 image.maxX = -image.minX;
6853 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
6854 image.maxY = -image.minY;
6855 image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
6856 image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
6857
6858 if (!image.isMoved && !isScaling) {
6859 if (swiper.isHorizontal() && (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x || Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)) {
6860 image.isTouched = false;
6861 return;
6862 }
6863
6864 if (!swiper.isHorizontal() && (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y || Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)) {
6865 image.isTouched = false;
6866 return;
6867 }
6868 }
6869
6870 if (e.cancelable) {
6871 e.preventDefault();
6872 }
6873
6874 e.stopPropagation();
6875 image.isMoved = true;
6876 image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX;
6877 image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY;
6878
6879 if (image.currentX < image.minX) {
6880 image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8;
6881 }
6882
6883 if (image.currentX > image.maxX) {
6884 image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8;
6885 }
6886
6887 if (image.currentY < image.minY) {
6888 image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8;
6889 }
6890
6891 if (image.currentY > image.maxY) {
6892 image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8;
6893 } // Velocity
6894
6895
6896 if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x;
6897 if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y;
6898 if (!velocity.prevTime) velocity.prevTime = Date.now();
6899 velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
6900 velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
6901 if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0;
6902 if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0;
6903 velocity.prevPositionX = image.touchesCurrent.x;
6904 velocity.prevPositionY = image.touchesCurrent.y;
6905 velocity.prevTime = Date.now();
6906 gesture.$imageWrapEl.transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
6907 }
6908
6909 function onTouchEnd() {
6910 const zoom = swiper.zoom;
6911 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6912
6913 if (!image.isTouched || !image.isMoved) {
6914 image.isTouched = false;
6915 image.isMoved = false;
6916 return;
6917 }
6918
6919 image.isTouched = false;
6920 image.isMoved = false;
6921 let momentumDurationX = 300;
6922 let momentumDurationY = 300;
6923 const momentumDistanceX = velocity.x * momentumDurationX;
6924 const newPositionX = image.currentX + momentumDistanceX;
6925 const momentumDistanceY = velocity.y * momentumDurationY;
6926 const newPositionY = image.currentY + momentumDistanceY; // Fix duration
6927
6928 if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x);
6929 if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y);
6930 const momentumDuration = Math.max(momentumDurationX, momentumDurationY);
6931 image.currentX = newPositionX;
6932 image.currentY = newPositionY; // Define if we need image drag
6933
6934 const scaledWidth = image.width * zoom.scale;
6935 const scaledHeight = image.height * zoom.scale;
6936 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
6937 image.maxX = -image.minX;
6938 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
6939 image.maxY = -image.minY;
6940 image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
6941 image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
6942 gesture.$imageWrapEl.transition(momentumDuration).transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
6943 }
6944
6945 function onTransitionEnd() {
6946 const zoom = swiper.zoom;
6947
6948 if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {
6949 if (gesture.$imageEl) {
6950 gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');
6951 }
6952
6953 if (gesture.$imageWrapEl) {
6954 gesture.$imageWrapEl.transform('translate3d(0,0,0)');
6955 }
6956
6957 zoom.scale = 1;
6958 currentScale = 1;
6959 gesture.$slideEl = undefined;
6960 gesture.$imageEl = undefined;
6961 gesture.$imageWrapEl = undefined;
6962 }
6963 }
6964
6965 function zoomIn(e) {
6966 const zoom = swiper.zoom;
6967 const params = swiper.params.zoom;
6968
6969 if (!gesture.$slideEl) {
6970 if (e && e.target) {
6971 gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);
6972 }
6973
6974 if (!gesture.$slideEl) {
6975 if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
6976 gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);
6977 } else {
6978 gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
6979 }
6980 }
6981
6982 gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('img, svg, canvas, picture, .swiper-zoom-target');
6983 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
6984 }
6985
6986 if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;
6987
6988 if (swiper.params.cssMode) {
6989 swiper.wrapperEl.style.overflow = 'hidden';
6990 swiper.wrapperEl.style.touchAction = 'none';
6991 }
6992
6993 gesture.$slideEl.addClass(`${params.zoomedSlideClass}`);
6994 let touchX;
6995 let touchY;
6996 let offsetX;
6997 let offsetY;
6998 let diffX;
6999 let diffY;
7000 let translateX;
7001 let translateY;
7002 let imageWidth;
7003 let imageHeight;
7004 let scaledWidth;
7005 let scaledHeight;
7006 let translateMinX;
7007 let translateMinY;
7008 let translateMaxX;
7009 let translateMaxY;
7010 let slideWidth;
7011 let slideHeight;
7012
7013 if (typeof image.touchesStart.x === 'undefined' && e) {
7014 touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
7015 touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
7016 } else {
7017 touchX = image.touchesStart.x;
7018 touchY = image.touchesStart.y;
7019 }
7020
7021 zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
7022 currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
7023
7024 if (e) {
7025 slideWidth = gesture.$slideEl[0].offsetWidth;
7026 slideHeight = gesture.$slideEl[0].offsetHeight;
7027 offsetX = gesture.$slideEl.offset().left + window.scrollX;
7028 offsetY = gesture.$slideEl.offset().top + window.scrollY;
7029 diffX = offsetX + slideWidth / 2 - touchX;
7030 diffY = offsetY + slideHeight / 2 - touchY;
7031 imageWidth = gesture.$imageEl[0].offsetWidth;
7032 imageHeight = gesture.$imageEl[0].offsetHeight;
7033 scaledWidth = imageWidth * zoom.scale;
7034 scaledHeight = imageHeight * zoom.scale;
7035 translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);
7036 translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);
7037 translateMaxX = -translateMinX;
7038 translateMaxY = -translateMinY;
7039 translateX = diffX * zoom.scale;
7040 translateY = diffY * zoom.scale;
7041
7042 if (translateX < translateMinX) {
7043 translateX = translateMinX;
7044 }
7045
7046 if (translateX > translateMaxX) {
7047 translateX = translateMaxX;
7048 }
7049
7050 if (translateY < translateMinY) {
7051 translateY = translateMinY;
7052 }
7053
7054 if (translateY > translateMaxY) {
7055 translateY = translateMaxY;
7056 }
7057 } else {
7058 translateX = 0;
7059 translateY = 0;
7060 }
7061
7062 gesture.$imageWrapEl.transition(300).transform(`translate3d(${translateX}px, ${translateY}px,0)`);
7063 gesture.$imageEl.transition(300).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
7064 }
7065
7066 function zoomOut() {
7067 const zoom = swiper.zoom;
7068 const params = swiper.params.zoom;
7069
7070 if (!gesture.$slideEl) {
7071 if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
7072 gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);
7073 } else {
7074 gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
7075 }
7076
7077 gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('img, svg, canvas, picture, .swiper-zoom-target');
7078 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
7079 }
7080
7081 if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;
7082
7083 if (swiper.params.cssMode) {
7084 swiper.wrapperEl.style.overflow = '';
7085 swiper.wrapperEl.style.touchAction = '';
7086 }
7087
7088 zoom.scale = 1;
7089 currentScale = 1;
7090 gesture.$imageWrapEl.transition(300).transform('translate3d(0,0,0)');
7091 gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');
7092 gesture.$slideEl.removeClass(`${params.zoomedSlideClass}`);
7093 gesture.$slideEl = undefined;
7094 } // Toggle Zoom
7095
7096
7097 function zoomToggle(e) {
7098 const zoom = swiper.zoom;
7099
7100 if (zoom.scale && zoom.scale !== 1) {
7101 // Zoom Out
7102 zoomOut();
7103 } else {
7104 // Zoom In
7105 zoomIn(e);
7106 }
7107 }
7108
7109 function getListeners() {
7110 const support = swiper.support;
7111 const passiveListener = swiper.touchEvents.start === 'touchstart' && support.passiveListener && swiper.params.passiveListeners ? {
7112 passive: true,
7113 capture: false
7114 } : false;
7115 const activeListenerWithCapture = support.passiveListener ? {
7116 passive: false,
7117 capture: true
7118 } : true;
7119 return {
7120 passiveListener,
7121 activeListenerWithCapture
7122 };
7123 }
7124
7125 function getSlideSelector() {
7126 return `.${swiper.params.slideClass}`;
7127 }
7128
7129 function toggleGestures(method) {
7130 const {
7131 passiveListener
7132 } = getListeners();
7133 const slideSelector = getSlideSelector();
7134 swiper.$wrapperEl[method]('gesturestart', slideSelector, onGestureStart, passiveListener);
7135 swiper.$wrapperEl[method]('gesturechange', slideSelector, onGestureChange, passiveListener);
7136 swiper.$wrapperEl[method]('gestureend', slideSelector, onGestureEnd, passiveListener);
7137 }
7138
7139 function enableGestures() {
7140 if (gesturesEnabled) return;
7141 gesturesEnabled = true;
7142 toggleGestures('on');
7143 }
7144
7145 function disableGestures() {
7146 if (!gesturesEnabled) return;
7147 gesturesEnabled = false;
7148 toggleGestures('off');
7149 } // Attach/Detach Events
7150
7151
7152 function enable() {
7153 const zoom = swiper.zoom;
7154 if (zoom.enabled) return;
7155 zoom.enabled = true;
7156 const support = swiper.support;
7157 const {
7158 passiveListener,
7159 activeListenerWithCapture
7160 } = getListeners();
7161 const slideSelector = getSlideSelector(); // Scale image
7162
7163 if (support.gestures) {
7164 swiper.$wrapperEl.on(swiper.touchEvents.start, enableGestures, passiveListener);
7165 swiper.$wrapperEl.on(swiper.touchEvents.end, disableGestures, passiveListener);
7166 } else if (swiper.touchEvents.start === 'touchstart') {
7167 swiper.$wrapperEl.on(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);
7168 swiper.$wrapperEl.on(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);
7169 swiper.$wrapperEl.on(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);
7170
7171 if (swiper.touchEvents.cancel) {
7172 swiper.$wrapperEl.on(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);
7173 }
7174 } // Move image
7175
7176
7177 swiper.$wrapperEl.on(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);
7178 }
7179
7180 function disable() {
7181 const zoom = swiper.zoom;
7182 if (!zoom.enabled) return;
7183 const support = swiper.support;
7184 zoom.enabled = false;
7185 const {
7186 passiveListener,
7187 activeListenerWithCapture
7188 } = getListeners();
7189 const slideSelector = getSlideSelector(); // Scale image
7190
7191 if (support.gestures) {
7192 swiper.$wrapperEl.off(swiper.touchEvents.start, enableGestures, passiveListener);
7193 swiper.$wrapperEl.off(swiper.touchEvents.end, disableGestures, passiveListener);
7194 } else if (swiper.touchEvents.start === 'touchstart') {
7195 swiper.$wrapperEl.off(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);
7196 swiper.$wrapperEl.off(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);
7197 swiper.$wrapperEl.off(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);
7198
7199 if (swiper.touchEvents.cancel) {
7200 swiper.$wrapperEl.off(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);
7201 }
7202 } // Move image
7203
7204
7205 swiper.$wrapperEl.off(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);
7206 }
7207
7208 on('init', () => {
7209 if (swiper.params.zoom.enabled) {
7210 enable();
7211 }
7212 });
7213 on('destroy', () => {
7214 disable();
7215 });
7216 on('touchStart', (_s, e) => {
7217 if (!swiper.zoom.enabled) return;
7218 onTouchStart(e);
7219 });
7220 on('touchEnd', (_s, e) => {
7221 if (!swiper.zoom.enabled) return;
7222 onTouchEnd();
7223 });
7224 on('doubleTap', (_s, e) => {
7225 if (!swiper.animating && swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
7226 zoomToggle(e);
7227 }
7228 });
7229 on('transitionEnd', () => {
7230 if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
7231 onTransitionEnd();
7232 }
7233 });
7234 on('slideChange', () => {
7235 if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {
7236 onTransitionEnd();
7237 }
7238 });
7239 Object.assign(swiper.zoom, {
7240 enable,
7241 disable,
7242 in: zoomIn,
7243 out: zoomOut,
7244 toggle: zoomToggle
7245 });
7246 }
7247
7248 function Lazy({
7249 swiper,
7250 extendParams,
7251 on,
7252 emit
7253 }) {
7254 extendParams({
7255 lazy: {
7256 checkInView: false,
7257 enabled: false,
7258 loadPrevNext: false,
7259 loadPrevNextAmount: 1,
7260 loadOnTransitionStart: false,
7261 scrollingElement: '',
7262 elementClass: 'swiper-lazy',
7263 loadingClass: 'swiper-lazy-loading',
7264 loadedClass: 'swiper-lazy-loaded',
7265 preloaderClass: 'swiper-lazy-preloader'
7266 }
7267 });
7268 swiper.lazy = {};
7269 let scrollHandlerAttached = false;
7270 let initialImageLoaded = false;
7271
7272 function loadInSlide(index, loadInDuplicate = true) {
7273 const params = swiper.params.lazy;
7274 if (typeof index === 'undefined') return;
7275 if (swiper.slides.length === 0) return;
7276 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
7277 const $slideEl = isVirtual ? swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-swiper-slide-index="${index}"]`) : swiper.slides.eq(index);
7278 const $images = $slideEl.find(`.${params.elementClass}:not(.${params.loadedClass}):not(.${params.loadingClass})`);
7279
7280 if ($slideEl.hasClass(params.elementClass) && !$slideEl.hasClass(params.loadedClass) && !$slideEl.hasClass(params.loadingClass)) {
7281 $images.push($slideEl[0]);
7282 }
7283
7284 if ($images.length === 0) return;
7285 $images.each(imageEl => {
7286 const $imageEl = $(imageEl);
7287 $imageEl.addClass(params.loadingClass);
7288 const background = $imageEl.attr('data-background');
7289 const src = $imageEl.attr('data-src');
7290 const srcset = $imageEl.attr('data-srcset');
7291 const sizes = $imageEl.attr('data-sizes');
7292 const $pictureEl = $imageEl.parent('picture');
7293 swiper.loadImage($imageEl[0], src || background, srcset, sizes, false, () => {
7294 if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper && !swiper.params || swiper.destroyed) return;
7295
7296 if (background) {
7297 $imageEl.css('background-image', `url("${background}")`);
7298 $imageEl.removeAttr('data-background');
7299 } else {
7300 if (srcset) {
7301 $imageEl.attr('srcset', srcset);
7302 $imageEl.removeAttr('data-srcset');
7303 }
7304
7305 if (sizes) {
7306 $imageEl.attr('sizes', sizes);
7307 $imageEl.removeAttr('data-sizes');
7308 }
7309
7310 if ($pictureEl.length) {
7311 $pictureEl.children('source').each(sourceEl => {
7312 const $source = $(sourceEl);
7313
7314 if ($source.attr('data-srcset')) {
7315 $source.attr('srcset', $source.attr('data-srcset'));
7316 $source.removeAttr('data-srcset');
7317 }
7318 });
7319 }
7320
7321 if (src) {
7322 $imageEl.attr('src', src);
7323 $imageEl.removeAttr('data-src');
7324 }
7325 }
7326
7327 $imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);
7328 $slideEl.find(`.${params.preloaderClass}`).remove();
7329
7330 if (swiper.params.loop && loadInDuplicate) {
7331 const slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');
7332
7333 if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {
7334 const originalSlide = swiper.$wrapperEl.children(`[data-swiper-slide-index="${slideOriginalIndex}"]:not(.${swiper.params.slideDuplicateClass})`);
7335 loadInSlide(originalSlide.index(), false);
7336 } else {
7337 const duplicatedSlide = swiper.$wrapperEl.children(`.${swiper.params.slideDuplicateClass}[data-swiper-slide-index="${slideOriginalIndex}"]`);
7338 loadInSlide(duplicatedSlide.index(), false);
7339 }
7340 }
7341
7342 emit('lazyImageReady', $slideEl[0], $imageEl[0]);
7343
7344 if (swiper.params.autoHeight) {
7345 swiper.updateAutoHeight();
7346 }
7347 });
7348 emit('lazyImageLoad', $slideEl[0], $imageEl[0]);
7349 });
7350 }
7351
7352 function load() {
7353 const {
7354 $wrapperEl,
7355 params: swiperParams,
7356 slides,
7357 activeIndex
7358 } = swiper;
7359 const isVirtual = swiper.virtual && swiperParams.virtual.enabled;
7360 const params = swiperParams.lazy;
7361 let slidesPerView = swiperParams.slidesPerView;
7362
7363 if (slidesPerView === 'auto') {
7364 slidesPerView = 0;
7365 }
7366
7367 function slideExist(index) {
7368 if (isVirtual) {
7369 if ($wrapperEl.children(`.${swiperParams.slideClass}[data-swiper-slide-index="${index}"]`).length) {
7370 return true;
7371 }
7372 } else if (slides[index]) return true;
7373
7374 return false;
7375 }
7376
7377 function slideIndex(slideEl) {
7378 if (isVirtual) {
7379 return $(slideEl).attr('data-swiper-slide-index');
7380 }
7381
7382 return $(slideEl).index();
7383 }
7384
7385 if (!initialImageLoaded) initialImageLoaded = true;
7386
7387 if (swiper.params.watchSlidesProgress) {
7388 $wrapperEl.children(`.${swiperParams.slideVisibleClass}`).each(slideEl => {
7389 const index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();
7390 loadInSlide(index);
7391 });
7392 } else if (slidesPerView > 1) {
7393 for (let i = activeIndex; i < activeIndex + slidesPerView; i += 1) {
7394 if (slideExist(i)) loadInSlide(i);
7395 }
7396 } else {
7397 loadInSlide(activeIndex);
7398 }
7399
7400 if (params.loadPrevNext) {
7401 if (slidesPerView > 1 || params.loadPrevNextAmount && params.loadPrevNextAmount > 1) {
7402 const amount = params.loadPrevNextAmount;
7403 const spv = slidesPerView;
7404 const maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);
7405 const minIndex = Math.max(activeIndex - Math.max(spv, amount), 0); // Next Slides
7406
7407 for (let i = activeIndex + slidesPerView; i < maxIndex; i += 1) {
7408 if (slideExist(i)) loadInSlide(i);
7409 } // Prev Slides
7410
7411
7412 for (let i = minIndex; i < activeIndex; i += 1) {
7413 if (slideExist(i)) loadInSlide(i);
7414 }
7415 } else {
7416 const nextSlide = $wrapperEl.children(`.${swiperParams.slideNextClass}`);
7417 if (nextSlide.length > 0) loadInSlide(slideIndex(nextSlide));
7418 const prevSlide = $wrapperEl.children(`.${swiperParams.slidePrevClass}`);
7419 if (prevSlide.length > 0) loadInSlide(slideIndex(prevSlide));
7420 }
7421 }
7422 }
7423
7424 function checkInViewOnLoad() {
7425 const window = getWindow();
7426 if (!swiper || swiper.destroyed) return;
7427 const $scrollElement = swiper.params.lazy.scrollingElement ? $(swiper.params.lazy.scrollingElement) : $(window);
7428 const isWindow = $scrollElement[0] === window;
7429 const scrollElementWidth = isWindow ? window.innerWidth : $scrollElement[0].offsetWidth;
7430 const scrollElementHeight = isWindow ? window.innerHeight : $scrollElement[0].offsetHeight;
7431 const swiperOffset = swiper.$el.offset();
7432 const {
7433 rtlTranslate: rtl
7434 } = swiper;
7435 let inView = false;
7436 if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;
7437 const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiper.width, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiper.height], [swiperOffset.left + swiper.width, swiperOffset.top + swiper.height]];
7438
7439 for (let i = 0; i < swiperCoord.length; i += 1) {
7440 const point = swiperCoord[i];
7441
7442 if (point[0] >= 0 && point[0] <= scrollElementWidth && point[1] >= 0 && point[1] <= scrollElementHeight) {
7443 if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line
7444
7445 inView = true;
7446 }
7447 }
7448
7449 const passiveListener = swiper.touchEvents.start === 'touchstart' && swiper.support.passiveListener && swiper.params.passiveListeners ? {
7450 passive: true,
7451 capture: false
7452 } : false;
7453
7454 if (inView) {
7455 load();
7456 $scrollElement.off('scroll', checkInViewOnLoad, passiveListener);
7457 } else if (!scrollHandlerAttached) {
7458 scrollHandlerAttached = true;
7459 $scrollElement.on('scroll', checkInViewOnLoad, passiveListener);
7460 }
7461 }
7462
7463 on('beforeInit', () => {
7464 if (swiper.params.lazy.enabled && swiper.params.preloadImages) {
7465 swiper.params.preloadImages = false;
7466 }
7467 });
7468 on('init', () => {
7469 if (swiper.params.lazy.enabled) {
7470 if (swiper.params.lazy.checkInView) {
7471 checkInViewOnLoad();
7472 } else {
7473 load();
7474 }
7475 }
7476 });
7477 on('scroll', () => {
7478 if (swiper.params.freeMode && swiper.params.freeMode.enabled && !swiper.params.freeMode.sticky) {
7479 load();
7480 }
7481 });
7482 on('scrollbarDragMove resize _freeModeNoMomentumRelease', () => {
7483 if (swiper.params.lazy.enabled) {
7484 if (swiper.params.lazy.checkInView) {
7485 checkInViewOnLoad();
7486 } else {
7487 load();
7488 }
7489 }
7490 });
7491 on('transitionStart', () => {
7492 if (swiper.params.lazy.enabled) {
7493 if (swiper.params.lazy.loadOnTransitionStart || !swiper.params.lazy.loadOnTransitionStart && !initialImageLoaded) {
7494 if (swiper.params.lazy.checkInView) {
7495 checkInViewOnLoad();
7496 } else {
7497 load();
7498 }
7499 }
7500 }
7501 });
7502 on('transitionEnd', () => {
7503 if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {
7504 if (swiper.params.lazy.checkInView) {
7505 checkInViewOnLoad();
7506 } else {
7507 load();
7508 }
7509 }
7510 });
7511 on('slideChange', () => {
7512 const {
7513 lazy,
7514 cssMode,
7515 watchSlidesProgress,
7516 touchReleaseOnEdges,
7517 resistanceRatio
7518 } = swiper.params;
7519
7520 if (lazy.enabled && (cssMode || watchSlidesProgress && (touchReleaseOnEdges || resistanceRatio === 0))) {
7521 load();
7522 }
7523 });
7524 Object.assign(swiper.lazy, {
7525 load,
7526 loadInSlide
7527 });
7528 }
7529
7530 /* eslint no-bitwise: ["error", { "allow": [">>"] }] */
7531 function Controller({
7532 swiper,
7533 extendParams,
7534 on
7535 }) {
7536 extendParams({
7537 controller: {
7538 control: undefined,
7539 inverse: false,
7540 by: 'slide' // or 'container'
7541
7542 }
7543 });
7544 swiper.controller = {
7545 control: undefined
7546 };
7547
7548 function LinearSpline(x, y) {
7549 const binarySearch = function search() {
7550 let maxIndex;
7551 let minIndex;
7552 let guess;
7553 return (array, val) => {
7554 minIndex = -1;
7555 maxIndex = array.length;
7556
7557 while (maxIndex - minIndex > 1) {
7558 guess = maxIndex + minIndex >> 1;
7559
7560 if (array[guess] <= val) {
7561 minIndex = guess;
7562 } else {
7563 maxIndex = guess;
7564 }
7565 }
7566
7567 return maxIndex;
7568 };
7569 }();
7570
7571 this.x = x;
7572 this.y = y;
7573 this.lastIndex = x.length - 1; // Given an x value (x2), return the expected y2 value:
7574 // (x1,y1) is the known point before given value,
7575 // (x3,y3) is the known point after given value.
7576
7577 let i1;
7578 let i3;
7579
7580 this.interpolate = function interpolate(x2) {
7581 if (!x2) return 0; // Get the indexes of x1 and x3 (the array indexes before and after given x2):
7582
7583 i3 = binarySearch(this.x, x2);
7584 i1 = i3 - 1; // We have our indexes i1 & i3, so we can calculate already:
7585 // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
7586
7587 return (x2 - this.x[i1]) * (this.y[i3] - this.y[i1]) / (this.x[i3] - this.x[i1]) + this.y[i1];
7588 };
7589
7590 return this;
7591 } // xxx: for now i will just save one spline function to to
7592
7593
7594 function getInterpolateFunction(c) {
7595 if (!swiper.controller.spline) {
7596 swiper.controller.spline = swiper.params.loop ? new LinearSpline(swiper.slidesGrid, c.slidesGrid) : new LinearSpline(swiper.snapGrid, c.snapGrid);
7597 }
7598 }
7599
7600 function setTranslate(_t, byController) {
7601 const controlled = swiper.controller.control;
7602 let multiplier;
7603 let controlledTranslate;
7604 const Swiper = swiper.constructor;
7605
7606 function setControlledTranslate(c) {
7607 // this will create an Interpolate function based on the snapGrids
7608 // x is the Grid of the scrolled scroller and y will be the controlled scroller
7609 // it makes sense to create this only once and recall it for the interpolation
7610 // the function does a lot of value caching for performance
7611 const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
7612
7613 if (swiper.params.controller.by === 'slide') {
7614 getInterpolateFunction(c); // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
7615 // but it did not work out
7616
7617 controlledTranslate = -swiper.controller.spline.interpolate(-translate);
7618 }
7619
7620 if (!controlledTranslate || swiper.params.controller.by === 'container') {
7621 multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
7622 controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate();
7623 }
7624
7625 if (swiper.params.controller.inverse) {
7626 controlledTranslate = c.maxTranslate() - controlledTranslate;
7627 }
7628
7629 c.updateProgress(controlledTranslate);
7630 c.setTranslate(controlledTranslate, swiper);
7631 c.updateActiveIndex();
7632 c.updateSlidesClasses();
7633 }
7634
7635 if (Array.isArray(controlled)) {
7636 for (let i = 0; i < controlled.length; i += 1) {
7637 if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
7638 setControlledTranslate(controlled[i]);
7639 }
7640 }
7641 } else if (controlled instanceof Swiper && byController !== controlled) {
7642 setControlledTranslate(controlled);
7643 }
7644 }
7645
7646 function setTransition(duration, byController) {
7647 const Swiper = swiper.constructor;
7648 const controlled = swiper.controller.control;
7649 let i;
7650
7651 function setControlledTransition(c) {
7652 c.setTransition(duration, swiper);
7653
7654 if (duration !== 0) {
7655 c.transitionStart();
7656
7657 if (c.params.autoHeight) {
7658 nextTick(() => {
7659 c.updateAutoHeight();
7660 });
7661 }
7662
7663 c.$wrapperEl.transitionEnd(() => {
7664 if (!controlled) return;
7665
7666 if (c.params.loop && swiper.params.controller.by === 'slide') {
7667 c.loopFix();
7668 }
7669
7670 c.transitionEnd();
7671 });
7672 }
7673 }
7674
7675 if (Array.isArray(controlled)) {
7676 for (i = 0; i < controlled.length; i += 1) {
7677 if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
7678 setControlledTransition(controlled[i]);
7679 }
7680 }
7681 } else if (controlled instanceof Swiper && byController !== controlled) {
7682 setControlledTransition(controlled);
7683 }
7684 }
7685
7686 function removeSpline() {
7687 if (!swiper.controller.control) return;
7688
7689 if (swiper.controller.spline) {
7690 swiper.controller.spline = undefined;
7691 delete swiper.controller.spline;
7692 }
7693 }
7694
7695 on('beforeInit', () => {
7696 swiper.controller.control = swiper.params.controller.control;
7697 });
7698 on('update', () => {
7699 removeSpline();
7700 });
7701 on('resize', () => {
7702 removeSpline();
7703 });
7704 on('observerUpdate', () => {
7705 removeSpline();
7706 });
7707 on('setTranslate', (_s, translate, byController) => {
7708 if (!swiper.controller.control) return;
7709 swiper.controller.setTranslate(translate, byController);
7710 });
7711 on('setTransition', (_s, duration, byController) => {
7712 if (!swiper.controller.control) return;
7713 swiper.controller.setTransition(duration, byController);
7714 });
7715 Object.assign(swiper.controller, {
7716 setTranslate,
7717 setTransition
7718 });
7719 }
7720
7721 function A11y({
7722 swiper,
7723 extendParams,
7724 on
7725 }) {
7726 extendParams({
7727 a11y: {
7728 enabled: true,
7729 notificationClass: 'swiper-notification',
7730 prevSlideMessage: 'Previous slide',
7731 nextSlideMessage: 'Next slide',
7732 firstSlideMessage: 'This is the first slide',
7733 lastSlideMessage: 'This is the last slide',
7734 paginationBulletMessage: 'Go to slide {{index}}',
7735 slideLabelMessage: '{{index}} / {{slidesLength}}',
7736 containerMessage: null,
7737 containerRoleDescriptionMessage: null,
7738 itemRoleDescriptionMessage: null,
7739 slideRole: 'group'
7740 }
7741 });
7742 let liveRegion = null;
7743
7744 function notify(message) {
7745 const notification = liveRegion;
7746 if (notification.length === 0) return;
7747 notification.html('');
7748 notification.html(message);
7749 }
7750
7751 function getRandomNumber(size = 16) {
7752 const randomChar = () => Math.round(16 * Math.random()).toString(16);
7753
7754 return 'x'.repeat(size).replace(/x/g, randomChar);
7755 }
7756
7757 function makeElFocusable($el) {
7758 $el.attr('tabIndex', '0');
7759 }
7760
7761 function makeElNotFocusable($el) {
7762 $el.attr('tabIndex', '-1');
7763 }
7764
7765 function addElRole($el, role) {
7766 $el.attr('role', role);
7767 }
7768
7769 function addElRoleDescription($el, description) {
7770 $el.attr('aria-roledescription', description);
7771 }
7772
7773 function addElControls($el, controls) {
7774 $el.attr('aria-controls', controls);
7775 }
7776
7777 function addElLabel($el, label) {
7778 $el.attr('aria-label', label);
7779 }
7780
7781 function addElId($el, id) {
7782 $el.attr('id', id);
7783 }
7784
7785 function addElLive($el, live) {
7786 $el.attr('aria-live', live);
7787 }
7788
7789 function disableEl($el) {
7790 $el.attr('aria-disabled', true);
7791 }
7792
7793 function enableEl($el) {
7794 $el.attr('aria-disabled', false);
7795 }
7796
7797 function onEnterOrSpaceKey(e) {
7798 if (e.keyCode !== 13 && e.keyCode !== 32) return;
7799 const params = swiper.params.a11y;
7800 const $targetEl = $(e.target);
7801
7802 if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {
7803 if (!(swiper.isEnd && !swiper.params.loop)) {
7804 swiper.slideNext();
7805 }
7806
7807 if (swiper.isEnd) {
7808 notify(params.lastSlideMessage);
7809 } else {
7810 notify(params.nextSlideMessage);
7811 }
7812 }
7813
7814 if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {
7815 if (!(swiper.isBeginning && !swiper.params.loop)) {
7816 swiper.slidePrev();
7817 }
7818
7819 if (swiper.isBeginning) {
7820 notify(params.firstSlideMessage);
7821 } else {
7822 notify(params.prevSlideMessage);
7823 }
7824 }
7825
7826 if (swiper.pagination && $targetEl.is(classesToSelector(swiper.params.pagination.bulletClass))) {
7827 $targetEl[0].click();
7828 }
7829 }
7830
7831 function updateNavigation() {
7832 if (swiper.params.loop || !swiper.navigation) return;
7833 const {
7834 $nextEl,
7835 $prevEl
7836 } = swiper.navigation;
7837
7838 if ($prevEl && $prevEl.length > 0) {
7839 if (swiper.isBeginning) {
7840 disableEl($prevEl);
7841 makeElNotFocusable($prevEl);
7842 } else {
7843 enableEl($prevEl);
7844 makeElFocusable($prevEl);
7845 }
7846 }
7847
7848 if ($nextEl && $nextEl.length > 0) {
7849 if (swiper.isEnd) {
7850 disableEl($nextEl);
7851 makeElNotFocusable($nextEl);
7852 } else {
7853 enableEl($nextEl);
7854 makeElFocusable($nextEl);
7855 }
7856 }
7857 }
7858
7859 function hasPagination() {
7860 return swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length;
7861 }
7862
7863 function updatePagination() {
7864 const params = swiper.params.a11y;
7865
7866 if (hasPagination()) {
7867 swiper.pagination.bullets.each(bulletEl => {
7868 const $bulletEl = $(bulletEl);
7869 makeElFocusable($bulletEl);
7870
7871 if (!swiper.params.pagination.renderBullet) {
7872 addElRole($bulletEl, 'button');
7873 addElLabel($bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, $bulletEl.index() + 1));
7874 }
7875 });
7876 }
7877 }
7878
7879 const initNavEl = ($el, wrapperId, message) => {
7880 makeElFocusable($el);
7881
7882 if ($el[0].tagName !== 'BUTTON') {
7883 addElRole($el, 'button');
7884 $el.on('keydown', onEnterOrSpaceKey);
7885 }
7886
7887 addElLabel($el, message);
7888 addElControls($el, wrapperId);
7889 };
7890
7891 function init() {
7892 const params = swiper.params.a11y;
7893 swiper.$el.append(liveRegion); // Container
7894
7895 const $containerEl = swiper.$el;
7896
7897 if (params.containerRoleDescriptionMessage) {
7898 addElRoleDescription($containerEl, params.containerRoleDescriptionMessage);
7899 }
7900
7901 if (params.containerMessage) {
7902 addElLabel($containerEl, params.containerMessage);
7903 } // Wrapper
7904
7905
7906 const $wrapperEl = swiper.$wrapperEl;
7907 const wrapperId = $wrapperEl.attr('id') || `swiper-wrapper-${getRandomNumber(16)}`;
7908 const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';
7909 addElId($wrapperEl, wrapperId);
7910 addElLive($wrapperEl, live); // Slide
7911
7912 if (params.itemRoleDescriptionMessage) {
7913 addElRoleDescription($(swiper.slides), params.itemRoleDescriptionMessage);
7914 }
7915
7916 addElRole($(swiper.slides), params.slideRole);
7917 const slidesLength = swiper.params.loop ? swiper.slides.filter(el => !el.classList.contains(swiper.params.slideDuplicateClass)).length : swiper.slides.length;
7918 swiper.slides.each((slideEl, index) => {
7919 const $slideEl = $(slideEl);
7920 const slideIndex = swiper.params.loop ? parseInt($slideEl.attr('data-swiper-slide-index'), 10) : index;
7921 const ariaLabelMessage = params.slideLabelMessage.replace(/\{\{index\}\}/, slideIndex + 1).replace(/\{\{slidesLength\}\}/, slidesLength);
7922 addElLabel($slideEl, ariaLabelMessage);
7923 }); // Navigation
7924
7925 let $nextEl;
7926 let $prevEl;
7927
7928 if (swiper.navigation && swiper.navigation.$nextEl) {
7929 $nextEl = swiper.navigation.$nextEl;
7930 }
7931
7932 if (swiper.navigation && swiper.navigation.$prevEl) {
7933 $prevEl = swiper.navigation.$prevEl;
7934 }
7935
7936 if ($nextEl && $nextEl.length) {
7937 initNavEl($nextEl, wrapperId, params.nextSlideMessage);
7938 }
7939
7940 if ($prevEl && $prevEl.length) {
7941 initNavEl($prevEl, wrapperId, params.prevSlideMessage);
7942 } // Pagination
7943
7944
7945 if (hasPagination()) {
7946 swiper.pagination.$el.on('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);
7947 }
7948 }
7949
7950 function destroy() {
7951 if (liveRegion && liveRegion.length > 0) liveRegion.remove();
7952 let $nextEl;
7953 let $prevEl;
7954
7955 if (swiper.navigation && swiper.navigation.$nextEl) {
7956 $nextEl = swiper.navigation.$nextEl;
7957 }
7958
7959 if (swiper.navigation && swiper.navigation.$prevEl) {
7960 $prevEl = swiper.navigation.$prevEl;
7961 }
7962
7963 if ($nextEl) {
7964 $nextEl.off('keydown', onEnterOrSpaceKey);
7965 }
7966
7967 if ($prevEl) {
7968 $prevEl.off('keydown', onEnterOrSpaceKey);
7969 } // Pagination
7970
7971
7972 if (hasPagination()) {
7973 swiper.pagination.$el.off('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);
7974 }
7975 }
7976
7977 on('beforeInit', () => {
7978 liveRegion = $(`<span class="${swiper.params.a11y.notificationClass}" aria-live="assertive" aria-atomic="true"></span>`);
7979 });
7980 on('afterInit', () => {
7981 if (!swiper.params.a11y.enabled) return;
7982 init();
7983 updateNavigation();
7984 });
7985 on('toEdge', () => {
7986 if (!swiper.params.a11y.enabled) return;
7987 updateNavigation();
7988 });
7989 on('fromEdge', () => {
7990 if (!swiper.params.a11y.enabled) return;
7991 updateNavigation();
7992 });
7993 on('paginationUpdate', () => {
7994 if (!swiper.params.a11y.enabled) return;
7995 updatePagination();
7996 });
7997 on('destroy', () => {
7998 if (!swiper.params.a11y.enabled) return;
7999 destroy();
8000 });
8001 }
8002
8003 function History({
8004 swiper,
8005 extendParams,
8006 on
8007 }) {
8008 extendParams({
8009 history: {
8010 enabled: false,
8011 root: '',
8012 replaceState: false,
8013 key: 'slides'
8014 }
8015 });
8016 let initialized = false;
8017 let paths = {};
8018
8019 const slugify = text => {
8020 return text.toString().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
8021 };
8022
8023 const getPathValues = urlOverride => {
8024 const window = getWindow();
8025 let location;
8026
8027 if (urlOverride) {
8028 location = new URL(urlOverride);
8029 } else {
8030 location = window.location;
8031 }
8032
8033 const pathArray = location.pathname.slice(1).split('/').filter(part => part !== '');
8034 const total = pathArray.length;
8035 const key = pathArray[total - 2];
8036 const value = pathArray[total - 1];
8037 return {
8038 key,
8039 value
8040 };
8041 };
8042
8043 const setHistory = (key, index) => {
8044 const window = getWindow();
8045 if (!initialized || !swiper.params.history.enabled) return;
8046 let location;
8047
8048 if (swiper.params.url) {
8049 location = new URL(swiper.params.url);
8050 } else {
8051 location = window.location;
8052 }
8053
8054 const slide = swiper.slides.eq(index);
8055 let value = slugify(slide.attr('data-history'));
8056
8057 if (swiper.params.history.root.length > 0) {
8058 let root = swiper.params.history.root;
8059 if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1);
8060 value = `${root}/${key}/${value}`;
8061 } else if (!location.pathname.includes(key)) {
8062 value = `${key}/${value}`;
8063 }
8064
8065 const currentState = window.history.state;
8066
8067 if (currentState && currentState.value === value) {
8068 return;
8069 }
8070
8071 if (swiper.params.history.replaceState) {
8072 window.history.replaceState({
8073 value
8074 }, null, value);
8075 } else {
8076 window.history.pushState({
8077 value
8078 }, null, value);
8079 }
8080 };
8081
8082 const scrollToSlide = (speed, value, runCallbacks) => {
8083 if (value) {
8084 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
8085 const slide = swiper.slides.eq(i);
8086 const slideHistory = slugify(slide.attr('data-history'));
8087
8088 if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {
8089 const index = slide.index();
8090 swiper.slideTo(index, speed, runCallbacks);
8091 }
8092 }
8093 } else {
8094 swiper.slideTo(0, speed, runCallbacks);
8095 }
8096 };
8097
8098 const setHistoryPopState = () => {
8099 paths = getPathValues(swiper.params.url);
8100 scrollToSlide(swiper.params.speed, swiper.paths.value, false);
8101 };
8102
8103 const init = () => {
8104 const window = getWindow();
8105 if (!swiper.params.history) return;
8106
8107 if (!window.history || !window.history.pushState) {
8108 swiper.params.history.enabled = false;
8109 swiper.params.hashNavigation.enabled = true;
8110 return;
8111 }
8112
8113 initialized = true;
8114 paths = getPathValues(swiper.params.url);
8115 if (!paths.key && !paths.value) return;
8116 scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit);
8117
8118 if (!swiper.params.history.replaceState) {
8119 window.addEventListener('popstate', setHistoryPopState);
8120 }
8121 };
8122
8123 const destroy = () => {
8124 const window = getWindow();
8125
8126 if (!swiper.params.history.replaceState) {
8127 window.removeEventListener('popstate', setHistoryPopState);
8128 }
8129 };
8130
8131 on('init', () => {
8132 if (swiper.params.history.enabled) {
8133 init();
8134 }
8135 });
8136 on('destroy', () => {
8137 if (swiper.params.history.enabled) {
8138 destroy();
8139 }
8140 });
8141 on('transitionEnd _freeModeNoMomentumRelease', () => {
8142 if (initialized) {
8143 setHistory(swiper.params.history.key, swiper.activeIndex);
8144 }
8145 });
8146 on('slideChange', () => {
8147 if (initialized && swiper.params.cssMode) {
8148 setHistory(swiper.params.history.key, swiper.activeIndex);
8149 }
8150 });
8151 }
8152
8153 function HashNavigation({
8154 swiper,
8155 extendParams,
8156 emit,
8157 on
8158 }) {
8159 let initialized = false;
8160 const document = getDocument();
8161 const window = getWindow();
8162 extendParams({
8163 hashNavigation: {
8164 enabled: false,
8165 replaceState: false,
8166 watchState: false
8167 }
8168 });
8169
8170 const onHashChange = () => {
8171 emit('hashChange');
8172 const newHash = document.location.hash.replace('#', '');
8173 const activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');
8174
8175 if (newHash !== activeSlideHash) {
8176 const newIndex = swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-hash="${newHash}"]`).index();
8177 if (typeof newIndex === 'undefined') return;
8178 swiper.slideTo(newIndex);
8179 }
8180 };
8181
8182 const setHash = () => {
8183 if (!initialized || !swiper.params.hashNavigation.enabled) return;
8184
8185 if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) {
8186 window.history.replaceState(null, null, `#${swiper.slides.eq(swiper.activeIndex).attr('data-hash')}` || '');
8187 emit('hashSet');
8188 } else {
8189 const slide = swiper.slides.eq(swiper.activeIndex);
8190 const hash = slide.attr('data-hash') || slide.attr('data-history');
8191 document.location.hash = hash || '';
8192 emit('hashSet');
8193 }
8194 };
8195
8196 const init = () => {
8197 if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return;
8198 initialized = true;
8199 const hash = document.location.hash.replace('#', '');
8200
8201 if (hash) {
8202 const speed = 0;
8203
8204 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
8205 const slide = swiper.slides.eq(i);
8206 const slideHash = slide.attr('data-hash') || slide.attr('data-history');
8207
8208 if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {
8209 const index = slide.index();
8210 swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);
8211 }
8212 }
8213 }
8214
8215 if (swiper.params.hashNavigation.watchState) {
8216 $(window).on('hashchange', onHashChange);
8217 }
8218 };
8219
8220 const destroy = () => {
8221 if (swiper.params.hashNavigation.watchState) {
8222 $(window).off('hashchange', onHashChange);
8223 }
8224 };
8225
8226 on('init', () => {
8227 if (swiper.params.hashNavigation.enabled) {
8228 init();
8229 }
8230 });
8231 on('destroy', () => {
8232 if (swiper.params.hashNavigation.enabled) {
8233 destroy();
8234 }
8235 });
8236 on('transitionEnd _freeModeNoMomentumRelease', () => {
8237 if (initialized) {
8238 setHash();
8239 }
8240 });
8241 on('slideChange', () => {
8242 if (initialized && swiper.params.cssMode) {
8243 setHash();
8244 }
8245 });
8246 }
8247
8248 /* eslint no-underscore-dangle: "off" */
8249 function Autoplay({
8250 swiper,
8251 extendParams,
8252 on,
8253 emit
8254 }) {
8255 let timeout;
8256 swiper.autoplay = {
8257 running: false,
8258 paused: false
8259 };
8260 extendParams({
8261 autoplay: {
8262 enabled: false,
8263 delay: 3000,
8264 waitForTransition: true,
8265 disableOnInteraction: true,
8266 stopOnLastSlide: false,
8267 reverseDirection: false,
8268 pauseOnMouseEnter: false
8269 }
8270 });
8271
8272 function run() {
8273 const $activeSlideEl = swiper.slides.eq(swiper.activeIndex);
8274 let delay = swiper.params.autoplay.delay;
8275
8276 if ($activeSlideEl.attr('data-swiper-autoplay')) {
8277 delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;
8278 }
8279
8280 clearTimeout(timeout);
8281 timeout = nextTick(() => {
8282 let autoplayResult;
8283
8284 if (swiper.params.autoplay.reverseDirection) {
8285 if (swiper.params.loop) {
8286 swiper.loopFix();
8287 autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);
8288 emit('autoplay');
8289 } else if (!swiper.isBeginning) {
8290 autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);
8291 emit('autoplay');
8292 } else if (!swiper.params.autoplay.stopOnLastSlide) {
8293 autoplayResult = swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);
8294 emit('autoplay');
8295 } else {
8296 stop();
8297 }
8298 } else if (swiper.params.loop) {
8299 swiper.loopFix();
8300 autoplayResult = swiper.slideNext(swiper.params.speed, true, true);
8301 emit('autoplay');
8302 } else if (!swiper.isEnd) {
8303 autoplayResult = swiper.slideNext(swiper.params.speed, true, true);
8304 emit('autoplay');
8305 } else if (!swiper.params.autoplay.stopOnLastSlide) {
8306 autoplayResult = swiper.slideTo(0, swiper.params.speed, true, true);
8307 emit('autoplay');
8308 } else {
8309 stop();
8310 }
8311
8312 if (swiper.params.cssMode && swiper.autoplay.running) run();else if (autoplayResult === false) {
8313 run();
8314 }
8315 }, delay);
8316 }
8317
8318 function start() {
8319 if (typeof timeout !== 'undefined') return false;
8320 if (swiper.autoplay.running) return false;
8321 swiper.autoplay.running = true;
8322 emit('autoplayStart');
8323 run();
8324 return true;
8325 }
8326
8327 function stop() {
8328 if (!swiper.autoplay.running) return false;
8329 if (typeof timeout === 'undefined') return false;
8330
8331 if (timeout) {
8332 clearTimeout(timeout);
8333 timeout = undefined;
8334 }
8335
8336 swiper.autoplay.running = false;
8337 emit('autoplayStop');
8338 return true;
8339 }
8340
8341 function pause(speed) {
8342 if (!swiper.autoplay.running) return;
8343 if (swiper.autoplay.paused) return;
8344 if (timeout) clearTimeout(timeout);
8345 swiper.autoplay.paused = true;
8346
8347 if (speed === 0 || !swiper.params.autoplay.waitForTransition) {
8348 swiper.autoplay.paused = false;
8349 run();
8350 } else {
8351 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8352 swiper.$wrapperEl[0].addEventListener(event, onTransitionEnd);
8353 });
8354 }
8355 }
8356
8357 function onVisibilityChange() {
8358 const document = getDocument();
8359
8360 if (document.visibilityState === 'hidden' && swiper.autoplay.running) {
8361 pause();
8362 }
8363
8364 if (document.visibilityState === 'visible' && swiper.autoplay.paused) {
8365 run();
8366 swiper.autoplay.paused = false;
8367 }
8368 }
8369
8370 function onTransitionEnd(e) {
8371 if (!swiper || swiper.destroyed || !swiper.$wrapperEl) return;
8372 if (e.target !== swiper.$wrapperEl[0]) return;
8373 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8374 swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);
8375 });
8376 swiper.autoplay.paused = false;
8377
8378 if (!swiper.autoplay.running) {
8379 stop();
8380 } else {
8381 run();
8382 }
8383 }
8384
8385 function onMouseEnter() {
8386 if (swiper.params.autoplay.disableOnInteraction) {
8387 stop();
8388 } else {
8389 pause();
8390 }
8391
8392 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8393 swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);
8394 });
8395 }
8396
8397 function onMouseLeave() {
8398 if (swiper.params.autoplay.disableOnInteraction) {
8399 return;
8400 }
8401
8402 swiper.autoplay.paused = false;
8403 run();
8404 }
8405
8406 function attachMouseEvents() {
8407 if (swiper.params.autoplay.pauseOnMouseEnter) {
8408 swiper.$el.on('mouseenter', onMouseEnter);
8409 swiper.$el.on('mouseleave', onMouseLeave);
8410 }
8411 }
8412
8413 function detachMouseEvents() {
8414 swiper.$el.off('mouseenter', onMouseEnter);
8415 swiper.$el.off('mouseleave', onMouseLeave);
8416 }
8417
8418 on('init', () => {
8419 if (swiper.params.autoplay.enabled) {
8420 start();
8421 const document = getDocument();
8422 document.addEventListener('visibilitychange', onVisibilityChange);
8423 attachMouseEvents();
8424 }
8425 });
8426 on('beforeTransitionStart', (_s, speed, internal) => {
8427 if (swiper.autoplay.running) {
8428 if (internal || !swiper.params.autoplay.disableOnInteraction) {
8429 swiper.autoplay.pause(speed);
8430 } else {
8431 stop();
8432 }
8433 }
8434 });
8435 on('sliderFirstMove', () => {
8436 if (swiper.autoplay.running) {
8437 if (swiper.params.autoplay.disableOnInteraction) {
8438 stop();
8439 } else {
8440 pause();
8441 }
8442 }
8443 });
8444 on('touchEnd', () => {
8445 if (swiper.params.cssMode && swiper.autoplay.paused && !swiper.params.autoplay.disableOnInteraction) {
8446 run();
8447 }
8448 });
8449 on('destroy', () => {
8450 detachMouseEvents();
8451
8452 if (swiper.autoplay.running) {
8453 stop();
8454 }
8455
8456 const document = getDocument();
8457 document.removeEventListener('visibilitychange', onVisibilityChange);
8458 });
8459 Object.assign(swiper.autoplay, {
8460 pause,
8461 run,
8462 start,
8463 stop
8464 });
8465 }
8466
8467 function Thumb({
8468 swiper,
8469 extendParams,
8470 on
8471 }) {
8472 extendParams({
8473 thumbs: {
8474 swiper: null,
8475 multipleActiveThumbs: true,
8476 autoScrollOffset: 0,
8477 slideThumbActiveClass: 'swiper-slide-thumb-active',
8478 thumbsContainerClass: 'swiper-thumbs'
8479 }
8480 });
8481 let initialized = false;
8482 let swiperCreated = false;
8483 swiper.thumbs = {
8484 swiper: null
8485 };
8486
8487 function onThumbClick() {
8488 const thumbsSwiper = swiper.thumbs.swiper;
8489 if (!thumbsSwiper) return;
8490 const clickedIndex = thumbsSwiper.clickedIndex;
8491 const clickedSlide = thumbsSwiper.clickedSlide;
8492 if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) return;
8493 if (typeof clickedIndex === 'undefined' || clickedIndex === null) return;
8494 let slideToIndex;
8495
8496 if (thumbsSwiper.params.loop) {
8497 slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);
8498 } else {
8499 slideToIndex = clickedIndex;
8500 }
8501
8502 if (swiper.params.loop) {
8503 let currentIndex = swiper.activeIndex;
8504
8505 if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {
8506 swiper.loopFix(); // eslint-disable-next-line
8507
8508 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
8509 currentIndex = swiper.activeIndex;
8510 }
8511
8512 const prevIndex = swiper.slides.eq(currentIndex).prevAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
8513 const nextIndex = swiper.slides.eq(currentIndex).nextAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
8514 if (typeof prevIndex === 'undefined') slideToIndex = nextIndex;else if (typeof nextIndex === 'undefined') slideToIndex = prevIndex;else if (nextIndex - currentIndex < currentIndex - prevIndex) slideToIndex = nextIndex;else slideToIndex = prevIndex;
8515 }
8516
8517 swiper.slideTo(slideToIndex);
8518 }
8519
8520 function init() {
8521 const {
8522 thumbs: thumbsParams
8523 } = swiper.params;
8524 if (initialized) return false;
8525 initialized = true;
8526 const SwiperClass = swiper.constructor;
8527
8528 if (thumbsParams.swiper instanceof SwiperClass) {
8529 swiper.thumbs.swiper = thumbsParams.swiper;
8530 Object.assign(swiper.thumbs.swiper.originalParams, {
8531 watchSlidesProgress: true,
8532 slideToClickedSlide: false
8533 });
8534 Object.assign(swiper.thumbs.swiper.params, {
8535 watchSlidesProgress: true,
8536 slideToClickedSlide: false
8537 });
8538 } else if (isObject(thumbsParams.swiper)) {
8539 const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper);
8540 Object.assign(thumbsSwiperParams, {
8541 watchSlidesProgress: true,
8542 slideToClickedSlide: false
8543 });
8544 swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams);
8545 swiperCreated = true;
8546 }
8547
8548 swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);
8549 swiper.thumbs.swiper.on('tap', onThumbClick);
8550 return true;
8551 }
8552
8553 function update(initial) {
8554 const thumbsSwiper = swiper.thumbs.swiper;
8555 if (!thumbsSwiper) return;
8556 const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto' ? thumbsSwiper.slidesPerViewDynamic() : thumbsSwiper.params.slidesPerView;
8557 const autoScrollOffset = swiper.params.thumbs.autoScrollOffset;
8558 const useOffset = autoScrollOffset && !thumbsSwiper.params.loop;
8559
8560 if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) {
8561 let currentThumbsIndex = thumbsSwiper.activeIndex;
8562 let newThumbsIndex;
8563 let direction;
8564
8565 if (thumbsSwiper.params.loop) {
8566 if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {
8567 thumbsSwiper.loopFix(); // eslint-disable-next-line
8568
8569 thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;
8570 currentThumbsIndex = thumbsSwiper.activeIndex;
8571 } // Find actual thumbs index to slide to
8572
8573
8574 const prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
8575 const nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
8576
8577 if (typeof prevThumbsIndex === 'undefined') {
8578 newThumbsIndex = nextThumbsIndex;
8579 } else if (typeof nextThumbsIndex === 'undefined') {
8580 newThumbsIndex = prevThumbsIndex;
8581 } else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) {
8582 newThumbsIndex = thumbsSwiper.params.slidesPerGroup > 1 ? nextThumbsIndex : currentThumbsIndex;
8583 } else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) {
8584 newThumbsIndex = nextThumbsIndex;
8585 } else {
8586 newThumbsIndex = prevThumbsIndex;
8587 }
8588
8589 direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev';
8590 } else {
8591 newThumbsIndex = swiper.realIndex;
8592 direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev';
8593 }
8594
8595 if (useOffset) {
8596 newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset;
8597 }
8598
8599 if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {
8600 if (thumbsSwiper.params.centeredSlides) {
8601 if (newThumbsIndex > currentThumbsIndex) {
8602 newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
8603 } else {
8604 newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
8605 }
8606 } else if (newThumbsIndex > currentThumbsIndex && thumbsSwiper.params.slidesPerGroup === 1) ;
8607
8608 thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
8609 }
8610 } // Activate thumbs
8611
8612
8613 let thumbsToActivate = 1;
8614 const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
8615
8616 if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
8617 thumbsToActivate = swiper.params.slidesPerView;
8618 }
8619
8620 if (!swiper.params.thumbs.multipleActiveThumbs) {
8621 thumbsToActivate = 1;
8622 }
8623
8624 thumbsToActivate = Math.floor(thumbsToActivate);
8625 thumbsSwiper.slides.removeClass(thumbActiveClass);
8626
8627 if (thumbsSwiper.params.loop || thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled) {
8628 for (let i = 0; i < thumbsToActivate; i += 1) {
8629 thumbsSwiper.$wrapperEl.children(`[data-swiper-slide-index="${swiper.realIndex + i}"]`).addClass(thumbActiveClass);
8630 }
8631 } else {
8632 for (let i = 0; i < thumbsToActivate; i += 1) {
8633 thumbsSwiper.slides.eq(swiper.realIndex + i).addClass(thumbActiveClass);
8634 }
8635 }
8636 }
8637
8638 on('beforeInit', () => {
8639 const {
8640 thumbs
8641 } = swiper.params;
8642 if (!thumbs || !thumbs.swiper) return;
8643 init();
8644 update(true);
8645 });
8646 on('slideChange update resize observerUpdate', () => {
8647 if (!swiper.thumbs.swiper) return;
8648 update();
8649 });
8650 on('setTransition', (_s, duration) => {
8651 const thumbsSwiper = swiper.thumbs.swiper;
8652 if (!thumbsSwiper) return;
8653 thumbsSwiper.setTransition(duration);
8654 });
8655 on('beforeDestroy', () => {
8656 const thumbsSwiper = swiper.thumbs.swiper;
8657 if (!thumbsSwiper) return;
8658
8659 if (swiperCreated && thumbsSwiper) {
8660 thumbsSwiper.destroy();
8661 }
8662 });
8663 Object.assign(swiper.thumbs, {
8664 init,
8665 update
8666 });
8667 }
8668
8669 function freeMode({
8670 swiper,
8671 extendParams,
8672 emit,
8673 once
8674 }) {
8675 extendParams({
8676 freeMode: {
8677 enabled: false,
8678 momentum: true,
8679 momentumRatio: 1,
8680 momentumBounce: true,
8681 momentumBounceRatio: 1,
8682 momentumVelocityRatio: 1,
8683 sticky: false,
8684 minimumVelocity: 0.02
8685 }
8686 });
8687
8688 function onTouchMove() {
8689 const {
8690 touchEventsData: data,
8691 touches
8692 } = swiper; // Velocity
8693
8694 if (data.velocities.length === 0) {
8695 data.velocities.push({
8696 position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
8697 time: data.touchStartTime
8698 });
8699 }
8700
8701 data.velocities.push({
8702 position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
8703 time: now()
8704 });
8705 }
8706
8707 function onTouchEnd({
8708 currentPos
8709 }) {
8710 const {
8711 params,
8712 $wrapperEl,
8713 rtlTranslate: rtl,
8714 snapGrid,
8715 touchEventsData: data
8716 } = swiper; // Time diff
8717
8718 const touchEndTime = now();
8719 const timeDiff = touchEndTime - data.touchStartTime;
8720
8721 if (currentPos < -swiper.minTranslate()) {
8722 swiper.slideTo(swiper.activeIndex);
8723 return;
8724 }
8725
8726 if (currentPos > -swiper.maxTranslate()) {
8727 if (swiper.slides.length < snapGrid.length) {
8728 swiper.slideTo(snapGrid.length - 1);
8729 } else {
8730 swiper.slideTo(swiper.slides.length - 1);
8731 }
8732
8733 return;
8734 }
8735
8736 if (params.freeMode.momentum) {
8737 if (data.velocities.length > 1) {
8738 const lastMoveEvent = data.velocities.pop();
8739 const velocityEvent = data.velocities.pop();
8740 const distance = lastMoveEvent.position - velocityEvent.position;
8741 const time = lastMoveEvent.time - velocityEvent.time;
8742 swiper.velocity = distance / time;
8743 swiper.velocity /= 2;
8744
8745 if (Math.abs(swiper.velocity) < params.freeMode.minimumVelocity) {
8746 swiper.velocity = 0;
8747 } // this implies that the user stopped moving a finger then released.
8748 // There would be no events with distance zero, so the last event is stale.
8749
8750
8751 if (time > 150 || now() - lastMoveEvent.time > 300) {
8752 swiper.velocity = 0;
8753 }
8754 } else {
8755 swiper.velocity = 0;
8756 }
8757
8758 swiper.velocity *= params.freeMode.momentumVelocityRatio;
8759 data.velocities.length = 0;
8760 let momentumDuration = 1000 * params.freeMode.momentumRatio;
8761 const momentumDistance = swiper.velocity * momentumDuration;
8762 let newPosition = swiper.translate + momentumDistance;
8763 if (rtl) newPosition = -newPosition;
8764 let doBounce = false;
8765 let afterBouncePosition;
8766 const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeMode.momentumBounceRatio;
8767 let needsLoopFix;
8768
8769 if (newPosition < swiper.maxTranslate()) {
8770 if (params.freeMode.momentumBounce) {
8771 if (newPosition + swiper.maxTranslate() < -bounceAmount) {
8772 newPosition = swiper.maxTranslate() - bounceAmount;
8773 }
8774
8775 afterBouncePosition = swiper.maxTranslate();
8776 doBounce = true;
8777 data.allowMomentumBounce = true;
8778 } else {
8779 newPosition = swiper.maxTranslate();
8780 }
8781
8782 if (params.loop && params.centeredSlides) needsLoopFix = true;
8783 } else if (newPosition > swiper.minTranslate()) {
8784 if (params.freeMode.momentumBounce) {
8785 if (newPosition - swiper.minTranslate() > bounceAmount) {
8786 newPosition = swiper.minTranslate() + bounceAmount;
8787 }
8788
8789 afterBouncePosition = swiper.minTranslate();
8790 doBounce = true;
8791 data.allowMomentumBounce = true;
8792 } else {
8793 newPosition = swiper.minTranslate();
8794 }
8795
8796 if (params.loop && params.centeredSlides) needsLoopFix = true;
8797 } else if (params.freeMode.sticky) {
8798 let nextSlide;
8799
8800 for (let j = 0; j < snapGrid.length; j += 1) {
8801 if (snapGrid[j] > -newPosition) {
8802 nextSlide = j;
8803 break;
8804 }
8805 }
8806
8807 if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
8808 newPosition = snapGrid[nextSlide];
8809 } else {
8810 newPosition = snapGrid[nextSlide - 1];
8811 }
8812
8813 newPosition = -newPosition;
8814 }
8815
8816 if (needsLoopFix) {
8817 once('transitionEnd', () => {
8818 swiper.loopFix();
8819 });
8820 } // Fix duration
8821
8822
8823 if (swiper.velocity !== 0) {
8824 if (rtl) {
8825 momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
8826 } else {
8827 momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
8828 }
8829
8830 if (params.freeMode.sticky) {
8831 // If freeMode.sticky is active and the user ends a swipe with a slow-velocity
8832 // event, then durations can be 20+ seconds to slide one (or zero!) slides.
8833 // It's easy to see this when simulating touch with mouse events. To fix this,
8834 // limit single-slide swipes to the default slide duration. This also has the
8835 // nice side effect of matching slide speed if the user stopped moving before
8836 // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
8837 // For faster swipes, also apply limits (albeit higher ones).
8838 const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
8839 const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
8840
8841 if (moveDistance < currentSlideSize) {
8842 momentumDuration = params.speed;
8843 } else if (moveDistance < 2 * currentSlideSize) {
8844 momentumDuration = params.speed * 1.5;
8845 } else {
8846 momentumDuration = params.speed * 2.5;
8847 }
8848 }
8849 } else if (params.freeMode.sticky) {
8850 swiper.slideToClosest();
8851 return;
8852 }
8853
8854 if (params.freeMode.momentumBounce && doBounce) {
8855 swiper.updateProgress(afterBouncePosition);
8856 swiper.setTransition(momentumDuration);
8857 swiper.setTranslate(newPosition);
8858 swiper.transitionStart(true, swiper.swipeDirection);
8859 swiper.animating = true;
8860 $wrapperEl.transitionEnd(() => {
8861 if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
8862 emit('momentumBounce');
8863 swiper.setTransition(params.speed);
8864 setTimeout(() => {
8865 swiper.setTranslate(afterBouncePosition);
8866 $wrapperEl.transitionEnd(() => {
8867 if (!swiper || swiper.destroyed) return;
8868 swiper.transitionEnd();
8869 });
8870 }, 0);
8871 });
8872 } else if (swiper.velocity) {
8873 emit('_freeModeNoMomentumRelease');
8874 swiper.updateProgress(newPosition);
8875 swiper.setTransition(momentumDuration);
8876 swiper.setTranslate(newPosition);
8877 swiper.transitionStart(true, swiper.swipeDirection);
8878
8879 if (!swiper.animating) {
8880 swiper.animating = true;
8881 $wrapperEl.transitionEnd(() => {
8882 if (!swiper || swiper.destroyed) return;
8883 swiper.transitionEnd();
8884 });
8885 }
8886 } else {
8887 swiper.updateProgress(newPosition);
8888 }
8889
8890 swiper.updateActiveIndex();
8891 swiper.updateSlidesClasses();
8892 } else if (params.freeMode.sticky) {
8893 swiper.slideToClosest();
8894 return;
8895 } else if (params.freeMode) {
8896 emit('_freeModeNoMomentumRelease');
8897 }
8898
8899 if (!params.freeMode.momentum || timeDiff >= params.longSwipesMs) {
8900 swiper.updateProgress();
8901 swiper.updateActiveIndex();
8902 swiper.updateSlidesClasses();
8903 }
8904 }
8905
8906 Object.assign(swiper, {
8907 freeMode: {
8908 onTouchMove,
8909 onTouchEnd
8910 }
8911 });
8912 }
8913
8914 function Grid({
8915 swiper,
8916 extendParams
8917 }) {
8918 extendParams({
8919 grid: {
8920 rows: 1,
8921 fill: 'column'
8922 }
8923 });
8924 let slidesNumberEvenToRows;
8925 let slidesPerRow;
8926 let numFullColumns;
8927
8928 const initSlides = slidesLength => {
8929 const {
8930 slidesPerView
8931 } = swiper.params;
8932 const {
8933 rows,
8934 fill
8935 } = swiper.params.grid;
8936 slidesPerRow = slidesNumberEvenToRows / rows;
8937 numFullColumns = Math.floor(slidesLength / rows);
8938
8939 if (Math.floor(slidesLength / rows) === slidesLength / rows) {
8940 slidesNumberEvenToRows = slidesLength;
8941 } else {
8942 slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows;
8943 }
8944
8945 if (slidesPerView !== 'auto' && fill === 'row') {
8946 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, slidesPerView * rows);
8947 }
8948 };
8949
8950 const updateSlide = (i, slide, slidesLength, getDirectionLabel) => {
8951 const {
8952 slidesPerGroup,
8953 spaceBetween
8954 } = swiper.params;
8955 const {
8956 rows,
8957 fill
8958 } = swiper.params.grid; // Set slides order
8959
8960 let newSlideOrderIndex;
8961 let column;
8962 let row;
8963
8964 if (fill === 'row' && slidesPerGroup > 1) {
8965 const groupIndex = Math.floor(i / (slidesPerGroup * rows));
8966 const slideIndexInGroup = i - rows * slidesPerGroup * groupIndex;
8967 const columnsInGroup = groupIndex === 0 ? slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * rows * slidesPerGroup) / rows), slidesPerGroup);
8968 row = Math.floor(slideIndexInGroup / columnsInGroup);
8969 column = slideIndexInGroup - row * columnsInGroup + groupIndex * slidesPerGroup;
8970 newSlideOrderIndex = column + row * slidesNumberEvenToRows / rows;
8971 slide.css({
8972 '-webkit-order': newSlideOrderIndex,
8973 order: newSlideOrderIndex
8974 });
8975 } else if (fill === 'column') {
8976 column = Math.floor(i / rows);
8977 row = i - column * rows;
8978
8979 if (column > numFullColumns || column === numFullColumns && row === rows - 1) {
8980 row += 1;
8981
8982 if (row >= rows) {
8983 row = 0;
8984 column += 1;
8985 }
8986 }
8987 } else {
8988 row = Math.floor(i / slidesPerRow);
8989 column = i - row * slidesPerRow;
8990 }
8991
8992 slide.css(getDirectionLabel('margin-top'), row !== 0 ? spaceBetween && `${spaceBetween}px` : '');
8993 };
8994
8995 const updateWrapperSize = (slideSize, snapGrid, getDirectionLabel) => {
8996 const {
8997 spaceBetween,
8998 centeredSlides,
8999 roundLengths
9000 } = swiper.params;
9001 const {
9002 rows
9003 } = swiper.params.grid;
9004 swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows;
9005 swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween;
9006 swiper.$wrapperEl.css({
9007 [getDirectionLabel('width')]: `${swiper.virtualSize + spaceBetween}px`
9008 });
9009
9010 if (centeredSlides) {
9011 snapGrid.splice(0, snapGrid.length);
9012 const newSlidesGrid = [];
9013
9014 for (let i = 0; i < snapGrid.length; i += 1) {
9015 let slidesGridItem = snapGrid[i];
9016 if (roundLengths) slidesGridItem = Math.floor(slidesGridItem);
9017 if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
9018 }
9019
9020 snapGrid.push(...newSlidesGrid);
9021 }
9022 };
9023
9024 swiper.grid = {
9025 initSlides,
9026 updateSlide,
9027 updateWrapperSize
9028 };
9029 }
9030
9031 function appendSlide(slides) {
9032 const swiper = this;
9033 const {
9034 $wrapperEl,
9035 params
9036 } = swiper;
9037
9038 if (params.loop) {
9039 swiper.loopDestroy();
9040 }
9041
9042 if (typeof slides === 'object' && 'length' in slides) {
9043 for (let i = 0; i < slides.length; i += 1) {
9044 if (slides[i]) $wrapperEl.append(slides[i]);
9045 }
9046 } else {
9047 $wrapperEl.append(slides);
9048 }
9049
9050 if (params.loop) {
9051 swiper.loopCreate();
9052 }
9053
9054 if (!params.observer) {
9055 swiper.update();
9056 }
9057 }
9058
9059 function prependSlide(slides) {
9060 const swiper = this;
9061 const {
9062 params,
9063 $wrapperEl,
9064 activeIndex
9065 } = swiper;
9066
9067 if (params.loop) {
9068 swiper.loopDestroy();
9069 }
9070
9071 let newActiveIndex = activeIndex + 1;
9072
9073 if (typeof slides === 'object' && 'length' in slides) {
9074 for (let i = 0; i < slides.length; i += 1) {
9075 if (slides[i]) $wrapperEl.prepend(slides[i]);
9076 }
9077
9078 newActiveIndex = activeIndex + slides.length;
9079 } else {
9080 $wrapperEl.prepend(slides);
9081 }
9082
9083 if (params.loop) {
9084 swiper.loopCreate();
9085 }
9086
9087 if (!params.observer) {
9088 swiper.update();
9089 }
9090
9091 swiper.slideTo(newActiveIndex, 0, false);
9092 }
9093
9094 function addSlide(index, slides) {
9095 const swiper = this;
9096 const {
9097 $wrapperEl,
9098 params,
9099 activeIndex
9100 } = swiper;
9101 let activeIndexBuffer = activeIndex;
9102
9103 if (params.loop) {
9104 activeIndexBuffer -= swiper.loopedSlides;
9105 swiper.loopDestroy();
9106 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
9107 }
9108
9109 const baseLength = swiper.slides.length;
9110
9111 if (index <= 0) {
9112 swiper.prependSlide(slides);
9113 return;
9114 }
9115
9116 if (index >= baseLength) {
9117 swiper.appendSlide(slides);
9118 return;
9119 }
9120
9121 let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
9122 const slidesBuffer = [];
9123
9124 for (let i = baseLength - 1; i >= index; i -= 1) {
9125 const currentSlide = swiper.slides.eq(i);
9126 currentSlide.remove();
9127 slidesBuffer.unshift(currentSlide);
9128 }
9129
9130 if (typeof slides === 'object' && 'length' in slides) {
9131 for (let i = 0; i < slides.length; i += 1) {
9132 if (slides[i]) $wrapperEl.append(slides[i]);
9133 }
9134
9135 newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
9136 } else {
9137 $wrapperEl.append(slides);
9138 }
9139
9140 for (let i = 0; i < slidesBuffer.length; i += 1) {
9141 $wrapperEl.append(slidesBuffer[i]);
9142 }
9143
9144 if (params.loop) {
9145 swiper.loopCreate();
9146 }
9147
9148 if (!params.observer) {
9149 swiper.update();
9150 }
9151
9152 if (params.loop) {
9153 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
9154 } else {
9155 swiper.slideTo(newActiveIndex, 0, false);
9156 }
9157 }
9158
9159 function removeSlide(slidesIndexes) {
9160 const swiper = this;
9161 const {
9162 params,
9163 $wrapperEl,
9164 activeIndex
9165 } = swiper;
9166 let activeIndexBuffer = activeIndex;
9167
9168 if (params.loop) {
9169 activeIndexBuffer -= swiper.loopedSlides;
9170 swiper.loopDestroy();
9171 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
9172 }
9173
9174 let newActiveIndex = activeIndexBuffer;
9175 let indexToRemove;
9176
9177 if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
9178 for (let i = 0; i < slidesIndexes.length; i += 1) {
9179 indexToRemove = slidesIndexes[i];
9180 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
9181 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
9182 }
9183
9184 newActiveIndex = Math.max(newActiveIndex, 0);
9185 } else {
9186 indexToRemove = slidesIndexes;
9187 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
9188 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
9189 newActiveIndex = Math.max(newActiveIndex, 0);
9190 }
9191
9192 if (params.loop) {
9193 swiper.loopCreate();
9194 }
9195
9196 if (!params.observer) {
9197 swiper.update();
9198 }
9199
9200 if (params.loop) {
9201 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
9202 } else {
9203 swiper.slideTo(newActiveIndex, 0, false);
9204 }
9205 }
9206
9207 function removeAllSlides() {
9208 const swiper = this;
9209 const slidesIndexes = [];
9210
9211 for (let i = 0; i < swiper.slides.length; i += 1) {
9212 slidesIndexes.push(i);
9213 }
9214
9215 swiper.removeSlide(slidesIndexes);
9216 }
9217
9218 function Manipulation({
9219 swiper
9220 }) {
9221 Object.assign(swiper, {
9222 appendSlide: appendSlide.bind(swiper),
9223 prependSlide: prependSlide.bind(swiper),
9224 addSlide: addSlide.bind(swiper),
9225 removeSlide: removeSlide.bind(swiper),
9226 removeAllSlides: removeAllSlides.bind(swiper)
9227 });
9228 }
9229
9230 function effectInit(params) {
9231 const {
9232 effect,
9233 swiper,
9234 on,
9235 setTranslate,
9236 setTransition,
9237 overwriteParams,
9238 perspective
9239 } = params;
9240 on('beforeInit', () => {
9241 if (swiper.params.effect !== effect) return;
9242 swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`);
9243
9244 if (perspective && perspective()) {
9245 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
9246 }
9247
9248 const overwriteParamsResult = overwriteParams ? overwriteParams() : {};
9249 Object.assign(swiper.params, overwriteParamsResult);
9250 Object.assign(swiper.originalParams, overwriteParamsResult);
9251 });
9252 on('setTranslate', () => {
9253 if (swiper.params.effect !== effect) return;
9254 setTranslate();
9255 });
9256 on('setTransition', (_s, duration) => {
9257 if (swiper.params.effect !== effect) return;
9258 setTransition(duration);
9259 });
9260 }
9261
9262 function effectTarget(effectParams, $slideEl) {
9263 if (effectParams.transformEl) {
9264 return $slideEl.find(effectParams.transformEl).css({
9265 'backface-visibility': 'hidden',
9266 '-webkit-backface-visibility': 'hidden'
9267 });
9268 }
9269
9270 return $slideEl;
9271 }
9272
9273 function effectVirtualTransitionEnd({
9274 swiper,
9275 duration,
9276 transformEl,
9277 allSlides
9278 }) {
9279 const {
9280 slides,
9281 activeIndex,
9282 $wrapperEl
9283 } = swiper;
9284
9285 if (swiper.params.virtualTranslate && duration !== 0) {
9286 let eventTriggered = false;
9287 let $transitionEndTarget;
9288
9289 if (allSlides) {
9290 $transitionEndTarget = transformEl ? slides.find(transformEl) : slides;
9291 } else {
9292 $transitionEndTarget = transformEl ? slides.eq(activeIndex).find(transformEl) : slides.eq(activeIndex);
9293 }
9294
9295 $transitionEndTarget.transitionEnd(() => {
9296 if (eventTriggered) return;
9297 if (!swiper || swiper.destroyed) return;
9298 eventTriggered = true;
9299 swiper.animating = false;
9300 const triggerEvents = ['webkitTransitionEnd', 'transitionend'];
9301
9302 for (let i = 0; i < triggerEvents.length; i += 1) {
9303 $wrapperEl.trigger(triggerEvents[i]);
9304 }
9305 });
9306 }
9307 }
9308
9309 function EffectFade({
9310 swiper,
9311 extendParams,
9312 on
9313 }) {
9314 extendParams({
9315 fadeEffect: {
9316 crossFade: false,
9317 transformEl: null
9318 }
9319 });
9320
9321 const setTranslate = () => {
9322 const {
9323 slides
9324 } = swiper;
9325 const params = swiper.params.fadeEffect;
9326
9327 for (let i = 0; i < slides.length; i += 1) {
9328 const $slideEl = swiper.slides.eq(i);
9329 const offset = $slideEl[0].swiperSlideOffset;
9330 let tx = -offset;
9331 if (!swiper.params.virtualTranslate) tx -= swiper.translate;
9332 let ty = 0;
9333
9334 if (!swiper.isHorizontal()) {
9335 ty = tx;
9336 tx = 0;
9337 }
9338
9339 const slideOpacity = swiper.params.fadeEffect.crossFade ? Math.max(1 - Math.abs($slideEl[0].progress), 0) : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);
9340 const $targetEl = effectTarget(params, $slideEl);
9341 $targetEl.css({
9342 opacity: slideOpacity
9343 }).transform(`translate3d(${tx}px, ${ty}px, 0px)`);
9344 }
9345 };
9346
9347 const setTransition = duration => {
9348 const {
9349 transformEl
9350 } = swiper.params.fadeEffect;
9351 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9352 $transitionElements.transition(duration);
9353 effectVirtualTransitionEnd({
9354 swiper,
9355 duration,
9356 transformEl,
9357 allSlides: true
9358 });
9359 };
9360
9361 effectInit({
9362 effect: 'fade',
9363 swiper,
9364 on,
9365 setTranslate,
9366 setTransition,
9367 overwriteParams: () => ({
9368 slidesPerView: 1,
9369 slidesPerGroup: 1,
9370 watchSlidesProgress: true,
9371 spaceBetween: 0,
9372 virtualTranslate: !swiper.params.cssMode
9373 })
9374 });
9375 }
9376
9377 function EffectCube({
9378 swiper,
9379 extendParams,
9380 on
9381 }) {
9382 extendParams({
9383 cubeEffect: {
9384 slideShadows: true,
9385 shadow: true,
9386 shadowOffset: 20,
9387 shadowScale: 0.94
9388 }
9389 });
9390
9391 const setTranslate = () => {
9392 const {
9393 $el,
9394 $wrapperEl,
9395 slides,
9396 width: swiperWidth,
9397 height: swiperHeight,
9398 rtlTranslate: rtl,
9399 size: swiperSize,
9400 browser
9401 } = swiper;
9402 const params = swiper.params.cubeEffect;
9403 const isHorizontal = swiper.isHorizontal();
9404 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
9405 let wrapperRotate = 0;
9406 let $cubeShadowEl;
9407
9408 if (params.shadow) {
9409 if (isHorizontal) {
9410 $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');
9411
9412 if ($cubeShadowEl.length === 0) {
9413 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
9414 $wrapperEl.append($cubeShadowEl);
9415 }
9416
9417 $cubeShadowEl.css({
9418 height: `${swiperWidth}px`
9419 });
9420 } else {
9421 $cubeShadowEl = $el.find('.swiper-cube-shadow');
9422
9423 if ($cubeShadowEl.length === 0) {
9424 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
9425 $el.append($cubeShadowEl);
9426 }
9427 }
9428 }
9429
9430 for (let i = 0; i < slides.length; i += 1) {
9431 const $slideEl = slides.eq(i);
9432 let slideIndex = i;
9433
9434 if (isVirtual) {
9435 slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);
9436 }
9437
9438 let slideAngle = slideIndex * 90;
9439 let round = Math.floor(slideAngle / 360);
9440
9441 if (rtl) {
9442 slideAngle = -slideAngle;
9443 round = Math.floor(-slideAngle / 360);
9444 }
9445
9446 const progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
9447 let tx = 0;
9448 let ty = 0;
9449 let tz = 0;
9450
9451 if (slideIndex % 4 === 0) {
9452 tx = -round * 4 * swiperSize;
9453 tz = 0;
9454 } else if ((slideIndex - 1) % 4 === 0) {
9455 tx = 0;
9456 tz = -round * 4 * swiperSize;
9457 } else if ((slideIndex - 2) % 4 === 0) {
9458 tx = swiperSize + round * 4 * swiperSize;
9459 tz = swiperSize;
9460 } else if ((slideIndex - 3) % 4 === 0) {
9461 tx = -swiperSize;
9462 tz = 3 * swiperSize + swiperSize * 4 * round;
9463 }
9464
9465 if (rtl) {
9466 tx = -tx;
9467 }
9468
9469 if (!isHorizontal) {
9470 ty = tx;
9471 tx = 0;
9472 }
9473
9474 const transform = `rotateX(${isHorizontal ? 0 : -slideAngle}deg) rotateY(${isHorizontal ? slideAngle : 0}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;
9475
9476 if (progress <= 1 && progress > -1) {
9477 wrapperRotate = slideIndex * 90 + progress * 90;
9478 if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90;
9479 }
9480
9481 $slideEl.transform(transform);
9482
9483 if (params.slideShadows) {
9484 // Set shadows
9485 let shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9486 let shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9487
9488 if (shadowBefore.length === 0) {
9489 shadowBefore = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}"></div>`);
9490 $slideEl.append(shadowBefore);
9491 }
9492
9493 if (shadowAfter.length === 0) {
9494 shadowAfter = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}"></div>`);
9495 $slideEl.append(shadowAfter);
9496 }
9497
9498 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
9499 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
9500 }
9501 }
9502
9503 $wrapperEl.css({
9504 '-webkit-transform-origin': `50% 50% -${swiperSize / 2}px`,
9505 'transform-origin': `50% 50% -${swiperSize / 2}px`
9506 });
9507
9508 if (params.shadow) {
9509 if (isHorizontal) {
9510 $cubeShadowEl.transform(`translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(90deg) rotateZ(0deg) scale(${params.shadowScale})`);
9511 } else {
9512 const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
9513 const multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
9514 const scale1 = params.shadowScale;
9515 const scale2 = params.shadowScale / multiplier;
9516 const offset = params.shadowOffset;
9517 $cubeShadowEl.transform(`scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-90deg)`);
9518 }
9519 }
9520
9521 const zFactor = browser.isSafari || browser.isWebView ? -swiperSize / 2 : 0;
9522 $wrapperEl.transform(`translate3d(0px,0,${zFactor}px) rotateX(${swiper.isHorizontal() ? 0 : wrapperRotate}deg) rotateY(${swiper.isHorizontal() ? -wrapperRotate : 0}deg)`);
9523 };
9524
9525 const setTransition = duration => {
9526 const {
9527 $el,
9528 slides
9529 } = swiper;
9530 slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9531
9532 if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
9533 $el.find('.swiper-cube-shadow').transition(duration);
9534 }
9535 };
9536
9537 effectInit({
9538 effect: 'cube',
9539 swiper,
9540 on,
9541 setTranslate,
9542 setTransition,
9543 perspective: () => true,
9544 overwriteParams: () => ({
9545 slidesPerView: 1,
9546 slidesPerGroup: 1,
9547 watchSlidesProgress: true,
9548 resistanceRatio: 0,
9549 spaceBetween: 0,
9550 centeredSlides: false,
9551 virtualTranslate: true
9552 })
9553 });
9554 }
9555
9556 function createShadow(params, $slideEl, side) {
9557 const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}`;
9558 const $shadowContainer = params.transformEl ? $slideEl.find(params.transformEl) : $slideEl;
9559 let $shadowEl = $shadowContainer.children(`.${shadowClass}`);
9560
9561 if (!$shadowEl.length) {
9562 $shadowEl = $(`<div class="swiper-slide-shadow${side ? `-${side}` : ''}"></div>`);
9563 $shadowContainer.append($shadowEl);
9564 }
9565
9566 return $shadowEl;
9567 }
9568
9569 function EffectFlip({
9570 swiper,
9571 extendParams,
9572 on
9573 }) {
9574 extendParams({
9575 flipEffect: {
9576 slideShadows: true,
9577 limitRotation: true,
9578 transformEl: null
9579 }
9580 });
9581
9582 const setTranslate = () => {
9583 const {
9584 slides,
9585 rtlTranslate: rtl
9586 } = swiper;
9587 const params = swiper.params.flipEffect;
9588
9589 for (let i = 0; i < slides.length; i += 1) {
9590 const $slideEl = slides.eq(i);
9591 let progress = $slideEl[0].progress;
9592
9593 if (swiper.params.flipEffect.limitRotation) {
9594 progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
9595 }
9596
9597 const offset = $slideEl[0].swiperSlideOffset;
9598 const rotate = -180 * progress;
9599 let rotateY = rotate;
9600 let rotateX = 0;
9601 let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset;
9602 let ty = 0;
9603
9604 if (!swiper.isHorizontal()) {
9605 ty = tx;
9606 tx = 0;
9607 rotateX = -rotateY;
9608 rotateY = 0;
9609 } else if (rtl) {
9610 rotateY = -rotateY;
9611 }
9612
9613 $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
9614
9615 if (params.slideShadows) {
9616 // Set shadows
9617 let shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9618 let shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9619
9620 if (shadowBefore.length === 0) {
9621 shadowBefore = createShadow(params, $slideEl, swiper.isHorizontal() ? 'left' : 'top');
9622 }
9623
9624 if (shadowAfter.length === 0) {
9625 shadowAfter = createShadow(params, $slideEl, swiper.isHorizontal() ? 'right' : 'bottom');
9626 }
9627
9628 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
9629 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
9630 }
9631
9632 const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
9633 const $targetEl = effectTarget(params, $slideEl);
9634 $targetEl.transform(transform);
9635 }
9636 };
9637
9638 const setTransition = duration => {
9639 const {
9640 transformEl
9641 } = swiper.params.flipEffect;
9642 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9643 $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9644 effectVirtualTransitionEnd({
9645 swiper,
9646 duration,
9647 transformEl
9648 });
9649 };
9650
9651 effectInit({
9652 effect: 'flip',
9653 swiper,
9654 on,
9655 setTranslate,
9656 setTransition,
9657 perspective: () => true,
9658 overwriteParams: () => ({
9659 slidesPerView: 1,
9660 slidesPerGroup: 1,
9661 watchSlidesProgress: true,
9662 spaceBetween: 0,
9663 virtualTranslate: !swiper.params.cssMode
9664 })
9665 });
9666 }
9667
9668 function EffectCoverflow({
9669 swiper,
9670 extendParams,
9671 on
9672 }) {
9673 extendParams({
9674 coverflowEffect: {
9675 rotate: 50,
9676 stretch: 0,
9677 depth: 100,
9678 scale: 1,
9679 modifier: 1,
9680 slideShadows: true,
9681 transformEl: null
9682 }
9683 });
9684
9685 const setTranslate = () => {
9686 const {
9687 width: swiperWidth,
9688 height: swiperHeight,
9689 slides,
9690 slidesSizesGrid
9691 } = swiper;
9692 const params = swiper.params.coverflowEffect;
9693 const isHorizontal = swiper.isHorizontal();
9694 const transform = swiper.translate;
9695 const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2;
9696 const rotate = isHorizontal ? params.rotate : -params.rotate;
9697 const translate = params.depth; // Each slide offset from center
9698
9699 for (let i = 0, length = slides.length; i < length; i += 1) {
9700 const $slideEl = slides.eq(i);
9701 const slideSize = slidesSizesGrid[i];
9702 const slideOffset = $slideEl[0].swiperSlideOffset;
9703 const offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * params.modifier;
9704 let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
9705 let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier; // var rotateZ = 0
9706
9707 let translateZ = -translate * Math.abs(offsetMultiplier);
9708 let stretch = params.stretch; // Allow percentage to make a relative stretch for responsive sliders
9709
9710 if (typeof stretch === 'string' && stretch.indexOf('%') !== -1) {
9711 stretch = parseFloat(params.stretch) / 100 * slideSize;
9712 }
9713
9714 let translateY = isHorizontal ? 0 : stretch * offsetMultiplier;
9715 let translateX = isHorizontal ? stretch * offsetMultiplier : 0;
9716 let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier); // Fix for ultra small values
9717
9718 if (Math.abs(translateX) < 0.001) translateX = 0;
9719 if (Math.abs(translateY) < 0.001) translateY = 0;
9720 if (Math.abs(translateZ) < 0.001) translateZ = 0;
9721 if (Math.abs(rotateY) < 0.001) rotateY = 0;
9722 if (Math.abs(rotateX) < 0.001) rotateX = 0;
9723 if (Math.abs(scale) < 0.001) scale = 0;
9724 const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${scale})`;
9725 const $targetEl = effectTarget(params, $slideEl);
9726 $targetEl.transform(slideTransform);
9727 $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
9728
9729 if (params.slideShadows) {
9730 // Set shadows
9731 let $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9732 let $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9733
9734 if ($shadowBeforeEl.length === 0) {
9735 $shadowBeforeEl = createShadow(params, $slideEl, isHorizontal ? 'left' : 'top');
9736 }
9737
9738 if ($shadowAfterEl.length === 0) {
9739 $shadowAfterEl = createShadow(params, $slideEl, isHorizontal ? 'right' : 'bottom');
9740 }
9741
9742 if ($shadowBeforeEl.length) $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
9743 if ($shadowAfterEl.length) $shadowAfterEl[0].style.opacity = -offsetMultiplier > 0 ? -offsetMultiplier : 0;
9744 }
9745 }
9746 };
9747
9748 const setTransition = duration => {
9749 const {
9750 transformEl
9751 } = swiper.params.coverflowEffect;
9752 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9753 $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9754 };
9755
9756 effectInit({
9757 effect: 'coverflow',
9758 swiper,
9759 on,
9760 setTranslate,
9761 setTransition,
9762 perspective: () => true,
9763 overwriteParams: () => ({
9764 watchSlidesProgress: true
9765 })
9766 });
9767 }
9768
9769 function EffectCreative({
9770 swiper,
9771 extendParams,
9772 on
9773 }) {
9774 extendParams({
9775 creativeEffect: {
9776 transformEl: null,
9777 limitProgress: 1,
9778 shadowPerProgress: false,
9779 progressMultiplier: 1,
9780 perspective: true,
9781 prev: {
9782 translate: [0, 0, 0],
9783 rotate: [0, 0, 0],
9784 opacity: 1,
9785 scale: 1
9786 },
9787 next: {
9788 translate: [0, 0, 0],
9789 rotate: [0, 0, 0],
9790 opacity: 1,
9791 scale: 1
9792 }
9793 }
9794 });
9795
9796 const getTranslateValue = value => {
9797 if (typeof value === 'string') return value;
9798 return `${value}px`;
9799 };
9800
9801 const setTranslate = () => {
9802 const {
9803 slides
9804 } = swiper;
9805 const params = swiper.params.creativeEffect;
9806 const {
9807 progressMultiplier: multiplier
9808 } = params;
9809
9810 for (let i = 0; i < slides.length; i += 1) {
9811 const $slideEl = slides.eq(i);
9812 const slideProgress = $slideEl[0].progress;
9813 const progress = Math.min(Math.max($slideEl[0].progress, -params.limitProgress), params.limitProgress);
9814 const offset = $slideEl[0].swiperSlideOffset;
9815 const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0];
9816 const r = [0, 0, 0];
9817 let custom = false;
9818
9819 if (!swiper.isHorizontal()) {
9820 t[1] = t[0];
9821 t[0] = 0;
9822 }
9823
9824 let data = {
9825 translate: [0, 0, 0],
9826 rotate: [0, 0, 0],
9827 scale: 1,
9828 opacity: 1
9829 };
9830
9831 if (progress < 0) {
9832 data = params.next;
9833 custom = true;
9834 } else if (progress > 0) {
9835 data = params.prev;
9836 custom = true;
9837 } // set translate
9838
9839
9840 t.forEach((value, index) => {
9841 t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`;
9842 }); // set rotates
9843
9844 r.forEach((value, index) => {
9845 r[index] = data.rotate[index] * Math.abs(progress * multiplier);
9846 });
9847 $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
9848 const translateString = t.join(', ');
9849 const rotateString = `rotateX(${r[0]}deg) rotateY(${r[1]}deg) rotateZ(${r[2]}deg)`;
9850 const scaleString = progress < 0 ? `scale(${1 + (1 - data.scale) * progress * multiplier})` : `scale(${1 - (1 - data.scale) * progress * multiplier})`;
9851 const opacityString = progress < 0 ? 1 + (1 - data.opacity) * progress * multiplier : 1 - (1 - data.opacity) * progress * multiplier;
9852 const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`; // Set shadows
9853
9854 if (custom && data.shadow || !custom) {
9855 let $shadowEl = $slideEl.children('.swiper-slide-shadow');
9856
9857 if ($shadowEl.length === 0 && data.shadow) {
9858 $shadowEl = createShadow(params, $slideEl);
9859 }
9860
9861 if ($shadowEl.length) {
9862 const shadowOpacity = params.shadowPerProgress ? progress * (1 / params.limitProgress) : progress;
9863 $shadowEl[0].style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1);
9864 }
9865 }
9866
9867 const $targetEl = effectTarget(params, $slideEl);
9868 $targetEl.transform(transform).css({
9869 opacity: opacityString
9870 });
9871
9872 if (data.origin) {
9873 $targetEl.css('transform-origin', data.origin);
9874 }
9875 }
9876 };
9877
9878 const setTransition = duration => {
9879 const {
9880 transformEl
9881 } = swiper.params.creativeEffect;
9882 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9883 $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);
9884 effectVirtualTransitionEnd({
9885 swiper,
9886 duration,
9887 transformEl,
9888 allSlides: true
9889 });
9890 };
9891
9892 effectInit({
9893 effect: 'creative',
9894 swiper,
9895 on,
9896 setTranslate,
9897 setTransition,
9898 perspective: () => swiper.params.creativeEffect.perspective,
9899 overwriteParams: () => ({
9900 watchSlidesProgress: true,
9901 virtualTranslate: !swiper.params.cssMode
9902 })
9903 });
9904 }
9905
9906 function EffectCards({
9907 swiper,
9908 extendParams,
9909 on
9910 }) {
9911 extendParams({
9912 cardsEffect: {
9913 slideShadows: true,
9914 transformEl: null
9915 }
9916 });
9917
9918 const setTranslate = () => {
9919 const {
9920 slides,
9921 activeIndex
9922 } = swiper;
9923 const params = swiper.params.cardsEffect;
9924 const {
9925 startTranslate,
9926 isTouched
9927 } = swiper.touchEventsData;
9928 const currentTranslate = swiper.translate;
9929
9930 for (let i = 0; i < slides.length; i += 1) {
9931 const $slideEl = slides.eq(i);
9932 const slideProgress = $slideEl[0].progress;
9933 const progress = Math.min(Math.max(slideProgress, -4), 4);
9934 let offset = $slideEl[0].swiperSlideOffset;
9935
9936 if (swiper.params.centeredSlides && !swiper.params.cssMode) {
9937 swiper.$wrapperEl.transform(`translateX(${swiper.minTranslate()}px)`);
9938 }
9939
9940 if (swiper.params.centeredSlides && swiper.params.cssMode) {
9941 offset -= slides[0].swiperSlideOffset;
9942 }
9943
9944 let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset;
9945 let tY = 0;
9946 const tZ = -100 * Math.abs(progress);
9947 let scale = 1;
9948 let rotate = -2 * progress;
9949 let tXAdd = 8 - Math.abs(progress) * 0.75;
9950 const isSwipeToNext = (i === activeIndex || i === activeIndex - 1) && progress > 0 && progress < 1 && (isTouched || swiper.params.cssMode) && currentTranslate < startTranslate;
9951 const isSwipeToPrev = (i === activeIndex || i === activeIndex + 1) && progress < 0 && progress > -1 && (isTouched || swiper.params.cssMode) && currentTranslate > startTranslate;
9952
9953 if (isSwipeToNext || isSwipeToPrev) {
9954 const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5;
9955 rotate += -28 * progress * subProgress;
9956 scale += -0.5 * subProgress;
9957 tXAdd += 96 * subProgress;
9958 tY = `${-25 * subProgress * Math.abs(progress)}%`;
9959 }
9960
9961 if (progress < 0) {
9962 // next
9963 tX = `calc(${tX}px + (${tXAdd * Math.abs(progress)}%))`;
9964 } else if (progress > 0) {
9965 // prev
9966 tX = `calc(${tX}px + (-${tXAdd * Math.abs(progress)}%))`;
9967 } else {
9968 tX = `${tX}px`;
9969 }
9970
9971 if (!swiper.isHorizontal()) {
9972 const prevY = tY;
9973 tY = tX;
9974 tX = prevY;
9975 }
9976
9977 const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`;
9978 const transform = `
9979 translate3d(${tX}, ${tY}, ${tZ}px)
9980 rotateZ(${rotate}deg)
9981 scale(${scaleString})
9982 `;
9983
9984 if (params.slideShadows) {
9985 // Set shadows
9986 let $shadowEl = $slideEl.find('.swiper-slide-shadow');
9987
9988 if ($shadowEl.length === 0) {
9989 $shadowEl = createShadow(params, $slideEl);
9990 }
9991
9992 if ($shadowEl.length) $shadowEl[0].style.opacity = Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1);
9993 }
9994
9995 $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
9996 const $targetEl = effectTarget(params, $slideEl);
9997 $targetEl.transform(transform);
9998 }
9999 };
10000
10001 const setTransition = duration => {
10002 const {
10003 transformEl
10004 } = swiper.params.cardsEffect;
10005 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
10006 $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);
10007 effectVirtualTransitionEnd({
10008 swiper,
10009 duration,
10010 transformEl
10011 });
10012 };
10013
10014 effectInit({
10015 effect: 'cards',
10016 swiper,
10017 on,
10018 setTranslate,
10019 setTransition,
10020 perspective: () => true,
10021 overwriteParams: () => ({
10022 watchSlidesProgress: true,
10023 virtualTranslate: !swiper.params.cssMode
10024 })
10025 });
10026 }
10027
10028 // Swiper Class
10029 const modules = [Virtual, Keyboard, Mousewheel, Navigation, Pagination, Scrollbar, Parallax, Zoom, Lazy, Controller, A11y, History, HashNavigation, Autoplay, Thumb, freeMode, Grid, Manipulation, EffectFade, EffectCube, EffectFlip, EffectCoverflow, EffectCreative, EffectCards];
10030 Swiper.use(modules);
10031
10032 return Swiper;
10033
10034})));
10035//# sourceMappingURL=swiper-bundle.js.map