UNPKG

swiper

Version:

Most modern mobile touch slider and framework with hardware accelerated transitions

1,644 lines (1,552 loc) 276 kB
/** * Swiper 5.4.5 * Most modern mobile touch slider and framework with hardware accelerated transitions * http://swiperjs.com * * Copyright 2014-2020 Vladimir Kharlampidi * * Released under the MIT License * * Released on: June 16, 2020 */ /** * SSR Window 2.0.0 * Better handling for window object in SSR environment * https://github.com/nolimits4web/ssr-window * * Copyright 2020, Vladimir Kharlampidi * * Licensed under MIT * * Released on: May 12, 2020 */ /* eslint-disable no-param-reassign */ function isObject(obj) { return (obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object); } function extend(target, src) { if (target === void 0) { target = {}; } if (src === void 0) { src = {}; } Object.keys(src).forEach(function (key) { if (typeof target[key] === 'undefined') target[key] = src[key]; else if (isObject(src[key]) && isObject(target[key]) && Object.keys(src[key]).length > 0) { extend(target[key], src[key]); } }); } var doc = typeof document !== 'undefined' ? document : {}; var ssrDocument = { body: {}, addEventListener: function () { }, removeEventListener: function () { }, activeElement: { blur: function () { }, nodeName: '', }, querySelector: function () { return null; }, querySelectorAll: function () { return []; }, getElementById: function () { return null; }, createEvent: function () { return { initEvent: function () { }, }; }, createElement: function () { return { children: [], childNodes: [], style: {}, setAttribute: function () { }, getElementsByTagName: function () { return []; }, }; }, createElementNS: function () { return {}; }, importNode: function () { return null; }, location: { hash: '', host: '', hostname: '', href: '', origin: '', pathname: '', protocol: '', search: '', }, }; extend(doc, ssrDocument); var win = typeof window !== 'undefined' ? window : {}; var ssrWindow = { document: ssrDocument, navigator: { userAgent: '', }, location: { hash: '', host: '', hostname: '', href: '', origin: '', pathname: '', protocol: '', search: '', }, history: { replaceState: function () { }, pushState: function () { }, go: function () { }, back: function () { }, }, CustomEvent: function CustomEvent() { return this; }, addEventListener: function () { }, removeEventListener: function () { }, getComputedStyle: function () { return { getPropertyValue: function () { return ''; }, }; }, Image: function () { }, Date: function () { }, screen: {}, setTimeout: function () { }, clearTimeout: function () { }, matchMedia: function () { return {}; }, }; extend(win, ssrWindow); /** * Dom7 2.1.5 * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API * http://framework7.io/docs/dom.html * * Copyright 2020, Vladimir Kharlampidi * The iDangero.us * http://www.idangero.us/ * * Licensed under MIT * * Released on: May 15, 2020 */ class Dom7 { constructor(arr) { const self = this; // Create array-like object for (let i = 0; i < arr.length; i += 1) { self[i] = arr[i]; } self.length = arr.length; // Return collection with methods return this; } } function $(selector, context) { const arr = []; let i = 0; if (selector && !context) { if (selector instanceof Dom7) { return selector; } } if (selector) { // String if (typeof selector === 'string') { let els; let tempParent; const html = selector.trim(); if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) { let toCreate = 'div'; if (html.indexOf('<li') === 0) toCreate = 'ul'; if (html.indexOf('<tr') === 0) toCreate = 'tbody'; if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr'; if (html.indexOf('<tbody') === 0) toCreate = 'table'; if (html.indexOf('<option') === 0) toCreate = 'select'; tempParent = doc.createElement(toCreate); tempParent.innerHTML = html; for (i = 0; i < tempParent.childNodes.length; i += 1) { arr.push(tempParent.childNodes[i]); } } else { if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) { // Pure ID selector els = [doc.getElementById(selector.trim().split('#')[1])]; } else { // Other selectors els = (context || doc).querySelectorAll(selector.trim()); } for (i = 0; i < els.length; i += 1) { if (els[i]) arr.push(els[i]); } } } else if (selector.nodeType || selector === win || selector === doc) { // Node/element arr.push(selector); } else if (selector.length > 0 && selector[0].nodeType) { // Array of elements or instance of Dom for (i = 0; i < selector.length; i += 1) { arr.push(selector[i]); } } } return new Dom7(arr); } $.fn = Dom7.prototype; $.Class = Dom7; $.Dom7 = Dom7; function unique(arr) { const uniqueArray = []; for (let i = 0; i < arr.length; i += 1) { if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]); } return uniqueArray; } // Classes and attributes function addClass(className) { if (typeof className === 'undefined') { return this; } const classes = className.split(' '); for (let i = 0; i < classes.length; i += 1) { for (let j = 0; j < this.length; j += 1) { if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.add(classes[i]); } } return this; } function removeClass(className) { const classes = className.split(' '); for (let i = 0; i < classes.length; i += 1) { for (let j = 0; j < this.length; j += 1) { if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.remove(classes[i]); } } return this; } function hasClass(className) { if (!this[0]) return false; return this[0].classList.contains(className); } function toggleClass(className) { const classes = className.split(' '); for (let i = 0; i < classes.length; i += 1) { for (let j = 0; j < this.length; j += 1) { if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') this[j].classList.toggle(classes[i]); } } return this; } function attr(attrs, value) { if (arguments.length === 1 && typeof attrs === 'string') { // Get attr if (this[0]) return this[0].getAttribute(attrs); return undefined; } // Set attrs for (let i = 0; i < this.length; i += 1) { if (arguments.length === 2) { // String this[i].setAttribute(attrs, value); } else { // Object // eslint-disable-next-line for (const attrName in attrs) { this[i][attrName] = attrs[attrName]; this[i].setAttribute(attrName, attrs[attrName]); } } } return this; } // eslint-disable-next-line function removeAttr(attr) { for (let i = 0; i < this.length; i += 1) { this[i].removeAttribute(attr); } return this; } function data(key, value) { let el; if (typeof value === 'undefined') { el = this[0]; // Get value if (el) { if (el.dom7ElementDataStorage && (key in el.dom7ElementDataStorage)) { return el.dom7ElementDataStorage[key]; } const dataKey = el.getAttribute(`data-${key}`); if (dataKey) { return dataKey; } return undefined; } return undefined; } // Set value for (let i = 0; i < this.length; i += 1) { el = this[i]; if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {}; el.dom7ElementDataStorage[key] = value; } return this; } // Transforms // eslint-disable-next-line function transform(transform) { for (let i = 0; i < this.length; i += 1) { const elStyle = this[i].style; elStyle.webkitTransform = transform; elStyle.transform = transform; } return this; } function transition(duration) { if (typeof duration !== 'string') { duration = `${duration}ms`; // eslint-disable-line } for (let i = 0; i < this.length; i += 1) { const elStyle = this[i].style; elStyle.webkitTransitionDuration = duration; elStyle.transitionDuration = duration; } return this; } // Events function on(...args) { let [eventType, targetSelector, listener, capture] = args; if (typeof args[1] === 'function') { [eventType, listener, capture] = args; targetSelector = undefined; } if (!capture) capture = false; function handleLiveEvent(e) { const target = e.target; if (!target) return; const eventData = e.target.dom7EventData || []; if (eventData.indexOf(e) < 0) { eventData.unshift(e); } if ($(target).is(targetSelector)) listener.apply(target, eventData); else { const parents = $(target).parents(); // eslint-disable-line for (let k = 0; k < parents.length; k += 1) { if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData); } } } function handleEvent(e) { const eventData = e && e.target ? e.target.dom7EventData || [] : []; if (eventData.indexOf(e) < 0) { eventData.unshift(e); } listener.apply(this, eventData); } const events = eventType.split(' '); let j; for (let i = 0; i < this.length; i += 1) { const el = this[i]; if (!targetSelector) { for (j = 0; j < events.length; j += 1) { const event = events[j]; if (!el.dom7Listeners) el.dom7Listeners = {}; if (!el.dom7Listeners[event]) el.dom7Listeners[event] = []; el.dom7Listeners[event].push({ listener, proxyListener: handleEvent, }); el.addEventListener(event, handleEvent, capture); } } else { // Live events for (j = 0; j < events.length; j += 1) { const event = events[j]; if (!el.dom7LiveListeners) el.dom7LiveListeners = {}; if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = []; el.dom7LiveListeners[event].push({ listener, proxyListener: handleLiveEvent, }); el.addEventListener(event, handleLiveEvent, capture); } } } return this; } function off(...args) { let [eventType, targetSelector, listener, capture] = args; if (typeof args[1] === 'function') { [eventType, listener, capture] = args; targetSelector = undefined; } if (!capture) capture = false; const events = eventType.split(' '); for (let i = 0; i < events.length; i += 1) { const event = events[i]; for (let j = 0; j < this.length; j += 1) { const el = this[j]; let handlers; if (!targetSelector && el.dom7Listeners) { handlers = el.dom7Listeners[event]; } else if (targetSelector && el.dom7LiveListeners) { handlers = el.dom7LiveListeners[event]; } if (handlers && handlers.length) { for (let k = handlers.length - 1; k >= 0; k -= 1) { const handler = handlers[k]; if (listener && handler.listener === listener) { el.removeEventListener(event, handler.proxyListener, capture); handlers.splice(k, 1); } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) { el.removeEventListener(event, handler.proxyListener, capture); handlers.splice(k, 1); } else if (!listener) { el.removeEventListener(event, handler.proxyListener, capture); handlers.splice(k, 1); } } } } } return this; } function trigger(...args) { const events = args[0].split(' '); const eventData = args[1]; for (let i = 0; i < events.length; i += 1) { const event = events[i]; for (let j = 0; j < this.length; j += 1) { const el = this[j]; let evt; try { evt = new win.CustomEvent(event, { detail: eventData, bubbles: true, cancelable: true, }); } catch (e) { evt = doc.createEvent('Event'); evt.initEvent(event, true, true); evt.detail = eventData; } // eslint-disable-next-line el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0); el.dispatchEvent(evt); el.dom7EventData = []; delete el.dom7EventData; } } return this; } function transitionEnd(callback) { const events = ['webkitTransitionEnd', 'transitionend']; const dom = this; let i; function fireCallBack(e) { /* jshint validthis:true */ if (e.target !== this) return; callback.call(this, e); for (i = 0; i < events.length; i += 1) { dom.off(events[i], fireCallBack); } } if (callback) { for (i = 0; i < events.length; i += 1) { dom.on(events[i], fireCallBack); } } return this; } function outerWidth(includeMargins) { if (this.length > 0) { if (includeMargins) { // eslint-disable-next-line const styles = this.styles(); return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left')); } return this[0].offsetWidth; } return null; } function outerHeight(includeMargins) { if (this.length > 0) { if (includeMargins) { // eslint-disable-next-line const styles = this.styles(); return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom')); } return this[0].offsetHeight; } return null; } function offset() { if (this.length > 0) { const el = this[0]; const box = el.getBoundingClientRect(); const body = doc.body; const clientTop = el.clientTop || body.clientTop || 0; const clientLeft = el.clientLeft || body.clientLeft || 0; const scrollTop = el === win ? win.scrollY : el.scrollTop; const scrollLeft = el === win ? win.scrollX : el.scrollLeft; return { top: (box.top + scrollTop) - clientTop, left: (box.left + scrollLeft) - clientLeft, }; } return null; } function styles() { if (this[0]) return win.getComputedStyle(this[0], null); return {}; } function css(props, value) { let i; if (arguments.length === 1) { if (typeof props === 'string') { if (this[0]) return win.getComputedStyle(this[0], null).getPropertyValue(props); } else { for (i = 0; i < this.length; i += 1) { // eslint-disable-next-line for (let prop in props) { this[i].style[prop] = props[prop]; } } return this; } } if (arguments.length === 2 && typeof props === 'string') { for (i = 0; i < this.length; i += 1) { this[i].style[props] = value; } return this; } return this; } // Iterate over the collection passing elements to `callback` function each(callback) { // Don't bother continuing without a callback if (!callback) return this; // Iterate over the current collection for (let i = 0; i < this.length; i += 1) { // If the callback returns false if (callback.call(this[i], i, this[i]) === false) { // End the loop early return this; } } // Return `this` to allow chained DOM operations return this; } function filter(callback) { const matchedItems = []; const dom = this; for (let i = 0; i < dom.length; i += 1) { if (callback.call(dom[i], i, dom[i])) matchedItems.push(dom[i]); } return new Dom7(matchedItems); } // eslint-disable-next-line function html(html) { if (typeof html === 'undefined') { return this[0] ? this[0].innerHTML : undefined; } for (let i = 0; i < this.length; i += 1) { this[i].innerHTML = html; } return this; } // eslint-disable-next-line function text(text) { if (typeof text === 'undefined') { if (this[0]) { return this[0].textContent.trim(); } return null; } for (let i = 0; i < this.length; i += 1) { this[i].textContent = text; } return this; } function is(selector) { const el = this[0]; let compareWith; let i; if (!el || typeof selector === 'undefined') return false; if (typeof selector === 'string') { if (el.matches) return el.matches(selector); else if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector); else if (el.msMatchesSelector) return el.msMatchesSelector(selector); compareWith = $(selector); for (i = 0; i < compareWith.length; i += 1) { if (compareWith[i] === el) return true; } return false; } else if (selector === doc) return el === doc; else if (selector === win) return el === win; if (selector.nodeType || selector instanceof Dom7) { compareWith = selector.nodeType ? [selector] : selector; for (i = 0; i < compareWith.length; i += 1) { if (compareWith[i] === el) return true; } return false; } return false; } function index() { let child = this[0]; let i; if (child) { i = 0; // eslint-disable-next-line while ((child = child.previousSibling) !== null) { if (child.nodeType === 1) i += 1; } return i; } return undefined; } // eslint-disable-next-line function eq(index) { if (typeof index === 'undefined') return this; const length = this.length; let returnIndex; if (index > length - 1) { return new Dom7([]); } if (index < 0) { returnIndex = length + index; if (returnIndex < 0) return new Dom7([]); return new Dom7([this[returnIndex]]); } return new Dom7([this[index]]); } function append(...args) { let newChild; for (let k = 0; k < args.length; k += 1) { newChild = args[k]; for (let i = 0; i < this.length; i += 1) { if (typeof newChild === 'string') { const tempDiv = doc.createElement('div'); tempDiv.innerHTML = newChild; while (tempDiv.firstChild) { this[i].appendChild(tempDiv.firstChild); } } else if (newChild instanceof Dom7) { for (let j = 0; j < newChild.length; j += 1) { this[i].appendChild(newChild[j]); } } else { this[i].appendChild(newChild); } } } return this; } function prepend(newChild) { let i; let j; for (i = 0; i < this.length; i += 1) { if (typeof newChild === 'string') { const tempDiv = doc.createElement('div'); tempDiv.innerHTML = newChild; for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) { this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]); } } else if (newChild instanceof Dom7) { for (j = 0; j < newChild.length; j += 1) { this[i].insertBefore(newChild[j], this[i].childNodes[0]); } } else { this[i].insertBefore(newChild, this[i].childNodes[0]); } } return this; } function next(selector) { if (this.length > 0) { if (selector) { if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) { return new Dom7([this[0].nextElementSibling]); } return new Dom7([]); } if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]); return new Dom7([]); } return new Dom7([]); } function nextAll(selector) { const nextEls = []; let el = this[0]; if (!el) return new Dom7([]); while (el.nextElementSibling) { const next = el.nextElementSibling; // eslint-disable-line if (selector) { if ($(next).is(selector)) nextEls.push(next); } else nextEls.push(next); el = next; } return new Dom7(nextEls); } function prev(selector) { if (this.length > 0) { const el = this[0]; if (selector) { if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) { return new Dom7([el.previousElementSibling]); } return new Dom7([]); } if (el.previousElementSibling) return new Dom7([el.previousElementSibling]); return new Dom7([]); } return new Dom7([]); } function prevAll(selector) { const prevEls = []; let el = this[0]; if (!el) return new Dom7([]); while (el.previousElementSibling) { const prev = el.previousElementSibling; // eslint-disable-line if (selector) { if ($(prev).is(selector)) prevEls.push(prev); } else prevEls.push(prev); el = prev; } return new Dom7(prevEls); } function parent(selector) { const parents = []; // eslint-disable-line for (let i = 0; i < this.length; i += 1) { if (this[i].parentNode !== null) { if (selector) { if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode); } else { parents.push(this[i].parentNode); } } } return $(unique(parents)); } function parents(selector) { const parents = []; // eslint-disable-line for (let i = 0; i < this.length; i += 1) { let parent = this[i].parentNode; // eslint-disable-line while (parent) { if (selector) { if ($(parent).is(selector)) parents.push(parent); } else { parents.push(parent); } parent = parent.parentNode; } } return $(unique(parents)); } function closest(selector) { let closest = this; // eslint-disable-line if (typeof selector === 'undefined') { return new Dom7([]); } if (!closest.is(selector)) { closest = closest.parents(selector).eq(0); } return closest; } function find(selector) { const foundElements = []; for (let i = 0; i < this.length; i += 1) { const found = this[i].querySelectorAll(selector); for (let j = 0; j < found.length; j += 1) { foundElements.push(found[j]); } } return new Dom7(foundElements); } function children(selector) { const children = []; // eslint-disable-line for (let i = 0; i < this.length; i += 1) { const childNodes = this[i].childNodes; for (let j = 0; j < childNodes.length; j += 1) { if (!selector) { if (childNodes[j].nodeType === 1) children.push(childNodes[j]); } else if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) { children.push(childNodes[j]); } } } return new Dom7(unique(children)); } function remove() { for (let i = 0; i < this.length; i += 1) { if (this[i].parentNode) this[i].parentNode.removeChild(this[i]); } return this; } function add(...args) { const dom = this; let i; let j; for (i = 0; i < args.length; i += 1) { const toAdd = $(args[i]); for (j = 0; j < toAdd.length; j += 1) { dom[dom.length] = toAdd[j]; dom.length += 1; } } return dom; } const Methods = { addClass, removeClass, hasClass, toggleClass, attr, removeAttr, data, transform, transition, on, off, trigger, transitionEnd, outerWidth, outerHeight, offset, css, each, html, text, is, index, eq, append, prepend, next, nextAll, prev, prevAll, parent, parents, closest, find, children, filter, remove, add, styles, }; Object.keys(Methods).forEach((methodName) => { $.fn[methodName] = $.fn[methodName] || Methods[methodName]; }); const Utils = { deleteProps(obj) { const object = obj; Object.keys(object).forEach((key) => { try { object[key] = null; } catch (e) { // no getter for object } try { delete object[key]; } catch (e) { // something got wrong } }); }, nextTick(callback, delay = 0) { return setTimeout(callback, delay); }, now() { return Date.now(); }, getTranslate(el, axis = 'x') { let matrix; let curTransform; let transformMatrix; const curStyle = win.getComputedStyle(el, null); if (win.WebKitCSSMatrix) { curTransform = curStyle.transform || curStyle.webkitTransform; if (curTransform.split(',').length > 6) { curTransform = curTransform.split(', ').map((a) => a.replace(',', '.')).join(', '); } // Some old versions of Webkit choke when 'none' is passed; pass // empty string instead in this case transformMatrix = new win.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform); } else { transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); matrix = transformMatrix.toString().split(','); } if (axis === 'x') { // Latest Chrome and webkits Fix if (win.WebKitCSSMatrix) curTransform = transformMatrix.m41; // Crazy IE10 Matrix else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); // Normal Browsers else curTransform = parseFloat(matrix[4]); } if (axis === 'y') { // Latest Chrome and webkits Fix if (win.WebKitCSSMatrix) curTransform = transformMatrix.m42; // Crazy IE10 Matrix else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); // Normal Browsers else curTransform = parseFloat(matrix[5]); } return curTransform || 0; }, parseUrlQuery(url) { const query = {}; let urlToParse = url || win.location.href; let i; let params; let param; let length; if (typeof urlToParse === 'string' && urlToParse.length) { urlToParse = urlToParse.indexOf('?') > -1 ? urlToParse.replace(/\S*\?/, '') : ''; params = urlToParse.split('&').filter((paramsPart) => paramsPart !== ''); length = params.length; for (i = 0; i < length; i += 1) { param = params[i].replace(/#\S+/g, '').split('='); query[decodeURIComponent(param[0])] = typeof param[1] === 'undefined' ? undefined : decodeURIComponent(param[1]) || ''; } } return query; }, isObject(o) { return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object; }, extend(...args) { const to = Object(args[0]); for (let i = 1; i < args.length; i += 1) { const nextSource = args[i]; if (nextSource !== undefined && nextSource !== null) { const keysArray = Object.keys(Object(nextSource)); for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) { const nextKey = keysArray[nextIndex]; const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { if (Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) { Utils.extend(to[nextKey], nextSource[nextKey]); } else if (!Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) { to[nextKey] = {}; Utils.extend(to[nextKey], nextSource[nextKey]); } else { to[nextKey] = nextSource[nextKey]; } } } } } return to; }, }; const Support = (function Support() { return { touch: !!(('ontouchstart' in win) || (win.DocumentTouch && doc instanceof win.DocumentTouch)), pointerEvents: !!win.PointerEvent && ('maxTouchPoints' in win.navigator) && win.navigator.maxTouchPoints >= 0, observer: (function checkObserver() { return ('MutationObserver' in win || 'WebkitMutationObserver' in win); }()), passiveListener: (function checkPassiveListener() { let supportsPassive = false; try { const opts = Object.defineProperty({}, 'passive', { // eslint-disable-next-line get() { supportsPassive = true; }, }); win.addEventListener('testPassiveListener', null, opts); } catch (e) { // No support } return supportsPassive; }()), gestures: (function checkGestures() { return 'ongesturestart' in win; }()), }; }()); class SwiperClass { constructor(params = {}) { const self = this; self.params = params; // Events self.eventsListeners = {}; if (self.params && self.params.on) { Object.keys(self.params.on).forEach((eventName) => { self.on(eventName, self.params.on[eventName]); }); } } on(events, handler, priority) { const self = this; if (typeof handler !== 'function') return self; const method = priority ? 'unshift' : 'push'; events.split(' ').forEach((event) => { if (!self.eventsListeners[event]) self.eventsListeners[event] = []; self.eventsListeners[event][method](handler); }); return self; } once(events, handler, priority) { const self = this; if (typeof handler !== 'function') return self; function onceHandler(...args) { self.off(events, onceHandler); if (onceHandler.f7proxy) { delete onceHandler.f7proxy; } handler.apply(self, args); } onceHandler.f7proxy = handler; return self.on(events, onceHandler, priority); } off(events, handler) { const self = this; if (!self.eventsListeners) return self; events.split(' ').forEach((event) => { if (typeof handler === 'undefined') { self.eventsListeners[event] = []; } else if (self.eventsListeners[event] && self.eventsListeners[event].length) { self.eventsListeners[event].forEach((eventHandler, index) => { if (eventHandler === handler || (eventHandler.f7proxy && eventHandler.f7proxy === handler)) { self.eventsListeners[event].splice(index, 1); } }); } }); return self; } emit(...args) { const self = this; if (!self.eventsListeners) return self; let events; let data; let context; if (typeof args[0] === 'string' || Array.isArray(args[0])) { events = args[0]; data = args.slice(1, args.length); context = self; } else { events = args[0].events; data = args[0].data; context = args[0].context || self; } const eventsArray = Array.isArray(events) ? events : events.split(' '); eventsArray.forEach((event) => { if (self.eventsListeners && self.eventsListeners[event]) { const handlers = []; self.eventsListeners[event].forEach((eventHandler) => { handlers.push(eventHandler); }); handlers.forEach((eventHandler) => { eventHandler.apply(context, data); }); } }); return self; } useModulesParams(instanceParams) { const instance = this; if (!instance.modules) return; Object.keys(instance.modules).forEach((moduleName) => { const module = instance.modules[moduleName]; // Extend params if (module.params) { Utils.extend(instanceParams, module.params); } }); } useModules(modulesParams = {}) { const instance = this; if (!instance.modules) return; Object.keys(instance.modules).forEach((moduleName) => { const module = instance.modules[moduleName]; const moduleParams = modulesParams[moduleName] || {}; // Extend instance methods and props if (module.instance) { Object.keys(module.instance).forEach((modulePropName) => { const moduleProp = module.instance[modulePropName]; if (typeof moduleProp === 'function') { instance[modulePropName] = moduleProp.bind(instance); } else { instance[modulePropName] = moduleProp; } }); } // Add event listeners if (module.on && instance.on) { Object.keys(module.on).forEach((moduleEventName) => { instance.on(moduleEventName, module.on[moduleEventName]); }); } // Module create callback if (module.create) { module.create.bind(instance)(moduleParams); } }); } static set components(components) { const Class = this; if (!Class.use) return; Class.use(components); } static installModule(module, ...params) { const Class = this; if (!Class.prototype.modules) Class.prototype.modules = {}; const name = module.name || (`${Object.keys(Class.prototype.modules).length}_${Utils.now()}`); Class.prototype.modules[name] = module; // Prototype if (module.proto) { Object.keys(module.proto).forEach((key) => { Class.prototype[key] = module.proto[key]; }); } // Class if (module.static) { Object.keys(module.static).forEach((key) => { Class[key] = module.static[key]; }); } // Callback if (module.install) { module.install.apply(Class, params); } return Class; } static use(module, ...params) { const Class = this; if (Array.isArray(module)) { module.forEach((m) => Class.installModule(m)); return Class; } return Class.installModule(module, ...params); } } function updateSize () { const swiper = this; let width; let height; const $el = swiper.$el; if (typeof swiper.params.width !== 'undefined') { width = swiper.params.width; } else { width = $el[0].clientWidth; } if (typeof swiper.params.height !== 'undefined') { height = swiper.params.height; } else { height = $el[0].clientHeight; } if ((width === 0 && swiper.isHorizontal()) || (height === 0 && swiper.isVertical())) { return; } // Subtract paddings width = width - parseInt($el.css('padding-left'), 10) - parseInt($el.css('padding-right'), 10); height = height - parseInt($el.css('padding-top'), 10) - parseInt($el.css('padding-bottom'), 10); Utils.extend(swiper, { width, height, size: swiper.isHorizontal() ? width : height, }); } function updateSlides () { const swiper = this; const params = swiper.params; const { $wrapperEl, size: swiperSize, rtlTranslate: rtl, wrongRTL, } = swiper; const isVirtual = swiper.virtual && params.virtual.enabled; const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length; const slides = $wrapperEl.children(`.${swiper.params.slideClass}`); const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length; let snapGrid = []; const slidesGrid = []; const slidesSizesGrid = []; function slidesForMargin(slideIndex) { if (!params.cssMode) return true; if (slideIndex === slides.length - 1) { return false; } return true; } let offsetBefore = params.slidesOffsetBefore; if (typeof offsetBefore === 'function') { offsetBefore = params.slidesOffsetBefore.call(swiper); } let offsetAfter = params.slidesOffsetAfter; if (typeof offsetAfter === 'function') { offsetAfter = params.slidesOffsetAfter.call(swiper); } const previousSnapGridLength = swiper.snapGrid.length; const previousSlidesGridLength = swiper.snapGrid.length; let spaceBetween = params.spaceBetween; let slidePosition = -offsetBefore; let prevSlideSize = 0; let index = 0; if (typeof swiperSize === 'undefined') { return; } if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiperSize; } swiper.virtualSize = -spaceBetween; // reset margins if (rtl) slides.css({ marginLeft: '', marginTop: '' }); else slides.css({ marginRight: '', marginBottom: '' }); let slidesNumberEvenToRows; if (params.slidesPerColumn > 1) { if (Math.floor(slidesLength / params.slidesPerColumn) === slidesLength / swiper.params.slidesPerColumn) { slidesNumberEvenToRows = slidesLength; } else { slidesNumberEvenToRows = Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn; } if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') { slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, params.slidesPerView * params.slidesPerColumn); } } // Calc slides let slideSize; const slidesPerColumn = params.slidesPerColumn; const slidesPerRow = slidesNumberEvenToRows / slidesPerColumn; const numFullColumns = Math.floor(slidesLength / params.slidesPerColumn); for (let i = 0; i < slidesLength; i += 1) { slideSize = 0; const slide = slides.eq(i); if (params.slidesPerColumn > 1) { // Set slides order let newSlideOrderIndex; let column; let row; if (params.slidesPerColumnFill === 'row' && params.slidesPerGroup > 1) { const groupIndex = Math.floor(i / (params.slidesPerGroup * params.slidesPerColumn)); const slideIndexInGroup = i - params.slidesPerColumn * params.slidesPerGroup * groupIndex; const columnsInGroup = groupIndex === 0 ? params.slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * slidesPerColumn * params.slidesPerGroup) / slidesPerColumn), params.slidesPerGroup); row = Math.floor(slideIndexInGroup / columnsInGroup); column = (slideIndexInGroup - row * columnsInGroup) + groupIndex * params.slidesPerGroup; newSlideOrderIndex = column + ((row * slidesNumberEvenToRows) / slidesPerColumn); slide .css({ '-webkit-box-ordinal-group': newSlideOrderIndex, '-moz-box-ordinal-group': newSlideOrderIndex, '-ms-flex-order': newSlideOrderIndex, '-webkit-order': newSlideOrderIndex, order: newSlideOrderIndex, }); } else if (params.slidesPerColumnFill === 'column') { column = Math.floor(i / slidesPerColumn); row = i - (column * slidesPerColumn); if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn - 1)) { row += 1; if (row >= slidesPerColumn) { row = 0; column += 1; } } } else { row = Math.floor(i / slidesPerRow); column = i - (row * slidesPerRow); } slide.css( `margin-${swiper.isHorizontal() ? 'top' : 'left'}`, (row !== 0 && params.spaceBetween) && (`${params.spaceBetween}px`) ); } if (slide.css('display') === 'none') continue; // eslint-disable-line if (params.slidesPerView === 'auto') { const slideStyles = win.getComputedStyle(slide[0], null); const currentTransform = slide[0].style.transform; const currentWebKitTransform = slide[0].style.webkitTransform; if (currentTransform) { slide[0].style.transform = 'none'; } if (currentWebKitTransform) { slide[0].style.webkitTransform = 'none'; } if (params.roundLengths) { slideSize = swiper.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true); } else { // eslint-disable-next-line if (swiper.isHorizontal()) { const width = parseFloat(slideStyles.getPropertyValue('width')); const paddingLeft = parseFloat(slideStyles.getPropertyValue('padding-left')); const paddingRight = parseFloat(slideStyles.getPropertyValue('padding-right')); const marginLeft = parseFloat(slideStyles.getPropertyValue('margin-left')); const marginRight = parseFloat(slideStyles.getPropertyValue('margin-right')); const boxSizing = slideStyles.getPropertyValue('box-sizing'); if (boxSizing && boxSizing === 'border-box') { slideSize = width + marginLeft + marginRight; } else { slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight; } } else { const height = parseFloat(slideStyles.getPropertyValue('height')); const paddingTop = parseFloat(slideStyles.getPropertyValue('padding-top')); const paddingBottom = parseFloat(slideStyles.getPropertyValue('padding-bottom')); const marginTop = parseFloat(slideStyles.getPropertyValue('margin-top')); const marginBottom = parseFloat(slideStyles.getPropertyValue('margin-bottom')); const boxSizing = slideStyles.getPropertyValue('box-sizing'); if (boxSizing && boxSizing === 'border-box') { slideSize = height + marginTop + marginBottom; } else { slideSize = height + paddingTop + paddingBottom + marginTop + marginBottom; } } } if (currentTransform) { slide[0].style.transform = currentTransform; } if (currentWebKitTransform) { slide[0].style.webkitTransform = currentWebKitTransform; } if (params.roundLengths) slideSize = Math.floor(slideSize); } else { slideSize = (swiperSize - ((params.slidesPerView - 1) * spaceBetween)) / params.slidesPerView; if (params.roundLengths) slideSize = Math.floor(slideSize); if (slides[i]) { if (swiper.isHorizontal()) { slides[i].style.width = `${slideSize}px`; } else { slides[i].style.height = `${slideSize}px`; } } } if (slides[i]) { slides[i].swiperSlideSize = slideSize; } slidesSizesGrid.push(slideSize); if (params.centeredSlides) { slidePosition = slidePosition + (slideSize / 2) + (prevSlideSize / 2) + spaceBetween; if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; if (i === 0) slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; if (params.roundLengths) slidePosition = Math.floor(slidePosition); if ((index) % params.slidesPerGroup === 0) snapGrid.push(slidePosition); slidesGrid.push(slidePosition); } else { if (params.roundLengths) slidePosition = Math.floor(slidePosition); if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition); slidesGrid.push(slidePosition); slidePosition = slidePosition + slideSize + spaceBetween; } swiper.virtualSize += slideSize + spaceBetween; prevSlideSize = slideSize; index += 1; } swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter; let newSlidesGrid; if ( rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) { $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` }); } if (params.setWrapperSize) { if (swiper.isHorizontal()) $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` }); else $wrapperEl.css({ height: `${swiper.virtualSize + params.spaceBetween}px` }); } if (params.slidesPerColumn > 1) { swiper.virtualSize = (slideSize + params.spaceBetween) * slidesNumberEvenToRows; swiper.virtualSize = Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween; if (swiper.isHorizontal()) $wrapperEl.css({ width: `${swiper.virtualSize + params.spaceBetween}px` }); else $wrapperEl.css({ height: `${swiper.virtualSize + params.spaceBetween}px` }); if (params.centeredSlides) { newSlidesGrid = []; for (let i = 0; i < snapGrid.length; i += 1) { let slidesGridItem = snapGrid[i]; if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem); if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem); } snapGrid = newSlidesGrid; } } // Remove last grid elements depending on width if (!params.centeredSlides) { newSlidesGrid = []; for (let i = 0; i < snapGrid.length; i += 1) { let slidesGridItem = snapGrid[i]; if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem); if (snapGrid[i] <= swiper.virtualSize - swiperSize) { newSlidesGrid.push(slidesGridItem); } } snapGrid = newSlidesGrid; if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) { snapGrid.push(swiper.virtualSize - swiperSize); } } if (snapGrid.length === 0) snapGrid = [0]; if (params.spaceBetween !== 0) { if (swiper.isHorizontal()) { if (rtl) slides.filter(slidesForMargin).css({ marginLeft: `${spaceBetween}px` }); else slides.filter(slidesForMargin).css({ marginRight: `${spaceBetween}px` }); } else slides.filter(slidesForMargin).css({ marginBottom: `${spaceBetween}px` }); } if (params.centeredSlides && params.centeredSlidesBounds) { let allSlidesSize = 0; slidesSizesGrid.forEach((slideSizeValue) => { allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0); }); allSlidesSize -= params.spaceBetween; const maxSnap = allSlidesSize - swiperSize; snapGrid = snapGrid.map((snap) => { if (snap < 0) return -offsetBefore; if (snap > maxSnap) return maxSnap + offsetAfter; return snap; }); } if (params.centerInsufficientSlides) { let allSlidesSize = 0; slidesSizesGrid.forEach((slideSizeValue) => { allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0); }); allSlidesSize -= params.spaceBetween; if (allSlidesSize < swiperSize) { const allSlidesOffset = (swiperSize - allSlidesSize) / 2; snapGrid.forEach((snap, snapIndex) => { snapGrid[snapIndex] = snap - allSlidesOffset; }); slidesGrid.forEach((snap, snapIndex) => { slidesGrid[snapIndex] = snap + allSlidesOffset; }); } } Utils.extend(swiper, { slides, snapGrid, slidesGrid, slidesSizesGrid, }); if (slidesLength !== previousSlidesLength) { swiper.emit('slidesLengthChange'); } if (snapGrid.length !== previousSnapGridLength) { if (swiper.params.watchOverflow) swiper.checkOverflow(); swiper.emit('snapGridLengthChange'); } if (slidesGrid.length !== previousSlidesGridLength) { swiper.emit('slidesGridLengthChange'); } if (params.watchSlidesProgress || params.watchSlidesVisibility) { swiper.updateSlidesOffset(); } } function updateAutoHeight (speed) { const swiper = this; const activeSlides = []; let newHeight = 0; let i; if (typeof speed === 'number') { swiper.setTransition(speed); } else if (speed === true) { swiper.setTransition(swiper.params.speed); } // Find slides currently in view if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) { if (swiper.params.centeredSlides) { swiper.visibleSlides.each((index, slide) => { activeSlides.push(slide); }); } else { for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) { const index = swiper.activeIndex + i; if (index > swiper.slides.length) break; activeSlides.push(swiper.slides.eq(index)[0]); } } } else { activeSlides.push(swiper.slides.eq(swiper.activeIndex)[0]); } // Find new height from highest slide in view for (i = 0; i < activeSlides.length; i += 1) { if (typeof activeSlides[i] !== 'undefined') { const height = activeSlides[i].offsetHeight; newHeight = height > newHeight ? height : newHeight; } } // Update Height if (newHeight) swiper.$wrapperEl.css('height', `${newHeight}px`); } function updateSlidesOffset () { const swiper = this; const slides = swiper.slides; for (let i = 0; i < slides.length; i += 1) { slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop; } } function updateSlidesProgress (translate = (this && this.translate) || 0) { const swiper = this; const params = swiper.params; const { slides, rtlTranslate: rtl } = swiper; if (slides.length === 0) return; if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset(); let offsetCenter = -translate; if (rtl) offsetCenter = translate; // Visible Slides slides.removeClass(params.slideVisibleClass); swiper.visibleSlidesIndexes = []; swiper.visibleSlides = []; for (let i = 0; i < slides.length; i += 1) { const slide = slides[i]; const slideProgress = ( (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0)) - slide.swiperSlideOffset ) / (slide.swiperSlideSize + params.spaceBetween); if (params.watchSlidesVisibility || (params.centeredSlides && params.autoHeight)) { const slideBefore = -(offsetCenter - slide.swiperSlideOffset); const slideAfter = slideBefore + swiper.slidesSizesGrid[i]; const isVisible = (slideBefore >= 0 && slideBefore < swiper.size - 1) || (slideAfter > 1 && slideAfter <= swiper.size) || (slideBefore <= 0 && slideAfter >= swiper.size); if (isVisible) { swiper.visibleSlides.push(slide); swiper.visibleSlidesIndexes.push(i); slides.eq(i).addClass(params.slideVisibleClass); } } slide.progress = rtl ? -slideProgress : slideProgress; } swiper.visibleSlides = $(swiper.visibleSlides); } function updateProgress (translate) { const swiper = this; if (typeof translate === 'undefined') { const multiplier = swiper.rtlTranslate ? -1 : 1; // eslint-disable-next-line translate = (swiper && swiper.translate && (swiper.translate * multiplier)) || 0; } const params = swiper.params; const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); let { progress, isBeginning, isEnd } = swiper; const wasBeginning = isBeginning; const wasEnd = isEnd; if (translatesDiff === 0) { progress = 0; isBeginning = true; isEnd = true; } else { progress