UNPKG

vue-glide-js

Version:
2,196 lines (1,856 loc) 100 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["vue-glide"] = factory(); else root["vue-glide"] = factory(); })((typeof self !== 'undefined' ? self : this), function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // 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 }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "fb15"); /******/ }) /************************************************************************/ /******/ ({ /***/ "4d21": /***/ (function(module, exports, __webpack_require__) { // extracted by mini-css-extract-plugin /***/ }), /***/ "f6fd": /***/ (function(module, exports) { // document.currentScript polyfill by Adam Miller // MIT license (function(document){ var currentScript = "currentScript", scripts = document.getElementsByTagName('script'); // Live NodeList collection // If browser needs currentScript polyfill, add get currentScript() to the document object if (!(currentScript in document)) { Object.defineProperty(document, currentScript, { get: function(){ // IE 6-10 supports script readyState // IE 10+ support stack trace try { throw new Error(); } catch (err) { // Find the second match for the "at" string to get file src url from stack. // Specifically works with the format of stack traces in IE. var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1]; // For all scripts on the page, if src matches or if ready state is interactive, return the script tag for(i in scripts){ if(scripts[i].src == res || scripts[i].readyState == "interactive"){ return scripts[i]; } } // If no match, return null return null; } } }); } })(document); /***/ }), /***/ "fb15": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js // This file is imported into lib/wc client bundles. if (typeof window !== 'undefined') { if (true) { __webpack_require__("f6fd") } var i if ((i = window.document.currentScript) && (i = i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { __webpack_require__.p = i[1] // eslint-disable-line } } // Indicate to webpack that this file can be concatenated /* harmony default export */ var setPublicPath = (null); // CONCATENATED MODULE: ./node_modules/@glidejs/glide/dist/glide.esm.js /*! * Glide.js v3.4.1 * (c) 2013-2019 Jędrzej Chałubek <jedrzej.chalubek@gmail.com> (http://jedrzejchalubek.com/) * Released under the MIT License. */ var defaults = { /** * Type of the movement. * * Available types: * `slider` - Rewinds slider to the start/end when it reaches the first or last slide. * `carousel` - Changes slides without starting over when it reaches the first or last slide. * * @type {String} */ type: 'slider', /** * Start at specific slide number defined with zero-based index. * * @type {Number} */ startAt: 0, /** * A number of slides visible on the single viewport. * * @type {Number} */ perView: 1, /** * Focus currently active slide at a specified position in the track. * * Available inputs: * `center` - Current slide will be always focused at the center of a track. * `0,1,2,3...` - Current slide will be focused on the specified zero-based index. * * @type {String|Number} */ focusAt: 0, /** * A size of the gap added between slides. * * @type {Number} */ gap: 10, /** * Change slides after a specified interval. Use `false` for turning off autoplay. * * @type {Number|Boolean} */ autoplay: false, /** * Stop autoplay on mouseover event. * * @type {Boolean} */ hoverpause: true, /** * Allow for changing slides with left and right keyboard arrows. * * @type {Boolean} */ keyboard: true, /** * Stop running `perView` number of slides from the end. Use this * option if you don't want to have an empty space after * a slider. Works only with `slider` type and a * non-centered `focusAt` setting. * * @type {Boolean} */ bound: false, /** * Minimal swipe distance needed to change the slide. Use `false` for turning off a swiping. * * @type {Number|Boolean} */ swipeThreshold: 80, /** * Minimal mouse drag distance needed to change the slide. Use `false` for turning off a dragging. * * @type {Number|Boolean} */ dragThreshold: 120, /** * A maximum number of slides to which movement will be made on swiping or dragging. Use `false` for unlimited. * * @type {Number|Boolean} */ perTouch: false, /** * Moving distance ratio of the slides on a swiping and dragging. * * @type {Number} */ touchRatio: 0.5, /** * Angle required to activate slides moving on swiping or dragging. * * @type {Number} */ touchAngle: 45, /** * Duration of the animation in milliseconds. * * @type {Number} */ animationDuration: 400, /** * Allows looping the `slider` type. Slider will rewind to the first/last slide when it's at the start/end. * * @type {Boolean} */ rewind: true, /** * Duration of the rewinding animation of the `slider` type in milliseconds. * * @type {Number} */ rewindDuration: 800, /** * Easing function for the animation. * * @type {String} */ animationTimingFunc: 'cubic-bezier(.165, .840, .440, 1)', /** * Throttle costly events at most once per every wait milliseconds. * * @type {Number} */ throttle: 10, /** * Moving direction mode. * * Available inputs: * - 'ltr' - left to right movement, * - 'rtl' - right to left movement. * * @type {String} */ direction: 'ltr', /** * The distance value of the next and previous viewports which * have to peek in the current view. Accepts number and * pixels as a string. Left and right peeking can be * set up separately with a directions object. * * For example: * `100` - Peek 100px on the both sides. * { before: 100, after: 50 }` - Peek 100px on the left side and 50px on the right side. * * @type {Number|String|Object} */ peek: 0, /** * Collection of options applied at specified media breakpoints. * For example: display two slides per view under 800px. * `{ * '800px': { * perView: 2 * } * }` */ breakpoints: {}, /** * Collection of internally used HTML classes. * * @todo Refactor `slider` and `carousel` properties to single `type: { slider: '', carousel: '' }` object * @type {Object} */ classes: { direction: { ltr: 'glide--ltr', rtl: 'glide--rtl' }, slider: 'glide--slider', carousel: 'glide--carousel', swipeable: 'glide--swipeable', dragging: 'glide--dragging', cloneSlide: 'glide__slide--clone', activeNav: 'glide__bullet--active', activeSlide: 'glide__slide--active', disabledArrow: 'glide__arrow--disabled' } }; /** * Outputs warning message to the bowser console. * * @param {String} msg * @return {Void} */ function warn(msg) { console.error("[Glide warn]: " + msg); } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _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; }; var get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; /** * Converts value entered as number * or string to integer value. * * @param {String} value * @returns {Number} */ function toInt(value) { return parseInt(value); } /** * Converts value entered as number * or string to flat value. * * @param {String} value * @returns {Number} */ function toFloat(value) { return parseFloat(value); } /** * Indicates whether the specified value is a string. * * @param {*} value * @return {Boolean} */ function isString(value) { return typeof value === 'string'; } /** * Indicates whether the specified value is an object. * * @param {*} value * @return {Boolean} * * @see https://github.com/jashkenas/underscore */ function isObject(value) { var type = typeof value === 'undefined' ? 'undefined' : _typeof(value); return type === 'function' || type === 'object' && !!value; // eslint-disable-line no-mixed-operators } /** * Indicates whether the specified value is a number. * * @param {*} value * @return {Boolean} */ function isNumber(value) { return typeof value === 'number'; } /** * Indicates whether the specified value is a function. * * @param {*} value * @return {Boolean} */ function isFunction(value) { return typeof value === 'function'; } /** * Indicates whether the specified value is undefined. * * @param {*} value * @return {Boolean} */ function isUndefined(value) { return typeof value === 'undefined'; } /** * Indicates whether the specified value is an array. * * @param {*} value * @return {Boolean} */ function isArray(value) { return value.constructor === Array; } /** * Creates and initializes specified collection of extensions. * Each extension receives access to instance of glide and rest of components. * * @param {Object} glide * @param {Object} extensions * * @returns {Object} */ function mount(glide, extensions, events) { var components = {}; for (var name in extensions) { if (isFunction(extensions[name])) { components[name] = extensions[name](glide, components, events); } else { warn('Extension must be a function'); } } for (var _name in components) { if (isFunction(components[_name].mount)) { components[_name].mount(); } } return components; } /** * Defines getter and setter property on the specified object. * * @param {Object} obj Object where property has to be defined. * @param {String} prop Name of the defined property. * @param {Object} definition Get and set definitions for the property. * @return {Void} */ function define(obj, prop, definition) { Object.defineProperty(obj, prop, definition); } /** * Sorts aphabetically object keys. * * @param {Object} obj * @return {Object} */ function sortKeys(obj) { return Object.keys(obj).sort().reduce(function (r, k) { r[k] = obj[k]; return r[k], r; }, {}); } /** * Merges passed settings object with default options. * * @param {Object} defaults * @param {Object} settings * @return {Object} */ function mergeOptions(defaults, settings) { var options = _extends({}, defaults, settings); // `Object.assign` do not deeply merge objects, so we // have to do it manually for every nested object // in options. Although it does not look smart, // it's smaller and faster than some fancy // merging deep-merge algorithm script. if (settings.hasOwnProperty('classes')) { options.classes = _extends({}, defaults.classes, settings.classes); if (settings.classes.hasOwnProperty('direction')) { options.classes.direction = _extends({}, defaults.classes.direction, settings.classes.direction); } } if (settings.hasOwnProperty('breakpoints')) { options.breakpoints = _extends({}, defaults.breakpoints, settings.breakpoints); } return options; } var EventsBus = function () { /** * Construct a EventBus instance. * * @param {Object} events */ function EventsBus() { var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck(this, EventsBus); this.events = events; this.hop = events.hasOwnProperty; } /** * Adds listener to the specifed event. * * @param {String|Array} event * @param {Function} handler */ createClass(EventsBus, [{ key: 'on', value: function on(event, handler) { if (isArray(event)) { for (var i = 0; i < event.length; i++) { this.on(event[i], handler); } } // Create the event's object if not yet created if (!this.hop.call(this.events, event)) { this.events[event] = []; } // Add the handler to queue var index = this.events[event].push(handler) - 1; // Provide handle back for removal of event return { remove: function remove() { delete this.events[event][index]; } }; } /** * Runs registered handlers for specified event. * * @param {String|Array} event * @param {Object=} context */ }, { key: 'emit', value: function emit(event, context) { if (isArray(event)) { for (var i = 0; i < event.length; i++) { this.emit(event[i], context); } } // If the event doesn't exist, or there's no handlers in queue, just leave if (!this.hop.call(this.events, event)) { return; } // Cycle through events queue, fire! this.events[event].forEach(function (item) { item(context || {}); }); } }]); return EventsBus; }(); var Glide = function () { /** * Construct glide. * * @param {String} selector * @param {Object} options */ function Glide(selector) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; classCallCheck(this, Glide); this._c = {}; this._t = []; this._e = new EventsBus(); this.disabled = false; this.selector = selector; this.settings = mergeOptions(defaults, options); this.index = this.settings.startAt; } /** * Initializes glide. * * @param {Object} extensions Collection of extensions to initialize. * @return {Glide} */ createClass(Glide, [{ key: 'mount', value: function mount$$1() { var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this._e.emit('mount.before'); if (isObject(extensions)) { this._c = mount(this, extensions, this._e); } else { warn('You need to provide a object on `mount()`'); } this._e.emit('mount.after'); return this; } /** * Collects an instance `translate` transformers. * * @param {Array} transformers Collection of transformers. * @return {Void} */ }, { key: 'mutate', value: function mutate() { var transformers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (isArray(transformers)) { this._t = transformers; } else { warn('You need to provide a array on `mutate()`'); } return this; } /** * Updates glide with specified settings. * * @param {Object} settings * @return {Glide} */ }, { key: 'update', value: function update() { var settings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.settings = mergeOptions(this.settings, settings); if (settings.hasOwnProperty('startAt')) { this.index = settings.startAt; } this._e.emit('update'); return this; } /** * Change slide with specified pattern. A pattern must be in the special format: * `>` - Move one forward * `<` - Move one backward * `={i}` - Go to {i} zero-based slide (eq. '=1', will go to second slide) * `>>` - Rewinds to end (last slide) * `<<` - Rewinds to start (first slide) * * @param {String} pattern * @return {Glide} */ }, { key: 'go', value: function go(pattern) { this._c.Run.make(pattern); return this; } /** * Move track by specified distance. * * @param {String} distance * @return {Glide} */ }, { key: 'move', value: function move(distance) { this._c.Transition.disable(); this._c.Move.make(distance); return this; } /** * Destroy instance and revert all changes done by this._c. * * @return {Glide} */ }, { key: 'destroy', value: function destroy() { this._e.emit('destroy'); return this; } /** * Start instance autoplaying. * * @param {Boolean|Number} interval Run autoplaying with passed interval regardless of `autoplay` settings * @return {Glide} */ }, { key: 'play', value: function play() { var interval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (interval) { this.settings.autoplay = interval; } this._e.emit('play'); return this; } /** * Stop instance autoplaying. * * @return {Glide} */ }, { key: 'pause', value: function pause() { this._e.emit('pause'); return this; } /** * Sets glide into a idle status. * * @return {Glide} */ }, { key: 'disable', value: function disable() { this.disabled = true; return this; } /** * Sets glide into a active status. * * @return {Glide} */ }, { key: 'enable', value: function enable() { this.disabled = false; return this; } /** * Adds cuutom event listener with handler. * * @param {String|Array} event * @param {Function} handler * @return {Glide} */ }, { key: 'on', value: function on(event, handler) { this._e.on(event, handler); return this; } /** * Checks if glide is a precised type. * * @param {String} name * @return {Boolean} */ }, { key: 'isType', value: function isType(name) { return this.settings.type === name; } /** * Gets value of the core options. * * @return {Object} */ }, { key: 'settings', get: function get$$1() { return this._o; } /** * Sets value of the core options. * * @param {Object} o * @return {Void} */ , set: function set$$1(o) { if (isObject(o)) { this._o = o; } else { warn('Options must be an `object` instance.'); } } /** * Gets current index of the slider. * * @return {Object} */ }, { key: 'index', get: function get$$1() { return this._i; } /** * Sets current index a slider. * * @return {Object} */ , set: function set$$1(i) { this._i = toInt(i); } /** * Gets type name of the slider. * * @return {String} */ }, { key: 'type', get: function get$$1() { return this.settings.type; } /** * Gets value of the idle status. * * @return {Boolean} */ }, { key: 'disabled', get: function get$$1() { return this._d; } /** * Sets value of the idle status. * * @return {Boolean} */ , set: function set$$1(status) { this._d = !!status; } }]); return Glide; }(); function Run (Glide, Components, Events) { var Run = { /** * Initializes autorunning of the glide. * * @return {Void} */ mount: function mount() { this._o = false; }, /** * Makes glides running based on the passed moving schema. * * @param {String} move */ make: function make(move) { var _this = this; if (!Glide.disabled) { Glide.disable(); this.move = move; Events.emit('run.before', this.move); this.calculate(); Events.emit('run', this.move); Components.Transition.after(function () { if (_this.isStart()) { Events.emit('run.start', _this.move); } if (_this.isEnd()) { Events.emit('run.end', _this.move); } if (_this.isOffset('<') || _this.isOffset('>')) { _this._o = false; Events.emit('run.offset', _this.move); } Events.emit('run.after', _this.move); Glide.enable(); }); } }, /** * Calculates current index based on defined move. * * @return {Void} */ calculate: function calculate() { var move = this.move, length = this.length; var steps = move.steps, direction = move.direction; var countableSteps = isNumber(toInt(steps)) && toInt(steps) !== 0; switch (direction) { case '>': if (steps === '>') { Glide.index = length; } else if (this.isEnd()) { if (!(Glide.isType('slider') && !Glide.settings.rewind)) { this._o = true; Glide.index = 0; } } else if (countableSteps) { Glide.index += Math.min(length - Glide.index, -toInt(steps)); } else { Glide.index++; } break; case '<': if (steps === '<') { Glide.index = 0; } else if (this.isStart()) { if (!(Glide.isType('slider') && !Glide.settings.rewind)) { this._o = true; Glide.index = length; } } else if (countableSteps) { Glide.index -= Math.min(Glide.index, toInt(steps)); } else { Glide.index--; } break; case '=': Glide.index = steps; break; default: warn('Invalid direction pattern [' + direction + steps + '] has been used'); break; } }, /** * Checks if we are on the first slide. * * @return {Boolean} */ isStart: function isStart() { return Glide.index === 0; }, /** * Checks if we are on the last slide. * * @return {Boolean} */ isEnd: function isEnd() { return Glide.index === this.length; }, /** * Checks if we are making a offset run. * * @param {String} direction * @return {Boolean} */ isOffset: function isOffset(direction) { return this._o && this.move.direction === direction; } }; define(Run, 'move', { /** * Gets value of the move schema. * * @returns {Object} */ get: function get() { return this._m; }, /** * Sets value of the move schema. * * @returns {Object} */ set: function set(value) { var step = value.substr(1); this._m = { direction: value.substr(0, 1), steps: step ? toInt(step) ? toInt(step) : step : 0 }; } }); define(Run, 'length', { /** * Gets value of the running distance based * on zero-indexing number of slides. * * @return {Number} */ get: function get() { var settings = Glide.settings; var length = Components.Html.slides.length; // If the `bound` option is acitve, a maximum running distance should be // reduced by `perView` and `focusAt` settings. Running distance // should end before creating an empty space after instance. if (Glide.isType('slider') && settings.focusAt !== 'center' && settings.bound) { return length - 1 - (toInt(settings.perView) - 1) + toInt(settings.focusAt); } return length - 1; } }); define(Run, 'offset', { /** * Gets status of the offsetting flag. * * @return {Boolean} */ get: function get() { return this._o; } }); return Run; } /** * Returns a current time. * * @return {Number} */ function now() { return new Date().getTime(); } /** * Returns a function, that, when invoked, will only be triggered * at most once during a given window of time. * * @param {Function} func * @param {Number} wait * @param {Object=} options * @return {Function} * * @see https://github.com/jashkenas/underscore */ function throttle(func, wait, options) { var timeout = void 0, context = void 0, args = void 0, result = void 0; var previous = 0; if (!options) options = {}; var later = function later() { previous = options.leading === false ? 0 : now(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; var throttled = function throttled() { var at = now(); if (!previous && options.leading === false) previous = at; var remaining = wait - (at - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = at; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function () { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; } var MARGIN_TYPE = { ltr: ['marginLeft', 'marginRight'], rtl: ['marginRight', 'marginLeft'] }; function Gaps (Glide, Components, Events) { var Gaps = { /** * Applies gaps between slides. First and last * slides do not receive it's edge margins. * * @param {HTMLCollection} slides * @return {Void} */ apply: function apply(slides) { for (var i = 0, len = slides.length; i < len; i++) { var style = slides[i].style; var direction = Components.Direction.value; if (i !== 0) { style[MARGIN_TYPE[direction][0]] = this.value / 2 + 'px'; } else { style[MARGIN_TYPE[direction][0]] = ''; } if (i !== slides.length - 1) { style[MARGIN_TYPE[direction][1]] = this.value / 2 + 'px'; } else { style[MARGIN_TYPE[direction][1]] = ''; } } }, /** * Removes gaps from the slides. * * @param {HTMLCollection} slides * @returns {Void} */ remove: function remove(slides) { for (var i = 0, len = slides.length; i < len; i++) { var style = slides[i].style; style.marginLeft = ''; style.marginRight = ''; } } }; define(Gaps, 'value', { /** * Gets value of the gap. * * @returns {Number} */ get: function get() { return toInt(Glide.settings.gap); } }); define(Gaps, 'grow', { /** * Gets additional dimentions value caused by gaps. * Used to increase width of the slides wrapper. * * @returns {Number} */ get: function get() { return Gaps.value * (Components.Sizes.length - 1); } }); define(Gaps, 'reductor', { /** * Gets reduction value caused by gaps. * Used to subtract width of the slides. * * @returns {Number} */ get: function get() { var perView = Glide.settings.perView; return Gaps.value * (perView - 1) / perView; } }); /** * Apply calculated gaps: * - after building, so slides (including clones) will receive proper margins * - on updating via API, to recalculate gaps with new options */ Events.on(['build.after', 'update'], throttle(function () { Gaps.apply(Components.Html.wrapper.children); }, 30)); /** * Remove gaps: * - on destroying to bring markup to its inital state */ Events.on('destroy', function () { Gaps.remove(Components.Html.wrapper.children); }); return Gaps; } /** * Finds siblings nodes of the passed node. * * @param {Element} node * @return {Array} */ function siblings(node) { if (node && node.parentNode) { var n = node.parentNode.firstChild; var matched = []; for (; n; n = n.nextSibling) { if (n.nodeType === 1 && n !== node) { matched.push(n); } } return matched; } return []; } /** * Checks if passed node exist and is a valid element. * * @param {Element} node * @return {Boolean} */ function exist(node) { if (node && node instanceof window.HTMLElement) { return true; } return false; } var TRACK_SELECTOR = '[data-glide-el="track"]'; function Html (Glide, Components) { var Html = { /** * Setup slider HTML nodes. * * @param {Glide} glide */ mount: function mount() { this.root = Glide.selector; this.track = this.root.querySelector(TRACK_SELECTOR); this.slides = Array.prototype.slice.call(this.wrapper.children).filter(function (slide) { return !slide.classList.contains(Glide.settings.classes.cloneSlide); }); } }; define(Html, 'root', { /** * Gets node of the glide main element. * * @return {Object} */ get: function get() { return Html._r; }, /** * Sets node of the glide main element. * * @return {Object} */ set: function set(r) { if (isString(r)) { r = document.querySelector(r); } if (exist(r)) { Html._r = r; } else { warn('Root element must be a existing Html node'); } } }); define(Html, 'track', { /** * Gets node of the glide track with slides. * * @return {Object} */ get: function get() { return Html._t; }, /** * Sets node of the glide track with slides. * * @return {Object} */ set: function set(t) { if (exist(t)) { Html._t = t; } else { warn('Could not find track element. Please use ' + TRACK_SELECTOR + ' attribute.'); } } }); define(Html, 'wrapper', { /** * Gets node of the slides wrapper. * * @return {Object} */ get: function get() { return Html.track.children[0]; } }); return Html; } function Peek (Glide, Components, Events) { var Peek = { /** * Setups how much to peek based on settings. * * @return {Void} */ mount: function mount() { this.value = Glide.settings.peek; } }; define(Peek, 'value', { /** * Gets value of the peek. * * @returns {Number|Object} */ get: function get() { return Peek._v; }, /** * Sets value of the peek. * * @param {Number|Object} value * @return {Void} */ set: function set(value) { if (isObject(value)) { value.before = toInt(value.before); value.after = toInt(value.after); } else { value = toInt(value); } Peek._v = value; } }); define(Peek, 'reductor', { /** * Gets reduction value caused by peek. * * @returns {Number} */ get: function get() { var value = Peek.value; var perView = Glide.settings.perView; if (isObject(value)) { return value.before / perView + value.after / perView; } return value * 2 / perView; } }); /** * Recalculate peeking sizes on: * - when resizing window to update to proper percents */ Events.on(['resize', 'update'], function () { Peek.mount(); }); return Peek; } function Move (Glide, Components, Events) { var Move = { /** * Constructs move component. * * @returns {Void} */ mount: function mount() { this._o = 0; }, /** * Calculates a movement value based on passed offset and currently active index. * * @param {Number} offset * @return {Void} */ make: function make() { var _this = this; var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; this.offset = offset; Events.emit('move', { movement: this.value }); Components.Transition.after(function () { Events.emit('move.after', { movement: _this.value }); }); } }; define(Move, 'offset', { /** * Gets an offset value used to modify current translate. * * @return {Object} */ get: function get() { return Move._o; }, /** * Sets an offset value used to modify current translate. * * @return {Object} */ set: function set(value) { Move._o = !isUndefined(value) ? toInt(value) : 0; } }); define(Move, 'translate', { /** * Gets a raw movement value. * * @return {Number} */ get: function get() { return Components.Sizes.slideWidth * Glide.index; } }); define(Move, 'value', { /** * Gets an actual movement value corrected by offset. * * @return {Number} */ get: function get() { var offset = this.offset; var translate = this.translate; if (Components.Direction.is('rtl')) { return translate + offset; } return translate - offset; } }); /** * Make movement to proper slide on: * - before build, so glide will start at `startAt` index * - on each standard run to move to newly calculated index */ Events.on(['build.before', 'run'], function () { Move.make(); }); return Move; } function Sizes (Glide, Components, Events) { var Sizes = { /** * Setups dimentions of slides. * * @return {Void} */ setupSlides: function setupSlides() { var width = this.slideWidth + 'px'; var slides = Components.Html.slides; for (var i = 0; i < slides.length; i++) { slides[i].style.width = width; } }, /** * Setups dimentions of slides wrapper. * * @return {Void} */ setupWrapper: function setupWrapper(dimention) { Components.Html.wrapper.style.width = this.wrapperSize + 'px'; }, /** * Removes applied styles from HTML elements. * * @returns {Void} */ remove: function remove() { var slides = Components.Html.slides; for (var i = 0; i < slides.length; i++) { slides[i].style.width = ''; } Components.Html.wrapper.style.width = ''; } }; define(Sizes, 'length', { /** * Gets count number of the slides. * * @return {Number} */ get: function get() { return Components.Html.slides.length; } }); define(Sizes, 'width', { /** * Gets width value of the glide. * * @return {Number} */ get: function get() { return Components.Html.root.offsetWidth; } }); define(Sizes, 'wrapperSize', { /** * Gets size of the slides wrapper. * * @return {Number} */ get: function get() { return Sizes.slideWidth * Sizes.length + Components.Gaps.grow + Components.Clones.grow; } }); define(Sizes, 'slideWidth', { /** * Gets width value of the single slide. * * @return {Number} */ get: function get() { return Sizes.width / Glide.settings.perView - Components.Peek.reductor - Components.Gaps.reductor; } }); /** * Apply calculated glide's dimensions: * - before building, so other dimentions (e.g. translate) will be calculated propertly * - when resizing window to recalculate sildes dimensions * - on updating via API, to calculate dimensions based on new options */ Events.on(['build.before', 'resize', 'update'], function () { Sizes.setupSlides(); Sizes.setupWrapper(); }); /** * Remove calculated glide's dimensions: * - on destoting to bring markup to its inital state */ Events.on('destroy', function () { Sizes.remove(); }); return Sizes; } function Build (Glide, Components, Events) { var Build = { /** * Init glide building. Adds classes, sets * dimensions and setups initial state. * * @return {Void} */ mount: function mount() { Events.emit('build.before'); this.typeClass(); this.activeClass(); Events.emit('build.after'); }, /** * Adds `type` class to the glide element. * * @return {Void} */ typeClass: function typeClass() { Components.Html.root.classList.add(Glide.settings.classes[Glide.settings.type]); }, /** * Sets active class to current slide. * * @return {Void} */ activeClass: function activeClass() { var classes = Glide.settings.classes; var slide = Components.Html.slides[Glide.index]; if (slide) { slide.classList.add(classes.activeSlide); siblings(slide).forEach(function (sibling) { sibling.classList.remove(classes.activeSlide); }); } }, /** * Removes HTML classes applied at building. * * @return {Void} */ removeClasses: function removeClasses() { var classes = Glide.settings.classes; Components.Html.root.classList.remove(classes[Glide.settings.type]); Components.Html.slides.forEach(function (sibling) { sibling.classList.remove(classes.activeSlide); }); } }; /** * Clear building classes: * - on destroying to bring HTML to its initial state * - on updating to remove classes before remounting component */ Events.on(['destroy', 'update'], function () { Build.removeClasses(); }); /** * Remount component: * - on resizing of the window to calculate new dimentions * - on updating settings via API */ Events.on(['resize', 'update'], function () { Build.mount(); }); /** * Swap active class of current slide: * - after each move to the new index */ Events.on('move.after', function () { Build.activeClass(); }); return Build; } function Clones (Glide, Components, Events) { var Clones = { /** * Create pattern map and collect slides to be cloned. */ mount: function mount() { this.items = []; if (Glide.isType('carousel')) { this.items = this.collect(); } }, /** * Collect clones with pattern. * * @return {Void} */ collect: function collect() { var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var slides = Components.Html.slides; var _Glide$settings = Glide.settings, perView = _Glide$settings.perView, classes = _Glide$settings.classes; var peekIncrementer = +!!Glide.settings.peek; var part = perView + peekIncrementer; var start = slides.slice(0, part); var end = slides.slice(-part); for (var r = 0; r < Math.max(1, Math.floor(perView / slides.length)); r++) { for (var i = 0; i < start.length; i++) { var clone = start[i].cloneNode(true); clone.classList.add(classes.cloneSlide); items.push(clone); } for (var _i = 0; _i < end.length; _i++) { var _clone = end[_i].cloneNode(true); _clone.classList.add(classes.cloneSlide); items.unshift(_clone); } } return items; }, /** * Append cloned slides with generated pattern. * * @return {Void} */ append: function append() { var items = this.items; var _Components$Html = Components.Html, wrapper = _Components$Html.wrapper, slides = _Components$Html.slides; var half = Math.floor(items.length / 2); var prepend = items.slice(0, half).reverse(); var append = items.slice(half, items.length); var width = Components.Sizes.slideWidth + 'px'; for (var i = 0; i < append.length; i++) { wrapper.appendChild(append[i]); } for (var _i2 = 0; _i2 < prepend.length; _i2++) { wrapper.insertBefore(prepend[_i2], slides[0]); } for (var _i3 = 0; _i3 < items.length; _i3++) { items[_i3].style.width = width; } }, /** * Remove all cloned slides. * * @return {Void} */ remove: function remove() { var items = this.items; for (var i = 0; i < items.length; i++) { Components.Html.wrapper.removeChild(items[i]); } } }; define(Clones, 'grow', { /** * Gets additional dimentions value caused by clones. * * @return {Number} */ get: function get() { return (Components.Sizes.slideWidth + Components.Gaps.value) * Clones.items.length; } }); /** * Append additional slide's clones: * - while glide's type is `carousel` */ Events.on('update', function () { Clones.remove(); Clones.mount(); Clones.append(); }); /** * Append additional slide's clones: * - while glide's type is `carousel` */ Events.on('build.before', function () { if (Glide.isType('carousel')) { Clones.append(); } }); /** * Remove clones HTMLElements: * - on destroying, to bring HTML to its initial state */ Events.on('destroy', function () { Clones.remove(); }); return Clones; } var EventsBinder = function () { /** * Construct a EventsBinder instance. */ function EventsBinder() { var listeners = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck(this, EventsBinder); this.listeners = listeners; } /** * Adds events listeners to arrows HTML elements. * * @param {String|Array} events * @param {Element|Window|Document} el * @param {Function} closure * @param {Boolean|Object} capture * @return {Void} */ createClass(EventsBinder, [{ key: 'on', value: function on(events, el, closure) { var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; if (isString(events)) { events = [events]; } for (var i = 0; i < events.length; i++) { this.listeners[events[i]] = closure; el.addEventListener(events[i], this.listeners[events[i]], capture); } } /** * Removes event listeners from arrows HTML elements. * * @param {String|Array} events * @param {Element|Window|Document} el * @param {Boolean|Object} capture * @return {Void} */ }, { key: 'off', value: function off(events, el) { var capture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (isString(events)) { events = [events]; } for (var i = 0; i < events.length; i++) { el.removeEventListener(events[i], this.listeners[events[i]], capture); } } /** * Destroy collected listeners. * * @returns {Void} */ }, { key: 'destroy', value: function destroy() { delete this.listeners; } }]); return EventsBinder; }(); function Resize (Glide, Components, Events) { /** * Instance of the binder for DOM Events. * * @type {EventsBinder} */ var Binder = new EventsBinder(); var Resize = { /** * Initializes window bindings. */ mount: function mount() { this.bind(); }, /** * Binds `rezsize` listener to the window. * It's a costly event, so we are debouncing it. * * @return {Void} */ bind: function bind() { Binder.on('resize', window, throttle(function () { Events.emit('resize'); }, Glide.settings.throttle)); }, /** * Unbinds listeners from the window. * * @return {Void} */ unbind: function unbind() { Binder.off('resize', window); } }; /** * Remove bindings from window: * - on destroying, to remove added EventListener */ Events.on('destroy', function () { Resize.unbind(); Binder.destroy(); }); return Resize; } var VALID_DIRECTIONS = ['ltr', 'rtl']; var FLIPED_MOVEMENTS = { '>': '<', '<': '>', '=':