UNPKG

321 kBJavaScriptView Raw
1/**
2 * Swiper 7.3.2
3 * Most modern mobile touch slider and framework with hardware accelerated transitions
4 * https://swiperjs.com
5 *
6 * Copyright 2014-2021 Vladimir Kharlampidi
7 *
8 * Released under the MIT License
9 *
10 * Released on: December 13, 2021
11 */
12
13(function (global, factory) {
14 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
15 typeof define === 'function' && define.amd ? define(factory) :
16 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Swiper = factory());
17}(this, (function () { 'use strict';
18
19 /**
20 * SSR Window 4.0.2
21 * Better handling for window object in SSR environment
22 * https://github.com/nolimits4web/ssr-window
23 *
24 * Copyright 2021, Vladimir Kharlampidi
25 *
26 * Licensed under MIT
27 *
28 * Released on: December 13, 2021
29 */
30
31 /* eslint-disable no-param-reassign */
32 function isObject$1(obj) {
33 return obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object;
34 }
35
36 function extend$1(target = {}, src = {}) {
37 Object.keys(src).forEach(key => {
38 if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject$1(src[key]) && isObject$1(target[key]) && Object.keys(src[key]).length > 0) {
39 extend$1(target[key], src[key]);
40 }
41 });
42 }
43
44 const ssrDocument = {
45 body: {},
46
47 addEventListener() {},
48
49 removeEventListener() {},
50
51 activeElement: {
52 blur() {},
53
54 nodeName: ''
55 },
56
57 querySelector() {
58 return null;
59 },
60
61 querySelectorAll() {
62 return [];
63 },
64
65 getElementById() {
66 return null;
67 },
68
69 createEvent() {
70 return {
71 initEvent() {}
72
73 };
74 },
75
76 createElement() {
77 return {
78 children: [],
79 childNodes: [],
80 style: {},
81
82 setAttribute() {},
83
84 getElementsByTagName() {
85 return [];
86 }
87
88 };
89 },
90
91 createElementNS() {
92 return {};
93 },
94
95 importNode() {
96 return null;
97 },
98
99 location: {
100 hash: '',
101 host: '',
102 hostname: '',
103 href: '',
104 origin: '',
105 pathname: '',
106 protocol: '',
107 search: ''
108 }
109 };
110
111 function getDocument() {
112 const doc = typeof document !== 'undefined' ? document : {};
113 extend$1(doc, ssrDocument);
114 return doc;
115 }
116
117 const ssrWindow = {
118 document: ssrDocument,
119 navigator: {
120 userAgent: ''
121 },
122 location: {
123 hash: '',
124 host: '',
125 hostname: '',
126 href: '',
127 origin: '',
128 pathname: '',
129 protocol: '',
130 search: ''
131 },
132 history: {
133 replaceState() {},
134
135 pushState() {},
136
137 go() {},
138
139 back() {}
140
141 },
142 CustomEvent: function CustomEvent() {
143 return this;
144 },
145
146 addEventListener() {},
147
148 removeEventListener() {},
149
150 getComputedStyle() {
151 return {
152 getPropertyValue() {
153 return '';
154 }
155
156 };
157 },
158
159 Image() {},
160
161 Date() {},
162
163 screen: {},
164
165 setTimeout() {},
166
167 clearTimeout() {},
168
169 matchMedia() {
170 return {};
171 },
172
173 requestAnimationFrame(callback) {
174 if (typeof setTimeout === 'undefined') {
175 callback();
176 return null;
177 }
178
179 return setTimeout(callback, 0);
180 },
181
182 cancelAnimationFrame(id) {
183 if (typeof setTimeout === 'undefined') {
184 return;
185 }
186
187 clearTimeout(id);
188 }
189
190 };
191
192 function getWindow() {
193 const win = typeof window !== 'undefined' ? window : {};
194 extend$1(win, ssrWindow);
195 return win;
196 }
197
198 /**
199 * Dom7 4.0.2
200 * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API
201 * https://framework7.io/docs/dom7.html
202 *
203 * Copyright 2021, Vladimir Kharlampidi
204 *
205 * Licensed under MIT
206 *
207 * Released on: December 13, 2021
208 */
209 /* eslint-disable no-proto */
210
211 function makeReactive(obj) {
212 const proto = obj.__proto__;
213 Object.defineProperty(obj, '__proto__', {
214 get() {
215 return proto;
216 },
217
218 set(value) {
219 proto.__proto__ = value;
220 }
221
222 });
223 }
224
225 class Dom7 extends Array {
226 constructor(items) {
227 super(...(items || []));
228 makeReactive(this);
229 }
230
231 }
232
233 function arrayFlat(arr = []) {
234 const res = [];
235 arr.forEach(el => {
236 if (Array.isArray(el)) {
237 res.push(...arrayFlat(el));
238 } else {
239 res.push(el);
240 }
241 });
242 return res;
243 }
244
245 function arrayFilter(arr, callback) {
246 return Array.prototype.filter.call(arr, callback);
247 }
248
249 function arrayUnique(arr) {
250 const uniqueArray = [];
251
252 for (let i = 0; i < arr.length; i += 1) {
253 if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]);
254 }
255
256 return uniqueArray;
257 }
258
259
260 function qsa(selector, context) {
261 if (typeof selector !== 'string') {
262 return [selector];
263 }
264
265 const a = [];
266 const res = context.querySelectorAll(selector);
267
268 for (let i = 0; i < res.length; i += 1) {
269 a.push(res[i]);
270 }
271
272 return a;
273 }
274
275 function $(selector, context) {
276 const window = getWindow();
277 const document = getDocument();
278 let arr = [];
279
280 if (!context && selector instanceof Dom7) {
281 return selector;
282 }
283
284 if (!selector) {
285 return new Dom7(arr);
286 }
287
288 if (typeof selector === 'string') {
289 const html = selector.trim();
290
291 if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
292 let toCreate = 'div';
293 if (html.indexOf('<li') === 0) toCreate = 'ul';
294 if (html.indexOf('<tr') === 0) toCreate = 'tbody';
295 if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr';
296 if (html.indexOf('<tbody') === 0) toCreate = 'table';
297 if (html.indexOf('<option') === 0) toCreate = 'select';
298 const tempParent = document.createElement(toCreate);
299 tempParent.innerHTML = html;
300
301 for (let i = 0; i < tempParent.childNodes.length; i += 1) {
302 arr.push(tempParent.childNodes[i]);
303 }
304 } else {
305 arr = qsa(selector.trim(), context || document);
306 } // arr = qsa(selector, document);
307
308 } else if (selector.nodeType || selector === window || selector === document) {
309 arr.push(selector);
310 } else if (Array.isArray(selector)) {
311 if (selector instanceof Dom7) return selector;
312 arr = selector;
313 }
314
315 return new Dom7(arrayUnique(arr));
316 }
317
318 $.fn = Dom7.prototype; // eslint-disable-next-line
319
320 function addClass(...classes) {
321 const classNames = arrayFlat(classes.map(c => c.split(' ')));
322 this.forEach(el => {
323 el.classList.add(...classNames);
324 });
325 return this;
326 }
327
328 function removeClass(...classes) {
329 const classNames = arrayFlat(classes.map(c => c.split(' ')));
330 this.forEach(el => {
331 el.classList.remove(...classNames);
332 });
333 return this;
334 }
335
336 function toggleClass(...classes) {
337 const classNames = arrayFlat(classes.map(c => c.split(' ')));
338 this.forEach(el => {
339 classNames.forEach(className => {
340 el.classList.toggle(className);
341 });
342 });
343 }
344
345 function hasClass(...classes) {
346 const classNames = arrayFlat(classes.map(c => c.split(' ')));
347 return arrayFilter(this, el => {
348 return classNames.filter(className => el.classList.contains(className)).length > 0;
349 }).length > 0;
350 }
351
352 function attr(attrs, value) {
353 if (arguments.length === 1 && typeof attrs === 'string') {
354 // Get attr
355 if (this[0]) return this[0].getAttribute(attrs);
356 return undefined;
357 } // Set attrs
358
359
360 for (let i = 0; i < this.length; i += 1) {
361 if (arguments.length === 2) {
362 // String
363 this[i].setAttribute(attrs, value);
364 } else {
365 // Object
366 for (const attrName in attrs) {
367 this[i][attrName] = attrs[attrName];
368 this[i].setAttribute(attrName, attrs[attrName]);
369 }
370 }
371 }
372
373 return this;
374 }
375
376 function removeAttr(attr) {
377 for (let i = 0; i < this.length; i += 1) {
378 this[i].removeAttribute(attr);
379 }
380
381 return this;
382 }
383
384 function transform(transform) {
385 for (let i = 0; i < this.length; i += 1) {
386 this[i].style.transform = transform;
387 }
388
389 return this;
390 }
391
392 function transition$1(duration) {
393 for (let i = 0; i < this.length; i += 1) {
394 this[i].style.transitionDuration = typeof duration !== 'string' ? `${duration}ms` : duration;
395 }
396
397 return this;
398 }
399
400 function on(...args) {
401 let [eventType, targetSelector, listener, capture] = args;
402
403 if (typeof args[1] === 'function') {
404 [eventType, listener, capture] = args;
405 targetSelector = undefined;
406 }
407
408 if (!capture) capture = false;
409
410 function handleLiveEvent(e) {
411 const target = e.target;
412 if (!target) return;
413 const eventData = e.target.dom7EventData || [];
414
415 if (eventData.indexOf(e) < 0) {
416 eventData.unshift(e);
417 }
418
419 if ($(target).is(targetSelector)) listener.apply(target, eventData);else {
420 const parents = $(target).parents(); // eslint-disable-line
421
422 for (let k = 0; k < parents.length; k += 1) {
423 if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData);
424 }
425 }
426 }
427
428 function handleEvent(e) {
429 const eventData = e && e.target ? e.target.dom7EventData || [] : [];
430
431 if (eventData.indexOf(e) < 0) {
432 eventData.unshift(e);
433 }
434
435 listener.apply(this, eventData);
436 }
437
438 const events = eventType.split(' ');
439 let j;
440
441 for (let i = 0; i < this.length; i += 1) {
442 const el = this[i];
443
444 if (!targetSelector) {
445 for (j = 0; j < events.length; j += 1) {
446 const event = events[j];
447 if (!el.dom7Listeners) el.dom7Listeners = {};
448 if (!el.dom7Listeners[event]) el.dom7Listeners[event] = [];
449 el.dom7Listeners[event].push({
450 listener,
451 proxyListener: handleEvent
452 });
453 el.addEventListener(event, handleEvent, capture);
454 }
455 } else {
456 // Live events
457 for (j = 0; j < events.length; j += 1) {
458 const event = events[j];
459 if (!el.dom7LiveListeners) el.dom7LiveListeners = {};
460 if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = [];
461 el.dom7LiveListeners[event].push({
462 listener,
463 proxyListener: handleLiveEvent
464 });
465 el.addEventListener(event, handleLiveEvent, capture);
466 }
467 }
468 }
469
470 return this;
471 }
472
473 function off(...args) {
474 let [eventType, targetSelector, listener, capture] = args;
475
476 if (typeof args[1] === 'function') {
477 [eventType, listener, capture] = args;
478 targetSelector = undefined;
479 }
480
481 if (!capture) capture = false;
482 const events = eventType.split(' ');
483
484 for (let i = 0; i < events.length; i += 1) {
485 const event = events[i];
486
487 for (let j = 0; j < this.length; j += 1) {
488 const el = this[j];
489 let handlers;
490
491 if (!targetSelector && el.dom7Listeners) {
492 handlers = el.dom7Listeners[event];
493 } else if (targetSelector && el.dom7LiveListeners) {
494 handlers = el.dom7LiveListeners[event];
495 }
496
497 if (handlers && handlers.length) {
498 for (let k = handlers.length - 1; k >= 0; k -= 1) {
499 const handler = handlers[k];
500
501 if (listener && handler.listener === listener) {
502 el.removeEventListener(event, handler.proxyListener, capture);
503 handlers.splice(k, 1);
504 } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {
505 el.removeEventListener(event, handler.proxyListener, capture);
506 handlers.splice(k, 1);
507 } else if (!listener) {
508 el.removeEventListener(event, handler.proxyListener, capture);
509 handlers.splice(k, 1);
510 }
511 }
512 }
513 }
514 }
515
516 return this;
517 }
518
519 function trigger(...args) {
520 const window = getWindow();
521 const events = args[0].split(' ');
522 const eventData = args[1];
523
524 for (let i = 0; i < events.length; i += 1) {
525 const event = events[i];
526
527 for (let j = 0; j < this.length; j += 1) {
528 const el = this[j];
529
530 if (window.CustomEvent) {
531 const evt = new window.CustomEvent(event, {
532 detail: eventData,
533 bubbles: true,
534 cancelable: true
535 });
536 el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0);
537 el.dispatchEvent(evt);
538 el.dom7EventData = [];
539 delete el.dom7EventData;
540 }
541 }
542 }
543
544 return this;
545 }
546
547 function transitionEnd$1(callback) {
548 const dom = this;
549
550 function fireCallBack(e) {
551 if (e.target !== this) return;
552 callback.call(this, e);
553 dom.off('transitionend', fireCallBack);
554 }
555
556 if (callback) {
557 dom.on('transitionend', fireCallBack);
558 }
559
560 return this;
561 }
562
563 function outerWidth(includeMargins) {
564 if (this.length > 0) {
565 if (includeMargins) {
566 const styles = this.styles();
567 return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
568 }
569
570 return this[0].offsetWidth;
571 }
572
573 return null;
574 }
575
576 function outerHeight(includeMargins) {
577 if (this.length > 0) {
578 if (includeMargins) {
579 const styles = this.styles();
580 return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
581 }
582
583 return this[0].offsetHeight;
584 }
585
586 return null;
587 }
588
589 function offset() {
590 if (this.length > 0) {
591 const window = getWindow();
592 const document = getDocument();
593 const el = this[0];
594 const box = el.getBoundingClientRect();
595 const body = document.body;
596 const clientTop = el.clientTop || body.clientTop || 0;
597 const clientLeft = el.clientLeft || body.clientLeft || 0;
598 const scrollTop = el === window ? window.scrollY : el.scrollTop;
599 const scrollLeft = el === window ? window.scrollX : el.scrollLeft;
600 return {
601 top: box.top + scrollTop - clientTop,
602 left: box.left + scrollLeft - clientLeft
603 };
604 }
605
606 return null;
607 }
608
609 function styles() {
610 const window = getWindow();
611 if (this[0]) return window.getComputedStyle(this[0], null);
612 return {};
613 }
614
615 function css(props, value) {
616 const window = getWindow();
617 let i;
618
619 if (arguments.length === 1) {
620 if (typeof props === 'string') {
621 // .css('width')
622 if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);
623 } else {
624 // .css({ width: '100px' })
625 for (i = 0; i < this.length; i += 1) {
626 for (const prop in props) {
627 this[i].style[prop] = props[prop];
628 }
629 }
630
631 return this;
632 }
633 }
634
635 if (arguments.length === 2 && typeof props === 'string') {
636 // .css('width', '100px')
637 for (i = 0; i < this.length; i += 1) {
638 this[i].style[props] = value;
639 }
640
641 return this;
642 }
643
644 return this;
645 }
646
647 function each(callback) {
648 if (!callback) return this;
649 this.forEach((el, index) => {
650 callback.apply(el, [el, index]);
651 });
652 return this;
653 }
654
655 function filter(callback) {
656 const result = arrayFilter(this, callback);
657 return $(result);
658 }
659
660 function html(html) {
661 if (typeof html === 'undefined') {
662 return this[0] ? this[0].innerHTML : null;
663 }
664
665 for (let i = 0; i < this.length; i += 1) {
666 this[i].innerHTML = html;
667 }
668
669 return this;
670 }
671
672 function text(text) {
673 if (typeof text === 'undefined') {
674 return this[0] ? this[0].textContent.trim() : null;
675 }
676
677 for (let i = 0; i < this.length; i += 1) {
678 this[i].textContent = text;
679 }
680
681 return this;
682 }
683
684 function is(selector) {
685 const window = getWindow();
686 const document = getDocument();
687 const el = this[0];
688 let compareWith;
689 let i;
690 if (!el || typeof selector === 'undefined') return false;
691
692 if (typeof selector === 'string') {
693 if (el.matches) return el.matches(selector);
694 if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);
695 if (el.msMatchesSelector) return el.msMatchesSelector(selector);
696 compareWith = $(selector);
697
698 for (i = 0; i < compareWith.length; i += 1) {
699 if (compareWith[i] === el) return true;
700 }
701
702 return false;
703 }
704
705 if (selector === document) {
706 return el === document;
707 }
708
709 if (selector === window) {
710 return el === window;
711 }
712
713 if (selector.nodeType || selector instanceof Dom7) {
714 compareWith = selector.nodeType ? [selector] : selector;
715
716 for (i = 0; i < compareWith.length; i += 1) {
717 if (compareWith[i] === el) return true;
718 }
719
720 return false;
721 }
722
723 return false;
724 }
725
726 function index() {
727 let child = this[0];
728 let i;
729
730 if (child) {
731 i = 0; // eslint-disable-next-line
732
733 while ((child = child.previousSibling) !== null) {
734 if (child.nodeType === 1) i += 1;
735 }
736
737 return i;
738 }
739
740 return undefined;
741 }
742
743 function eq(index) {
744 if (typeof index === 'undefined') return this;
745 const length = this.length;
746
747 if (index > length - 1) {
748 return $([]);
749 }
750
751 if (index < 0) {
752 const returnIndex = length + index;
753 if (returnIndex < 0) return $([]);
754 return $([this[returnIndex]]);
755 }
756
757 return $([this[index]]);
758 }
759
760 function append(...els) {
761 let newChild;
762 const document = getDocument();
763
764 for (let k = 0; k < els.length; k += 1) {
765 newChild = els[k];
766
767 for (let i = 0; i < this.length; i += 1) {
768 if (typeof newChild === 'string') {
769 const tempDiv = document.createElement('div');
770 tempDiv.innerHTML = newChild;
771
772 while (tempDiv.firstChild) {
773 this[i].appendChild(tempDiv.firstChild);
774 }
775 } else if (newChild instanceof Dom7) {
776 for (let j = 0; j < newChild.length; j += 1) {
777 this[i].appendChild(newChild[j]);
778 }
779 } else {
780 this[i].appendChild(newChild);
781 }
782 }
783 }
784
785 return this;
786 }
787
788 function prepend(newChild) {
789 const document = getDocument();
790 let i;
791 let j;
792
793 for (i = 0; i < this.length; i += 1) {
794 if (typeof newChild === 'string') {
795 const tempDiv = document.createElement('div');
796 tempDiv.innerHTML = newChild;
797
798 for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {
799 this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
800 }
801 } else if (newChild instanceof Dom7) {
802 for (j = 0; j < newChild.length; j += 1) {
803 this[i].insertBefore(newChild[j], this[i].childNodes[0]);
804 }
805 } else {
806 this[i].insertBefore(newChild, this[i].childNodes[0]);
807 }
808 }
809
810 return this;
811 }
812
813 function next(selector) {
814 if (this.length > 0) {
815 if (selector) {
816 if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {
817 return $([this[0].nextElementSibling]);
818 }
819
820 return $([]);
821 }
822
823 if (this[0].nextElementSibling) return $([this[0].nextElementSibling]);
824 return $([]);
825 }
826
827 return $([]);
828 }
829
830 function nextAll(selector) {
831 const nextEls = [];
832 let el = this[0];
833 if (!el) return $([]);
834
835 while (el.nextElementSibling) {
836 const next = el.nextElementSibling; // eslint-disable-line
837
838 if (selector) {
839 if ($(next).is(selector)) nextEls.push(next);
840 } else nextEls.push(next);
841
842 el = next;
843 }
844
845 return $(nextEls);
846 }
847
848 function prev(selector) {
849 if (this.length > 0) {
850 const el = this[0];
851
852 if (selector) {
853 if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {
854 return $([el.previousElementSibling]);
855 }
856
857 return $([]);
858 }
859
860 if (el.previousElementSibling) return $([el.previousElementSibling]);
861 return $([]);
862 }
863
864 return $([]);
865 }
866
867 function prevAll(selector) {
868 const prevEls = [];
869 let el = this[0];
870 if (!el) return $([]);
871
872 while (el.previousElementSibling) {
873 const prev = el.previousElementSibling; // eslint-disable-line
874
875 if (selector) {
876 if ($(prev).is(selector)) prevEls.push(prev);
877 } else prevEls.push(prev);
878
879 el = prev;
880 }
881
882 return $(prevEls);
883 }
884
885 function parent(selector) {
886 const parents = []; // eslint-disable-line
887
888 for (let i = 0; i < this.length; i += 1) {
889 if (this[i].parentNode !== null) {
890 if (selector) {
891 if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);
892 } else {
893 parents.push(this[i].parentNode);
894 }
895 }
896 }
897
898 return $(parents);
899 }
900
901 function parents(selector) {
902 const parents = []; // eslint-disable-line
903
904 for (let i = 0; i < this.length; i += 1) {
905 let parent = this[i].parentNode; // eslint-disable-line
906
907 while (parent) {
908 if (selector) {
909 if ($(parent).is(selector)) parents.push(parent);
910 } else {
911 parents.push(parent);
912 }
913
914 parent = parent.parentNode;
915 }
916 }
917
918 return $(parents);
919 }
920
921 function closest(selector) {
922 let closest = this; // eslint-disable-line
923
924 if (typeof selector === 'undefined') {
925 return $([]);
926 }
927
928 if (!closest.is(selector)) {
929 closest = closest.parents(selector).eq(0);
930 }
931
932 return closest;
933 }
934
935 function find(selector) {
936 const foundElements = [];
937
938 for (let i = 0; i < this.length; i += 1) {
939 const found = this[i].querySelectorAll(selector);
940
941 for (let j = 0; j < found.length; j += 1) {
942 foundElements.push(found[j]);
943 }
944 }
945
946 return $(foundElements);
947 }
948
949 function children(selector) {
950 const children = []; // eslint-disable-line
951
952 for (let i = 0; i < this.length; i += 1) {
953 const childNodes = this[i].children;
954
955 for (let j = 0; j < childNodes.length; j += 1) {
956 if (!selector || $(childNodes[j]).is(selector)) {
957 children.push(childNodes[j]);
958 }
959 }
960 }
961
962 return $(children);
963 }
964
965 function remove() {
966 for (let i = 0; i < this.length; i += 1) {
967 if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);
968 }
969
970 return this;
971 }
972
973 const Methods = {
974 addClass,
975 removeClass,
976 hasClass,
977 toggleClass,
978 attr,
979 removeAttr,
980 transform,
981 transition: transition$1,
982 on,
983 off,
984 trigger,
985 transitionEnd: transitionEnd$1,
986 outerWidth,
987 outerHeight,
988 styles,
989 offset,
990 css,
991 each,
992 html,
993 text,
994 is,
995 index,
996 eq,
997 append,
998 prepend,
999 next,
1000 nextAll,
1001 prev,
1002 prevAll,
1003 parent,
1004 parents,
1005 closest,
1006 find,
1007 children,
1008 filter,
1009 remove
1010 };
1011 Object.keys(Methods).forEach(methodName => {
1012 Object.defineProperty($.fn, methodName, {
1013 value: Methods[methodName],
1014 writable: true
1015 });
1016 });
1017
1018 function deleteProps(obj) {
1019 const object = obj;
1020 Object.keys(object).forEach(key => {
1021 try {
1022 object[key] = null;
1023 } catch (e) {// no getter for object
1024 }
1025
1026 try {
1027 delete object[key];
1028 } catch (e) {// something got wrong
1029 }
1030 });
1031 }
1032
1033 function nextTick(callback, delay = 0) {
1034 return setTimeout(callback, delay);
1035 }
1036
1037 function now() {
1038 return Date.now();
1039 }
1040
1041 function getComputedStyle$1(el) {
1042 const window = getWindow();
1043 let style;
1044
1045 if (window.getComputedStyle) {
1046 style = window.getComputedStyle(el, null);
1047 }
1048
1049 if (!style && el.currentStyle) {
1050 style = el.currentStyle;
1051 }
1052
1053 if (!style) {
1054 style = el.style;
1055 }
1056
1057 return style;
1058 }
1059
1060 function getTranslate(el, axis = 'x') {
1061 const window = getWindow();
1062 let matrix;
1063 let curTransform;
1064 let transformMatrix;
1065 const curStyle = getComputedStyle$1(el);
1066
1067 if (window.WebKitCSSMatrix) {
1068 curTransform = curStyle.transform || curStyle.webkitTransform;
1069
1070 if (curTransform.split(',').length > 6) {
1071 curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');
1072 } // Some old versions of Webkit choke when 'none' is passed; pass
1073 // empty string instead in this case
1074
1075
1076 transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
1077 } else {
1078 transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
1079 matrix = transformMatrix.toString().split(',');
1080 }
1081
1082 if (axis === 'x') {
1083 // Latest Chrome and webkits Fix
1084 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41; // Crazy IE10 Matrix
1085 else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); // Normal Browsers
1086 else curTransform = parseFloat(matrix[4]);
1087 }
1088
1089 if (axis === 'y') {
1090 // Latest Chrome and webkits Fix
1091 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42; // Crazy IE10 Matrix
1092 else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); // Normal Browsers
1093 else curTransform = parseFloat(matrix[5]);
1094 }
1095
1096 return curTransform || 0;
1097 }
1098
1099 function isObject(o) {
1100 return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';
1101 }
1102
1103 function isNode(node) {
1104 // eslint-disable-next-line
1105 if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {
1106 return node instanceof HTMLElement;
1107 }
1108
1109 return node && (node.nodeType === 1 || node.nodeType === 11);
1110 }
1111
1112 function extend(...args) {
1113 const to = Object(args[0]);
1114 const noExtend = ['__proto__', 'constructor', 'prototype'];
1115
1116 for (let i = 1; i < args.length; i += 1) {
1117 const nextSource = args[i];
1118
1119 if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {
1120 const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);
1121
1122 for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
1123 const nextKey = keysArray[nextIndex];
1124 const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
1125
1126 if (desc !== undefined && desc.enumerable) {
1127 if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
1128 if (nextSource[nextKey].__swiper__) {
1129 to[nextKey] = nextSource[nextKey];
1130 } else {
1131 extend(to[nextKey], nextSource[nextKey]);
1132 }
1133 } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
1134 to[nextKey] = {};
1135
1136 if (nextSource[nextKey].__swiper__) {
1137 to[nextKey] = nextSource[nextKey];
1138 } else {
1139 extend(to[nextKey], nextSource[nextKey]);
1140 }
1141 } else {
1142 to[nextKey] = nextSource[nextKey];
1143 }
1144 }
1145 }
1146 }
1147 }
1148
1149 return to;
1150 }
1151
1152 function setCSSProperty(el, varName, varValue) {
1153 el.style.setProperty(varName, varValue);
1154 }
1155
1156 function animateCSSModeScroll({
1157 swiper,
1158 targetPosition,
1159 side
1160 }) {
1161 const window = getWindow();
1162 const startPosition = -swiper.translate;
1163 let startTime = null;
1164 let time;
1165 const duration = swiper.params.speed;
1166 swiper.wrapperEl.style.scrollSnapType = 'none';
1167 window.cancelAnimationFrame(swiper.cssModeFrameID);
1168 const dir = targetPosition > startPosition ? 'next' : 'prev';
1169
1170 const isOutOfBound = (current, target) => {
1171 return dir === 'next' && current >= target || dir === 'prev' && current <= target;
1172 };
1173
1174 const animate = () => {
1175 time = new Date().getTime();
1176
1177 if (startTime === null) {
1178 startTime = time;
1179 }
1180
1181 const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
1182 const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;
1183 let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);
1184
1185 if (isOutOfBound(currentPosition, targetPosition)) {
1186 currentPosition = targetPosition;
1187 }
1188
1189 swiper.wrapperEl.scrollTo({
1190 [side]: currentPosition
1191 });
1192
1193 if (isOutOfBound(currentPosition, targetPosition)) {
1194 swiper.wrapperEl.style.overflow = 'hidden';
1195 swiper.wrapperEl.style.scrollSnapType = '';
1196 setTimeout(() => {
1197 swiper.wrapperEl.style.overflow = '';
1198 swiper.wrapperEl.scrollTo({
1199 [side]: currentPosition
1200 });
1201 });
1202 window.cancelAnimationFrame(swiper.cssModeFrameID);
1203 return;
1204 }
1205
1206 swiper.cssModeFrameID = window.requestAnimationFrame(animate);
1207 };
1208
1209 animate();
1210 }
1211
1212 let support;
1213
1214 function calcSupport() {
1215 const window = getWindow();
1216 const document = getDocument();
1217 return {
1218 smoothScroll: document.documentElement && 'scrollBehavior' in document.documentElement.style,
1219 touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch),
1220 passiveListener: function checkPassiveListener() {
1221 let supportsPassive = false;
1222
1223 try {
1224 const opts = Object.defineProperty({}, 'passive', {
1225 // eslint-disable-next-line
1226 get() {
1227 supportsPassive = true;
1228 }
1229
1230 });
1231 window.addEventListener('testPassiveListener', null, opts);
1232 } catch (e) {// No support
1233 }
1234
1235 return supportsPassive;
1236 }(),
1237 gestures: function checkGestures() {
1238 return 'ongesturestart' in window;
1239 }()
1240 };
1241 }
1242
1243 function getSupport() {
1244 if (!support) {
1245 support = calcSupport();
1246 }
1247
1248 return support;
1249 }
1250
1251 let deviceCached;
1252
1253 function calcDevice({
1254 userAgent
1255 } = {}) {
1256 const support = getSupport();
1257 const window = getWindow();
1258 const platform = window.navigator.platform;
1259 const ua = userAgent || window.navigator.userAgent;
1260 const device = {
1261 ios: false,
1262 android: false
1263 };
1264 const screenWidth = window.screen.width;
1265 const screenHeight = window.screen.height;
1266 const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
1267
1268 let ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
1269 const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
1270 const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
1271 const windows = platform === 'Win32';
1272 let macos = platform === 'MacIntel'; // iPadOs 13 fix
1273
1274 const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810'];
1275
1276 if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) {
1277 ipad = ua.match(/(Version)\/([\d.]+)/);
1278 if (!ipad) ipad = [0, 1, '13_0_0'];
1279 macos = false;
1280 } // Android
1281
1282
1283 if (android && !windows) {
1284 device.os = 'android';
1285 device.android = true;
1286 }
1287
1288 if (ipad || iphone || ipod) {
1289 device.os = 'ios';
1290 device.ios = true;
1291 } // Export object
1292
1293
1294 return device;
1295 }
1296
1297 function getDevice(overrides = {}) {
1298 if (!deviceCached) {
1299 deviceCached = calcDevice(overrides);
1300 }
1301
1302 return deviceCached;
1303 }
1304
1305 let browser;
1306
1307 function calcBrowser() {
1308 const window = getWindow();
1309
1310 function isSafari() {
1311 const ua = window.navigator.userAgent.toLowerCase();
1312 return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0;
1313 }
1314
1315 return {
1316 isSafari: isSafari(),
1317 isWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent)
1318 };
1319 }
1320
1321 function getBrowser() {
1322 if (!browser) {
1323 browser = calcBrowser();
1324 }
1325
1326 return browser;
1327 }
1328
1329 function Resize({
1330 swiper,
1331 on,
1332 emit
1333 }) {
1334 const window = getWindow();
1335 let observer = null;
1336
1337 const resizeHandler = () => {
1338 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1339 emit('beforeResize');
1340 emit('resize');
1341 };
1342
1343 const createObserver = () => {
1344 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1345 observer = new ResizeObserver(entries => {
1346 const {
1347 width,
1348 height
1349 } = swiper;
1350 let newWidth = width;
1351 let newHeight = height;
1352 entries.forEach(({
1353 contentBoxSize,
1354 contentRect,
1355 target
1356 }) => {
1357 if (target && target !== swiper.el) return;
1358 newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize;
1359 newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize;
1360 });
1361
1362 if (newWidth !== width || newHeight !== height) {
1363 resizeHandler();
1364 }
1365 });
1366 observer.observe(swiper.el);
1367 };
1368
1369 const removeObserver = () => {
1370 if (observer && observer.unobserve && swiper.el) {
1371 observer.unobserve(swiper.el);
1372 observer = null;
1373 }
1374 };
1375
1376 const orientationChangeHandler = () => {
1377 if (!swiper || swiper.destroyed || !swiper.initialized) return;
1378 emit('orientationchange');
1379 };
1380
1381 on('init', () => {
1382 if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') {
1383 createObserver();
1384 return;
1385 }
1386
1387 window.addEventListener('resize', resizeHandler);
1388 window.addEventListener('orientationchange', orientationChangeHandler);
1389 });
1390 on('destroy', () => {
1391 removeObserver();
1392 window.removeEventListener('resize', resizeHandler);
1393 window.removeEventListener('orientationchange', orientationChangeHandler);
1394 });
1395 }
1396
1397 function Observer({
1398 swiper,
1399 extendParams,
1400 on,
1401 emit
1402 }) {
1403 const observers = [];
1404 const window = getWindow();
1405
1406 const attach = (target, options = {}) => {
1407 const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
1408 const observer = new ObserverFunc(mutations => {
1409 // The observerUpdate event should only be triggered
1410 // once despite the number of mutations. Additional
1411 // triggers are redundant and are very costly
1412 if (mutations.length === 1) {
1413 emit('observerUpdate', mutations[0]);
1414 return;
1415 }
1416
1417 const observerUpdate = function observerUpdate() {
1418 emit('observerUpdate', mutations[0]);
1419 };
1420
1421 if (window.requestAnimationFrame) {
1422 window.requestAnimationFrame(observerUpdate);
1423 } else {
1424 window.setTimeout(observerUpdate, 0);
1425 }
1426 });
1427 observer.observe(target, {
1428 attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
1429 childList: typeof options.childList === 'undefined' ? true : options.childList,
1430 characterData: typeof options.characterData === 'undefined' ? true : options.characterData
1431 });
1432 observers.push(observer);
1433 };
1434
1435 const init = () => {
1436 if (!swiper.params.observer) return;
1437
1438 if (swiper.params.observeParents) {
1439 const containerParents = swiper.$el.parents();
1440
1441 for (let i = 0; i < containerParents.length; i += 1) {
1442 attach(containerParents[i]);
1443 }
1444 } // Observe container
1445
1446
1447 attach(swiper.$el[0], {
1448 childList: swiper.params.observeSlideChildren
1449 }); // Observe wrapper
1450
1451 attach(swiper.$wrapperEl[0], {
1452 attributes: false
1453 });
1454 };
1455
1456 const destroy = () => {
1457 observers.forEach(observer => {
1458 observer.disconnect();
1459 });
1460 observers.splice(0, observers.length);
1461 };
1462
1463 extendParams({
1464 observer: false,
1465 observeParents: false,
1466 observeSlideChildren: false
1467 });
1468 on('init', init);
1469 on('destroy', destroy);
1470 }
1471
1472 /* eslint-disable no-underscore-dangle */
1473 var eventsEmitter = {
1474 on(events, handler, priority) {
1475 const self = this;
1476 if (typeof handler !== 'function') return self;
1477 const method = priority ? 'unshift' : 'push';
1478 events.split(' ').forEach(event => {
1479 if (!self.eventsListeners[event]) self.eventsListeners[event] = [];
1480 self.eventsListeners[event][method](handler);
1481 });
1482 return self;
1483 },
1484
1485 once(events, handler, priority) {
1486 const self = this;
1487 if (typeof handler !== 'function') return self;
1488
1489 function onceHandler(...args) {
1490 self.off(events, onceHandler);
1491
1492 if (onceHandler.__emitterProxy) {
1493 delete onceHandler.__emitterProxy;
1494 }
1495
1496 handler.apply(self, args);
1497 }
1498
1499 onceHandler.__emitterProxy = handler;
1500 return self.on(events, onceHandler, priority);
1501 },
1502
1503 onAny(handler, priority) {
1504 const self = this;
1505 if (typeof handler !== 'function') return self;
1506 const method = priority ? 'unshift' : 'push';
1507
1508 if (self.eventsAnyListeners.indexOf(handler) < 0) {
1509 self.eventsAnyListeners[method](handler);
1510 }
1511
1512 return self;
1513 },
1514
1515 offAny(handler) {
1516 const self = this;
1517 if (!self.eventsAnyListeners) return self;
1518 const index = self.eventsAnyListeners.indexOf(handler);
1519
1520 if (index >= 0) {
1521 self.eventsAnyListeners.splice(index, 1);
1522 }
1523
1524 return self;
1525 },
1526
1527 off(events, handler) {
1528 const self = this;
1529 if (!self.eventsListeners) return self;
1530 events.split(' ').forEach(event => {
1531 if (typeof handler === 'undefined') {
1532 self.eventsListeners[event] = [];
1533 } else if (self.eventsListeners[event]) {
1534 self.eventsListeners[event].forEach((eventHandler, index) => {
1535 if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) {
1536 self.eventsListeners[event].splice(index, 1);
1537 }
1538 });
1539 }
1540 });
1541 return self;
1542 },
1543
1544 emit(...args) {
1545 const self = this;
1546 if (!self.eventsListeners) return self;
1547 let events;
1548 let data;
1549 let context;
1550
1551 if (typeof args[0] === 'string' || Array.isArray(args[0])) {
1552 events = args[0];
1553 data = args.slice(1, args.length);
1554 context = self;
1555 } else {
1556 events = args[0].events;
1557 data = args[0].data;
1558 context = args[0].context || self;
1559 }
1560
1561 data.unshift(context);
1562 const eventsArray = Array.isArray(events) ? events : events.split(' ');
1563 eventsArray.forEach(event => {
1564 if (self.eventsAnyListeners && self.eventsAnyListeners.length) {
1565 self.eventsAnyListeners.forEach(eventHandler => {
1566 eventHandler.apply(context, [event, ...data]);
1567 });
1568 }
1569
1570 if (self.eventsListeners && self.eventsListeners[event]) {
1571 self.eventsListeners[event].forEach(eventHandler => {
1572 eventHandler.apply(context, data);
1573 });
1574 }
1575 });
1576 return self;
1577 }
1578
1579 };
1580
1581 function updateSize() {
1582 const swiper = this;
1583 let width;
1584 let height;
1585 const $el = swiper.$el;
1586
1587 if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) {
1588 width = swiper.params.width;
1589 } else {
1590 width = $el[0].clientWidth;
1591 }
1592
1593 if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) {
1594 height = swiper.params.height;
1595 } else {
1596 height = $el[0].clientHeight;
1597 }
1598
1599 if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) {
1600 return;
1601 } // Subtract paddings
1602
1603
1604 width = width - parseInt($el.css('padding-left') || 0, 10) - parseInt($el.css('padding-right') || 0, 10);
1605 height = height - parseInt($el.css('padding-top') || 0, 10) - parseInt($el.css('padding-bottom') || 0, 10);
1606 if (Number.isNaN(width)) width = 0;
1607 if (Number.isNaN(height)) height = 0;
1608 Object.assign(swiper, {
1609 width,
1610 height,
1611 size: swiper.isHorizontal() ? width : height
1612 });
1613 }
1614
1615 function updateSlides() {
1616 const swiper = this;
1617
1618 function getDirectionLabel(property) {
1619 if (swiper.isHorizontal()) {
1620 return property;
1621 } // prettier-ignore
1622
1623
1624 return {
1625 'width': 'height',
1626 'margin-top': 'margin-left',
1627 'margin-bottom ': 'margin-right',
1628 'margin-left': 'margin-top',
1629 'margin-right': 'margin-bottom',
1630 'padding-left': 'padding-top',
1631 'padding-right': 'padding-bottom',
1632 'marginRight': 'marginBottom'
1633 }[property];
1634 }
1635
1636 function getDirectionPropertyValue(node, label) {
1637 return parseFloat(node.getPropertyValue(getDirectionLabel(label)) || 0);
1638 }
1639
1640 const params = swiper.params;
1641 const {
1642 $wrapperEl,
1643 size: swiperSize,
1644 rtlTranslate: rtl,
1645 wrongRTL
1646 } = swiper;
1647 const isVirtual = swiper.virtual && params.virtual.enabled;
1648 const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
1649 const slides = $wrapperEl.children(`.${swiper.params.slideClass}`);
1650 const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
1651 let snapGrid = [];
1652 const slidesGrid = [];
1653 const slidesSizesGrid = [];
1654 let offsetBefore = params.slidesOffsetBefore;
1655
1656 if (typeof offsetBefore === 'function') {
1657 offsetBefore = params.slidesOffsetBefore.call(swiper);
1658 }
1659
1660 let offsetAfter = params.slidesOffsetAfter;
1661
1662 if (typeof offsetAfter === 'function') {
1663 offsetAfter = params.slidesOffsetAfter.call(swiper);
1664 }
1665
1666 const previousSnapGridLength = swiper.snapGrid.length;
1667 const previousSlidesGridLength = swiper.slidesGrid.length;
1668 let spaceBetween = params.spaceBetween;
1669 let slidePosition = -offsetBefore;
1670 let prevSlideSize = 0;
1671 let index = 0;
1672
1673 if (typeof swiperSize === 'undefined') {
1674 return;
1675 }
1676
1677 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
1678 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;
1679 }
1680
1681 swiper.virtualSize = -spaceBetween; // reset margins
1682
1683 if (rtl) slides.css({
1684 marginLeft: '',
1685 marginBottom: '',
1686 marginTop: ''
1687 });else slides.css({
1688 marginRight: '',
1689 marginBottom: '',
1690 marginTop: ''
1691 }); // reset cssMode offsets
1692
1693 if (params.centeredSlides && params.cssMode) {
1694 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', '');
1695 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', '');
1696 }
1697
1698 const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;
1699
1700 if (gridEnabled) {
1701 swiper.grid.initSlides(slidesLength);
1702 } // Calc slides
1703
1704
1705 let slideSize;
1706 const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {
1707 return typeof params.breakpoints[key].slidesPerView !== 'undefined';
1708 }).length > 0;
1709
1710 for (let i = 0; i < slidesLength; i += 1) {
1711 slideSize = 0;
1712 const slide = slides.eq(i);
1713
1714 if (gridEnabled) {
1715 swiper.grid.updateSlide(i, slide, slidesLength, getDirectionLabel);
1716 }
1717
1718 if (slide.css('display') === 'none') continue; // eslint-disable-line
1719
1720 if (params.slidesPerView === 'auto') {
1721 if (shouldResetSlideSize) {
1722 slides[i].style[getDirectionLabel('width')] = ``;
1723 }
1724
1725 const slideStyles = getComputedStyle(slide[0]);
1726 const currentTransform = slide[0].style.transform;
1727 const currentWebKitTransform = slide[0].style.webkitTransform;
1728
1729 if (currentTransform) {
1730 slide[0].style.transform = 'none';
1731 }
1732
1733 if (currentWebKitTransform) {
1734 slide[0].style.webkitTransform = 'none';
1735 }
1736
1737 if (params.roundLengths) {
1738 slideSize = swiper.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);
1739 } else {
1740 // eslint-disable-next-line
1741 const width = getDirectionPropertyValue(slideStyles, 'width');
1742 const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');
1743 const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
1744 const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
1745 const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
1746 const boxSizing = slideStyles.getPropertyValue('box-sizing');
1747
1748 if (boxSizing && boxSizing === 'border-box') {
1749 slideSize = width + marginLeft + marginRight;
1750 } else {
1751 const {
1752 clientWidth,
1753 offsetWidth
1754 } = slide[0];
1755 slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
1756 }
1757 }
1758
1759 if (currentTransform) {
1760 slide[0].style.transform = currentTransform;
1761 }
1762
1763 if (currentWebKitTransform) {
1764 slide[0].style.webkitTransform = currentWebKitTransform;
1765 }
1766
1767 if (params.roundLengths) slideSize = Math.floor(slideSize);
1768 } else {
1769 slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;
1770 if (params.roundLengths) slideSize = Math.floor(slideSize);
1771
1772 if (slides[i]) {
1773 slides[i].style[getDirectionLabel('width')] = `${slideSize}px`;
1774 }
1775 }
1776
1777 if (slides[i]) {
1778 slides[i].swiperSlideSize = slideSize;
1779 }
1780
1781 slidesSizesGrid.push(slideSize);
1782
1783 if (params.centeredSlides) {
1784 slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
1785 if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1786 if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1787 if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
1788 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1789 if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1790 slidesGrid.push(slidePosition);
1791 } else {
1792 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1793 if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1794 slidesGrid.push(slidePosition);
1795 slidePosition = slidePosition + slideSize + spaceBetween;
1796 }
1797
1798 swiper.virtualSize += slideSize + spaceBetween;
1799 prevSlideSize = slideSize;
1800 index += 1;
1801 }
1802
1803 swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
1804
1805 if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
1806 $wrapperEl.css({
1807 width: `${swiper.virtualSize + params.spaceBetween}px`
1808 });
1809 }
1810
1811 if (params.setWrapperSize) {
1812 $wrapperEl.css({
1813 [getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`
1814 });
1815 }
1816
1817 if (gridEnabled) {
1818 swiper.grid.updateWrapperSize(slideSize, snapGrid, getDirectionLabel);
1819 } // Remove last grid elements depending on width
1820
1821
1822 if (!params.centeredSlides) {
1823 const newSlidesGrid = [];
1824
1825 for (let i = 0; i < snapGrid.length; i += 1) {
1826 let slidesGridItem = snapGrid[i];
1827 if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
1828
1829 if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
1830 newSlidesGrid.push(slidesGridItem);
1831 }
1832 }
1833
1834 snapGrid = newSlidesGrid;
1835
1836 if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
1837 snapGrid.push(swiper.virtualSize - swiperSize);
1838 }
1839 }
1840
1841 if (snapGrid.length === 0) snapGrid = [0];
1842
1843 if (params.spaceBetween !== 0) {
1844 const key = swiper.isHorizontal() && rtl ? 'marginLeft' : getDirectionLabel('marginRight');
1845 slides.filter((_, slideIndex) => {
1846 if (!params.cssMode) return true;
1847
1848 if (slideIndex === slides.length - 1) {
1849 return false;
1850 }
1851
1852 return true;
1853 }).css({
1854 [key]: `${spaceBetween}px`
1855 });
1856 }
1857
1858 if (params.centeredSlides && params.centeredSlidesBounds) {
1859 let allSlidesSize = 0;
1860 slidesSizesGrid.forEach(slideSizeValue => {
1861 allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
1862 });
1863 allSlidesSize -= params.spaceBetween;
1864 const maxSnap = allSlidesSize - swiperSize;
1865 snapGrid = snapGrid.map(snap => {
1866 if (snap < 0) return -offsetBefore;
1867 if (snap > maxSnap) return maxSnap + offsetAfter;
1868 return snap;
1869 });
1870 }
1871
1872 if (params.centerInsufficientSlides) {
1873 let allSlidesSize = 0;
1874 slidesSizesGrid.forEach(slideSizeValue => {
1875 allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
1876 });
1877 allSlidesSize -= params.spaceBetween;
1878
1879 if (allSlidesSize < swiperSize) {
1880 const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
1881 snapGrid.forEach((snap, snapIndex) => {
1882 snapGrid[snapIndex] = snap - allSlidesOffset;
1883 });
1884 slidesGrid.forEach((snap, snapIndex) => {
1885 slidesGrid[snapIndex] = snap + allSlidesOffset;
1886 });
1887 }
1888 }
1889
1890 Object.assign(swiper, {
1891 slides,
1892 snapGrid,
1893 slidesGrid,
1894 slidesSizesGrid
1895 });
1896
1897 if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) {
1898 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`);
1899 setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`);
1900 const addToSnapGrid = -swiper.snapGrid[0];
1901 const addToSlidesGrid = -swiper.slidesGrid[0];
1902 swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);
1903 swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);
1904 }
1905
1906 if (slidesLength !== previousSlidesLength) {
1907 swiper.emit('slidesLengthChange');
1908 }
1909
1910 if (snapGrid.length !== previousSnapGridLength) {
1911 if (swiper.params.watchOverflow) swiper.checkOverflow();
1912 swiper.emit('snapGridLengthChange');
1913 }
1914
1915 if (slidesGrid.length !== previousSlidesGridLength) {
1916 swiper.emit('slidesGridLengthChange');
1917 }
1918
1919 if (params.watchSlidesProgress) {
1920 swiper.updateSlidesOffset();
1921 }
1922 }
1923
1924 function updateAutoHeight(speed) {
1925 const swiper = this;
1926 const activeSlides = [];
1927 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
1928 let newHeight = 0;
1929 let i;
1930
1931 if (typeof speed === 'number') {
1932 swiper.setTransition(speed);
1933 } else if (speed === true) {
1934 swiper.setTransition(swiper.params.speed);
1935 }
1936
1937 const getSlideByIndex = index => {
1938 if (isVirtual) {
1939 return swiper.slides.filter(el => parseInt(el.getAttribute('data-swiper-slide-index'), 10) === index)[0];
1940 }
1941
1942 return swiper.slides.eq(index)[0];
1943 }; // Find slides currently in view
1944
1945
1946 if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
1947 if (swiper.params.centeredSlides) {
1948 swiper.visibleSlides.each(slide => {
1949 activeSlides.push(slide);
1950 });
1951 } else {
1952 for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
1953 const index = swiper.activeIndex + i;
1954 if (index > swiper.slides.length && !isVirtual) break;
1955 activeSlides.push(getSlideByIndex(index));
1956 }
1957 }
1958 } else {
1959 activeSlides.push(getSlideByIndex(swiper.activeIndex));
1960 } // Find new height from highest slide in view
1961
1962
1963 for (i = 0; i < activeSlides.length; i += 1) {
1964 if (typeof activeSlides[i] !== 'undefined') {
1965 const height = activeSlides[i].offsetHeight;
1966 newHeight = height > newHeight ? height : newHeight;
1967 }
1968 } // Update Height
1969
1970
1971 if (newHeight) 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.pagination.bullets && swiper.pagination.bullets.length;
7881 }
7882
7883 function hasClickablePagination() {
7884 return hasPagination() && swiper.params.pagination.clickable;
7885 }
7886
7887 function updatePagination() {
7888 const params = swiper.params.a11y;
7889 if (!hasPagination()) return;
7890 swiper.pagination.bullets.each(bulletEl => {
7891 const $bulletEl = $(bulletEl);
7892
7893 if (swiper.params.pagination.clickable) {
7894 makeElFocusable($bulletEl);
7895
7896 if (!swiper.params.pagination.renderBullet) {
7897 addElRole($bulletEl, 'button');
7898 addElLabel($bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, $bulletEl.index() + 1));
7899 }
7900 }
7901
7902 if ($bulletEl.is(`.${swiper.params.pagination.bulletActiveClass}`)) {
7903 $bulletEl.attr('aria-current', 'true');
7904 } else {
7905 $bulletEl.removeAttr('aria-current');
7906 }
7907 });
7908 }
7909
7910 const initNavEl = ($el, wrapperId, message) => {
7911 makeElFocusable($el);
7912
7913 if ($el[0].tagName !== 'BUTTON') {
7914 addElRole($el, 'button');
7915 $el.on('keydown', onEnterOrSpaceKey);
7916 }
7917
7918 addElLabel($el, message);
7919 addElControls($el, wrapperId);
7920 };
7921
7922 function init() {
7923 const params = swiper.params.a11y;
7924 swiper.$el.append(liveRegion); // Container
7925
7926 const $containerEl = swiper.$el;
7927
7928 if (params.containerRoleDescriptionMessage) {
7929 addElRoleDescription($containerEl, params.containerRoleDescriptionMessage);
7930 }
7931
7932 if (params.containerMessage) {
7933 addElLabel($containerEl, params.containerMessage);
7934 } // Wrapper
7935
7936
7937 const $wrapperEl = swiper.$wrapperEl;
7938 const wrapperId = $wrapperEl.attr('id') || `swiper-wrapper-${getRandomNumber(16)}`;
7939 const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';
7940 addElId($wrapperEl, wrapperId);
7941 addElLive($wrapperEl, live); // Slide
7942
7943 if (params.itemRoleDescriptionMessage) {
7944 addElRoleDescription($(swiper.slides), params.itemRoleDescriptionMessage);
7945 }
7946
7947 addElRole($(swiper.slides), params.slideRole);
7948 const slidesLength = swiper.params.loop ? swiper.slides.filter(el => !el.classList.contains(swiper.params.slideDuplicateClass)).length : swiper.slides.length;
7949 swiper.slides.each((slideEl, index) => {
7950 const $slideEl = $(slideEl);
7951 const slideIndex = swiper.params.loop ? parseInt($slideEl.attr('data-swiper-slide-index'), 10) : index;
7952 const ariaLabelMessage = params.slideLabelMessage.replace(/\{\{index\}\}/, slideIndex + 1).replace(/\{\{slidesLength\}\}/, slidesLength);
7953 addElLabel($slideEl, ariaLabelMessage);
7954 }); // Navigation
7955
7956 let $nextEl;
7957 let $prevEl;
7958
7959 if (swiper.navigation && swiper.navigation.$nextEl) {
7960 $nextEl = swiper.navigation.$nextEl;
7961 }
7962
7963 if (swiper.navigation && swiper.navigation.$prevEl) {
7964 $prevEl = swiper.navigation.$prevEl;
7965 }
7966
7967 if ($nextEl && $nextEl.length) {
7968 initNavEl($nextEl, wrapperId, params.nextSlideMessage);
7969 }
7970
7971 if ($prevEl && $prevEl.length) {
7972 initNavEl($prevEl, wrapperId, params.prevSlideMessage);
7973 } // Pagination
7974
7975
7976 if (hasClickablePagination()) {
7977 swiper.pagination.$el.on('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);
7978 }
7979 }
7980
7981 function destroy() {
7982 if (liveRegion && liveRegion.length > 0) liveRegion.remove();
7983 let $nextEl;
7984 let $prevEl;
7985
7986 if (swiper.navigation && swiper.navigation.$nextEl) {
7987 $nextEl = swiper.navigation.$nextEl;
7988 }
7989
7990 if (swiper.navigation && swiper.navigation.$prevEl) {
7991 $prevEl = swiper.navigation.$prevEl;
7992 }
7993
7994 if ($nextEl) {
7995 $nextEl.off('keydown', onEnterOrSpaceKey);
7996 }
7997
7998 if ($prevEl) {
7999 $prevEl.off('keydown', onEnterOrSpaceKey);
8000 } // Pagination
8001
8002
8003 if (hasClickablePagination()) {
8004 swiper.pagination.$el.off('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);
8005 }
8006 }
8007
8008 on('beforeInit', () => {
8009 liveRegion = $(`<span class="${swiper.params.a11y.notificationClass}" aria-live="assertive" aria-atomic="true"></span>`);
8010 });
8011 on('afterInit', () => {
8012 if (!swiper.params.a11y.enabled) return;
8013 init();
8014 updateNavigation();
8015 });
8016 on('toEdge', () => {
8017 if (!swiper.params.a11y.enabled) return;
8018 updateNavigation();
8019 });
8020 on('fromEdge', () => {
8021 if (!swiper.params.a11y.enabled) return;
8022 updateNavigation();
8023 });
8024 on('paginationUpdate', () => {
8025 if (!swiper.params.a11y.enabled) return;
8026 updatePagination();
8027 });
8028 on('destroy', () => {
8029 if (!swiper.params.a11y.enabled) return;
8030 destroy();
8031 });
8032 }
8033
8034 function History({
8035 swiper,
8036 extendParams,
8037 on
8038 }) {
8039 extendParams({
8040 history: {
8041 enabled: false,
8042 root: '',
8043 replaceState: false,
8044 key: 'slides'
8045 }
8046 });
8047 let initialized = false;
8048 let paths = {};
8049
8050 const slugify = text => {
8051 return text.toString().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
8052 };
8053
8054 const getPathValues = urlOverride => {
8055 const window = getWindow();
8056 let location;
8057
8058 if (urlOverride) {
8059 location = new URL(urlOverride);
8060 } else {
8061 location = window.location;
8062 }
8063
8064 const pathArray = location.pathname.slice(1).split('/').filter(part => part !== '');
8065 const total = pathArray.length;
8066 const key = pathArray[total - 2];
8067 const value = pathArray[total - 1];
8068 return {
8069 key,
8070 value
8071 };
8072 };
8073
8074 const setHistory = (key, index) => {
8075 const window = getWindow();
8076 if (!initialized || !swiper.params.history.enabled) return;
8077 let location;
8078
8079 if (swiper.params.url) {
8080 location = new URL(swiper.params.url);
8081 } else {
8082 location = window.location;
8083 }
8084
8085 const slide = swiper.slides.eq(index);
8086 let value = slugify(slide.attr('data-history'));
8087
8088 if (swiper.params.history.root.length > 0) {
8089 let root = swiper.params.history.root;
8090 if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1);
8091 value = `${root}/${key}/${value}`;
8092 } else if (!location.pathname.includes(key)) {
8093 value = `${key}/${value}`;
8094 }
8095
8096 const currentState = window.history.state;
8097
8098 if (currentState && currentState.value === value) {
8099 return;
8100 }
8101
8102 if (swiper.params.history.replaceState) {
8103 window.history.replaceState({
8104 value
8105 }, null, value);
8106 } else {
8107 window.history.pushState({
8108 value
8109 }, null, value);
8110 }
8111 };
8112
8113 const scrollToSlide = (speed, value, runCallbacks) => {
8114 if (value) {
8115 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
8116 const slide = swiper.slides.eq(i);
8117 const slideHistory = slugify(slide.attr('data-history'));
8118
8119 if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {
8120 const index = slide.index();
8121 swiper.slideTo(index, speed, runCallbacks);
8122 }
8123 }
8124 } else {
8125 swiper.slideTo(0, speed, runCallbacks);
8126 }
8127 };
8128
8129 const setHistoryPopState = () => {
8130 paths = getPathValues(swiper.params.url);
8131 scrollToSlide(swiper.params.speed, swiper.paths.value, false);
8132 };
8133
8134 const init = () => {
8135 const window = getWindow();
8136 if (!swiper.params.history) return;
8137
8138 if (!window.history || !window.history.pushState) {
8139 swiper.params.history.enabled = false;
8140 swiper.params.hashNavigation.enabled = true;
8141 return;
8142 }
8143
8144 initialized = true;
8145 paths = getPathValues(swiper.params.url);
8146 if (!paths.key && !paths.value) return;
8147 scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit);
8148
8149 if (!swiper.params.history.replaceState) {
8150 window.addEventListener('popstate', setHistoryPopState);
8151 }
8152 };
8153
8154 const destroy = () => {
8155 const window = getWindow();
8156
8157 if (!swiper.params.history.replaceState) {
8158 window.removeEventListener('popstate', setHistoryPopState);
8159 }
8160 };
8161
8162 on('init', () => {
8163 if (swiper.params.history.enabled) {
8164 init();
8165 }
8166 });
8167 on('destroy', () => {
8168 if (swiper.params.history.enabled) {
8169 destroy();
8170 }
8171 });
8172 on('transitionEnd _freeModeNoMomentumRelease', () => {
8173 if (initialized) {
8174 setHistory(swiper.params.history.key, swiper.activeIndex);
8175 }
8176 });
8177 on('slideChange', () => {
8178 if (initialized && swiper.params.cssMode) {
8179 setHistory(swiper.params.history.key, swiper.activeIndex);
8180 }
8181 });
8182 }
8183
8184 function HashNavigation({
8185 swiper,
8186 extendParams,
8187 emit,
8188 on
8189 }) {
8190 let initialized = false;
8191 const document = getDocument();
8192 const window = getWindow();
8193 extendParams({
8194 hashNavigation: {
8195 enabled: false,
8196 replaceState: false,
8197 watchState: false
8198 }
8199 });
8200
8201 const onHashChange = () => {
8202 emit('hashChange');
8203 const newHash = document.location.hash.replace('#', '');
8204 const activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');
8205
8206 if (newHash !== activeSlideHash) {
8207 const newIndex = swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-hash="${newHash}"]`).index();
8208 if (typeof newIndex === 'undefined') return;
8209 swiper.slideTo(newIndex);
8210 }
8211 };
8212
8213 const setHash = () => {
8214 if (!initialized || !swiper.params.hashNavigation.enabled) return;
8215
8216 if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) {
8217 window.history.replaceState(null, null, `#${swiper.slides.eq(swiper.activeIndex).attr('data-hash')}` || '');
8218 emit('hashSet');
8219 } else {
8220 const slide = swiper.slides.eq(swiper.activeIndex);
8221 const hash = slide.attr('data-hash') || slide.attr('data-history');
8222 document.location.hash = hash || '';
8223 emit('hashSet');
8224 }
8225 };
8226
8227 const init = () => {
8228 if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return;
8229 initialized = true;
8230 const hash = document.location.hash.replace('#', '');
8231
8232 if (hash) {
8233 const speed = 0;
8234
8235 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
8236 const slide = swiper.slides.eq(i);
8237 const slideHash = slide.attr('data-hash') || slide.attr('data-history');
8238
8239 if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {
8240 const index = slide.index();
8241 swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);
8242 }
8243 }
8244 }
8245
8246 if (swiper.params.hashNavigation.watchState) {
8247 $(window).on('hashchange', onHashChange);
8248 }
8249 };
8250
8251 const destroy = () => {
8252 if (swiper.params.hashNavigation.watchState) {
8253 $(window).off('hashchange', onHashChange);
8254 }
8255 };
8256
8257 on('init', () => {
8258 if (swiper.params.hashNavigation.enabled) {
8259 init();
8260 }
8261 });
8262 on('destroy', () => {
8263 if (swiper.params.hashNavigation.enabled) {
8264 destroy();
8265 }
8266 });
8267 on('transitionEnd _freeModeNoMomentumRelease', () => {
8268 if (initialized) {
8269 setHash();
8270 }
8271 });
8272 on('slideChange', () => {
8273 if (initialized && swiper.params.cssMode) {
8274 setHash();
8275 }
8276 });
8277 }
8278
8279 /* eslint no-underscore-dangle: "off" */
8280 function Autoplay({
8281 swiper,
8282 extendParams,
8283 on,
8284 emit
8285 }) {
8286 let timeout;
8287 swiper.autoplay = {
8288 running: false,
8289 paused: false
8290 };
8291 extendParams({
8292 autoplay: {
8293 enabled: false,
8294 delay: 3000,
8295 waitForTransition: true,
8296 disableOnInteraction: true,
8297 stopOnLastSlide: false,
8298 reverseDirection: false,
8299 pauseOnMouseEnter: false
8300 }
8301 });
8302
8303 function run() {
8304 const $activeSlideEl = swiper.slides.eq(swiper.activeIndex);
8305 let delay = swiper.params.autoplay.delay;
8306
8307 if ($activeSlideEl.attr('data-swiper-autoplay')) {
8308 delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;
8309 }
8310
8311 clearTimeout(timeout);
8312 timeout = nextTick(() => {
8313 let autoplayResult;
8314
8315 if (swiper.params.autoplay.reverseDirection) {
8316 if (swiper.params.loop) {
8317 swiper.loopFix();
8318 autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);
8319 emit('autoplay');
8320 } else if (!swiper.isBeginning) {
8321 autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);
8322 emit('autoplay');
8323 } else if (!swiper.params.autoplay.stopOnLastSlide) {
8324 autoplayResult = swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);
8325 emit('autoplay');
8326 } else {
8327 stop();
8328 }
8329 } else if (swiper.params.loop) {
8330 swiper.loopFix();
8331 autoplayResult = swiper.slideNext(swiper.params.speed, true, true);
8332 emit('autoplay');
8333 } else if (!swiper.isEnd) {
8334 autoplayResult = swiper.slideNext(swiper.params.speed, true, true);
8335 emit('autoplay');
8336 } else if (!swiper.params.autoplay.stopOnLastSlide) {
8337 autoplayResult = swiper.slideTo(0, swiper.params.speed, true, true);
8338 emit('autoplay');
8339 } else {
8340 stop();
8341 }
8342
8343 if (swiper.params.cssMode && swiper.autoplay.running) run();else if (autoplayResult === false) {
8344 run();
8345 }
8346 }, delay);
8347 }
8348
8349 function start() {
8350 if (typeof timeout !== 'undefined') return false;
8351 if (swiper.autoplay.running) return false;
8352 swiper.autoplay.running = true;
8353 emit('autoplayStart');
8354 run();
8355 return true;
8356 }
8357
8358 function stop() {
8359 if (!swiper.autoplay.running) return false;
8360 if (typeof timeout === 'undefined') return false;
8361
8362 if (timeout) {
8363 clearTimeout(timeout);
8364 timeout = undefined;
8365 }
8366
8367 swiper.autoplay.running = false;
8368 emit('autoplayStop');
8369 return true;
8370 }
8371
8372 function pause(speed) {
8373 if (!swiper.autoplay.running) return;
8374 if (swiper.autoplay.paused) return;
8375 if (timeout) clearTimeout(timeout);
8376 swiper.autoplay.paused = true;
8377
8378 if (speed === 0 || !swiper.params.autoplay.waitForTransition) {
8379 swiper.autoplay.paused = false;
8380 run();
8381 } else {
8382 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8383 swiper.$wrapperEl[0].addEventListener(event, onTransitionEnd);
8384 });
8385 }
8386 }
8387
8388 function onVisibilityChange() {
8389 const document = getDocument();
8390
8391 if (document.visibilityState === 'hidden' && swiper.autoplay.running) {
8392 pause();
8393 }
8394
8395 if (document.visibilityState === 'visible' && swiper.autoplay.paused) {
8396 run();
8397 swiper.autoplay.paused = false;
8398 }
8399 }
8400
8401 function onTransitionEnd(e) {
8402 if (!swiper || swiper.destroyed || !swiper.$wrapperEl) return;
8403 if (e.target !== swiper.$wrapperEl[0]) return;
8404 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8405 swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);
8406 });
8407 swiper.autoplay.paused = false;
8408
8409 if (!swiper.autoplay.running) {
8410 stop();
8411 } else {
8412 run();
8413 }
8414 }
8415
8416 function onMouseEnter() {
8417 if (swiper.params.autoplay.disableOnInteraction) {
8418 stop();
8419 } else {
8420 pause();
8421 }
8422
8423 ['transitionend', 'webkitTransitionEnd'].forEach(event => {
8424 swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);
8425 });
8426 }
8427
8428 function onMouseLeave() {
8429 if (swiper.params.autoplay.disableOnInteraction) {
8430 return;
8431 }
8432
8433 swiper.autoplay.paused = false;
8434 run();
8435 }
8436
8437 function attachMouseEvents() {
8438 if (swiper.params.autoplay.pauseOnMouseEnter) {
8439 swiper.$el.on('mouseenter', onMouseEnter);
8440 swiper.$el.on('mouseleave', onMouseLeave);
8441 }
8442 }
8443
8444 function detachMouseEvents() {
8445 swiper.$el.off('mouseenter', onMouseEnter);
8446 swiper.$el.off('mouseleave', onMouseLeave);
8447 }
8448
8449 on('init', () => {
8450 if (swiper.params.autoplay.enabled) {
8451 start();
8452 const document = getDocument();
8453 document.addEventListener('visibilitychange', onVisibilityChange);
8454 attachMouseEvents();
8455 }
8456 });
8457 on('beforeTransitionStart', (_s, speed, internal) => {
8458 if (swiper.autoplay.running) {
8459 if (internal || !swiper.params.autoplay.disableOnInteraction) {
8460 swiper.autoplay.pause(speed);
8461 } else {
8462 stop();
8463 }
8464 }
8465 });
8466 on('sliderFirstMove', () => {
8467 if (swiper.autoplay.running) {
8468 if (swiper.params.autoplay.disableOnInteraction) {
8469 stop();
8470 } else {
8471 pause();
8472 }
8473 }
8474 });
8475 on('touchEnd', () => {
8476 if (swiper.params.cssMode && swiper.autoplay.paused && !swiper.params.autoplay.disableOnInteraction) {
8477 run();
8478 }
8479 });
8480 on('destroy', () => {
8481 detachMouseEvents();
8482
8483 if (swiper.autoplay.running) {
8484 stop();
8485 }
8486
8487 const document = getDocument();
8488 document.removeEventListener('visibilitychange', onVisibilityChange);
8489 });
8490 Object.assign(swiper.autoplay, {
8491 pause,
8492 run,
8493 start,
8494 stop
8495 });
8496 }
8497
8498 function Thumb({
8499 swiper,
8500 extendParams,
8501 on
8502 }) {
8503 extendParams({
8504 thumbs: {
8505 swiper: null,
8506 multipleActiveThumbs: true,
8507 autoScrollOffset: 0,
8508 slideThumbActiveClass: 'swiper-slide-thumb-active',
8509 thumbsContainerClass: 'swiper-thumbs'
8510 }
8511 });
8512 let initialized = false;
8513 let swiperCreated = false;
8514 swiper.thumbs = {
8515 swiper: null
8516 };
8517
8518 function onThumbClick() {
8519 const thumbsSwiper = swiper.thumbs.swiper;
8520 if (!thumbsSwiper) return;
8521 const clickedIndex = thumbsSwiper.clickedIndex;
8522 const clickedSlide = thumbsSwiper.clickedSlide;
8523 if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) return;
8524 if (typeof clickedIndex === 'undefined' || clickedIndex === null) return;
8525 let slideToIndex;
8526
8527 if (thumbsSwiper.params.loop) {
8528 slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);
8529 } else {
8530 slideToIndex = clickedIndex;
8531 }
8532
8533 if (swiper.params.loop) {
8534 let currentIndex = swiper.activeIndex;
8535
8536 if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {
8537 swiper.loopFix(); // eslint-disable-next-line
8538
8539 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
8540 currentIndex = swiper.activeIndex;
8541 }
8542
8543 const prevIndex = swiper.slides.eq(currentIndex).prevAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
8544 const nextIndex = swiper.slides.eq(currentIndex).nextAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
8545 if (typeof prevIndex === 'undefined') slideToIndex = nextIndex;else if (typeof nextIndex === 'undefined') slideToIndex = prevIndex;else if (nextIndex - currentIndex < currentIndex - prevIndex) slideToIndex = nextIndex;else slideToIndex = prevIndex;
8546 }
8547
8548 swiper.slideTo(slideToIndex);
8549 }
8550
8551 function init() {
8552 const {
8553 thumbs: thumbsParams
8554 } = swiper.params;
8555 if (initialized) return false;
8556 initialized = true;
8557 const SwiperClass = swiper.constructor;
8558
8559 if (thumbsParams.swiper instanceof SwiperClass) {
8560 swiper.thumbs.swiper = thumbsParams.swiper;
8561 Object.assign(swiper.thumbs.swiper.originalParams, {
8562 watchSlidesProgress: true,
8563 slideToClickedSlide: false
8564 });
8565 Object.assign(swiper.thumbs.swiper.params, {
8566 watchSlidesProgress: true,
8567 slideToClickedSlide: false
8568 });
8569 } else if (isObject(thumbsParams.swiper)) {
8570 const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper);
8571 Object.assign(thumbsSwiperParams, {
8572 watchSlidesProgress: true,
8573 slideToClickedSlide: false
8574 });
8575 swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams);
8576 swiperCreated = true;
8577 }
8578
8579 swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);
8580 swiper.thumbs.swiper.on('tap', onThumbClick);
8581 return true;
8582 }
8583
8584 function update(initial) {
8585 const thumbsSwiper = swiper.thumbs.swiper;
8586 if (!thumbsSwiper) return;
8587 const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto' ? thumbsSwiper.slidesPerViewDynamic() : thumbsSwiper.params.slidesPerView;
8588 const autoScrollOffset = swiper.params.thumbs.autoScrollOffset;
8589 const useOffset = autoScrollOffset && !thumbsSwiper.params.loop;
8590
8591 if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) {
8592 let currentThumbsIndex = thumbsSwiper.activeIndex;
8593 let newThumbsIndex;
8594 let direction;
8595
8596 if (thumbsSwiper.params.loop) {
8597 if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {
8598 thumbsSwiper.loopFix(); // eslint-disable-next-line
8599
8600 thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;
8601 currentThumbsIndex = thumbsSwiper.activeIndex;
8602 } // Find actual thumbs index to slide to
8603
8604
8605 const prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
8606 const nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
8607
8608 if (typeof prevThumbsIndex === 'undefined') {
8609 newThumbsIndex = nextThumbsIndex;
8610 } else if (typeof nextThumbsIndex === 'undefined') {
8611 newThumbsIndex = prevThumbsIndex;
8612 } else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) {
8613 newThumbsIndex = thumbsSwiper.params.slidesPerGroup > 1 ? nextThumbsIndex : currentThumbsIndex;
8614 } else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) {
8615 newThumbsIndex = nextThumbsIndex;
8616 } else {
8617 newThumbsIndex = prevThumbsIndex;
8618 }
8619
8620 direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev';
8621 } else {
8622 newThumbsIndex = swiper.realIndex;
8623 direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev';
8624 }
8625
8626 if (useOffset) {
8627 newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset;
8628 }
8629
8630 if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {
8631 if (thumbsSwiper.params.centeredSlides) {
8632 if (newThumbsIndex > currentThumbsIndex) {
8633 newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
8634 } else {
8635 newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
8636 }
8637 } else if (newThumbsIndex > currentThumbsIndex && thumbsSwiper.params.slidesPerGroup === 1) ;
8638
8639 thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
8640 }
8641 } // Activate thumbs
8642
8643
8644 let thumbsToActivate = 1;
8645 const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
8646
8647 if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
8648 thumbsToActivate = swiper.params.slidesPerView;
8649 }
8650
8651 if (!swiper.params.thumbs.multipleActiveThumbs) {
8652 thumbsToActivate = 1;
8653 }
8654
8655 thumbsToActivate = Math.floor(thumbsToActivate);
8656 thumbsSwiper.slides.removeClass(thumbActiveClass);
8657
8658 if (thumbsSwiper.params.loop || thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled) {
8659 for (let i = 0; i < thumbsToActivate; i += 1) {
8660 thumbsSwiper.$wrapperEl.children(`[data-swiper-slide-index="${swiper.realIndex + i}"]`).addClass(thumbActiveClass);
8661 }
8662 } else {
8663 for (let i = 0; i < thumbsToActivate; i += 1) {
8664 thumbsSwiper.slides.eq(swiper.realIndex + i).addClass(thumbActiveClass);
8665 }
8666 }
8667 }
8668
8669 on('beforeInit', () => {
8670 const {
8671 thumbs
8672 } = swiper.params;
8673 if (!thumbs || !thumbs.swiper) return;
8674 init();
8675 update(true);
8676 });
8677 on('slideChange update resize observerUpdate', () => {
8678 if (!swiper.thumbs.swiper) return;
8679 update();
8680 });
8681 on('setTransition', (_s, duration) => {
8682 const thumbsSwiper = swiper.thumbs.swiper;
8683 if (!thumbsSwiper) return;
8684 thumbsSwiper.setTransition(duration);
8685 });
8686 on('beforeDestroy', () => {
8687 const thumbsSwiper = swiper.thumbs.swiper;
8688 if (!thumbsSwiper) return;
8689
8690 if (swiperCreated && thumbsSwiper) {
8691 thumbsSwiper.destroy();
8692 }
8693 });
8694 Object.assign(swiper.thumbs, {
8695 init,
8696 update
8697 });
8698 }
8699
8700 function freeMode({
8701 swiper,
8702 extendParams,
8703 emit,
8704 once
8705 }) {
8706 extendParams({
8707 freeMode: {
8708 enabled: false,
8709 momentum: true,
8710 momentumRatio: 1,
8711 momentumBounce: true,
8712 momentumBounceRatio: 1,
8713 momentumVelocityRatio: 1,
8714 sticky: false,
8715 minimumVelocity: 0.02
8716 }
8717 });
8718
8719 function onTouchMove() {
8720 const {
8721 touchEventsData: data,
8722 touches
8723 } = swiper; // Velocity
8724
8725 if (data.velocities.length === 0) {
8726 data.velocities.push({
8727 position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
8728 time: data.touchStartTime
8729 });
8730 }
8731
8732 data.velocities.push({
8733 position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
8734 time: now()
8735 });
8736 }
8737
8738 function onTouchEnd({
8739 currentPos
8740 }) {
8741 const {
8742 params,
8743 $wrapperEl,
8744 rtlTranslate: rtl,
8745 snapGrid,
8746 touchEventsData: data
8747 } = swiper; // Time diff
8748
8749 const touchEndTime = now();
8750 const timeDiff = touchEndTime - data.touchStartTime;
8751
8752 if (currentPos < -swiper.minTranslate()) {
8753 swiper.slideTo(swiper.activeIndex);
8754 return;
8755 }
8756
8757 if (currentPos > -swiper.maxTranslate()) {
8758 if (swiper.slides.length < snapGrid.length) {
8759 swiper.slideTo(snapGrid.length - 1);
8760 } else {
8761 swiper.slideTo(swiper.slides.length - 1);
8762 }
8763
8764 return;
8765 }
8766
8767 if (params.freeMode.momentum) {
8768 if (data.velocities.length > 1) {
8769 const lastMoveEvent = data.velocities.pop();
8770 const velocityEvent = data.velocities.pop();
8771 const distance = lastMoveEvent.position - velocityEvent.position;
8772 const time = lastMoveEvent.time - velocityEvent.time;
8773 swiper.velocity = distance / time;
8774 swiper.velocity /= 2;
8775
8776 if (Math.abs(swiper.velocity) < params.freeMode.minimumVelocity) {
8777 swiper.velocity = 0;
8778 } // this implies that the user stopped moving a finger then released.
8779 // There would be no events with distance zero, so the last event is stale.
8780
8781
8782 if (time > 150 || now() - lastMoveEvent.time > 300) {
8783 swiper.velocity = 0;
8784 }
8785 } else {
8786 swiper.velocity = 0;
8787 }
8788
8789 swiper.velocity *= params.freeMode.momentumVelocityRatio;
8790 data.velocities.length = 0;
8791 let momentumDuration = 1000 * params.freeMode.momentumRatio;
8792 const momentumDistance = swiper.velocity * momentumDuration;
8793 let newPosition = swiper.translate + momentumDistance;
8794 if (rtl) newPosition = -newPosition;
8795 let doBounce = false;
8796 let afterBouncePosition;
8797 const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeMode.momentumBounceRatio;
8798 let needsLoopFix;
8799
8800 if (newPosition < swiper.maxTranslate()) {
8801 if (params.freeMode.momentumBounce) {
8802 if (newPosition + swiper.maxTranslate() < -bounceAmount) {
8803 newPosition = swiper.maxTranslate() - bounceAmount;
8804 }
8805
8806 afterBouncePosition = swiper.maxTranslate();
8807 doBounce = true;
8808 data.allowMomentumBounce = true;
8809 } else {
8810 newPosition = swiper.maxTranslate();
8811 }
8812
8813 if (params.loop && params.centeredSlides) needsLoopFix = true;
8814 } else if (newPosition > swiper.minTranslate()) {
8815 if (params.freeMode.momentumBounce) {
8816 if (newPosition - swiper.minTranslate() > bounceAmount) {
8817 newPosition = swiper.minTranslate() + bounceAmount;
8818 }
8819
8820 afterBouncePosition = swiper.minTranslate();
8821 doBounce = true;
8822 data.allowMomentumBounce = true;
8823 } else {
8824 newPosition = swiper.minTranslate();
8825 }
8826
8827 if (params.loop && params.centeredSlides) needsLoopFix = true;
8828 } else if (params.freeMode.sticky) {
8829 let nextSlide;
8830
8831 for (let j = 0; j < snapGrid.length; j += 1) {
8832 if (snapGrid[j] > -newPosition) {
8833 nextSlide = j;
8834 break;
8835 }
8836 }
8837
8838 if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
8839 newPosition = snapGrid[nextSlide];
8840 } else {
8841 newPosition = snapGrid[nextSlide - 1];
8842 }
8843
8844 newPosition = -newPosition;
8845 }
8846
8847 if (needsLoopFix) {
8848 once('transitionEnd', () => {
8849 swiper.loopFix();
8850 });
8851 } // Fix duration
8852
8853
8854 if (swiper.velocity !== 0) {
8855 if (rtl) {
8856 momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
8857 } else {
8858 momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
8859 }
8860
8861 if (params.freeMode.sticky) {
8862 // If freeMode.sticky is active and the user ends a swipe with a slow-velocity
8863 // event, then durations can be 20+ seconds to slide one (or zero!) slides.
8864 // It's easy to see this when simulating touch with mouse events. To fix this,
8865 // limit single-slide swipes to the default slide duration. This also has the
8866 // nice side effect of matching slide speed if the user stopped moving before
8867 // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
8868 // For faster swipes, also apply limits (albeit higher ones).
8869 const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
8870 const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
8871
8872 if (moveDistance < currentSlideSize) {
8873 momentumDuration = params.speed;
8874 } else if (moveDistance < 2 * currentSlideSize) {
8875 momentumDuration = params.speed * 1.5;
8876 } else {
8877 momentumDuration = params.speed * 2.5;
8878 }
8879 }
8880 } else if (params.freeMode.sticky) {
8881 swiper.slideToClosest();
8882 return;
8883 }
8884
8885 if (params.freeMode.momentumBounce && doBounce) {
8886 swiper.updateProgress(afterBouncePosition);
8887 swiper.setTransition(momentumDuration);
8888 swiper.setTranslate(newPosition);
8889 swiper.transitionStart(true, swiper.swipeDirection);
8890 swiper.animating = true;
8891 $wrapperEl.transitionEnd(() => {
8892 if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
8893 emit('momentumBounce');
8894 swiper.setTransition(params.speed);
8895 setTimeout(() => {
8896 swiper.setTranslate(afterBouncePosition);
8897 $wrapperEl.transitionEnd(() => {
8898 if (!swiper || swiper.destroyed) return;
8899 swiper.transitionEnd();
8900 });
8901 }, 0);
8902 });
8903 } else if (swiper.velocity) {
8904 emit('_freeModeNoMomentumRelease');
8905 swiper.updateProgress(newPosition);
8906 swiper.setTransition(momentumDuration);
8907 swiper.setTranslate(newPosition);
8908 swiper.transitionStart(true, swiper.swipeDirection);
8909
8910 if (!swiper.animating) {
8911 swiper.animating = true;
8912 $wrapperEl.transitionEnd(() => {
8913 if (!swiper || swiper.destroyed) return;
8914 swiper.transitionEnd();
8915 });
8916 }
8917 } else {
8918 swiper.updateProgress(newPosition);
8919 }
8920
8921 swiper.updateActiveIndex();
8922 swiper.updateSlidesClasses();
8923 } else if (params.freeMode.sticky) {
8924 swiper.slideToClosest();
8925 return;
8926 } else if (params.freeMode) {
8927 emit('_freeModeNoMomentumRelease');
8928 }
8929
8930 if (!params.freeMode.momentum || timeDiff >= params.longSwipesMs) {
8931 swiper.updateProgress();
8932 swiper.updateActiveIndex();
8933 swiper.updateSlidesClasses();
8934 }
8935 }
8936
8937 Object.assign(swiper, {
8938 freeMode: {
8939 onTouchMove,
8940 onTouchEnd
8941 }
8942 });
8943 }
8944
8945 function Grid({
8946 swiper,
8947 extendParams
8948 }) {
8949 extendParams({
8950 grid: {
8951 rows: 1,
8952 fill: 'column'
8953 }
8954 });
8955 let slidesNumberEvenToRows;
8956 let slidesPerRow;
8957 let numFullColumns;
8958
8959 const initSlides = slidesLength => {
8960 const {
8961 slidesPerView
8962 } = swiper.params;
8963 const {
8964 rows,
8965 fill
8966 } = swiper.params.grid;
8967 slidesPerRow = slidesNumberEvenToRows / rows;
8968 numFullColumns = Math.floor(slidesLength / rows);
8969
8970 if (Math.floor(slidesLength / rows) === slidesLength / rows) {
8971 slidesNumberEvenToRows = slidesLength;
8972 } else {
8973 slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows;
8974 }
8975
8976 if (slidesPerView !== 'auto' && fill === 'row') {
8977 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, slidesPerView * rows);
8978 }
8979 };
8980
8981 const updateSlide = (i, slide, slidesLength, getDirectionLabel) => {
8982 const {
8983 slidesPerGroup,
8984 spaceBetween
8985 } = swiper.params;
8986 const {
8987 rows,
8988 fill
8989 } = swiper.params.grid; // Set slides order
8990
8991 let newSlideOrderIndex;
8992 let column;
8993 let row;
8994
8995 if (fill === 'row' && slidesPerGroup > 1) {
8996 const groupIndex = Math.floor(i / (slidesPerGroup * rows));
8997 const slideIndexInGroup = i - rows * slidesPerGroup * groupIndex;
8998 const columnsInGroup = groupIndex === 0 ? slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * rows * slidesPerGroup) / rows), slidesPerGroup);
8999 row = Math.floor(slideIndexInGroup / columnsInGroup);
9000 column = slideIndexInGroup - row * columnsInGroup + groupIndex * slidesPerGroup;
9001 newSlideOrderIndex = column + row * slidesNumberEvenToRows / rows;
9002 slide.css({
9003 '-webkit-order': newSlideOrderIndex,
9004 order: newSlideOrderIndex
9005 });
9006 } else if (fill === 'column') {
9007 column = Math.floor(i / rows);
9008 row = i - column * rows;
9009
9010 if (column > numFullColumns || column === numFullColumns && row === rows - 1) {
9011 row += 1;
9012
9013 if (row >= rows) {
9014 row = 0;
9015 column += 1;
9016 }
9017 }
9018 } else {
9019 row = Math.floor(i / slidesPerRow);
9020 column = i - row * slidesPerRow;
9021 }
9022
9023 slide.css(getDirectionLabel('margin-top'), row !== 0 ? spaceBetween && `${spaceBetween}px` : '');
9024 };
9025
9026 const updateWrapperSize = (slideSize, snapGrid, getDirectionLabel) => {
9027 const {
9028 spaceBetween,
9029 centeredSlides,
9030 roundLengths
9031 } = swiper.params;
9032 const {
9033 rows
9034 } = swiper.params.grid;
9035 swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows;
9036 swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween;
9037 swiper.$wrapperEl.css({
9038 [getDirectionLabel('width')]: `${swiper.virtualSize + spaceBetween}px`
9039 });
9040
9041 if (centeredSlides) {
9042 snapGrid.splice(0, snapGrid.length);
9043 const newSlidesGrid = [];
9044
9045 for (let i = 0; i < snapGrid.length; i += 1) {
9046 let slidesGridItem = snapGrid[i];
9047 if (roundLengths) slidesGridItem = Math.floor(slidesGridItem);
9048 if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
9049 }
9050
9051 snapGrid.push(...newSlidesGrid);
9052 }
9053 };
9054
9055 swiper.grid = {
9056 initSlides,
9057 updateSlide,
9058 updateWrapperSize
9059 };
9060 }
9061
9062 function appendSlide(slides) {
9063 const swiper = this;
9064 const {
9065 $wrapperEl,
9066 params
9067 } = swiper;
9068
9069 if (params.loop) {
9070 swiper.loopDestroy();
9071 }
9072
9073 if (typeof slides === 'object' && 'length' in slides) {
9074 for (let i = 0; i < slides.length; i += 1) {
9075 if (slides[i]) $wrapperEl.append(slides[i]);
9076 }
9077 } else {
9078 $wrapperEl.append(slides);
9079 }
9080
9081 if (params.loop) {
9082 swiper.loopCreate();
9083 }
9084
9085 if (!params.observer) {
9086 swiper.update();
9087 }
9088 }
9089
9090 function prependSlide(slides) {
9091 const swiper = this;
9092 const {
9093 params,
9094 $wrapperEl,
9095 activeIndex
9096 } = swiper;
9097
9098 if (params.loop) {
9099 swiper.loopDestroy();
9100 }
9101
9102 let newActiveIndex = activeIndex + 1;
9103
9104 if (typeof slides === 'object' && 'length' in slides) {
9105 for (let i = 0; i < slides.length; i += 1) {
9106 if (slides[i]) $wrapperEl.prepend(slides[i]);
9107 }
9108
9109 newActiveIndex = activeIndex + slides.length;
9110 } else {
9111 $wrapperEl.prepend(slides);
9112 }
9113
9114 if (params.loop) {
9115 swiper.loopCreate();
9116 }
9117
9118 if (!params.observer) {
9119 swiper.update();
9120 }
9121
9122 swiper.slideTo(newActiveIndex, 0, false);
9123 }
9124
9125 function addSlide(index, slides) {
9126 const swiper = this;
9127 const {
9128 $wrapperEl,
9129 params,
9130 activeIndex
9131 } = swiper;
9132 let activeIndexBuffer = activeIndex;
9133
9134 if (params.loop) {
9135 activeIndexBuffer -= swiper.loopedSlides;
9136 swiper.loopDestroy();
9137 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
9138 }
9139
9140 const baseLength = swiper.slides.length;
9141
9142 if (index <= 0) {
9143 swiper.prependSlide(slides);
9144 return;
9145 }
9146
9147 if (index >= baseLength) {
9148 swiper.appendSlide(slides);
9149 return;
9150 }
9151
9152 let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
9153 const slidesBuffer = [];
9154
9155 for (let i = baseLength - 1; i >= index; i -= 1) {
9156 const currentSlide = swiper.slides.eq(i);
9157 currentSlide.remove();
9158 slidesBuffer.unshift(currentSlide);
9159 }
9160
9161 if (typeof slides === 'object' && 'length' in slides) {
9162 for (let i = 0; i < slides.length; i += 1) {
9163 if (slides[i]) $wrapperEl.append(slides[i]);
9164 }
9165
9166 newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
9167 } else {
9168 $wrapperEl.append(slides);
9169 }
9170
9171 for (let i = 0; i < slidesBuffer.length; i += 1) {
9172 $wrapperEl.append(slidesBuffer[i]);
9173 }
9174
9175 if (params.loop) {
9176 swiper.loopCreate();
9177 }
9178
9179 if (!params.observer) {
9180 swiper.update();
9181 }
9182
9183 if (params.loop) {
9184 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
9185 } else {
9186 swiper.slideTo(newActiveIndex, 0, false);
9187 }
9188 }
9189
9190 function removeSlide(slidesIndexes) {
9191 const swiper = this;
9192 const {
9193 params,
9194 $wrapperEl,
9195 activeIndex
9196 } = swiper;
9197 let activeIndexBuffer = activeIndex;
9198
9199 if (params.loop) {
9200 activeIndexBuffer -= swiper.loopedSlides;
9201 swiper.loopDestroy();
9202 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
9203 }
9204
9205 let newActiveIndex = activeIndexBuffer;
9206 let indexToRemove;
9207
9208 if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
9209 for (let i = 0; i < slidesIndexes.length; i += 1) {
9210 indexToRemove = slidesIndexes[i];
9211 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
9212 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
9213 }
9214
9215 newActiveIndex = Math.max(newActiveIndex, 0);
9216 } else {
9217 indexToRemove = slidesIndexes;
9218 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
9219 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
9220 newActiveIndex = Math.max(newActiveIndex, 0);
9221 }
9222
9223 if (params.loop) {
9224 swiper.loopCreate();
9225 }
9226
9227 if (!params.observer) {
9228 swiper.update();
9229 }
9230
9231 if (params.loop) {
9232 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
9233 } else {
9234 swiper.slideTo(newActiveIndex, 0, false);
9235 }
9236 }
9237
9238 function removeAllSlides() {
9239 const swiper = this;
9240 const slidesIndexes = [];
9241
9242 for (let i = 0; i < swiper.slides.length; i += 1) {
9243 slidesIndexes.push(i);
9244 }
9245
9246 swiper.removeSlide(slidesIndexes);
9247 }
9248
9249 function Manipulation({
9250 swiper
9251 }) {
9252 Object.assign(swiper, {
9253 appendSlide: appendSlide.bind(swiper),
9254 prependSlide: prependSlide.bind(swiper),
9255 addSlide: addSlide.bind(swiper),
9256 removeSlide: removeSlide.bind(swiper),
9257 removeAllSlides: removeAllSlides.bind(swiper)
9258 });
9259 }
9260
9261 function effectInit(params) {
9262 const {
9263 effect,
9264 swiper,
9265 on,
9266 setTranslate,
9267 setTransition,
9268 overwriteParams,
9269 perspective
9270 } = params;
9271 on('beforeInit', () => {
9272 if (swiper.params.effect !== effect) return;
9273 swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`);
9274
9275 if (perspective && perspective()) {
9276 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
9277 }
9278
9279 const overwriteParamsResult = overwriteParams ? overwriteParams() : {};
9280 Object.assign(swiper.params, overwriteParamsResult);
9281 Object.assign(swiper.originalParams, overwriteParamsResult);
9282 });
9283 on('setTranslate', () => {
9284 if (swiper.params.effect !== effect) return;
9285 setTranslate();
9286 });
9287 on('setTransition', (_s, duration) => {
9288 if (swiper.params.effect !== effect) return;
9289 setTransition(duration);
9290 });
9291 }
9292
9293 function effectTarget(effectParams, $slideEl) {
9294 if (effectParams.transformEl) {
9295 return $slideEl.find(effectParams.transformEl).css({
9296 'backface-visibility': 'hidden',
9297 '-webkit-backface-visibility': 'hidden'
9298 });
9299 }
9300
9301 return $slideEl;
9302 }
9303
9304 function effectVirtualTransitionEnd({
9305 swiper,
9306 duration,
9307 transformEl,
9308 allSlides
9309 }) {
9310 const {
9311 slides,
9312 activeIndex,
9313 $wrapperEl
9314 } = swiper;
9315
9316 if (swiper.params.virtualTranslate && duration !== 0) {
9317 let eventTriggered = false;
9318 let $transitionEndTarget;
9319
9320 if (allSlides) {
9321 $transitionEndTarget = transformEl ? slides.find(transformEl) : slides;
9322 } else {
9323 $transitionEndTarget = transformEl ? slides.eq(activeIndex).find(transformEl) : slides.eq(activeIndex);
9324 }
9325
9326 $transitionEndTarget.transitionEnd(() => {
9327 if (eventTriggered) return;
9328 if (!swiper || swiper.destroyed) return;
9329 eventTriggered = true;
9330 swiper.animating = false;
9331 const triggerEvents = ['webkitTransitionEnd', 'transitionend'];
9332
9333 for (let i = 0; i < triggerEvents.length; i += 1) {
9334 $wrapperEl.trigger(triggerEvents[i]);
9335 }
9336 });
9337 }
9338 }
9339
9340 function EffectFade({
9341 swiper,
9342 extendParams,
9343 on
9344 }) {
9345 extendParams({
9346 fadeEffect: {
9347 crossFade: false,
9348 transformEl: null
9349 }
9350 });
9351
9352 const setTranslate = () => {
9353 const {
9354 slides
9355 } = swiper;
9356 const params = swiper.params.fadeEffect;
9357
9358 for (let i = 0; i < slides.length; i += 1) {
9359 const $slideEl = swiper.slides.eq(i);
9360 const offset = $slideEl[0].swiperSlideOffset;
9361 let tx = -offset;
9362 if (!swiper.params.virtualTranslate) tx -= swiper.translate;
9363 let ty = 0;
9364
9365 if (!swiper.isHorizontal()) {
9366 ty = tx;
9367 tx = 0;
9368 }
9369
9370 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);
9371 const $targetEl = effectTarget(params, $slideEl);
9372 $targetEl.css({
9373 opacity: slideOpacity
9374 }).transform(`translate3d(${tx}px, ${ty}px, 0px)`);
9375 }
9376 };
9377
9378 const setTransition = duration => {
9379 const {
9380 transformEl
9381 } = swiper.params.fadeEffect;
9382 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9383 $transitionElements.transition(duration);
9384 effectVirtualTransitionEnd({
9385 swiper,
9386 duration,
9387 transformEl,
9388 allSlides: true
9389 });
9390 };
9391
9392 effectInit({
9393 effect: 'fade',
9394 swiper,
9395 on,
9396 setTranslate,
9397 setTransition,
9398 overwriteParams: () => ({
9399 slidesPerView: 1,
9400 slidesPerGroup: 1,
9401 watchSlidesProgress: true,
9402 spaceBetween: 0,
9403 virtualTranslate: !swiper.params.cssMode
9404 })
9405 });
9406 }
9407
9408 function EffectCube({
9409 swiper,
9410 extendParams,
9411 on
9412 }) {
9413 extendParams({
9414 cubeEffect: {
9415 slideShadows: true,
9416 shadow: true,
9417 shadowOffset: 20,
9418 shadowScale: 0.94
9419 }
9420 });
9421
9422 const setTranslate = () => {
9423 const {
9424 $el,
9425 $wrapperEl,
9426 slides,
9427 width: swiperWidth,
9428 height: swiperHeight,
9429 rtlTranslate: rtl,
9430 size: swiperSize,
9431 browser
9432 } = swiper;
9433 const params = swiper.params.cubeEffect;
9434 const isHorizontal = swiper.isHorizontal();
9435 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
9436 let wrapperRotate = 0;
9437 let $cubeShadowEl;
9438
9439 if (params.shadow) {
9440 if (isHorizontal) {
9441 $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');
9442
9443 if ($cubeShadowEl.length === 0) {
9444 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
9445 $wrapperEl.append($cubeShadowEl);
9446 }
9447
9448 $cubeShadowEl.css({
9449 height: `${swiperWidth}px`
9450 });
9451 } else {
9452 $cubeShadowEl = $el.find('.swiper-cube-shadow');
9453
9454 if ($cubeShadowEl.length === 0) {
9455 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
9456 $el.append($cubeShadowEl);
9457 }
9458 }
9459 }
9460
9461 for (let i = 0; i < slides.length; i += 1) {
9462 const $slideEl = slides.eq(i);
9463 let slideIndex = i;
9464
9465 if (isVirtual) {
9466 slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);
9467 }
9468
9469 let slideAngle = slideIndex * 90;
9470 let round = Math.floor(slideAngle / 360);
9471
9472 if (rtl) {
9473 slideAngle = -slideAngle;
9474 round = Math.floor(-slideAngle / 360);
9475 }
9476
9477 const progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
9478 let tx = 0;
9479 let ty = 0;
9480 let tz = 0;
9481
9482 if (slideIndex % 4 === 0) {
9483 tx = -round * 4 * swiperSize;
9484 tz = 0;
9485 } else if ((slideIndex - 1) % 4 === 0) {
9486 tx = 0;
9487 tz = -round * 4 * swiperSize;
9488 } else if ((slideIndex - 2) % 4 === 0) {
9489 tx = swiperSize + round * 4 * swiperSize;
9490 tz = swiperSize;
9491 } else if ((slideIndex - 3) % 4 === 0) {
9492 tx = -swiperSize;
9493 tz = 3 * swiperSize + swiperSize * 4 * round;
9494 }
9495
9496 if (rtl) {
9497 tx = -tx;
9498 }
9499
9500 if (!isHorizontal) {
9501 ty = tx;
9502 tx = 0;
9503 }
9504
9505 const transform = `rotateX(${isHorizontal ? 0 : -slideAngle}deg) rotateY(${isHorizontal ? slideAngle : 0}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;
9506
9507 if (progress <= 1 && progress > -1) {
9508 wrapperRotate = slideIndex * 90 + progress * 90;
9509 if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90;
9510 }
9511
9512 $slideEl.transform(transform);
9513
9514 if (params.slideShadows) {
9515 // Set shadows
9516 let shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9517 let shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9518
9519 if (shadowBefore.length === 0) {
9520 shadowBefore = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}"></div>`);
9521 $slideEl.append(shadowBefore);
9522 }
9523
9524 if (shadowAfter.length === 0) {
9525 shadowAfter = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}"></div>`);
9526 $slideEl.append(shadowAfter);
9527 }
9528
9529 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
9530 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
9531 }
9532 }
9533
9534 $wrapperEl.css({
9535 '-webkit-transform-origin': `50% 50% -${swiperSize / 2}px`,
9536 'transform-origin': `50% 50% -${swiperSize / 2}px`
9537 });
9538
9539 if (params.shadow) {
9540 if (isHorizontal) {
9541 $cubeShadowEl.transform(`translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(90deg) rotateZ(0deg) scale(${params.shadowScale})`);
9542 } else {
9543 const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
9544 const multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
9545 const scale1 = params.shadowScale;
9546 const scale2 = params.shadowScale / multiplier;
9547 const offset = params.shadowOffset;
9548 $cubeShadowEl.transform(`scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-90deg)`);
9549 }
9550 }
9551
9552 const zFactor = browser.isSafari || browser.isWebView ? -swiperSize / 2 : 0;
9553 $wrapperEl.transform(`translate3d(0px,0,${zFactor}px) rotateX(${swiper.isHorizontal() ? 0 : wrapperRotate}deg) rotateY(${swiper.isHorizontal() ? -wrapperRotate : 0}deg)`);
9554 };
9555
9556 const setTransition = duration => {
9557 const {
9558 $el,
9559 slides
9560 } = swiper;
9561 slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9562
9563 if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
9564 $el.find('.swiper-cube-shadow').transition(duration);
9565 }
9566 };
9567
9568 effectInit({
9569 effect: 'cube',
9570 swiper,
9571 on,
9572 setTranslate,
9573 setTransition,
9574 perspective: () => true,
9575 overwriteParams: () => ({
9576 slidesPerView: 1,
9577 slidesPerGroup: 1,
9578 watchSlidesProgress: true,
9579 resistanceRatio: 0,
9580 spaceBetween: 0,
9581 centeredSlides: false,
9582 virtualTranslate: true
9583 })
9584 });
9585 }
9586
9587 function createShadow(params, $slideEl, side) {
9588 const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}`;
9589 const $shadowContainer = params.transformEl ? $slideEl.find(params.transformEl) : $slideEl;
9590 let $shadowEl = $shadowContainer.children(`.${shadowClass}`);
9591
9592 if (!$shadowEl.length) {
9593 $shadowEl = $(`<div class="swiper-slide-shadow${side ? `-${side}` : ''}"></div>`);
9594 $shadowContainer.append($shadowEl);
9595 }
9596
9597 return $shadowEl;
9598 }
9599
9600 function EffectFlip({
9601 swiper,
9602 extendParams,
9603 on
9604 }) {
9605 extendParams({
9606 flipEffect: {
9607 slideShadows: true,
9608 limitRotation: true,
9609 transformEl: null
9610 }
9611 });
9612
9613 const setTranslate = () => {
9614 const {
9615 slides,
9616 rtlTranslate: rtl
9617 } = swiper;
9618 const params = swiper.params.flipEffect;
9619
9620 for (let i = 0; i < slides.length; i += 1) {
9621 const $slideEl = slides.eq(i);
9622 let progress = $slideEl[0].progress;
9623
9624 if (swiper.params.flipEffect.limitRotation) {
9625 progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
9626 }
9627
9628 const offset = $slideEl[0].swiperSlideOffset;
9629 const rotate = -180 * progress;
9630 let rotateY = rotate;
9631 let rotateX = 0;
9632 let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset;
9633 let ty = 0;
9634
9635 if (!swiper.isHorizontal()) {
9636 ty = tx;
9637 tx = 0;
9638 rotateX = -rotateY;
9639 rotateY = 0;
9640 } else if (rtl) {
9641 rotateY = -rotateY;
9642 }
9643
9644 $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
9645
9646 if (params.slideShadows) {
9647 // Set shadows
9648 let shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9649 let shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9650
9651 if (shadowBefore.length === 0) {
9652 shadowBefore = createShadow(params, $slideEl, swiper.isHorizontal() ? 'left' : 'top');
9653 }
9654
9655 if (shadowAfter.length === 0) {
9656 shadowAfter = createShadow(params, $slideEl, swiper.isHorizontal() ? 'right' : 'bottom');
9657 }
9658
9659 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
9660 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
9661 }
9662
9663 const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
9664 const $targetEl = effectTarget(params, $slideEl);
9665 $targetEl.transform(transform);
9666 }
9667 };
9668
9669 const setTransition = duration => {
9670 const {
9671 transformEl
9672 } = swiper.params.flipEffect;
9673 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9674 $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9675 effectVirtualTransitionEnd({
9676 swiper,
9677 duration,
9678 transformEl
9679 });
9680 };
9681
9682 effectInit({
9683 effect: 'flip',
9684 swiper,
9685 on,
9686 setTranslate,
9687 setTransition,
9688 perspective: () => true,
9689 overwriteParams: () => ({
9690 slidesPerView: 1,
9691 slidesPerGroup: 1,
9692 watchSlidesProgress: true,
9693 spaceBetween: 0,
9694 virtualTranslate: !swiper.params.cssMode
9695 })
9696 });
9697 }
9698
9699 function EffectCoverflow({
9700 swiper,
9701 extendParams,
9702 on
9703 }) {
9704 extendParams({
9705 coverflowEffect: {
9706 rotate: 50,
9707 stretch: 0,
9708 depth: 100,
9709 scale: 1,
9710 modifier: 1,
9711 slideShadows: true,
9712 transformEl: null
9713 }
9714 });
9715
9716 const setTranslate = () => {
9717 const {
9718 width: swiperWidth,
9719 height: swiperHeight,
9720 slides,
9721 slidesSizesGrid
9722 } = swiper;
9723 const params = swiper.params.coverflowEffect;
9724 const isHorizontal = swiper.isHorizontal();
9725 const transform = swiper.translate;
9726 const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2;
9727 const rotate = isHorizontal ? params.rotate : -params.rotate;
9728 const translate = params.depth; // Each slide offset from center
9729
9730 for (let i = 0, length = slides.length; i < length; i += 1) {
9731 const $slideEl = slides.eq(i);
9732 const slideSize = slidesSizesGrid[i];
9733 const slideOffset = $slideEl[0].swiperSlideOffset;
9734 const offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * params.modifier;
9735 let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
9736 let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier; // var rotateZ = 0
9737
9738 let translateZ = -translate * Math.abs(offsetMultiplier);
9739 let stretch = params.stretch; // Allow percentage to make a relative stretch for responsive sliders
9740
9741 if (typeof stretch === 'string' && stretch.indexOf('%') !== -1) {
9742 stretch = parseFloat(params.stretch) / 100 * slideSize;
9743 }
9744
9745 let translateY = isHorizontal ? 0 : stretch * offsetMultiplier;
9746 let translateX = isHorizontal ? stretch * offsetMultiplier : 0;
9747 let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier); // Fix for ultra small values
9748
9749 if (Math.abs(translateX) < 0.001) translateX = 0;
9750 if (Math.abs(translateY) < 0.001) translateY = 0;
9751 if (Math.abs(translateZ) < 0.001) translateZ = 0;
9752 if (Math.abs(rotateY) < 0.001) rotateY = 0;
9753 if (Math.abs(rotateX) < 0.001) rotateX = 0;
9754 if (Math.abs(scale) < 0.001) scale = 0;
9755 const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${scale})`;
9756 const $targetEl = effectTarget(params, $slideEl);
9757 $targetEl.transform(slideTransform);
9758 $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
9759
9760 if (params.slideShadows) {
9761 // Set shadows
9762 let $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
9763 let $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
9764
9765 if ($shadowBeforeEl.length === 0) {
9766 $shadowBeforeEl = createShadow(params, $slideEl, isHorizontal ? 'left' : 'top');
9767 }
9768
9769 if ($shadowAfterEl.length === 0) {
9770 $shadowAfterEl = createShadow(params, $slideEl, isHorizontal ? 'right' : 'bottom');
9771 }
9772
9773 if ($shadowBeforeEl.length) $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
9774 if ($shadowAfterEl.length) $shadowAfterEl[0].style.opacity = -offsetMultiplier > 0 ? -offsetMultiplier : 0;
9775 }
9776 }
9777 };
9778
9779 const setTransition = duration => {
9780 const {
9781 transformEl
9782 } = swiper.params.coverflowEffect;
9783 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9784 $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
9785 };
9786
9787 effectInit({
9788 effect: 'coverflow',
9789 swiper,
9790 on,
9791 setTranslate,
9792 setTransition,
9793 perspective: () => true,
9794 overwriteParams: () => ({
9795 watchSlidesProgress: true
9796 })
9797 });
9798 }
9799
9800 function EffectCreative({
9801 swiper,
9802 extendParams,
9803 on
9804 }) {
9805 extendParams({
9806 creativeEffect: {
9807 transformEl: null,
9808 limitProgress: 1,
9809 shadowPerProgress: false,
9810 progressMultiplier: 1,
9811 perspective: true,
9812 prev: {
9813 translate: [0, 0, 0],
9814 rotate: [0, 0, 0],
9815 opacity: 1,
9816 scale: 1
9817 },
9818 next: {
9819 translate: [0, 0, 0],
9820 rotate: [0, 0, 0],
9821 opacity: 1,
9822 scale: 1
9823 }
9824 }
9825 });
9826
9827 const getTranslateValue = value => {
9828 if (typeof value === 'string') return value;
9829 return `${value}px`;
9830 };
9831
9832 const setTranslate = () => {
9833 const {
9834 slides,
9835 $wrapperEl,
9836 slidesSizesGrid
9837 } = swiper;
9838 const params = swiper.params.creativeEffect;
9839 const {
9840 progressMultiplier: multiplier
9841 } = params;
9842 const isCenteredSlides = swiper.params.centeredSlides;
9843
9844 if (isCenteredSlides) {
9845 const margin = slidesSizesGrid[0] / 2 - swiper.params.slidesOffsetBefore || 0;
9846 $wrapperEl.transform(`translateX(calc(50% - ${margin}px))`);
9847 }
9848
9849 for (let i = 0; i < slides.length; i += 1) {
9850 const $slideEl = slides.eq(i);
9851 const slideProgress = $slideEl[0].progress;
9852 const progress = Math.min(Math.max($slideEl[0].progress, -params.limitProgress), params.limitProgress);
9853 let originalProgress = progress;
9854
9855 if (!isCenteredSlides) {
9856 originalProgress = Math.min(Math.max($slideEl[0].originalProgress, -params.limitProgress), params.limitProgress);
9857 }
9858
9859 const offset = $slideEl[0].swiperSlideOffset;
9860 const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0];
9861 const r = [0, 0, 0];
9862 let custom = false;
9863
9864 if (!swiper.isHorizontal()) {
9865 t[1] = t[0];
9866 t[0] = 0;
9867 }
9868
9869 let data = {
9870 translate: [0, 0, 0],
9871 rotate: [0, 0, 0],
9872 scale: 1,
9873 opacity: 1
9874 };
9875
9876 if (progress < 0) {
9877 data = params.next;
9878 custom = true;
9879 } else if (progress > 0) {
9880 data = params.prev;
9881 custom = true;
9882 } // set translate
9883
9884
9885 t.forEach((value, index) => {
9886 t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`;
9887 }); // set rotates
9888
9889 r.forEach((value, index) => {
9890 r[index] = data.rotate[index] * Math.abs(progress * multiplier);
9891 });
9892 $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
9893 const translateString = t.join(', ');
9894 const rotateString = `rotateX(${r[0]}deg) rotateY(${r[1]}deg) rotateZ(${r[2]}deg)`;
9895 const scaleString = originalProgress < 0 ? `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` : `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`;
9896 const opacityString = originalProgress < 0 ? 1 + (1 - data.opacity) * originalProgress * multiplier : 1 - (1 - data.opacity) * originalProgress * multiplier;
9897 const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`; // Set shadows
9898
9899 if (custom && data.shadow || !custom) {
9900 let $shadowEl = $slideEl.children('.swiper-slide-shadow');
9901
9902 if ($shadowEl.length === 0 && data.shadow) {
9903 $shadowEl = createShadow(params, $slideEl);
9904 }
9905
9906 if ($shadowEl.length) {
9907 const shadowOpacity = params.shadowPerProgress ? progress * (1 / params.limitProgress) : progress;
9908 $shadowEl[0].style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1);
9909 }
9910 }
9911
9912 const $targetEl = effectTarget(params, $slideEl);
9913 $targetEl.transform(transform).css({
9914 opacity: opacityString
9915 });
9916
9917 if (data.origin) {
9918 $targetEl.css('transform-origin', data.origin);
9919 }
9920 }
9921 };
9922
9923 const setTransition = duration => {
9924 const {
9925 transformEl
9926 } = swiper.params.creativeEffect;
9927 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
9928 $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);
9929 effectVirtualTransitionEnd({
9930 swiper,
9931 duration,
9932 transformEl,
9933 allSlides: true
9934 });
9935 };
9936
9937 effectInit({
9938 effect: 'creative',
9939 swiper,
9940 on,
9941 setTranslate,
9942 setTransition,
9943 perspective: () => swiper.params.creativeEffect.perspective,
9944 overwriteParams: () => ({
9945 watchSlidesProgress: true,
9946 virtualTranslate: !swiper.params.cssMode
9947 })
9948 });
9949 }
9950
9951 function EffectCards({
9952 swiper,
9953 extendParams,
9954 on
9955 }) {
9956 extendParams({
9957 cardsEffect: {
9958 slideShadows: true,
9959 transformEl: null
9960 }
9961 });
9962
9963 const setTranslate = () => {
9964 const {
9965 slides,
9966 activeIndex
9967 } = swiper;
9968 const params = swiper.params.cardsEffect;
9969 const {
9970 startTranslate,
9971 isTouched
9972 } = swiper.touchEventsData;
9973 const currentTranslate = swiper.translate;
9974
9975 for (let i = 0; i < slides.length; i += 1) {
9976 const $slideEl = slides.eq(i);
9977 const slideProgress = $slideEl[0].progress;
9978 const progress = Math.min(Math.max(slideProgress, -4), 4);
9979 let offset = $slideEl[0].swiperSlideOffset;
9980
9981 if (swiper.params.centeredSlides && !swiper.params.cssMode) {
9982 swiper.$wrapperEl.transform(`translateX(${swiper.minTranslate()}px)`);
9983 }
9984
9985 if (swiper.params.centeredSlides && swiper.params.cssMode) {
9986 offset -= slides[0].swiperSlideOffset;
9987 }
9988
9989 let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset;
9990 let tY = 0;
9991 const tZ = -100 * Math.abs(progress);
9992 let scale = 1;
9993 let rotate = -2 * progress;
9994 let tXAdd = 8 - Math.abs(progress) * 0.75;
9995 const isSwipeToNext = (i === activeIndex || i === activeIndex - 1) && progress > 0 && progress < 1 && (isTouched || swiper.params.cssMode) && currentTranslate < startTranslate;
9996 const isSwipeToPrev = (i === activeIndex || i === activeIndex + 1) && progress < 0 && progress > -1 && (isTouched || swiper.params.cssMode) && currentTranslate > startTranslate;
9997
9998 if (isSwipeToNext || isSwipeToPrev) {
9999 const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5;
10000 rotate += -28 * progress * subProgress;
10001 scale += -0.5 * subProgress;
10002 tXAdd += 96 * subProgress;
10003 tY = `${-25 * subProgress * Math.abs(progress)}%`;
10004 }
10005
10006 if (progress < 0) {
10007 // next
10008 tX = `calc(${tX}px + (${tXAdd * Math.abs(progress)}%))`;
10009 } else if (progress > 0) {
10010 // prev
10011 tX = `calc(${tX}px + (-${tXAdd * Math.abs(progress)}%))`;
10012 } else {
10013 tX = `${tX}px`;
10014 }
10015
10016 if (!swiper.isHorizontal()) {
10017 const prevY = tY;
10018 tY = tX;
10019 tX = prevY;
10020 }
10021
10022 const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`;
10023 const transform = `
10024 translate3d(${tX}, ${tY}, ${tZ}px)
10025 rotateZ(${rotate}deg)
10026 scale(${scaleString})
10027 `;
10028
10029 if (params.slideShadows) {
10030 // Set shadows
10031 let $shadowEl = $slideEl.find('.swiper-slide-shadow');
10032
10033 if ($shadowEl.length === 0) {
10034 $shadowEl = createShadow(params, $slideEl);
10035 }
10036
10037 if ($shadowEl.length) $shadowEl[0].style.opacity = Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1);
10038 }
10039
10040 $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
10041 const $targetEl = effectTarget(params, $slideEl);
10042 $targetEl.transform(transform);
10043 }
10044 };
10045
10046 const setTransition = duration => {
10047 const {
10048 transformEl
10049 } = swiper.params.cardsEffect;
10050 const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
10051 $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);
10052 effectVirtualTransitionEnd({
10053 swiper,
10054 duration,
10055 transformEl
10056 });
10057 };
10058
10059 effectInit({
10060 effect: 'cards',
10061 swiper,
10062 on,
10063 setTranslate,
10064 setTransition,
10065 perspective: () => true,
10066 overwriteParams: () => ({
10067 watchSlidesProgress: true,
10068 virtualTranslate: !swiper.params.cssMode
10069 })
10070 });
10071 }
10072
10073 // Swiper Class
10074 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];
10075 Swiper.use(modules);
10076
10077 return Swiper;
10078
10079})));
10080//# sourceMappingURL=swiper-bundle.js.map