UNPKG

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