UNPKG

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