UNPKG

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