PageSourceSearch

https://bkmaxwell.com/assets/scripts/glide/glide.js

js bkmaxwell.com collected 2026-10-05 07:13:48 UTC 86,576 bytes, 3,677 lines download raw bytes

1/*!
2 * Glide.js v3.4.1
3 * (c) 2013-2019 Jędrzej Chałubek <[email protected]> (http://jedrzejchalubek.com/)
4 * Released under the MIT License.
5 */
6
7(function (global, factory) {
8  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9  typeof define === 'function' && define.amd ? define(factory) :
10  (global.Glide = factory());
11}(this, (function () { 'use strict';
12
13  var defaults = {
14    /**
15     * Type of the movement.
16     *
17     * Available types:
18     * `slider` - Rewinds slider to the start/end when it reaches the first or last slide.
19     * `carousel` - Changes slides without starting over when it reaches the first or last slide.
20     *
21     * @type {String}
22     */
23    type: 'slider',
24
25    /**
26     * Start at specific slide number defined with zero-based index.
27     *
28     * @type {Number}
29     */
30    startAt: 0,
31
32    /**
33     * A number of slides visible on the single viewport.
34     *
35     * @type {Number}
36     */
37    perView: 1,
38
39    /**
40     * Focus currently active slide at a specified position in the track.
41     *
42     * Available inputs:
43     * `center` - Current slide will be always focused at the center of a track.
44     * `0,1,2,3...` - Current slide will be focused on the specified zero-based index.
45     *
46     * @type {String|Number}
47     */
48    focusAt: 0,
49
50    /**
51     * A size of the gap added between slides.
52     *
53     * @type {Number}
54     */
55    gap: 10,
56
57    /**
58     * Change slides after a specified interval. Use `false` for turning off autoplay.
59     *
60     * @type {Number|Boolean}
61     */
62    autoplay: false,
63
64    /**
65     * Stop autoplay on mouseover event.
66     *
67     * @type {Boolean}
68     */
69    hoverpause: true,
70
71    /**
72     * Allow for changing slides with left and right keyboard arrows.
73     *
74     * @type {Boolean}
75     */
76    keyboard: true,
77
78    /**
79     * Stop running `perView` number of slides from the end. Use this
80     * option if you don't want to have an empty space after
81     * a slider. Works only with `slider` type and a
82     * non-centered `focusAt` setting.
83     *
84     * @type {Boolean}
85     */
86    bound: false,
87
88    /**
89     * Minimal swipe distance needed to change the slide. Use `false` for turning off a swiping.
90     *
91     * @type {Number|Boolean}
92     */
93    swipeThreshold: 80,
94
95    /**
96     * Minimal mouse drag distance needed to change the slide. Use `false` for turning off a dragging.
97     *
98     * @type {Number|Boolean}
99     */
100    dragThreshold: 120,
101
102    /**
103     * A maximum number of slides to which movement will be made on swiping or dragging. Use `false` for unlimited.
104     *
105     * @type {Number|Boolean}
106     */
107    perTouch: false,
108
109    /**
110     * Moving distance ratio of the slides on a swiping and dragging.
111     *
112     * @type {Number}
113     */
114    touchRatio: 0.5,
115
116    /**
117     * Angle required to activate slides moving on swiping or dragging.
118     *
119     * @type {Number}
120     */
121    touchAngle: 45,
122
123    /**
124     * Duration of the animation in milliseconds.
125     *
126     * @type {Number}
127     */
128    animationDuration: 400,
129
130    /**
131     * Allows looping the `slider` type. Slider will rewind to the first/last slide when it's at the start/end.
132     *
133     * @type {Boolean}
134     */
135    rewind: true,
136
137    /**
138     * Duration of the rewinding animation of the `slider` type in milliseconds.
139     *
140     * @type {Number}
141     */
142    rewindDuration: 800,
143
144    /**
145     * Easing function for the animation.
146     *
147     * @type {String}
148     */
149    animationTimingFunc: 'cubic-bezier(.165, .840, .440, 1)',
150
151    /**
152     * Throttle costly events at most once per every wait milliseconds.
153     *
154     * @type {Number}
155     */
156    throttle: 10,
157
158    /**
159     * Moving direction mode.
160     *
161     * Available inputs:
162     * - 'ltr' - left to right movement,
163     * - 'rtl' - right to left movement.
164     *
165     * @type {String}
166     */
167    direction: 'ltr',
168
169    /**
170     * The distance value of the next and previous viewports which
171     * have to peek in the current view. Accepts number and
172     * pixels as a string. Left and right peeking can be
173     * set up separately with a directions object.
174     *
175     * For example:
176     * `100` - Peek 100px on the both sides.
177     * { before: 100, after: 50 }` - Peek 100px on the left side and 50px on the right side.
178     *
179     * @type {Number|String|Object}
180     */
181    peek: 0,
182
183    /**
184     * Collection of options applied at specified media breakpoints.
185     * For example: display two slides per view under 800px.
186     * `{
187     *   '800px': {
188     *     perView: 2
189     *   }
190     * }`
191     */
192    breakpoints: {},
193
194    /**
195     * Collection of internally used HTML classes.
196     *
197     * @todo Refactor `slider` and `carousel` properties to single `type: { slider: '', carousel: '' }` object
198     * @type {Object}
199     */
200    classes: {
201      direction: {
202        ltr: 'glide--ltr',
203        rtl: 'glide--rtl'
204      },
205      slider: 'glide--slider',
206      carousel: 'glide--carousel',
207      swipeable: 'glide--swipeable',
208      dragging: 'glide--dragging',
209      cloneSlide: 'glide__slide--clone',
210      activeNav: 'glide__bullet--active',
211      activeSlide: 'glide__slide--active',
212      disabledArrow: 'glide__arrow--disabled'
213    }
214  };
215
216  /**
217   * Outputs warning message to the bowser console.
218   *
219   * @param  {String} msg
220   * @return {Void}
221   */
222  function warn(msg) {
223    console.error("[Glide warn]: " + msg);
224  }
225
226  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
227    return typeof obj;
228  } : function (obj) {
229    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
230  };
231
232  var classCallCheck = function (instance, Constructor) {
233    if (!(instance instanceof Constructor)) {
234      throw new TypeError("Cannot call a class as a function");
235    }
236  };
237
238  var createClass = function () {
239    function defineProperties(target, props) {
240      for (var i = 0; i < props.length; i++) {
241        var descriptor = props[i];
242        descriptor.enumerable = descriptor.enumerable || false;
243        descriptor.configurable = true;
244        if ("value" in descriptor) descriptor.writable = true;
245        Object.defineProperty(target, descriptor.key, descriptor);
246      }
247    }
248
249    return function (Constructor, protoProps, staticProps) {
250      if (protoProps) defineProperties(Constructor.prototype, protoProps);
251      if (staticProps) defineProperties(Constructor, staticProps);
252      return Constructor;
253    };
254  }();
255
256  var _extends = Object.assign || function (target) {
257    for (var i = 1; i < arguments.length; i++) {
258      var source = arguments[i];
259
260      for (var key in source) {
261        if (Object.prototype.hasOwnProperty.call(source, key)) {
262          target[key] = source[key];
263        }
264      }
265    }
266
267    return target;
268  };
269
270  var get = function get(object, property, receiver) {
271    if (object === null) object = Function.prototype;
272    var desc = Object.getOwnPropertyDescriptor(object, property);
273
274    if (desc === undefined) {
275      var parent = Object.getPrototypeOf(object);
276
277      if (parent === null) {
278        return undefined;
279      } else {
280        return get(parent, property, receiver);
281      }
282    } else if ("value" in desc) {
283      return desc.value;
284    } else {
285      var getter = desc.get;
286
287      if (getter === undefined) {
288        return undefined;
289      }
290
291      return getter.call(receiver);
292    }
293  };
294
295  var inherits = function (subClass, superClass) {
296    if (typeof superClass !== "function" && superClass !== null) {
297      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
298    }
299
300    subClass.prototype = Object.create(superClass && superClass.prototype, {
301      constructor: {
302        value: subClass,
303        enumerable: false,
304        writable: true,
305        configurable: true
306      }
307    });
308    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
309  };
310
311  var possibleConstructorReturn = function (self, call) {
312    if (!self) {
313      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
314    }
315
316    return call && (typeof call === "object" || typeof call === "function") ? call : self;
317  };
318
319  /**
320   * Converts value entered as number
321   * or string to integer value.
322   *
323   * @param {String} value
324   * @returns {Number}
325   */
326  function toInt(value) {
327    return parseInt(value);
328  }
329
330  /**
331   * Converts value entered as number
332   * or string to flat value.
333   *
334   * @param {String} value
335   * @returns {Number}
336   */
337  function toFloat(value) {
338    return parseFloat(value);
339  }
340
341  /**
342   * Indicates whether the specified value is a string.
343   *
344   * @param  {*}   value
345   * @return {Boolean}
346   */
347  function isString(value) {
348    return typeof value === 'string';
349  }
350
351  /**
352   * Indicates whether the specified value is an object.
353   *
354   * @param  {*} value
355   * @return {Boolean}
356   *
357   * @see https://github.com/jashkenas/underscore
358   */
359  function isObject(value) {
360    var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
361
362    return type === 'function' || type === 'object' && !!value; // eslint-disable-line no-mixed-operators
363  }
364
365  /**
366   * Indicates whether the specified value is a number.
367   *
368   * @param  {*} value
369   * @return {Boolean}
370   */
371  function isNumber(value) {
372    return typeof value === 'number';
373  }
374
375  /**
376   * Indicates whether the specified value is a function.
377   *
378   * @param  {*} value
379   * @return {Boolean}
380   */
381  function isFunction(value) {
382    return typeof value === 'function';
383  }
384
385  /**
386   * Indicates whether the specified value is undefined.
387   *
388   * @param  {*} value
389   * @return {Boolean}
390   */
391  function isUndefined(value) {
392    return typeof value === 'undefined';
393  }
394
395  /**
396   * Indicates whether the specified value is an array.
vendor: 9,019 bytes, lines 397-779
397   *
398   * @param  {*} value
399   * @return {Boolean}
400   */
401  function isArray(value) {
402    return value.constructor === Array;
403  }
404
405  /**
406   * Creates and initializes specified collection of extensions.
407   * Each extension receives access to instance of glide and rest of components.
408   *
409   * @param {Object} glide
410   * @param {Object} extensions
411   *
412   * @returns {Object}
413   */
414  function mount(glide, extensions, events) {
415    var components = {};
416
417    for (var name in extensions) {
418      if (isFunction(extensions[name])) {
419        components[name] = extensions[name](glide, components, events);
420      } else {
421        warn('Extension must be a function');
422      }
423    }
424
425    for (var _name in components) {
426      if (isFunction(components[_name].mount)) {
427        components[_name].mount();
428      }
429    }
430
431    return components;
432  }
433
434  /**
435   * Defines getter and setter property on the specified object.
436   *
437   * @param  {Object} obj         Object where property has to be defined.
438   * @param  {String} prop        Name of the defined property.
439   * @param  {Object} definition  Get and set definitions for the property.
440   * @return {Void}
441   */
442  function define(obj, prop, definition) {
443    Object.defineProperty(obj, prop, definition);
444  }
445
446  /**
447   * Sorts aphabetically object keys.
448   *
449   * @param  {Object} obj
450   * @return {Object}
451   */
452  function sortKeys(obj) {
453    return Object.keys(obj).sort().reduce(function (r, k) {
454      r[k] = obj[k];
455
456      return r[k], r;
457    }, {});
458  }
459
460  /**
461   * Merges passed settings object with default options.
462   *
463   * @param  {Object} defaults
464   * @param  {Object} settings
465   * @return {Object}
466   */
467  function mergeOptions(defaults, settings) {
468    var options = _extends({}, defaults, settings);
469
470    // `Object.assign` do not deeply merge objects, so we
471    // have to do it manually for every nested object
472    // in options. Although it does not look smart,
473    // it's smaller and faster than some fancy
474    // merging deep-merge algorithm script.
475    if (settings.hasOwnProperty('classes')) {
476      options.classes = _extends({}, defaults.classes, settings.classes);
477
478      if (settings.classes.hasOwnProperty('direction')) {
479        options.classes.direction = _extends({}, defaults.classes.direction, settings.classes.direction);
480      }
481    }
482
483    if (settings.hasOwnProperty('breakpoints')) {
484      options.breakpoints = _extends({}, defaults.breakpoints, settings.breakpoints);
485    }
486
487    return options;
488  }
489
490  var EventsBus = function () {
491    /**
492     * Construct a EventBus instance.
493     *
494     * @param {Object} events
495     */
496    function EventsBus() {
497      var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
498      classCallCheck(this, EventsBus);
499
500      this.events = events;
501      this.hop = events.hasOwnProperty;
502    }
503
504    /**
505     * Adds listener to the specifed event.
506     *
507     * @param {String|Array} event
508     * @param {Function} handler
509     */
510
511
512    createClass(EventsBus, [{
513      key: 'on',
514      value: function on(event, handler) {
515        if (isArray(event)) {
516          for (var i = 0; i < event.length; i++) {
517            this.on(event[i], handler);
518          }
519        }
520
521        // Create the event's object if not yet created
522        if (!this.hop.call(this.events, event)) {
523          this.events[event] = [];
524        }
525
526        // Add the handler to queue
527        var index = this.events[event].push(handler) - 1;
528
529        // Provide handle back for removal of event
530        return {
531          remove: function remove() {
532            delete this.events[event][index];
533          }
534        };
535      }
536
537      /**
538       * Runs registered handlers for specified event.
539       *
540       * @param {String|Array} event
541       * @param {Object=} context
542       */
543
544    }, {
545      key: 'emit',
546      value: function emit(event, context) {
547        if (isArray(event)) {
548          for (var i = 0; i < event.length; i++) {
549            this.emit(event[i], context);
550          }
551        }
552
553        // If the event doesn't exist, or there's no handlers in queue, just leave
554        if (!this.hop.call(this.events, event)) {
555          return;
556        }
557
558        // Cycle through events queue, fire!
559        this.events[event].forEach(function (item) {
560          item(context || {});
561        });
562      }
563    }]);
564    return EventsBus;
565  }();
566
567  var Glide = function () {
568    /**
569     * Construct glide.
570     *
571     * @param  {String} selector
572     * @param  {Object} options
573     */
574    function Glide(selector) {
575      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
576      classCallCheck(this, Glide);
577
578      this._c = {};
579      this._t = [];
580      this._e = new EventsBus();
581
582      this.disabled = false;
583      this.selector = selector;
584      this.settings = mergeOptions(defaults, options);
585      this.index = this.settings.startAt;
586    }
587
588    /**
589     * Initializes glide.
590     *
591     * @param {Object} extensions Collection of extensions to initialize.
592     * @return {Glide}
593     */
594
595
596    createClass(Glide, [{
597      key: 'mount',
598      value: function mount$$1() {
599        var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
600
601        this._e.emit('mount.before');
602
603        if (isObject(extensions)) {
604          this._c = mount(this, extensions, this._e);
605        } else {
606          warn('You need to provide a object on `mount()`');
607        }
608
609        this._e.emit('mount.after');
610
611        return this;
612      }
613
614      /**
615       * Collects an instance `translate` transformers.
616       *
617       * @param  {Array} transformers Collection of transformers.
618       * @return {Void}
619       */
620
621    }, {
622      key: 'mutate',
623      value: function mutate() {
624        var transformers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
625
626        if (isArray(transformers)) {
627          this._t = transformers;
628        } else {
629          warn('You need to provide a array on `mutate()`');
630        }
631
632        return this;
633      }
634
635      /**
636       * Updates glide with specified settings.
637       *
638       * @param {Object} settings
639       * @return {Glide}
640       */
641
642    }, {
643      key: 'update',
644      value: function update() {
645        var settings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
646
647        this.settings = mergeOptions(this.settings, settings);
648
649        if (settings.hasOwnProperty('startAt')) {
650          this.index = settings.startAt;
651        }
652
653        this._e.emit('update');
654
655        return this;
656      }
657
658      /**
659       * Change slide with specified pattern. A pattern must be in the special format:
660       * `>` - Move one forward
661       * `<` - Move one backward
662       * `={i}` - Go to {i} zero-based slide (eq. '=1', will go to second slide)
663       * `>>` - Rewinds to end (last slide)
664       * `<<` - Rewinds to start (first slide)
665       *
666       * @param {String} pattern
667       * @return {Glide}
668       */
669
670    }, {
671      key: 'go',
672      value: function go(pattern) {
673        this._c.Run.make(pattern);
674
675        return this;
676      }
677
678      /**
679       * Move track by specified distance.
680       *
681       * @param {String} distance
682       * @return {Glide}
683       */
684
685    }, {
686      key: 'move',
687      value: function move(distance) {
688        this._c.Transition.disable();
689        this._c.Move.make(distance);
690
691        return this;
692      }
693
694      /**
695       * Destroy instance and revert all changes done by this._c.
696       *
697       * @return {Glide}
698       */
699
700    }, {
701      key: 'destroy',
702      value: function destroy() {
703        this._e.emit('destroy');
704
705        return this;
706      }
707
708      /**
709       * Start instance autoplaying.
710       *
711       * @param {Boolean|Number} interval Run autoplaying with passed interval regardless of `autoplay` settings
712       * @return {Glide}
713       */
714
715    }, {
716      key: 'play',
717      value: function play() {
718        var interval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
719
720        if (interval) {
721          this.settings.autoplay = interval;
722        }
723
724        this._e.emit('play');
725
726        return this;
727      }
728
729      /**
730       * Stop instance autoplaying.
731       *
732       * @return {Glide}
733       */
734
735    }, {
736      key: 'pause',
737      value: function pause() {
738        this._e.emit('pause');
739
740        return this;
741      }
742
743      /**
744       * Sets glide into a idle status.
745       *
746       * @return {Glide}
747       */
748
749    }, {
750      key: 'disable',
751      value: function disable() {
752        this.disabled = true;
753
754        return this;
755      }
756
757      /**
758       * Sets glide into a active status.
759       *
760       * @return {Glide}
761       */
762
763    }, {
764      key: 'enable',
765      value: function enable() {
766        this.disabled = false;
767
768        return this;
769      }
770
771      /**
772       * Adds cuutom event listener with handler.
773       *
774       * @param  {String|Array} event
775       * @param  {Function} handler
776       * @return {Glide}
777       */
778
779    }, {
780      key: 'on',
781      value: function on(event, handler) {
782        this._e.on(event, handler);
783
784        return this;
785      }
786
787      /**
788       * Checks if glide is a precised type.
789       *
790       * @param  {String} name
791       * @return {Boolean}
792       */
793
794    }, {
795      key: 'isType',
796      value: function isType(name) {
797        return this.settings.type === name;
798      }
799
800      /**
801       * Gets value of the core options.
802       *
803       * @return {Object}
804       */
805
806    }, {
807      key: 'settings',
808      get: function get$$1() {
809        return this._o;
810      }
811
812      /**
813       * Sets value of the core options.
814       *
815       * @param  {Object} o
816       * @return {Void}
817       */
818      ,
819      set: function set$$1(o) {
820        if (isObject(o)) {
821          this._o = o;
822        } else {
823          warn('Options must be an `object` instance.');
824        }
825      }
826
827      /**
828       * Gets current index of the slider.
829       *
830       * @return {Object}
831       */
832
833    }, {
834      key: 'index',
835      get: function get$$1() {
836        return this._i;
837      }
838
839      /**
840       * Sets current index a slider.
841       *
842       * @return {Object}
843       */
844      ,
845      set: function set$$1(i) {
846        this._i = toInt(i);
847      }
848
849      /**
850       * Gets type name of the slider.
851       *
852       * @return {String}
853       */
854
855    }, {
856      key: 'type',
857      get: function get$$1() {
858        return this.settings.type;
859      }
860
861      /**
862       * Gets value of the idle status.
863       *
864       * @return {Boolean}
865       */
866
867    }, {
868      key: 'disabled',
869      get: function get$$1() {
870        return this._d;
871      }
872
873      /**
874       * Sets value of the idle status.
875       *
876       * @return {Boolean}
877       */
878      ,
879      set: function set$$1(status) {
880        this._d = !!status;
881      }
882    }]);
883    return Glide;
884  }();
885
886  function Run (Glide, Components, Events) {
887    var Run = {
888      /**
889       * Initializes autorunning of the glide.
890       *
891       * @return {Void}
892       */
893      mount: function mount() {
894        this._o = false;
895      },
896
897
898      /**
899       * Makes glides running based on the passed moving schema.
900       *
901       * @param {String} move
902       */
903      make: function make(move) {
904        var _this = this;
905
906        if (!Glide.disabled) {
907          Glide.disable();
908
909          this.move = move;
910
911          Events.emit('run.before', this.move);
912
913          this.calculate();
914
915          Events.emit('run', this.move);
916
917          Components.Transition.after(function () {
918            if (_this.isStart()) {
919              Events.emit('run.start', _this.move);
920            }
921
922            if (_this.isEnd()) {
923              Events.emit('run.end', _this.move);
924            }
925
926            if (_this.isOffset('<') || _this.isOffset('>')) {
927              _this._o = false;
928
929              Events.emit('run.offset', _this.move);
930            }
931
932            Events.emit('run.after', _this.move);
933
934            Glide.enable();
935          });
936        }
937      },
938
939
940      /**
941       * Calculates current index based on defined move.
942       *
943       * @return {Void}
944       */
945      calculate: function calculate() {
946        var move = this.move,
947            length = this.length;
948        var steps = move.steps,
949            direction = move.direction;
950
951
952        var countableSteps = isNumber(toInt(steps)) && toInt(steps) !== 0;
953
954        switch (direction) {
955          case '>':
956            if (steps === '>') {
957              Glide.index = length;
958            } else if (this.isEnd()) {
959              if (!(Glide.isType('slider') && !Glide.settings.rewind)) {
960                this._o = true;
961
962                Glide.index = 0;
963              }
964            } else if (countableSteps) {
965              Glide.index += Math.min(length - Glide.index, -toInt(steps));
966            } else {
967              Glide.index++;
968            }
969            break;
970
971          case '<':
972            if (steps === '<') {
973              Glide.index = 0;
974            } else if (this.isStart()) {
975              if (!(Glide.isType('slider') && !Glide.settings.rewind)) {
976                this._o = true;
977
978                Glide.index = length;
979              }
980            } else if (countableSteps) {
981              Glide.index -= Math.min(Glide.index, toInt(steps));
982            } else {
983              Glide.index--;
984            }
985            break;
986
987          case '=':
988            Glide.index = steps;
989            break;
990
991          default:
992            warn('Invalid direction pattern [' + direction + steps + '] has been used');
993            break;
994        }
995      },
996
997
998      /**
999       * Checks if we are on the first slide.
1000       *
1001       * @return {Boolean}
1002       */
1003      isStart: function isStart() {
1004        return Glide.index === 0;
1005      },
1006
1007
1008      /**
1009       * Checks if we are on the last slide.
1010       *
1011       * @return {Boolean}
1012       */
1013      isEnd: function isEnd() {
1014        return Glide.index === this.length;
1015      },
1016
1017
1018      /**
1019       * Checks if we are making a offset run.
1020       *
1021       * @param {String} direction
1022       * @return {Boolean}
1023       */
1024      isOffset: function isOffset(direction) {
1025        return this._o && this.move.direction === direction;
1026      }
1027    };
1028
1029    define(Run, 'move', {
1030      /**
1031       * Gets value of the move schema.
1032       *
1033       * @returns {Object}
1034       */
1035      get: function get() {
1036        return this._m;
1037      },
1038
1039
1040      /**
1041       * Sets value of the move schema.
1042       *
1043       * @returns {Object}
1044       */
1045      set: function set(value) {
1046        var step = value.substr(1);
1047
1048        this._m = {
1049          direction: value.substr(0, 1),
1050          steps: step ? toInt(step) ? toInt(step) : step : 0
1051        };
1052      }
1053    });
1054
1055    define(Run, 'length', {
1056      /**
1057       * Gets value of the running distance based
1058       * on zero-indexing number of slides.
1059       *
1060       * @return {Number}
1061       */
1062      get: function get() {
1063        var settings = Glide.settings;
1064        var length = Components.Html.slides.length;
1065
1066        // If the `bound` option is acitve, a maximum running distance should be
1067        // reduced by `perView` and `focusAt` settings. Running distance
1068        // should end before creating an empty space after instance.
1069
1070        if (Glide.isType('slider') && settings.focusAt !== 'center' && settings.bound) {
vendor: 57,673 bytes, lines 1071-3532
1071          return length - 1 - (toInt(settings.perView) - 1) + toInt(settings.focusAt);
1072        }
1073
1074        return length - 1;
1075      }
1076    });
1077
1078    define(Run, 'offset', {
1079      /**
1080       * Gets status of the offsetting flag.
1081       *
1082       * @return {Boolean}
1083       */
1084      get: function get() {
1085        return this._o;
1086      }
1087    });
1088
1089    return Run;
1090  }
1091
1092  /**
1093   * Returns a current time.
1094   *
1095   * @return {Number}
1096   */
1097  function now() {
1098    return new Date().getTime();
1099  }
1100
1101  /**
1102   * Returns a function, that, when invoked, will only be triggered
1103   * at most once during a given window of time.
1104   *
1105   * @param {Function} func
1106   * @param {Number} wait
1107   * @param {Object=} options
1108   * @return {Function}
1109   *
1110   * @see https://github.com/jashkenas/underscore
1111   */
1112  function throttle(func, wait, options) {
1113    var timeout = void 0,
1114        context = void 0,
1115        args = void 0,
1116        result = void 0;
1117    var previous = 0;
1118    if (!options) options = {};
1119
1120    var later = function later() {
1121      previous = options.leading === false ? 0 : now();
1122      timeout = null;
1123      result = func.apply(context, args);
1124      if (!timeout) context = args = null;
1125    };
1126
1127    var throttled = function throttled() {
1128      var at = now();
1129      if (!previous && options.leading === false) previous = at;
1130      var remaining = wait - (at - previous);
1131      context = this;
1132      args = arguments;
1133      if (remaining <= 0 || remaining > wait) {
1134        if (timeout) {
1135          clearTimeout(timeout);
1136          timeout = null;
1137        }
1138        previous = at;
1139        result = func.apply(context, args);
1140        if (!timeout) context = args = null;
1141      } else if (!timeout && options.trailing !== false) {
1142        timeout = setTimeout(later, remaining);
1143      }
1144      return result;
1145    };
1146
1147    throttled.cancel = function () {
1148      clearTimeout(timeout);
1149      previous = 0;
1150      timeout = context = args = null;
1151    };
1152
1153    return throttled;
1154  }
1155
1156  var MARGIN_TYPE = {
1157    ltr: ['marginLeft', 'marginRight'],
1158    rtl: ['marginRight', 'marginLeft']
1159  };
1160
1161  function Gaps (Glide, Components, Events) {
1162    var Gaps = {
1163      /**
1164       * Applies gaps between slides. First and last
1165       * slides do not receive it's edge margins.
1166       *
1167       * @param {HTMLCollection} slides
1168       * @return {Void}
1169       */
1170      apply: function apply(slides) {
1171        for (var i = 0, len = slides.length; i < len; i++) {
1172          var style = slides[i].style;
1173          var direction = Components.Direction.value;
1174
1175          if (i !== 0) {
1176            style[MARGIN_TYPE[direction][0]] = this.value / 2 + 'px';
1177          } else {
1178            style[MARGIN_TYPE[direction][0]] = '';
1179          }
1180
1181          if (i !== slides.length - 1) {
1182            style[MARGIN_TYPE[direction][1]] = this.value / 2 + 'px';
1183          } else {
1184            style[MARGIN_TYPE[direction][1]] = '';
1185          }
1186        }
1187      },
1188
1189
1190      /**
1191       * Removes gaps from the slides.
1192       *
1193       * @param {HTMLCollection} slides
1194       * @returns {Void}
1195      */
1196      remove: function remove(slides) {
1197        for (var i = 0, len = slides.length; i < len; i++) {
1198          var style = slides[i].style;
1199
1200          style.marginLeft = '';
1201          style.marginRight = '';
1202        }
1203      }
1204    };
1205
1206    define(Gaps, 'value', {
1207      /**
1208       * Gets value of the gap.
1209       *
1210       * @returns {Number}
1211       */
1212      get: function get() {
1213        return toInt(Glide.settings.gap);
1214      }
1215    });
1216
1217    define(Gaps, 'grow', {
1218      /**
1219       * Gets additional dimentions value caused by gaps.
1220       * Used to increase width of the slides wrapper.
1221       *
1222       * @returns {Number}
1223       */
1224      get: function get() {
1225        return Gaps.value * (Components.Sizes.length - 1);
1226      }
1227    });
1228
1229    define(Gaps, 'reductor', {
1230      /**
1231       * Gets reduction value caused by gaps.
1232       * Used to subtract width of the slides.
1233       *
1234       * @returns {Number}
1235       */
1236      get: function get() {
1237        var perView = Glide.settings.perView;
1238
1239        return Gaps.value * (perView - 1) / perView;
1240      }
1241    });
1242
1243    /**
1244     * Apply calculated gaps:
1245     * - after building, so slides (including clones) will receive proper margins
1246     * - on updating via API, to recalculate gaps with new options
1247     */
1248    Events.on(['build.after', 'update'], throttle(function () {
1249      Gaps.apply(Components.Html.wrapper.children);
1250    }, 30));
1251
1252    /**
1253     * Remove gaps:
1254     * - on destroying to bring markup to its inital state
1255     */
1256    Events.on('destroy', function () {
1257      Gaps.remove(Components.Html.wrapper.children);
1258    });
1259
1260    return Gaps;
1261  }
1262
1263  /**
1264   * Finds siblings nodes of the passed node.
1265   *
1266   * @param  {Element} node
1267   * @return {Array}
1268   */
1269  function siblings(node) {
1270    if (node && node.parentNode) {
1271      var n = node.parentNode.firstChild;
1272      var matched = [];
1273
1274      for (; n; n = n.nextSibling) {
1275        if (n.nodeType === 1 && n !== node) {
1276          matched.push(n);
1277        }
1278      }
1279
1280      return matched;
1281    }
1282
1283    return [];
1284  }
1285
1286  /**
1287   * Checks if passed node exist and is a valid element.
1288   *
1289   * @param  {Element} node
1290   * @return {Boolean}
1291   */
1292  function exist(node) {
1293    // if (node && node instanceof window.HTMLElement) {
1294    if (node && node.nodeType === 1) {
1295      return true;
1296    }
1297
1298    return false;
1299  }
1300
1301  var TRACK_SELECTOR = '[data-glide-el="track"]';
1302
1303  function Html (Glide, Components) {
1304    var Html = {
1305      /**
1306       * Setup slider HTML nodes.
1307       *
1308       * @param {Glide} glide
1309       */
1310      mount: function mount() {
1311        this.root = Glide.selector;
1312        this.track = this.root.querySelector(TRACK_SELECTOR);
1313        this.slides = Array.prototype.slice.call(this.wrapper.children).filter(function (slide) {
1314          return !slide.classList.contains(Glide.settings.classes.cloneSlide);
1315        });
1316      }
1317    };
1318
1319    define(Html, 'root', {
1320      /**
1321       * Gets node of the glide main element.
1322       *
1323       * @return {Object}
1324       */
1325      get: function get() {
1326        return Html._r;
1327      },
1328
1329
1330      /**
1331       * Sets node of the glide main element.
1332       *
1333       * @return {Object}
1334       */
1335      set: function set(r) {
1336        if (isString(r)) {
1337          r = document.querySelector(r);
1338        }
1339
1340        if (exist(r)) {
1341          Html._r = r;
1342        } else {
1343          warn('Root element must be a existing Html node');
1344        }
1345      }
1346    });
1347
1348    define(Html, 'track', {
1349      /**
1350       * Gets node of the glide track with slides.
1351       *
1352       * @return {Object}
1353       */
1354      get: function get() {
1355        return Html._t;
1356      },
1357
1358
1359      /**
1360       * Sets node of the glide track with slides.
1361       *
1362       * @return {Object}
1363       */
1364      set: function set(t) {
1365        if (exist(t)) {
1366          Html._t = t;
1367        } else {
1368          warn('Could not find track element. Please use ' + TRACK_SELECTOR + ' attribute.');
1369        }
1370      }
1371    });
1372
1373    define(Html, 'wrapper', {
1374      /**
1375       * Gets node of the slides wrapper.
1376       *
1377       * @return {Object}
1378       */
1379      get: function get() {
1380        return Html.track.children[0];
1381      }
1382    });
1383
1384    return Html;
1385  }
1386
1387  function Peek (Glide, Components, Events) {
1388    var Peek = {
1389      /**
1390       * Setups how much to peek based on settings.
1391       *
1392       * @return {Void}
1393       */
1394      mount: function mount() {
1395        this.value = Glide.settings.peek;
1396      }
1397    };
1398
1399    define(Peek, 'value', {
1400      /**
1401       * Gets value of the peek.
1402       *
1403       * @returns {Number|Object}
1404       */
1405      get: function get() {
1406        return Peek._v;
1407      },
1408
1409
1410      /**
1411       * Sets value of the peek.
1412       *
1413       * @param {Number|Object} value
1414       * @return {Void}
1415       */
1416      set: function set(value) {
1417        if (isObject(value)) {
1418          value.before = toInt(value.before);
1419          value.after = toInt(value.after);
1420        } else {
1421          value = toInt(value);
1422        }
1423
1424        Peek._v = value;
1425      }
1426    });
1427
1428    define(Peek, 'reductor', {
1429      /**
1430       * Gets reduction value caused by peek.
1431       *
1432       * @returns {Number}
1433       */
1434      get: function get() {
1435        var value = Peek.value;
1436        var perView = Glide.settings.perView;
1437
1438        if (isObject(value)) {
1439          return value.before / perView + value.after / perView;
1440        }
1441
1442        return value * 2 / perView;
1443      }
1444    });
1445
1446    /**
1447     * Recalculate peeking sizes on:
1448     * - when resizing window to update to proper percents
1449     */
1450    Events.on(['resize', 'update'], function () {
1451      Peek.mount();
1452    });
1453
1454    return Peek;
1455  }
1456
1457  function Move (Glide, Components, Events) {
1458    var Move = {
1459      /**
1460       * Constructs move component.
1461       *
1462       * @returns {Void}
1463       */
1464      mount: function mount() {
1465        this._o = 0;
1466      },
1467
1468
1469      /**
1470       * Calculates a movement value based on passed offset and currently active index.
1471       *
1472       * @param  {Number} offset
1473       * @return {Void}
1474       */
1475      make: function make() {
1476        var _this = this;
1477
1478        var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
1479
1480        this.offset = offset;
1481
1482        Events.emit('move', {
1483          movement: this.value
1484        });
1485
1486        Components.Transition.after(function () {
1487          Events.emit('move.after', {
1488            movement: _this.value
1489          });
1490        });
1491      }
1492    };
1493
1494    define(Move, 'offset', {
1495      /**
1496       * Gets an offset value used to modify current translate.
1497       *
1498       * @return {Object}
1499       */
1500      get: function get() {
1501        return Move._o;
1502      },
1503
1504
1505      /**
1506       * Sets an offset value used to modify current translate.
1507       *
1508       * @return {Object}
1509       */
1510      set: function set(value) {
1511        Move._o = !isUndefined(value) ? toInt(value) : 0;
1512      }
1513    });
1514
1515    define(Move, 'translate', {
1516      /**
1517       * Gets a raw movement value.
1518       *
1519       * @return {Number}
1520       */
1521      get: function get() {
1522        return Components.Sizes.slideWidth * Glide.index;
1523      }
1524    });
1525
1526    define(Move, 'value', {
1527      /**
1528       * Gets an actual movement value corrected by offset.
1529       *
1530       * @return {Number}
1531       */
1532      get: function get() {
1533        var offset = this.offset;
1534        var translate = this.translate;
1535
1536        if (Components.Direction.is('rtl')) {
1537          return translate + offset;
1538        }
1539
1540        return translate - offset;
1541      }
1542    });
1543
1544    /**
1545     * Make movement to proper slide on:
1546     * - before build, so glide will start at `startAt` index
1547     * - on each standard run to move to newly calculated index
1548     */
1549    Events.on(['build.before', 'run'], function () {
1550      Move.make();
1551    });
1552
1553    return Move;
1554  }
1555
1556  function Sizes (Glide, Components, Events) {
1557    var Sizes = {
1558      /**
1559       * Setups dimentions of slides.
1560       *
1561       * @return {Void}
1562       */
1563      setupSlides: function setupSlides() {
1564        var width = this.slideWidth + 'px';
1565        var slides = Components.Html.slides;
1566
1567        for (var i = 0; i < slides.length; i++) {
1568          slides[i].style.width = width;
1569        }
1570      },
1571
1572
1573      /**
1574       * Setups dimentions of slides wrapper.
1575       *
1576       * @return {Void}
1577       */
1578      setupWrapper: function setupWrapper(dimention) {
1579        Components.Html.wrapper.style.width = this.wrapperSize + 'px';
1580      },
1581
1582
1583      /**
1584       * Removes applied styles from HTML elements.
1585       *
1586       * @returns {Void}
1587       */
1588      remove: function remove() {
1589        var slides = Components.Html.slides;
1590
1591        for (var i = 0; i < slides.length; i++) {
1592          slides[i].style.width = '';
1593        }
1594
1595        Components.Html.wrapper.style.width = '';
1596      }
1597    };
1598
1599    define(Sizes, 'length', {
1600      /**
1601       * Gets count number of the slides.
1602       *
1603       * @return {Number}
1604       */
1605      get: function get() {
1606        return Components.Html.slides.length;
1607      }
1608    });
1609
1610    define(Sizes, 'width', {
1611      /**
1612       * Gets width value of the glide.
1613       *
1614       * @return {Number}
1615       */
1616      get: function get() {
1617        return Components.Html.root.offsetWidth;
1618      }
1619    });
1620
1621    define(Sizes, 'wrapperSize', {
1622      /**
1623       * Gets size of the slides wrapper.
1624       *
1625       * @return {Number}
1626       */
1627      get: function get() {
1628        return Sizes.slideWidth * Sizes.length + Components.Gaps.grow + Components.Clones.grow;
1629      }
1630    });
1631
1632    define(Sizes, 'slideWidth', {
1633      /**
1634       * Gets width value of the single slide.
1635       *
1636       * @return {Number}
1637       */
1638      get: function get() {
1639        return Sizes.width / Glide.settings.perView - Components.Peek.reductor - Components.Gaps.reductor;
1640      }
1641    });
1642
1643    /**
1644     * Apply calculated glide's dimensions:
1645     * - before building, so other dimentions (e.g. translate) will be calculated propertly
1646     * - when resizing window to recalculate sildes dimensions
1647     * - on updating via API, to calculate dimensions based on new options
1648     */
1649    Events.on(['build.before', 'resize', 'update'], function () {
1650      Sizes.setupSlides();
1651      Sizes.setupWrapper();
1652    });
1653
1654    /**
1655     * Remove calculated glide's dimensions:
1656     * - on destoting to bring markup to its inital state
1657     */
1658    Events.on('destroy', function () {
1659      Sizes.remove();
1660    });
1661
1662    return Sizes;
1663  }
1664
1665  function Build (Glide, Components, Events) {
1666    var Build = {
1667      /**
1668       * Init glide building. Adds classes, sets
1669       * dimensions and setups initial state.
1670       *
1671       * @return {Void}
1672       */
1673      mount: function mount() {
1674        Events.emit('build.before');
1675
1676        this.typeClass();
1677        this.activeClass();
1678
1679        Events.emit('build.after');
1680      },
1681
1682
1683      /**
1684       * Adds `type` class to the glide element.
1685       *
1686       * @return {Void}
1687       */
1688      typeClass: function typeClass() {
1689        Components.Html.root.classList.add(Glide.settings.classes[Glide.settings.type]);
1690      },
1691
1692
1693      /**
1694       * Sets active class to current slide.
1695       *
1696       * @return {Void}
1697       */
1698      activeClass: function activeClass() {
1699        var classes = Glide.settings.classes;
1700        var slide = Components.Html.slides[Glide.index];
1701
1702        if (slide) {
1703          slide.classList.add(classes.activeSlide);
1704
1705          siblings(slide).forEach(function (sibling) {
1706            sibling.classList.remove(classes.activeSlide);
1707          });
1708        }
1709      },
1710
1711
1712      /**
1713       * Removes HTML classes applied at building.
1714       *
1715       * @return {Void}
1716       */
1717      removeClasses: function removeClasses() {
1718        var classes = Glide.settings.classes;
1719
1720        Components.Html.root.classList.remove(classes[Glide.settings.type]);
1721
1722        Components.Html.slides.forEach(function (sibling) {
1723          sibling.classList.remove(classes.activeSlide);
1724        });
1725      }
1726    };
1727
1728    /**
1729     * Clear building classes:
1730     * - on destroying to bring HTML to its initial state
1731     * - on updating to remove classes before remounting component
1732     */
1733    Events.on(['destroy', 'update'], function () {
1734      Build.removeClasses();
1735    });
1736
1737    /**
1738     * Remount component:
1739     * - on resizing of the window to calculate new dimentions
1740     * - on updating settings via API
1741     */
1742    Events.on(['resize', 'update'], function () {
1743      Build.mount();
1744    });
1745
1746    /**
1747     * Swap active class of current slide:
1748     * - after each move to the new index
1749     */
1750    Events.on('move.after', function () {
1751      Build.activeClass();
1752    });
1753
1754    return Build;
1755  }
1756
1757  function Clones (Glide, Components, Events) {
1758    var Clones = {
1759      /**
1760       * Create pattern map and collect slides to be cloned.
1761       */
1762      mount: function mount() {
1763        this.items = [];
1764
1765        if (Glide.isType('carousel')) {
1766          this.items = this.collect();
1767        }
1768      },
1769
1770
1771      /**
1772       * Collect clones with pattern.
1773       *
1774       * @return {Void}
1775       */
1776      collect: function collect() {
1777        var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1778        var slides = Components.Html.slides;
1779        var _Glide$settings = Glide.settings,
1780            perView = _Glide$settings.perView,
1781            classes = _Glide$settings.classes;
1782
1783
1784        var peekIncrementer = +!!Glide.settings.peek;
1785        var part = perView + peekIncrementer;
1786        var start = slides.slice(0, part);
1787        var end = slides.slice(-part);
1788
1789        for (var r = 0; r < Math.max(1, Math.floor(perView / slides.length)); r++) {
1790          for (var i = 0; i < start.length; i++) {
1791            var clone = start[i].cloneNode(true);
1792
1793            clone.classList.add(classes.cloneSlide);
1794
1795            items.push(clone);
1796          }
1797
1798          for (var _i = 0; _i < end.length; _i++) {
1799            var _clone = end[_i].cloneNode(true);
1800
1801            _clone.classList.add(classes.cloneSlide);
1802
1803            items.unshift(_clone);
1804          }
1805        }
1806
1807        return items;
1808      },
1809
1810
1811      /**
1812       * Append cloned slides with generated pattern.
1813       *
1814       * @return {Void}
1815       */
1816      append: function append() {
1817        var items = this.items;
1818        var _Components$Html = Components.Html,
1819            wrapper = _Components$Html.wrapper,
1820            slides = _Components$Html.slides;
1821
1822
1823        var half = Math.floor(items.length / 2);
1824        var prepend = items.slice(0, half).reverse();
1825        var append = items.slice(half, items.length);
1826        var width = Components.Sizes.slideWidth + 'px';
1827
1828        for (var i = 0; i < append.length; i++) {
1829          wrapper.appendChild(append[i]);
1830        }
1831
1832        for (var _i2 = 0; _i2 < prepend.length; _i2++) {
1833          wrapper.insertBefore(prepend[_i2], slides[0]);
1834        }
1835
1836        for (var _i3 = 0; _i3 < items.length; _i3++) {
1837          items[_i3].style.width = width;
1838        }
1839      },
1840
1841
1842      /**
1843       * Remove all cloned slides.
1844       *
1845       * @return {Void}
1846       */
1847      remove: function remove() {
1848        var items = this.items;
1849
1850
1851        for (var i = 0; i < items.length; i++) {
1852          Components.Html.wrapper.removeChild(items[i]);
1853        }
1854      }
1855    };
1856
1857    define(Clones, 'grow', {
1858      /**
1859       * Gets additional dimentions value caused by clones.
1860       *
1861       * @return {Number}
1862       */
1863      get: function get() {
1864        return (Components.Sizes.slideWidth + Components.Gaps.value) * Clones.items.length;
1865      }
1866    });
1867
1868    /**
1869     * Append additional slide's clones:
1870     * - while glide's type is `carousel`
1871     */
1872    Events.on('update', function () {
1873      Clones.remove();
1874      Clones.mount();
1875      Clones.append();
1876    });
1877
1878    /**
1879     * Append additional slide's clones:
1880     * - while glide's type is `carousel`
1881     */
1882    Events.on('build.before', function () {
1883      if (Glide.isType('carousel')) {
1884        Clones.append();
1885      }
1886    });
1887
1888    /**
1889     * Remove clones HTMLElements:
1890     * - on destroying, to bring HTML to its initial state
1891     */
1892    Events.on('destroy', function () {
1893      Clones.remove();
1894    });
1895
1896    return Clones;
1897  }
1898
1899  var EventsBinder = function () {
1900    /**
1901     * Construct a EventsBinder instance.
1902     */
1903    function EventsBinder() {
1904      var listeners = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1905      classCallCheck(this, EventsBinder);
1906
1907      this.listeners = listeners;
1908    }
1909
1910    /**
1911     * Adds events listeners to arrows HTML elements.
1912     *
1913     * @param  {String|Array} events
1914     * @param  {Element|Window|Document} el
1915     * @param  {Function} closure
1916     * @param  {Boolean|Object} capture
1917     * @return {Void}
1918     */
1919
1920
1921    createClass(EventsBinder, [{
1922      key: 'on',
1923      value: function on(events, el, closure) {
1924        var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
1925
1926        if (isString(events)) {
1927          events = [events];
1928        }
1929
1930        for (var i = 0; i < events.length; i++) {
1931          this.listeners[events[i]] = closure;
1932
1933          el.addEventListener(events[i], this.listeners[events[i]], capture);
1934        }
1935      }
1936
1937      /**
1938       * Removes event listeners from arrows HTML elements.
1939       *
1940       * @param  {String|Array} events
1941       * @param  {Element|Window|Document} el
1942       * @param  {Boolean|Object} capture
1943       * @return {Void}
1944       */
1945
1946    }, {
1947      key: 'off',
1948      value: function off(events, el) {
1949        var capture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1950
1951        if (isString(events)) {
1952          events = [events];
1953        }
1954
1955        for (var i = 0; i < events.length; i++) {
1956          el.removeEventListener(events[i], this.listeners[events[i]], capture);
1957        }
1958      }
1959
1960      /**
1961       * Destroy collected listeners.
1962       *
1963       * @returns {Void}
1964       */
1965
1966    }, {
1967      key: 'destroy',
1968      value: function destroy() {
1969        delete this.listeners;
1970      }
1971    }]);
1972    return EventsBinder;
1973  }();
1974
1975  function Resize (Glide, Components, Events) {
1976    /**
1977     * Instance of the binder for DOM Events.
1978     *
1979     * @type {EventsBinder}
1980     */
1981    var Binder = new EventsBinder();
1982
1983    var Resize = {
1984      /**
1985       * Initializes window bindings.
1986       */
1987      mount: function mount() {
1988        this.bind();
1989      },
1990
1991
1992      /**
1993       * Binds `rezsize` listener to the window.
1994       * It's a costly event, so we are debouncing it.
1995       *
1996       * @return {Void}
1997       */
1998      bind: function bind() {
1999        Binder.on('resize', window, throttle(function () {
2000          Events.emit('resize');
2001        }, Glide.settings.throttle));
2002      },
2003
2004
2005      /**
2006       * Unbinds listeners from the window.
2007       *
2008       * @return {Void}
2009       */
2010      unbind: function unbind() {
2011        Binder.off('resize', window);
2012      }
2013    };
2014
2015    /**
2016     * Remove bindings from window:
2017     * - on destroying, to remove added EventListener
2018     */
2019    Events.on('destroy', function () {
2020      Resize.unbind();
2021      Binder.destroy();
2022    });
2023
2024    return Resize;
2025  }
2026
2027  var VALID_DIRECTIONS = ['ltr', 'rtl'];
2028  var FLIPED_MOVEMENTS = {
2029    '>': '<',
2030    '<': '>',
2031    '=': '='
2032  };
2033
2034  function Direction (Glide, Components, Events) {
2035    var Direction = {
2036      /**
2037       * Setups gap value based on settings.
2038       *
2039       * @return {Void}
2040       */
2041      mount: function mount() {
2042        this.value = Glide.settings.direction;
2043      },
2044
2045
2046      /**
2047       * Resolves pattern based on direction value
2048       *
2049       * @param {String} pattern
2050       * @returns {String}
2051       */
2052      resolve: function resolve(pattern) {
2053        var token = pattern.slice(0, 1);
2054
2055        if (this.is('rtl')) {
2056          return pattern.split(token).join(FLIPED_MOVEMENTS[token]);
2057        }
2058
2059        return pattern;
2060      },
2061
2062
2063      /**
2064       * Checks value of direction mode.
2065       *
2066       * @param {String} direction
2067       * @returns {Boolean}
2068       */
2069      is: function is(direction) {
2070        return this.value === direction;
2071      },
2072
2073
2074      /**
2075       * Applies direction class to the root HTML element.
2076       *
2077       * @return {Void}
2078       */
2079      addClass: function addClass() {
2080        Components.Html.root.classList.add(Glide.settings.classes.direction[this.value]);
2081      },
2082
2083
2084      /**
2085       * Removes direction class from the root HTML element.
2086       *
2087       * @return {Void}
2088       */
2089      removeClass: function removeClass() {
2090        Components.Html.root.classList.remove(Glide.settings.classes.direction[this.value]);
2091      }
2092    };
2093
2094    define(Direction, 'value', {
2095      /**
2096       * Gets value of the direction.
2097       *
2098       * @returns {Number}
2099       */
2100      get: function get() {
2101        return Direction._v;
2102      },
2103
2104
2105      /**
2106       * Sets value of the direction.
2107       *
2108       * @param {String} value
2109       * @return {Void}
2110       */
2111      set: function set(value) {
2112        if (VALID_DIRECTIONS.indexOf(value) > -1) {
2113          Direction._v = value;
2114        } else {
2115          warn('Direction value must be `ltr` or `rtl`');
2116        }
2117      }
2118    });
2119
2120    /**
2121     * Clear direction class:
2122     * - on destroy to bring HTML to its initial state
2123     * - on update to remove class before reappling bellow
2124     */
2125    Events.on(['destroy', 'update'], function () {
2126      Direction.removeClass();
2127    });
2128
2129    /**
2130     * Remount component:
2131     * - on update to reflect changes in direction value
2132     */
2133    Events.on('update', function () {
2134      Direction.mount();
2135    });
2136
2137    /**
2138     * Apply direction class:
2139     * - before building to apply class for the first time
2140     * - on updating to reapply direction class that may changed
2141     */
2142    Events.on(['build.before', 'update'], function () {
2143      Direction.addClass();
2144    });
2145
2146    return Direction;
2147  }
2148
2149  /**
2150   * Reflects value of glide movement.
2151   *
2152   * @param  {Object} Glide
2153   * @param  {Object} Components
2154   * @return {Object}
2155   */
2156  function Rtl (Glide, Components) {
2157    return {
2158      /**
2159       * Negates the passed translate if glide is in RTL option.
2160       *
2161       * @param  {Number} translate
2162       * @return {Number}
2163       */
2164      modify: function modify(translate) {
2165        if (Components.Direction.is('rtl')) {
2166          return -translate;
2167        }
2168
2169        return translate;
2170      }
2171    };
2172  }
2173
2174  /**
2175   * Updates glide movement with a `gap` settings.
2176   *
2177   * @param  {Object} Glide
2178   * @param  {Object} Components
2179   * @return {Object}
2180   */
2181  function Gap (Glide, Components) {
2182    return {
2183      /**
2184       * Modifies passed translate value with number in the `gap` settings.
2185       *
2186       * @param  {Number} translate
2187       * @return {Number}
2188       */
2189      modify: function modify(translate) {
2190        return translate + Components.Gaps.value * Glide.index;
2191      }
2192    };
2193  }
2194
2195  /**
2196   * Updates glide movement with width of additional clones width.
2197   *
2198   * @param  {Object} Glide
2199   * @param  {Object} Components
2200   * @return {Object}
2201   */
2202  function Grow (Glide, Components) {
2203    return {
2204      /**
2205       * Adds to the passed translate width of the half of clones.
2206       *
2207       * @param  {Number} translate
2208       * @return {Number}
2209       */
2210      modify: function modify(translate) {
2211        return translate + Components.Clones.grow / 2;
2212      }
2213    };
2214  }
2215
2216  /**
2217   * Updates glide movement with a `peek` settings.
2218   *
2219   * @param  {Object} Glide
2220   * @param  {Object} Components
2221   * @return {Object}
2222   */
2223  function Peeking (Glide, Components) {
2224    return {
2225      /**
2226       * Modifies passed translate value with a `peek` setting.
2227       *
2228       * @param  {Number} translate
2229       * @return {Number}
2230       */
2231      modify: function modify(translate) {
2232        if (Glide.settings.focusAt >= 0) {
2233          var peek = Components.Peek.value;
2234
2235          if (isObject(peek)) {
2236            return translate - peek.before;
2237          }
2238
2239          return translate - peek;
2240        }
2241
2242        return translate;
2243      }
2244    };
2245  }
2246
2247  /**
2248   * Updates glide movement with a `focusAt` settings.
2249   *
2250   * @param  {Object} Glide
2251   * @param  {Object} Components
2252   * @return {Object}
2253   */
2254  function Focusing (Glide, Components) {
2255    return {
2256      /**
2257       * Modifies passed translate value with index in the `focusAt` setting.
2258       *
2259       * @param  {Number} translate
2260       * @return {Number}
2261       */
2262      modify: function modify(translate) {
2263        var gap = Components.Gaps.value;
2264        var width = Components.Sizes.width;
2265        var focusAt = Glide.settings.focusAt;
2266        var slideWidth = Components.Sizes.slideWidth;
2267
2268        if (focusAt === 'center') {
2269          return translate - (width / 2 - slideWidth / 2);
2270        }
2271
2272        return translate - slideWidth * focusAt - gap * focusAt;
2273      }
2274    };
2275  }
2276
2277  /**
2278   * Applies diffrent transformers on translate value.
2279   *
2280   * @param  {Object} Glide
2281   * @param  {Object} Components
2282   * @return {Object}
2283   */
2284  function mutator (Glide, Components, Events) {
2285    /**
2286     * Merge instance transformers with collection of default transformers.
2287     * It's important that the Rtl component be last on the list,
2288     * so it reflects all previous transformations.
2289     *
2290     * @type {Array}
2291     */
2292    var TRANSFORMERS = [Gap, Grow, Peeking, Focusing].concat(Glide._t, [Rtl]);
2293
2294    return {
2295      /**
2296       * Piplines translate value with registered transformers.
2297       *
2298       * @param  {Number} translate
2299       * @return {Number}
2300       */
2301      mutate: function mutate(translate) {
2302        for (var i = 0; i < TRANSFORMERS.length; i++) {
2303          var transformer = TRANSFORMERS[i];
2304
2305          if (isFunction(transformer) && isFunction(transformer().modify)) {
2306            translate = transformer(Glide, Components, Events).modify(translate);
2307          } else {
2308            warn('Transformer should be a function that returns an object with `modify()` method');
2309          }
2310        }
2311
2312        return translate;
2313      }
2314    };
2315  }
2316
2317  function Translate (Glide, Components, Events) {
2318    var Translate = {
2319      /**
2320       * Sets value of translate on HTML element.
2321       *
2322       * @param {Number} value
2323       * @return {Void}
2324       */
2325      set: function set(value) {
2326        var transform = mutator(Glide, Components).mutate(value);
2327
2328        Components.Html.wrapper.style.transform = 'translate3d(' + -1 * transform + 'px, 0px, 0px)';
2329      },
2330
2331
2332      /**
2333       * Removes value of translate from HTML element.
2334       *
2335       * @return {Void}
2336       */
2337      remove: function remove() {
2338        Components.Html.wrapper.style.transform = '';
2339      }
2340    };
2341
2342    /**
2343     * Set new translate value:
2344     * - on move to reflect index change
2345     * - on updating via API to reflect possible changes in options
2346     */
2347    Events.on('move', function (context) {
2348      var gap = Components.Gaps.value;
2349      var length = Components.Sizes.length;
2350      var width = Components.Sizes.slideWidth;
2351
2352      if (Glide.isType('carousel') && Components.Run.isOffset('<')) {
2353        Components.Transition.after(function () {
2354          Events.emit('translate.jump');
2355
2356          Translate.set(width * (length - 1));
2357        });
2358
2359        return Translate.set(-width - gap * length);
2360      }
2361
2362      if (Glide.isType('carousel') && Components.Run.isOffset('>')) {
2363        Components.Transition.after(function () {
2364          Events.emit('translate.jump');
2365
2366          Translate.set(0);
2367        });
2368
2369        return Translate.set(width * length + gap * length);
2370      }
2371
2372      return Translate.set(context.movement);
2373    });
2374
2375    /**
2376     * Remove translate:
2377     * - on destroying to bring markup to its inital state
2378     */
2379    Events.on('destroy', function () {
2380      Translate.remove();
2381    });
2382
2383    return Translate;
2384  }
2385
2386  function Transition (Glide, Components, Events) {
2387    /**
2388     * Holds inactivity status of transition.
2389     * When true transition is not applied.
2390     *
2391     * @type {Boolean}
2392     */
2393    var disabled = false;
2394
2395    var Transition = {
2396      /**
2397       * Composes string of the CSS transition.
2398       *
2399       * @param {String} property
2400       * @return {String}
2401       */
2402      compose: function compose(property) {
2403        var settings = Glide.settings;
2404
2405        if (!disabled) {
2406          return property + ' ' + this.duration + 'ms ' + settings.animationTimingFunc;
2407        }
2408
2409        return property + ' 0ms ' + settings.animationTimingFunc;
2410      },
2411
2412
2413      /**
2414       * Sets value of transition on HTML element.
2415       *
2416       * @param {String=} property
2417       * @return {Void}
2418       */
2419      set: function set() {
2420        var property = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'transform';
2421
2422        Components.Html.wrapper.style.transition = this.compose(property);
2423      },
2424
2425
2426      /**
2427       * Removes value of transition from HTML element.
2428       *
2429       * @return {Void}
2430       */
2431      remove: function remove() {
2432        Components.Html.wrapper.style.transition = '';
2433      },
2434
2435
2436      /**
2437       * Runs callback after animation.
2438       *
2439       * @param  {Function} callback
2440       * @return {Void}
2441       */
2442      after: function after(callback) {
2443        setTimeout(function () {
2444          callback();
2445        }, this.duration);
2446      },
2447
2448
2449      /**
2450       * Enable transition.
2451       *
2452       * @return {Void}
2453       */
2454      enable: function enable() {
2455        disabled = false;
2456
2457        this.set();
2458      },
2459
2460
2461      /**
2462       * Disable transition.
2463       *
2464       * @return {Void}
2465       */
2466      disable: function disable() {
2467        disabled = true;
2468
2469        this.set();
2470      }
2471    };
2472
2473    define(Transition, 'duration', {
2474      /**
2475       * Gets duration of the transition based
2476       * on currently running animation type.
2477       *
2478       * @return {Number}
2479       */
2480      get: function get() {
2481        var settings = Glide.settings;
2482
2483        if (Glide.isType('slider') && Components.Run.offset) {
2484          return settings.rewindDuration;
2485        }
2486
2487        return settings.animationDuration;
2488      }
2489    });
2490
2491    /**
2492     * Set transition `style` value:
2493     * - on each moving, because it may be cleared by offset move
2494     */
2495    Events.on('move', function () {
2496      Transition.set();
2497    });
2498
2499    /**
2500     * Disable transition:
2501     * - before initial build to avoid transitioning from `0` to `startAt` index
2502     * - while resizing window and recalculating dimentions
2503     * - on jumping from offset transition at start and end edges in `carousel` type
2504     */
2505    Events.on(['build.before', 'resize', 'translate.jump'], function () {
2506      Transition.disable();
2507    });
2508
2509    /**
2510     * Enable transition:
2511     * - on each running, because it may be disabled by offset move
2512     */
2513    Events.on('run', function () {
2514      Transition.enable();
2515    });
2516
2517    /**
2518     * Remove transition:
2519     * - on destroying to bring markup to its inital state
2520     */
2521    Events.on('destroy', function () {
2522      Transition.remove();
2523    });
2524
2525    return Transition;
2526  }
2527
2528  /**
2529   * Test via a getter in the options object to see
2530   * if the passive property is accessed.
2531   *
2532   * @see https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
2533   */
2534
2535  var supportsPassive = false;
2536
2537  try {
2538    var opts = Object.defineProperty({}, 'passive', {
2539      get: function get() {
2540        supportsPassive = true;
2541      }
2542    });
2543
2544    window.addEventListener('testPassive', null, opts);
2545    window.removeEventListener('testPassive', null, opts);
2546  } catch (e) {}
2547
2548  var supportsPassive$1 = supportsPassive;
2549
2550  var START_EVENTS = ['touchstart', 'mousedown'];
2551  var MOVE_EVENTS = ['touchmove', 'mousemove'];
2552  var END_EVENTS = ['touchend', 'touchcancel', 'mouseup', 'mouseleave'];
2553  var MOUSE_EVENTS = ['mousedown', 'mousemove', 'mouseup', 'mouseleave'];
2554
2555  function Swipe (Glide, Components, Events) {
2556    /**
2557     * Instance of the binder for DOM Events.
2558     *
2559     * @type {EventsBinder}
2560     */
2561    var Binder = new EventsBinder();
2562
2563    var swipeSin = 0;
2564    var swipeStartX = 0;
2565    var swipeStartY = 0;
2566    var disabled = false;
2567    var capture = supportsPassive$1 ? { passive: true } : false;
2568
2569    var Swipe = {
2570      /**
2571       * Initializes swipe bindings.
2572       *
2573       * @return {Void}
2574       */
2575      mount: function mount() {
2576        this.bindSwipeStart();
2577      },
2578
2579
2580      /**
2581       * Handler for `swipestart` event. Calculates entry points of the user's tap.
2582       *
2583       * @param {Object} event
2584       * @return {Void}
2585       */
2586      start: function start(event) {
2587        if (!disabled && !Glide.disabled) {
2588          this.disable();
2589
2590          var swipe = this.touches(event);
2591
2592          swipeSin = null;
2593          swipeStartX = toInt(swipe.pageX);
2594          swipeStartY = toInt(swipe.pageY);
2595
2596          this.bindSwipeMove();
2597          this.bindSwipeEnd();
2598
2599          Events.emit('swipe.start');
2600        }
2601      },
2602
2603
2604      /**
2605       * Handler for `swipemove` event. Calculates user's tap angle and distance.
2606       *
2607       * @param {Object} event
2608       */
2609      move: function move(event) {
2610        if (!Glide.disabled) {
2611          var _Glide$settings = Glide.settings,
2612              touchAngle = _Glide$settings.touchAngle,
2613              touchRatio = _Glide$settings.touchRatio,
2614              classes = _Glide$settings.classes;
2615
2616
2617          var swipe = this.touches(event);
2618
2619          var subExSx = toInt(swipe.pageX) - swipeStartX;
2620          var subEySy = toInt(swipe.pageY) - swipeStartY;
2621          var powEX = Math.abs(subExSx << 2);
2622          var powEY = Math.abs(subEySy << 2);
2623          var swipeHypotenuse = Math.sqrt(powEX + powEY);
2624          var swipeCathetus = Math.sqrt(powEY);
2625
2626          swipeSin = Math.asin(swipeCathetus / swipeHypotenuse);
2627
2628          if (swipeSin * 180 / Math.PI < touchAngle) {
2629            event.stopPropagation();
2630
2631            Components.Move.make(subExSx * toFloat(touchRatio));
2632
2633            Components.Html.root.classList.add(classes.dragging);
2634
2635            Events.emit('swipe.move');
2636          } else {
2637            return false;
2638          }
2639        }
2640      },
2641
2642
2643      /**
2644       * Handler for `swipeend` event. Finitializes user's tap and decides about glide move.
2645       *
2646       * @param {Object} event
2647       * @return {Void}
2648       */
2649      end: function end(event) {
2650        if (!Glide.disabled) {
2651          var settings = Glide.settings;
2652
2653          var swipe = this.touches(event);
2654          var threshold = this.threshold(event);
2655
2656          var swipeDistance = swipe.pageX - swipeStartX;
2657          var swipeDeg = swipeSin * 180 / Math.PI;
2658          var steps = Math.round(swipeDistance / Components.Sizes.slideWidth);
2659
2660          this.enable();
2661
2662          if (swipeDistance > threshold && swipeDeg < settings.touchAngle) {
2663            // While swipe is positive and greater than threshold move backward.
2664            if (settings.perTouch) {
2665              steps = Math.min(steps, toInt(settings.perTouch));
2666            }
2667
2668            if (Components.Direction.is('rtl')) {
2669              steps = -steps;
2670            }
2671
2672            Components.Run.make(Components.Direction.resolve('<' + steps));
2673          } else if (swipeDistance < -threshold && swipeDeg < settings.touchAngle) {
2674            // While swipe is negative and lower than negative threshold move forward.
2675            if (settings.perTouch) {
2676              steps = Math.max(steps, -toInt(settings.perTouch));
2677            }
2678
2679            if (Components.Direction.is('rtl')) {
2680              steps = -steps;
2681            }
2682
2683            Components.Run.make(Components.Direction.resolve('>' + steps));
2684          } else {
2685            // While swipe don't reach distance apply previous transform.
2686            Components.Move.make();
2687          }
2688
2689          Components.Html.root.classList.remove(settings.classes.dragging);
2690
2691          this.unbindSwipeMove();
2692          this.unbindSwipeEnd();
2693
2694          Events.emit('swipe.end');
2695        }
2696      },
2697
2698
2699      /**
2700       * Binds swipe's starting event.
2701       *
2702       * @return {Void}
2703       */
2704      bindSwipeStart: function bindSwipeStart() {
2705        var _this = this;
2706
2707        var settings = Glide.settings;
2708
2709        if (settings.swipeThreshold) {
2710          Binder.on(START_EVENTS[0], Components.Html.wrapper, function (event) {
2711            _this.start(event);
2712          }, capture);
2713        }
2714
2715        if (settings.dragThreshold) {
2716          Binder.on(START_EVENTS[1], Components.Html.wrapper, function (event) {
2717            _this.start(event);
2718          }, capture);
2719        }
2720      },
2721
2722
2723      /**
2724       * Unbinds swipe's starting event.
2725       *
2726       * @return {Void}
2727       */
2728      unbindSwipeStart: function unbindSwipeStart() {
2729        Binder.off(START_EVENTS[0], Components.Html.wrapper, capture);
2730        Binder.off(START_EVENTS[1], Components.Html.wrapper, capture);
2731      },
2732
2733
2734      /**
2735       * Binds swipe's moving event.
2736       *
2737       * @return {Void}
2738       */
2739      bindSwipeMove: function bindSwipeMove() {
2740        var _this2 = this;
2741
2742        Binder.on(MOVE_EVENTS, Components.Html.wrapper, throttle(function (event) {
2743          _this2.move(event);
2744        }, Glide.settings.throttle), capture);
2745      },
2746
2747
2748      /**
2749       * Unbinds swipe's moving event.
2750       *
2751       * @return {Void}
2752       */
2753      unbindSwipeMove: function unbindSwipeMove() {
2754        Binder.off(MOVE_EVENTS, Components.Html.wrapper, capture);
2755      },
2756
2757
2758      /**
2759       * Binds swipe's ending event.
2760       *
2761       * @return {Void}
2762       */
2763      bindSwipeEnd: function bindSwipeEnd() {
2764        var _this3 = this;
2765
2766        Binder.on(END_EVENTS, Components.Html.wrapper, function (event) {
2767          _this3.end(event);
2768        });
2769      },
2770
2771
2772      /**
2773       * Unbinds swipe's ending event.
2774       *
2775       * @return {Void}
2776       */
2777      unbindSwipeEnd: function unbindSwipeEnd() {
2778        Binder.off(END_EVENTS, Components.Html.wrapper);
2779      },
2780
2781
2782      /**
2783       * Normalizes event touches points accorting to different types.
2784       *
2785       * @param {Object} event
2786       */
2787      touches: function touches(event) {
2788        if (MOUSE_EVENTS.indexOf(event.type) > -1) {
2789          return event;
2790        }
2791
2792        return event.touches[0] || event.changedTouches[0];
2793      },
2794
2795
2796      /**
2797       * Gets value of minimum swipe distance settings based on event type.
2798       *
2799       * @return {Number}
2800       */
2801      threshold: function threshold(event) {
2802        var settings = Glide.settings;
2803
2804        if (MOUSE_EVENTS.indexOf(event.type) > -1) {
2805          return settings.dragThreshold;
2806        }
2807
2808        return settings.swipeThreshold;
2809      },
2810
2811
2812      /**
2813       * Enables swipe event.
2814       *
2815       * @return {self}
2816       */
2817      enable: function enable() {
2818        disabled = false;
2819
2820        Components.Transition.enable();
2821
2822        return this;
2823      },
2824
2825
2826      /**
2827       * Disables swipe event.
2828       *
2829       * @return {self}
2830       */
2831      disable: function disable() {
2832        disabled = true;
2833
2834        Components.Transition.disable();
2835
2836        return this;
2837      }
2838    };
2839
2840    /**
2841     * Add component class:
2842     * - after initial building
2843     */
2844    Events.on('build.after', function () {
2845      Components.Html.root.classList.add(Glide.settings.classes.swipeable);
2846    });
2847
2848    /**
2849     * Remove swiping bindings:
2850     * - on destroying, to remove added EventListeners
2851     */
2852    Events.on('destroy', function () {
2853      Swipe.unbindSwipeStart();
2854      Swipe.unbindSwipeMove();
2855      Swipe.unbindSwipeEnd();
2856      Binder.destroy();
2857    });
2858
2859    return Swipe;
2860  }
2861
2862  function Images (Glide, Components, Events) {
2863    /**
2864     * Instance of the binder for DOM Events.
2865     *
2866     * @type {EventsBinder}
2867     */
2868    var Binder = new EventsBinder();
2869
2870    var Images = {
2871      /**
2872       * Binds listener to glide wrapper.
2873       *
2874       * @return {Void}
2875       */
2876      mount: function mount() {
2877        this.bind();
2878      },
2879
2880
2881      /**
2882       * Binds `dragstart` event on wrapper to prevent dragging images.
2883       *
2884       * @return {Void}
2885       */
2886      bind: function bind() {
2887        Binder.on('dragstart', Components.Html.wrapper, this.dragstart);
2888      },
2889
2890
2891      /**
2892       * Unbinds `dragstart` event on wrapper.
2893       *
2894       * @return {Void}
2895       */
2896      unbind: function unbind() {
2897        Binder.off('dragstart', Components.Html.wrapper);
2898      },
2899
2900
2901      /**
2902       * Event handler. Prevents dragging.
2903       *
2904       * @return {Void}
2905       */
2906      dragstart: function dragstart(event) {
2907        event.preventDefault();
2908      }
2909    };
2910
2911    /**
2912     * Remove bindings from images:
2913     * - on destroying, to remove added EventListeners
2914     */
2915    Events.on('destroy', function () {
2916      Images.unbind();
2917      Binder.destroy();
2918    });
2919
2920    return Images;
2921  }
2922
2923  function Anchors (Glide, Components, Events) {
2924    /**
2925     * Instance of the binder for DOM Events.
2926     *
2927     * @type {EventsBinder}
2928     */
2929    var Binder = new EventsBinder();
2930
2931    /**
2932     * Holds detaching status of anchors.
2933     * Prevents detaching of already detached anchors.
2934     *
2935     * @private
2936     * @type {Boolean}
2937     */
2938    var detached = false;
2939
2940    /**
2941     * Holds preventing status of anchors.
2942     * If `true` redirection after click will be disabled.
2943     *
2944     * @private
2945     * @type {Boolean}
2946     */
2947    var prevented = false;
2948
2949    var Anchors = {
2950      /**
2951       * Setups a initial state of anchors component.
2952       *
2953       * @returns {Void}
2954       */
2955      mount: function mount() {
2956        /**
2957         * Holds collection of anchors elements.
2958         *
2959         * @private
2960         * @type {HTMLCollection}
2961         */
2962        this._a = Components.Html.wrapper.querySelectorAll('a');
2963
2964        this.bind();
2965      },
2966
2967
2968      /**
2969       * Binds events to anchors inside a track.
2970       *
2971       * @return {Void}
2972       */
2973      bind: function bind() {
2974        Binder.on('click', Components.Html.wrapper, this.click);
2975      },
2976
2977
2978      /**
2979       * Unbinds events attached to anchors inside a track.
2980       *
2981       * @return {Void}
2982       */
2983      unbind: function unbind() {
2984        Binder.off('click', Components.Html.wrapper);
2985      },
2986
2987
2988      /**
2989       * Handler for click event. Prevents clicks when glide is in `prevent` status.
2990       *
2991       * @param  {Object} event
2992       * @return {Void}
2993       */
2994      click: function click(event) {
2995        if (prevented) {
2996          event.stopPropagation();
2997          event.preventDefault();
2998        }
2999      },
3000
3001
3002      /**
3003       * Detaches anchors click event inside glide.
3004       *
3005       * @return {self}
3006       */
3007      detach: function detach() {
3008        prevented = true;
3009
3010        if (!detached) {
3011          for (var i = 0; i < this.items.length; i++) {
3012            this.items[i].draggable = false;
3013
3014            this.items[i].setAttribute('data-href', this.items[i].getAttribute('href'));
3015
3016            this.items[i].removeAttribute('href');
3017          }
3018
3019          detached = true;
3020        }
3021
3022        return this;
3023      },
3024
3025
3026      /**
3027       * Attaches anchors click events inside glide.
3028       *
3029       * @return {self}
3030       */
3031      attach: function attach() {
3032        prevented = false;
3033
3034        if (detached) {
3035          for (var i = 0; i < this.items.length; i++) {
3036            this.items[i].draggable = true;
3037
3038            this.items[i].setAttribute('href', this.items[i].getAttribute('data-href'));
3039          }
3040
3041          detached = false;
3042        }
3043
3044        return this;
3045      }
3046    };
3047
3048    define(Anchors, 'items', {
3049      /**
3050       * Gets collection of the arrows HTML elements.
3051       *
3052       * @return {HTMLElement[]}
3053       */
3054      get: function get() {
3055        return Anchors._a;
3056      }
3057    });
3058
3059    /**
3060     * Detach anchors inside slides:
3061     * - on swiping, so they won't redirect to its `href` attributes
3062     */
3063    Events.on('swipe.move', function () {
3064      Anchors.detach();
3065    });
3066
3067    /**
3068     * Attach anchors inside slides:
3069     * - after swiping and transitions ends, so they can redirect after click again
3070     */
3071    Events.on('swipe.end', function () {
3072      Components.Transition.after(function () {
3073        Anchors.attach();
3074      });
3075    });
3076
3077    /**
3078     * Unbind anchors inside slides:
3079     * - on destroying, to bring anchors to its initial state
3080     */
3081    Events.on('destroy', function () {
3082      Anchors.attach();
3083      Anchors.unbind();
3084      Binder.destroy();
3085    });
3086
3087    return Anchors;
3088  }
3089
3090  var NAV_SELECTOR = '[data-glide-el="controls[nav]"]';
3091  var CONTROLS_SELECTOR = '[data-glide-el^="controls"]';
3092
3093  function Controls (Glide, Components, Events) {
3094    /**
3095     * Instance of the binder for DOM Events.
3096     *
3097     * @type {EventsBinder}
3098     */
3099    var Binder = new EventsBinder();
3100
3101    var capture = supportsPassive$1 ? { passive: true } : false;
3102
3103    var Controls = {
3104      /**
3105       * Inits arrows. Binds events listeners
3106       * to the arrows HTML elements.
3107       *
3108       * @return {Void}
3109       */
3110      mount: function mount() {
3111        /**
3112         * Collection of navigation HTML elements.
3113         *
3114         * @private
3115         * @type {HTMLCollection}
3116         */
3117        this._n = Components.Html.root.querySelectorAll(NAV_SELECTOR);
3118
3119        /**
3120         * Collection of controls HTML elements.
3121         *
3122         * @private
3123         * @type {HTMLCollection}
3124         */
3125        this._c = Components.Html.root.querySelectorAll(CONTROLS_SELECTOR);
3126
3127        this.addBindings();
3128      },
3129
3130
3131      /**
3132       * Sets active class to current slide.
3133       *
3134       * @return {Void}
3135       */
3136      setActive: function setActive() {
3137        for (var i = 0; i < this._n.length; i++) {
3138          this.addClass(this._n[i].children);
3139        }
3140      },
3141
3142
3143      /**
3144       * Removes active class to current slide.
3145       *
3146       * @return {Void}
3147       */
3148      removeActive: function removeActive() {
3149        for (var i = 0; i < this._n.length; i++) {
3150          this.removeClass(this._n[i].children);
3151        }
3152      },
3153
3154
3155      /**
3156       * Toggles active class on items inside navigation.
3157       *
3158       * @param  {HTMLElement} controls
3159       * @return {Void}
3160       */
3161      addClass: function addClass(controls) {
3162        var settings = Glide.settings;
3163        var item = controls[Glide.index];
3164
3165        if (item) {
3166          item.classList.add(settings.classes.activeNav);
3167
3168          siblings(item).forEach(function (sibling) {
3169            sibling.classList.remove(settings.classes.activeNav);
3170          });
3171        }
3172      },
3173
3174
3175      /**
3176       * Removes active class from active control.
3177       *
3178       * @param  {HTMLElement} controls
3179       * @return {Void}
3180       */
3181      removeClass: function removeClass(controls) {
3182        var item = controls[Glide.index];
3183
3184        if (item) {
3185          item.classList.remove(Glide.settings.classes.activeNav);
3186        }
3187      },
3188
3189
3190      /**
3191       * Adds handles to the each group of controls.
3192       *
3193       * @return {Void}
3194       */
3195      addBindings: function addBindings() {
3196        for (var i = 0; i < this._c.length; i++) {
3197          this.bind(this._c[i].children);
3198        }
3199      },
3200
3201
3202      /**
3203       * Removes handles from the each group of controls.
3204       *
3205       * @return {Void}
3206       */
3207      removeBindings: function removeBindings() {
3208        for (var i = 0; i < this._c.length; i++) {
3209          this.unbind(this._c[i].children);
3210        }
3211      },
3212
3213
3214      /**
3215       * Binds events to arrows HTML elements.
3216       *
3217       * @param {HTMLCollection} elements
3218       * @return {Void}
3219       */
3220      bind: function bind(elements) {
3221        for (var i = 0; i < elements.length; i++) {
3222          Binder.on('click', elements[i], this.click);
3223          Binder.on('touchstart', elements[i], this.click, capture);
3224        }
3225      },
3226
3227
3228      /**
3229       * Unbinds events binded to the arrows HTML elements.
3230       *
3231       * @param {HTMLCollection} elements
3232       * @return {Void}
3233       */
3234      unbind: function unbind(elements) {
3235        for (var i = 0; i < elements.length; i++) {
3236          Binder.off(['click', 'touchstart'], elements[i]);
3237        }
3238      },
3239
3240
3241      /**
3242       * Handles `click` event on the arrows HTML elements.
3243       * Moves slider in driection precised in
3244       * `data-glide-dir` attribute.
3245       *
3246       * @param {Object} event
3247       * @return {Void}
3248       */
3249      click: function click(event) {
3250        event.preventDefault();
3251
3252        Components.Run.make(Components.Direction.resolve(event.currentTarget.getAttribute('data-glide-dir')));
3253      }
3254    };
3255
3256    define(Controls, 'items', {
3257      /**
3258       * Gets collection of the controls HTML elements.
3259       *
3260       * @return {HTMLElement[]}
3261       */
3262      get: function get() {
3263        return Controls._c;
3264      }
3265    });
3266
3267    /**
3268     * Swap active class of current navigation item:
3269     * - after mounting to set it to initial index
3270     * - after each move to the new index
3271     */
3272    Events.on(['mount.after', 'move.after'], function () {
3273      Controls.setActive();
3274    });
3275
3276    /**
3277     * Remove bindings and HTML Classes:
3278     * - on destroying, to bring markup to its initial state
3279     */
3280    Events.on('destroy', function () {
3281      Controls.removeBindings();
3282      Controls.removeActive();
3283      Binder.destroy();
3284    });
3285
3286    return Controls;
3287  }
3288
3289  function Keyboard (Glide, Components, Events) {
3290    /**
3291     * Instance of the binder for DOM Events.
3292     *
3293     * @type {EventsBinder}
3294     */
3295    var Binder = new EventsBinder();
3296
3297    var Keyboard = {
3298      /**
3299       * Binds keyboard events on component mount.
3300       *
3301       * @return {Void}
3302       */
3303      mount: function mount() {
3304        if (Glide.settings.keyboard) {
3305          this.bind();
3306        }
3307      },
3308
3309
3310      /**
3311       * Adds keyboard press events.
3312       *
3313       * @return {Void}
3314       */
3315      bind: function bind() {
3316        Binder.on('keyup', document, this.press);
3317      },
3318
3319
3320      /**
3321       * Removes keyboard press events.
3322       *
3323       * @return {Void}
3324       */
3325      unbind: function unbind() {
3326        Binder.off('keyup', document);
3327      },
3328
3329
3330      /**
3331       * Handles keyboard's arrows press and moving glide foward and backward.
3332       *
3333       * @param  {Object} event
3334       * @return {Void}
3335       */
3336      press: function press(event) {
3337        if (event.keyCode === 39) {
3338          Components.Run.make(Components.Direction.resolve('>'));
3339        }
3340
3341        if (event.keyCode === 37) {
3342          Components.Run.make(Components.Direction.resolve('<'));
3343        }
3344      }
3345    };
3346
3347    /**
3348     * Remove bindings from keyboard:
3349     * - on destroying to remove added events
3350     * - on updating to remove events before remounting
3351     */
3352    Events.on(['destroy', 'update'], function () {
3353      Keyboard.unbind();
3354    });
3355
3356    /**
3357     * Remount component
3358     * - on updating to reflect potential changes in settings
3359     */
3360    Events.on('update', function () {
3361      Keyboard.mount();
3362    });
3363
3364    /**
3365     * Destroy binder:
3366     * - on destroying to remove listeners
3367     */
3368    Events.on('destroy', function () {
3369      Binder.destroy();
3370    });
3371
3372    return Keyboard;
3373  }
3374
3375  function Autoplay (Glide, Components, Events) {
3376    /**
3377     * Instance of the binder for DOM Events.
3378     *
3379     * @type {EventsBinder}
3380     */
3381    var Binder = new EventsBinder();
3382
3383    var Autoplay = {
3384      /**
3385       * Initializes autoplaying and events.
3386       *
3387       * @return {Void}
3388       */
3389      mount: function mount() {
3390        this.start();
3391
3392        if (Glide.settings.hoverpause) {
3393          this.bind();
3394        }
3395      },
3396
3397
3398      /**
3399       * Starts autoplaying in configured interval.
3400       *
3401       * @param {Boolean|Number} force Run autoplaying with passed interval regardless of `autoplay` settings
3402       * @return {Void}
3403       */
3404      start: function start() {
3405        var _this = this;
3406
3407        if (Glide.settings.autoplay) {
3408          if (isUndefined(this._i)) {
3409            this._i = setInterval(function () {
3410              _this.stop();
3411
3412              Components.Run.make('>');
3413
3414              _this.start();
3415            }, this.time);
3416          }
3417        }
3418      },
3419
3420
3421      /**
3422       * Stops autorunning of the glide.
3423       *
3424       * @return {Void}
3425       */
3426      stop: function stop() {
3427        this._i = clearInterval(this._i);
3428      },
3429
3430
3431      /**
3432       * Stops autoplaying while mouse is over glide's area.
3433       *
3434       * @return {Void}
3435       */
3436      bind: function bind() {
3437        var _this2 = this;
3438
3439        Binder.on('mouseover', Components.Html.root, function () {
3440          _this2.stop();
3441        });
3442
3443        Binder.on('mouseout', Components.Html.root, function () {
3444          _this2.start();
3445        });
3446      },
3447
3448
3449      /**
3450       * Unbind mouseover events.
3451       *
3452       * @returns {Void}
3453       */
3454      unbind: function unbind() {
3455        Binder.off(['mouseover', 'mouseout'], Components.Html.root);
3456      }
3457    };
3458
3459    define(Autoplay, 'time', {
3460      /**
3461       * Gets time period value for the autoplay interval. Prioritizes
3462       * times in `data-glide-autoplay` attrubutes over options.
3463       *
3464       * @return {Number}
3465       */
3466      get: function get() {
3467        var autoplay = Components.Html.slides[Glide.index].getAttribute('data-glide-autoplay');
3468
3469        if (autoplay) {
3470          return toInt(autoplay);
3471        }
3472
3473        return toInt(Glide.settings.autoplay);
3474      }
3475    });
3476
3477    /**
3478     * Stop autoplaying and unbind events:
3479     * - on destroying, to clear defined interval
3480     * - on updating via API to reset interval that may changed
3481     */
3482    Events.on(['destroy', 'update'], function () {
3483      Autoplay.unbind();
3484    });
3485
3486    /**
3487     * Stop autoplaying:
3488     * - before each run, to restart autoplaying
3489     * - on pausing via API
3490     * - on destroying, to clear defined interval
3491     * - while starting a swipe
3492     * - on updating via API to reset interval that may changed
3493     */
3494    Events.on(['run.before', 'pause', 'destroy', 'swipe.start', 'update'], function () {
3495      Autoplay.stop();
3496    });
3497
3498    /**
3499     * Start autoplaying:
3500     * - after each run, to restart autoplaying
3501     * - on playing via API
3502     * - while ending a swipe
3503     */
3504    Events.on(['run.after', 'play', 'swipe.end'], function () {
3505      Autoplay.start();
3506    });
3507
3508    /**
3509     * Remount autoplaying:
3510     * - on updating via API to reset interval that may changed
3511     */
3512    Events.on('update', function () {
3513      Autoplay.mount();
3514    });
3515
3516    /**
3517     * Destroy a binder:
3518     * - on destroying glide instance to clearup listeners
3519     */
3520    Events.on('destroy', function () {
3521      Binder.destroy();
3522    });
3523
3524    return Autoplay;
3525  }
3526
3527  /**
3528   * Sorts keys of breakpoint object so they will be ordered from lower to bigger.
3529   *
3530   * @param {Object} points
3531   * @returns {Object}
3532   */
3533  function sortBreakpoints(points) {
3534    if (isObject(points)) {
3535      return sortKeys(points);
3536    } else {
3537      warn('Breakpoints option must be an object');
3538    }
3539
3540    return {};
3541  }
3542
3543  function Breakpoints (Glide, Components, Events) {
3544    /**
3545     * Instance of the binder for DOM Events.
3546     *
3547     * @type {EventsBinder}
3548     */
3549    var Binder = new EventsBinder();
3550
3551    /**
3552     * Holds reference to settings.
3553     *
3554     * @type {Object}
3555     */
3556    var settings = Glide.settings;
3557
3558    /**
3559     * Holds reference to breakpoints object in settings. Sorts breakpoints
3560     * from smaller to larger. It is required in order to proper
3561     * matching currently active breakpoint settings.
3562     *
3563     * @type {Object}
3564     */
3565    var points = sortBreakpoints(settings.breakpoints);
3566
3567    /**
3568     * Cache initial settings before overwritting.
3569     *
3570     * @type {Object}
3571     */
3572    var defaults = _extends({}, settings);
3573
3574    var Breakpoints = {
3575      /**
3576       * Matches settings for currectly matching media breakpoint.
3577       *
3578       * @param {Object} points
3579       * @returns {Object}
3580       */
3581      match: function match(points) {
3582        if (typeof window.matchMedia !== 'undefined') {
3583          for (var point in points) {
3584            if (points.hasOwnProperty(point)) {
3585              if (window.matchMedia('(max-width: ' + point + 'px)').matches) {
3586                return points[point];
3587              }
3588            }
3589          }
3590        }
3591
3592        return defaults;
3593      }
3594    };
3595
3596    /**
3597     * Overwrite instance settings with currently matching breakpoint settings.
3598     * This happens right after component initialization.
3599     */
3600    _extends(settings, Breakpoints.match(points));
3601
3602    /**
3603     * Update glide with settings of matched brekpoint:
3604     * - window resize to update slider
3605     */
3606    Binder.on('resize', window, throttle(function () {
3607      Glide.settings = mergeOptions(settings, Breakpoints.match(points));
3608    }, Glide.settings.throttle));
3609
3610    /**
3611     * Resort and update default settings:
3612     * - on reinit via API, so breakpoint matching will be performed with options
3613     */
3614    Events.on('update', function () {
3615      points = sortBreakpoints(points);
3616
3617      defaults = _extends({}, settings);
3618    });
3619
3620    /**
3621     * Unbind resize listener:
3622     * - on destroying, to bring markup to its initial state
3623     */
3624    Events.on('destroy', function () {
3625      Binder.off('resize', window);
3626    });
3627
3628    return Breakpoints;
3629  }
3630
3631  var COMPONENTS = {
3632    // Required
3633    Html: Html,
3634    Translate: Translate,
3635    Transition: Transition,
3636    Direction: Direction,
3637    Peek: Peek,
3638    Sizes: Sizes,
3639    Gaps: Gaps,
3640    Move: Move,
3641    Clones: Clones,
3642    Resize: Resize,
3643    Build: Build,
3644    Run: Run,
3645
3646    // Optional
3647    Swipe: Swipe,
3648    Images: Images,
3649    Anchors: Anchors,
3650    Controls: Controls,
3651    Keyboard: Keyboard,
3652    Autoplay: Autoplay,
3653    Breakpoints: Breakpoints
3654  };
3655
3656  var Glide$1 = function (_Core) {
3657    inherits(Glide$$1, _Core);
3658
3659    function Glide$$1() {
3660      classCallCheck(this, Glide$$1);
3661      return possibleConstructorReturn(this, (Glide$$1.__proto__ || Object.getPrototypeOf(Glide$$1)).apply(this, arguments));
3662    }
3663
3664    createClass(Glide$$1, [{
3665      key: 'mount',
3666      value: function mount() {
3667        var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3668
3669        return get(Glide$$1.prototype.__proto__ || Object.getPrototypeOf(Glide$$1.prototype), 'mount', this).call(this, _extends({}, COMPONENTS, extensions));
3670      }
3671    }]);
3672    return Glide$$1;
3673  }(Glide);
3674
3675  return Glide$1;
3676
3677})));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.