UNPKG

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