/*! * Splide.js * Version : 2.4.20 * License : MIT * Copyright: 2020 Naotoshi Fujita */ /******/ (function() { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ !function() { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = function(exports, definition) { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !function() { /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /******/ }(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ !function() { /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ }(); /******/ /************************************************************************/ // UNUSED EXPORTS: Splide // NAMESPACE OBJECT: ./src/js/constants/states.js var states_namespaceObject = {}; __webpack_require__.r(states_namespaceObject); __webpack_require__.d(states_namespaceObject, { "CREATED": function() { return CREATED; }, "DESTROYED": function() { return DESTROYED; }, "IDLE": function() { return IDLE; }, "MOUNTED": function() { return MOUNTED; }, "MOVING": function() { return MOVING; } }); ;// CONCATENATED MODULE: ./src/js/core/event.js /** * The function for providing an Event object simply managing events. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The function for providing an Event object simply managing events. */ /* harmony default export */ var core_event = (function () { /** * Store all event data. * * @type {Array} */ var data = []; var Event = { /** * Subscribe the given event(s). * * @param {string} events - An event name. Use space to separate multiple events. * Also, namespace is accepted by dot, such as 'resize.{namespace}'. * @param {function} handler - A callback function. * @param {Element} elm - Optional. Native event will be listened to when this arg is provided. * @param {Object} options - Optional. Options for addEventListener. */ on: function on(events, handler, elm, options) { if (elm === void 0) { elm = null; } if (options === void 0) { options = {}; } events.split(' ').forEach(function (event) { if (elm) { elm.addEventListener(event, handler, options); } data.push({ event: event, handler: handler, elm: elm, options: options }); }); }, /** * Unsubscribe the given event(s). * * @param {string} events - A event name or names split by space. * @param {Element} elm - Optional. removeEventListener() will be called when this arg is provided. */ off: function off(events, elm) { if (elm === void 0) { elm = null; } events.split(' ').forEach(function (event) { data = data.filter(function (item) { if (item && item.event === event && item.elm === elm) { unsubscribe(item); return false; } return true; }); }); }, /** * Emit an event. * This method is only for custom events. * * @param {string} event - An event name. * @param {*} args - Any number of arguments passed to handlers. */ emit: function emit(event) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } data.forEach(function (item) { if (!item.elm && item.event.split('.')[0] === event) { item.handler.apply(item, args); } }); }, /** * Clear event data. */ destroy: function destroy() { data.forEach(unsubscribe); data = []; } }; /** * Remove the registered event listener. * * @param {Object} item - An object containing event data. */ function unsubscribe(item) { if (item.elm) { item.elm.removeEventListener(item.event, item.handler, item.options); } } return Event; }); ;// CONCATENATED MODULE: ./src/js/core/state.js /** * The function providing a super simple state system. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The function providing a super simple state system. * * @param {string|number} initialState - Provide the initial state value. */ /* harmony default export */ var state = (function (initialState) { /** * Store the current state. * * @type {string|number} */ var curr = initialState; return { /** * Change state. * * @param {string|number} state - A new state. */ set: function set(state) { curr = state; }, /** * Verify if the current state is given one or not. * * @param {string|number} state - A state name to be verified. * * @return {boolean} - True if the current state is the given one. */ is: function is(state) { return state === curr; } }; }); ;// CONCATENATED MODULE: ./src/js/utils/object.js function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /** * Some utility functions related with Object, supporting IE. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ var keys = Object.keys; /** * Iterate an object like Array.forEach. * IE doesn't support forEach of HTMLCollection. * * @param {Object} obj - An object. * @param {function} callback - A function handling each value. Arguments are value, property and index. */ function each(obj, callback) { keys(obj).some(function (key, index) { return callback(obj[key], key, index); }); } /** * Return values of the given object as an array. * IE doesn't support Object.values. * * @param {Object} obj - An object. * * @return {Array} - An array containing all values of the given object. */ function values(obj) { return keys(obj).map(function (key) { return obj[key]; }); } /** * Check if the given subject is object or not. * * @param {*} subject - A subject to be verified. * * @return {boolean} - True if object, false otherwise. */ function isObject(subject) { return typeof subject === 'object'; } /** * Merge two objects deeply. * * @param {Object} to - An object where "from" is merged. * @param {Object} from - An object merged to "to". * * @return {Object} - A merged object. */ function merge(_ref, from) { var to = _extends({}, _ref); each(from, function (value, key) { if (isObject(value)) { if (!isObject(to[key])) { to[key] = {}; } to[key] = merge(to[key], value); } else { to[key] = value; } }); return to; } /** * Assign all properties "from" to "to" object. * * @param {Object} to - An object where properties are assigned. * @param {Object} from - An object whose properties are assigned to "to". * * @return {Object} - An assigned object. */ function object_assign(to, from) { keys(from).forEach(function (key) { if (!to[key]) { Object.defineProperty(to, key, Object.getOwnPropertyDescriptor(from, key)); } }); return to; } ;// CONCATENATED MODULE: ./src/js/utils/utils.js /** * A package of some miscellaneous utility functions. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Convert the given value to array. * * @param {*} value - Any value. * * @return {*[]} - Array containing the given value. */ function toArray(value) { return Array.isArray(value) ? value : [value]; } /** * Check if the given value is between min and max. * Min will be returned when the value is less than min or max will do when greater than max. * * @param {number} value - A number to be checked. * @param {number} m1 - Minimum or maximum number. * @param {number} m2 - Maximum or minimum number. * * @return {number} - A value itself, min or max. */ function between(value, m1, m2) { return Math.min(Math.max(value, m1 > m2 ? m2 : m1), m1 > m2 ? m1 : m2); } /** * The sprintf method with minimum functionality. * * @param {string} format - The string format. * @param {string|Array} replacements - Replacements accepting multiple arguments. * * @returns {string} - Converted string. */ function sprintf(format, replacements) { var i = 0; return format.replace(/%s/g, function () { return toArray(replacements)[i++]; }); } /** * Append px unit to the given subject if necessary. * * @param {number|string} value - A value that may not include an unit. * * @return {string} - If the value is string, return itself. * If number, do value + "px". An empty string, otherwise. */ function unit(value) { var type = typeof value; if (type === 'number' && value > 0) { return parseFloat(value) + 'px'; } return type === 'string' ? value : ''; } /** * Pad start with 0. * * @param {number} number - A number to be filled with 0. * * @return {string|number} - Padded number. */ function pad(number) { return number < 10 ? '0' + number : number; } /** * Convert the given value to pixel. * * @param {Element} root - Root element where a dummy div is appended. * @param {string|number} value - CSS value to be converted, such as 10rem. * * @return {number} - Pixel. */ function toPixel(root, value) { if (typeof value === 'string') { var div = create('div', {}); applyStyle(div, { position: 'absolute', width: value }); append(root, div); value = div.clientWidth; dom_remove(div); } return +value || 0; } ;// CONCATENATED MODULE: ./src/js/utils/dom.js /** * Some utility functions related with DOM. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Find the first element matching the given selector. * Be aware that all selectors after a space are ignored. * * @param {Element|Node} elm - An ancestor element. * @param {string} selector - DOMString. * * @return {Element|null} - A found element or null. */ function find(elm, selector) { return elm ? elm.querySelector(selector.split(' ')[0]) : null; } /** * Find a first child having the given tag or class name. * * @param {Element} parent - A parent element. * @param {string} tagOrClassName - A tag or class name. * * @return {Element|undefined} - A found element on success or undefined on failure. */ function child(parent, tagOrClassName) { return children(parent, tagOrClassName)[0]; } /** * Return chile elements that matches the provided tag or class name. * * @param {Element} parent - A parent element. * @param {string} tagOrClassName - A tag or class name. * * @return {Element[]} - Found elements. */ function children(parent, tagOrClassName) { if (parent) { return values(parent.children).filter(function (child) { return hasClass(child, tagOrClassName.split(' ')[0]) || child.tagName === tagOrClassName; }); } return []; } /** * Create an element with some optional attributes. * * @param {string} tag - A tag name. * @param {Object} attrs - An object any attribute pairs of name and value. * * @return {Element} - A created element. */ function create(tag, attrs) { var elm = document.createElement(tag); each(attrs, function (value, key) { return setAttribute(elm, key, value); }); return elm; } /** * Convert HTML string to DOM node. * * @param {string} html - HTML string. * * @return {Node} - A created node. */ function domify(html) { var div = create('div', {}); div.innerHTML = html; return div.firstChild; } /** * Remove a given element from a DOM tree. * * @param {Element|Element[]} elms - Element(s) to be removed. */ function dom_remove(elms) { toArray(elms).forEach(function (elm) { if (elm) { var parent = elm.parentElement; parent && parent.removeChild(elm); } }); } /** * Append a child to a given element. * * @param {Element} parent - A parent element. * @param {Element} child - An element to be appended. */ function append(parent, child) { if (parent) { parent.appendChild(child); } } /** * Insert an element before the reference element. * * @param {Element|Node} ref - A reference element. * @param {Element} elm - An element to be inserted. */ function before(elm, ref) { if (elm && ref) { var parent = ref.parentElement; parent && parent.insertBefore(elm, ref); } } /** * Apply styles to the given element. * * @param {Element} elm - An element where styles are applied. * @param {Object} styles - Object containing styles. */ function applyStyle(elm, styles) { if (elm) { each(styles, function (value, prop) { if (value !== null) { elm.style[prop] = value; } }); } } /** * Add or remove classes to/from the element. * This function is for internal usage. * * @param {Element} elm - An element where classes are added. * @param {string|string[]} classes - Class names being added. * @param {boolean} remove - Whether to remove or add classes. */ function addOrRemoveClasses(elm, classes, remove) { if (elm) { toArray(classes).forEach(function (name) { if (name) { elm.classList[remove ? 'remove' : 'add'](name); } }); } } /** * Add classes to the element. * * @param {Element} elm - An element where classes are added. * @param {string|string[]} classes - Class names being added. */ function addClass(elm, classes) { addOrRemoveClasses(elm, classes, false); } /** * Remove a class from the element. * * @param {Element} elm - An element where classes are removed. * @param {string|string[]} classes - A class name being removed. */ function removeClass(elm, classes) { addOrRemoveClasses(elm, classes, true); } /** * Verify if the provided element has the class or not. * * @param {Element} elm - An element. * @param {string} className - A class name. * * @return {boolean} - True if the element has the class or false if not. */ function hasClass(elm, className) { return !!elm && elm.classList.contains(className); } /** * Set attribute to the given element. * * @param {Element} elm - An element where an attribute is assigned. * @param {string} name - Attribute name. * @param {string|number|boolean} value - Attribute value. */ function setAttribute(elm, name, value) { if (elm) { elm.setAttribute(name, value); } } /** * Get attribute from the given element. * * @param {Element} elm - An element where an attribute is assigned. * @param {string} name - Attribute name. * * @return {string} - The value of the given attribute if available. An empty string if not. */ function getAttribute(elm, name) { return elm ? elm.getAttribute(name) : ''; } /** * Remove attribute from the given element. * * @param {Element|Element[]} elms - An element where an attribute is removed. * @param {string|string[]} names - Attribute name. */ function removeAttribute(elms, names) { toArray(names).forEach(function (name) { toArray(elms).forEach(function (elm) { return elm && elm.removeAttribute(name); }); }); } /** * Return the Rect object of the provided object. * * @param {Element} elm - An element. * * @return {ClientRect|DOMRect} - A rect object. */ function getRect(elm) { return elm.getBoundingClientRect(); } /** * Trigger the given callback after all images contained by the element are loaded. * * @param {Element} elm - Element that may contain images. * @param {Function} callback - Callback function fired right after all images are loaded. */ function loaded(elm, callback) { var images = elm.querySelectorAll('img'); var length = images.length; if (length) { var count = 0; each(images, function (img) { img.onload = img.onerror = function () { if (++count === length) { callback(); } }; }); } else { // Trigger the callback immediately if there is no image. callback(); } } ;// CONCATENATED MODULE: ./src/js/constants/types.js /** * Export slider types. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Normal slider. * * @type {string} */ var SLIDE = 'slide'; /** * Loop after the last slide and before the first one. * * @type {string} */ var LOOP = 'loop'; /** * The track doesn't move. * * @type {string} */ var FADE = 'fade'; ;// CONCATENATED MODULE: ./src/js/transitions/slide/index.js /** * The component for general slide effect transition. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for general slide effect transition. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var slide = (function (Splide, Components) { /** * Hold the list element. * * @type {Element} */ var list; /** * Hold the onEnd callback function. * * @type {function} */ var endCallback; return { /** * Called when the component is mounted. */ mount: function mount() { list = Components.Elements.list; Splide.on('transitionend', function (e) { if (e.target === list && endCallback) { endCallback(); } }, list); }, /** * Start transition. * * @param {number} destIndex - Destination slide index that might be clone's. * @param {number} newIndex - New index. * @param {number} prevIndex - Previous index. * @param {Object} coord - Destination coordinates. * @param {function} done - Callback function must be invoked when transition is completed. */ start: function start(destIndex, newIndex, prevIndex, coord, done) { var options = Splide.options; var edgeIndex = Components.Controller.edgeIndex; var speed = options.speed; endCallback = done; if (Splide.is(SLIDE)) { if (prevIndex === 0 && newIndex >= edgeIndex || prevIndex >= edgeIndex && newIndex === 0) { speed = options.rewindSpeed || speed; } } applyStyle(list, { transition: "transform " + speed + "ms " + options.easing, transform: "translate(" + coord.x + "px," + coord.y + "px)" }); } }; }); ;// CONCATENATED MODULE: ./src/js/transitions/fade/index.js /** * The component for fade transition. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for fade transition. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var fade = (function (Splide, Components) { var Fade = { /** * Called when the component is mounted. * Apply transition style to the first slide. */ mount: function mount() { apply(Splide.index); }, /** * Start transition. * * @param {number} destIndex - Destination slide index that might be clone's. * @param {number} newIndex - New index. * @param {number} prevIndex - Previous index. * @param {Object} coord - Destination coordinates. * @param {function} done - Callback function must be invoked when transition is completed. */ start: function start(destIndex, newIndex, prevIndex, coord, done) { var track = Components.Elements.track; applyStyle(track, { height: unit(track.clientHeight) }); apply(newIndex); setTimeout(function () { done(); applyStyle(track, { height: '' }); }); } }; /** * Apply transition style to the slide specified by the given index. * * @param {number} index - A slide index. */ function apply(index) { var options = Splide.options; applyStyle(Components.Elements.slides[index], { transition: "opacity " + options.speed + "ms " + options.easing }); } return Fade; }); ;// CONCATENATED MODULE: ./src/js/transitions/index.js /** * Export transition components. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ ;// CONCATENATED MODULE: ./src/js/core/composer.js /** * Provide a function for composing components. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Compose components. * * @param {Splide} Splide - Splide instance. * @param {Object} Components - Additional components. * @param {function} Transition - Change component for transition. * * @return {Object} - An object containing all components. */ function compose(Splide, Components, Transition) { var components = {}; each(Components, function (Component, name) { components[name] = Component(Splide, components, name.toLowerCase()); }); if (!Transition) { Transition = Splide.is(FADE) ? fade : slide; } components.Transition = Transition(Splide, components); return components; } ;// CONCATENATED MODULE: ./src/js/utils/error.js /** * Utility functions for outputting logs. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Prefix of an error massage. * * @type {string} */ var MESSAGE_PREFIX = '[SPLIDE]'; /** * Display an error message on the browser console. * * @param {string} message - An error message. */ function error(message) { console.error(MESSAGE_PREFIX + " " + message); } /** * Check existence of the given object and throw an error if it doesn't. * * @throws {Error} * * @param {*} subject - A subject to be confirmed. * @param {string} message - An error message. */ function exist(subject, message) { if (!subject) { throw new Error(message); } } ;// CONCATENATED MODULE: ./src/js/constants/classes.js /** * Export class names. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * A root class name. * * @type {string} */ var ROOT = 'splide'; /** * The definition table of all classes for elements. * They might be modified by options. * * @type {Object} */ var ELEMENT_CLASSES = { root: ROOT, slider: ROOT + "__slider", track: ROOT + "__track", list: ROOT + "__list", slide: ROOT + "__slide", container: ROOT + "__slide__container", arrows: ROOT + "__arrows", arrow: ROOT + "__arrow", prev: ROOT + "__arrow--prev", next: ROOT + "__arrow--next", pagination: ROOT + "__pagination", page: ROOT + "__pagination__page", clone: ROOT + "__slide--clone", progress: ROOT + "__progress", bar: ROOT + "__progress__bar", autoplay: ROOT + "__autoplay", play: ROOT + "__play", pause: ROOT + "__pause", spinner: ROOT + "__spinner", sr: ROOT + "__sr" }; /** * Definitions of status classes. * * @type {Object} */ var STATUS_CLASSES = { active: 'is-active', visible: 'is-visible', loading: 'is-loading' }; ;// CONCATENATED MODULE: ./src/js/constants/i18n.js /** * Export i18n texts as object. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Texts for i18n. * * @type {Object} */ var I18N = { prev: 'Previous slide', next: 'Next slide', first: 'Go to first slide', last: 'Go to last slide', slideX: 'Go to slide %s', pageX: 'Go to page %s', play: 'Start autoplay', pause: 'Pause autoplay' }; ;// CONCATENATED MODULE: ./src/js/constants/defaults.js /** * Export default options. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ var DEFAULTS = { /** * Determine a slider type. * - 'slide': Regular slider. * - 'loop' : Carousel slider. * - 'fade' : Change slides with fade transition. perPage, drag options are ignored. * * @type {string} */ type: 'slide', /** * Whether to rewind a slider before the first slide or after the last one. * In "loop" mode, this option is ignored. * * @type {boolean} */ rewind: false, /** * Transition speed in milliseconds. * * @type {number} */ speed: 400, /** * Transition speed on rewind in milliseconds. * * @type {number} */ rewindSpeed: 0, /** * Whether to prevent any actions while a slider is transitioning. * If false, navigation, drag and swipe work while the slider is running. * Even so, it will be forced to wait for transition in some cases in the loop mode to shift a slider. * * @type {boolean} */ waitForTransition: true, /** * Define slider max width. * * @type {number} */ width: 0, /** * Define slider height. * * @type {number} */ height: 0, /** * Fix width of slides. CSS format is allowed such as 10em, 80% or 80vw. * perPage number will be ignored when this option is falsy. * * @type {number|string} */ fixedWidth: 0, /** * Fix height of slides. CSS format is allowed such as 10em, 80vh but % unit is not accepted. * heightRatio option will be ignored when this option is falsy. * * @type {number|string} */ fixedHeight: 0, /** * Determine height of slides by ratio to a slider width. * This will be ignored when the fixedHeight is provided. * * @type {number} */ heightRatio: 0, /** * If true, slide width will be determined by the element width itself. * - perPage/perMove should be 1. * * @type {boolean} */ autoWidth: false, /** * If true, slide height will be determined by the element width itself. * - perPage/perMove should be 1. * * @type {boolean} */ autoHeight: false, /** * Determine how many slides should be displayed per page. * * @type {number} */ perPage: 1, /** * Determine how many slides should be moved when a slider goes to next or perv. * * @type {number} */ perMove: 0, /** * Determine manually how many clones should be generated on the left and right side. * The total number of clones will be twice of this number. * * @type {number} */ clones: 0, /** * Start index. * * @type {number} */ start: 0, /** * Determine which slide should be focused if there are multiple slides in a page. * A string "center" is acceptable for centering slides. * * @type {boolean|number|string} */ focus: false, /** * Gap between slides. CSS format is allowed such as 1em. * * @type {number|string} */ gap: 0, /** * Set padding-left/right in horizontal mode or padding-top/bottom in vertical one. * Give a single value to set a same size for both sides or * do an object for different sizes. * Also, CSS format is allowed such as 1em. * * @example * - 10: Number * - '1em': CSS format. * - { left: 0, right: 20 }: Object for different sizes in horizontal mode. * - { top: 0, bottom: 20 }: Object for different sizes in vertical mode. * * @type {number|string|Object} */ padding: 0, /** * Whether to append arrows. * * @type {boolean} */ arrows: true, /** * Change the arrow SVG path like 'm7.61 0.807-2.12...'. * * @type {string} */ arrowPath: '', /** * Whether to append pagination(indicator dots) or not. * * @type {boolean} */ pagination: true, /** * Activate autoplay. * * @type {boolean} */ autoplay: false, /** * Autoplay interval in milliseconds. * * @type {number} */ interval: 5000, /** * Whether to stop autoplay when a slider is hovered. * * @type {boolean} */ pauseOnHover: true, /** * Whether to stop autoplay when a slider elements are focused. * True is recommended for accessibility. * * @type {boolean} */ pauseOnFocus: true, /** * Whether to reset progress of the autoplay timer when resumed. * * @type {boolean} */ resetProgress: true, /** * Loading images lazily. * Image src must be provided by a data-splide-lazy attribute. * * - false: Do nothing. * - 'nearby': Only images around an active slide will be loaded. * - 'sequential': All images will be sequentially loaded. * * @type {boolean|string} */ lazyLoad: false, /** * This option works only when a lazyLoad option is "nearby". * Determine how many pages(not slides) around an active slide should be loaded beforehand. * * @type {number} */ preloadPages: 1, /** * Easing for CSS transition. For example, linear, ease or cubic-bezier(). * * @type {string} */ easing: 'cubic-bezier(.42,.65,.27,.99)', /** * Whether to enable keyboard shortcuts * - true or 'global': Listen to keydown event of the document. * - 'focused': Listen to the keydown event of the slider root element. tabindex="0" will be added to the element. * - false: Disable keyboard shortcuts. * * @type {boolean|string} */ keyboard: 'global', /** * Whether to allow mouse drag and touch swipe. * * @type {boolean} */ drag: true, /** * The angle threshold for drag. * The slider starts moving only when the drag angle is less than this threshold. * * @type {number} */ dragAngleThreshold: 30, /** * Distance threshold for determining if the action is "flick" or "swipe". * When a drag distance is over this value, the action will be treated as "swipe", not "flick". * * @type {number} */ swipeDistanceThreshold: 150, /** * Velocity threshold for determining if the action is "flick" or "swipe". * Around 0.5 is recommended. * * @type {number} */ flickVelocityThreshold: .6, /** * Determine power of flick. The larger number this is, the farther a slider runs by flick. * Around 500 is recommended. * * @type {number} */ flickPower: 600, /** * Limit a number of pages to move by flick. * * @type {number} */ flickMaxPages: 1, /** * Slider direction. * - 'ltr': Left to right. * - 'rtl': Right to left. * - 'ttb': Top to bottom. * * @type {string} */ direction: 'ltr', /** * Set img src to background-image of its parent element. * Images with various sizes can be displayed as same dimension without cropping work. * fixedHeight or heightRatio is required. * * @type {boolean} */ cover: false, /** * Whether to enable accessibility(aria and screen reader texts) or not. * * @type {boolean} */ accessibility: true, /** * Whether to add tabindex="0" to visible slides or not. * * @type {boolean} */ slideFocus: true, /** * Determine if a slider is navigation for another. * Use "sync" API to synchronize two sliders. * * @type {boolean} */ isNavigation: false, /** * Whether to trim spaces before the fist slide or after the last one when "focus" is not 0. * * @type {boolean} */ trimSpace: true, /** * The "is-active" class is added after transition as default. * If true, it will be added before move. * * @type {boolean} */ updateOnMove: false, /** * Throttle duration in milliseconds for the resize event. * * @type {number} */ throttle: 100, /** * Whether to destroy a slider or not. * * @type {boolean} */ destroy: false, /** * Options for specific breakpoints. * * @example * { * 1000: { * perPage: 3, * gap: 20 * }, * 600: { * perPage: 1, * gap: 5, * } * } * * @type {boolean|Object} */ breakpoints: false, /** * Collection of class names. * * @see ./classes.js * * @type {Object} */ classes: ELEMENT_CLASSES, /** * Collection of i18n texts. * * @see ./i18n.js * * @type {Object} */ i18n: I18N }; ;// CONCATENATED MODULE: ./src/js/constants/states.js /** * Export state constants. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Splide has been just created. * * @type {number} */ var CREATED = 1; /** * All components have been mounted and initialized. * * @type {number} */ var MOUNTED = 2; /** * Splide is ready for transition. * * @type {number} */ var IDLE = 3; /** * Splide is moving. * * @type {number} */ var MOVING = 4; /** * Splide is moving. * * @type {number} */ var DESTROYED = 5; ;// CONCATENATED MODULE: ./src/js/splide.js function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } /** * The main class for applying Splide to an element. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The main class for applying Splide to an element, * providing some APIs to control the behavior. */ var Splide = /*#__PURE__*/function () { /** * Splide constructor. * * @throws {Error} When the given root element or selector is invalid. * * @param {Element|string} root - A selector for a root element or an element itself. * @param {Object} options - Optional. Options to change default behaviour. * @param {Object} Components - Optional. Components. */ function Splide(root, options, Components) { if (options === void 0) { options = {}; } if (Components === void 0) { Components = {}; } this.root = root instanceof Element ? root : document.querySelector(root); exist(this.root, 'An invalid element/selector was given.'); this.Components = null; this.Event = core_event(); this.State = state(CREATED); this.STATES = states_namespaceObject; this._o = merge(DEFAULTS, options); this._i = 0; this._c = Components; this._e = {}; // Extensions this._t = null; // Transition } /** * Compose and mount components. * * @param {Object} Extensions - Optional. Additional components. * @param {function} Transition - Optional. Set a custom transition component. * * @return {Splide|undefined} - This instance or undefined if an exception occurred. */ var _proto = Splide.prototype; _proto.mount = function mount(Extensions, Transition) { var _this = this; if (Extensions === void 0) { Extensions = this._e; } if (Transition === void 0) { Transition = this._t; } // Reset the state. this.State.set(CREATED); this._e = Extensions; this._t = Transition; this.Components = compose(this, merge(this._c, Extensions), Transition); try { each(this.Components, function (component, key) { var required = component.required; if (required === undefined || required) { component.mount && component.mount(); } else { delete _this.Components[key]; } }); } catch (e) { error(e.message); return; } var State = this.State; State.set(MOUNTED); each(this.Components, function (component) { component.mounted && component.mounted(); }); this.emit('mounted'); State.set(IDLE); this.emit('ready'); applyStyle(this.root, { visibility: 'visible' }); this.on('move drag', function () { return State.set(MOVING); }).on('moved dragged', function () { return State.set(IDLE); }); return this; } /** * Set sync target. * * @param {Splide} splide - A Splide instance. * * @return {Splide} - This instance. */ ; _proto.sync = function sync(splide) { this.sibling = splide; return this; } /** * Register callback fired on the given event(s). * * @param {string} events - An event name. Use space to separate multiple events. * Also, namespace is accepted by dot, such as 'resize.{namespace}'. * @param {function} handler - A callback function. * @param {Element} elm - Optional. Native event will be listened to when this arg is provided. * @param {Object} options - Optional. Options for addEventListener. * * @return {Splide} - This instance. */ ; _proto.on = function on(events, handler, elm, options) { if (elm === void 0) { elm = null; } if (options === void 0) { options = {}; } this.Event.on(events, handler, elm, options); return this; } /** * Unsubscribe the given event. * * @param {string} events - A event name. * @param {Element} elm - Optional. removeEventListener() will be called when this arg is provided. * * @return {Splide} - This instance. */ ; _proto.off = function off(events, elm) { if (elm === void 0) { elm = null; } this.Event.off(events, elm); return this; } /** * Emit an event. * * @param {string} event - An event name. * @param {*} args - Any number of arguments passed to handlers. */ ; _proto.emit = function emit(event) { var _this$Event; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } (_this$Event = this.Event).emit.apply(_this$Event, [event].concat(args)); return this; } /** * Go to the slide specified by the given control. * * @param {string|number} control - A control pattern. * @param {boolean} wait - Optional. Whether to wait for transition. */ ; _proto.go = function go(control, wait) { if (wait === void 0) { wait = this.options.waitForTransition; } if (this.State.is(IDLE) || this.State.is(MOVING) && !wait) { this.Components.Controller.go(control, false); } return this; } /** * Verify whether the slider type is the given one or not. * * @param {string} type - A slider type. * * @return {boolean} - True if the slider type is the provided type or false if not. */ ; _proto.is = function is(type) { return type === this._o.type; } /** * Insert a slide. * * @param {Element|string} slide - A slide element to be added. * @param {number} index - A slide will be added at the position. */ ; _proto.add = function add(slide, index) { if (index === void 0) { index = -1; } this.Components.Elements.add(slide, index, this.refresh.bind(this)); return this; } /** * Remove the slide designated by the index. * * @param {number} index - A slide index. */ ; _proto.remove = function remove(index) { this.Components.Elements.remove(index); this.refresh(); return this; } /** * Destroy all Slide objects and clones and recreate them again. */ ; _proto.refresh = function refresh() { this.emit('refresh:before').emit('refresh').emit('resize'); return this; } /** * Destroy the Splide. * "Completely" boolean is mainly for breakpoints. * * @param {boolean} completely - Destroy completely. */ ; _proto.destroy = function destroy(completely) { var _this2 = this; if (completely === void 0) { completely = true; } // Postpone destroy because it should be done after mount. if (this.State.is(CREATED)) { this.on('ready', function () { return _this2.destroy(completely); }); return; } values(this.Components).reverse().forEach(function (component) { component.destroy && component.destroy(completely); }); this.emit('destroy', completely); // Destroy all event handlers, including ones for native events. this.Event.destroy(); this.State.set(DESTROYED); return this; } /** * Return the current slide index. * * @return {number} - The current slide index. // */ ; _createClass(Splide, [{ key: "index", get: function get() { return this._i; } /** * Set the current slide index. * * @param {number|string} index - A new index. */ , set: function set(index) { this._i = parseInt(index); } /** * Return length of slides. * This is an alias of Elements.length. * * @return {number} - A number of slides. */ }, { key: "length", get: function get() { return this.Components.Elements.length; } /** * Return options. * * @return {Object} - Options object. */ }, { key: "options", get: function get() { return this._o; } /** * Set options with merging the given object to the current one. * * @param {Object} options - New options. */ , set: function set(options) { var created = this.State.is(CREATED); if (!created) { this.emit('update'); } this._o = merge(this._o, options); if (!created) { this.emit('updated', this._o); } } /** * Return the class list. * This is an alias of Splide.options.classList. * * @return {Object} - An object containing all class list. */ }, { key: "classes", get: function get() { return this._o.classes; } /** * Return the i18n strings. * This is an alias of Splide.options.i18n. * * @return {Object} - An object containing all i18n strings. */ }, { key: "i18n", get: function get() { return this._o.i18n; } }]); return Splide; }(); ;// CONCATENATED MODULE: ./src/js/components/options/index.js /** * The component for initializing options. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for initializing options. * * @param {Splide} Splide - A Splide instance. * * @return {Object} - The component object. */ /* harmony default export */ var options = (function (Splide) { /** * Retrieve options from the data attribute. * Note that IE10 doesn't support dataset property. * * @type {string} */ var options = getAttribute(Splide.root, 'data-splide'); if (options) { try { Splide.options = JSON.parse(options); } catch (e) { error(e.message); } } return { /** * Called when the component is mounted. */ mount: function mount() { if (Splide.State.is(CREATED)) { Splide.index = Splide.options.start; } } }; }); ;// CONCATENATED MODULE: ./src/js/constants/directions.js /** * Export layout modes. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Enumerate slides from left to right. * * @type {string} */ var LTR = 'ltr'; /** * Enumerate slides from right to left. * * @type {string} */ var RTL = 'rtl'; /** * Enumerate slides in a col. * * @type {string} */ var TTB = 'ttb'; ;// CONCATENATED MODULE: ./src/js/components/elements/slide.js /** * The sub component for handling each slide. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Events for restoring original styles. * * @type {string} */ var STYLE_RESTORE_EVENTS = 'update.slide'; /** * The sub component for handling each slide. * * @param {Splide} Splide - A Splide instance. * @param {number} index - An unique slide index. * @param {number} realIndex - Clones should pass a real slide index. * @param {Element} slide - A slide element. * * @return {Object} - The sub component object. */ /* harmony default export */ var elements_slide = (function (Splide, index, realIndex, slide) { /** * Whether to update "is-active" class before or after transition. * * @type {boolean} */ var updateOnMove = Splide.options.updateOnMove; /** * Events when the slide status is updated. * Append a namespace to remove listeners later. * * @type {string} */ var STATUS_UPDATE_EVENTS = 'ready.slide updated.slide resized.slide moved.slide' + (updateOnMove ? ' move.slide' : ''); /** * Slide sub component object. * * @type {Object} */ var Slide = { /** * Slide element. * * @type {Element} */ slide: slide, /** * Slide index. * * @type {number} */ index: index, /** * Real index for clones. * * @type {number} */ realIndex: realIndex, /** * Container element if available. * * @type {Element|undefined} */ container: child(slide, Splide.classes.container), /** * Whether this is a cloned slide or not. * * @type {boolean} */ isClone: realIndex > -1, /** * Called when the component is mounted. */ mount: function mount() { var _this = this; if (!this.isClone) { slide.id = Splide.root.id + "-slide" + pad(index + 1); } Splide.on(STATUS_UPDATE_EVENTS, function () { return _this.update(); }).on(STYLE_RESTORE_EVENTS, restoreStyles).on('click', function () { return Splide.emit('click', _this); }, slide); /* * Add "is-active" class to a clone element temporarily * and it will be removed on "moved" event. */ if (updateOnMove) { Splide.on('move.slide', function (newIndex) { if (newIndex === realIndex) { _update(true, false); } }); } // Make sure the slide is shown. applyStyle(slide, { display: '' }); // Hold the original styles. this.styles = getAttribute(slide, 'style') || ''; }, /** * Destroy. */ destroy: function destroy() { Splide.off(STATUS_UPDATE_EVENTS).off(STYLE_RESTORE_EVENTS).off('click', slide); removeClass(slide, values(STATUS_CLASSES)); restoreStyles(); removeAttribute(this.container, 'style'); }, /** * Update active and visible status. */ update: function update() { _update(this.isActive(), false); _update(this.isVisible(), true); }, /** * Check whether this slide is active or not. * * @return {boolean} - True if the slide is active or false if not. */ isActive: function isActive() { return Splide.index === index; }, /** * Check whether this slide is visible in the viewport or not. * * @return {boolean} - True if the slide is visible or false if not. */ isVisible: function isVisible() { var active = this.isActive(); if (Splide.is(FADE) || active) { return active; } var ceil = Math.ceil; var trackRect = getRect(Splide.Components.Elements.track); var slideRect = getRect(slide); if (Splide.options.direction === TTB) { return trackRect.top <= slideRect.top && slideRect.bottom <= ceil(trackRect.bottom); } return trackRect.left <= slideRect.left && slideRect.right <= ceil(trackRect.right); }, /** * Calculate how far this slide is from another slide and * return true if the distance is within the given number. * * @param {number} from - Index of a target slide. * @param {number} within - True if the slide is within this number. * * @return {boolean} - True if the slide is within the number or false otherwise. */ isWithin: function isWithin(from, within) { var diff = Math.abs(from - index); if (!Splide.is(SLIDE) && !this.isClone) { diff = Math.min(diff, Splide.length - diff); } return diff < within; } }; /** * Update classes for activity or visibility. * * @param {boolean} active - Is active/visible or not. * @param {boolean} forVisibility - Toggle classes for activity or visibility. */ function _update(active, forVisibility) { var type = forVisibility ? 'visible' : 'active'; var className = STATUS_CLASSES[type]; if (active) { addClass(slide, className); Splide.emit("" + type, Slide); } else { if (hasClass(slide, className)) { removeClass(slide, className); Splide.emit("" + (forVisibility ? 'hidden' : 'inactive'), Slide); } } } /** * Restore the original styles. */ function restoreStyles() { setAttribute(slide, 'style', Slide.styles); } return Slide; }); ;// CONCATENATED MODULE: ./src/js/components/elements/index.js /** * The component for main elements. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The property name for UID stored in a window object. * * @type {string} */ var UID_NAME = 'uid'; /** * The component for main elements. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var components_elements = (function (Splide, Components) { /** * Hold the root element. * * @type {Element} */ var root = Splide.root; /** * Hold the class list. * * @type {Object} */ var classes = Splide.classes; /** * Store Slide objects. * * @type {Array} */ var Slides = []; /* * Assign unique ID to the root element if it doesn't have the one. * Note that IE doesn't support padStart() to fill the uid by 0. */ if (!root.id) { window.splide = window.splide || {}; var uid = window.splide[UID_NAME] || 0; window.splide[UID_NAME] = ++uid; root.id = "splide" + pad(uid); } /** * Elements component object. * * @type {Object} */ var Elements = { /** * Called when the component is mounted. * Collect main elements and store them as member properties. */ mount: function mount() { var _this = this; this.init(); Splide.on('refresh', function () { _this.destroy(); _this.init(); }).on('updated', function () { removeClass(root, getClasses()); addClass(root, getClasses()); }); }, /** * Destroy. */ destroy: function destroy() { Slides.forEach(function (Slide) { Slide.destroy(); }); Slides = []; removeClass(root, getClasses()); }, /** * Initialization. */ init: function init() { var _this2 = this; collect(); addClass(root, getClasses()); this.slides.forEach(function (slide, index) { _this2.register(slide, index, -1); }); }, /** * Register a slide to create a Slide object and handle its behavior. * * @param {Element} slide - A slide element. * @param {number} index - A unique index. This can be negative. * @param {number} realIndex - A real index for clones. Set -1 for real slides. */ register: function register(slide, index, realIndex) { var SlideObject = elements_slide(Splide, index, realIndex, slide); SlideObject.mount(); Slides.push(SlideObject); }, /** * Return the Slide object designated by the index. * Note that "find" is not supported by IE. * * @return {Object|undefined} - A Slide object if available. Undefined if not. */ getSlide: function getSlide(index) { return Slides.filter(function (Slide) { return Slide.index === index; })[0]; }, /** * Return all Slide objects. * * @param {boolean} includeClones - Whether to include cloned slides or not. * * @return {Object[]} - Slide objects. */ getSlides: function getSlides(includeClones) { return includeClones ? Slides : Slides.filter(function (Slide) { return !Slide.isClone; }); }, /** * Return Slide objects belonging to the given page. * * @param {number} page - A page number. * * @return {Object[]} - An array containing Slide objects. */ getSlidesByPage: function getSlidesByPage(page) { var idx = Components.Controller.toIndex(page); var options = Splide.options; var max = options.focus !== false ? 1 : options.perPage; return Slides.filter(function (_ref) { var index = _ref.index; return idx <= index && index < idx + max; }); }, /** * Insert a slide to a slider. * Need to refresh Splide after adding a slide. * * @param {Node|string} slide - A slide element to be added. * @param {number} index - A slide will be added at the position. * @param {Function} callback - Called right after the slide is added to the DOM tree. */ add: function add(slide, index, callback) { if (typeof slide === 'string') { slide = domify(slide); } if (slide instanceof Element) { var ref = this.slides[index]; // This will be removed in mount() of a Slide component. applyStyle(slide, { display: 'none' }); if (ref) { before(slide, ref); this.slides.splice(index, 0, slide); } else { append(this.list, slide); this.slides.push(slide); } loaded(slide, function () { callback && callback(slide); }); } }, /** * Remove a slide from a slider. * Need to refresh Splide after removing a slide. * * @param index - Slide index. */ remove: function remove(index) { dom_remove(this.slides.splice(index, 1)[0]); }, /** * Trigger the provided callback for each Slide object. * * @param {Function} callback - A callback function. The first argument will be the Slide object. */ each: function each(callback) { Slides.forEach(callback); }, /** * Return slides length without clones. * * @return {number} - Slide length. */ get length() { return this.slides.length; }, /** * Return "SlideObjects" length including clones. * * @return {number} - Slide length including clones. */ get total() { return Slides.length; } }; /** * Collect elements. */ function collect() { Elements.slider = child(root, classes.slider); Elements.track = find(root, "." + classes.track); Elements.list = child(Elements.track, classes.list); exist(Elements.track && Elements.list, 'Track or list was not found.'); Elements.slides = children(Elements.list, classes.slide); var arrows = findParts(classes.arrows); Elements.arrows = { prev: find(arrows, "." + classes.prev), next: find(arrows, "." + classes.next) }; var autoplay = findParts(classes.autoplay); Elements.bar = find(findParts(classes.progress), "." + classes.bar); Elements.play = find(autoplay, "." + classes.play); Elements.pause = find(autoplay, "." + classes.pause); Elements.track.id = Elements.track.id || root.id + "-track"; Elements.list.id = Elements.list.id || root.id + "-list"; } /** * Return class names for the root element. */ function getClasses() { var rootClass = classes.root; var options = Splide.options; return [rootClass + "--" + options.type, rootClass + "--" + options.direction, options.drag ? rootClass + "--draggable" : '', options.isNavigation ? rootClass + "--nav" : '', STATUS_CLASSES.active]; } /** * Find parts only from children of the root or track. * * @return {Element} - A found element or undefined. */ function findParts(className) { return child(root, className) || child(Elements.slider, className); } return Elements; }); ;// CONCATENATED MODULE: ./src/js/components/controller/index.js /** * The component for controlling the track. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ var floor = Math.floor; /** * The component for controlling the track. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var controller = (function (Splide, Components) { /** * Store current options. * * @type {Object} */ var options; /** * True if the slide is LOOP mode. * * @type {boolean} */ var isLoop; /** * Controller component object. * * @type {Object} */ var Controller = { /** * Called when the component is mounted. */ mount: function mount() { options = Splide.options; isLoop = Splide.is(LOOP); bind(); }, /** * Make track run by the given control. * - "+{i}" : Increment the slide index by i. * - "-{i}" : Decrement the slide index by i. * - "{i}" : Go to the slide whose index is i. * - ">" : Go to next page. * - "<" : Go to prev page. * - ">{i}" : Go to page i. * * @param {string|number} control - A control pattern. * @param {boolean} silently - Go to the destination without event emission. */ go: function go(control, silently) { var destIndex = this.trim(this.parse(control)); Components.Track.go(destIndex, this.rewind(destIndex), silently); }, /** * Parse the given control and return the destination index for the track. * * @param {string} control - A control target pattern. * * @return {number} - A parsed target. */ parse: function parse(control) { var index = Splide.index; var matches = String(control).match(/([+\-<>]+)(\d+)?/); var indicator = matches ? matches[1] : ''; var number = matches ? parseInt(matches[2]) : 0; switch (indicator) { case '+': index += number || 1; break; case '-': index -= number || 1; break; case '>': case '<': index = parsePage(number, index, indicator === '<'); break; default: index = parseInt(control); } return index; }, /** * Compute index from the given page number. * * @param {number} page - Page number. * * @return {number} - A computed page number. */ toIndex: function toIndex(page) { if (hasFocus()) { return page; } var length = Splide.length; var perPage = options.perPage; var index = page * perPage; index = index - (this.pageLength * perPage - length) * floor(index / length); // Adjustment for the last page. if (length - perPage <= index && index < length) { index = length - perPage; } return index; }, /** * Compute page number from the given slide index. * * @param {number} index - Slide index. * * @return {number} - A computed page number. */ toPage: function toPage(index) { if (hasFocus()) { return index; } var length = Splide.length; var perPage = options.perPage; // Make the last "perPage" number of slides belong to the last page. if (length - perPage <= index && index < length) { return floor((length - 1) / perPage); } return floor(index / perPage); }, /** * Trim the given index according to the current mode. * Index being returned could be less than 0 or greater than the length in Loop mode. * * @param {number} index - An index being trimmed. * * @return {number} - A trimmed index. */ trim: function trim(index) { if (!isLoop) { index = options.rewind ? this.rewind(index) : between(index, 0, this.edgeIndex); } return index; }, /** * Rewind the given index if it's out of range. * * @param {number} index - An index. * * @return {number} - A rewound index. */ rewind: function rewind(index) { var edge = this.edgeIndex; if (isLoop) { while (index > edge) { index -= edge + 1; } while (index < 0) { index += edge + 1; } } else { if (index > edge) { index = 0; } else if (index < 0) { index = edge; } } return index; }, /** * Check if the direction is "rtl" or not. * * @return {boolean} - True if "rtl" or false if not. */ isRtl: function isRtl() { return options.direction === RTL; }, /** * Return the page length. * * @return {number} - Max page number. */ get pageLength() { var length = Splide.length; return hasFocus() ? length : Math.ceil(length / options.perPage); }, /** * Return the edge index. * * @return {number} - Edge index. */ get edgeIndex() { var length = Splide.length; if (!length) { return 0; } if (hasFocus() || options.isNavigation || isLoop) { return length - 1; } return length - options.perPage; }, /** * Return the index of the previous slide. * * @return {number} - The index of the previous slide if available. -1 otherwise. */ get prevIndex() { var prev = Splide.index - 1; if (isLoop || options.rewind) { prev = this.rewind(prev); } return prev > -1 ? prev : -1; }, /** * Return the index of the next slide. * * @return {number} - The index of the next slide if available. -1 otherwise. */ get nextIndex() { var next = Splide.index + 1; if (isLoop || options.rewind) { next = this.rewind(next); } return Splide.index < next && next <= this.edgeIndex || next === 0 ? next : -1; } }; /** * Listen to some events. */ function bind() { Splide.on('move', function (newIndex) { Splide.index = newIndex; }).on('updated refresh', function (newOptions) { options = newOptions || options; Splide.index = between(Splide.index, 0, Controller.edgeIndex); }); } /** * Verify if the focus option is available or not. * * @return {boolean} - True if a slider has the focus option. */ function hasFocus() { return options.focus !== false; } /** * Return the next or previous page index computed by the page number and current index. * * @param {number} number - Specify the page number. * @param {number} index - Current index. * @param {boolean} prev - Prev or next. * * @return {number} - Slide index. */ function parsePage(number, index, prev) { if (number > -1) { return Controller.toIndex(number); } var perMove = options.perMove; var sign = prev ? -1 : 1; if (perMove) { return index + perMove * sign; } return Controller.toIndex(Controller.toPage(index) + sign); } return Controller; }); ;// CONCATENATED MODULE: ./src/js/components/track/index.js /** * The component for moving list in the track. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ var abs = Math.abs; /** * The component for moving list in the track. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var track = (function (Splide, Components) { /** * Hold the Layout component. * * @type {Object} */ var Layout; /** * Hold the Layout component. * * @type {Object} */ var Elements; /** * Store the list element. * * @type {Element} */ var list; /** * Whether the current direction is vertical or not. * * @type {boolean} */ var isVertical = Splide.options.direction === TTB; /** * Whether the slider type is FADE or not. * * @type {boolean} */ var isFade = Splide.is(FADE); /** * Whether the slider direction is RTL or not. * * @type {boolean} */ var isRTL = Splide.options.direction === RTL; /** * This will be true while transitioning from the last index to the first one. * * @type {boolean} */ var isLoopPending = false; /** * Sign for the direction. Only RTL mode uses the positive sign. * * @type {number} */ var sign = isRTL ? 1 : -1; /** * Track component object. * * @type {Object} */ var Track = { /** * Make public the sign defined locally. * * @type {number} */ sign: sign, /** * Called when the component is mounted. */ mount: function mount() { Elements = Components.Elements; Layout = Components.Layout; list = Elements.list; }, /** * Called after the component is mounted. * The resize event must be registered after the Layout's one is done. */ mounted: function mounted() { var _this = this; if (!isFade) { this.jump(0); Splide.on('mounted resize updated', function () { _this.jump(Splide.index); }); } }, /** * Go to the given destination index. * After arriving there, the track is jump to the new index without animation, mainly for loop mode. * * @param {number} destIndex - A destination index. * This can be negative or greater than slides length for reaching clones. * @param {number} newIndex - An actual new index. They are always same in Slide and Rewind mode. * @param {boolean} silently - If true, suppress emitting events. */ go: function go(destIndex, newIndex, silently) { var newPosition = getTrimmedPosition(destIndex); var prevIndex = Splide.index; // Prevent any actions while transitioning from the last index to the first one for jump. if (Splide.State.is(MOVING) && isLoopPending) { return; } isLoopPending = destIndex !== newIndex; if (!silently) { Splide.emit('move', newIndex, prevIndex, destIndex); } if (Math.abs(newPosition - this.position) >= 1 || isFade) { Components.Transition.start(destIndex, newIndex, prevIndex, this.toCoord(newPosition), function () { onTransitionEnd(destIndex, newIndex, prevIndex, silently); }); } else { if (destIndex !== prevIndex && Splide.options.trimSpace === 'move') { Components.Controller.go(destIndex + destIndex - prevIndex, silently); } else { onTransitionEnd(destIndex, newIndex, prevIndex, silently); } } }, /** * Move the track to the specified index. * * @param {number} index - A destination index where the track jumps. */ jump: function jump(index) { this.translate(getTrimmedPosition(index)); }, /** * Set the list position by CSS translate property. * * @param {number} position - A new position value. */ translate: function translate(position) { applyStyle(list, { transform: "translate" + (isVertical ? 'Y' : 'X') + "(" + position + "px)" }); }, /** * Cancel the transition and set the list position. * Also, loop the slider if necessary. */ cancel: function cancel() { if (Splide.is(LOOP)) { this.shift(); } else { // Ensure the current position. this.translate(this.position); } applyStyle(list, { transition: '' }); }, /** * Shift the slider if it exceeds borders on the edge. */ shift: function shift() { var position = abs(this.position); var left = abs(this.toPosition(0)); var right = abs(this.toPosition(Splide.length)); var innerSize = right - left; if (position < left) { position += innerSize; } else if (position > right) { position -= innerSize; } this.translate(sign * position); }, /** * Trim redundant spaces on the left or right edge if necessary. * * @param {number} position - Position value to be trimmed. * * @return {number} - Trimmed position. */ trim: function trim(position) { if (!Splide.options.trimSpace || Splide.is(LOOP)) { return position; } var edge = sign * (Layout.totalSize() - Layout.size - Layout.gap); return between(position, edge, 0); }, /** * Calculate the closest slide index from the given position. * * @param {number} position - A position converted to an slide index. * * @return {number} - The closest slide index. */ toIndex: function toIndex(position) { var _this2 = this; var index = 0; var minDistance = Infinity; Elements.getSlides(true).forEach(function (Slide) { var slideIndex = Slide.index; var distance = abs(_this2.toPosition(slideIndex) - position); if (distance < minDistance) { minDistance = distance; index = slideIndex; } }); return index; }, /** * Return coordinates object by the given position. * * @param {number} position - A position value. * * @return {Object} - A coordinates object. */ toCoord: function toCoord(position) { return { x: isVertical ? 0 : position, y: isVertical ? position : 0 }; }, /** * Calculate the track position by a slide index. * * @param {number} index - Slide index. * * @return {Object} - Calculated position. */ toPosition: function toPosition(index) { var position = Layout.totalSize(index) - Layout.slideSize(index) - Layout.gap; return sign * (position + this.offset(index)); }, /** * Return the current offset value, considering direction. * * @return {number} - Offset amount. */ offset: function offset(index) { var focus = Splide.options.focus; var slideSize = Layout.slideSize(index); if (focus === 'center') { return -(Layout.size - slideSize) / 2; } return -(parseInt(focus) || 0) * (slideSize + Layout.gap); }, /** * Return the current position. * This returns the correct position even while transitioning by CSS. * * @return {number} - Current position. */ get position() { var prop = isVertical ? 'top' : isRTL ? 'right' : 'left'; return getRect(list)[prop] - (getRect(Elements.track)[prop] - Layout.padding[prop] * sign); } }; /** * Called whenever slides arrive at a destination. * * @param {number} destIndex - A destination index. * @param {number} newIndex - A new index. * @param {number} prevIndex - A previous index. * @param {boolean} silently - If true, suppress emitting events. */ function onTransitionEnd(destIndex, newIndex, prevIndex, silently) { applyStyle(list, { transition: '' }); isLoopPending = false; if (!isFade) { Track.jump(newIndex); } if (!silently) { Splide.emit('moved', newIndex, prevIndex, destIndex); } } /** * Convert index to the trimmed position. * * @return {number} - Trimmed position. */ function getTrimmedPosition(index) { return Track.trim(Track.toPosition(index)); } return Track; }); ;// CONCATENATED MODULE: ./src/js/components/clones/index.js /** * The component for cloning some slides for "loop" mode of the track. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for cloning some slides for "loop" mode of the track. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var clones = (function (Splide, Components) { /** * Store information of all clones. * * @type {Array} */ var clones = []; /** * Store the current clone count on one side. * * @type {number} */ var cloneCount = 0; /** * Keep Elements component. * * @type {Object} */ var Elements = Components.Elements; /** * Clones component object. * * @type {Object} */ var Clones = { /** * Called when the component is mounted. */ mount: function mount() { var _this = this; if (Splide.is(LOOP)) { init(); Splide.on('refresh:before', function () { _this.destroy(); }).on('refresh', init).on('resize', function () { if (cloneCount !== getCloneCount()) { // Destroy before refresh not to collect clones by the Elements component. _this.destroy(); Splide.refresh(); } }); } }, /** * Destroy. */ destroy: function destroy() { dom_remove(clones); clones = []; }, /** * Return all clones. * * @return {Element[]} - Cloned elements. */ get clones() { return clones; }, /** * Return clone length. * * @return {number} - A length of clones. */ get length() { return clones.length; } }; /** * Initialization. */ function init() { Clones.destroy(); cloneCount = getCloneCount(); generateClones(cloneCount); } /** * Generate and append/prepend clones. * * @param {number} count - The half number of clones. */ function generateClones(count) { var length = Elements.length, register = Elements.register; if (length) { var slides = Elements.slides; while (slides.length < count) { slides = slides.concat(slides); } // Clones after the last element. slides.slice(0, count).forEach(function (elm, index) { var clone = cloneDeeply(elm); append(Elements.list, clone); clones.push(clone); register(clone, index + length, index % length); }); // Clones before the first element. slides.slice(-count).forEach(function (elm, index) { var clone = cloneDeeply(elm); before(clone, slides[0]); clones.push(clone); register(clone, index - count, (length + index - count % length) % length); }); } } /** * Return half count of clones to be generated. * Clone count is determined by: * - "clones" value in the options. * - Number of slides that can be placed in a view in "fixed" mode. * - Max pages a flick action can move. * - Whether the slide length is enough for perPage. * * @return {number} - Count for clones. */ function getCloneCount() { var options = Splide.options; if (options.clones) { return options.clones; } // Use the slide length in autoWidth mode because the number cannot be calculated. var baseCount = options.autoWidth || options.autoHeight ? Elements.length : options.perPage; var dimension = options.direction === TTB ? 'Height' : 'Width'; var fixedSize = toPixel(Splide.root, options["fixed" + dimension]); if (fixedSize) { // Roughly calculate the count. This needs not to be strict. baseCount = Math.ceil(Elements.track["client" + dimension] / fixedSize); } return baseCount * (options.drag ? options.flickMaxPages + 1 : 1); } /** * Clone deeply the given element. * * @param {Element} elm - An element being duplicated. * * @return {Node} - A cloned node(element). */ function cloneDeeply(elm) { var clone = elm.cloneNode(true); addClass(clone, Splide.classes.clone); // ID should not be duplicated. removeAttribute(clone, 'id'); return clone; } return Clones; }); ;// CONCATENATED MODULE: ./src/js/components/layout/directions/horizontal.js /** * The resolver component for horizontal layout. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The resolver component for horizontal layout. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The resolver object. */ /* harmony default export */ var horizontal = (function (Splide, Components) { /** * Keep the Elements component. * * @type {string} */ var Elements = Components.Elements; /** * Keep the root element. * * @type {Element} */ var root = Splide.root; /** * Keep the track element. * * @type {Element} */ var track; /** * Keep the latest options. * * @type {Element} */ var options = Splide.options; return { /** * Margin property name. * * @type {string} */ margin: 'margin' + (options.direction === RTL ? 'Left' : 'Right'), /** * Always 0 because the height will be determined by inner contents. * * @type {number} */ height: 0, /** * Initialization. */ init: function init() { this.resize(); }, /** * Resize gap and padding. * This must be called on init. */ resize: function resize() { options = Splide.options; track = Elements.track; this.gap = toPixel(root, options.gap); var padding = options.padding; var left = toPixel(root, padding.left || padding); var right = toPixel(root, padding.right || padding); this.padding = { left: left, right: right }; applyStyle(track, { paddingLeft: unit(left), paddingRight: unit(right) }); }, /** * Return total width from the left of the list to the right of the slide specified by the provided index. * * @param {number} index - Optional. A slide index. If undefined, total width of the slider will be returned. * * @return {number} - Total width to the right side of the specified slide, or 0 for an invalid index. */ totalWidth: function totalWidth(index) { if (index === void 0) { index = Splide.length - 1; } var Slide = Elements.getSlide(index); var width = 0; if (Slide) { var slideRect = getRect(Slide.slide); var listRect = getRect(Elements.list); if (options.direction === RTL) { width = listRect.right - slideRect.left; } else { width = slideRect.right - listRect.left; } width += this.gap; } return width; }, /** * Return the slide width in px. * * @param {number} index - Slide index. * * @return {number} - The slide width. */ slideWidth: function slideWidth(index) { if (options.autoWidth) { var Slide = Elements.getSlide(index); return Slide ? Slide.slide.offsetWidth : 0; } var width = options.fixedWidth || (this.width + this.gap) / options.perPage - this.gap; return toPixel(root, width); }, /** * Return the slide height in px. * * @return {number} - The slide height. */ slideHeight: function slideHeight() { var height = options.height || options.fixedHeight || this.width * options.heightRatio; return toPixel(root, height); }, /** * Return slider width without padding. * * @return {number} - Current slider width. */ get width() { return track.clientWidth - this.padding.left - this.padding.right; } }; }); ;// CONCATENATED MODULE: ./src/js/components/layout/directions/vertical.js /** * The resolver component for vertical layout. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The resolver component for vertical layout. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The resolver object. */ /* harmony default export */ var vertical = (function (Splide, Components) { /** * Keep the Elements component. * * @type {string} */ var Elements = Components.Elements; /** * Keep the root element. * * @type {Element} */ var root = Splide.root; /** * Keep the track element. * * @type {Element} */ var track; /** * Keep the latest options. * * @type {Element} */ var options; return { /** * Margin property name. * * @type {string} */ margin: 'marginBottom', /** * Initialization. */ init: function init() { this.resize(); }, /** * Resize gap and padding. * This must be called on init. */ resize: function resize() { options = Splide.options; track = Elements.track; this.gap = toPixel(root, options.gap); var padding = options.padding; var top = toPixel(root, padding.top || padding); var bottom = toPixel(root, padding.bottom || padding); this.padding = { top: top, bottom: bottom }; applyStyle(track, { paddingTop: unit(top), paddingBottom: unit(bottom) }); }, /** * Return total height from the top of the list to the bottom of the slide specified by the provided index. * * @param {number} index - Optional. A slide index. If undefined, total height of the slider will be returned. * * @return {number} - Total height to the bottom of the specified slide, or 0 for an invalid index. */ totalHeight: function totalHeight(index) { if (index === void 0) { index = Splide.length - 1; } var Slide = Elements.getSlide(index); if (Slide) { return getRect(Slide.slide).bottom - getRect(Elements.list).top + this.gap; } return 0; }, /** * Return the slide width in px. * * @return {number} - The slide width. */ slideWidth: function slideWidth() { return toPixel(root, options.fixedWidth || this.width); }, /** * Return the slide height in px. * * @param {number} index - Slide index. * * @return {number} - The slide height. */ slideHeight: function slideHeight(index) { if (options.autoHeight) { var Slide = Elements.getSlide(index); return Slide ? Slide.slide.offsetHeight : 0; } var height = options.fixedHeight || (this.height + this.gap) / options.perPage - this.gap; return toPixel(root, height); }, /** * Return slider width without padding. * * @return {number} - Current slider width. */ get width() { return track.clientWidth; }, /** * Return slide height without padding. * * @return {number} - Slider height. */ get height() { var height = options.height || this.width * options.heightRatio; exist(height, '"height" or "heightRatio" is missing.'); return toPixel(root, height) - this.padding.top - this.padding.bottom; } }; }); ;// CONCATENATED MODULE: ./src/js/utils/time.js /** * A package of utility functions related with time. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Simple throttle function that controls how often the given function is executed. * * @param {function} func - A function to be throttled. * @param {number} wait - Time in millisecond for interval of execution. * * @return {Function} - A debounced function. */ function throttle(func, wait) { var timeout; // Declare function by the "function" keyword to prevent "this" from being inherited. return function () { if (!timeout) { timeout = setTimeout(function () { func(); timeout = null; }, wait); } }; } /** * Custom setInterval function that provides progress rate as callback. * * @param {function} callback - A callback function fired every time the interval time passes. * @param {number} interval - Interval duration in milliseconds. * @param {function} progress - A callback function fired whenever the progress goes. * * @return {Object} - An object containing play() and pause() functions. */ function createInterval(callback, interval, progress) { var _window = window, requestAnimationFrame = _window.requestAnimationFrame; var start, elapse, rate, _pause = true; var step = function step(timestamp) { if (!_pause) { if (!start) { start = timestamp; if (rate && rate < 1) { start -= rate * interval; } } elapse = timestamp - start; rate = elapse / interval; if (elapse >= interval) { start = 0; rate = 1; callback(); } if (progress) { progress(rate); } requestAnimationFrame(step); } }; return { pause: function pause() { _pause = true; start = 0; }, play: function play(reset) { start = 0; if (reset) { rate = 0; } if (_pause) { _pause = false; requestAnimationFrame(step); } } }; } ;// CONCATENATED MODULE: ./src/js/components/layout/index.js /** * The component for handing slide layouts and their sizes. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for handing slide layouts and their sizes. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var layout = (function (Splide, Components) { /** * Keep the Elements component. * * @type {string} */ var Elements = Components.Elements; /** * Whether the slider is vertical or not. * * @type {boolean} */ var isVertical = Splide.options.direction === TTB; /** * Layout component object. * * @type {Object} */ var Layout = object_assign({ /** * Called when the component is mounted. */ mount: function mount() { bind(); init(); // The word "size" means width for a horizontal slider and height for a vertical slider. this.totalSize = isVertical ? this.totalHeight : this.totalWidth; this.slideSize = isVertical ? this.slideHeight : this.slideWidth; }, /** * Destroy the component. */ destroy: function destroy() { removeAttribute([Elements.list, Elements.track], 'style'); }, /** * Return the slider height on the vertical mode or width on the horizontal mode. * * @return {number} */ get size() { return isVertical ? this.height : this.width; } }, isVertical ? vertical(Splide, Components) : horizontal(Splide, Components)); /** * Init slider styles according to options. */ function init() { Layout.init(); applyStyle(Splide.root, { maxWidth: unit(Splide.options.width) }); Elements.each(function (Slide) { Slide.slide.style[Layout.margin] = unit(Layout.gap); }); resize(); } /** * Listen the resize native event with throttle. * Initialize when the component is mounted or options are updated. */ function bind() { Splide.on('resize load', throttle(function () { Splide.emit('resize'); }, Splide.options.throttle), window).on('resize', resize).on('updated refresh', init); } /** * Resize the track and slide elements. */ function resize() { var options = Splide.options; Layout.resize(); applyStyle(Elements.track, { height: unit(Layout.height) }); var slideHeight = options.autoHeight ? null : unit(Layout.slideHeight()); Elements.each(function (Slide) { applyStyle(Slide.container, { height: slideHeight }); applyStyle(Slide.slide, { width: options.autoWidth ? null : unit(Layout.slideWidth(Slide.index)), height: Slide.container ? null : slideHeight }); }); Splide.emit('resized'); } return Layout; }); ;// CONCATENATED MODULE: ./src/js/components/drag/index.js /** * The component for supporting mouse drag and swipe. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ var drag_abs = Math.abs; /** * If the absolute velocity is greater thant this value, * a slider always goes to a different slide after drag, not allowed to stay on a current slide. */ var MIN_VELOCITY = 0.1; /** * Adjust how much the track can be pulled on the first or last page. * The larger number this is, the farther the track moves. * This should be around 5 - 9. * * @type {number} */ var FRICTION_REDUCER = 7; /** * The component supporting mouse drag and swipe. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var drag = (function (Splide, Components) { /** * Store the Move component. * * @type {Object} */ var Track = Components.Track; /** * Store the Controller component. * * @type {Object} */ var Controller = Components.Controller; /** * Coordinate of the track on starting drag. * * @type {Object} */ var startCoord; /** * Analyzed info on starting drag. * * @type {Object|null} */ var startInfo; /** * Analyzed info being updated while dragging/swiping. * * @type {Object} */ var currentInfo; /** * Determine whether slides are being dragged or not. * * @type {boolean} */ var isDragging; /** * Whether the slider direction is vertical or not. * * @type {boolean} */ var isVertical = Splide.options.direction === TTB; /** * Axis for the direction. * * @type {string} */ var axis = isVertical ? 'y' : 'x'; /** * Drag component object. * * @type {Object} */ var Drag = { /** * Whether dragging is disabled or not. * * @type {boolean} */ disabled: false, /** * Called when the component is mounted. */ mount: function mount() { var _this = this; var Elements = Components.Elements; var track = Elements.track; Splide.on('touchstart mousedown', start, track).on('touchmove mousemove', move, track, { passive: false }).on('touchend touchcancel mouseleave mouseup dragend', end, track).on('mounted refresh', function () { // Prevent dragging an image or anchor itself. each(Elements.list.querySelectorAll('img, a'), function (elm) { Splide.off('dragstart', elm).on('dragstart', function (e) { e.preventDefault(); }, elm, { passive: false }); }); }).on('mounted updated', function () { _this.disabled = !Splide.options.drag; }); } }; /** * Called when the track starts to be dragged. * * @param {TouchEvent|MouseEvent} e - TouchEvent or MouseEvent object. */ function start(e) { if (!Drag.disabled && !isDragging) { // These prams are used to evaluate whether the slider should start moving. init(e); } } /** * Initialize parameters. * * @param {TouchEvent|MouseEvent} e - TouchEvent or MouseEvent object. */ function init(e) { startCoord = Track.toCoord(Track.position); startInfo = analyze(e, {}); currentInfo = startInfo; } /** * Called while the track being dragged. * * @param {TouchEvent|MouseEvent} e - TouchEvent or MouseEvent object. */ function move(e) { if (startInfo) { currentInfo = analyze(e, startInfo); if (isDragging) { if (e.cancelable) { e.preventDefault(); } if (!Splide.is(FADE)) { var position = startCoord[axis] + currentInfo.offset[axis]; Track.translate(resist(position)); } } else { if (shouldMove(currentInfo)) { Splide.emit('drag', startInfo); isDragging = true; Track.cancel(); // These params are actual drag data. init(e); } } } } /** * Determine whether to start moving the track or not by drag angle. * * @param {Object} info - An information object. * * @return {boolean} - True if the track should be moved or false if not. */ function shouldMove(_ref) { var offset = _ref.offset; if (Splide.State.is(MOVING) && Splide.options.waitForTransition) { return false; } var angle = Math.atan(drag_abs(offset.y) / drag_abs(offset.x)) * 180 / Math.PI; if (isVertical) { angle = 90 - angle; } return angle < Splide.options.dragAngleThreshold; } /** * Resist dragging the track on the first/last page because there is no more. * * @param {number} position - A position being applied to the track. * * @return {Object} - Adjusted position. */ function resist(position) { if (Splide.is(SLIDE)) { var sign = Track.sign; var _start = sign * Track.trim(Track.toPosition(0)); var _end = sign * Track.trim(Track.toPosition(Controller.edgeIndex)); position *= sign; if (position < _start) { position = _start - FRICTION_REDUCER * Math.log(_start - position); } else if (position > _end) { position = _end + FRICTION_REDUCER * Math.log(position - _end); } position *= sign; } return position; } /** * Called when dragging ends. */ function end() { startInfo = null; if (isDragging) { Splide.emit('dragged', currentInfo); go(currentInfo); isDragging = false; } } /** * Go to the slide determined by the analyzed data. * * @param {Object} info - An info object. */ function go(info) { var velocity = info.velocity[axis]; var absV = drag_abs(velocity); if (absV > 0) { var options = Splide.options; var index = Splide.index; var sign = velocity < 0 ? -1 : 1; var destIndex = index; if (!Splide.is(FADE)) { var destination = Track.position; if (absV > options.flickVelocityThreshold && drag_abs(info.offset[axis]) < options.swipeDistanceThreshold) { destination += sign * Math.min(absV * options.flickPower, Components.Layout.size * (options.flickMaxPages || 1)); } destIndex = Track.toIndex(destination); } /* * Do not allow the track to go to a previous position if there is enough velocity. * Always use the adjacent index for the fade mode. */ if (destIndex === index && absV > MIN_VELOCITY) { destIndex = index + sign * Track.sign; } if (Splide.is(SLIDE)) { destIndex = between(destIndex, 0, Controller.edgeIndex); } Controller.go(destIndex, options.isNavigation); } } /** * Analyze the given event object and return important information for handling swipe behavior. * * @param {Event} e - Touch or Mouse event object. * @param {Object} startInfo - Information analyzed on start for calculating difference from the current one. * * @return {Object} - An object containing analyzed information, such as offset, velocity, etc. */ function analyze(e, startInfo) { var timeStamp = e.timeStamp, touches = e.touches; var _ref2 = touches ? touches[0] : e, clientX = _ref2.clientX, clientY = _ref2.clientY; var _ref3 = startInfo.to || {}, _ref3$x = _ref3.x, fromX = _ref3$x === void 0 ? clientX : _ref3$x, _ref3$y = _ref3.y, fromY = _ref3$y === void 0 ? clientY : _ref3$y; var startTime = startInfo.time || 0; var offset = { x: clientX - fromX, y: clientY - fromY }; var duration = timeStamp - startTime; var velocity = { x: offset.x / duration, y: offset.y / duration }; return { to: { x: clientX, y: clientY }, offset: offset, time: timeStamp, velocity: velocity }; } return Drag; }); ;// CONCATENATED MODULE: ./src/js/components/click/index.js /** * The component for handling a click event. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for handling a click event. * Click should be disabled during drag/swipe. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var click = (function (Splide, Components) { /** * Whether click is disabled or not. * * @type {boolean} */ var disabled = false; /** * Click component object. * * @type {Object} */ var Click = { /** * Mount only when the drag is activated and the slide type is not "fade". * * @type {boolean} */ required: Splide.options.drag, /** * Called when the component is mounted. */ mount: function mount() { Splide.on('click', onClick, Components.Elements.track, { capture: true }).on('drag', function () { disabled = true; }).on('dragged', function () { // Make sure the flag is released after the click event is fired. setTimeout(function () { disabled = false; }); }); } }; /** * Called when a track element is clicked. * * @param {Event} e - A click event. */ function onClick(e) { if (disabled) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); } } return Click; }); ;// CONCATENATED MODULE: ./src/js/components/autoplay/index.js /** * The component for playing slides automatically. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Set of pause flags. */ var PAUSE_FLAGS = { HOVER: 1, FOCUS: 2, MANUAL: 3 }; /** * The component for playing slides automatically. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * @param {string} name - A component name as a lowercase string. * * @return {Object} - The component object. */ /* harmony default export */ var autoplay = (function (Splide, Components, name) { /** * Store pause flags. * * @type {Array} */ var flags = []; /** * Store an interval object. * * @type {Object}; */ var interval; /** * Keep the Elements component. * * @type {string} */ var Elements = Components.Elements; /** * Autoplay component object. * * @type {Object} */ var Autoplay = { /** * Required only when the autoplay option is true. * * @type {boolean} */ required: Splide.options.autoplay, /** * Called when the component is mounted. * Note that autoplay starts only if there are slides over perPage number. */ mount: function mount() { var options = Splide.options; if (Elements.slides.length > options.perPage) { interval = createInterval(function () { Splide.go('>'); }, options.interval, function (rate) { Splide.emit(name + ":playing", rate); if (Elements.bar) { applyStyle(Elements.bar, { width: rate * 100 + "%" }); } }); bind(); this.play(); } }, /** * Start autoplay. * * @param {number} flag - A pause flag to be removed. */ play: function play(flag) { if (flag === void 0) { flag = 0; } flags = flags.filter(function (f) { return f !== flag; }); if (!flags.length) { Splide.emit(name + ":play"); interval.play(Splide.options.resetProgress); } }, /** * Pause autoplay. * Note that Array.includes is not supported by IE. * * @param {number} flag - A pause flag to be added. */ pause: function pause(flag) { if (flag === void 0) { flag = 0; } interval.pause(); if (flags.indexOf(flag) === -1) { flags.push(flag); } if (flags.length === 1) { Splide.emit(name + ":pause"); } } }; /** * Listen some events. */ function bind() { var options = Splide.options; var sibling = Splide.sibling; var elms = [Splide.root, sibling ? sibling.root : null]; if (options.pauseOnHover) { switchOn(elms, 'mouseleave', PAUSE_FLAGS.HOVER, true); switchOn(elms, 'mouseenter', PAUSE_FLAGS.HOVER, false); } if (options.pauseOnFocus) { switchOn(elms, 'focusout', PAUSE_FLAGS.FOCUS, true); switchOn(elms, 'focusin', PAUSE_FLAGS.FOCUS, false); } if (Elements.play) { Splide.on('click', function () { // Need to be removed a focus flag at first. Autoplay.play(PAUSE_FLAGS.FOCUS); Autoplay.play(PAUSE_FLAGS.MANUAL); }, Elements.play); } if (Elements.pause) { switchOn([Elements.pause], 'click', PAUSE_FLAGS.MANUAL, false); } Splide.on('move refresh', function () { Autoplay.play(); }) // Rewind the timer. .on('destroy', function () { Autoplay.pause(); }); } /** * Play or pause on the given event. * * @param {Element[]} elms - Elements. * @param {string} event - An event name or names. * @param {number} flag - A pause flag defined on the top. * @param {boolean} play - Determine whether to play or pause. */ function switchOn(elms, event, flag, play) { elms.forEach(function (elm) { Splide.on(event, function () { Autoplay[play ? 'play' : 'pause'](flag); }, elm); }); } return Autoplay; }); ;// CONCATENATED MODULE: ./src/js/components/cover/index.js /** * The component for change an img element to background image of its wrapper. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for change an img element to background image of its wrapper. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * * @return {Object} - The component object. */ /* harmony default export */ var cover = (function (Splide, Components) { /** * Hold options. * * @type {Object} */ var options = Splide.options; /** * Cover component object. * * @type {Object} */ var Cover = { /** * Required only when "cover" option is true. * * @type {boolean} */ required: options.cover, /** * Called when the component is mounted. */ mount: function mount() { Splide.on('lazyload:loaded', function (img) { cover(img, false); }); Splide.on('mounted updated refresh', function () { return apply(false); }); }, /** * Destroy. */ destroy: function destroy() { apply(true); } }; /** * Apply "cover" to all slides. * * @param {boolean} uncover - If true, "cover" will be clear. */ function apply(uncover) { Components.Elements.each(function (Slide) { var img = child(Slide.slide, 'IMG') || child(Slide.container, 'IMG'); if (img && img.src) { cover(img, uncover); } }); } /** * Set background image of the parent element, using source of the given image element. * * @param {Element} img - An image element. * @param {boolean} uncover - Reset "cover". */ function cover(img, uncover) { applyStyle(img.parentElement, { background: uncover ? '' : "center/cover no-repeat url(\"" + img.src + "\")" }); applyStyle(img, { display: uncover ? '' : 'none' }); } return Cover; }); ;// CONCATENATED MODULE: ./src/js/components/arrows/path.js /** * Export vector path for an arrow. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * Namespace definition for SVG element. * * @type {string} */ var XML_NAME_SPACE = 'http://www.w3.org/2000/svg'; /** * The arrow vector path. * * @type {number} */ var PATH = 'm15.5 0.932-4.3 4.38 14.5 14.6-14.5 14.5 4.3 4.4 14.6-14.6 4.4-4.3-4.4-4.4-14.6-14.6z'; /** * SVG width and height. * * @type {number} */ var SIZE = 40; ;// CONCATENATED MODULE: ./src/js/components/arrows/index.js /** * The component for appending prev/next arrows. * * @author Naotoshi Fujita * @copyright Naotoshi Fujita. All rights reserved. */ /** * The component for appending prev/next arrows. * * @param {Splide} Splide - A Splide instance. * @param {Object} Components - An object containing components. * @param {string} name - A component name as a lowercase string. * * @return {Object} - The component object. */ /* harmony default export */ var arrows = (function (Splide, Components, name) { /** * Previous arrow element. * * @type {Element|undefined} */ var prev; /** * Next arrow element. * * @type {Element|undefined} */ var next; /** * Store the class list. * * @type {Object} */ var classes = Splide.classes; /** * Hold the root element. * * @type {Element} */ var root = Splide.root; /** * Whether arrows are created programmatically or not. * * @type {boolean} */ var created; /** * Hold the Elements component. * * @type {Object} */ var Elements = Components.Elements; /** * Arrows component object. * * @type {Object} */ var Arrows = { /** * Required when the arrows option is true. * * @type {boolean} */ required: Splide.options.arrows, /** * Called when the component is mounted. */ mount: function mount() { // Attempt to get arrows from HTML source. prev = Elements.arrows.prev; next = Elements.arrows.next; // If arrows were not found in HTML, let's generate them. if ((!prev || !next) && Splide.options.arrows) { prev = createArrow(true); next = createArrow(false); created = true; appendArrows(); } if (prev && next) { bind(); } this.arrows = { prev: prev, next: next }; }, /** * Called after all components are mounted. */ mounted: function mounted() { Splide.emit(name + ":mounted", prev, next); }, /** * Destroy. */ destroy: function destroy() { removeAttribute([prev, next], 'disabled'); if (created) { dom_remove(prev.parentElement); } } }; /** * Listen to native and custom events. */ function bind() { Splide.on('click', function () { Splide.go('<'); }, prev).on('click', function () { Splide.go('>'); }, next).on('mounted move updated refresh', updateDisabled); } /** * Update a disabled attribute. */ function updateDisabled() { var _Components$Controlle = Components.Controller, prevIndex = _Components$Controlle.prevIndex, nextIndex = _Components$Controlle.nextIndex; var isEnough = Splide.length > Splide.options.perPage || Splide.is(LOOP); prev.disabled = prevIndex < 0 || !isEnough; next.disabled = nextIndex < 0 || !isEnough; Splide.emit(name + ":updated", prev, next, prevIndex, nextIndex); } /** * Create a wrapper element and append arrows. */ function appendArrows() { var wrapper = create('div', { "class": classes.arrows }); append(wrapper, prev); append(wrapper, next); var slider = Elements.slider; var parent = Splide.options.arrows === 'slider' && slider ? slider : root; before(wrapper, parent.firstElementChild); } /** * Create an arrow element. * * @param {boolean} prev - Determine to create a prev arrow or next arrow. * * @return {Element} - A created arrow element. */ function createArrow(prev) { var arrow = "