UNPKG

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