UNPKG

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