UNPKG

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