UNPKG

256 kBJavaScriptView Raw
1/**
2 * Swiper 5.0.4
3 * Most modern mobile touch slider and framework with hardware accelerated transitions
4 * http://swiperjs.com
5 *
6 * Copyright 2014-2019 Vladimir Kharlampidi
7 *
8 * Released under the MIT License
9 *
10 * Released on: September 30, 2019
11 */
12
13/**
14 * SSR Window 1.0.1
15 * Better handling for window object in SSR environment
16 * https://github.com/nolimits4web/ssr-window
17 *
18 * Copyright 2018, Vladimir Kharlampidi
19 *
20 * Licensed under MIT
21 *
22 * Released on: July 18, 2018
23 */
24var doc = (typeof document === 'undefined') ? {
25 body: {},
26 addEventListener: function addEventListener() {},
27 removeEventListener: function removeEventListener() {},
28 activeElement: {
29 blur: function blur() {},
30 nodeName: '',
31 },
32 querySelector: function querySelector() {
33 return null;
34 },
35 querySelectorAll: function querySelectorAll() {
36 return [];
37 },
38 getElementById: function getElementById() {
39 return null;
40 },
41 createEvent: function createEvent() {
42 return {
43 initEvent: function initEvent() {},
44 };
45 },
46 createElement: function createElement() {
47 return {
48 children: [],
49 childNodes: [],
50 style: {},
51 setAttribute: function setAttribute() {},
52 getElementsByTagName: function getElementsByTagName() {
53 return [];
54 },
55 };
56 },
57 location: { hash: '' },
58} : document; // eslint-disable-line
59
60var win = (typeof window === 'undefined') ? {
61 document: doc,
62 navigator: {
63 userAgent: '',
64 },
65 location: {},
66 history: {},
67 CustomEvent: function CustomEvent() {
68 return this;
69 },
70 addEventListener: function addEventListener() {},
71 removeEventListener: function removeEventListener() {},
72 getComputedStyle: function getComputedStyle() {
73 return {
74 getPropertyValue: function getPropertyValue() {
75 return '';
76 },
77 };
78 },
79 Image: function Image() {},
80 Date: function Date() {},
81 screen: {},
82 setTimeout: function setTimeout() {},
83 clearTimeout: function clearTimeout() {},
84} : window; // eslint-disable-line
85
86/**
87 * Dom7 2.1.3
88 * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API
89 * http://framework7.io/docs/dom.html
90 *
91 * Copyright 2019, Vladimir Kharlampidi
92 * The iDangero.us
93 * http://www.idangero.us/
94 *
95 * Licensed under MIT
96 *
97 * Released on: February 11, 2019
98 */
99
100class Dom7 {
101 constructor(arr) {
102 const self = this;
103 // Create array-like object
104 for (let i = 0; i < arr.length; i += 1) {
105 self[i] = arr[i];
106 }
107 self.length = arr.length;
108 // Return collection with methods
109 return this;
110 }
111}
112
113function $(selector, context) {
114 const arr = [];
115 let i = 0;
116 if (selector && !context) {
117 if (selector instanceof Dom7) {
118 return selector;
119 }
120 }
121 if (selector) {
122 // String
123 if (typeof selector === 'string') {
124 let els;
125 let tempParent;
126 const html = selector.trim();
127 if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
128 let toCreate = 'div';
129 if (html.indexOf('<li') === 0) toCreate = 'ul';
130 if (html.indexOf('<tr') === 0) toCreate = 'tbody';
131 if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr';
132 if (html.indexOf('<tbody') === 0) toCreate = 'table';
133 if (html.indexOf('<option') === 0) toCreate = 'select';
134 tempParent = doc.createElement(toCreate);
135 tempParent.innerHTML = html;
136 for (i = 0; i < tempParent.childNodes.length; i += 1) {
137 arr.push(tempParent.childNodes[i]);
138 }
139 } else {
140 if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) {
141 // Pure ID selector
142 els = [doc.getElementById(selector.trim().split('#')[1])];
143 } else {
144 // Other selectors
145 els = (context || doc).querySelectorAll(selector.trim());
146 }
147 for (i = 0; i < els.length; i += 1) {
148 if (els[i]) arr.push(els[i]);
149 }
150 }
151 } else if (selector.nodeType || selector === win || selector === doc) {
152 // Node/element
153 arr.push(selector);
154 } else if (selector.length > 0 && selector[0].nodeType) {
155 // Array of elements or instance of Dom
156 for (i = 0; i < selector.length; i += 1) {
157 arr.push(selector[i]);
158 }
159 }
160 }
161 return new Dom7(arr);
162}
163
164$.fn = Dom7.prototype;
165$.Class = Dom7;
166$.Dom7 = Dom7;
167
168function unique(arr) {
169 const uniqueArray = [];
170 for (let i = 0; i < arr.length; i += 1) {
171 if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]);
172 }
173 return uniqueArray;
174}
175
176// Classes and attributes
177function addClass(className) {
178 if (typeof className === 'undefined') {
179 return this;
180 }
181 const classes = className.split(' ');
182 for (let i = 0; i < classes.length; i += 1) {
183 for (let j = 0; j < this.length; j += 1) {
184 if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.add(classes[i]);
185 }
186 }
187 return this;
188}
189function removeClass(className) {
190 const classes = className.split(' ');
191 for (let i = 0; i < classes.length; i += 1) {
192 for (let j = 0; j < this.length; j += 1) {
193 if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.remove(classes[i]);
194 }
195 }
196 return this;
197}
198function hasClass(className) {
199 if (!this[0]) return false;
200 return this[0].classList.contains(className);
201}
202function toggleClass(className) {
203 const classes = className.split(' ');
204 for (let i = 0; i < classes.length; i += 1) {
205 for (let j = 0; j < this.length; j += 1) {
206 if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.toggle(classes[i]);
207 }
208 }
209 return this;
210}
211function attr(attrs, value) {
212 if (arguments.length === 1 && typeof attrs === 'string') {
213 // Get attr
214 if (this[0]) return this[0].getAttribute(attrs);
215 return undefined;
216 }
217
218 // Set attrs
219 for (let i = 0; i < this.length; i += 1) {
220 if (arguments.length === 2) {
221 // String
222 this[i].setAttribute(attrs, value);
223 } else {
224 // Object
225 // eslint-disable-next-line
226 for (const attrName in attrs) {
227 this[i][attrName] = attrs[attrName];
228 this[i].setAttribute(attrName, attrs[attrName]);
229 }
230 }
231 }
232 return this;
233}
234// eslint-disable-next-line
235function removeAttr(attr) {
236 for (let i = 0; i < this.length; i += 1) {
237 this[i].removeAttribute(attr);
238 }
239 return this;
240}
241function data(key, value) {
242 let el;
243 if (typeof value === 'undefined') {
244 el = this[0];
245 // Get value
246 if (el) {
247 if (el.dom7ElementDataStorage && (key in el.dom7ElementDataStorage)) {
248 return el.dom7ElementDataStorage[key];
249 }
250
251 const dataKey = el.getAttribute(`data-${key}`);
252 if (dataKey) {
253 return dataKey;
254 }
255 return undefined;
256 }
257 return undefined;
258 }
259
260 // Set value
261 for (let i = 0; i < this.length; i += 1) {
262 el = this[i];
263 if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {};
264 el.dom7ElementDataStorage[key] = value;
265 }
266 return this;
267}
268// Transforms
269// eslint-disable-next-line
270function transform(transform) {
271 for (let i = 0; i < this.length; i += 1) {
272 const elStyle = this[i].style;
273 elStyle.webkitTransform = transform;
274 elStyle.transform = transform;
275 }
276 return this;
277}
278function transition(duration) {
279 if (typeof duration !== 'string') {
280 duration = `${duration}ms`; // eslint-disable-line
281 }
282 for (let i = 0; i < this.length; i += 1) {
283 const elStyle = this[i].style;
284 elStyle.webkitTransitionDuration = duration;
285 elStyle.transitionDuration = duration;
286 }
287 return this;
288}
289// Events
290function on(...args) {
291 let [eventType, targetSelector, listener, capture] = args;
292 if (typeof args[1] === 'function') {
293 [eventType, listener, capture] = args;
294 targetSelector = undefined;
295 }
296 if (!capture) capture = false;
297
298 function handleLiveEvent(e) {
299 const target = e.target;
300 if (!target) return;
301 const eventData = e.target.dom7EventData || [];
302 if (eventData.indexOf(e) < 0) {
303 eventData.unshift(e);
304 }
305 if ($(target).is(targetSelector)) listener.apply(target, eventData);
306 else {
307 const parents = $(target).parents(); // eslint-disable-line
308 for (let k = 0; k < parents.length; k += 1) {
309 if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData);
310 }
311 }
312 }
313 function handleEvent(e) {
314 const eventData = e && e.target ? e.target.dom7EventData || [] : [];
315 if (eventData.indexOf(e) < 0) {
316 eventData.unshift(e);
317 }
318 listener.apply(this, eventData);
319 }
320 const events = eventType.split(' ');
321 let j;
322 for (let i = 0; i < this.length; i += 1) {
323 const el = this[i];
324 if (!targetSelector) {
325 for (j = 0; j < events.length; j += 1) {
326 const event = events[j];
327 if (!el.dom7Listeners) el.dom7Listeners = {};
328 if (!el.dom7Listeners[event]) el.dom7Listeners[event] = [];
329 el.dom7Listeners[event].push({
330 listener,
331 proxyListener: handleEvent,
332 });
333 el.addEventListener(event, handleEvent, capture);
334 }
335 } else {
336 // Live events
337 for (j = 0; j < events.length; j += 1) {
338 const event = events[j];
339 if (!el.dom7LiveListeners) el.dom7LiveListeners = {};
340 if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = [];
341 el.dom7LiveListeners[event].push({
342 listener,
343 proxyListener: handleLiveEvent,
344 });
345 el.addEventListener(event, handleLiveEvent, capture);
346 }
347 }
348 }
349 return this;
350}
351function off(...args) {
352 let [eventType, targetSelector, listener, capture] = args;
353 if (typeof args[1] === 'function') {
354 [eventType, listener, capture] = args;
355 targetSelector = undefined;
356 }
357 if (!capture) capture = false;
358
359 const events = eventType.split(' ');
360 for (let i = 0; i < events.length; i += 1) {
361 const event = events[i];
362 for (let j = 0; j < this.length; j += 1) {
363 const el = this[j];
364 let handlers;
365 if (!targetSelector && el.dom7Listeners) {
366 handlers = el.dom7Listeners[event];
367 } else if (targetSelector && el.dom7LiveListeners) {
368 handlers = el.dom7LiveListeners[event];
369 }
370 if (handlers && handlers.length) {
371 for (let k = handlers.length - 1; k >= 0; k -= 1) {
372 const handler = handlers[k];
373 if (listener && handler.listener === listener) {
374 el.removeEventListener(event, handler.proxyListener, capture);
375 handlers.splice(k, 1);
376 } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {
377 el.removeEventListener(event, handler.proxyListener, capture);
378 handlers.splice(k, 1);
379 } else if (!listener) {
380 el.removeEventListener(event, handler.proxyListener, capture);
381 handlers.splice(k, 1);
382 }
383 }
384 }
385 }
386 }
387 return this;
388}
389function trigger(...args) {
390 const events = args[0].split(' ');
391 const eventData = args[1];
392 for (let i = 0; i < events.length; i += 1) {
393 const event = events[i];
394 for (let j = 0; j < this.length; j += 1) {
395 const el = this[j];
396 let evt;
397 try {
398 evt = new win.CustomEvent(event, {
399 detail: eventData,
400 bubbles: true,
401 cancelable: true,
402 });
403 } catch (e) {
404 evt = doc.createEvent('Event');
405 evt.initEvent(event, true, true);
406 evt.detail = eventData;
407 }
408 // eslint-disable-next-line
409 el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0);
410 el.dispatchEvent(evt);
411 el.dom7EventData = [];
412 delete el.dom7EventData;
413 }
414 }
415 return this;
416}
417function transitionEnd(callback) {
418 const events = ['webkitTransitionEnd', 'transitionend'];
419 const dom = this;
420 let i;
421 function fireCallBack(e) {
422 /* jshint validthis:true */
423 if (e.target !== this) return;
424 callback.call(this, e);
425 for (i = 0; i < events.length; i += 1) {
426 dom.off(events[i], fireCallBack);
427 }
428 }
429 if (callback) {
430 for (i = 0; i < events.length; i += 1) {
431 dom.on(events[i], fireCallBack);
432 }
433 }
434 return this;
435}
436function outerWidth(includeMargins) {
437 if (this.length > 0) {
438 if (includeMargins) {
439 // eslint-disable-next-line
440 const styles = this.styles();
441 return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
442 }
443 return this[0].offsetWidth;
444 }
445 return null;
446}
447function outerHeight(includeMargins) {
448 if (this.length > 0) {
449 if (includeMargins) {
450 // eslint-disable-next-line
451 const styles = this.styles();
452 return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
453 }
454 return this[0].offsetHeight;
455 }
456 return null;
457}
458function offset() {
459 if (this.length > 0) {
460 const el = this[0];
461 const box = el.getBoundingClientRect();
462 const body = doc.body;
463 const clientTop = el.clientTop || body.clientTop || 0;
464 const clientLeft = el.clientLeft || body.clientLeft || 0;
465 const scrollTop = el === win ? win.scrollY : el.scrollTop;
466 const scrollLeft = el === win ? win.scrollX : el.scrollLeft;
467 return {
468 top: (box.top + scrollTop) - clientTop,
469 left: (box.left + scrollLeft) - clientLeft,
470 };
471 }
472
473 return null;
474}
475function styles() {
476 if (this[0]) return win.getComputedStyle(this[0], null);
477 return {};
478}
479function css(props, value) {
480 let i;
481 if (arguments.length === 1) {
482 if (typeof props === 'string') {
483 if (this[0]) return win.getComputedStyle(this[0], null).getPropertyValue(props);
484 } else {
485 for (i = 0; i < this.length; i += 1) {
486 // eslint-disable-next-line
487 for (let prop in props) {
488 this[i].style[prop] = props[prop];
489 }
490 }
491 return this;
492 }
493 }
494 if (arguments.length === 2 && typeof props === 'string') {
495 for (i = 0; i < this.length; i += 1) {
496 this[i].style[props] = value;
497 }
498 return this;
499 }
500 return this;
501}
502// Iterate over the collection passing elements to `callback`
503function each(callback) {
504 // Don't bother continuing without a callback
505 if (!callback) return this;
506 // Iterate over the current collection
507 for (let i = 0; i < this.length; i += 1) {
508 // If the callback returns false
509 if (callback.call(this[i], i, this[i]) === false) {
510 // End the loop early
511 return this;
512 }
513 }
514 // Return `this` to allow chained DOM operations
515 return this;
516}
517function filter(callback) {
518 const matchedItems = [];
519 const dom = this;
520 for (let i = 0; i < dom.length; i += 1) {
521 if (callback.call(dom[i], i, dom[i])) matchedItems.push(dom[i]);
522 }
523 return new Dom7(matchedItems);
524}
525// eslint-disable-next-line
526function html(html) {
527 if (typeof html === 'undefined') {
528 return this[0] ? this[0].innerHTML : undefined;
529 }
530
531 for (let i = 0; i < this.length; i += 1) {
532 this[i].innerHTML = html;
533 }
534 return this;
535}
536// eslint-disable-next-line
537function text(text) {
538 if (typeof text === 'undefined') {
539 if (this[0]) {
540 return this[0].textContent.trim();
541 }
542 return null;
543 }
544
545 for (let i = 0; i < this.length; i += 1) {
546 this[i].textContent = text;
547 }
548 return this;
549}
550function is(selector) {
551 const el = this[0];
552 let compareWith;
553 let i;
554 if (!el || typeof selector === 'undefined') return false;
555 if (typeof selector === 'string') {
556 if (el.matches) return el.matches(selector);
557 else if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);
558 else if (el.msMatchesSelector) return el.msMatchesSelector(selector);
559
560 compareWith = $(selector);
561 for (i = 0; i < compareWith.length; i += 1) {
562 if (compareWith[i] === el) return true;
563 }
564 return false;
565 } else if (selector === doc) return el === doc;
566 else if (selector === win) return el === win;
567
568 if (selector.nodeType || selector instanceof Dom7) {
569 compareWith = selector.nodeType ? [selector] : selector;
570 for (i = 0; i < compareWith.length; i += 1) {
571 if (compareWith[i] === el) return true;
572 }
573 return false;
574 }
575 return false;
576}
577function index() {
578 let child = this[0];
579 let i;
580 if (child) {
581 i = 0;
582 // eslint-disable-next-line
583 while ((child = child.previousSibling) !== null) {
584 if (child.nodeType === 1) i += 1;
585 }
586 return i;
587 }
588 return undefined;
589}
590// eslint-disable-next-line
591function eq(index) {
592 if (typeof index === 'undefined') return this;
593 const length = this.length;
594 let returnIndex;
595 if (index > length - 1) {
596 return new Dom7([]);
597 }
598 if (index < 0) {
599 returnIndex = length + index;
600 if (returnIndex < 0) return new Dom7([]);
601 return new Dom7([this[returnIndex]]);
602 }
603 return new Dom7([this[index]]);
604}
605function append(...args) {
606 let newChild;
607
608 for (let k = 0; k < args.length; k += 1) {
609 newChild = args[k];
610 for (let i = 0; i < this.length; i += 1) {
611 if (typeof newChild === 'string') {
612 const tempDiv = doc.createElement('div');
613 tempDiv.innerHTML = newChild;
614 while (tempDiv.firstChild) {
615 this[i].appendChild(tempDiv.firstChild);
616 }
617 } else if (newChild instanceof Dom7) {
618 for (let j = 0; j < newChild.length; j += 1) {
619 this[i].appendChild(newChild[j]);
620 }
621 } else {
622 this[i].appendChild(newChild);
623 }
624 }
625 }
626
627 return this;
628}
629function prepend(newChild) {
630 let i;
631 let j;
632 for (i = 0; i < this.length; i += 1) {
633 if (typeof newChild === 'string') {
634 const tempDiv = doc.createElement('div');
635 tempDiv.innerHTML = newChild;
636 for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {
637 this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
638 }
639 } else if (newChild instanceof Dom7) {
640 for (j = 0; j < newChild.length; j += 1) {
641 this[i].insertBefore(newChild[j], this[i].childNodes[0]);
642 }
643 } else {
644 this[i].insertBefore(newChild, this[i].childNodes[0]);
645 }
646 }
647 return this;
648}
649function next(selector) {
650 if (this.length > 0) {
651 if (selector) {
652 if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {
653 return new Dom7([this[0].nextElementSibling]);
654 }
655 return new Dom7([]);
656 }
657
658 if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]);
659 return new Dom7([]);
660 }
661 return new Dom7([]);
662}
663function nextAll(selector) {
664 const nextEls = [];
665 let el = this[0];
666 if (!el) return new Dom7([]);
667 while (el.nextElementSibling) {
668 const next = el.nextElementSibling; // eslint-disable-line
669 if (selector) {
670 if ($(next).is(selector)) nextEls.push(next);
671 } else nextEls.push(next);
672 el = next;
673 }
674 return new Dom7(nextEls);
675}
676function prev(selector) {
677 if (this.length > 0) {
678 const el = this[0];
679 if (selector) {
680 if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {
681 return new Dom7([el.previousElementSibling]);
682 }
683 return new Dom7([]);
684 }
685
686 if (el.previousElementSibling) return new Dom7([el.previousElementSibling]);
687 return new Dom7([]);
688 }
689 return new Dom7([]);
690}
691function prevAll(selector) {
692 const prevEls = [];
693 let el = this[0];
694 if (!el) return new Dom7([]);
695 while (el.previousElementSibling) {
696 const prev = el.previousElementSibling; // eslint-disable-line
697 if (selector) {
698 if ($(prev).is(selector)) prevEls.push(prev);
699 } else prevEls.push(prev);
700 el = prev;
701 }
702 return new Dom7(prevEls);
703}
704function parent(selector) {
705 const parents = []; // eslint-disable-line
706 for (let i = 0; i < this.length; i += 1) {
707 if (this[i].parentNode !== null) {
708 if (selector) {
709 if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);
710 } else {
711 parents.push(this[i].parentNode);
712 }
713 }
714 }
715 return $(unique(parents));
716}
717function parents(selector) {
718 const parents = []; // eslint-disable-line
719 for (let i = 0; i < this.length; i += 1) {
720 let parent = this[i].parentNode; // eslint-disable-line
721 while (parent) {
722 if (selector) {
723 if ($(parent).is(selector)) parents.push(parent);
724 } else {
725 parents.push(parent);
726 }
727 parent = parent.parentNode;
728 }
729 }
730 return $(unique(parents));
731}
732function closest(selector) {
733 let closest = this; // eslint-disable-line
734 if (typeof selector === 'undefined') {
735 return new Dom7([]);
736 }
737 if (!closest.is(selector)) {
738 closest = closest.parents(selector).eq(0);
739 }
740 return closest;
741}
742function find(selector) {
743 const foundElements = [];
744 for (let i = 0; i < this.length; i += 1) {
745 const found = this[i].querySelectorAll(selector);
746 for (let j = 0; j < found.length; j += 1) {
747 foundElements.push(found[j]);
748 }
749 }
750 return new Dom7(foundElements);
751}
752function children(selector) {
753 const children = []; // eslint-disable-line
754 for (let i = 0; i < this.length; i += 1) {
755 const childNodes = this[i].childNodes;
756
757 for (let j = 0; j < childNodes.length; j += 1) {
758 if (!selector) {
759 if (childNodes[j].nodeType === 1) children.push(childNodes[j]);
760 } else if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) {
761 children.push(childNodes[j]);
762 }
763 }
764 }
765 return new Dom7(unique(children));
766}
767function remove() {
768 for (let i = 0; i < this.length; i += 1) {
769 if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);
770 }
771 return this;
772}
773function add(...args) {
774 const dom = this;
775 let i;
776 let j;
777 for (i = 0; i < args.length; i += 1) {
778 const toAdd = $(args[i]);
779 for (j = 0; j < toAdd.length; j += 1) {
780 dom[dom.length] = toAdd[j];
781 dom.length += 1;
782 }
783 }
784 return dom;
785}
786
787const Methods = {
788 addClass,
789 removeClass,
790 hasClass,
791 toggleClass,
792 attr,
793 removeAttr,
794 data,
795 transform,
796 transition,
797 on,
798 off,
799 trigger,
800 transitionEnd,
801 outerWidth,
802 outerHeight,
803 offset,
804 css,
805 each,
806 html,
807 text,
808 is,
809 index,
810 eq,
811 append,
812 prepend,
813 next,
814 nextAll,
815 prev,
816 prevAll,
817 parent,
818 parents,
819 closest,
820 find,
821 children,
822 filter,
823 remove,
824 add,
825 styles,
826};
827
828Object.keys(Methods).forEach((methodName) => {
829 $.fn[methodName] = $.fn[methodName] || Methods[methodName];
830});
831
832const Utils = {
833 deleteProps(obj) {
834 const object = obj;
835 Object.keys(object).forEach((key) => {
836 try {
837 object[key] = null;
838 } catch (e) {
839 // no getter for object
840 }
841 try {
842 delete object[key];
843 } catch (e) {
844 // something got wrong
845 }
846 });
847 },
848 nextTick(callback, delay = 0) {
849 return setTimeout(callback, delay);
850 },
851 now() {
852 return Date.now();
853 },
854 getTranslate(el, axis = 'x') {
855 let matrix;
856 let curTransform;
857 let transformMatrix;
858
859 const curStyle = win.getComputedStyle(el, null);
860
861 if (win.WebKitCSSMatrix) {
862 curTransform = curStyle.transform || curStyle.webkitTransform;
863 if (curTransform.split(',').length > 6) {
864 curTransform = curTransform.split(', ').map((a) => a.replace(',', '.')).join(', ');
865 }
866 // Some old versions of Webkit choke when 'none' is passed; pass
867 // empty string instead in this case
868 transformMatrix = new win.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
869 } else {
870 transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
871 matrix = transformMatrix.toString().split(',');
872 }
873
874 if (axis === 'x') {
875 // Latest Chrome and webkits Fix
876 if (win.WebKitCSSMatrix) curTransform = transformMatrix.m41;
877 // Crazy IE10 Matrix
878 else if (matrix.length === 16) curTransform = parseFloat(matrix[12]);
879 // Normal Browsers
880 else curTransform = parseFloat(matrix[4]);
881 }
882 if (axis === 'y') {
883 // Latest Chrome and webkits Fix
884 if (win.WebKitCSSMatrix) curTransform = transformMatrix.m42;
885 // Crazy IE10 Matrix
886 else if (matrix.length === 16) curTransform = parseFloat(matrix[13]);
887 // Normal Browsers
888 else curTransform = parseFloat(matrix[5]);
889 }
890 return curTransform || 0;
891 },
892 parseUrlQuery(url) {
893 const query = {};
894 let urlToParse = url || win.location.href;
895 let i;
896 let params;
897 let param;
898 let length;
899 if (typeof urlToParse === 'string' && urlToParse.length) {
900 urlToParse = urlToParse.indexOf('?') > -1 ? urlToParse.replace(/\S*\?/, '') : '';
901 params = urlToParse.split('&').filter((paramsPart) => paramsPart !== '');
902 length = params.length;
903
904 for (i = 0; i < length; i += 1) {
905 param = params[i].replace(/#\S+/g, '').split('=');
906 query[decodeURIComponent(param[0])] = typeof param[1] === 'undefined' ? undefined : decodeURIComponent(param[1]) || '';
907 }
908 }
909 return query;
910 },
911 isObject(o) {
912 return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object;
913 },
914 extend(...args) {
915 const to = Object(args[0]);
916 for (let i = 1; i < args.length; i += 1) {
917 const nextSource = args[i];
918 if (nextSource !== undefined && nextSource !== null) {
919 const keysArray = Object.keys(Object(nextSource));
920 for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
921 const nextKey = keysArray[nextIndex];
922 const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
923 if (desc !== undefined && desc.enumerable) {
924 if (Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
925 Utils.extend(to[nextKey], nextSource[nextKey]);
926 } else if (!Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
927 to[nextKey] = {};
928 Utils.extend(to[nextKey], nextSource[nextKey]);
929 } else {
930 to[nextKey] = nextSource[nextKey];
931 }
932 }
933 }
934 }
935 }
936 return to;
937 },
938};
939
940const Support = (function Support() {
941 return {
942 touch: (win.Modernizr && win.Modernizr.touch === true) || (function checkTouch() {
943 return !!((win.navigator.maxTouchPoints > 0) || ('ontouchstart' in win) || (win.DocumentTouch && doc instanceof win.DocumentTouch));
944 }()),
945
946 pointerEvents: !!win.PointerEvent && ('maxTouchPoints' in win.navigator) && win.navigator.maxTouchPoints > 0,
947
948 observer: (function checkObserver() {
949 return ('MutationObserver' in win || 'WebkitMutationObserver' in win);
950 }()),
951
952 passiveListener: (function checkPassiveListener() {
953 let supportsPassive = false;
954 try {
955 const opts = Object.defineProperty({}, 'passive', {
956 // eslint-disable-next-line
957 get() {
958 supportsPassive = true;
959 },
960 });
961 win.addEventListener('testPassiveListener', null, opts);
962 } catch (e) {
963 // No support
964 }
965 return supportsPassive;
966 }()),
967
968 gestures: (function checkGestures() {
969 return 'ongesturestart' in win;
970 }()),
971 };
972}());
973
974class SwiperClass {
975 constructor(params = {}) {
976 const self = this;
977 self.params = params;
978
979 // Events
980 self.eventsListeners = {};
981
982 if (self.params && self.params.on) {
983 Object.keys(self.params.on).forEach((eventName) => {
984 self.on(eventName, self.params.on[eventName]);
985 });
986 }
987 }
988
989 on(events, handler, priority) {
990 const self = this;
991 if (typeof handler !== 'function') return self;
992 const method = priority ? 'unshift' : 'push';
993 events.split(' ').forEach((event) => {
994 if (!self.eventsListeners[event]) self.eventsListeners[event] = [];
995 self.eventsListeners[event][method](handler);
996 });
997 return self;
998 }
999
1000 once(events, handler, priority) {
1001 const self = this;
1002 if (typeof handler !== 'function') return self;
1003 function onceHandler(...args) {
1004 handler.apply(self, args);
1005 self.off(events, onceHandler);
1006 if (onceHandler.f7proxy) {
1007 delete onceHandler.f7proxy;
1008 }
1009 }
1010 onceHandler.f7proxy = handler;
1011 return self.on(events, onceHandler, priority);
1012 }
1013
1014 off(events, handler) {
1015 const self = this;
1016 if (!self.eventsListeners) return self;
1017 events.split(' ').forEach((event) => {
1018 if (typeof handler === 'undefined') {
1019 self.eventsListeners[event] = [];
1020 } else if (self.eventsListeners[event] && self.eventsListeners[event].length) {
1021 self.eventsListeners[event].forEach((eventHandler, index) => {
1022 if (eventHandler === handler || (eventHandler.f7proxy && eventHandler.f7proxy === handler)) {
1023 self.eventsListeners[event].splice(index, 1);
1024 }
1025 });
1026 }
1027 });
1028 return self;
1029 }
1030
1031 emit(...args) {
1032 const self = this;
1033 if (!self.eventsListeners) return self;
1034 let events;
1035 let data;
1036 let context;
1037 if (typeof args[0] === 'string' || Array.isArray(args[0])) {
1038 events = args[0];
1039 data = args.slice(1, args.length);
1040 context = self;
1041 } else {
1042 events = args[0].events;
1043 data = args[0].data;
1044 context = args[0].context || self;
1045 }
1046 const eventsArray = Array.isArray(events) ? events : events.split(' ');
1047 eventsArray.forEach((event) => {
1048 if (self.eventsListeners && self.eventsListeners[event]) {
1049 const handlers = [];
1050 self.eventsListeners[event].forEach((eventHandler) => {
1051 handlers.push(eventHandler);
1052 });
1053 handlers.forEach((eventHandler) => {
1054 eventHandler.apply(context, data);
1055 });
1056 }
1057 });
1058 return self;
1059 }
1060
1061 useModulesParams(instanceParams) {
1062 const instance = this;
1063 if (!instance.modules) return;
1064 Object.keys(instance.modules).forEach((moduleName) => {
1065 const module = instance.modules[moduleName];
1066 // Extend params
1067 if (module.params) {
1068 Utils.extend(instanceParams, module.params);
1069 }
1070 });
1071 }
1072
1073 useModules(modulesParams = {}) {
1074 const instance = this;
1075 if (!instance.modules) return;
1076 Object.keys(instance.modules).forEach((moduleName) => {
1077 const module = instance.modules[moduleName];
1078 const moduleParams = modulesParams[moduleName] || {};
1079 // Extend instance methods and props
1080 if (module.instance) {
1081 Object.keys(module.instance).forEach((modulePropName) => {
1082 const moduleProp = module.instance[modulePropName];
1083 if (typeof moduleProp === 'function') {
1084 instance[modulePropName] = moduleProp.bind(instance);
1085 } else {
1086 instance[modulePropName] = moduleProp;
1087 }
1088 });
1089 }
1090 // Add event listeners
1091 if (module.on && instance.on) {
1092 Object.keys(module.on).forEach((moduleEventName) => {
1093 instance.on(moduleEventName, module.on[moduleEventName]);
1094 });
1095 }
1096
1097 // Module create callback
1098 if (module.create) {
1099 module.create.bind(instance)(moduleParams);
1100 }
1101 });
1102 }
1103
1104 static set components(components) {
1105 const Class = this;
1106 if (!Class.use) return;
1107 Class.use(components);
1108 }
1109
1110 static installModule(module, ...params) {
1111 const Class = this;
1112 if (!Class.prototype.modules) Class.prototype.modules = {};
1113 const name = module.name || (`${Object.keys(Class.prototype.modules).length}_${Utils.now()}`);
1114 Class.prototype.modules[name] = module;
1115 // Prototype
1116 if (module.proto) {
1117 Object.keys(module.proto).forEach((key) => {
1118 Class.prototype[key] = module.proto[key];
1119 });
1120 }
1121 // Class
1122 if (module.static) {
1123 Object.keys(module.static).forEach((key) => {
1124 Class[key] = module.static[key];
1125 });
1126 }
1127 // Callback
1128 if (module.install) {
1129 module.install.apply(Class, params);
1130 }
1131 return Class;
1132 }
1133
1134 static use(module, ...params) {
1135 const Class = this;
1136 if (Array.isArray(module)) {
1137 module.forEach((m) => Class.installModule(m));
1138 return Class;
1139 }
1140 return Class.installModule(module, ...params);
1141 }
1142}
1143
1144function updateSize () {
1145 const swiper = this;
1146 let width;
1147 let height;
1148 const $el = swiper.$el;
1149 if (typeof swiper.params.width !== 'undefined') {
1150 width = swiper.params.width;
1151 } else {
1152 width = $el[0].clientWidth;
1153 }
1154 if (typeof swiper.params.height !== 'undefined') {
1155 height = swiper.params.height;
1156 } else {
1157 height = $el[0].clientHeight;
1158 }
1159 if ((width === 0 && swiper.isHorizontal()) || (height === 0 && swiper.isVertical())) {
1160 return;
1161 }
1162
1163 // Subtract paddings
1164 width = width - parseInt($el.css('padding-left'), 10) - parseInt($el.css('padding-right'), 10);
1165 height = height - parseInt($el.css('padding-top'), 10) - parseInt($el.css('padding-bottom'), 10);
1166
1167 Utils.extend(swiper, {
1168 width,
1169 height,
1170 size: swiper.isHorizontal() ? width : height,
1171 });
1172}
1173
1174function updateSlides () {
1175 const swiper = this;
1176 const params = swiper.params;
1177
1178 const {
1179 $wrapperEl, size: swiperSize, rtlTranslate: rtl, wrongRTL,
1180 } = swiper;
1181 const isVirtual = swiper.virtual && params.virtual.enabled;
1182 const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
1183 const slides = $wrapperEl.children(`.${swiper.params.slideClass}`);
1184 const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
1185 let snapGrid = [];
1186 const slidesGrid = [];
1187 const slidesSizesGrid = [];
1188
1189 function slidesForMargin(slideIndex) {
1190 if (!params.cssMode) return true;
1191 if (slideIndex === slides.length - 1) {
1192 return false;
1193 }
1194 return true;
1195 }
1196
1197 let offsetBefore = params.slidesOffsetBefore;
1198 if (typeof offsetBefore === 'function') {
1199 offsetBefore = params.slidesOffsetBefore.call(swiper);
1200 }
1201
1202 let offsetAfter = params.slidesOffsetAfter;
1203 if (typeof offsetAfter === 'function') {
1204 offsetAfter = params.slidesOffsetAfter.call(swiper);
1205 }
1206
1207 const previousSnapGridLength = swiper.snapGrid.length;
1208 const previousSlidesGridLength = swiper.snapGrid.length;
1209
1210 let spaceBetween = params.spaceBetween;
1211 let slidePosition = -offsetBefore;
1212 let prevSlideSize = 0;
1213 let index = 0;
1214 if (typeof swiperSize === 'undefined') {
1215 return;
1216 }
1217 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
1218 spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiperSize;
1219 }
1220
1221 swiper.virtualSize = -spaceBetween;
1222
1223 // reset margins
1224 if (rtl) slides.css({ marginLeft: '', marginTop: '' });
1225 else slides.css({ marginRight: '', marginBottom: '' });
1226
1227 let slidesNumberEvenToRows;
1228 if (params.slidesPerColumn > 1) {
1229 if (Math.floor(slidesLength / params.slidesPerColumn) === slidesLength / swiper.params.slidesPerColumn) {
1230 slidesNumberEvenToRows = slidesLength;
1231 } else {
1232 slidesNumberEvenToRows = Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn;
1233 }
1234 if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') {
1235 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, params.slidesPerView * params.slidesPerColumn);
1236 }
1237 }
1238
1239 // Calc slides
1240 let slideSize;
1241 const slidesPerColumn = params.slidesPerColumn;
1242 const slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
1243 const numFullColumns = Math.floor(slidesLength / params.slidesPerColumn);
1244 for (let i = 0; i < slidesLength; i += 1) {
1245 slideSize = 0;
1246 const slide = slides.eq(i);
1247 if (params.slidesPerColumn > 1) {
1248 // Set slides order
1249 let newSlideOrderIndex;
1250 let column;
1251 let row;
1252 if (params.slidesPerColumnFill === 'row' && params.slidesPerGroup > 1) {
1253 const groupIndex = Math.floor(i / (params.slidesPerGroup * params.slidesPerColumn));
1254 const slideIndexInGroup = i - params.slidesPerColumn * params.slidesPerGroup * groupIndex;
1255 row = Math.floor(slideIndexInGroup / params.slidesPerGroup);
1256 column = (slideIndexInGroup - row * params.slidesPerGroup) + groupIndex * params.slidesPerGroup;
1257
1258 newSlideOrderIndex = column + ((row * slidesNumberEvenToRows) / slidesPerColumn);
1259 slide
1260 .css({
1261 '-webkit-box-ordinal-group': newSlideOrderIndex,
1262 '-moz-box-ordinal-group': newSlideOrderIndex,
1263 '-ms-flex-order': newSlideOrderIndex,
1264 '-webkit-order': newSlideOrderIndex,
1265 order: newSlideOrderIndex,
1266 });
1267 } else if (params.slidesPerColumnFill === 'column') {
1268 column = Math.floor(i / slidesPerColumn);
1269 row = i - (column * slidesPerColumn);
1270 if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn - 1)) {
1271 row += 1;
1272 if (row >= slidesPerColumn) {
1273 row = 0;
1274 column += 1;
1275 }
1276 }
1277 } else {
1278 row = Math.floor(i / slidesPerRow);
1279 column = i - (row * slidesPerRow);
1280 }
1281 slide.css(
1282 `margin-${swiper.isHorizontal() ? 'top' : 'left'}`,
1283 (row !== 0 && params.spaceBetween) && (`${params.spaceBetween}px`)
1284 );
1285 }
1286 if (slide.css('display') === 'none') continue; // eslint-disable-line
1287
1288 if (params.slidesPerView === 'auto') {
1289 const slideStyles = win.getComputedStyle(slide[0], null);
1290 const currentTransform = slide[0].style.transform;
1291 const currentWebKitTransform = slide[0].style.webkitTransform;
1292 if (currentTransform) {
1293 slide[0].style.transform = 'none';
1294 }
1295 if (currentWebKitTransform) {
1296 slide[0].style.webkitTransform = 'none';
1297 }
1298 if (params.roundLengths) {
1299 slideSize = swiper.isHorizontal()
1300 ? slide.outerWidth(true)
1301 : slide.outerHeight(true);
1302 } else {
1303 // eslint-disable-next-line
1304 if (swiper.isHorizontal()) {
1305 const width = parseFloat(slideStyles.getPropertyValue('width'));
1306 const paddingLeft = parseFloat(slideStyles.getPropertyValue('padding-left'));
1307 const paddingRight = parseFloat(slideStyles.getPropertyValue('padding-right'));
1308 const marginLeft = parseFloat(slideStyles.getPropertyValue('margin-left'));
1309 const marginRight = parseFloat(slideStyles.getPropertyValue('margin-right'));
1310 const boxSizing = slideStyles.getPropertyValue('box-sizing');
1311 if (boxSizing && boxSizing === 'border-box') {
1312 slideSize = width + marginLeft + marginRight;
1313 } else {
1314 slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight;
1315 }
1316 } else {
1317 const height = parseFloat(slideStyles.getPropertyValue('height'));
1318 const paddingTop = parseFloat(slideStyles.getPropertyValue('padding-top'));
1319 const paddingBottom = parseFloat(slideStyles.getPropertyValue('padding-bottom'));
1320 const marginTop = parseFloat(slideStyles.getPropertyValue('margin-top'));
1321 const marginBottom = parseFloat(slideStyles.getPropertyValue('margin-bottom'));
1322 const boxSizing = slideStyles.getPropertyValue('box-sizing');
1323 if (boxSizing && boxSizing === 'border-box') {
1324 slideSize = height + marginTop + marginBottom;
1325 } else {
1326 slideSize = height + paddingTop + paddingBottom + marginTop + marginBottom;
1327 }
1328 }
1329 }
1330 if (currentTransform) {
1331 slide[0].style.transform = currentTransform;
1332 }
1333 if (currentWebKitTransform) {
1334 slide[0].style.webkitTransform = currentWebKitTransform;
1335 }
1336 if (params.roundLengths) slideSize = Math.floor(slideSize);
1337 } else {
1338 slideSize = (swiperSize - ((params.slidesPerView - 1) * spaceBetween)) / params.slidesPerView;
1339 if (params.roundLengths) slideSize = Math.floor(slideSize);
1340
1341 if (slides[i]) {
1342 if (swiper.isHorizontal()) {
1343 slides[i].style.width = `${slideSize}px`;
1344 } else {
1345 slides[i].style.height = `${slideSize}px`;
1346 }
1347 }
1348 }
1349 if (slides[i]) {
1350 slides[i].swiperSlideSize = slideSize;
1351 }
1352 slidesSizesGrid.push(slideSize);
1353
1354
1355 if (params.centeredSlides) {
1356 slidePosition = slidePosition + (slideSize / 2) + (prevSlideSize / 2) + spaceBetween;
1357 if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - (swiperSize / 2) - spaceBetween;
1358 if (i === 0) slidePosition = slidePosition - (swiperSize / 2) - spaceBetween;
1359 if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
1360 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1361 if ((index) % params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1362 slidesGrid.push(slidePosition);
1363 } else {
1364 if (params.roundLengths) slidePosition = Math.floor(slidePosition);
1365 if ((index) % params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1366 slidesGrid.push(slidePosition);
1367 slidePosition = slidePosition + slideSize + spaceBetween;
1368 }
1369
1370 swiper.virtualSize += slideSize + spaceBetween;
1371
1372 prevSlideSize = slideSize;
1373
1374 index += 1;
1375 }
1376 swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
1377 let newSlidesGrid;
1378
1379 if (
1380 rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
1381 $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` });
1382 }
1383 if (params.setWrapperSize) {
1384 if (swiper.isHorizontal()) $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` });
1385 else $wrapperEl.css({ height: `${swiper.virtualSize + params.spaceBetween}px` });
1386 }
1387
1388 if (params.slidesPerColumn > 1) {
1389 swiper.virtualSize = (slideSize + params.spaceBetween) * slidesNumberEvenToRows;
1390 swiper.virtualSize = Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween;
1391 if (swiper.isHorizontal()) $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` });
1392 else $wrapperEl.css({ height: `${swiper.virtualSize + params.spaceBetween}px` });
1393 if (params.centeredSlides) {
1394 newSlidesGrid = [];
1395 for (let i = 0; i < snapGrid.length; i += 1) {
1396 let slidesGridItem = snapGrid[i];
1397 if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
1398 if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
1399 }
1400 snapGrid = newSlidesGrid;
1401 }
1402 }
1403
1404 // Remove last grid elements depending on width
1405 if (!params.centeredSlides) {
1406 newSlidesGrid = [];
1407 for (let i = 0; i < snapGrid.length; i += 1) {
1408 let slidesGridItem = snapGrid[i];
1409 if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
1410 if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
1411 newSlidesGrid.push(slidesGridItem);
1412 }
1413 }
1414 snapGrid = newSlidesGrid;
1415 if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
1416 snapGrid.push(swiper.virtualSize - swiperSize);
1417 }
1418 }
1419 if (snapGrid.length === 0) snapGrid = [0];
1420
1421 if (params.spaceBetween !== 0) {
1422 if (swiper.isHorizontal()) {
1423 if (rtl) slides.filter(slidesForMargin).css({ marginLeft: `${spaceBetween}px` });
1424 else slides.filter(slidesForMargin).css({ marginRight: `${spaceBetween}px` });
1425 } else slides.filter(slidesForMargin).css({ marginBottom: `${spaceBetween}px` });
1426 }
1427
1428 if (params.centerInsufficientSlides) {
1429 let allSlidesSize = 0;
1430 slidesSizesGrid.forEach((slideSizeValue) => {
1431 allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
1432 });
1433 allSlidesSize -= params.spaceBetween;
1434 if (allSlidesSize < swiperSize) {
1435 const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
1436 snapGrid.forEach((snap, snapIndex) => {
1437 snapGrid[snapIndex] = snap - allSlidesOffset;
1438 });
1439 slidesGrid.forEach((snap, snapIndex) => {
1440 slidesGrid[snapIndex] = snap + allSlidesOffset;
1441 });
1442 }
1443 }
1444
1445 Utils.extend(swiper, {
1446 slides,
1447 snapGrid,
1448 slidesGrid,
1449 slidesSizesGrid,
1450 });
1451
1452 if (slidesLength !== previousSlidesLength) {
1453 swiper.emit('slidesLengthChange');
1454 }
1455 if (snapGrid.length !== previousSnapGridLength) {
1456 if (swiper.params.watchOverflow) swiper.checkOverflow();
1457 swiper.emit('snapGridLengthChange');
1458 }
1459 if (slidesGrid.length !== previousSlidesGridLength) {
1460 swiper.emit('slidesGridLengthChange');
1461 }
1462
1463 if (params.watchSlidesProgress || params.watchSlidesVisibility) {
1464 swiper.updateSlidesOffset();
1465 }
1466}
1467
1468function updateAutoHeight (speed) {
1469 const swiper = this;
1470 const activeSlides = [];
1471 let newHeight = 0;
1472 let i;
1473 if (typeof speed === 'number') {
1474 swiper.setTransition(speed);
1475 } else if (speed === true) {
1476 swiper.setTransition(swiper.params.speed);
1477 }
1478 // Find slides currently in view
1479 if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
1480 for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
1481 const index = swiper.activeIndex + i;
1482 if (index > swiper.slides.length) break;
1483 activeSlides.push(swiper.slides.eq(index)[0]);
1484 }
1485 } else {
1486 activeSlides.push(swiper.slides.eq(swiper.activeIndex)[0]);
1487 }
1488
1489 // Find new height from highest slide in view
1490 for (i = 0; i < activeSlides.length; i += 1) {
1491 if (typeof activeSlides[i] !== 'undefined') {
1492 const height = activeSlides[i].offsetHeight;
1493 newHeight = height > newHeight ? height : newHeight;
1494 }
1495 }
1496
1497 // Update Height
1498 if (newHeight) swiper.$wrapperEl.css('height', `${newHeight}px`);
1499}
1500
1501function updateSlidesOffset () {
1502 const swiper = this;
1503 const slides = swiper.slides;
1504 for (let i = 0; i < slides.length; i += 1) {
1505 slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;
1506 }
1507}
1508
1509function updateSlidesProgress (translate = (this && this.translate) || 0) {
1510 const swiper = this;
1511 const params = swiper.params;
1512
1513 const { slides, rtlTranslate: rtl } = swiper;
1514
1515 if (slides.length === 0) return;
1516 if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
1517
1518 let offsetCenter = -translate;
1519 if (rtl) offsetCenter = translate;
1520
1521 // Visible Slides
1522 slides.removeClass(params.slideVisibleClass);
1523
1524 swiper.visibleSlidesIndexes = [];
1525 swiper.visibleSlides = [];
1526
1527 for (let i = 0; i < slides.length; i += 1) {
1528 const slide = slides[i];
1529 const slideProgress = (
1530 (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0)) - slide.swiperSlideOffset
1531 ) / (slide.swiperSlideSize + params.spaceBetween);
1532 if (params.watchSlidesVisibility) {
1533 const slideBefore = -(offsetCenter - slide.swiperSlideOffset);
1534 const slideAfter = slideBefore + swiper.slidesSizesGrid[i];
1535 const isVisible = (slideBefore >= 0 && slideBefore < swiper.size - 1)
1536 || (slideAfter > 1 && slideAfter <= swiper.size)
1537 || (slideBefore <= 0 && slideAfter >= swiper.size);
1538 if (isVisible) {
1539 swiper.visibleSlides.push(slide);
1540 swiper.visibleSlidesIndexes.push(i);
1541 slides.eq(i).addClass(params.slideVisibleClass);
1542 }
1543 }
1544 slide.progress = rtl ? -slideProgress : slideProgress;
1545 }
1546 swiper.visibleSlides = $(swiper.visibleSlides);
1547}
1548
1549function updateProgress (translate) {
1550 const swiper = this;
1551 if (typeof translate === 'undefined') {
1552 const multiplier = swiper.rtlTranslate ? -1 : 1;
1553 // eslint-disable-next-line
1554 translate = (swiper && swiper.translate && (swiper.translate * multiplier)) || 0;
1555 }
1556 const params = swiper.params;
1557 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
1558 let { progress, isBeginning, isEnd } = swiper;
1559 const wasBeginning = isBeginning;
1560 const wasEnd = isEnd;
1561 if (translatesDiff === 0) {
1562 progress = 0;
1563 isBeginning = true;
1564 isEnd = true;
1565 } else {
1566 progress = (translate - swiper.minTranslate()) / (translatesDiff);
1567 isBeginning = progress <= 0;
1568 isEnd = progress >= 1;
1569 }
1570 Utils.extend(swiper, {
1571 progress,
1572 isBeginning,
1573 isEnd,
1574 });
1575
1576 if (params.watchSlidesProgress || params.watchSlidesVisibility) swiper.updateSlidesProgress(translate);
1577
1578 if (isBeginning && !wasBeginning) {
1579 swiper.emit('reachBeginning toEdge');
1580 }
1581 if (isEnd && !wasEnd) {
1582 swiper.emit('reachEnd toEdge');
1583 }
1584 if ((wasBeginning && !isBeginning) || (wasEnd && !isEnd)) {
1585 swiper.emit('fromEdge');
1586 }
1587
1588 swiper.emit('progress', progress);
1589}
1590
1591function updateSlidesClasses () {
1592 const swiper = this;
1593
1594 const {
1595 slides, params, $wrapperEl, activeIndex, realIndex,
1596 } = swiper;
1597 const isVirtual = swiper.virtual && params.virtual.enabled;
1598
1599 slides.removeClass(`${params.slideActiveClass} ${params.slideNextClass} ${params.slidePrevClass} ${params.slideDuplicateActiveClass} ${params.slideDuplicateNextClass} ${params.slideDuplicatePrevClass}`);
1600
1601 let activeSlide;
1602 if (isVirtual) {
1603 activeSlide = swiper.$wrapperEl.find(`.${params.slideClass}[data-swiper-slide-index="${activeIndex}"]`);
1604 } else {
1605 activeSlide = slides.eq(activeIndex);
1606 }
1607
1608 // Active classes
1609 activeSlide.addClass(params.slideActiveClass);
1610
1611 if (params.loop) {
1612 // Duplicate to all looped slides
1613 if (activeSlide.hasClass(params.slideDuplicateClass)) {
1614 $wrapperEl
1615 .children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${realIndex}"]`)
1616 .addClass(params.slideDuplicateActiveClass);
1617 } else {
1618 $wrapperEl
1619 .children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${realIndex}"]`)
1620 .addClass(params.slideDuplicateActiveClass);
1621 }
1622 }
1623 // Next Slide
1624 let nextSlide = activeSlide.nextAll(`.${params.slideClass}`).eq(0).addClass(params.slideNextClass);
1625 if (params.loop && nextSlide.length === 0) {
1626 nextSlide = slides.eq(0);
1627 nextSlide.addClass(params.slideNextClass);
1628 }
1629 // Prev Slide
1630 let prevSlide = activeSlide.prevAll(`.${params.slideClass}`).eq(0).addClass(params.slidePrevClass);
1631 if (params.loop && prevSlide.length === 0) {
1632 prevSlide = slides.eq(-1);
1633 prevSlide.addClass(params.slidePrevClass);
1634 }
1635 if (params.loop) {
1636 // Duplicate to all looped slides
1637 if (nextSlide.hasClass(params.slideDuplicateClass)) {
1638 $wrapperEl
1639 .children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${nextSlide.attr('data-swiper-slide-index')}"]`)
1640 .addClass(params.slideDuplicateNextClass);
1641 } else {
1642 $wrapperEl
1643 .children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${nextSlide.attr('data-swiper-slide-index')}"]`)
1644 .addClass(params.slideDuplicateNextClass);
1645 }
1646 if (prevSlide.hasClass(params.slideDuplicateClass)) {
1647 $wrapperEl
1648 .children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index="${prevSlide.attr('data-swiper-slide-index')}"]`)
1649 .addClass(params.slideDuplicatePrevClass);
1650 } else {
1651 $wrapperEl
1652 .children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index="${prevSlide.attr('data-swiper-slide-index')}"]`)
1653 .addClass(params.slideDuplicatePrevClass);
1654 }
1655 }
1656}
1657
1658function updateActiveIndex (newActiveIndex) {
1659 const swiper = this;
1660 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
1661 const {
1662 slidesGrid, snapGrid, params, activeIndex: previousIndex, realIndex: previousRealIndex, snapIndex: previousSnapIndex,
1663 } = swiper;
1664 let activeIndex = newActiveIndex;
1665 let snapIndex;
1666 if (typeof activeIndex === 'undefined') {
1667 for (let i = 0; i < slidesGrid.length; i += 1) {
1668 if (typeof slidesGrid[i + 1] !== 'undefined') {
1669 if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - ((slidesGrid[i + 1] - slidesGrid[i]) / 2)) {
1670 activeIndex = i;
1671 } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {
1672 activeIndex = i + 1;
1673 }
1674 } else if (translate >= slidesGrid[i]) {
1675 activeIndex = i;
1676 }
1677 }
1678 // Normalize slideIndex
1679 if (params.normalizeSlideIndex) {
1680 if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;
1681 }
1682 }
1683 if (snapGrid.indexOf(translate) >= 0) {
1684 snapIndex = snapGrid.indexOf(translate);
1685 } else {
1686 snapIndex = Math.floor(activeIndex / params.slidesPerGroup);
1687 }
1688 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
1689 if (activeIndex === previousIndex) {
1690 if (snapIndex !== previousSnapIndex) {
1691 swiper.snapIndex = snapIndex;
1692 swiper.emit('snapIndexChange');
1693 }
1694 return;
1695 }
1696
1697 // Get real index
1698 const realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);
1699
1700 Utils.extend(swiper, {
1701 snapIndex,
1702 realIndex,
1703 previousIndex,
1704 activeIndex,
1705 });
1706 swiper.emit('activeIndexChange');
1707 swiper.emit('snapIndexChange');
1708 if (previousRealIndex !== realIndex) {
1709 swiper.emit('realIndexChange');
1710 }
1711 if (swiper.initialized || swiper.runCallbacksOnInit) {
1712 swiper.emit('slideChange');
1713 }
1714}
1715
1716function updateClickedSlide (e) {
1717 const swiper = this;
1718 const params = swiper.params;
1719 const slide = $(e.target).closest(`.${params.slideClass}`)[0];
1720 let slideFound = false;
1721 if (slide) {
1722 for (let i = 0; i < swiper.slides.length; i += 1) {
1723 if (swiper.slides[i] === slide) slideFound = true;
1724 }
1725 }
1726
1727 if (slide && slideFound) {
1728 swiper.clickedSlide = slide;
1729 if (swiper.virtual && swiper.params.virtual.enabled) {
1730 swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);
1731 } else {
1732 swiper.clickedIndex = $(slide).index();
1733 }
1734 } else {
1735 swiper.clickedSlide = undefined;
1736 swiper.clickedIndex = undefined;
1737 return;
1738 }
1739 if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {
1740 swiper.slideToClickedSlide();
1741 }
1742}
1743
1744var update = {
1745 updateSize,
1746 updateSlides,
1747 updateAutoHeight,
1748 updateSlidesOffset,
1749 updateSlidesProgress,
1750 updateProgress,
1751 updateSlidesClasses,
1752 updateActiveIndex,
1753 updateClickedSlide,
1754};
1755
1756function getTranslate (axis = this.isHorizontal() ? 'x' : 'y') {
1757 const swiper = this;
1758
1759 const {
1760 params, rtlTranslate: rtl, translate, $wrapperEl,
1761 } = swiper;
1762
1763 if (params.virtualTranslate) {
1764 return rtl ? -translate : translate;
1765 }
1766 if (params.cssMode) {
1767 return translate;
1768 }
1769
1770 let currentTranslate = Utils.getTranslate($wrapperEl[0], axis);
1771 if (rtl) currentTranslate = -currentTranslate;
1772
1773 return currentTranslate || 0;
1774}
1775
1776function setTranslate (translate, byController) {
1777 const swiper = this;
1778 const {
1779 rtlTranslate: rtl, params, $wrapperEl, wrapperEl, progress,
1780 } = swiper;
1781 let x = 0;
1782 let y = 0;
1783 const z = 0;
1784
1785 if (swiper.isHorizontal()) {
1786 x = rtl ? -translate : translate;
1787 } else {
1788 y = translate;
1789 }
1790
1791 if (params.roundLengths) {
1792 x = Math.floor(x);
1793 y = Math.floor(y);
1794 }
1795
1796 if (params.cssMode) {
1797 wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
1798 } else if (!params.virtualTranslate) {
1799 $wrapperEl.transform(`translate3d(${x}px, ${y}px, ${z}px)`);
1800 }
1801 swiper.previousTranslate = swiper.translate;
1802 swiper.translate = swiper.isHorizontal() ? x : y;
1803
1804 // Check if we need to update progress
1805 let newProgress;
1806 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
1807 if (translatesDiff === 0) {
1808 newProgress = 0;
1809 } else {
1810 newProgress = (translate - swiper.minTranslate()) / (translatesDiff);
1811 }
1812 if (newProgress !== progress) {
1813 swiper.updateProgress(translate);
1814 }
1815
1816 swiper.emit('setTranslate', swiper.translate, byController);
1817}
1818
1819function minTranslate () {
1820 return (-this.snapGrid[0]);
1821}
1822
1823function maxTranslate () {
1824 return (-this.snapGrid[this.snapGrid.length - 1]);
1825}
1826
1827var translate = {
1828 getTranslate,
1829 setTranslate,
1830 minTranslate,
1831 maxTranslate,
1832};
1833
1834function setTransition (duration, byController) {
1835 const swiper = this;
1836
1837 if (!swiper.params.cssMode) {
1838 swiper.$wrapperEl.transition(duration);
1839 }
1840
1841 swiper.emit('setTransition', duration, byController);
1842}
1843
1844function transitionStart (runCallbacks = true, direction) {
1845 const swiper = this;
1846 const { activeIndex, params, previousIndex } = swiper;
1847 if (params.cssMode) return;
1848 if (params.autoHeight) {
1849 swiper.updateAutoHeight();
1850 }
1851
1852 let dir = direction;
1853 if (!dir) {
1854 if (activeIndex > previousIndex) dir = 'next';
1855 else if (activeIndex < previousIndex) dir = 'prev';
1856 else dir = 'reset';
1857 }
1858
1859 swiper.emit('transitionStart');
1860
1861 if (runCallbacks && activeIndex !== previousIndex) {
1862 if (dir === 'reset') {
1863 swiper.emit('slideResetTransitionStart');
1864 return;
1865 }
1866 swiper.emit('slideChangeTransitionStart');
1867 if (dir === 'next') {
1868 swiper.emit('slideNextTransitionStart');
1869 } else {
1870 swiper.emit('slidePrevTransitionStart');
1871 }
1872 }
1873}
1874
1875function transitionEnd$1 (runCallbacks = true, direction) {
1876 const swiper = this;
1877 const { activeIndex, previousIndex, params } = swiper;
1878 swiper.animating = false;
1879 if (params.cssMode) return;
1880 swiper.setTransition(0);
1881
1882 let dir = direction;
1883 if (!dir) {
1884 if (activeIndex > previousIndex) dir = 'next';
1885 else if (activeIndex < previousIndex) dir = 'prev';
1886 else dir = 'reset';
1887 }
1888
1889 swiper.emit('transitionEnd');
1890
1891 if (runCallbacks && activeIndex !== previousIndex) {
1892 if (dir === 'reset') {
1893 swiper.emit('slideResetTransitionEnd');
1894 return;
1895 }
1896 swiper.emit('slideChangeTransitionEnd');
1897 if (dir === 'next') {
1898 swiper.emit('slideNextTransitionEnd');
1899 } else {
1900 swiper.emit('slidePrevTransitionEnd');
1901 }
1902 }
1903}
1904
1905var transition$1 = {
1906 setTransition,
1907 transitionStart,
1908 transitionEnd: transitionEnd$1,
1909};
1910
1911function slideTo (index = 0, speed = this.params.speed, runCallbacks = true, internal) {
1912 const swiper = this;
1913 let slideIndex = index;
1914 if (slideIndex < 0) slideIndex = 0;
1915
1916 const {
1917 params, snapGrid, slidesGrid, previousIndex, activeIndex, rtlTranslate: rtl, wrapperEl,
1918 } = swiper;
1919 if (swiper.animating && params.preventInteractionOnTransition) {
1920 return false;
1921 }
1922
1923 let snapIndex = Math.floor(slideIndex / params.slidesPerGroup);
1924 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
1925
1926 if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {
1927 swiper.emit('beforeSlideChangeStart');
1928 }
1929
1930 const translate = -snapGrid[snapIndex];
1931
1932 // Update progress
1933 swiper.updateProgress(translate);
1934
1935 // Normalize slideIndex
1936 if (params.normalizeSlideIndex) {
1937 for (let i = 0; i < slidesGrid.length; i += 1) {
1938 if (-Math.floor(translate * 100) >= Math.floor(slidesGrid[i] * 100)) {
1939 slideIndex = i;
1940 }
1941 }
1942 }
1943 // Directions locks
1944 if (swiper.initialized && slideIndex !== activeIndex) {
1945 if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {
1946 return false;
1947 }
1948 if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
1949 if ((activeIndex || 0) !== slideIndex) return false;
1950 }
1951 }
1952
1953 let direction;
1954 if (slideIndex > activeIndex) direction = 'next';
1955 else if (slideIndex < activeIndex) direction = 'prev';
1956 else direction = 'reset';
1957
1958
1959 // Update Index
1960 if ((rtl && -translate === swiper.translate) || (!rtl && translate === swiper.translate)) {
1961 swiper.updateActiveIndex(slideIndex);
1962 // Update Height
1963 if (params.autoHeight) {
1964 swiper.updateAutoHeight();
1965 }
1966 swiper.updateSlidesClasses();
1967 if (params.effect !== 'slide') {
1968 swiper.setTranslate(translate);
1969 }
1970 if (direction !== 'reset') {
1971 swiper.transitionStart(runCallbacks, direction);
1972 swiper.transitionEnd(runCallbacks, direction);
1973 }
1974 return false;
1975 }
1976 if (params.cssMode) {
1977 const isH = swiper.isHorizontal();
1978 if (speed === 0) {
1979 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -translate;
1980 } else {
1981 // eslint-disable-next-line
1982 if (wrapperEl.scrollTo) {
1983 wrapperEl.scrollTo({
1984 [isH ? 'left' : 'top']: -translate,
1985 behavior: 'smooth',
1986 });
1987 } else {
1988 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -translate;
1989 }
1990 }
1991 return true;
1992 }
1993
1994 if (speed === 0) {
1995 swiper.setTransition(0);
1996 swiper.setTranslate(translate);
1997 swiper.updateActiveIndex(slideIndex);
1998 swiper.updateSlidesClasses();
1999 swiper.emit('beforeTransitionStart', speed, internal);
2000 swiper.transitionStart(runCallbacks, direction);
2001 swiper.transitionEnd(runCallbacks, direction);
2002 } else {
2003 swiper.setTransition(speed);
2004 swiper.setTranslate(translate);
2005 swiper.updateActiveIndex(slideIndex);
2006 swiper.updateSlidesClasses();
2007 swiper.emit('beforeTransitionStart', speed, internal);
2008 swiper.transitionStart(runCallbacks, direction);
2009 if (!swiper.animating) {
2010 swiper.animating = true;
2011 if (!swiper.onSlideToWrapperTransitionEnd) {
2012 swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {
2013 if (!swiper || swiper.destroyed) return;
2014 if (e.target !== this) return;
2015 swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
2016 swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
2017 swiper.onSlideToWrapperTransitionEnd = null;
2018 delete swiper.onSlideToWrapperTransitionEnd;
2019 swiper.transitionEnd(runCallbacks, direction);
2020 };
2021 }
2022 swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
2023 swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
2024 }
2025 }
2026
2027 return true;
2028}
2029
2030function slideToLoop (index = 0, speed = this.params.speed, runCallbacks = true, internal) {
2031 const swiper = this;
2032 let newIndex = index;
2033 if (swiper.params.loop) {
2034 newIndex += swiper.loopedSlides;
2035 }
2036
2037 return swiper.slideTo(newIndex, speed, runCallbacks, internal);
2038}
2039
2040/* eslint no-unused-vars: "off" */
2041function slideNext (speed = this.params.speed, runCallbacks = true, internal) {
2042 const swiper = this;
2043 const { params, animating } = swiper;
2044 if (params.loop) {
2045 if (animating) return false;
2046 swiper.loopFix();
2047 // eslint-disable-next-line
2048 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
2049 return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
2050 }
2051 return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
2052}
2053
2054/* eslint no-unused-vars: "off" */
2055function slidePrev (speed = this.params.speed, runCallbacks = true, internal) {
2056 const swiper = this;
2057 const {
2058 params, animating, snapGrid, slidesGrid, rtlTranslate,
2059 } = swiper;
2060
2061 if (params.loop) {
2062 if (animating) return false;
2063 swiper.loopFix();
2064 // eslint-disable-next-line
2065 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
2066 }
2067 const translate = rtlTranslate ? swiper.translate : -swiper.translate;
2068 function normalize(val) {
2069 if (val < 0) return -Math.floor(Math.abs(val));
2070 return Math.floor(val);
2071 }
2072 const normalizedTranslate = normalize(translate);
2073 const normalizedSnapGrid = snapGrid.map((val) => normalize(val));
2074 const normalizedSlidesGrid = slidesGrid.map((val) => normalize(val));
2075
2076 const currentSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate)];
2077 let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
2078 if (typeof prevSnap === 'undefined' && params.cssMode) {
2079 snapGrid.forEach((snap) => {
2080 if (!prevSnap && normalizedTranslate >= snap) prevSnap = snap;
2081 });
2082 }
2083 let prevIndex;
2084 if (typeof prevSnap !== 'undefined') {
2085 prevIndex = slidesGrid.indexOf(prevSnap);
2086 if (prevIndex < 0) prevIndex = swiper.activeIndex - 1;
2087 }
2088 return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2089}
2090
2091/* eslint no-unused-vars: "off" */
2092function slideReset (speed = this.params.speed, runCallbacks = true, internal) {
2093 const swiper = this;
2094 return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
2095}
2096
2097/* eslint no-unused-vars: "off" */
2098function slideToClosest (speed = this.params.speed, runCallbacks = true, internal) {
2099 const swiper = this;
2100 let index = swiper.activeIndex;
2101 const snapIndex = Math.floor(index / swiper.params.slidesPerGroup);
2102
2103 if (snapIndex < swiper.snapGrid.length - 1) {
2104 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
2105
2106 const currentSnap = swiper.snapGrid[snapIndex];
2107 const nextSnap = swiper.snapGrid[snapIndex + 1];
2108
2109 if ((translate - currentSnap) > (nextSnap - currentSnap) / 2) {
2110 index = swiper.params.slidesPerGroup;
2111 }
2112 }
2113
2114 return swiper.slideTo(index, speed, runCallbacks, internal);
2115}
2116
2117function slideToClickedSlide () {
2118 const swiper = this;
2119 const { params, $wrapperEl } = swiper;
2120
2121 const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
2122 let slideToIndex = swiper.clickedIndex;
2123 let realIndex;
2124 if (params.loop) {
2125 if (swiper.animating) return;
2126 realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);
2127 if (params.centeredSlides) {
2128 if (
2129 (slideToIndex < swiper.loopedSlides - (slidesPerView / 2))
2130 || (slideToIndex > (swiper.slides.length - swiper.loopedSlides) + (slidesPerView / 2))
2131 ) {
2132 swiper.loopFix();
2133 slideToIndex = $wrapperEl
2134 .children(`.${params.slideClass}[data-swiper-slide-index="${realIndex}"]:not(.${params.slideDuplicateClass})`)
2135 .eq(0)
2136 .index();
2137
2138 Utils.nextTick(() => {
2139 swiper.slideTo(slideToIndex);
2140 });
2141 } else {
2142 swiper.slideTo(slideToIndex);
2143 }
2144 } else if (slideToIndex > swiper.slides.length - slidesPerView) {
2145 swiper.loopFix();
2146 slideToIndex = $wrapperEl
2147 .children(`.${params.slideClass}[data-swiper-slide-index="${realIndex}"]:not(.${params.slideDuplicateClass})`)
2148 .eq(0)
2149 .index();
2150
2151 Utils.nextTick(() => {
2152 swiper.slideTo(slideToIndex);
2153 });
2154 } else {
2155 swiper.slideTo(slideToIndex);
2156 }
2157 } else {
2158 swiper.slideTo(slideToIndex);
2159 }
2160}
2161
2162var slide = {
2163 slideTo,
2164 slideToLoop,
2165 slideNext,
2166 slidePrev,
2167 slideReset,
2168 slideToClosest,
2169 slideToClickedSlide,
2170};
2171
2172function loopCreate () {
2173 const swiper = this;
2174 const { params, $wrapperEl } = swiper;
2175 // Remove duplicated slides
2176 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}`).remove();
2177
2178 let slides = $wrapperEl.children(`.${params.slideClass}`);
2179
2180 if (params.loopFillGroupWithBlank) {
2181 const blankSlidesNum = params.slidesPerGroup - (slides.length % params.slidesPerGroup);
2182 if (blankSlidesNum !== params.slidesPerGroup) {
2183 for (let i = 0; i < blankSlidesNum; i += 1) {
2184 const blankNode = $(doc.createElement('div')).addClass(`${params.slideClass} ${params.slideBlankClass}`);
2185 $wrapperEl.append(blankNode);
2186 }
2187 slides = $wrapperEl.children(`.${params.slideClass}`);
2188 }
2189 }
2190
2191 if (params.slidesPerView === 'auto' && !params.loopedSlides) params.loopedSlides = slides.length;
2192
2193 swiper.loopedSlides = Math.ceil(parseFloat(params.loopedSlides || params.slidesPerView, 10));
2194 swiper.loopedSlides += params.loopAdditionalSlides;
2195 if (swiper.loopedSlides > slides.length) {
2196 swiper.loopedSlides = slides.length;
2197 }
2198
2199 const prependSlides = [];
2200 const appendSlides = [];
2201 slides.each((index, el) => {
2202 const slide = $(el);
2203 if (index < swiper.loopedSlides) appendSlides.push(el);
2204 if (index < slides.length && index >= slides.length - swiper.loopedSlides) prependSlides.push(el);
2205 slide.attr('data-swiper-slide-index', index);
2206 });
2207 for (let i = 0; i < appendSlides.length; i += 1) {
2208 $wrapperEl.append($(appendSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));
2209 }
2210 for (let i = prependSlides.length - 1; i >= 0; i -= 1) {
2211 $wrapperEl.prepend($(prependSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));
2212 }
2213}
2214
2215function loopFix () {
2216 const swiper = this;
2217 const {
2218 params, activeIndex, slides, loopedSlides, allowSlidePrev, allowSlideNext, snapGrid, rtlTranslate: rtl,
2219 } = swiper;
2220 let newIndex;
2221 swiper.allowSlidePrev = true;
2222 swiper.allowSlideNext = true;
2223
2224 const snapTranslate = -snapGrid[activeIndex];
2225 const diff = snapTranslate - swiper.getTranslate();
2226
2227
2228 // Fix For Negative Oversliding
2229 if (activeIndex < loopedSlides) {
2230 newIndex = (slides.length - (loopedSlides * 3)) + activeIndex;
2231 newIndex += loopedSlides;
2232 const slideChanged = swiper.slideTo(newIndex, 0, false, true);
2233 if (slideChanged && diff !== 0) {
2234 swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
2235 }
2236 } else if ((params.slidesPerView === 'auto' && activeIndex >= loopedSlides * 2) || (activeIndex >= slides.length - loopedSlides)) {
2237 // Fix For Positive Oversliding
2238 newIndex = -slides.length + activeIndex + loopedSlides;
2239 newIndex += loopedSlides;
2240 const slideChanged = swiper.slideTo(newIndex, 0, false, true);
2241 if (slideChanged && diff !== 0) {
2242 swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
2243 }
2244 }
2245 swiper.allowSlidePrev = allowSlidePrev;
2246 swiper.allowSlideNext = allowSlideNext;
2247}
2248
2249function loopDestroy () {
2250 const swiper = this;
2251 const { $wrapperEl, params, slides } = swiper;
2252 $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass},.${params.slideClass}.${params.slideBlankClass}`).remove();
2253 slides.removeAttr('data-swiper-slide-index');
2254}
2255
2256var loop = {
2257 loopCreate,
2258 loopFix,
2259 loopDestroy,
2260};
2261
2262function setGrabCursor (moving) {
2263 const swiper = this;
2264 if (Support.touch || !swiper.params.simulateTouch || (swiper.params.watchOverflow && swiper.isLocked) || swiper.params.cssMode) return;
2265 const el = swiper.el;
2266 el.style.cursor = 'move';
2267 el.style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';
2268 el.style.cursor = moving ? '-moz-grabbin' : '-moz-grab';
2269 el.style.cursor = moving ? 'grabbing' : 'grab';
2270}
2271
2272function unsetGrabCursor () {
2273 const swiper = this;
2274 if (Support.touch || (swiper.params.watchOverflow && swiper.isLocked) || swiper.params.cssMode) return;
2275 swiper.el.style.cursor = '';
2276}
2277
2278var grabCursor = {
2279 setGrabCursor,
2280 unsetGrabCursor,
2281};
2282
2283function appendSlide (slides) {
2284 const swiper = this;
2285 const { $wrapperEl, params } = swiper;
2286 if (params.loop) {
2287 swiper.loopDestroy();
2288 }
2289 if (typeof slides === 'object' && 'length' in slides) {
2290 for (let i = 0; i < slides.length; i += 1) {
2291 if (slides[i]) $wrapperEl.append(slides[i]);
2292 }
2293 } else {
2294 $wrapperEl.append(slides);
2295 }
2296 if (params.loop) {
2297 swiper.loopCreate();
2298 }
2299 if (!(params.observer && Support.observer)) {
2300 swiper.update();
2301 }
2302}
2303
2304function prependSlide (slides) {
2305 const swiper = this;
2306 const { params, $wrapperEl, activeIndex } = swiper;
2307
2308 if (params.loop) {
2309 swiper.loopDestroy();
2310 }
2311 let newActiveIndex = activeIndex + 1;
2312 if (typeof slides === 'object' && 'length' in slides) {
2313 for (let i = 0; i < slides.length; i += 1) {
2314 if (slides[i]) $wrapperEl.prepend(slides[i]);
2315 }
2316 newActiveIndex = activeIndex + slides.length;
2317 } else {
2318 $wrapperEl.prepend(slides);
2319 }
2320 if (params.loop) {
2321 swiper.loopCreate();
2322 }
2323 if (!(params.observer && Support.observer)) {
2324 swiper.update();
2325 }
2326 swiper.slideTo(newActiveIndex, 0, false);
2327}
2328
2329function addSlide (index, slides) {
2330 const swiper = this;
2331 const { $wrapperEl, params, activeIndex } = swiper;
2332 let activeIndexBuffer = activeIndex;
2333 if (params.loop) {
2334 activeIndexBuffer -= swiper.loopedSlides;
2335 swiper.loopDestroy();
2336 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
2337 }
2338 const baseLength = swiper.slides.length;
2339 if (index <= 0) {
2340 swiper.prependSlide(slides);
2341 return;
2342 }
2343 if (index >= baseLength) {
2344 swiper.appendSlide(slides);
2345 return;
2346 }
2347 let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
2348
2349 const slidesBuffer = [];
2350 for (let i = baseLength - 1; i >= index; i -= 1) {
2351 const currentSlide = swiper.slides.eq(i);
2352 currentSlide.remove();
2353 slidesBuffer.unshift(currentSlide);
2354 }
2355
2356 if (typeof slides === 'object' && 'length' in slides) {
2357 for (let i = 0; i < slides.length; i += 1) {
2358 if (slides[i]) $wrapperEl.append(slides[i]);
2359 }
2360 newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
2361 } else {
2362 $wrapperEl.append(slides);
2363 }
2364
2365 for (let i = 0; i < slidesBuffer.length; i += 1) {
2366 $wrapperEl.append(slidesBuffer[i]);
2367 }
2368
2369 if (params.loop) {
2370 swiper.loopCreate();
2371 }
2372 if (!(params.observer && Support.observer)) {
2373 swiper.update();
2374 }
2375 if (params.loop) {
2376 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
2377 } else {
2378 swiper.slideTo(newActiveIndex, 0, false);
2379 }
2380}
2381
2382function removeSlide (slidesIndexes) {
2383 const swiper = this;
2384 const { params, $wrapperEl, activeIndex } = swiper;
2385
2386 let activeIndexBuffer = activeIndex;
2387 if (params.loop) {
2388 activeIndexBuffer -= swiper.loopedSlides;
2389 swiper.loopDestroy();
2390 swiper.slides = $wrapperEl.children(`.${params.slideClass}`);
2391 }
2392 let newActiveIndex = activeIndexBuffer;
2393 let indexToRemove;
2394
2395 if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
2396 for (let i = 0; i < slidesIndexes.length; i += 1) {
2397 indexToRemove = slidesIndexes[i];
2398 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
2399 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
2400 }
2401 newActiveIndex = Math.max(newActiveIndex, 0);
2402 } else {
2403 indexToRemove = slidesIndexes;
2404 if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();
2405 if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
2406 newActiveIndex = Math.max(newActiveIndex, 0);
2407 }
2408
2409 if (params.loop) {
2410 swiper.loopCreate();
2411 }
2412
2413 if (!(params.observer && Support.observer)) {
2414 swiper.update();
2415 }
2416 if (params.loop) {
2417 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
2418 } else {
2419 swiper.slideTo(newActiveIndex, 0, false);
2420 }
2421}
2422
2423function removeAllSlides () {
2424 const swiper = this;
2425
2426 const slidesIndexes = [];
2427 for (let i = 0; i < swiper.slides.length; i += 1) {
2428 slidesIndexes.push(i);
2429 }
2430 swiper.removeSlide(slidesIndexes);
2431}
2432
2433var manipulation = {
2434 appendSlide,
2435 prependSlide,
2436 addSlide,
2437 removeSlide,
2438 removeAllSlides,
2439};
2440
2441const Device = (function Device() {
2442 const platform = win.navigator.platform;
2443 const ua = win.navigator.userAgent;
2444
2445 const device = {
2446 ios: false,
2447 android: false,
2448 androidChrome: false,
2449 desktop: false,
2450 iphone: false,
2451 ipod: false,
2452 ipad: false,
2453 edge: false,
2454 ie: false,
2455 firefox: false,
2456 macos: false,
2457 windows: false,
2458 cordova: !!(win.cordova || win.phonegap),
2459 phonegap: !!(win.cordova || win.phonegap),
2460 electron: false,
2461 };
2462
2463 const screenWidth = win.screen.width;
2464 const screenHeight = win.screen.height;
2465
2466 const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
2467 let ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
2468 const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
2469 const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
2470 const ie = ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
2471 const edge = ua.indexOf('Edge/') >= 0;
2472 const firefox = ua.indexOf('Gecko/') >= 0 && ua.indexOf('Firefox/') >= 0;
2473 const windows = platform === 'Win32';
2474 const electron = ua.toLowerCase().indexOf('electron') >= 0;
2475 let macos = platform === 'MacIntel';
2476
2477 // iPadOs 13 fix
2478 if (!ipad
2479 && macos
2480 && Support.touch
2481 && (
2482 (screenWidth === 1024 && screenHeight === 1366) // Pro 12.9
2483 || (screenWidth === 834 && screenHeight === 1194) // Pro 11
2484 || (screenWidth === 834 && screenHeight === 1112) // Pro 10.5
2485 || (screenWidth === 768 && screenHeight === 1024) // other
2486 )
2487 ) {
2488 ipad = ua.match(/(Version)\/([\d.]+)/);
2489 macos = false;
2490 }
2491
2492 device.ie = ie;
2493 device.edge = edge;
2494 device.firefox = firefox;
2495
2496 // Android
2497 if (android && !windows) {
2498 device.os = 'android';
2499 device.osVersion = android[2];
2500 device.android = true;
2501 device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
2502 }
2503 if (ipad || iphone || ipod) {
2504 device.os = 'ios';
2505 device.ios = true;
2506 }
2507 // iOS
2508 if (iphone && !ipod) {
2509 device.osVersion = iphone[2].replace(/_/g, '.');
2510 device.iphone = true;
2511 }
2512 if (ipad) {
2513 device.osVersion = ipad[2].replace(/_/g, '.');
2514 device.ipad = true;
2515 }
2516 if (ipod) {
2517 device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
2518 device.ipod = true;
2519 }
2520 // iOS 8+ changed UA
2521 if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
2522 if (device.osVersion.split('.')[0] === '10') {
2523 device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
2524 }
2525 }
2526
2527 // Webview
2528 device.webView = !!((iphone || ipad || ipod) && (ua.match(/.*AppleWebKit(?!.*Safari)/i) || win.navigator.standalone))
2529 || (win.matchMedia && win.matchMedia('(display-mode: standalone)').matches);
2530 device.webview = device.webView;
2531 device.standalone = device.webView;
2532
2533 // Desktop
2534 device.desktop = !(device.ios || device.android) || electron;
2535 if (device.desktop) {
2536 device.electron = electron;
2537 device.macos = macos;
2538 device.windows = windows;
2539 if (device.macos) {
2540 device.os = 'macos';
2541 }
2542 if (device.windows) {
2543 device.os = 'windows';
2544 }
2545 }
2546
2547 // Pixel Ratio
2548 device.pixelRatio = win.devicePixelRatio || 1;
2549
2550 // Export object
2551 return device;
2552}());
2553
2554function onTouchStart (event) {
2555 const swiper = this;
2556 const data = swiper.touchEventsData;
2557 const { params, touches } = swiper;
2558
2559 if (swiper.animating && params.preventInteractionOnTransition) {
2560 return;
2561 }
2562 let e = event;
2563 if (e.originalEvent) e = e.originalEvent;
2564 const $targetEl = $(e.target);
2565
2566 if (params.touchEventsTarget === 'wrapper') {
2567 if (!$targetEl.closest(swiper.wrapperEl).length) return;
2568 }
2569 data.isTouchEvent = e.type === 'touchstart';
2570 if (!data.isTouchEvent && 'which' in e && e.which === 3) return;
2571 if (!data.isTouchEvent && 'button' in e && e.button > 0) return;
2572 if (data.isTouched && data.isMoved) return;
2573 if (params.noSwiping && $targetEl.closest(params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`)[0]) {
2574 swiper.allowClick = true;
2575 return;
2576 }
2577 if (params.swipeHandler) {
2578 if (!$targetEl.closest(params.swipeHandler)[0]) return;
2579 }
2580
2581 touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
2582 touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
2583 const startX = touches.currentX;
2584 const startY = touches.currentY;
2585
2586 // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
2587
2588 const edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;
2589 const edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;
2590 if (
2591 edgeSwipeDetection
2592 && ((startX <= edgeSwipeThreshold)
2593 || (startX >= win.screen.width - edgeSwipeThreshold))
2594 ) {
2595 return;
2596 }
2597
2598 Utils.extend(data, {
2599 isTouched: true,
2600 isMoved: false,
2601 allowTouchCallbacks: true,
2602 isScrolling: undefined,
2603 startMoving: undefined,
2604 });
2605
2606 touches.startX = startX;
2607 touches.startY = startY;
2608 data.touchStartTime = Utils.now();
2609 swiper.allowClick = true;
2610 swiper.updateSize();
2611 swiper.swipeDirection = undefined;
2612 if (params.threshold > 0) data.allowThresholdMove = false;
2613 if (e.type !== 'touchstart') {
2614 let preventDefault = true;
2615 if ($targetEl.is(data.formElements)) preventDefault = false;
2616 if (
2617 doc.activeElement
2618 && $(doc.activeElement).is(data.formElements)
2619 && doc.activeElement !== $targetEl[0]
2620 ) {
2621 doc.activeElement.blur();
2622 }
2623
2624 const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
2625 if (params.touchStartForcePreventDefault || shouldPreventDefault) {
2626 e.preventDefault();
2627 }
2628 }
2629 swiper.emit('touchStart', e);
2630}
2631
2632function onTouchMove (event) {
2633 const swiper = this;
2634 const data = swiper.touchEventsData;
2635 const { params, touches, rtlTranslate: rtl } = swiper;
2636 let e = event;
2637 if (e.originalEvent) e = e.originalEvent;
2638 if (!data.isTouched) {
2639 if (data.startMoving && data.isScrolling) {
2640 swiper.emit('touchMoveOpposite', e);
2641 }
2642 return;
2643 }
2644 if (data.isTouchEvent && e.type === 'mousemove') return;
2645 const pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
2646 const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
2647 if (e.preventedByNestedSwiper) {
2648 touches.startX = pageX;
2649 touches.startY = pageY;
2650 return;
2651 }
2652 if (!swiper.allowTouchMove) {
2653 // isMoved = true;
2654 swiper.allowClick = false;
2655 if (data.isTouched) {
2656 Utils.extend(touches, {
2657 startX: pageX,
2658 startY: pageY,
2659 currentX: pageX,
2660 currentY: pageY,
2661 });
2662 data.touchStartTime = Utils.now();
2663 }
2664 return;
2665 }
2666 if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {
2667 if (swiper.isVertical()) {
2668 // Vertical
2669 if (
2670 (pageY < touches.startY && swiper.translate <= swiper.maxTranslate())
2671 || (pageY > touches.startY && swiper.translate >= swiper.minTranslate())
2672 ) {
2673 data.isTouched = false;
2674 data.isMoved = false;
2675 return;
2676 }
2677 } else if (
2678 (pageX < touches.startX && swiper.translate <= swiper.maxTranslate())
2679 || (pageX > touches.startX && swiper.translate >= swiper.minTranslate())
2680 ) {
2681 return;
2682 }
2683 }
2684 if (data.isTouchEvent && doc.activeElement) {
2685 if (e.target === doc.activeElement && $(e.target).is(data.formElements)) {
2686 data.isMoved = true;
2687 swiper.allowClick = false;
2688 return;
2689 }
2690 }
2691 if (data.allowTouchCallbacks) {
2692 swiper.emit('touchMove', e);
2693 }
2694 if (e.targetTouches && e.targetTouches.length > 1) return;
2695
2696 touches.currentX = pageX;
2697 touches.currentY = pageY;
2698
2699 const diffX = touches.currentX - touches.startX;
2700 const diffY = touches.currentY - touches.startY;
2701 if (swiper.params.threshold && Math.sqrt((diffX ** 2) + (diffY ** 2)) < swiper.params.threshold) return;
2702
2703 if (typeof data.isScrolling === 'undefined') {
2704 let touchAngle;
2705 if ((swiper.isHorizontal() && touches.currentY === touches.startY) || (swiper.isVertical() && touches.currentX === touches.startX)) {
2706 data.isScrolling = false;
2707 } else {
2708 // eslint-disable-next-line
2709 if ((diffX * diffX) + (diffY * diffY) >= 25) {
2710 touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI;
2711 data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : (90 - touchAngle > params.touchAngle);
2712 }
2713 }
2714 }
2715 if (data.isScrolling) {
2716 swiper.emit('touchMoveOpposite', e);
2717 }
2718 if (typeof data.startMoving === 'undefined') {
2719 if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
2720 data.startMoving = true;
2721 }
2722 }
2723 if (data.isScrolling) {
2724 data.isTouched = false;
2725 return;
2726 }
2727 if (!data.startMoving) {
2728 return;
2729 }
2730 swiper.allowClick = false;
2731 if (!params.cssMode) {
2732 e.preventDefault();
2733 }
2734 if (params.touchMoveStopPropagation && !params.nested) {
2735 e.stopPropagation();
2736 }
2737
2738 if (!data.isMoved) {
2739 if (params.loop) {
2740 swiper.loopFix();
2741 }
2742 data.startTranslate = swiper.getTranslate();
2743 swiper.setTransition(0);
2744 if (swiper.animating) {
2745 swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');
2746 }
2747 data.allowMomentumBounce = false;
2748 // Grab Cursor
2749 if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
2750 swiper.setGrabCursor(true);
2751 }
2752 swiper.emit('sliderFirstMove', e);
2753 }
2754 swiper.emit('sliderMove', e);
2755 data.isMoved = true;
2756
2757 let diff = swiper.isHorizontal() ? diffX : diffY;
2758 touches.diff = diff;
2759
2760 diff *= params.touchRatio;
2761 if (rtl) diff = -diff;
2762
2763 swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
2764 data.currentTranslate = diff + data.startTranslate;
2765
2766 let disableParentSwiper = true;
2767 let resistanceRatio = params.resistanceRatio;
2768 if (params.touchReleaseOnEdges) {
2769 resistanceRatio = 0;
2770 }
2771 if ((diff > 0 && data.currentTranslate > swiper.minTranslate())) {
2772 disableParentSwiper = false;
2773 if (params.resistance) data.currentTranslate = (swiper.minTranslate() - 1) + ((-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio);
2774 } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {
2775 disableParentSwiper = false;
2776 if (params.resistance) data.currentTranslate = (swiper.maxTranslate() + 1) - ((swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio);
2777 }
2778
2779 if (disableParentSwiper) {
2780 e.preventedByNestedSwiper = true;
2781 }
2782
2783 // Directions locks
2784 if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
2785 data.currentTranslate = data.startTranslate;
2786 }
2787 if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
2788 data.currentTranslate = data.startTranslate;
2789 }
2790
2791
2792 // Threshold
2793 if (params.threshold > 0) {
2794 if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
2795 if (!data.allowThresholdMove) {
2796 data.allowThresholdMove = true;
2797 touches.startX = touches.currentX;
2798 touches.startY = touches.currentY;
2799 data.currentTranslate = data.startTranslate;
2800 touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;
2801 return;
2802 }
2803 } else {
2804 data.currentTranslate = data.startTranslate;
2805 return;
2806 }
2807 }
2808
2809 if (!params.followFinger || params.cssMode) return;
2810
2811 // Update active index in free mode
2812 if (params.freeMode || params.watchSlidesProgress || params.watchSlidesVisibility) {
2813 swiper.updateActiveIndex();
2814 swiper.updateSlidesClasses();
2815 }
2816 if (params.freeMode) {
2817 // Velocity
2818 if (data.velocities.length === 0) {
2819 data.velocities.push({
2820 position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
2821 time: data.touchStartTime,
2822 });
2823 }
2824 data.velocities.push({
2825 position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
2826 time: Utils.now(),
2827 });
2828 }
2829 // Update progress
2830 swiper.updateProgress(data.currentTranslate);
2831 // Update translate
2832 swiper.setTranslate(data.currentTranslate);
2833}
2834
2835function onTouchEnd (event) {
2836 const swiper = this;
2837 const data = swiper.touchEventsData;
2838
2839 const {
2840 params, touches, rtlTranslate: rtl, $wrapperEl, slidesGrid, snapGrid,
2841 } = swiper;
2842 let e = event;
2843 if (e.originalEvent) e = e.originalEvent;
2844 if (data.allowTouchCallbacks) {
2845 swiper.emit('touchEnd', e);
2846 }
2847 data.allowTouchCallbacks = false;
2848 if (!data.isTouched) {
2849 if (data.isMoved && params.grabCursor) {
2850 swiper.setGrabCursor(false);
2851 }
2852 data.isMoved = false;
2853 data.startMoving = false;
2854 return;
2855 }
2856 // Return Grab Cursor
2857 if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
2858 swiper.setGrabCursor(false);
2859 }
2860
2861 // Time diff
2862 const touchEndTime = Utils.now();
2863 const timeDiff = touchEndTime - data.touchStartTime;
2864
2865 // Tap, doubleTap, Click
2866 if (swiper.allowClick) {
2867 swiper.updateClickedSlide(e);
2868 swiper.emit('tap click', e);
2869 if (timeDiff < 300 && (touchEndTime - data.lastClickTime) < 300) {
2870 swiper.emit('doubleTap doubleClick', e);
2871 }
2872 }
2873
2874 data.lastClickTime = Utils.now();
2875 Utils.nextTick(() => {
2876 if (!swiper.destroyed) swiper.allowClick = true;
2877 });
2878
2879 if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
2880 data.isTouched = false;
2881 data.isMoved = false;
2882 data.startMoving = false;
2883 return;
2884 }
2885 data.isTouched = false;
2886 data.isMoved = false;
2887 data.startMoving = false;
2888
2889 let currentPos;
2890 if (params.followFinger) {
2891 currentPos = rtl ? swiper.translate : -swiper.translate;
2892 } else {
2893 currentPos = -data.currentTranslate;
2894 }
2895
2896 if (params.cssMode) {
2897 return;
2898 }
2899
2900 if (params.freeMode) {
2901 if (currentPos < -swiper.minTranslate()) {
2902 swiper.slideTo(swiper.activeIndex);
2903 return;
2904 }
2905 if (currentPos > -swiper.maxTranslate()) {
2906 if (swiper.slides.length < snapGrid.length) {
2907 swiper.slideTo(snapGrid.length - 1);
2908 } else {
2909 swiper.slideTo(swiper.slides.length - 1);
2910 }
2911 return;
2912 }
2913
2914 if (params.freeModeMomentum) {
2915 if (data.velocities.length > 1) {
2916 const lastMoveEvent = data.velocities.pop();
2917 const velocityEvent = data.velocities.pop();
2918
2919 const distance = lastMoveEvent.position - velocityEvent.position;
2920 const time = lastMoveEvent.time - velocityEvent.time;
2921 swiper.velocity = distance / time;
2922 swiper.velocity /= 2;
2923 if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
2924 swiper.velocity = 0;
2925 }
2926 // this implies that the user stopped moving a finger then released.
2927 // There would be no events with distance zero, so the last event is stale.
2928 if (time > 150 || (Utils.now() - lastMoveEvent.time) > 300) {
2929 swiper.velocity = 0;
2930 }
2931 } else {
2932 swiper.velocity = 0;
2933 }
2934 swiper.velocity *= params.freeModeMomentumVelocityRatio;
2935
2936 data.velocities.length = 0;
2937 let momentumDuration = 1000 * params.freeModeMomentumRatio;
2938 const momentumDistance = swiper.velocity * momentumDuration;
2939
2940 let newPosition = swiper.translate + momentumDistance;
2941 if (rtl) newPosition = -newPosition;
2942
2943 let doBounce = false;
2944 let afterBouncePosition;
2945 const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
2946 let needsLoopFix;
2947 if (newPosition < swiper.maxTranslate()) {
2948 if (params.freeModeMomentumBounce) {
2949 if (newPosition + swiper.maxTranslate() < -bounceAmount) {
2950 newPosition = swiper.maxTranslate() - bounceAmount;
2951 }
2952 afterBouncePosition = swiper.maxTranslate();
2953 doBounce = true;
2954 data.allowMomentumBounce = true;
2955 } else {
2956 newPosition = swiper.maxTranslate();
2957 }
2958 if (params.loop && params.centeredSlides) needsLoopFix = true;
2959 } else if (newPosition > swiper.minTranslate()) {
2960 if (params.freeModeMomentumBounce) {
2961 if (newPosition - swiper.minTranslate() > bounceAmount) {
2962 newPosition = swiper.minTranslate() + bounceAmount;
2963 }
2964 afterBouncePosition = swiper.minTranslate();
2965 doBounce = true;
2966 data.allowMomentumBounce = true;
2967 } else {
2968 newPosition = swiper.minTranslate();
2969 }
2970 if (params.loop && params.centeredSlides) needsLoopFix = true;
2971 } else if (params.freeModeSticky) {
2972 let nextSlide;
2973 for (let j = 0; j < snapGrid.length; j += 1) {
2974 if (snapGrid[j] > -newPosition) {
2975 nextSlide = j;
2976 break;
2977 }
2978 }
2979
2980 if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
2981 newPosition = snapGrid[nextSlide];
2982 } else {
2983 newPosition = snapGrid[nextSlide - 1];
2984 }
2985 newPosition = -newPosition;
2986 }
2987 if (needsLoopFix) {
2988 swiper.once('transitionEnd', () => {
2989 swiper.loopFix();
2990 });
2991 }
2992 // Fix duration
2993 if (swiper.velocity !== 0) {
2994 if (rtl) {
2995 momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
2996 } else {
2997 momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
2998 }
2999 } else if (params.freeModeSticky) {
3000 swiper.slideToClosest();
3001 return;
3002 }
3003
3004 if (params.freeModeMomentumBounce && doBounce) {
3005 swiper.updateProgress(afterBouncePosition);
3006 swiper.setTransition(momentumDuration);
3007 swiper.setTranslate(newPosition);
3008 swiper.transitionStart(true, swiper.swipeDirection);
3009 swiper.animating = true;
3010 $wrapperEl.transitionEnd(() => {
3011 if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
3012 swiper.emit('momentumBounce');
3013
3014 swiper.setTransition(params.speed);
3015 swiper.setTranslate(afterBouncePosition);
3016 $wrapperEl.transitionEnd(() => {
3017 if (!swiper || swiper.destroyed) return;
3018 swiper.transitionEnd();
3019 });
3020 });
3021 } else if (swiper.velocity) {
3022 swiper.updateProgress(newPosition);
3023 swiper.setTransition(momentumDuration);
3024 swiper.setTranslate(newPosition);
3025 swiper.transitionStart(true, swiper.swipeDirection);
3026 if (!swiper.animating) {
3027 swiper.animating = true;
3028 $wrapperEl.transitionEnd(() => {
3029 if (!swiper || swiper.destroyed) return;
3030 swiper.transitionEnd();
3031 });
3032 }
3033 } else {
3034 swiper.updateProgress(newPosition);
3035 }
3036
3037 swiper.updateActiveIndex();
3038 swiper.updateSlidesClasses();
3039 } else if (params.freeModeSticky) {
3040 swiper.slideToClosest();
3041 return;
3042 }
3043
3044 if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
3045 swiper.updateProgress();
3046 swiper.updateActiveIndex();
3047 swiper.updateSlidesClasses();
3048 }
3049 return;
3050 }
3051
3052 // Find current slide
3053 let stopIndex = 0;
3054 let groupSize = swiper.slidesSizesGrid[0];
3055 for (let i = 0; i < slidesGrid.length; i += params.slidesPerGroup) {
3056 if (typeof slidesGrid[i + params.slidesPerGroup] !== 'undefined') {
3057 if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + params.slidesPerGroup]) {
3058 stopIndex = i;
3059 groupSize = slidesGrid[i + params.slidesPerGroup] - slidesGrid[i];
3060 }
3061 } else if (currentPos >= slidesGrid[i]) {
3062 stopIndex = i;
3063 groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
3064 }
3065 }
3066
3067 // Find current slide size
3068 const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
3069
3070 if (timeDiff > params.longSwipesMs) {
3071 // Long touches
3072 if (!params.longSwipes) {
3073 swiper.slideTo(swiper.activeIndex);
3074 return;
3075 }
3076 if (swiper.swipeDirection === 'next') {
3077 if (ratio >= params.longSwipesRatio) swiper.slideTo(stopIndex + params.slidesPerGroup);
3078 else swiper.slideTo(stopIndex);
3079 }
3080 if (swiper.swipeDirection === 'prev') {
3081 if (ratio > (1 - params.longSwipesRatio)) swiper.slideTo(stopIndex + params.slidesPerGroup);
3082 else swiper.slideTo(stopIndex);
3083 }
3084 } else {
3085 // Short swipes
3086 if (!params.shortSwipes) {
3087 swiper.slideTo(swiper.activeIndex);
3088 return;
3089 }
3090 const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
3091 if (!isNavButtonTarget) {
3092 if (swiper.swipeDirection === 'next') {
3093 swiper.slideTo(stopIndex + params.slidesPerGroup);
3094 }
3095 if (swiper.swipeDirection === 'prev') {
3096 swiper.slideTo(stopIndex);
3097 }
3098 } else if (e.target === swiper.navigation.nextEl) {
3099 swiper.slideTo(stopIndex + params.slidesPerGroup);
3100 } else {
3101 swiper.slideTo(stopIndex);
3102 }
3103 }
3104}
3105
3106function onResize () {
3107 const swiper = this;
3108
3109 const { params, el } = swiper;
3110
3111 if (el && el.offsetWidth === 0) return;
3112
3113 // Breakpoints
3114 if (params.breakpoints) {
3115 swiper.setBreakpoint();
3116 }
3117
3118 // Save locks
3119 const { allowSlideNext, allowSlidePrev, snapGrid } = swiper;
3120
3121 // Disable locks on resize
3122 swiper.allowSlideNext = true;
3123 swiper.allowSlidePrev = true;
3124
3125 swiper.updateSize();
3126 swiper.updateSlides();
3127
3128 if (params.freeMode) {
3129 const newTranslate = Math.min(Math.max(swiper.translate, swiper.maxTranslate()), swiper.minTranslate());
3130 swiper.setTranslate(newTranslate);
3131 swiper.updateActiveIndex();
3132 swiper.updateSlidesClasses();
3133
3134 if (params.autoHeight) {
3135 swiper.updateAutoHeight();
3136 }
3137 } else {
3138 swiper.updateSlidesClasses();
3139 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
3140 swiper.slideTo(swiper.slides.length - 1, 0, false, true);
3141 } else {
3142 swiper.slideTo(swiper.activeIndex, 0, false, true);
3143 }
3144 }
3145 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
3146 swiper.autoplay.run();
3147 }
3148 // Return locks after resize
3149 swiper.allowSlidePrev = allowSlidePrev;
3150 swiper.allowSlideNext = allowSlideNext;
3151
3152 if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
3153 swiper.checkOverflow();
3154 }
3155}
3156
3157function onClick (e) {
3158 const swiper = this;
3159 if (!swiper.allowClick) {
3160 if (swiper.params.preventClicks) e.preventDefault();
3161 if (swiper.params.preventClicksPropagation && swiper.animating) {
3162 e.stopPropagation();
3163 e.stopImmediatePropagation();
3164 }
3165 }
3166}
3167
3168function onScroll () {
3169 const swiper = this;
3170 const { wrapperEl } = swiper;
3171 swiper.previousTranslate = swiper.translate;
3172 swiper.translate = swiper.isHorizontal() ? -wrapperEl.scrollLeft : -wrapperEl.scrollTop;
3173 // eslint-disable-next-line
3174 if (swiper.translate === -0) swiper.translate = 0;
3175
3176 swiper.updateActiveIndex();
3177 swiper.updateSlidesClasses();
3178
3179 let newProgress;
3180 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
3181 if (translatesDiff === 0) {
3182 newProgress = 0;
3183 } else {
3184 newProgress = (swiper.translate - swiper.minTranslate()) / (translatesDiff);
3185 }
3186 if (newProgress !== swiper.progress) {
3187 swiper.updateProgress(swiper.translate);
3188 }
3189
3190 swiper.emit('setTranslate', swiper.translate, false);
3191}
3192
3193function attachEvents() {
3194 const swiper = this;
3195 const {
3196 params, touchEvents, el, wrapperEl,
3197 } = swiper;
3198
3199 swiper.onTouchStart = onTouchStart.bind(swiper);
3200 swiper.onTouchMove = onTouchMove.bind(swiper);
3201 swiper.onTouchEnd = onTouchEnd.bind(swiper);
3202 if (params.cssMode) {
3203 swiper.onScroll = onScroll.bind(swiper);
3204 }
3205
3206 swiper.onClick = onClick.bind(swiper);
3207
3208 const capture = !!params.nested;
3209
3210 // Touch Events
3211 if (!Support.touch && Support.pointerEvents) {
3212 el.addEventListener(touchEvents.start, swiper.onTouchStart, false);
3213 doc.addEventListener(touchEvents.move, swiper.onTouchMove, capture);
3214 doc.addEventListener(touchEvents.end, swiper.onTouchEnd, false);
3215 } else {
3216 if (Support.touch) {
3217 const passiveListener = touchEvents.start === 'touchstart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
3218 el.addEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
3219 el.addEventListener(touchEvents.move, swiper.onTouchMove, Support.passiveListener ? { passive: false, capture } : capture);
3220 el.addEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
3221 if (touchEvents.cancel) {
3222 el.addEventListener(touchEvents.cancel, swiper.onTouchEnd, passiveListener);
3223 }
3224 }
3225 if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
3226 el.addEventListener('mousedown', swiper.onTouchStart, false);
3227 doc.addEventListener('mousemove', swiper.onTouchMove, capture);
3228 doc.addEventListener('mouseup', swiper.onTouchEnd, false);
3229 }
3230 }
3231 // Prevent Links Clicks
3232 if (params.preventClicks || params.preventClicksPropagation) {
3233 el.addEventListener('click', swiper.onClick, true);
3234 }
3235 if (params.cssMode) {
3236 wrapperEl.addEventListener('scroll', swiper.onScroll);
3237 }
3238
3239 // Resize handler
3240 swiper.on((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize, true);
3241}
3242
3243function detachEvents() {
3244 const swiper = this;
3245
3246 const {
3247 params, touchEvents, el, wrapperEl,
3248 } = swiper;
3249
3250 const capture = !!params.nested;
3251
3252 // Touch Events
3253 if (!Support.touch && Support.pointerEvents) {
3254 el.removeEventListener(touchEvents.start, swiper.onTouchStart, false);
3255 doc.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
3256 doc.removeEventListener(touchEvents.end, swiper.onTouchEnd, false);
3257 } else {
3258 if (Support.touch) {
3259 const passiveListener = touchEvents.start === 'onTouchStart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
3260 el.removeEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
3261 el.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
3262 el.removeEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
3263 if (touchEvents.cancel) {
3264 el.removeEventListener(touchEvents.cancel, swiper.onTouchEnd, passiveListener);
3265 }
3266 }
3267 if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
3268 el.removeEventListener('mousedown', swiper.onTouchStart, false);
3269 doc.removeEventListener('mousemove', swiper.onTouchMove, capture);
3270 doc.removeEventListener('mouseup', swiper.onTouchEnd, false);
3271 }
3272 }
3273 // Prevent Links Clicks
3274 if (params.preventClicks || params.preventClicksPropagation) {
3275 el.removeEventListener('click', swiper.onClick, true);
3276 }
3277
3278 if (params.cssMode) {
3279 wrapperEl.removeEventListener('scroll', swiper.onScroll);
3280 }
3281
3282 // Resize handler
3283 swiper.off((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize);
3284}
3285
3286var events = {
3287 attachEvents,
3288 detachEvents,
3289};
3290
3291function setBreakpoint () {
3292 const swiper = this;
3293 const {
3294 activeIndex, initialized, loopedSlides = 0, params, $el,
3295 } = swiper;
3296 const breakpoints = params.breakpoints;
3297 if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) return;
3298
3299 // Get breakpoint for window width and update parameters
3300 const breakpoint = swiper.getBreakpoint(breakpoints);
3301
3302 if (breakpoint && swiper.currentBreakpoint !== breakpoint) {
3303 const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
3304 if (breakpointOnlyParams) {
3305 ['slidesPerView', 'spaceBetween', 'slidesPerGroup', 'slidesPerColumn'].forEach((param) => {
3306 const paramValue = breakpointOnlyParams[param];
3307 if (typeof paramValue === 'undefined') return;
3308 if (param === 'slidesPerView' && (paramValue === 'AUTO' || paramValue === 'auto')) {
3309 breakpointOnlyParams[param] = 'auto';
3310 } else if (param === 'slidesPerView') {
3311 breakpointOnlyParams[param] = parseFloat(paramValue);
3312 } else {
3313 breakpointOnlyParams[param] = parseInt(paramValue, 10);
3314 }
3315 });
3316 }
3317
3318 const breakpointParams = breakpointOnlyParams || swiper.originalParams;
3319 const wasMultiRow = params.slidesPerColumn > 1;
3320 const isMultiRow = breakpointParams.slidesPerColumn > 1;
3321 if (wasMultiRow && !isMultiRow) {
3322 $el.removeClass(`${params.containerModifierClass}multirow ${params.containerModifierClass}multirow-column`);
3323 } else if (!wasMultiRow && isMultiRow) {
3324 $el.addClass(`${params.containerModifierClass}multirow`);
3325 if (breakpointParams.slidesPerColumnFill === 'column') {
3326 $el.addClass(`${params.containerModifierClass}multirow-column`);
3327 }
3328 }
3329
3330 const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
3331 const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
3332
3333 if (directionChanged && initialized) {
3334 swiper.changeDirection();
3335 }
3336
3337 Utils.extend(swiper.params, breakpointParams);
3338
3339 Utils.extend(swiper, {
3340 allowTouchMove: swiper.params.allowTouchMove,
3341 allowSlideNext: swiper.params.allowSlideNext,
3342 allowSlidePrev: swiper.params.allowSlidePrev,
3343 });
3344
3345 swiper.currentBreakpoint = breakpoint;
3346
3347 if (needsReLoop && initialized) {
3348 swiper.loopDestroy();
3349 swiper.loopCreate();
3350 swiper.updateSlides();
3351 swiper.slideTo((activeIndex - loopedSlides) + swiper.loopedSlides, 0, false);
3352 }
3353
3354 swiper.emit('breakpoint', breakpointParams);
3355 }
3356}
3357
3358function getBreakpoint (breakpoints) {
3359 // Get breakpoint for window width
3360 if (!breakpoints) return undefined;
3361 let breakpoint = false;
3362 const points = [];
3363 Object.keys(breakpoints).forEach((point) => {
3364 points.push(point);
3365 });
3366 points.sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
3367 for (let i = 0; i < points.length; i += 1) {
3368 const point = points[i];
3369 if (point <= win.innerWidth) {
3370 breakpoint = point;
3371 }
3372 }
3373 return breakpoint || 'max';
3374}
3375
3376var breakpoints = { setBreakpoint, getBreakpoint };
3377
3378function addClasses () {
3379 const swiper = this;
3380 const {
3381 classNames, params, rtl, $el,
3382 } = swiper;
3383 const suffixes = [];
3384
3385 suffixes.push('initialized');
3386 suffixes.push(params.direction);
3387
3388 if (params.freeMode) {
3389 suffixes.push('free-mode');
3390 }
3391 if (params.autoHeight) {
3392 suffixes.push('autoheight');
3393 }
3394 if (rtl) {
3395 suffixes.push('rtl');
3396 }
3397 if (params.slidesPerColumn > 1) {
3398 suffixes.push('multirow');
3399 if (params.slidesPerColumnFill === 'column') {
3400 suffixes.push('multirow-column');
3401 }
3402 }
3403 if (Device.android) {
3404 suffixes.push('android');
3405 }
3406 if (Device.ios) {
3407 suffixes.push('ios');
3408 }
3409
3410 if (params.cssMode) {
3411 suffixes.push('css-mode');
3412 }
3413
3414 suffixes.forEach((suffix) => {
3415 classNames.push(params.containerModifierClass + suffix);
3416 });
3417
3418 $el.addClass(classNames.join(' '));
3419}
3420
3421function removeClasses () {
3422 const swiper = this;
3423 const { $el, classNames } = swiper;
3424
3425 $el.removeClass(classNames.join(' '));
3426}
3427
3428var classes = { addClasses, removeClasses };
3429
3430function loadImage (imageEl, src, srcset, sizes, checkForComplete, callback) {
3431 let image;
3432 function onReady() {
3433 if (callback) callback();
3434 }
3435 if (!imageEl.complete || !checkForComplete) {
3436 if (src) {
3437 image = new win.Image();
3438 image.onload = onReady;
3439 image.onerror = onReady;
3440 if (sizes) {
3441 image.sizes = sizes;
3442 }
3443 if (srcset) {
3444 image.srcset = srcset;
3445 }
3446 if (src) {
3447 image.src = src;
3448 }
3449 } else {
3450 onReady();
3451 }
3452 } else {
3453 // image already loaded...
3454 onReady();
3455 }
3456}
3457
3458function preloadImages () {
3459 const swiper = this;
3460 swiper.imagesToLoad = swiper.$el.find('img');
3461 function onReady() {
3462 if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) return;
3463 if (swiper.imagesLoaded !== undefined) swiper.imagesLoaded += 1;
3464 if (swiper.imagesLoaded === swiper.imagesToLoad.length) {
3465 if (swiper.params.updateOnImagesReady) swiper.update();
3466 swiper.emit('imagesReady');
3467 }
3468 }
3469 for (let i = 0; i < swiper.imagesToLoad.length; i += 1) {
3470 const imageEl = swiper.imagesToLoad[i];
3471 swiper.loadImage(
3472 imageEl,
3473 imageEl.currentSrc || imageEl.getAttribute('src'),
3474 imageEl.srcset || imageEl.getAttribute('srcset'),
3475 imageEl.sizes || imageEl.getAttribute('sizes'),
3476 true,
3477 onReady
3478 );
3479 }
3480}
3481
3482var images = {
3483 loadImage,
3484 preloadImages,
3485};
3486
3487function checkOverflow() {
3488 const swiper = this;
3489 const wasLocked = swiper.isLocked;
3490
3491 swiper.isLocked = swiper.snapGrid.length === 1;
3492 swiper.allowSlideNext = !swiper.isLocked;
3493 swiper.allowSlidePrev = !swiper.isLocked;
3494
3495 // events
3496 if (wasLocked !== swiper.isLocked) swiper.emit(swiper.isLocked ? 'lock' : 'unlock');
3497
3498 if (wasLocked && wasLocked !== swiper.isLocked) {
3499 swiper.isEnd = false;
3500 swiper.navigation.update();
3501 }
3502}
3503
3504var checkOverflow$1 = { checkOverflow };
3505
3506var defaults = {
3507 init: true,
3508 direction: 'horizontal',
3509 touchEventsTarget: 'container',
3510 initialSlide: 0,
3511 speed: 300,
3512 cssMode: false,
3513 //
3514 preventInteractionOnTransition: false,
3515
3516 // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
3517 edgeSwipeDetection: false,
3518 edgeSwipeThreshold: 20,
3519
3520 // Free mode
3521 freeMode: false,
3522 freeModeMomentum: true,
3523 freeModeMomentumRatio: 1,
3524 freeModeMomentumBounce: true,
3525 freeModeMomentumBounceRatio: 1,
3526 freeModeMomentumVelocityRatio: 1,
3527 freeModeSticky: false,
3528 freeModeMinimumVelocity: 0.02,
3529
3530 // Autoheight
3531 autoHeight: false,
3532
3533 // Set wrapper width
3534 setWrapperSize: false,
3535
3536 // Virtual Translate
3537 virtualTranslate: false,
3538
3539 // Effects
3540 effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
3541
3542 // Breakpoints
3543 breakpoints: undefined,
3544
3545 // Slides grid
3546 spaceBetween: 0,
3547 slidesPerView: 1,
3548 slidesPerColumn: 1,
3549 slidesPerColumnFill: 'column',
3550 slidesPerGroup: 1,
3551 centeredSlides: false,
3552 slidesOffsetBefore: 0, // in px
3553 slidesOffsetAfter: 0, // in px
3554 normalizeSlideIndex: true,
3555 centerInsufficientSlides: false,
3556
3557 // Disable swiper and hide navigation when container not overflow
3558 watchOverflow: false,
3559
3560 // Round length
3561 roundLengths: false,
3562
3563 // Touches
3564 touchRatio: 1,
3565 touchAngle: 45,
3566 simulateTouch: true,
3567 shortSwipes: true,
3568 longSwipes: true,
3569 longSwipesRatio: 0.5,
3570 longSwipesMs: 300,
3571 followFinger: true,
3572 allowTouchMove: true,
3573 threshold: 0,
3574 touchMoveStopPropagation: false,
3575 touchStartPreventDefault: true,
3576 touchStartForcePreventDefault: false,
3577 touchReleaseOnEdges: false,
3578
3579 // Unique Navigation Elements
3580 uniqueNavElements: true,
3581
3582 // Resistance
3583 resistance: true,
3584 resistanceRatio: 0.85,
3585
3586 // Progress
3587 watchSlidesProgress: false,
3588 watchSlidesVisibility: false,
3589
3590 // Cursor
3591 grabCursor: false,
3592
3593 // Clicks
3594 preventClicks: true,
3595 preventClicksPropagation: true,
3596 slideToClickedSlide: false,
3597
3598 // Images
3599 preloadImages: true,
3600 updateOnImagesReady: true,
3601
3602 // loop
3603 loop: false,
3604 loopAdditionalSlides: 0,
3605 loopedSlides: null,
3606 loopFillGroupWithBlank: false,
3607
3608 // Swiping/no swiping
3609 allowSlidePrev: true,
3610 allowSlideNext: true,
3611 swipeHandler: null, // '.swipe-handler',
3612 noSwiping: true,
3613 noSwipingClass: 'swiper-no-swiping',
3614 noSwipingSelector: null,
3615
3616 // Passive Listeners
3617 passiveListeners: true,
3618
3619 // NS
3620 containerModifierClass: 'swiper-container-', // NEW
3621 slideClass: 'swiper-slide',
3622 slideBlankClass: 'swiper-slide-invisible-blank',
3623 slideActiveClass: 'swiper-slide-active',
3624 slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
3625 slideVisibleClass: 'swiper-slide-visible',
3626 slideDuplicateClass: 'swiper-slide-duplicate',
3627 slideNextClass: 'swiper-slide-next',
3628 slideDuplicateNextClass: 'swiper-slide-duplicate-next',
3629 slidePrevClass: 'swiper-slide-prev',
3630 slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
3631 wrapperClass: 'swiper-wrapper',
3632
3633 // Callbacks
3634 runCallbacksOnInit: true,
3635};
3636
3637/* eslint no-param-reassign: "off" */
3638
3639const prototypes = {
3640 update,
3641 translate,
3642 transition: transition$1,
3643 slide,
3644 loop,
3645 grabCursor,
3646 manipulation,
3647 events,
3648 breakpoints,
3649 checkOverflow: checkOverflow$1,
3650 classes,
3651 images,
3652};
3653
3654const extendedDefaults = {};
3655
3656class Swiper extends SwiperClass {
3657 constructor(...args) {
3658 let el;
3659 let params;
3660 if (args.length === 1 && args[0].constructor && args[0].constructor === Object) {
3661 params = args[0];
3662 } else {
3663 [el, params] = args;
3664 }
3665 if (!params) params = {};
3666
3667 params = Utils.extend({}, params);
3668 if (el && !params.el) params.el = el;
3669
3670 super(params);
3671
3672 Object.keys(prototypes).forEach((prototypeGroup) => {
3673 Object.keys(prototypes[prototypeGroup]).forEach((protoMethod) => {
3674 if (!Swiper.prototype[protoMethod]) {
3675 Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
3676 }
3677 });
3678 });
3679
3680 // Swiper Instance
3681 const swiper = this;
3682 if (typeof swiper.modules === 'undefined') {
3683 swiper.modules = {};
3684 }
3685 Object.keys(swiper.modules).forEach((moduleName) => {
3686 const module = swiper.modules[moduleName];
3687 if (module.params) {
3688 const moduleParamName = Object.keys(module.params)[0];
3689 const moduleParams = module.params[moduleParamName];
3690 if (typeof moduleParams !== 'object' || moduleParams === null) return;
3691 if (!(moduleParamName in params && 'enabled' in moduleParams)) return;
3692 if (params[moduleParamName] === true) {
3693 params[moduleParamName] = { enabled: true };
3694 }
3695 if (
3696 typeof params[moduleParamName] === 'object'
3697 && !('enabled' in params[moduleParamName])
3698 ) {
3699 params[moduleParamName].enabled = true;
3700 }
3701 if (!params[moduleParamName]) params[moduleParamName] = { enabled: false };
3702 }
3703 });
3704
3705 // Extend defaults with modules params
3706 const swiperParams = Utils.extend({}, defaults);
3707 swiper.useModulesParams(swiperParams);
3708
3709 // Extend defaults with passed params
3710 swiper.params = Utils.extend({}, swiperParams, extendedDefaults, params);
3711 swiper.originalParams = Utils.extend({}, swiper.params);
3712 swiper.passedParams = Utils.extend({}, params);
3713
3714 // Save Dom lib
3715 swiper.$ = $;
3716
3717 // Find el
3718 const $el = $(swiper.params.el);
3719 el = $el[0];
3720
3721 if (!el) {
3722 return undefined;
3723 }
3724
3725 if ($el.length > 1) {
3726 const swipers = [];
3727 $el.each((index, containerEl) => {
3728 const newParams = Utils.extend({}, params, { el: containerEl });
3729 swipers.push(new Swiper(newParams));
3730 });
3731 return swipers;
3732 }
3733
3734 el.swiper = swiper;
3735 $el.data('swiper', swiper);
3736
3737 // Find Wrapper
3738 let $wrapperEl;
3739 if (el && el.shadowRoot && el.shadowRoot.querySelector) {
3740 $wrapperEl = $(el.shadowRoot.querySelector(`.${swiper.params.wrapperClass}`));
3741 // Children needs to return slot items
3742 $wrapperEl.children = (options) => $el.children(options);
3743 } else {
3744 $wrapperEl = $el.children(`.${swiper.params.wrapperClass}`);
3745 }
3746 // Extend Swiper
3747 Utils.extend(swiper, {
3748 $el,
3749 el,
3750 $wrapperEl,
3751 wrapperEl: $wrapperEl[0],
3752
3753 // Classes
3754 classNames: [],
3755
3756 // Slides
3757 slides: $(),
3758 slidesGrid: [],
3759 snapGrid: [],
3760 slidesSizesGrid: [],
3761
3762 // isDirection
3763 isHorizontal() {
3764 return swiper.params.direction === 'horizontal';
3765 },
3766 isVertical() {
3767 return swiper.params.direction === 'vertical';
3768 },
3769 // RTL
3770 rtl: (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
3771 rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
3772 wrongRTL: $wrapperEl.css('display') === '-webkit-box',
3773
3774 // Indexes
3775 activeIndex: 0,
3776 realIndex: 0,
3777
3778 //
3779 isBeginning: true,
3780 isEnd: false,
3781
3782 // Props
3783 translate: 0,
3784 previousTranslate: 0,
3785 progress: 0,
3786 velocity: 0,
3787 animating: false,
3788
3789 // Locks
3790 allowSlideNext: swiper.params.allowSlideNext,
3791 allowSlidePrev: swiper.params.allowSlidePrev,
3792
3793 // Touch Events
3794 touchEvents: (function touchEvents() {
3795 const touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];
3796 let desktop = ['mousedown', 'mousemove', 'mouseup'];
3797 if (Support.pointerEvents) {
3798 desktop = ['pointerdown', 'pointermove', 'pointerup'];
3799 }
3800 swiper.touchEventsTouch = {
3801 start: touch[0],
3802 move: touch[1],
3803 end: touch[2],
3804 cancel: touch[3],
3805 };
3806 swiper.touchEventsDesktop = {
3807 start: desktop[0],
3808 move: desktop[1],
3809 end: desktop[2],
3810 };
3811 return Support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;
3812 }()),
3813 touchEventsData: {
3814 isTouched: undefined,
3815 isMoved: undefined,
3816 allowTouchCallbacks: undefined,
3817 touchStartTime: undefined,
3818 isScrolling: undefined,
3819 currentTranslate: undefined,
3820 startTranslate: undefined,
3821 allowThresholdMove: undefined,
3822 // Form elements to match
3823 formElements: 'input, select, option, textarea, button, video',
3824 // Last click time
3825 lastClickTime: Utils.now(),
3826 clickTimeout: undefined,
3827 // Velocities
3828 velocities: [],
3829 allowMomentumBounce: undefined,
3830 isTouchEvent: undefined,
3831 startMoving: undefined,
3832 },
3833
3834 // Clicks
3835 allowClick: true,
3836
3837 // Touches
3838 allowTouchMove: swiper.params.allowTouchMove,
3839
3840 touches: {
3841 startX: 0,
3842 startY: 0,
3843 currentX: 0,
3844 currentY: 0,
3845 diff: 0,
3846 },
3847
3848 // Images
3849 imagesToLoad: [],
3850 imagesLoaded: 0,
3851
3852 });
3853
3854 // Install Modules
3855 swiper.useModules();
3856
3857 // Init
3858 if (swiper.params.init) {
3859 swiper.init();
3860 }
3861
3862 // Return app instance
3863 return swiper;
3864 }
3865
3866 slidesPerViewDynamic() {
3867 const swiper = this;
3868 const {
3869 params, slides, slidesGrid, size: swiperSize, activeIndex,
3870 } = swiper;
3871 let spv = 1;
3872 if (params.centeredSlides) {
3873 let slideSize = slides[activeIndex].swiperSlideSize;
3874 let breakLoop;
3875 for (let i = activeIndex + 1; i < slides.length; i += 1) {
3876 if (slides[i] && !breakLoop) {
3877 slideSize += slides[i].swiperSlideSize;
3878 spv += 1;
3879 if (slideSize > swiperSize) breakLoop = true;
3880 }
3881 }
3882 for (let i = activeIndex - 1; i >= 0; i -= 1) {
3883 if (slides[i] && !breakLoop) {
3884 slideSize += slides[i].swiperSlideSize;
3885 spv += 1;
3886 if (slideSize > swiperSize) breakLoop = true;
3887 }
3888 }
3889 } else {
3890 for (let i = activeIndex + 1; i < slides.length; i += 1) {
3891 if (slidesGrid[i] - slidesGrid[activeIndex] < swiperSize) {
3892 spv += 1;
3893 }
3894 }
3895 }
3896 return spv;
3897 }
3898
3899 update() {
3900 const swiper = this;
3901 if (!swiper || swiper.destroyed) return;
3902 const { snapGrid, params } = swiper;
3903 // Breakpoints
3904 if (params.breakpoints) {
3905 swiper.setBreakpoint();
3906 }
3907 swiper.updateSize();
3908 swiper.updateSlides();
3909 swiper.updateProgress();
3910 swiper.updateSlidesClasses();
3911
3912 function setTranslate() {
3913 const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
3914 const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
3915 swiper.setTranslate(newTranslate);
3916 swiper.updateActiveIndex();
3917 swiper.updateSlidesClasses();
3918 }
3919 let translated;
3920 if (swiper.params.freeMode) {
3921 setTranslate();
3922 if (swiper.params.autoHeight) {
3923 swiper.updateAutoHeight();
3924 }
3925 } else {
3926 if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
3927 translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
3928 } else {
3929 translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
3930 }
3931 if (!translated) {
3932 setTranslate();
3933 }
3934 }
3935 if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
3936 swiper.checkOverflow();
3937 }
3938 swiper.emit('update');
3939 }
3940
3941 changeDirection(newDirection, needUpdate = true) {
3942 const swiper = this;
3943 const currentDirection = swiper.params.direction;
3944 if (!newDirection) {
3945 // eslint-disable-next-line
3946 newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
3947 }
3948 if ((newDirection === currentDirection) || (newDirection !== 'horizontal' && newDirection !== 'vertical')) {
3949 return swiper;
3950 }
3951
3952 swiper.$el
3953 .removeClass(`${swiper.params.containerModifierClass}${currentDirection}`)
3954 .addClass(`${swiper.params.containerModifierClass}${newDirection}`);
3955
3956 swiper.params.direction = newDirection;
3957
3958 swiper.slides.each((slideIndex, slideEl) => {
3959 if (newDirection === 'vertical') {
3960 slideEl.style.width = '';
3961 } else {
3962 slideEl.style.height = '';
3963 }
3964 });
3965
3966 swiper.emit('changeDirection');
3967 if (needUpdate) swiper.update();
3968
3969 return swiper;
3970 }
3971
3972 init() {
3973 const swiper = this;
3974 if (swiper.initialized) return;
3975
3976 swiper.emit('beforeInit');
3977
3978 // Set breakpoint
3979 if (swiper.params.breakpoints) {
3980 swiper.setBreakpoint();
3981 }
3982
3983 // Add Classes
3984 swiper.addClasses();
3985
3986 // Create loop
3987 if (swiper.params.loop) {
3988 swiper.loopCreate();
3989 }
3990
3991 // Update size
3992 swiper.updateSize();
3993
3994 // Update slides
3995 swiper.updateSlides();
3996
3997 if (swiper.params.watchOverflow) {
3998 swiper.checkOverflow();
3999 }
4000
4001 // Set Grab Cursor
4002 if (swiper.params.grabCursor) {
4003 swiper.setGrabCursor();
4004 }
4005
4006 if (swiper.params.preloadImages) {
4007 swiper.preloadImages();
4008 }
4009
4010 // Slide To Initial Slide
4011 if (swiper.params.loop) {
4012 swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit);
4013 } else {
4014 swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit);
4015 }
4016
4017 // Attach events
4018 swiper.attachEvents();
4019
4020 // Init Flag
4021 swiper.initialized = true;
4022
4023 // Emit
4024 swiper.emit('init');
4025 }
4026
4027 destroy(deleteInstance = true, cleanStyles = true) {
4028 const swiper = this;
4029 const {
4030 params, $el, $wrapperEl, slides,
4031 } = swiper;
4032
4033 if (typeof swiper.params === 'undefined' || swiper.destroyed) {
4034 return null;
4035 }
4036
4037 swiper.emit('beforeDestroy');
4038
4039 // Init Flag
4040 swiper.initialized = false;
4041
4042 // Detach events
4043 swiper.detachEvents();
4044
4045 // Destroy loop
4046 if (params.loop) {
4047 swiper.loopDestroy();
4048 }
4049
4050 // Cleanup styles
4051 if (cleanStyles) {
4052 swiper.removeClasses();
4053 $el.removeAttr('style');
4054 $wrapperEl.removeAttr('style');
4055 if (slides && slides.length) {
4056 slides
4057 .removeClass([
4058 params.slideVisibleClass,
4059 params.slideActiveClass,
4060 params.slideNextClass,
4061 params.slidePrevClass,
4062 ].join(' '))
4063 .removeAttr('style')
4064 .removeAttr('data-swiper-slide-index');
4065 }
4066 }
4067
4068 swiper.emit('destroy');
4069
4070 // Detach emitter events
4071 Object.keys(swiper.eventsListeners).forEach((eventName) => {
4072 swiper.off(eventName);
4073 });
4074
4075 if (deleteInstance !== false) {
4076 swiper.$el[0].swiper = null;
4077 swiper.$el.data('swiper', null);
4078 Utils.deleteProps(swiper);
4079 }
4080 swiper.destroyed = true;
4081
4082 return null;
4083 }
4084
4085 static extendDefaults(newDefaults) {
4086 Utils.extend(extendedDefaults, newDefaults);
4087 }
4088
4089 static get extendedDefaults() {
4090 return extendedDefaults;
4091 }
4092
4093 static get defaults() {
4094 return defaults;
4095 }
4096
4097 static get Class() {
4098 return SwiperClass;
4099 }
4100
4101 static get $() {
4102 return $;
4103 }
4104}
4105
4106var Device$1 = {
4107 name: 'device',
4108 proto: {
4109 device: Device,
4110 },
4111 static: {
4112 device: Device,
4113 },
4114};
4115
4116var Support$1 = {
4117 name: 'support',
4118 proto: {
4119 support: Support,
4120 },
4121 static: {
4122 support: Support,
4123 },
4124};
4125
4126const Browser = (function Browser() {
4127 function isSafari() {
4128 const ua = win.navigator.userAgent.toLowerCase();
4129 return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
4130 }
4131 return {
4132 isEdge: !!win.navigator.userAgent.match(/Edge/g),
4133 isSafari: isSafari(),
4134 isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(win.navigator.userAgent),
4135 };
4136}());
4137
4138var Browser$1 = {
4139 name: 'browser',
4140 proto: {
4141 browser: Browser,
4142 },
4143 static: {
4144 browser: Browser,
4145 },
4146};
4147
4148var Resize = {
4149 name: 'resize',
4150 create() {
4151 const swiper = this;
4152 Utils.extend(swiper, {
4153 resize: {
4154 resizeHandler() {
4155 if (!swiper || swiper.destroyed || !swiper.initialized) return;
4156 swiper.emit('beforeResize');
4157 swiper.emit('resize');
4158 },
4159 orientationChangeHandler() {
4160 if (!swiper || swiper.destroyed || !swiper.initialized) return;
4161 swiper.emit('orientationchange');
4162 },
4163 },
4164 });
4165 },
4166 on: {
4167 init() {
4168 const swiper = this;
4169 // Emit resize
4170 win.addEventListener('resize', swiper.resize.resizeHandler);
4171
4172 // Emit orientationchange
4173 win.addEventListener('orientationchange', swiper.resize.orientationChangeHandler);
4174 },
4175 destroy() {
4176 const swiper = this;
4177 win.removeEventListener('resize', swiper.resize.resizeHandler);
4178 win.removeEventListener('orientationchange', swiper.resize.orientationChangeHandler);
4179 },
4180 },
4181};
4182
4183const Observer = {
4184 func: win.MutationObserver || win.WebkitMutationObserver,
4185 attach(target, options = {}) {
4186 const swiper = this;
4187
4188 const ObserverFunc = Observer.func;
4189 const observer = new ObserverFunc((mutations) => {
4190 // The observerUpdate event should only be triggered
4191 // once despite the number of mutations. Additional
4192 // triggers are redundant and are very costly
4193 if (mutations.length === 1) {
4194 swiper.emit('observerUpdate', mutations[0]);
4195 return;
4196 }
4197 const observerUpdate = function observerUpdate() {
4198 swiper.emit('observerUpdate', mutations[0]);
4199 };
4200
4201 if (win.requestAnimationFrame) {
4202 win.requestAnimationFrame(observerUpdate);
4203 } else {
4204 win.setTimeout(observerUpdate, 0);
4205 }
4206 });
4207
4208 observer.observe(target, {
4209 attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
4210 childList: typeof options.childList === 'undefined' ? true : options.childList,
4211 characterData: typeof options.characterData === 'undefined' ? true : options.characterData,
4212 });
4213
4214 swiper.observer.observers.push(observer);
4215 },
4216 init() {
4217 const swiper = this;
4218 if (!Support.observer || !swiper.params.observer) return;
4219 if (swiper.params.observeParents) {
4220 const containerParents = swiper.$el.parents();
4221 for (let i = 0; i < containerParents.length; i += 1) {
4222 swiper.observer.attach(containerParents[i]);
4223 }
4224 }
4225 // Observe container
4226 swiper.observer.attach(swiper.$el[0], { childList: swiper.params.observeSlideChildren });
4227
4228 // Observe wrapper
4229 swiper.observer.attach(swiper.$wrapperEl[0], { attributes: false });
4230 },
4231 destroy() {
4232 const swiper = this;
4233 swiper.observer.observers.forEach((observer) => {
4234 observer.disconnect();
4235 });
4236 swiper.observer.observers = [];
4237 },
4238};
4239
4240var Observer$1 = {
4241 name: 'observer',
4242 params: {
4243 observer: false,
4244 observeParents: false,
4245 observeSlideChildren: false,
4246 },
4247 create() {
4248 const swiper = this;
4249 Utils.extend(swiper, {
4250 observer: {
4251 init: Observer.init.bind(swiper),
4252 attach: Observer.attach.bind(swiper),
4253 destroy: Observer.destroy.bind(swiper),
4254 observers: [],
4255 },
4256 });
4257 },
4258 on: {
4259 init() {
4260 const swiper = this;
4261 swiper.observer.init();
4262 },
4263 destroy() {
4264 const swiper = this;
4265 swiper.observer.destroy();
4266 },
4267 },
4268};
4269
4270const Virtual = {
4271 update(force) {
4272 const swiper = this;
4273 const { slidesPerView, slidesPerGroup, centeredSlides } = swiper.params;
4274 const { addSlidesBefore, addSlidesAfter } = swiper.params.virtual;
4275 const {
4276 from: previousFrom,
4277 to: previousTo,
4278 slides,
4279 slidesGrid: previousSlidesGrid,
4280 renderSlide,
4281 offset: previousOffset,
4282 } = swiper.virtual;
4283 swiper.updateActiveIndex();
4284 const activeIndex = swiper.activeIndex || 0;
4285
4286 let offsetProp;
4287 if (swiper.rtlTranslate) offsetProp = 'right';
4288 else offsetProp = swiper.isHorizontal() ? 'left' : 'top';
4289
4290 let slidesAfter;
4291 let slidesBefore;
4292 if (centeredSlides) {
4293 slidesAfter = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;
4294 slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesAfter;
4295 } else {
4296 slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesBefore;
4297 slidesBefore = slidesPerGroup + addSlidesAfter;
4298 }
4299 const from = Math.max((activeIndex || 0) - slidesBefore, 0);
4300 const to = Math.min((activeIndex || 0) + slidesAfter, slides.length - 1);
4301 const offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
4302
4303 Utils.extend(swiper.virtual, {
4304 from,
4305 to,
4306 offset,
4307 slidesGrid: swiper.slidesGrid,
4308 });
4309
4310 function onRendered() {
4311 swiper.updateSlides();
4312 swiper.updateProgress();
4313 swiper.updateSlidesClasses();
4314 if (swiper.lazy && swiper.params.lazy.enabled) {
4315 swiper.lazy.load();
4316 }
4317 }
4318
4319 if (previousFrom === from && previousTo === to && !force) {
4320 if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
4321 swiper.slides.css(offsetProp, `${offset}px`);
4322 }
4323 swiper.updateProgress();
4324 return;
4325 }
4326 if (swiper.params.virtual.renderExternal) {
4327 swiper.params.virtual.renderExternal.call(swiper, {
4328 offset,
4329 from,
4330 to,
4331 slides: (function getSlides() {
4332 const slidesToRender = [];
4333 for (let i = from; i <= to; i += 1) {
4334 slidesToRender.push(slides[i]);
4335 }
4336 return slidesToRender;
4337 }()),
4338 });
4339 onRendered();
4340 return;
4341 }
4342 const prependIndexes = [];
4343 const appendIndexes = [];
4344 if (force) {
4345 swiper.$wrapperEl.find(`.${swiper.params.slideClass}`).remove();
4346 } else {
4347 for (let i = previousFrom; i <= previousTo; i += 1) {
4348 if (i < from || i > to) {
4349 swiper.$wrapperEl.find(`.${swiper.params.slideClass}[data-swiper-slide-index="${i}"]`).remove();
4350 }
4351 }
4352 }
4353 for (let i = 0; i < slides.length; i += 1) {
4354 if (i >= from && i <= to) {
4355 if (typeof previousTo === 'undefined' || force) {
4356 appendIndexes.push(i);
4357 } else {
4358 if (i > previousTo) appendIndexes.push(i);
4359 if (i < previousFrom) prependIndexes.push(i);
4360 }
4361 }
4362 }
4363 appendIndexes.forEach((index) => {
4364 swiper.$wrapperEl.append(renderSlide(slides[index], index));
4365 });
4366 prependIndexes.sort((a, b) => b - a).forEach((index) => {
4367 swiper.$wrapperEl.prepend(renderSlide(slides[index], index));
4368 });
4369 swiper.$wrapperEl.children('.swiper-slide').css(offsetProp, `${offset}px`);
4370 onRendered();
4371 },
4372 renderSlide(slide, index) {
4373 const swiper = this;
4374 const params = swiper.params.virtual;
4375 if (params.cache && swiper.virtual.cache[index]) {
4376 return swiper.virtual.cache[index];
4377 }
4378 const $slideEl = params.renderSlide
4379 ? $(params.renderSlide.call(swiper, slide, index))
4380 : $(`<div class="${swiper.params.slideClass}" data-swiper-slide-index="${index}">${slide}</div>`);
4381 if (!$slideEl.attr('data-swiper-slide-index')) $slideEl.attr('data-swiper-slide-index', index);
4382 if (params.cache) swiper.virtual.cache[index] = $slideEl;
4383 return $slideEl;
4384 },
4385 appendSlide(slides) {
4386 const swiper = this;
4387 if (typeof slides === 'object' && 'length' in slides) {
4388 for (let i = 0; i < slides.length; i += 1) {
4389 if (slides[i]) swiper.virtual.slides.push(slides[i]);
4390 }
4391 } else {
4392 swiper.virtual.slides.push(slides);
4393 }
4394 swiper.virtual.update(true);
4395 },
4396 prependSlide(slides) {
4397 const swiper = this;
4398 const activeIndex = swiper.activeIndex;
4399 let newActiveIndex = activeIndex + 1;
4400 let numberOfNewSlides = 1;
4401
4402 if (Array.isArray(slides)) {
4403 for (let i = 0; i < slides.length; i += 1) {
4404 if (slides[i]) swiper.virtual.slides.unshift(slides[i]);
4405 }
4406 newActiveIndex = activeIndex + slides.length;
4407 numberOfNewSlides = slides.length;
4408 } else {
4409 swiper.virtual.slides.unshift(slides);
4410 }
4411 if (swiper.params.virtual.cache) {
4412 const cache = swiper.virtual.cache;
4413 const newCache = {};
4414 Object.keys(cache).forEach((cachedIndex) => {
4415 const $cachedEl = cache[cachedIndex];
4416 const cachedElIndex = $cachedEl.attr('data-swiper-slide-index');
4417 if (cachedElIndex) {
4418 $cachedEl.attr('data-swiper-slide-index', parseInt(cachedElIndex, 10) + 1);
4419 }
4420 newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = $cachedEl;
4421 });
4422 swiper.virtual.cache = newCache;
4423 }
4424 swiper.virtual.update(true);
4425 swiper.slideTo(newActiveIndex, 0);
4426 },
4427 removeSlide(slidesIndexes) {
4428 const swiper = this;
4429 if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return;
4430 let activeIndex = swiper.activeIndex;
4431 if (Array.isArray(slidesIndexes)) {
4432 for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) {
4433 swiper.virtual.slides.splice(slidesIndexes[i], 1);
4434 if (swiper.params.virtual.cache) {
4435 delete swiper.virtual.cache[slidesIndexes[i]];
4436 }
4437 if (slidesIndexes[i] < activeIndex) activeIndex -= 1;
4438 activeIndex = Math.max(activeIndex, 0);
4439 }
4440 } else {
4441 swiper.virtual.slides.splice(slidesIndexes, 1);
4442 if (swiper.params.virtual.cache) {
4443 delete swiper.virtual.cache[slidesIndexes];
4444 }
4445 if (slidesIndexes < activeIndex) activeIndex -= 1;
4446 activeIndex = Math.max(activeIndex, 0);
4447 }
4448 swiper.virtual.update(true);
4449 swiper.slideTo(activeIndex, 0);
4450 },
4451 removeAllSlides() {
4452 const swiper = this;
4453 swiper.virtual.slides = [];
4454 if (swiper.params.virtual.cache) {
4455 swiper.virtual.cache = {};
4456 }
4457 swiper.virtual.update(true);
4458 swiper.slideTo(0, 0);
4459 },
4460};
4461
4462var Virtual$1 = {
4463 name: 'virtual',
4464 params: {
4465 virtual: {
4466 enabled: false,
4467 slides: [],
4468 cache: true,
4469 renderSlide: null,
4470 renderExternal: null,
4471 addSlidesBefore: 0,
4472 addSlidesAfter: 0,
4473 },
4474 },
4475 create() {
4476 const swiper = this;
4477 Utils.extend(swiper, {
4478 virtual: {
4479 update: Virtual.update.bind(swiper),
4480 appendSlide: Virtual.appendSlide.bind(swiper),
4481 prependSlide: Virtual.prependSlide.bind(swiper),
4482 removeSlide: Virtual.removeSlide.bind(swiper),
4483 removeAllSlides: Virtual.removeAllSlides.bind(swiper),
4484 renderSlide: Virtual.renderSlide.bind(swiper),
4485 slides: swiper.params.virtual.slides,
4486 cache: {},
4487 },
4488 });
4489 },
4490 on: {
4491 beforeInit() {
4492 const swiper = this;
4493 if (!swiper.params.virtual.enabled) return;
4494 swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`);
4495 const overwriteParams = {
4496 watchSlidesProgress: true,
4497 };
4498 Utils.extend(swiper.params, overwriteParams);
4499 Utils.extend(swiper.originalParams, overwriteParams);
4500
4501 if (!swiper.params.initialSlide) {
4502 swiper.virtual.update();
4503 }
4504 },
4505 setTranslate() {
4506 const swiper = this;
4507 if (!swiper.params.virtual.enabled) return;
4508 swiper.virtual.update();
4509 },
4510 },
4511};
4512
4513const Keyboard = {
4514 handle(event) {
4515 const swiper = this;
4516 const { rtlTranslate: rtl } = swiper;
4517 let e = event;
4518 if (e.originalEvent) e = e.originalEvent; // jquery fix
4519 const kc = e.keyCode || e.charCode;
4520 // Directions locks
4521 if (!swiper.allowSlideNext && ((swiper.isHorizontal() && kc === 39) || (swiper.isVertical() && kc === 40) || kc === 34)) {
4522 return false;
4523 }
4524 if (!swiper.allowSlidePrev && ((swiper.isHorizontal() && kc === 37) || (swiper.isVertical() && kc === 38) || kc === 33)) {
4525 return false;
4526 }
4527 if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
4528 return undefined;
4529 }
4530 if (doc.activeElement && doc.activeElement.nodeName && (doc.activeElement.nodeName.toLowerCase() === 'input' || doc.activeElement.nodeName.toLowerCase() === 'textarea')) {
4531 return undefined;
4532 }
4533 if (swiper.params.keyboard.onlyInViewport && (kc === 33 || kc === 34 || kc === 37 || kc === 39 || kc === 38 || kc === 40)) {
4534 let inView = false;
4535 // Check that swiper should be inside of visible area of window
4536 if (swiper.$el.parents(`.${swiper.params.slideClass}`).length > 0 && swiper.$el.parents(`.${swiper.params.slideActiveClass}`).length === 0) {
4537 return undefined;
4538 }
4539 const windowWidth = win.innerWidth;
4540 const windowHeight = win.innerHeight;
4541 const swiperOffset = swiper.$el.offset();
4542 if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;
4543 const swiperCoord = [
4544 [swiperOffset.left, swiperOffset.top],
4545 [swiperOffset.left + swiper.width, swiperOffset.top],
4546 [swiperOffset.left, swiperOffset.top + swiper.height],
4547 [swiperOffset.left + swiper.width, swiperOffset.top + swiper.height],
4548 ];
4549 for (let i = 0; i < swiperCoord.length; i += 1) {
4550 const point = swiperCoord[i];
4551 if (
4552 point[0] >= 0 && point[0] <= windowWidth
4553 && point[1] >= 0 && point[1] <= windowHeight
4554 ) {
4555 inView = true;
4556 }
4557 }
4558 if (!inView) return undefined;
4559 }
4560 if (swiper.isHorizontal()) {
4561 if (kc === 33 || kc === 34 || kc === 37 || kc === 39) {
4562 if (e.preventDefault) e.preventDefault();
4563 else e.returnValue = false;
4564 }
4565 if (((kc === 34 || kc === 39) && !rtl) || ((kc === 33 || kc === 37) && rtl)) swiper.slideNext();
4566 if (((kc === 33 || kc === 37) && !rtl) || ((kc === 34 || kc === 39) && rtl)) swiper.slidePrev();
4567 } else {
4568 if (kc === 33 || kc === 34 || kc === 38 || kc === 40) {
4569 if (e.preventDefault) e.preventDefault();
4570 else e.returnValue = false;
4571 }
4572 if (kc === 34 || kc === 40) swiper.slideNext();
4573 if (kc === 33 || kc === 38) swiper.slidePrev();
4574 }
4575 swiper.emit('keyPress', kc);
4576 return undefined;
4577 },
4578 enable() {
4579 const swiper = this;
4580 if (swiper.keyboard.enabled) return;
4581 $(doc).on('keydown', swiper.keyboard.handle);
4582 swiper.keyboard.enabled = true;
4583 },
4584 disable() {
4585 const swiper = this;
4586 if (!swiper.keyboard.enabled) return;
4587 $(doc).off('keydown', swiper.keyboard.handle);
4588 swiper.keyboard.enabled = false;
4589 },
4590};
4591
4592var Keyboard$1 = {
4593 name: 'keyboard',
4594 params: {
4595 keyboard: {
4596 enabled: false,
4597 onlyInViewport: true,
4598 },
4599 },
4600 create() {
4601 const swiper = this;
4602 Utils.extend(swiper, {
4603 keyboard: {
4604 enabled: false,
4605 enable: Keyboard.enable.bind(swiper),
4606 disable: Keyboard.disable.bind(swiper),
4607 handle: Keyboard.handle.bind(swiper),
4608 },
4609 });
4610 },
4611 on: {
4612 init() {
4613 const swiper = this;
4614 if (swiper.params.keyboard.enabled) {
4615 swiper.keyboard.enable();
4616 }
4617 },
4618 destroy() {
4619 const swiper = this;
4620 if (swiper.keyboard.enabled) {
4621 swiper.keyboard.disable();
4622 }
4623 },
4624 },
4625};
4626
4627function isEventSupported() {
4628 const eventName = 'onwheel';
4629 let isSupported = eventName in doc;
4630
4631 if (!isSupported) {
4632 const element = doc.createElement('div');
4633 element.setAttribute(eventName, 'return;');
4634 isSupported = typeof element[eventName] === 'function';
4635 }
4636
4637 if (!isSupported
4638 && doc.implementation
4639 && doc.implementation.hasFeature
4640 // always returns true in newer browsers as per the standard.
4641 // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
4642 && doc.implementation.hasFeature('', '') !== true
4643 ) {
4644 // This is the only way to test support for the `wheel` event in IE9+.
4645 isSupported = doc.implementation.hasFeature('Events.wheel', '3.0');
4646 }
4647
4648 return isSupported;
4649}
4650const Mousewheel = {
4651 lastScrollTime: Utils.now(),
4652 event() {
4653 if (win.navigator.userAgent.indexOf('firefox') > -1) return 'DOMMouseScroll';
4654 return isEventSupported() ? 'wheel' : 'mousewheel';
4655 },
4656 normalize(e) {
4657 // Reasonable defaults
4658 const PIXEL_STEP = 10;
4659 const LINE_HEIGHT = 40;
4660 const PAGE_HEIGHT = 800;
4661
4662 let sX = 0;
4663 let sY = 0; // spinX, spinY
4664 let pX = 0;
4665 let pY = 0; // pixelX, pixelY
4666
4667 // Legacy
4668 if ('detail' in e) {
4669 sY = e.detail;
4670 }
4671 if ('wheelDelta' in e) {
4672 sY = -e.wheelDelta / 120;
4673 }
4674 if ('wheelDeltaY' in e) {
4675 sY = -e.wheelDeltaY / 120;
4676 }
4677 if ('wheelDeltaX' in e) {
4678 sX = -e.wheelDeltaX / 120;
4679 }
4680
4681 // side scrolling on FF with DOMMouseScroll
4682 if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
4683 sX = sY;
4684 sY = 0;
4685 }
4686
4687 pX = sX * PIXEL_STEP;
4688 pY = sY * PIXEL_STEP;
4689
4690 if ('deltaY' in e) {
4691 pY = e.deltaY;
4692 }
4693 if ('deltaX' in e) {
4694 pX = e.deltaX;
4695 }
4696
4697 if (e.shiftKey && !pX) { // if user scrolls with shift he wants horizontal scroll
4698 pX = pY;
4699 pY = 0;
4700 }
4701
4702 if ((pX || pY) && e.deltaMode) {
4703 if (e.deltaMode === 1) { // delta in LINE units
4704 pX *= LINE_HEIGHT;
4705 pY *= LINE_HEIGHT;
4706 } else { // delta in PAGE units
4707 pX *= PAGE_HEIGHT;
4708 pY *= PAGE_HEIGHT;
4709 }
4710 }
4711
4712 // Fall-back if spin cannot be determined
4713 if (pX && !sX) {
4714 sX = (pX < 1) ? -1 : 1;
4715 }
4716 if (pY && !sY) {
4717 sY = (pY < 1) ? -1 : 1;
4718 }
4719
4720 return {
4721 spinX: sX,
4722 spinY: sY,
4723 pixelX: pX,
4724 pixelY: pY,
4725 };
4726 },
4727 handleMouseEnter() {
4728 const swiper = this;
4729 swiper.mouseEntered = true;
4730 },
4731 handleMouseLeave() {
4732 const swiper = this;
4733 swiper.mouseEntered = false;
4734 },
4735 handle(event) {
4736 let e = event;
4737 const swiper = this;
4738 const params = swiper.params.mousewheel;
4739
4740 if (swiper.params.cssMode) {
4741 e.preventDefault();
4742 }
4743
4744 if (!swiper.mouseEntered && !params.releaseOnEdges) return true;
4745
4746 if (e.originalEvent) e = e.originalEvent; // jquery fix
4747 let delta = 0;
4748 const rtlFactor = swiper.rtlTranslate ? -1 : 1;
4749
4750 const data = Mousewheel.normalize(e);
4751
4752 if (params.forceToAxis) {
4753 if (swiper.isHorizontal()) {
4754 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = data.pixelX * rtlFactor;
4755 else return true;
4756 } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = data.pixelY;
4757 else return true;
4758 } else {
4759 delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
4760 }
4761
4762 if (delta === 0) return true;
4763
4764 if (params.invert) delta = -delta;
4765
4766 if (!swiper.params.freeMode) {
4767 if (Utils.now() - swiper.mousewheel.lastScrollTime > 60) {
4768 if (delta < 0) {
4769 if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
4770 swiper.slideNext();
4771 swiper.emit('scroll', e);
4772 } else if (params.releaseOnEdges) return true;
4773 } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
4774 swiper.slidePrev();
4775 swiper.emit('scroll', e);
4776 } else if (params.releaseOnEdges) return true;
4777 }
4778 swiper.mousewheel.lastScrollTime = (new win.Date()).getTime();
4779 } else {
4780 // Freemode or scrollContainer:
4781 if (swiper.params.loop) {
4782 swiper.loopFix();
4783 }
4784 let position = swiper.getTranslate() + (delta * params.sensitivity);
4785 const wasBeginning = swiper.isBeginning;
4786 const wasEnd = swiper.isEnd;
4787
4788 if (position >= swiper.minTranslate()) position = swiper.minTranslate();
4789 if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();
4790
4791 swiper.setTransition(0);
4792 swiper.setTranslate(position);
4793 swiper.updateProgress();
4794 swiper.updateActiveIndex();
4795 swiper.updateSlidesClasses();
4796
4797 if ((!wasBeginning && swiper.isBeginning) || (!wasEnd && swiper.isEnd)) {
4798 swiper.updateSlidesClasses();
4799 }
4800
4801 if (swiper.params.freeModeSticky) {
4802 clearTimeout(swiper.mousewheel.timeout);
4803 swiper.mousewheel.timeout = Utils.nextTick(() => {
4804 swiper.slideToClosest();
4805 }, 300);
4806 }
4807 // Emit event
4808 swiper.emit('scroll', e);
4809
4810 // Stop autoplay
4811 if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) swiper.autoplay.stop();
4812 // Return page scroll on edge positions
4813 if (position === swiper.minTranslate() || position === swiper.maxTranslate()) return true;
4814 }
4815
4816 if (e.preventDefault) e.preventDefault();
4817 else e.returnValue = false;
4818 return false;
4819 },
4820 enable() {
4821 const swiper = this;
4822 const event = Mousewheel.event();
4823 if (swiper.params.cssMode) {
4824 swiper.wrapperEl.removeEventListener(event, swiper.mousewheel.handle);
4825 return true;
4826 }
4827 if (!event) return false;
4828 if (swiper.mousewheel.enabled) return false;
4829 let target = swiper.$el;
4830 if (swiper.params.mousewheel.eventsTarged !== 'container') {
4831 target = $(swiper.params.mousewheel.eventsTarged);
4832 }
4833 target.on('mouseenter', swiper.mousewheel.handleMouseEnter);
4834 target.on('mouseleave', swiper.mousewheel.handleMouseLeave);
4835 target.on(event, swiper.mousewheel.handle);
4836 swiper.mousewheel.enabled = true;
4837 return true;
4838 },
4839 disable() {
4840 const swiper = this;
4841 const event = Mousewheel.event();
4842 if (swiper.params.cssMode) {
4843 swiper.wrapperEl.addEventListener(event, swiper.mousewheel.handle);
4844 return true;
4845 }
4846 if (!event) return false;
4847 if (!swiper.mousewheel.enabled) return false;
4848 let target = swiper.$el;
4849 if (swiper.params.mousewheel.eventsTarged !== 'container') {
4850 target = $(swiper.params.mousewheel.eventsTarged);
4851 }
4852 target.off(event, swiper.mousewheel.handle);
4853 swiper.mousewheel.enabled = false;
4854 return true;
4855 },
4856};
4857
4858var Mousewheel$1 = {
4859 name: 'mousewheel',
4860 params: {
4861 mousewheel: {
4862 enabled: false,
4863 releaseOnEdges: false,
4864 invert: false,
4865 forceToAxis: false,
4866 sensitivity: 1,
4867 eventsTarged: 'container',
4868 },
4869 },
4870 create() {
4871 const swiper = this;
4872 Utils.extend(swiper, {
4873 mousewheel: {
4874 enabled: false,
4875 enable: Mousewheel.enable.bind(swiper),
4876 disable: Mousewheel.disable.bind(swiper),
4877 handle: Mousewheel.handle.bind(swiper),
4878 handleMouseEnter: Mousewheel.handleMouseEnter.bind(swiper),
4879 handleMouseLeave: Mousewheel.handleMouseLeave.bind(swiper),
4880 lastScrollTime: Utils.now(),
4881 },
4882 });
4883 },
4884 on: {
4885 init() {
4886 const swiper = this;
4887 if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
4888 swiper.mousewheel.disable();
4889 }
4890 if (swiper.params.mousewheel.enabled) swiper.mousewheel.enable();
4891 },
4892 destroy() {
4893 const swiper = this;
4894 if (swiper.params.cssMode) {
4895 swiper.mousewheel.enable();
4896 }
4897 if (swiper.mousewheel.enabled) swiper.mousewheel.disable();
4898 },
4899 },
4900};
4901
4902const Navigation = {
4903 update() {
4904 // Update Navigation Buttons
4905 const swiper = this;
4906 const params = swiper.params.navigation;
4907
4908 if (swiper.params.loop) return;
4909 const { $nextEl, $prevEl } = swiper.navigation;
4910
4911 if ($prevEl && $prevEl.length > 0) {
4912 if (swiper.isBeginning) {
4913 $prevEl.addClass(params.disabledClass);
4914 } else {
4915 $prevEl.removeClass(params.disabledClass);
4916 }
4917 $prevEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
4918 }
4919 if ($nextEl && $nextEl.length > 0) {
4920 if (swiper.isEnd) {
4921 $nextEl.addClass(params.disabledClass);
4922 } else {
4923 $nextEl.removeClass(params.disabledClass);
4924 }
4925 $nextEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
4926 }
4927 },
4928 onPrevClick(e) {
4929 const swiper = this;
4930 e.preventDefault();
4931 if (swiper.isBeginning && !swiper.params.loop) return;
4932 swiper.slidePrev();
4933 },
4934 onNextClick(e) {
4935 const swiper = this;
4936 e.preventDefault();
4937 if (swiper.isEnd && !swiper.params.loop) return;
4938 swiper.slideNext();
4939 },
4940 init() {
4941 const swiper = this;
4942 const params = swiper.params.navigation;
4943 if (!(params.nextEl || params.prevEl)) return;
4944
4945 let $nextEl;
4946 let $prevEl;
4947 if (params.nextEl) {
4948 $nextEl = $(params.nextEl);
4949 if (
4950 swiper.params.uniqueNavElements
4951 && typeof params.nextEl === 'string'
4952 && $nextEl.length > 1
4953 && swiper.$el.find(params.nextEl).length === 1
4954 ) {
4955 $nextEl = swiper.$el.find(params.nextEl);
4956 }
4957 }
4958 if (params.prevEl) {
4959 $prevEl = $(params.prevEl);
4960 if (
4961 swiper.params.uniqueNavElements
4962 && typeof params.prevEl === 'string'
4963 && $prevEl.length > 1
4964 && swiper.$el.find(params.prevEl).length === 1
4965 ) {
4966 $prevEl = swiper.$el.find(params.prevEl);
4967 }
4968 }
4969
4970 if ($nextEl && $nextEl.length > 0) {
4971 $nextEl.on('click', swiper.navigation.onNextClick);
4972 }
4973 if ($prevEl && $prevEl.length > 0) {
4974 $prevEl.on('click', swiper.navigation.onPrevClick);
4975 }
4976
4977 Utils.extend(swiper.navigation, {
4978 $nextEl,
4979 nextEl: $nextEl && $nextEl[0],
4980 $prevEl,
4981 prevEl: $prevEl && $prevEl[0],
4982 });
4983 },
4984 destroy() {
4985 const swiper = this;
4986 const { $nextEl, $prevEl } = swiper.navigation;
4987 if ($nextEl && $nextEl.length) {
4988 $nextEl.off('click', swiper.navigation.onNextClick);
4989 $nextEl.removeClass(swiper.params.navigation.disabledClass);
4990 }
4991 if ($prevEl && $prevEl.length) {
4992 $prevEl.off('click', swiper.navigation.onPrevClick);
4993 $prevEl.removeClass(swiper.params.navigation.disabledClass);
4994 }
4995 },
4996};
4997
4998var Navigation$1 = {
4999 name: 'navigation',
5000 params: {
5001 navigation: {
5002 nextEl: null,
5003 prevEl: null,
5004
5005 hideOnClick: false,
5006 disabledClass: 'swiper-button-disabled',
5007 hiddenClass: 'swiper-button-hidden',
5008 lockClass: 'swiper-button-lock',
5009 },
5010 },
5011 create() {
5012 const swiper = this;
5013 Utils.extend(swiper, {
5014 navigation: {
5015 init: Navigation.init.bind(swiper),
5016 update: Navigation.update.bind(swiper),
5017 destroy: Navigation.destroy.bind(swiper),
5018 onNextClick: Navigation.onNextClick.bind(swiper),
5019 onPrevClick: Navigation.onPrevClick.bind(swiper),
5020 },
5021 });
5022 },
5023 on: {
5024 init() {
5025 const swiper = this;
5026 swiper.navigation.init();
5027 swiper.navigation.update();
5028 },
5029 toEdge() {
5030 const swiper = this;
5031 swiper.navigation.update();
5032 },
5033 fromEdge() {
5034 const swiper = this;
5035 swiper.navigation.update();
5036 },
5037 destroy() {
5038 const swiper = this;
5039 swiper.navigation.destroy();
5040 },
5041 click(e) {
5042 const swiper = this;
5043 const { $nextEl, $prevEl } = swiper.navigation;
5044 if (
5045 swiper.params.navigation.hideOnClick
5046 && !$(e.target).is($prevEl)
5047 && !$(e.target).is($nextEl)
5048 ) {
5049 let isHidden;
5050 if ($nextEl) {
5051 isHidden = $nextEl.hasClass(swiper.params.navigation.hiddenClass);
5052 } else if ($prevEl) {
5053 isHidden = $prevEl.hasClass(swiper.params.navigation.hiddenClass);
5054 }
5055 if (isHidden === true) {
5056 swiper.emit('navigationShow', swiper);
5057 } else {
5058 swiper.emit('navigationHide', swiper);
5059 }
5060 if ($nextEl) {
5061 $nextEl.toggleClass(swiper.params.navigation.hiddenClass);
5062 }
5063 if ($prevEl) {
5064 $prevEl.toggleClass(swiper.params.navigation.hiddenClass);
5065 }
5066 }
5067 },
5068 },
5069};
5070
5071const Pagination = {
5072 update() {
5073 // Render || Update Pagination bullets/items
5074 const swiper = this;
5075 const rtl = swiper.rtl;
5076 const params = swiper.params.pagination;
5077 if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
5078 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
5079 const $el = swiper.pagination.$el;
5080 // Current/Total
5081 let current;
5082 const total = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
5083 if (swiper.params.loop) {
5084 current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
5085 if (current > slidesLength - 1 - (swiper.loopedSlides * 2)) {
5086 current -= (slidesLength - (swiper.loopedSlides * 2));
5087 }
5088 if (current > total - 1) current -= total;
5089 if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
5090 } else if (typeof swiper.snapIndex !== 'undefined') {
5091 current = swiper.snapIndex;
5092 } else {
5093 current = swiper.activeIndex || 0;
5094 }
5095 // Types
5096 if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
5097 const bullets = swiper.pagination.bullets;
5098 let firstIndex;
5099 let lastIndex;
5100 let midIndex;
5101 if (params.dynamicBullets) {
5102 swiper.pagination.bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
5103 $el.css(swiper.isHorizontal() ? 'width' : 'height', `${swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)}px`);
5104 if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
5105 swiper.pagination.dynamicBulletIndex += (current - swiper.previousIndex);
5106 if (swiper.pagination.dynamicBulletIndex > (params.dynamicMainBullets - 1)) {
5107 swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
5108 } else if (swiper.pagination.dynamicBulletIndex < 0) {
5109 swiper.pagination.dynamicBulletIndex = 0;
5110 }
5111 }
5112 firstIndex = current - swiper.pagination.dynamicBulletIndex;
5113 lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
5114 midIndex = (lastIndex + firstIndex) / 2;
5115 }
5116 bullets.removeClass(`${params.bulletActiveClass} ${params.bulletActiveClass}-next ${params.bulletActiveClass}-next-next ${params.bulletActiveClass}-prev ${params.bulletActiveClass}-prev-prev ${params.bulletActiveClass}-main`);
5117 if ($el.length > 1) {
5118 bullets.each((index, bullet) => {
5119 const $bullet = $(bullet);
5120 const bulletIndex = $bullet.index();
5121 if (bulletIndex === current) {
5122 $bullet.addClass(params.bulletActiveClass);
5123 }
5124 if (params.dynamicBullets) {
5125 if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
5126 $bullet.addClass(`${params.bulletActiveClass}-main`);
5127 }
5128 if (bulletIndex === firstIndex) {
5129 $bullet
5130 .prev()
5131 .addClass(`${params.bulletActiveClass}-prev`)
5132 .prev()
5133 .addClass(`${params.bulletActiveClass}-prev-prev`);
5134 }
5135 if (bulletIndex === lastIndex) {
5136 $bullet
5137 .next()
5138 .addClass(`${params.bulletActiveClass}-next`)
5139 .next()
5140 .addClass(`${params.bulletActiveClass}-next-next`);
5141 }
5142 }
5143 });
5144 } else {
5145 const $bullet = bullets.eq(current);
5146 $bullet.addClass(params.bulletActiveClass);
5147 if (params.dynamicBullets) {
5148 const $firstDisplayedBullet = bullets.eq(firstIndex);
5149 const $lastDisplayedBullet = bullets.eq(lastIndex);
5150 for (let i = firstIndex; i <= lastIndex; i += 1) {
5151 bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
5152 }
5153 $firstDisplayedBullet
5154 .prev()
5155 .addClass(`${params.bulletActiveClass}-prev`)
5156 .prev()
5157 .addClass(`${params.bulletActiveClass}-prev-prev`);
5158 $lastDisplayedBullet
5159 .next()
5160 .addClass(`${params.bulletActiveClass}-next`)
5161 .next()
5162 .addClass(`${params.bulletActiveClass}-next-next`);
5163 }
5164 }
5165 if (params.dynamicBullets) {
5166 const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
5167 const bulletsOffset = (((swiper.pagination.bulletSize * dynamicBulletsLength) - (swiper.pagination.bulletSize)) / 2) - (midIndex * swiper.pagination.bulletSize);
5168 const offsetProp = rtl ? 'right' : 'left';
5169 bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
5170 }
5171 }
5172 if (params.type === 'fraction') {
5173 $el.find(`.${params.currentClass}`).text(params.formatFractionCurrent(current + 1));
5174 $el.find(`.${params.totalClass}`).text(params.formatFractionTotal(total));
5175 }
5176 if (params.type === 'progressbar') {
5177 let progressbarDirection;
5178 if (params.progressbarOpposite) {
5179 progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
5180 } else {
5181 progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
5182 }
5183 const scale = (current + 1) / total;
5184 let scaleX = 1;
5185 let scaleY = 1;
5186 if (progressbarDirection === 'horizontal') {
5187 scaleX = scale;
5188 } else {
5189 scaleY = scale;
5190 }
5191 $el.find(`.${params.progressbarFillClass}`).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);
5192 }
5193 if (params.type === 'custom' && params.renderCustom) {
5194 $el.html(params.renderCustom(swiper, current + 1, total));
5195 swiper.emit('paginationRender', swiper, $el[0]);
5196 } else {
5197 swiper.emit('paginationUpdate', swiper, $el[0]);
5198 }
5199 $el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
5200 },
5201 render() {
5202 // Render Container
5203 const swiper = this;
5204 const params = swiper.params.pagination;
5205 if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
5206 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
5207
5208 const $el = swiper.pagination.$el;
5209 let paginationHTML = '';
5210 if (params.type === 'bullets') {
5211 const numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
5212 for (let i = 0; i < numberOfBullets; i += 1) {
5213 if (params.renderBullet) {
5214 paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
5215 } else {
5216 paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
5217 }
5218 }
5219 $el.html(paginationHTML);
5220 swiper.pagination.bullets = $el.find(`.${params.bulletClass}`);
5221 }
5222 if (params.type === 'fraction') {
5223 if (params.renderFraction) {
5224 paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
5225 } else {
5226 paginationHTML = `<span class="${params.currentClass}"></span>`
5227 + ' / '
5228 + `<span class="${params.totalClass}"></span>`;
5229 }
5230 $el.html(paginationHTML);
5231 }
5232 if (params.type === 'progressbar') {
5233 if (params.renderProgressbar) {
5234 paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
5235 } else {
5236 paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
5237 }
5238 $el.html(paginationHTML);
5239 }
5240 if (params.type !== 'custom') {
5241 swiper.emit('paginationRender', swiper.pagination.$el[0]);
5242 }
5243 },
5244 init() {
5245 const swiper = this;
5246 const params = swiper.params.pagination;
5247 if (!params.el) return;
5248
5249 let $el = $(params.el);
5250 if ($el.length === 0) return;
5251
5252 if (
5253 swiper.params.uniqueNavElements
5254 && typeof params.el === 'string'
5255 && $el.length > 1
5256 && swiper.$el.find(params.el).length === 1
5257 ) {
5258 $el = swiper.$el.find(params.el);
5259 }
5260
5261 if (params.type === 'bullets' && params.clickable) {
5262 $el.addClass(params.clickableClass);
5263 }
5264
5265 $el.addClass(params.modifierClass + params.type);
5266
5267 if (params.type === 'bullets' && params.dynamicBullets) {
5268 $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
5269 swiper.pagination.dynamicBulletIndex = 0;
5270 if (params.dynamicMainBullets < 1) {
5271 params.dynamicMainBullets = 1;
5272 }
5273 }
5274 if (params.type === 'progressbar' && params.progressbarOpposite) {
5275 $el.addClass(params.progressbarOppositeClass);
5276 }
5277
5278 if (params.clickable) {
5279 $el.on('click', `.${params.bulletClass}`, function onClick(e) {
5280 e.preventDefault();
5281 let index = $(this).index() * swiper.params.slidesPerGroup;
5282 if (swiper.params.loop) index += swiper.loopedSlides;
5283 swiper.slideTo(index);
5284 });
5285 }
5286
5287 Utils.extend(swiper.pagination, {
5288 $el,
5289 el: $el[0],
5290 });
5291 },
5292 destroy() {
5293 const swiper = this;
5294 const params = swiper.params.pagination;
5295 if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
5296 const $el = swiper.pagination.$el;
5297
5298 $el.removeClass(params.hiddenClass);
5299 $el.removeClass(params.modifierClass + params.type);
5300 if (swiper.pagination.bullets) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
5301 if (params.clickable) {
5302 $el.off('click', `.${params.bulletClass}`);
5303 }
5304 },
5305};
5306
5307var Pagination$1 = {
5308 name: 'pagination',
5309 params: {
5310 pagination: {
5311 el: null,
5312 bulletElement: 'span',
5313 clickable: false,
5314 hideOnClick: false,
5315 renderBullet: null,
5316 renderProgressbar: null,
5317 renderFraction: null,
5318 renderCustom: null,
5319 progressbarOpposite: false,
5320 type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
5321 dynamicBullets: false,
5322 dynamicMainBullets: 1,
5323 formatFractionCurrent: (number) => number,
5324 formatFractionTotal: (number) => number,
5325 bulletClass: 'swiper-pagination-bullet',
5326 bulletActiveClass: 'swiper-pagination-bullet-active',
5327 modifierClass: 'swiper-pagination-', // NEW
5328 currentClass: 'swiper-pagination-current',
5329 totalClass: 'swiper-pagination-total',
5330 hiddenClass: 'swiper-pagination-hidden',
5331 progressbarFillClass: 'swiper-pagination-progressbar-fill',
5332 progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
5333 clickableClass: 'swiper-pagination-clickable', // NEW
5334 lockClass: 'swiper-pagination-lock',
5335 },
5336 },
5337 create() {
5338 const swiper = this;
5339 Utils.extend(swiper, {
5340 pagination: {
5341 init: Pagination.init.bind(swiper),
5342 render: Pagination.render.bind(swiper),
5343 update: Pagination.update.bind(swiper),
5344 destroy: Pagination.destroy.bind(swiper),
5345 dynamicBulletIndex: 0,
5346 },
5347 });
5348 },
5349 on: {
5350 init() {
5351 const swiper = this;
5352 swiper.pagination.init();
5353 swiper.pagination.render();
5354 swiper.pagination.update();
5355 },
5356 activeIndexChange() {
5357 const swiper = this;
5358 if (swiper.params.loop) {
5359 swiper.pagination.update();
5360 } else if (typeof swiper.snapIndex === 'undefined') {
5361 swiper.pagination.update();
5362 }
5363 },
5364 snapIndexChange() {
5365 const swiper = this;
5366 if (!swiper.params.loop) {
5367 swiper.pagination.update();
5368 }
5369 },
5370 slidesLengthChange() {
5371 const swiper = this;
5372 if (swiper.params.loop) {
5373 swiper.pagination.render();
5374 swiper.pagination.update();
5375 }
5376 },
5377 snapGridLengthChange() {
5378 const swiper = this;
5379 if (!swiper.params.loop) {
5380 swiper.pagination.render();
5381 swiper.pagination.update();
5382 }
5383 },
5384 destroy() {
5385 const swiper = this;
5386 swiper.pagination.destroy();
5387 },
5388 click(e) {
5389 const swiper = this;
5390 if (
5391 swiper.params.pagination.el
5392 && swiper.params.pagination.hideOnClick
5393 && swiper.pagination.$el.length > 0
5394 && !$(e.target).hasClass(swiper.params.pagination.bulletClass)
5395 ) {
5396 const isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
5397 if (isHidden === true) {
5398 swiper.emit('paginationShow', swiper);
5399 } else {
5400 swiper.emit('paginationHide', swiper);
5401 }
5402 swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
5403 }
5404 },
5405 },
5406};
5407
5408const Scrollbar = {
5409 setTranslate() {
5410 const swiper = this;
5411 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
5412 const { scrollbar, rtlTranslate: rtl, progress } = swiper;
5413 const {
5414 dragSize, trackSize, $dragEl, $el,
5415 } = scrollbar;
5416 const params = swiper.params.scrollbar;
5417
5418 let newSize = dragSize;
5419 let newPos = (trackSize - dragSize) * progress;
5420 if (rtl) {
5421 newPos = -newPos;
5422 if (newPos > 0) {
5423 newSize = dragSize - newPos;
5424 newPos = 0;
5425 } else if (-newPos + dragSize > trackSize) {
5426 newSize = trackSize + newPos;
5427 }
5428 } else if (newPos < 0) {
5429 newSize = dragSize + newPos;
5430 newPos = 0;
5431 } else if (newPos + dragSize > trackSize) {
5432 newSize = trackSize - newPos;
5433 }
5434 if (swiper.isHorizontal()) {
5435 $dragEl.transform(`translate3d(${newPos}px, 0, 0)`);
5436 $dragEl[0].style.width = `${newSize}px`;
5437 } else {
5438 $dragEl.transform(`translate3d(0px, ${newPos}px, 0)`);
5439 $dragEl[0].style.height = `${newSize}px`;
5440 }
5441 if (params.hide) {
5442 clearTimeout(swiper.scrollbar.timeout);
5443 $el[0].style.opacity = 1;
5444 swiper.scrollbar.timeout = setTimeout(() => {
5445 $el[0].style.opacity = 0;
5446 $el.transition(400);
5447 }, 1000);
5448 }
5449 },
5450 setTransition(duration) {
5451 const swiper = this;
5452 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
5453 swiper.scrollbar.$dragEl.transition(duration);
5454 },
5455 updateSize() {
5456 const swiper = this;
5457 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
5458
5459 const { scrollbar } = swiper;
5460 const { $dragEl, $el } = scrollbar;
5461
5462 $dragEl[0].style.width = '';
5463 $dragEl[0].style.height = '';
5464 const trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;
5465
5466 const divider = swiper.size / swiper.virtualSize;
5467 const moveDivider = divider * (trackSize / swiper.size);
5468 let dragSize;
5469 if (swiper.params.scrollbar.dragSize === 'auto') {
5470 dragSize = trackSize * divider;
5471 } else {
5472 dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
5473 }
5474
5475 if (swiper.isHorizontal()) {
5476 $dragEl[0].style.width = `${dragSize}px`;
5477 } else {
5478 $dragEl[0].style.height = `${dragSize}px`;
5479 }
5480
5481 if (divider >= 1) {
5482 $el[0].style.display = 'none';
5483 } else {
5484 $el[0].style.display = '';
5485 }
5486 if (swiper.params.scrollbar.hide) {
5487 $el[0].style.opacity = 0;
5488 }
5489 Utils.extend(scrollbar, {
5490 trackSize,
5491 divider,
5492 moveDivider,
5493 dragSize,
5494 });
5495 scrollbar.$el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);
5496 },
5497 getPointerPosition(e) {
5498 const swiper = this;
5499 if (swiper.isHorizontal()) {
5500 return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientX : e.clientX);
5501 }
5502 return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientY : e.clientY);
5503 },
5504 setDragPosition(e) {
5505 const swiper = this;
5506 const { scrollbar, rtlTranslate: rtl } = swiper;
5507 const {
5508 $el,
5509 dragSize,
5510 trackSize,
5511 dragStartPos,
5512 } = scrollbar;
5513
5514 let positionRatio;
5515 positionRatio = ((scrollbar.getPointerPosition(e)) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top']
5516 - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
5517 positionRatio = Math.max(Math.min(positionRatio, 1), 0);
5518 if (rtl) {
5519 positionRatio = 1 - positionRatio;
5520 }
5521
5522 const position = swiper.minTranslate() + ((swiper.maxTranslate() - swiper.minTranslate()) * positionRatio);
5523
5524 swiper.updateProgress(position);
5525 swiper.setTranslate(position);
5526 swiper.updateActiveIndex();
5527 swiper.updateSlidesClasses();
5528 },
5529 onDragStart(e) {
5530 const swiper = this;
5531 const params = swiper.params.scrollbar;
5532 const { scrollbar, $wrapperEl } = swiper;
5533 const { $el, $dragEl } = scrollbar;
5534 swiper.scrollbar.isTouched = true;
5535 swiper.scrollbar.dragStartPos = (e.target === $dragEl[0] || e.target === $dragEl)
5536 ? scrollbar.getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
5537 e.preventDefault();
5538 e.stopPropagation();
5539
5540 $wrapperEl.transition(100);
5541 $dragEl.transition(100);
5542 scrollbar.setDragPosition(e);
5543
5544 clearTimeout(swiper.scrollbar.dragTimeout);
5545
5546 $el.transition(0);
5547 if (params.hide) {
5548 $el.css('opacity', 1);
5549 }
5550 if (swiper.params.cssMode) {
5551 swiper.$wrapperEl.css('scroll-snap-type', 'none');
5552 }
5553 swiper.emit('scrollbarDragStart', e);
5554 },
5555 onDragMove(e) {
5556 const swiper = this;
5557 const { scrollbar, $wrapperEl } = swiper;
5558 const { $el, $dragEl } = scrollbar;
5559
5560 if (!swiper.scrollbar.isTouched) return;
5561 if (e.preventDefault) e.preventDefault();
5562 else e.returnValue = false;
5563 scrollbar.setDragPosition(e);
5564 $wrapperEl.transition(0);
5565 $el.transition(0);
5566 $dragEl.transition(0);
5567 swiper.emit('scrollbarDragMove', e);
5568 },
5569 onDragEnd(e) {
5570 const swiper = this;
5571
5572 const params = swiper.params.scrollbar;
5573 const { scrollbar, $wrapperEl } = swiper;
5574 const { $el } = scrollbar;
5575
5576 if (!swiper.scrollbar.isTouched) return;
5577 swiper.scrollbar.isTouched = false;
5578 if (swiper.params.cssMode) {
5579 swiper.$wrapperEl.css('scroll-snap-type', '');
5580 $wrapperEl.transition('');
5581 }
5582 if (params.hide) {
5583 clearTimeout(swiper.scrollbar.dragTimeout);
5584 swiper.scrollbar.dragTimeout = Utils.nextTick(() => {
5585 $el.css('opacity', 0);
5586 $el.transition(400);
5587 }, 1000);
5588 }
5589 swiper.emit('scrollbarDragEnd', e);
5590 if (params.snapOnRelease) {
5591 swiper.slideToClosest();
5592 }
5593 },
5594 enableDraggable() {
5595 const swiper = this;
5596 if (!swiper.params.scrollbar.el) return;
5597 const {
5598 scrollbar, touchEventsTouch, touchEventsDesktop, params,
5599 } = swiper;
5600 const $el = scrollbar.$el;
5601 const target = $el[0];
5602 const activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
5603 const passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
5604 if (!Support.touch) {
5605 target.addEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
5606 doc.addEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
5607 doc.addEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
5608 } else {
5609 target.addEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
5610 target.addEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
5611 target.addEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
5612 }
5613 },
5614 disableDraggable() {
5615 const swiper = this;
5616 if (!swiper.params.scrollbar.el) return;
5617 const {
5618 scrollbar, touchEventsTouch, touchEventsDesktop, params,
5619 } = swiper;
5620 const $el = scrollbar.$el;
5621 const target = $el[0];
5622 const activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
5623 const passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
5624 if (!Support.touch) {
5625 target.removeEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
5626 doc.removeEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
5627 doc.removeEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
5628 } else {
5629 target.removeEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
5630 target.removeEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
5631 target.removeEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
5632 }
5633 },
5634 init() {
5635 const swiper = this;
5636 if (!swiper.params.scrollbar.el) return;
5637 const { scrollbar, $el: $swiperEl } = swiper;
5638 const params = swiper.params.scrollbar;
5639
5640 let $el = $(params.el);
5641 if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {
5642 $el = $swiperEl.find(params.el);
5643 }
5644
5645 let $dragEl = $el.find(`.${swiper.params.scrollbar.dragClass}`);
5646 if ($dragEl.length === 0) {
5647 $dragEl = $(`<div class="${swiper.params.scrollbar.dragClass}"></div>`);
5648 $el.append($dragEl);
5649 }
5650
5651 Utils.extend(scrollbar, {
5652 $el,
5653 el: $el[0],
5654 $dragEl,
5655 dragEl: $dragEl[0],
5656 });
5657
5658 if (params.draggable) {
5659 scrollbar.enableDraggable();
5660 }
5661 },
5662 destroy() {
5663 const swiper = this;
5664 swiper.scrollbar.disableDraggable();
5665 },
5666};
5667
5668var Scrollbar$1 = {
5669 name: 'scrollbar',
5670 params: {
5671 scrollbar: {
5672 el: null,
5673 dragSize: 'auto',
5674 hide: false,
5675 draggable: false,
5676 snapOnRelease: true,
5677 lockClass: 'swiper-scrollbar-lock',
5678 dragClass: 'swiper-scrollbar-drag',
5679 },
5680 },
5681 create() {
5682 const swiper = this;
5683 Utils.extend(swiper, {
5684 scrollbar: {
5685 init: Scrollbar.init.bind(swiper),
5686 destroy: Scrollbar.destroy.bind(swiper),
5687 updateSize: Scrollbar.updateSize.bind(swiper),
5688 setTranslate: Scrollbar.setTranslate.bind(swiper),
5689 setTransition: Scrollbar.setTransition.bind(swiper),
5690 enableDraggable: Scrollbar.enableDraggable.bind(swiper),
5691 disableDraggable: Scrollbar.disableDraggable.bind(swiper),
5692 setDragPosition: Scrollbar.setDragPosition.bind(swiper),
5693 getPointerPosition: Scrollbar.getPointerPosition.bind(swiper),
5694 onDragStart: Scrollbar.onDragStart.bind(swiper),
5695 onDragMove: Scrollbar.onDragMove.bind(swiper),
5696 onDragEnd: Scrollbar.onDragEnd.bind(swiper),
5697 isTouched: false,
5698 timeout: null,
5699 dragTimeout: null,
5700 },
5701 });
5702 },
5703 on: {
5704 init() {
5705 const swiper = this;
5706 swiper.scrollbar.init();
5707 swiper.scrollbar.updateSize();
5708 swiper.scrollbar.setTranslate();
5709 },
5710 update() {
5711 const swiper = this;
5712 swiper.scrollbar.updateSize();
5713 },
5714 resize() {
5715 const swiper = this;
5716 swiper.scrollbar.updateSize();
5717 },
5718 observerUpdate() {
5719 const swiper = this;
5720 swiper.scrollbar.updateSize();
5721 },
5722 setTranslate() {
5723 const swiper = this;
5724 swiper.scrollbar.setTranslate();
5725 },
5726 setTransition(duration) {
5727 const swiper = this;
5728 swiper.scrollbar.setTransition(duration);
5729 },
5730 destroy() {
5731 const swiper = this;
5732 swiper.scrollbar.destroy();
5733 },
5734 },
5735};
5736
5737const Parallax = {
5738 setTransform(el, progress) {
5739 const swiper = this;
5740 const { rtl } = swiper;
5741
5742 const $el = $(el);
5743 const rtlFactor = rtl ? -1 : 1;
5744
5745 const p = $el.attr('data-swiper-parallax') || '0';
5746 let x = $el.attr('data-swiper-parallax-x');
5747 let y = $el.attr('data-swiper-parallax-y');
5748 const scale = $el.attr('data-swiper-parallax-scale');
5749 const opacity = $el.attr('data-swiper-parallax-opacity');
5750
5751 if (x || y) {
5752 x = x || '0';
5753 y = y || '0';
5754 } else if (swiper.isHorizontal()) {
5755 x = p;
5756 y = '0';
5757 } else {
5758 y = p;
5759 x = '0';
5760 }
5761
5762 if ((x).indexOf('%') >= 0) {
5763 x = `${parseInt(x, 10) * progress * rtlFactor}%`;
5764 } else {
5765 x = `${x * progress * rtlFactor}px`;
5766 }
5767 if ((y).indexOf('%') >= 0) {
5768 y = `${parseInt(y, 10) * progress}%`;
5769 } else {
5770 y = `${y * progress}px`;
5771 }
5772
5773 if (typeof opacity !== 'undefined' && opacity !== null) {
5774 const currentOpacity = opacity - ((opacity - 1) * (1 - Math.abs(progress)));
5775 $el[0].style.opacity = currentOpacity;
5776 }
5777 if (typeof scale === 'undefined' || scale === null) {
5778 $el.transform(`translate3d(${x}, ${y}, 0px)`);
5779 } else {
5780 const currentScale = scale - ((scale - 1) * (1 - Math.abs(progress)));
5781 $el.transform(`translate3d(${x}, ${y}, 0px) scale(${currentScale})`);
5782 }
5783 },
5784 setTranslate() {
5785 const swiper = this;
5786 const {
5787 $el, slides, progress, snapGrid,
5788 } = swiper;
5789 $el.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
5790 .each((index, el) => {
5791 swiper.parallax.setTransform(el, progress);
5792 });
5793 slides.each((slideIndex, slideEl) => {
5794 let slideProgress = slideEl.progress;
5795 if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {
5796 slideProgress += Math.ceil(slideIndex / 2) - (progress * (snapGrid.length - 1));
5797 }
5798 slideProgress = Math.min(Math.max(slideProgress, -1), 1);
5799 $(slideEl).find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
5800 .each((index, el) => {
5801 swiper.parallax.setTransform(el, slideProgress);
5802 });
5803 });
5804 },
5805 setTransition(duration = this.params.speed) {
5806 const swiper = this;
5807 const { $el } = swiper;
5808 $el.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
5809 .each((index, parallaxEl) => {
5810 const $parallaxEl = $(parallaxEl);
5811 let parallaxDuration = parseInt($parallaxEl.attr('data-swiper-parallax-duration'), 10) || duration;
5812 if (duration === 0) parallaxDuration = 0;
5813 $parallaxEl.transition(parallaxDuration);
5814 });
5815 },
5816};
5817
5818var Parallax$1 = {
5819 name: 'parallax',
5820 params: {
5821 parallax: {
5822 enabled: false,
5823 },
5824 },
5825 create() {
5826 const swiper = this;
5827 Utils.extend(swiper, {
5828 parallax: {
5829 setTransform: Parallax.setTransform.bind(swiper),
5830 setTranslate: Parallax.setTranslate.bind(swiper),
5831 setTransition: Parallax.setTransition.bind(swiper),
5832 },
5833 });
5834 },
5835 on: {
5836 beforeInit() {
5837 const swiper = this;
5838 if (!swiper.params.parallax.enabled) return;
5839 swiper.params.watchSlidesProgress = true;
5840 swiper.originalParams.watchSlidesProgress = true;
5841 },
5842 init() {
5843 const swiper = this;
5844 if (!swiper.params.parallax.enabled) return;
5845 swiper.parallax.setTranslate();
5846 },
5847 setTranslate() {
5848 const swiper = this;
5849 if (!swiper.params.parallax.enabled) return;
5850 swiper.parallax.setTranslate();
5851 },
5852 setTransition(duration) {
5853 const swiper = this;
5854 if (!swiper.params.parallax.enabled) return;
5855 swiper.parallax.setTransition(duration);
5856 },
5857 },
5858};
5859
5860const Zoom = {
5861 // Calc Scale From Multi-touches
5862 getDistanceBetweenTouches(e) {
5863 if (e.targetTouches.length < 2) return 1;
5864 const x1 = e.targetTouches[0].pageX;
5865 const y1 = e.targetTouches[0].pageY;
5866 const x2 = e.targetTouches[1].pageX;
5867 const y2 = e.targetTouches[1].pageY;
5868 const distance = Math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2));
5869 return distance;
5870 },
5871 // Events
5872 onGestureStart(e) {
5873 const swiper = this;
5874 const params = swiper.params.zoom;
5875 const zoom = swiper.zoom;
5876 const { gesture } = zoom;
5877 zoom.fakeGestureTouched = false;
5878 zoom.fakeGestureMoved = false;
5879 if (!Support.gestures) {
5880 if (e.type !== 'touchstart' || (e.type === 'touchstart' && e.targetTouches.length < 2)) {
5881 return;
5882 }
5883 zoom.fakeGestureTouched = true;
5884 gesture.scaleStart = Zoom.getDistanceBetweenTouches(e);
5885 }
5886 if (!gesture.$slideEl || !gesture.$slideEl.length) {
5887 gesture.$slideEl = $(e.target).closest('.swiper-slide');
5888 if (gesture.$slideEl.length === 0) gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
5889 gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
5890 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
5891 gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
5892 if (gesture.$imageWrapEl.length === 0) {
5893 gesture.$imageEl = undefined;
5894 return;
5895 }
5896 }
5897 gesture.$imageEl.transition(0);
5898 swiper.zoom.isScaling = true;
5899 },
5900 onGestureChange(e) {
5901 const swiper = this;
5902 const params = swiper.params.zoom;
5903 const zoom = swiper.zoom;
5904 const { gesture } = zoom;
5905 if (!Support.gestures) {
5906 if (e.type !== 'touchmove' || (e.type === 'touchmove' && e.targetTouches.length < 2)) {
5907 return;
5908 }
5909 zoom.fakeGestureMoved = true;
5910 gesture.scaleMove = Zoom.getDistanceBetweenTouches(e);
5911 }
5912 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
5913 if (Support.gestures) {
5914 zoom.scale = e.scale * zoom.currentScale;
5915 } else {
5916 zoom.scale = (gesture.scaleMove / gesture.scaleStart) * zoom.currentScale;
5917 }
5918 if (zoom.scale > gesture.maxRatio) {
5919 zoom.scale = (gesture.maxRatio - 1) + (((zoom.scale - gesture.maxRatio) + 1) ** 0.5);
5920 }
5921 if (zoom.scale < params.minRatio) {
5922 zoom.scale = (params.minRatio + 1) - (((params.minRatio - zoom.scale) + 1) ** 0.5);
5923 }
5924 gesture.$imageEl.transform(`translate3d(0,0,0) scale(${zoom.scale})`);
5925 },
5926 onGestureEnd(e) {
5927 const swiper = this;
5928 const params = swiper.params.zoom;
5929 const zoom = swiper.zoom;
5930 const { gesture } = zoom;
5931 if (!Support.gestures) {
5932 if (!zoom.fakeGestureTouched || !zoom.fakeGestureMoved) {
5933 return;
5934 }
5935 if (e.type !== 'touchend' || (e.type === 'touchend' && e.changedTouches.length < 2 && !Device.android)) {
5936 return;
5937 }
5938 zoom.fakeGestureTouched = false;
5939 zoom.fakeGestureMoved = false;
5940 }
5941 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
5942 zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
5943 gesture.$imageEl.transition(swiper.params.speed).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
5944 zoom.currentScale = zoom.scale;
5945 zoom.isScaling = false;
5946 if (zoom.scale === 1) gesture.$slideEl = undefined;
5947 },
5948 onTouchStart(e) {
5949 const swiper = this;
5950 const zoom = swiper.zoom;
5951 const { gesture, image } = zoom;
5952 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
5953 if (image.isTouched) return;
5954 if (Device.android) e.preventDefault();
5955 image.isTouched = true;
5956 image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
5957 image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
5958 },
5959 onTouchMove(e) {
5960 const swiper = this;
5961 const zoom = swiper.zoom;
5962 const { gesture, image, velocity } = zoom;
5963 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
5964 swiper.allowClick = false;
5965 if (!image.isTouched || !gesture.$slideEl) return;
5966
5967 if (!image.isMoved) {
5968 image.width = gesture.$imageEl[0].offsetWidth;
5969 image.height = gesture.$imageEl[0].offsetHeight;
5970 image.startX = Utils.getTranslate(gesture.$imageWrapEl[0], 'x') || 0;
5971 image.startY = Utils.getTranslate(gesture.$imageWrapEl[0], 'y') || 0;
5972 gesture.slideWidth = gesture.$slideEl[0].offsetWidth;
5973 gesture.slideHeight = gesture.$slideEl[0].offsetHeight;
5974 gesture.$imageWrapEl.transition(0);
5975 if (swiper.rtl) {
5976 image.startX = -image.startX;
5977 image.startY = -image.startY;
5978 }
5979 }
5980 // Define if we need image drag
5981 const scaledWidth = image.width * zoom.scale;
5982 const scaledHeight = image.height * zoom.scale;
5983
5984 if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) return;
5985
5986 image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
5987 image.maxX = -image.minX;
5988 image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
5989 image.maxY = -image.minY;
5990
5991 image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
5992 image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
5993
5994 if (!image.isMoved && !zoom.isScaling) {
5995 if (
5996 swiper.isHorizontal()
5997 && (
5998 (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x)
5999 || (Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)
6000 )
6001 ) {
6002 image.isTouched = false;
6003 return;
6004 } if (
6005 !swiper.isHorizontal()
6006 && (
6007 (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y)
6008 || (Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)
6009 )
6010 ) {
6011 image.isTouched = false;
6012 return;
6013 }
6014 }
6015 e.preventDefault();
6016 e.stopPropagation();
6017
6018 image.isMoved = true;
6019 image.currentX = (image.touchesCurrent.x - image.touchesStart.x) + image.startX;
6020 image.currentY = (image.touchesCurrent.y - image.touchesStart.y) + image.startY;
6021
6022 if (image.currentX < image.minX) {
6023 image.currentX = (image.minX + 1) - (((image.minX - image.currentX) + 1) ** 0.8);
6024 }
6025 if (image.currentX > image.maxX) {
6026 image.currentX = (image.maxX - 1) + (((image.currentX - image.maxX) + 1) ** 0.8);
6027 }
6028
6029 if (image.currentY < image.minY) {
6030 image.currentY = (image.minY + 1) - (((image.minY - image.currentY) + 1) ** 0.8);
6031 }
6032 if (image.currentY > image.maxY) {
6033 image.currentY = (image.maxY - 1) + (((image.currentY - image.maxY) + 1) ** 0.8);
6034 }
6035
6036 // Velocity
6037 if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x;
6038 if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y;
6039 if (!velocity.prevTime) velocity.prevTime = Date.now();
6040 velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
6041 velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
6042 if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0;
6043 if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0;
6044 velocity.prevPositionX = image.touchesCurrent.x;
6045 velocity.prevPositionY = image.touchesCurrent.y;
6046 velocity.prevTime = Date.now();
6047
6048 gesture.$imageWrapEl.transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
6049 },
6050 onTouchEnd() {
6051 const swiper = this;
6052 const zoom = swiper.zoom;
6053 const { gesture, image, velocity } = zoom;
6054 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6055 if (!image.isTouched || !image.isMoved) {
6056 image.isTouched = false;
6057 image.isMoved = false;
6058 return;
6059 }
6060 image.isTouched = false;
6061 image.isMoved = false;
6062 let momentumDurationX = 300;
6063 let momentumDurationY = 300;
6064 const momentumDistanceX = velocity.x * momentumDurationX;
6065 const newPositionX = image.currentX + momentumDistanceX;
6066 const momentumDistanceY = velocity.y * momentumDurationY;
6067 const newPositionY = image.currentY + momentumDistanceY;
6068
6069 // Fix duration
6070 if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x);
6071 if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y);
6072 const momentumDuration = Math.max(momentumDurationX, momentumDurationY);
6073
6074 image.currentX = newPositionX;
6075 image.currentY = newPositionY;
6076
6077 // Define if we need image drag
6078 const scaledWidth = image.width * zoom.scale;
6079 const scaledHeight = image.height * zoom.scale;
6080 image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
6081 image.maxX = -image.minX;
6082 image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
6083 image.maxY = -image.minY;
6084 image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
6085 image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
6086
6087 gesture.$imageWrapEl.transition(momentumDuration).transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
6088 },
6089 onTransitionEnd() {
6090 const swiper = this;
6091 const zoom = swiper.zoom;
6092 const { gesture } = zoom;
6093 if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {
6094 gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');
6095 gesture.$imageWrapEl.transform('translate3d(0,0,0)');
6096
6097 zoom.scale = 1;
6098 zoom.currentScale = 1;
6099
6100 gesture.$slideEl = undefined;
6101 gesture.$imageEl = undefined;
6102 gesture.$imageWrapEl = undefined;
6103 }
6104 },
6105 // Toggle Zoom
6106 toggle(e) {
6107 const swiper = this;
6108 const zoom = swiper.zoom;
6109
6110 if (zoom.scale && zoom.scale !== 1) {
6111 // Zoom Out
6112 zoom.out();
6113 } else {
6114 // Zoom In
6115 zoom.in(e);
6116 }
6117 },
6118 in(e) {
6119 const swiper = this;
6120
6121 const zoom = swiper.zoom;
6122 const params = swiper.params.zoom;
6123 const { gesture, image } = zoom;
6124
6125 if (!gesture.$slideEl) {
6126 gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
6127 gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
6128 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
6129 }
6130 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6131
6132 gesture.$slideEl.addClass(`${params.zoomedSlideClass}`);
6133
6134 let touchX;
6135 let touchY;
6136 let offsetX;
6137 let offsetY;
6138 let diffX;
6139 let diffY;
6140 let translateX;
6141 let translateY;
6142 let imageWidth;
6143 let imageHeight;
6144 let scaledWidth;
6145 let scaledHeight;
6146 let translateMinX;
6147 let translateMinY;
6148 let translateMaxX;
6149 let translateMaxY;
6150 let slideWidth;
6151 let slideHeight;
6152
6153 if (typeof image.touchesStart.x === 'undefined' && e) {
6154 touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
6155 touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
6156 } else {
6157 touchX = image.touchesStart.x;
6158 touchY = image.touchesStart.y;
6159 }
6160
6161 zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
6162 zoom.currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
6163 if (e) {
6164 slideWidth = gesture.$slideEl[0].offsetWidth;
6165 slideHeight = gesture.$slideEl[0].offsetHeight;
6166 offsetX = gesture.$slideEl.offset().left;
6167 offsetY = gesture.$slideEl.offset().top;
6168 diffX = (offsetX + (slideWidth / 2)) - touchX;
6169 diffY = (offsetY + (slideHeight / 2)) - touchY;
6170
6171 imageWidth = gesture.$imageEl[0].offsetWidth;
6172 imageHeight = gesture.$imageEl[0].offsetHeight;
6173 scaledWidth = imageWidth * zoom.scale;
6174 scaledHeight = imageHeight * zoom.scale;
6175
6176 translateMinX = Math.min(((slideWidth / 2) - (scaledWidth / 2)), 0);
6177 translateMinY = Math.min(((slideHeight / 2) - (scaledHeight / 2)), 0);
6178 translateMaxX = -translateMinX;
6179 translateMaxY = -translateMinY;
6180
6181 translateX = diffX * zoom.scale;
6182 translateY = diffY * zoom.scale;
6183
6184 if (translateX < translateMinX) {
6185 translateX = translateMinX;
6186 }
6187 if (translateX > translateMaxX) {
6188 translateX = translateMaxX;
6189 }
6190
6191 if (translateY < translateMinY) {
6192 translateY = translateMinY;
6193 }
6194 if (translateY > translateMaxY) {
6195 translateY = translateMaxY;
6196 }
6197 } else {
6198 translateX = 0;
6199 translateY = 0;
6200 }
6201 gesture.$imageWrapEl.transition(300).transform(`translate3d(${translateX}px, ${translateY}px,0)`);
6202 gesture.$imageEl.transition(300).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
6203 },
6204 out() {
6205 const swiper = this;
6206
6207 const zoom = swiper.zoom;
6208 const params = swiper.params.zoom;
6209 const { gesture } = zoom;
6210
6211 if (!gesture.$slideEl) {
6212 gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
6213 gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
6214 gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
6215 }
6216 if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
6217
6218 zoom.scale = 1;
6219 zoom.currentScale = 1;
6220 gesture.$imageWrapEl.transition(300).transform('translate3d(0,0,0)');
6221 gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');
6222 gesture.$slideEl.removeClass(`${params.zoomedSlideClass}`);
6223 gesture.$slideEl = undefined;
6224 },
6225 // Attach/Detach Events
6226 enable() {
6227 const swiper = this;
6228 const zoom = swiper.zoom;
6229 if (zoom.enabled) return;
6230 zoom.enabled = true;
6231
6232 const passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
6233 const activeListenerWithCapture = Support.passiveListener ? { passive: false, capture: true } : true;
6234
6235 // Scale image
6236 if (Support.gestures) {
6237 swiper.$wrapperEl.on('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
6238 swiper.$wrapperEl.on('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
6239 swiper.$wrapperEl.on('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
6240 } else if (swiper.touchEvents.start === 'touchstart') {
6241 swiper.$wrapperEl.on(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
6242 swiper.$wrapperEl.on(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, passiveListener);
6243 swiper.$wrapperEl.on(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
6244 if (swiper.touchEvents.cancel) {
6245 swiper.$wrapperEl.on(swiper.touchEvents.cancel, '.swiper-slide', zoom.onGestureEnd, passiveListener);
6246 }
6247 }
6248
6249 // Move image
6250 swiper.$wrapperEl.on(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, zoom.onTouchMove, activeListenerWithCapture);
6251 },
6252 disable() {
6253 const swiper = this;
6254 const zoom = swiper.zoom;
6255 if (!zoom.enabled) return;
6256
6257 swiper.zoom.enabled = false;
6258
6259 const passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
6260 const activeListenerWithCapture = Support.passiveListener ? { passive: false, capture: true } : true;
6261
6262 // Scale image
6263 if (Support.gestures) {
6264 swiper.$wrapperEl.off('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
6265 swiper.$wrapperEl.off('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
6266 swiper.$wrapperEl.off('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
6267 } else if (swiper.touchEvents.start === 'touchstart') {
6268 swiper.$wrapperEl.off(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
6269 swiper.$wrapperEl.off(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, passiveListener);
6270 swiper.$wrapperEl.off(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
6271 if (swiper.touchEvents.cancel) {
6272 swiper.$wrapperEl.off(swiper.touchEvents.cancel, '.swiper-slide', zoom.onGestureEnd, passiveListener);
6273 }
6274 }
6275
6276 // Move image
6277 swiper.$wrapperEl.off(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, zoom.onTouchMove, activeListenerWithCapture);
6278 },
6279};
6280
6281var Zoom$1 = {
6282 name: 'zoom',
6283 params: {
6284 zoom: {
6285 enabled: false,
6286 maxRatio: 3,
6287 minRatio: 1,
6288 toggle: true,
6289 containerClass: 'swiper-zoom-container',
6290 zoomedSlideClass: 'swiper-slide-zoomed',
6291 },
6292 },
6293 create() {
6294 const swiper = this;
6295 const zoom = {
6296 enabled: false,
6297 scale: 1,
6298 currentScale: 1,
6299 isScaling: false,
6300 gesture: {
6301 $slideEl: undefined,
6302 slideWidth: undefined,
6303 slideHeight: undefined,
6304 $imageEl: undefined,
6305 $imageWrapEl: undefined,
6306 maxRatio: 3,
6307 },
6308 image: {
6309 isTouched: undefined,
6310 isMoved: undefined,
6311 currentX: undefined,
6312 currentY: undefined,
6313 minX: undefined,
6314 minY: undefined,
6315 maxX: undefined,
6316 maxY: undefined,
6317 width: undefined,
6318 height: undefined,
6319 startX: undefined,
6320 startY: undefined,
6321 touchesStart: {},
6322 touchesCurrent: {},
6323 },
6324 velocity: {
6325 x: undefined,
6326 y: undefined,
6327 prevPositionX: undefined,
6328 prevPositionY: undefined,
6329 prevTime: undefined,
6330 },
6331 };
6332
6333 ('onGestureStart onGestureChange onGestureEnd onTouchStart onTouchMove onTouchEnd onTransitionEnd toggle enable disable in out').split(' ').forEach((methodName) => {
6334 zoom[methodName] = Zoom[methodName].bind(swiper);
6335 });
6336 Utils.extend(swiper, {
6337 zoom,
6338 });
6339
6340 let scale = 1;
6341 Object.defineProperty(swiper.zoom, 'scale', {
6342 get() {
6343 return scale;
6344 },
6345 set(value) {
6346 if (scale !== value) {
6347 const imageEl = swiper.zoom.gesture.$imageEl ? swiper.zoom.gesture.$imageEl[0] : undefined;
6348 const slideEl = swiper.zoom.gesture.$slideEl ? swiper.zoom.gesture.$slideEl[0] : undefined;
6349 swiper.emit('zoomChange', value, imageEl, slideEl);
6350 }
6351 scale = value;
6352 },
6353 });
6354 },
6355 on: {
6356 init() {
6357 const swiper = this;
6358 if (swiper.params.zoom.enabled) {
6359 swiper.zoom.enable();
6360 }
6361 },
6362 destroy() {
6363 const swiper = this;
6364 swiper.zoom.disable();
6365 },
6366 touchStart(e) {
6367 const swiper = this;
6368 if (!swiper.zoom.enabled) return;
6369 swiper.zoom.onTouchStart(e);
6370 },
6371 touchEnd(e) {
6372 const swiper = this;
6373 if (!swiper.zoom.enabled) return;
6374 swiper.zoom.onTouchEnd(e);
6375 },
6376 doubleTap(e) {
6377 const swiper = this;
6378 if (swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
6379 swiper.zoom.toggle(e);
6380 }
6381 },
6382 transitionEnd() {
6383 const swiper = this;
6384 if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
6385 swiper.zoom.onTransitionEnd();
6386 }
6387 },
6388 slideChange() {
6389 const swiper = this;
6390 if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {
6391 swiper.zoom.onTransitionEnd();
6392 }
6393 },
6394 },
6395};
6396
6397const Lazy = {
6398 loadInSlide(index, loadInDuplicate = true) {
6399 const swiper = this;
6400 const params = swiper.params.lazy;
6401 if (typeof index === 'undefined') return;
6402 if (swiper.slides.length === 0) return;
6403 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
6404
6405 const $slideEl = isVirtual
6406 ? swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-swiper-slide-index="${index}"]`)
6407 : swiper.slides.eq(index);
6408
6409 let $images = $slideEl.find(`.${params.elementClass}:not(.${params.loadedClass}):not(.${params.loadingClass})`);
6410 if ($slideEl.hasClass(params.elementClass) && !$slideEl.hasClass(params.loadedClass) && !$slideEl.hasClass(params.loadingClass)) {
6411 $images = $images.add($slideEl[0]);
6412 }
6413 if ($images.length === 0) return;
6414
6415 $images.each((imageIndex, imageEl) => {
6416 const $imageEl = $(imageEl);
6417 $imageEl.addClass(params.loadingClass);
6418
6419 const background = $imageEl.attr('data-background');
6420 const src = $imageEl.attr('data-src');
6421 const srcset = $imageEl.attr('data-srcset');
6422 const sizes = $imageEl.attr('data-sizes');
6423
6424 swiper.loadImage($imageEl[0], (src || background), srcset, sizes, false, () => {
6425 if (typeof swiper === 'undefined' || swiper === null || !swiper || (swiper && !swiper.params) || swiper.destroyed) return;
6426 if (background) {
6427 $imageEl.css('background-image', `url("${background}")`);
6428 $imageEl.removeAttr('data-background');
6429 } else {
6430 if (srcset) {
6431 $imageEl.attr('srcset', srcset);
6432 $imageEl.removeAttr('data-srcset');
6433 }
6434 if (sizes) {
6435 $imageEl.attr('sizes', sizes);
6436 $imageEl.removeAttr('data-sizes');
6437 }
6438 if (src) {
6439 $imageEl.attr('src', src);
6440 $imageEl.removeAttr('data-src');
6441 }
6442 }
6443
6444 $imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);
6445 $slideEl.find(`.${params.preloaderClass}`).remove();
6446 if (swiper.params.loop && loadInDuplicate) {
6447 const slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');
6448 if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {
6449 const originalSlide = swiper.$wrapperEl.children(`[data-swiper-slide-index="${slideOriginalIndex}"]:not(.${swiper.params.slideDuplicateClass})`);
6450 swiper.lazy.loadInSlide(originalSlide.index(), false);
6451 } else {
6452 const duplicatedSlide = swiper.$wrapperEl.children(`.${swiper.params.slideDuplicateClass}[data-swiper-slide-index="${slideOriginalIndex}"]`);
6453 swiper.lazy.loadInSlide(duplicatedSlide.index(), false);
6454 }
6455 }
6456 swiper.emit('lazyImageReady', $slideEl[0], $imageEl[0]);
6457 });
6458
6459 swiper.emit('lazyImageLoad', $slideEl[0], $imageEl[0]);
6460 });
6461 },
6462 load() {
6463 const swiper = this;
6464 const {
6465 $wrapperEl, params: swiperParams, slides, activeIndex,
6466 } = swiper;
6467 const isVirtual = swiper.virtual && swiperParams.virtual.enabled;
6468 const params = swiperParams.lazy;
6469
6470 let slidesPerView = swiperParams.slidesPerView;
6471 if (slidesPerView === 'auto') {
6472 slidesPerView = 0;
6473 }
6474
6475 function slideExist(index) {
6476 if (isVirtual) {
6477 if ($wrapperEl.children(`.${swiperParams.slideClass}[data-swiper-slide-index="${index}"]`).length) {
6478 return true;
6479 }
6480 } else if (slides[index]) return true;
6481 return false;
6482 }
6483 function slideIndex(slideEl) {
6484 if (isVirtual) {
6485 return $(slideEl).attr('data-swiper-slide-index');
6486 }
6487 return $(slideEl).index();
6488 }
6489
6490 if (!swiper.lazy.initialImageLoaded) swiper.lazy.initialImageLoaded = true;
6491 if (swiper.params.watchSlidesVisibility) {
6492 $wrapperEl.children(`.${swiperParams.slideVisibleClass}`).each((elIndex, slideEl) => {
6493 const index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();
6494 swiper.lazy.loadInSlide(index);
6495 });
6496 } else if (slidesPerView > 1) {
6497 for (let i = activeIndex; i < activeIndex + slidesPerView; i += 1) {
6498 if (slideExist(i)) swiper.lazy.loadInSlide(i);
6499 }
6500 } else {
6501 swiper.lazy.loadInSlide(activeIndex);
6502 }
6503 if (params.loadPrevNext) {
6504 if (slidesPerView > 1 || (params.loadPrevNextAmount && params.loadPrevNextAmount > 1)) {
6505 const amount = params.loadPrevNextAmount;
6506 const spv = slidesPerView;
6507 const maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);
6508 const minIndex = Math.max(activeIndex - Math.max(spv, amount), 0);
6509 // Next Slides
6510 for (let i = activeIndex + slidesPerView; i < maxIndex; i += 1) {
6511 if (slideExist(i)) swiper.lazy.loadInSlide(i);
6512 }
6513 // Prev Slides
6514 for (let i = minIndex; i < activeIndex; i += 1) {
6515 if (slideExist(i)) swiper.lazy.loadInSlide(i);
6516 }
6517 } else {
6518 const nextSlide = $wrapperEl.children(`.${swiperParams.slideNextClass}`);
6519 if (nextSlide.length > 0) swiper.lazy.loadInSlide(slideIndex(nextSlide));
6520
6521 const prevSlide = $wrapperEl.children(`.${swiperParams.slidePrevClass}`);
6522 if (prevSlide.length > 0) swiper.lazy.loadInSlide(slideIndex(prevSlide));
6523 }
6524 }
6525 },
6526};
6527
6528var Lazy$1 = {
6529 name: 'lazy',
6530 params: {
6531 lazy: {
6532 enabled: false,
6533 loadPrevNext: false,
6534 loadPrevNextAmount: 1,
6535 loadOnTransitionStart: false,
6536
6537 elementClass: 'swiper-lazy',
6538 loadingClass: 'swiper-lazy-loading',
6539 loadedClass: 'swiper-lazy-loaded',
6540 preloaderClass: 'swiper-lazy-preloader',
6541 },
6542 },
6543 create() {
6544 const swiper = this;
6545 Utils.extend(swiper, {
6546 lazy: {
6547 initialImageLoaded: false,
6548 load: Lazy.load.bind(swiper),
6549 loadInSlide: Lazy.loadInSlide.bind(swiper),
6550 },
6551 });
6552 },
6553 on: {
6554 beforeInit() {
6555 const swiper = this;
6556 if (swiper.params.lazy.enabled && swiper.params.preloadImages) {
6557 swiper.params.preloadImages = false;
6558 }
6559 },
6560 init() {
6561 const swiper = this;
6562 if (swiper.params.lazy.enabled && !swiper.params.loop && swiper.params.initialSlide === 0) {
6563 swiper.lazy.load();
6564 }
6565 },
6566 scroll() {
6567 const swiper = this;
6568 if (swiper.params.freeMode && !swiper.params.freeModeSticky) {
6569 swiper.lazy.load();
6570 }
6571 },
6572 resize() {
6573 const swiper = this;
6574 if (swiper.params.lazy.enabled) {
6575 swiper.lazy.load();
6576 }
6577 },
6578 scrollbarDragMove() {
6579 const swiper = this;
6580 if (swiper.params.lazy.enabled) {
6581 swiper.lazy.load();
6582 }
6583 },
6584 transitionStart() {
6585 const swiper = this;
6586 if (swiper.params.lazy.enabled) {
6587 if (swiper.params.lazy.loadOnTransitionStart || (!swiper.params.lazy.loadOnTransitionStart && !swiper.lazy.initialImageLoaded)) {
6588 swiper.lazy.load();
6589 }
6590 }
6591 },
6592 transitionEnd() {
6593 const swiper = this;
6594 if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {
6595 swiper.lazy.load();
6596 }
6597 },
6598 slideChange() {
6599 const swiper = this;
6600 if (swiper.params.lazy.enabled && swiper.params.cssMode) {
6601 swiper.lazy.load();
6602 }
6603 },
6604 },
6605};
6606
6607/* eslint no-bitwise: ["error", { "allow": [">>"] }] */
6608
6609const Controller = {
6610 LinearSpline: function LinearSpline(x, y) {
6611 const binarySearch = (function search() {
6612 let maxIndex;
6613 let minIndex;
6614 let guess;
6615 return (array, val) => {
6616 minIndex = -1;
6617 maxIndex = array.length;
6618 while (maxIndex - minIndex > 1) {
6619 guess = maxIndex + minIndex >> 1;
6620 if (array[guess] <= val) {
6621 minIndex = guess;
6622 } else {
6623 maxIndex = guess;
6624 }
6625 }
6626 return maxIndex;
6627 };
6628 }());
6629 this.x = x;
6630 this.y = y;
6631 this.lastIndex = x.length - 1;
6632 // Given an x value (x2), return the expected y2 value:
6633 // (x1,y1) is the known point before given value,
6634 // (x3,y3) is the known point after given value.
6635 let i1;
6636 let i3;
6637
6638 this.interpolate = function interpolate(x2) {
6639 if (!x2) return 0;
6640
6641 // Get the indexes of x1 and x3 (the array indexes before and after given x2):
6642 i3 = binarySearch(this.x, x2);
6643 i1 = i3 - 1;
6644
6645 // We have our indexes i1 & i3, so we can calculate already:
6646 // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
6647 return (((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1])) + this.y[i1];
6648 };
6649 return this;
6650 },
6651 // xxx: for now i will just save one spline function to to
6652 getInterpolateFunction(c) {
6653 const swiper = this;
6654 if (!swiper.controller.spline) {
6655 swiper.controller.spline = swiper.params.loop
6656 ? new Controller.LinearSpline(swiper.slidesGrid, c.slidesGrid)
6657 : new Controller.LinearSpline(swiper.snapGrid, c.snapGrid);
6658 }
6659 },
6660 setTranslate(setTranslate, byController) {
6661 const swiper = this;
6662 const controlled = swiper.controller.control;
6663 let multiplier;
6664 let controlledTranslate;
6665 function setControlledTranslate(c) {
6666 // this will create an Interpolate function based on the snapGrids
6667 // x is the Grid of the scrolled scroller and y will be the controlled scroller
6668 // it makes sense to create this only once and recall it for the interpolation
6669 // the function does a lot of value caching for performance
6670 const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
6671 if (swiper.params.controller.by === 'slide') {
6672 swiper.controller.getInterpolateFunction(c);
6673 // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
6674 // but it did not work out
6675 controlledTranslate = -swiper.controller.spline.interpolate(-translate);
6676 }
6677
6678 if (!controlledTranslate || swiper.params.controller.by === 'container') {
6679 multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
6680 controlledTranslate = ((translate - swiper.minTranslate()) * multiplier) + c.minTranslate();
6681 }
6682
6683 if (swiper.params.controller.inverse) {
6684 controlledTranslate = c.maxTranslate() - controlledTranslate;
6685 }
6686 c.updateProgress(controlledTranslate);
6687 c.setTranslate(controlledTranslate, swiper);
6688 c.updateActiveIndex();
6689 c.updateSlidesClasses();
6690 }
6691 if (Array.isArray(controlled)) {
6692 for (let i = 0; i < controlled.length; i += 1) {
6693 if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
6694 setControlledTranslate(controlled[i]);
6695 }
6696 }
6697 } else if (controlled instanceof Swiper && byController !== controlled) {
6698 setControlledTranslate(controlled);
6699 }
6700 },
6701 setTransition(duration, byController) {
6702 const swiper = this;
6703 const controlled = swiper.controller.control;
6704 let i;
6705 function setControlledTransition(c) {
6706 c.setTransition(duration, swiper);
6707 if (duration !== 0) {
6708 c.transitionStart();
6709 if (c.params.autoHeight) {
6710 Utils.nextTick(() => {
6711 c.updateAutoHeight();
6712 });
6713 }
6714 c.$wrapperEl.transitionEnd(() => {
6715 if (!controlled) return;
6716 if (c.params.loop && swiper.params.controller.by === 'slide') {
6717 c.loopFix();
6718 }
6719 c.transitionEnd();
6720 });
6721 }
6722 }
6723 if (Array.isArray(controlled)) {
6724 for (i = 0; i < controlled.length; i += 1) {
6725 if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
6726 setControlledTransition(controlled[i]);
6727 }
6728 }
6729 } else if (controlled instanceof Swiper && byController !== controlled) {
6730 setControlledTransition(controlled);
6731 }
6732 },
6733};
6734var Controller$1 = {
6735 name: 'controller',
6736 params: {
6737 controller: {
6738 control: undefined,
6739 inverse: false,
6740 by: 'slide', // or 'container'
6741 },
6742 },
6743 create() {
6744 const swiper = this;
6745 Utils.extend(swiper, {
6746 controller: {
6747 control: swiper.params.controller.control,
6748 getInterpolateFunction: Controller.getInterpolateFunction.bind(swiper),
6749 setTranslate: Controller.setTranslate.bind(swiper),
6750 setTransition: Controller.setTransition.bind(swiper),
6751 },
6752 });
6753 },
6754 on: {
6755 update() {
6756 const swiper = this;
6757 if (!swiper.controller.control) return;
6758 if (swiper.controller.spline) {
6759 swiper.controller.spline = undefined;
6760 delete swiper.controller.spline;
6761 }
6762 },
6763 resize() {
6764 const swiper = this;
6765 if (!swiper.controller.control) return;
6766 if (swiper.controller.spline) {
6767 swiper.controller.spline = undefined;
6768 delete swiper.controller.spline;
6769 }
6770 },
6771 observerUpdate() {
6772 const swiper = this;
6773 if (!swiper.controller.control) return;
6774 if (swiper.controller.spline) {
6775 swiper.controller.spline = undefined;
6776 delete swiper.controller.spline;
6777 }
6778 },
6779 setTranslate(translate, byController) {
6780 const swiper = this;
6781 if (!swiper.controller.control) return;
6782 swiper.controller.setTranslate(translate, byController);
6783 },
6784 setTransition(duration, byController) {
6785 const swiper = this;
6786 if (!swiper.controller.control) return;
6787 swiper.controller.setTransition(duration, byController);
6788 },
6789 },
6790};
6791
6792const a11y = {
6793 makeElFocusable($el) {
6794 $el.attr('tabIndex', '0');
6795 return $el;
6796 },
6797 addElRole($el, role) {
6798 $el.attr('role', role);
6799 return $el;
6800 },
6801 addElLabel($el, label) {
6802 $el.attr('aria-label', label);
6803 return $el;
6804 },
6805 disableEl($el) {
6806 $el.attr('aria-disabled', true);
6807 return $el;
6808 },
6809 enableEl($el) {
6810 $el.attr('aria-disabled', false);
6811 return $el;
6812 },
6813 onEnterKey(e) {
6814 const swiper = this;
6815 const params = swiper.params.a11y;
6816 if (e.keyCode !== 13) return;
6817 const $targetEl = $(e.target);
6818 if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {
6819 if (!(swiper.isEnd && !swiper.params.loop)) {
6820 swiper.slideNext();
6821 }
6822 if (swiper.isEnd) {
6823 swiper.a11y.notify(params.lastSlideMessage);
6824 } else {
6825 swiper.a11y.notify(params.nextSlideMessage);
6826 }
6827 }
6828 if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {
6829 if (!(swiper.isBeginning && !swiper.params.loop)) {
6830 swiper.slidePrev();
6831 }
6832 if (swiper.isBeginning) {
6833 swiper.a11y.notify(params.firstSlideMessage);
6834 } else {
6835 swiper.a11y.notify(params.prevSlideMessage);
6836 }
6837 }
6838 if (swiper.pagination && $targetEl.is(`.${swiper.params.pagination.bulletClass}`)) {
6839 $targetEl[0].click();
6840 }
6841 },
6842 notify(message) {
6843 const swiper = this;
6844 const notification = swiper.a11y.liveRegion;
6845 if (notification.length === 0) return;
6846 notification.html('');
6847 notification.html(message);
6848 },
6849 updateNavigation() {
6850 const swiper = this;
6851
6852 if (swiper.params.loop) return;
6853 const { $nextEl, $prevEl } = swiper.navigation;
6854
6855 if ($prevEl && $prevEl.length > 0) {
6856 if (swiper.isBeginning) {
6857 swiper.a11y.disableEl($prevEl);
6858 } else {
6859 swiper.a11y.enableEl($prevEl);
6860 }
6861 }
6862 if ($nextEl && $nextEl.length > 0) {
6863 if (swiper.isEnd) {
6864 swiper.a11y.disableEl($nextEl);
6865 } else {
6866 swiper.a11y.enableEl($nextEl);
6867 }
6868 }
6869 },
6870 updatePagination() {
6871 const swiper = this;
6872 const params = swiper.params.a11y;
6873 if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
6874 swiper.pagination.bullets.each((bulletIndex, bulletEl) => {
6875 const $bulletEl = $(bulletEl);
6876 swiper.a11y.makeElFocusable($bulletEl);
6877 swiper.a11y.addElRole($bulletEl, 'button');
6878 swiper.a11y.addElLabel($bulletEl, params.paginationBulletMessage.replace(/{{index}}/, $bulletEl.index() + 1));
6879 });
6880 }
6881 },
6882 init() {
6883 const swiper = this;
6884
6885 swiper.$el.append(swiper.a11y.liveRegion);
6886
6887 // Navigation
6888 const params = swiper.params.a11y;
6889 let $nextEl;
6890 let $prevEl;
6891 if (swiper.navigation && swiper.navigation.$nextEl) {
6892 $nextEl = swiper.navigation.$nextEl;
6893 }
6894 if (swiper.navigation && swiper.navigation.$prevEl) {
6895 $prevEl = swiper.navigation.$prevEl;
6896 }
6897 if ($nextEl) {
6898 swiper.a11y.makeElFocusable($nextEl);
6899 swiper.a11y.addElRole($nextEl, 'button');
6900 swiper.a11y.addElLabel($nextEl, params.nextSlideMessage);
6901 $nextEl.on('keydown', swiper.a11y.onEnterKey);
6902 }
6903 if ($prevEl) {
6904 swiper.a11y.makeElFocusable($prevEl);
6905 swiper.a11y.addElRole($prevEl, 'button');
6906 swiper.a11y.addElLabel($prevEl, params.prevSlideMessage);
6907 $prevEl.on('keydown', swiper.a11y.onEnterKey);
6908 }
6909
6910 // Pagination
6911 if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
6912 swiper.pagination.$el.on('keydown', `.${swiper.params.pagination.bulletClass}`, swiper.a11y.onEnterKey);
6913 }
6914 },
6915 destroy() {
6916 const swiper = this;
6917 if (swiper.a11y.liveRegion && swiper.a11y.liveRegion.length > 0) swiper.a11y.liveRegion.remove();
6918
6919 let $nextEl;
6920 let $prevEl;
6921 if (swiper.navigation && swiper.navigation.$nextEl) {
6922 $nextEl = swiper.navigation.$nextEl;
6923 }
6924 if (swiper.navigation && swiper.navigation.$prevEl) {
6925 $prevEl = swiper.navigation.$prevEl;
6926 }
6927 if ($nextEl) {
6928 $nextEl.off('keydown', swiper.a11y.onEnterKey);
6929 }
6930 if ($prevEl) {
6931 $prevEl.off('keydown', swiper.a11y.onEnterKey);
6932 }
6933
6934 // Pagination
6935 if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
6936 swiper.pagination.$el.off('keydown', `.${swiper.params.pagination.bulletClass}`, swiper.a11y.onEnterKey);
6937 }
6938 },
6939};
6940var A11y = {
6941 name: 'a11y',
6942 params: {
6943 a11y: {
6944 enabled: true,
6945 notificationClass: 'swiper-notification',
6946 prevSlideMessage: 'Previous slide',
6947 nextSlideMessage: 'Next slide',
6948 firstSlideMessage: 'This is the first slide',
6949 lastSlideMessage: 'This is the last slide',
6950 paginationBulletMessage: 'Go to slide {{index}}',
6951 },
6952 },
6953 create() {
6954 const swiper = this;
6955 Utils.extend(swiper, {
6956 a11y: {
6957 liveRegion: $(`<span class="${swiper.params.a11y.notificationClass}" aria-live="assertive" aria-atomic="true"></span>`),
6958 },
6959 });
6960 Object.keys(a11y).forEach((methodName) => {
6961 swiper.a11y[methodName] = a11y[methodName].bind(swiper);
6962 });
6963 },
6964 on: {
6965 init() {
6966 const swiper = this;
6967 if (!swiper.params.a11y.enabled) return;
6968 swiper.a11y.init();
6969 swiper.a11y.updateNavigation();
6970 },
6971 toEdge() {
6972 const swiper = this;
6973 if (!swiper.params.a11y.enabled) return;
6974 swiper.a11y.updateNavigation();
6975 },
6976 fromEdge() {
6977 const swiper = this;
6978 if (!swiper.params.a11y.enabled) return;
6979 swiper.a11y.updateNavigation();
6980 },
6981 paginationUpdate() {
6982 const swiper = this;
6983 if (!swiper.params.a11y.enabled) return;
6984 swiper.a11y.updatePagination();
6985 },
6986 destroy() {
6987 const swiper = this;
6988 if (!swiper.params.a11y.enabled) return;
6989 swiper.a11y.destroy();
6990 },
6991 },
6992};
6993
6994const History = {
6995 init() {
6996 const swiper = this;
6997 if (!swiper.params.history) return;
6998 if (!win.history || !win.history.pushState) {
6999 swiper.params.history.enabled = false;
7000 swiper.params.hashNavigation.enabled = true;
7001 return;
7002 }
7003 const history = swiper.history;
7004 history.initialized = true;
7005 history.paths = History.getPathValues();
7006 if (!history.paths.key && !history.paths.value) return;
7007 history.scrollToSlide(0, history.paths.value, swiper.params.runCallbacksOnInit);
7008 if (!swiper.params.history.replaceState) {
7009 win.addEventListener('popstate', swiper.history.setHistoryPopState);
7010 }
7011 },
7012 destroy() {
7013 const swiper = this;
7014 if (!swiper.params.history.replaceState) {
7015 win.removeEventListener('popstate', swiper.history.setHistoryPopState);
7016 }
7017 },
7018 setHistoryPopState() {
7019 const swiper = this;
7020 swiper.history.paths = History.getPathValues();
7021 swiper.history.scrollToSlide(swiper.params.speed, swiper.history.paths.value, false);
7022 },
7023 getPathValues() {
7024 const pathArray = win.location.pathname.slice(1).split('/').filter((part) => part !== '');
7025 const total = pathArray.length;
7026 const key = pathArray[total - 2];
7027 const value = pathArray[total - 1];
7028 return { key, value };
7029 },
7030 setHistory(key, index) {
7031 const swiper = this;
7032 if (!swiper.history.initialized || !swiper.params.history.enabled) return;
7033 const slide = swiper.slides.eq(index);
7034 let value = History.slugify(slide.attr('data-history'));
7035 if (!win.location.pathname.includes(key)) {
7036 value = `${key}/${value}`;
7037 }
7038 const currentState = win.history.state;
7039 if (currentState && currentState.value === value) {
7040 return;
7041 }
7042 if (swiper.params.history.replaceState) {
7043 win.history.replaceState({ value }, null, value);
7044 } else {
7045 win.history.pushState({ value }, null, value);
7046 }
7047 },
7048 slugify(text) {
7049 return text.toString()
7050 .replace(/\s+/g, '-')
7051 .replace(/[^\w-]+/g, '')
7052 .replace(/--+/g, '-')
7053 .replace(/^-+/, '')
7054 .replace(/-+$/, '');
7055 },
7056 scrollToSlide(speed, value, runCallbacks) {
7057 const swiper = this;
7058 if (value) {
7059 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
7060 const slide = swiper.slides.eq(i);
7061 const slideHistory = History.slugify(slide.attr('data-history'));
7062 if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {
7063 const index = slide.index();
7064 swiper.slideTo(index, speed, runCallbacks);
7065 }
7066 }
7067 } else {
7068 swiper.slideTo(0, speed, runCallbacks);
7069 }
7070 },
7071};
7072
7073var History$1 = {
7074 name: 'history',
7075 params: {
7076 history: {
7077 enabled: false,
7078 replaceState: false,
7079 key: 'slides',
7080 },
7081 },
7082 create() {
7083 const swiper = this;
7084 Utils.extend(swiper, {
7085 history: {
7086 init: History.init.bind(swiper),
7087 setHistory: History.setHistory.bind(swiper),
7088 setHistoryPopState: History.setHistoryPopState.bind(swiper),
7089 scrollToSlide: History.scrollToSlide.bind(swiper),
7090 destroy: History.destroy.bind(swiper),
7091 },
7092 });
7093 },
7094 on: {
7095 init() {
7096 const swiper = this;
7097 if (swiper.params.history.enabled) {
7098 swiper.history.init();
7099 }
7100 },
7101 destroy() {
7102 const swiper = this;
7103 if (swiper.params.history.enabled) {
7104 swiper.history.destroy();
7105 }
7106 },
7107 transitionEnd() {
7108 const swiper = this;
7109 if (swiper.history.initialized) {
7110 swiper.history.setHistory(swiper.params.history.key, swiper.activeIndex);
7111 }
7112 },
7113 slideChange() {
7114 const swiper = this;
7115 if (swiper.history.initialized && swiper.params.cssMode) {
7116 swiper.history.setHistory(swiper.params.history.key, swiper.activeIndex);
7117 }
7118 },
7119 },
7120};
7121
7122const HashNavigation = {
7123 onHashCange() {
7124 const swiper = this;
7125 const newHash = doc.location.hash.replace('#', '');
7126 const activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');
7127 if (newHash !== activeSlideHash) {
7128 const newIndex = swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-hash="${newHash}"]`).index();
7129 if (typeof newIndex === 'undefined') return;
7130 swiper.slideTo(newIndex);
7131 }
7132 },
7133 setHash() {
7134 const swiper = this;
7135 if (!swiper.hashNavigation.initialized || !swiper.params.hashNavigation.enabled) return;
7136 if (swiper.params.hashNavigation.replaceState && win.history && win.history.replaceState) {
7137 win.history.replaceState(null, null, (`#${swiper.slides.eq(swiper.activeIndex).attr('data-hash')}` || ''));
7138 } else {
7139 const slide = swiper.slides.eq(swiper.activeIndex);
7140 const hash = slide.attr('data-hash') || slide.attr('data-history');
7141 doc.location.hash = hash || '';
7142 }
7143 },
7144 init() {
7145 const swiper = this;
7146 if (!swiper.params.hashNavigation.enabled || (swiper.params.history && swiper.params.history.enabled)) return;
7147 swiper.hashNavigation.initialized = true;
7148 const hash = doc.location.hash.replace('#', '');
7149 if (hash) {
7150 const speed = 0;
7151 for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
7152 const slide = swiper.slides.eq(i);
7153 const slideHash = slide.attr('data-hash') || slide.attr('data-history');
7154 if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {
7155 const index = slide.index();
7156 swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);
7157 }
7158 }
7159 }
7160 if (swiper.params.hashNavigation.watchState) {
7161 $(win).on('hashchange', swiper.hashNavigation.onHashCange);
7162 }
7163 },
7164 destroy() {
7165 const swiper = this;
7166 if (swiper.params.hashNavigation.watchState) {
7167 $(win).off('hashchange', swiper.hashNavigation.onHashCange);
7168 }
7169 },
7170};
7171var HashNavigation$1 = {
7172 name: 'hash-navigation',
7173 params: {
7174 hashNavigation: {
7175 enabled: false,
7176 replaceState: false,
7177 watchState: false,
7178 },
7179 },
7180 create() {
7181 const swiper = this;
7182 Utils.extend(swiper, {
7183 hashNavigation: {
7184 initialized: false,
7185 init: HashNavigation.init.bind(swiper),
7186 destroy: HashNavigation.destroy.bind(swiper),
7187 setHash: HashNavigation.setHash.bind(swiper),
7188 onHashCange: HashNavigation.onHashCange.bind(swiper),
7189 },
7190 });
7191 },
7192 on: {
7193 init() {
7194 const swiper = this;
7195 if (swiper.params.hashNavigation.enabled) {
7196 swiper.hashNavigation.init();
7197 }
7198 },
7199 destroy() {
7200 const swiper = this;
7201 if (swiper.params.hashNavigation.enabled) {
7202 swiper.hashNavigation.destroy();
7203 }
7204 },
7205 transitionEnd() {
7206 const swiper = this;
7207 if (swiper.hashNavigation.initialized) {
7208 swiper.hashNavigation.setHash();
7209 }
7210 },
7211 slideChange() {
7212 const swiper = this;
7213 if (swiper.hashNavigation.initialized && swiper.params.cssMode) {
7214 swiper.hashNavigation.setHash();
7215 }
7216 },
7217 },
7218};
7219
7220/* eslint no-underscore-dangle: "off" */
7221
7222const Autoplay = {
7223 run() {
7224 const swiper = this;
7225 const $activeSlideEl = swiper.slides.eq(swiper.activeIndex);
7226 let delay = swiper.params.autoplay.delay;
7227 if ($activeSlideEl.attr('data-swiper-autoplay')) {
7228 delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;
7229 }
7230 clearTimeout(swiper.autoplay.timeout);
7231 swiper.autoplay.timeout = Utils.nextTick(() => {
7232 if (swiper.params.autoplay.reverseDirection) {
7233 if (swiper.params.loop) {
7234 swiper.loopFix();
7235 swiper.slidePrev(swiper.params.speed, true, true);
7236 swiper.emit('autoplay');
7237 } else if (!swiper.isBeginning) {
7238 swiper.slidePrev(swiper.params.speed, true, true);
7239 swiper.emit('autoplay');
7240 } else if (!swiper.params.autoplay.stopOnLastSlide) {
7241 swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);
7242 swiper.emit('autoplay');
7243 } else {
7244 swiper.autoplay.stop();
7245 }
7246 } else if (swiper.params.loop) {
7247 swiper.loopFix();
7248 swiper.slideNext(swiper.params.speed, true, true);
7249 swiper.emit('autoplay');
7250 } else if (!swiper.isEnd) {
7251 swiper.slideNext(swiper.params.speed, true, true);
7252 swiper.emit('autoplay');
7253 } else if (!swiper.params.autoplay.stopOnLastSlide) {
7254 swiper.slideTo(0, swiper.params.speed, true, true);
7255 swiper.emit('autoplay');
7256 } else {
7257 swiper.autoplay.stop();
7258 }
7259 if (swiper.params.cssMode && swiper.autoplay.running) swiper.autoplay.run();
7260 }, delay);
7261 },
7262 start() {
7263 const swiper = this;
7264 if (typeof swiper.autoplay.timeout !== 'undefined') return false;
7265 if (swiper.autoplay.running) return false;
7266 swiper.autoplay.running = true;
7267 swiper.emit('autoplayStart');
7268 swiper.autoplay.run();
7269 return true;
7270 },
7271 stop() {
7272 const swiper = this;
7273 if (!swiper.autoplay.running) return false;
7274 if (typeof swiper.autoplay.timeout === 'undefined') return false;
7275
7276 if (swiper.autoplay.timeout) {
7277 clearTimeout(swiper.autoplay.timeout);
7278 swiper.autoplay.timeout = undefined;
7279 }
7280 swiper.autoplay.running = false;
7281 swiper.emit('autoplayStop');
7282 return true;
7283 },
7284 pause(speed) {
7285 const swiper = this;
7286 if (!swiper.autoplay.running) return;
7287 if (swiper.autoplay.paused) return;
7288 if (swiper.autoplay.timeout) clearTimeout(swiper.autoplay.timeout);
7289 swiper.autoplay.paused = true;
7290 if (speed === 0 || !swiper.params.autoplay.waitForTransition) {
7291 swiper.autoplay.paused = false;
7292 swiper.autoplay.run();
7293 } else {
7294 swiper.$wrapperEl[0].addEventListener('transitionend', swiper.autoplay.onTransitionEnd);
7295 swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
7296 }
7297 },
7298};
7299
7300var Autoplay$1 = {
7301 name: 'autoplay',
7302 params: {
7303 autoplay: {
7304 enabled: false,
7305 delay: 3000,
7306 waitForTransition: true,
7307 disableOnInteraction: true,
7308 stopOnLastSlide: false,
7309 reverseDirection: false,
7310 },
7311 },
7312 create() {
7313 const swiper = this;
7314 Utils.extend(swiper, {
7315 autoplay: {
7316 running: false,
7317 paused: false,
7318 run: Autoplay.run.bind(swiper),
7319 start: Autoplay.start.bind(swiper),
7320 stop: Autoplay.stop.bind(swiper),
7321 pause: Autoplay.pause.bind(swiper),
7322 onVisibilityChange() {
7323 if (document.visibilityState === 'hidden' && swiper.autoplay.running) {
7324 swiper.autoplay.pause();
7325 }
7326 if (document.visibilityState === 'visible' && swiper.autoplay.paused) {
7327 swiper.autoplay.run();
7328 swiper.autoplay.paused = false;
7329 }
7330 },
7331 onTransitionEnd(e) {
7332 if (!swiper || swiper.destroyed || !swiper.$wrapperEl) return;
7333 if (e.target !== this) return;
7334 swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.autoplay.onTransitionEnd);
7335 swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
7336 swiper.autoplay.paused = false;
7337 if (!swiper.autoplay.running) {
7338 swiper.autoplay.stop();
7339 } else {
7340 swiper.autoplay.run();
7341 }
7342 },
7343 },
7344 });
7345 },
7346 on: {
7347 init() {
7348 const swiper = this;
7349 if (swiper.params.autoplay.enabled) {
7350 swiper.autoplay.start();
7351 document.addEventListener('visibilitychange', swiper.autoplay.onVisibilityChange);
7352 }
7353 },
7354 beforeTransitionStart(speed, internal) {
7355 const swiper = this;
7356 if (swiper.autoplay.running) {
7357 if (internal || !swiper.params.autoplay.disableOnInteraction) {
7358 swiper.autoplay.pause(speed);
7359 } else {
7360 swiper.autoplay.stop();
7361 }
7362 }
7363 },
7364 sliderFirstMove() {
7365 const swiper = this;
7366 if (swiper.autoplay.running) {
7367 if (swiper.params.autoplay.disableOnInteraction) {
7368 swiper.autoplay.stop();
7369 } else {
7370 swiper.autoplay.pause();
7371 }
7372 }
7373 },
7374 touchEnd() {
7375 const swiper = this;
7376 if (swiper.params.cssMode && swiper.autoplay.paused && !swiper.params.autoplay.disableOnInteraction) {
7377 swiper.autoplay.run();
7378 }
7379 },
7380 destroy() {
7381 const swiper = this;
7382 if (swiper.autoplay.running) {
7383 swiper.autoplay.stop();
7384 }
7385 document.removeEventListener('visibilitychange', swiper.autoplay.onVisibilityChange);
7386 },
7387 },
7388};
7389
7390const Fade = {
7391 setTranslate() {
7392 const swiper = this;
7393 const { slides } = swiper;
7394 for (let i = 0; i < slides.length; i += 1) {
7395 const $slideEl = swiper.slides.eq(i);
7396 const offset = $slideEl[0].swiperSlideOffset;
7397 let tx = -offset;
7398 if (!swiper.params.virtualTranslate) tx -= swiper.translate;
7399 let ty = 0;
7400 if (!swiper.isHorizontal()) {
7401 ty = tx;
7402 tx = 0;
7403 }
7404 const slideOpacity = swiper.params.fadeEffect.crossFade
7405 ? Math.max(1 - Math.abs($slideEl[0].progress), 0)
7406 : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);
7407 $slideEl
7408 .css({
7409 opacity: slideOpacity,
7410 })
7411 .transform(`translate3d(${tx}px, ${ty}px, 0px)`);
7412 }
7413 },
7414 setTransition(duration) {
7415 const swiper = this;
7416 const { slides, $wrapperEl } = swiper;
7417 slides.transition(duration);
7418 if (swiper.params.virtualTranslate && duration !== 0) {
7419 let eventTriggered = false;
7420 slides.transitionEnd(() => {
7421 if (eventTriggered) return;
7422 if (!swiper || swiper.destroyed) return;
7423 eventTriggered = true;
7424 swiper.animating = false;
7425 const triggerEvents = ['webkitTransitionEnd', 'transitionend'];
7426 for (let i = 0; i < triggerEvents.length; i += 1) {
7427 $wrapperEl.trigger(triggerEvents[i]);
7428 }
7429 });
7430 }
7431 },
7432};
7433
7434var EffectFade = {
7435 name: 'effect-fade',
7436 params: {
7437 fadeEffect: {
7438 crossFade: false,
7439 },
7440 },
7441 create() {
7442 const swiper = this;
7443 Utils.extend(swiper, {
7444 fadeEffect: {
7445 setTranslate: Fade.setTranslate.bind(swiper),
7446 setTransition: Fade.setTransition.bind(swiper),
7447 },
7448 });
7449 },
7450 on: {
7451 beforeInit() {
7452 const swiper = this;
7453 if (swiper.params.effect !== 'fade') return;
7454 swiper.classNames.push(`${swiper.params.containerModifierClass}fade`);
7455 const overwriteParams = {
7456 slidesPerView: 1,
7457 slidesPerColumn: 1,
7458 slidesPerGroup: 1,
7459 watchSlidesProgress: true,
7460 spaceBetween: 0,
7461 virtualTranslate: true,
7462 };
7463 Utils.extend(swiper.params, overwriteParams);
7464 Utils.extend(swiper.originalParams, overwriteParams);
7465 },
7466 setTranslate() {
7467 const swiper = this;
7468 if (swiper.params.effect !== 'fade') return;
7469 swiper.fadeEffect.setTranslate();
7470 },
7471 setTransition(duration) {
7472 const swiper = this;
7473 if (swiper.params.effect !== 'fade') return;
7474 swiper.fadeEffect.setTransition(duration);
7475 },
7476 },
7477};
7478
7479const Cube = {
7480 setTranslate() {
7481 const swiper = this;
7482 const {
7483 $el, $wrapperEl, slides, width: swiperWidth, height: swiperHeight, rtlTranslate: rtl, size: swiperSize,
7484 } = swiper;
7485 const params = swiper.params.cubeEffect;
7486 const isHorizontal = swiper.isHorizontal();
7487 const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
7488 let wrapperRotate = 0;
7489 let $cubeShadowEl;
7490 if (params.shadow) {
7491 if (isHorizontal) {
7492 $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');
7493 if ($cubeShadowEl.length === 0) {
7494 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
7495 $wrapperEl.append($cubeShadowEl);
7496 }
7497 $cubeShadowEl.css({ height: `${swiperWidth}px` });
7498 } else {
7499 $cubeShadowEl = $el.find('.swiper-cube-shadow');
7500 if ($cubeShadowEl.length === 0) {
7501 $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
7502 $el.append($cubeShadowEl);
7503 }
7504 }
7505 }
7506 for (let i = 0; i < slides.length; i += 1) {
7507 const $slideEl = slides.eq(i);
7508 let slideIndex = i;
7509 if (isVirtual) {
7510 slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);
7511 }
7512 let slideAngle = slideIndex * 90;
7513 let round = Math.floor(slideAngle / 360);
7514 if (rtl) {
7515 slideAngle = -slideAngle;
7516 round = Math.floor(-slideAngle / 360);
7517 }
7518 const progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
7519 let tx = 0;
7520 let ty = 0;
7521 let tz = 0;
7522 if (slideIndex % 4 === 0) {
7523 tx = -round * 4 * swiperSize;
7524 tz = 0;
7525 } else if ((slideIndex - 1) % 4 === 0) {
7526 tx = 0;
7527 tz = -round * 4 * swiperSize;
7528 } else if ((slideIndex - 2) % 4 === 0) {
7529 tx = swiperSize + (round * 4 * swiperSize);
7530 tz = swiperSize;
7531 } else if ((slideIndex - 3) % 4 === 0) {
7532 tx = -swiperSize;
7533 tz = (3 * swiperSize) + (swiperSize * 4 * round);
7534 }
7535 if (rtl) {
7536 tx = -tx;
7537 }
7538
7539 if (!isHorizontal) {
7540 ty = tx;
7541 tx = 0;
7542 }
7543
7544 const transform = `rotateX(${isHorizontal ? 0 : -slideAngle}deg) rotateY(${isHorizontal ? slideAngle : 0}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;
7545 if (progress <= 1 && progress > -1) {
7546 wrapperRotate = (slideIndex * 90) + (progress * 90);
7547 if (rtl) wrapperRotate = (-slideIndex * 90) - (progress * 90);
7548 }
7549 $slideEl.transform(transform);
7550 if (params.slideShadows) {
7551 // Set shadows
7552 let shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
7553 let shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
7554 if (shadowBefore.length === 0) {
7555 shadowBefore = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}"></div>`);
7556 $slideEl.append(shadowBefore);
7557 }
7558 if (shadowAfter.length === 0) {
7559 shadowAfter = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}"></div>`);
7560 $slideEl.append(shadowAfter);
7561 }
7562 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
7563 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
7564 }
7565 }
7566 $wrapperEl.css({
7567 '-webkit-transform-origin': `50% 50% -${swiperSize / 2}px`,
7568 '-moz-transform-origin': `50% 50% -${swiperSize / 2}px`,
7569 '-ms-transform-origin': `50% 50% -${swiperSize / 2}px`,
7570 'transform-origin': `50% 50% -${swiperSize / 2}px`,
7571 });
7572
7573 if (params.shadow) {
7574 if (isHorizontal) {
7575 $cubeShadowEl.transform(`translate3d(0px, ${(swiperWidth / 2) + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(90deg) rotateZ(0deg) scale(${params.shadowScale})`);
7576 } else {
7577 const shadowAngle = Math.abs(wrapperRotate) - (Math.floor(Math.abs(wrapperRotate) / 90) * 90);
7578 const multiplier = 1.5 - (
7579 (Math.sin((shadowAngle * 2 * Math.PI) / 360) / 2)
7580 + (Math.cos((shadowAngle * 2 * Math.PI) / 360) / 2)
7581 );
7582 const scale1 = params.shadowScale;
7583 const scale2 = params.shadowScale / multiplier;
7584 const offset = params.shadowOffset;
7585 $cubeShadowEl.transform(`scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${(swiperHeight / 2) + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-90deg)`);
7586 }
7587 }
7588 const zFactor = (Browser.isSafari || Browser.isUiWebView) ? (-swiperSize / 2) : 0;
7589 $wrapperEl
7590 .transform(`translate3d(0px,0,${zFactor}px) rotateX(${swiper.isHorizontal() ? 0 : wrapperRotate}deg) rotateY(${swiper.isHorizontal() ? -wrapperRotate : 0}deg)`);
7591 },
7592 setTransition(duration) {
7593 const swiper = this;
7594 const { $el, slides } = swiper;
7595 slides
7596 .transition(duration)
7597 .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
7598 .transition(duration);
7599 if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
7600 $el.find('.swiper-cube-shadow').transition(duration);
7601 }
7602 },
7603};
7604
7605var EffectCube = {
7606 name: 'effect-cube',
7607 params: {
7608 cubeEffect: {
7609 slideShadows: true,
7610 shadow: true,
7611 shadowOffset: 20,
7612 shadowScale: 0.94,
7613 },
7614 },
7615 create() {
7616 const swiper = this;
7617 Utils.extend(swiper, {
7618 cubeEffect: {
7619 setTranslate: Cube.setTranslate.bind(swiper),
7620 setTransition: Cube.setTransition.bind(swiper),
7621 },
7622 });
7623 },
7624 on: {
7625 beforeInit() {
7626 const swiper = this;
7627 if (swiper.params.effect !== 'cube') return;
7628 swiper.classNames.push(`${swiper.params.containerModifierClass}cube`);
7629 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
7630 const overwriteParams = {
7631 slidesPerView: 1,
7632 slidesPerColumn: 1,
7633 slidesPerGroup: 1,
7634 watchSlidesProgress: true,
7635 resistanceRatio: 0,
7636 spaceBetween: 0,
7637 centeredSlides: false,
7638 virtualTranslate: true,
7639 };
7640 Utils.extend(swiper.params, overwriteParams);
7641 Utils.extend(swiper.originalParams, overwriteParams);
7642 },
7643 setTranslate() {
7644 const swiper = this;
7645 if (swiper.params.effect !== 'cube') return;
7646 swiper.cubeEffect.setTranslate();
7647 },
7648 setTransition(duration) {
7649 const swiper = this;
7650 if (swiper.params.effect !== 'cube') return;
7651 swiper.cubeEffect.setTransition(duration);
7652 },
7653 },
7654};
7655
7656const Flip = {
7657 setTranslate() {
7658 const swiper = this;
7659 const { slides, rtlTranslate: rtl } = swiper;
7660 for (let i = 0; i < slides.length; i += 1) {
7661 const $slideEl = slides.eq(i);
7662 let progress = $slideEl[0].progress;
7663 if (swiper.params.flipEffect.limitRotation) {
7664 progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
7665 }
7666 const offset = $slideEl[0].swiperSlideOffset;
7667 const rotate = -180 * progress;
7668 let rotateY = rotate;
7669 let rotateX = 0;
7670 let tx = -offset;
7671 let ty = 0;
7672 if (!swiper.isHorizontal()) {
7673 ty = tx;
7674 tx = 0;
7675 rotateX = -rotateY;
7676 rotateY = 0;
7677 } else if (rtl) {
7678 rotateY = -rotateY;
7679 }
7680
7681 $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
7682
7683 if (swiper.params.flipEffect.slideShadows) {
7684 // Set shadows
7685 let shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
7686 let shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
7687 if (shadowBefore.length === 0) {
7688 shadowBefore = $(`<div class="swiper-slide-shadow-${swiper.isHorizontal() ? 'left' : 'top'}"></div>`);
7689 $slideEl.append(shadowBefore);
7690 }
7691 if (shadowAfter.length === 0) {
7692 shadowAfter = $(`<div class="swiper-slide-shadow-${swiper.isHorizontal() ? 'right' : 'bottom'}"></div>`);
7693 $slideEl.append(shadowAfter);
7694 }
7695 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
7696 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
7697 }
7698 $slideEl
7699 .transform(`translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`);
7700 }
7701 },
7702 setTransition(duration) {
7703 const swiper = this;
7704 const { slides, activeIndex, $wrapperEl } = swiper;
7705 slides
7706 .transition(duration)
7707 .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
7708 .transition(duration);
7709 if (swiper.params.virtualTranslate && duration !== 0) {
7710 let eventTriggered = false;
7711 // eslint-disable-next-line
7712 slides.eq(activeIndex).transitionEnd(function onTransitionEnd() {
7713 if (eventTriggered) return;
7714 if (!swiper || swiper.destroyed) return;
7715 // if (!$(this).hasClass(swiper.params.slideActiveClass)) return;
7716 eventTriggered = true;
7717 swiper.animating = false;
7718 const triggerEvents = ['webkitTransitionEnd', 'transitionend'];
7719 for (let i = 0; i < triggerEvents.length; i += 1) {
7720 $wrapperEl.trigger(triggerEvents[i]);
7721 }
7722 });
7723 }
7724 },
7725};
7726
7727var EffectFlip = {
7728 name: 'effect-flip',
7729 params: {
7730 flipEffect: {
7731 slideShadows: true,
7732 limitRotation: true,
7733 },
7734 },
7735 create() {
7736 const swiper = this;
7737 Utils.extend(swiper, {
7738 flipEffect: {
7739 setTranslate: Flip.setTranslate.bind(swiper),
7740 setTransition: Flip.setTransition.bind(swiper),
7741 },
7742 });
7743 },
7744 on: {
7745 beforeInit() {
7746 const swiper = this;
7747 if (swiper.params.effect !== 'flip') return;
7748 swiper.classNames.push(`${swiper.params.containerModifierClass}flip`);
7749 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
7750 const overwriteParams = {
7751 slidesPerView: 1,
7752 slidesPerColumn: 1,
7753 slidesPerGroup: 1,
7754 watchSlidesProgress: true,
7755 spaceBetween: 0,
7756 virtualTranslate: true,
7757 };
7758 Utils.extend(swiper.params, overwriteParams);
7759 Utils.extend(swiper.originalParams, overwriteParams);
7760 },
7761 setTranslate() {
7762 const swiper = this;
7763 if (swiper.params.effect !== 'flip') return;
7764 swiper.flipEffect.setTranslate();
7765 },
7766 setTransition(duration) {
7767 const swiper = this;
7768 if (swiper.params.effect !== 'flip') return;
7769 swiper.flipEffect.setTransition(duration);
7770 },
7771 },
7772};
7773
7774const Coverflow = {
7775 setTranslate() {
7776 const swiper = this;
7777 const {
7778 width: swiperWidth, height: swiperHeight, slides, $wrapperEl, slidesSizesGrid,
7779 } = swiper;
7780 const params = swiper.params.coverflowEffect;
7781 const isHorizontal = swiper.isHorizontal();
7782 const transform = swiper.translate;
7783 const center = isHorizontal ? -transform + (swiperWidth / 2) : -transform + (swiperHeight / 2);
7784 const rotate = isHorizontal ? params.rotate : -params.rotate;
7785 const translate = params.depth;
7786 // Each slide offset from center
7787 for (let i = 0, length = slides.length; i < length; i += 1) {
7788 const $slideEl = slides.eq(i);
7789 const slideSize = slidesSizesGrid[i];
7790 const slideOffset = $slideEl[0].swiperSlideOffset;
7791 const offsetMultiplier = ((center - slideOffset - (slideSize / 2)) / slideSize) * params.modifier;
7792
7793 let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
7794 let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier;
7795 // var rotateZ = 0
7796 let translateZ = -translate * Math.abs(offsetMultiplier);
7797
7798 let translateY = isHorizontal ? 0 : params.stretch * (offsetMultiplier);
7799 let translateX = isHorizontal ? params.stretch * (offsetMultiplier) : 0;
7800
7801 // Fix for ultra small values
7802 if (Math.abs(translateX) < 0.001) translateX = 0;
7803 if (Math.abs(translateY) < 0.001) translateY = 0;
7804 if (Math.abs(translateZ) < 0.001) translateZ = 0;
7805 if (Math.abs(rotateY) < 0.001) rotateY = 0;
7806 if (Math.abs(rotateX) < 0.001) rotateX = 0;
7807
7808 const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
7809
7810 $slideEl.transform(slideTransform);
7811 $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
7812 if (params.slideShadows) {
7813 // Set shadows
7814 let $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
7815 let $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
7816 if ($shadowBeforeEl.length === 0) {
7817 $shadowBeforeEl = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}"></div>`);
7818 $slideEl.append($shadowBeforeEl);
7819 }
7820 if ($shadowAfterEl.length === 0) {
7821 $shadowAfterEl = $(`<div class="swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}"></div>`);
7822 $slideEl.append($shadowAfterEl);
7823 }
7824 if ($shadowBeforeEl.length) $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
7825 if ($shadowAfterEl.length) $shadowAfterEl[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0;
7826 }
7827 }
7828
7829 // Set correct perspective for IE10
7830 if (Support.pointerEvents || Support.prefixedPointerEvents) {
7831 const ws = $wrapperEl[0].style;
7832 ws.perspectiveOrigin = `${center}px 50%`;
7833 }
7834 },
7835 setTransition(duration) {
7836 const swiper = this;
7837 swiper.slides
7838 .transition(duration)
7839 .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
7840 .transition(duration);
7841 },
7842};
7843
7844var EffectCoverflow = {
7845 name: 'effect-coverflow',
7846 params: {
7847 coverflowEffect: {
7848 rotate: 50,
7849 stretch: 0,
7850 depth: 100,
7851 modifier: 1,
7852 slideShadows: true,
7853 },
7854 },
7855 create() {
7856 const swiper = this;
7857 Utils.extend(swiper, {
7858 coverflowEffect: {
7859 setTranslate: Coverflow.setTranslate.bind(swiper),
7860 setTransition: Coverflow.setTransition.bind(swiper),
7861 },
7862 });
7863 },
7864 on: {
7865 beforeInit() {
7866 const swiper = this;
7867 if (swiper.params.effect !== 'coverflow') return;
7868
7869 swiper.classNames.push(`${swiper.params.containerModifierClass}coverflow`);
7870 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
7871
7872 swiper.params.watchSlidesProgress = true;
7873 swiper.originalParams.watchSlidesProgress = true;
7874 },
7875 setTranslate() {
7876 const swiper = this;
7877 if (swiper.params.effect !== 'coverflow') return;
7878 swiper.coverflowEffect.setTranslate();
7879 },
7880 setTransition(duration) {
7881 const swiper = this;
7882 if (swiper.params.effect !== 'coverflow') return;
7883 swiper.coverflowEffect.setTransition(duration);
7884 },
7885 },
7886};
7887
7888const Thumbs = {
7889 init() {
7890 const swiper = this;
7891 const { thumbs: thumbsParams } = swiper.params;
7892 const SwiperClass = swiper.constructor;
7893 if (thumbsParams.swiper instanceof SwiperClass) {
7894 swiper.thumbs.swiper = thumbsParams.swiper;
7895 Utils.extend(swiper.thumbs.swiper.originalParams, {
7896 watchSlidesProgress: true,
7897 slideToClickedSlide: false,
7898 });
7899 Utils.extend(swiper.thumbs.swiper.params, {
7900 watchSlidesProgress: true,
7901 slideToClickedSlide: false,
7902 });
7903 } else if (Utils.isObject(thumbsParams.swiper)) {
7904 swiper.thumbs.swiper = new SwiperClass(Utils.extend({}, thumbsParams.swiper, {
7905 watchSlidesVisibility: true,
7906 watchSlidesProgress: true,
7907 slideToClickedSlide: false,
7908 }));
7909 swiper.thumbs.swiperCreated = true;
7910 }
7911 swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);
7912 swiper.thumbs.swiper.on('tap', swiper.thumbs.onThumbClick);
7913 },
7914 onThumbClick() {
7915 const swiper = this;
7916 const thumbsSwiper = swiper.thumbs.swiper;
7917 if (!thumbsSwiper) return;
7918 const clickedIndex = thumbsSwiper.clickedIndex;
7919 const clickedSlide = thumbsSwiper.clickedSlide;
7920 if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) return;
7921 if (typeof clickedIndex === 'undefined' || clickedIndex === null) return;
7922 let slideToIndex;
7923 if (thumbsSwiper.params.loop) {
7924 slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);
7925 } else {
7926 slideToIndex = clickedIndex;
7927 }
7928 if (swiper.params.loop) {
7929 let currentIndex = swiper.activeIndex;
7930 if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {
7931 swiper.loopFix();
7932 // eslint-disable-next-line
7933 swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
7934 currentIndex = swiper.activeIndex;
7935 }
7936 const prevIndex = swiper.slides.eq(currentIndex).prevAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
7937 const nextIndex = swiper.slides.eq(currentIndex).nextAll(`[data-swiper-slide-index="${slideToIndex}"]`).eq(0).index();
7938 if (typeof prevIndex === 'undefined') slideToIndex = nextIndex;
7939 else if (typeof nextIndex === 'undefined') slideToIndex = prevIndex;
7940 else if (nextIndex - currentIndex < currentIndex - prevIndex) slideToIndex = nextIndex;
7941 else slideToIndex = prevIndex;
7942 }
7943 swiper.slideTo(slideToIndex);
7944 },
7945 update(initial) {
7946 const swiper = this;
7947 const thumbsSwiper = swiper.thumbs.swiper;
7948 if (!thumbsSwiper) return;
7949
7950 const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto'
7951 ? thumbsSwiper.slidesPerViewDynamic()
7952 : thumbsSwiper.params.slidesPerView;
7953
7954 if (swiper.realIndex !== thumbsSwiper.realIndex) {
7955 let currentThumbsIndex = thumbsSwiper.activeIndex;
7956 let newThumbsIndex;
7957 if (thumbsSwiper.params.loop) {
7958 if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {
7959 thumbsSwiper.loopFix();
7960 // eslint-disable-next-line
7961 thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;
7962 currentThumbsIndex = thumbsSwiper.activeIndex;
7963 }
7964 // Find actual thumbs index to slide to
7965 const prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
7966 const nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(`[data-swiper-slide-index="${swiper.realIndex}"]`).eq(0).index();
7967 if (typeof prevThumbsIndex === 'undefined') newThumbsIndex = nextThumbsIndex;
7968 else if (typeof nextThumbsIndex === 'undefined') newThumbsIndex = prevThumbsIndex;
7969 else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) newThumbsIndex = currentThumbsIndex;
7970 else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) newThumbsIndex = nextThumbsIndex;
7971 else newThumbsIndex = prevThumbsIndex;
7972 } else {
7973 newThumbsIndex = swiper.realIndex;
7974 }
7975 if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {
7976 if (thumbsSwiper.params.centeredSlides) {
7977 if (newThumbsIndex > currentThumbsIndex) {
7978 newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
7979 } else {
7980 newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
7981 }
7982 } else if (newThumbsIndex > currentThumbsIndex) {
7983 newThumbsIndex = newThumbsIndex - slidesPerView + 1;
7984 }
7985 thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
7986 }
7987 }
7988
7989 // Activate thumbs
7990 let thumbsToActivate = 1;
7991 const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
7992
7993 if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
7994 thumbsToActivate = swiper.params.slidesPerView;
7995 }
7996
7997 thumbsSwiper.slides.removeClass(thumbActiveClass);
7998 if (thumbsSwiper.params.loop || (thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled)) {
7999 for (let i = 0; i < thumbsToActivate; i += 1) {
8000 thumbsSwiper.$wrapperEl.children(`[data-swiper-slide-index="${swiper.realIndex + i}"]`).addClass(thumbActiveClass);
8001 }
8002 } else {
8003 for (let i = 0; i < thumbsToActivate; i += 1) {
8004 thumbsSwiper.slides.eq(swiper.realIndex + i).addClass(thumbActiveClass);
8005 }
8006 }
8007 },
8008};
8009var Thumbs$1 = {
8010 name: 'thumbs',
8011 params: {
8012 thumbs: {
8013 swiper: null,
8014 slideThumbActiveClass: 'swiper-slide-thumb-active',
8015 thumbsContainerClass: 'swiper-container-thumbs',
8016 },
8017 },
8018 create() {
8019 const swiper = this;
8020 Utils.extend(swiper, {
8021 thumbs: {
8022 swiper: null,
8023 init: Thumbs.init.bind(swiper),
8024 update: Thumbs.update.bind(swiper),
8025 onThumbClick: Thumbs.onThumbClick.bind(swiper),
8026 },
8027 });
8028 },
8029 on: {
8030 beforeInit() {
8031 const swiper = this;
8032 const { thumbs } = swiper.params;
8033 if (!thumbs || !thumbs.swiper) return;
8034 swiper.thumbs.init();
8035 swiper.thumbs.update(true);
8036 },
8037 slideChange() {
8038 const swiper = this;
8039 if (!swiper.thumbs.swiper) return;
8040 swiper.thumbs.update();
8041 },
8042 update() {
8043 const swiper = this;
8044 if (!swiper.thumbs.swiper) return;
8045 swiper.thumbs.update();
8046 },
8047 resize() {
8048 const swiper = this;
8049 if (!swiper.thumbs.swiper) return;
8050 swiper.thumbs.update();
8051 },
8052 observerUpdate() {
8053 const swiper = this;
8054 if (!swiper.thumbs.swiper) return;
8055 swiper.thumbs.update();
8056 },
8057 setTransition(duration) {
8058 const swiper = this;
8059 const thumbsSwiper = swiper.thumbs.swiper;
8060 if (!thumbsSwiper) return;
8061 thumbsSwiper.setTransition(duration);
8062 },
8063 beforeDestroy() {
8064 const swiper = this;
8065 const thumbsSwiper = swiper.thumbs.swiper;
8066 if (!thumbsSwiper) return;
8067 if (swiper.thumbs.swiperCreated && thumbsSwiper) {
8068 thumbsSwiper.destroy();
8069 }
8070 },
8071 },
8072};
8073
8074// Swiper Class
8075
8076const components = [
8077 Device$1,
8078 Support$1,
8079 Browser$1,
8080 Resize,
8081 Observer$1,
8082 Virtual$1,
8083 Keyboard$1,
8084 Mousewheel$1,
8085 Navigation$1,
8086 Pagination$1,
8087 Scrollbar$1,
8088 Parallax$1,
8089 Zoom$1,
8090 Lazy$1,
8091 Controller$1,
8092 A11y,
8093 History$1,
8094 HashNavigation$1,
8095 Autoplay$1,
8096 EffectFade,
8097 EffectCube,
8098 EffectFlip,
8099 EffectCoverflow,
8100 Thumbs$1
8101];
8102
8103if (typeof Swiper.use === 'undefined') {
8104 Swiper.use = Swiper.Class.use;
8105 Swiper.installModule = Swiper.Class.installModule;
8106}
8107
8108Swiper.use(components);
8109
8110export default Swiper;