PageSourceSearch

https://summitroadsociety.org.nz/public/js/contentbox56/assets/scripts/glide/glide.js

js summitroadsociety.org.nz collected 2026-10-06 19:00:47 UTC 86,534 bytes, 3,676 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,631 bytes, lines 1071-3531
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      return true;
1295    }
1296
1297    return false;
1298  }
1299
1300  var TRACK_SELECTOR = '[data-glide-el="track"]';
1301
1302  function Html (Glide, Components) {
1303    var Html = {
1304      /**
1305       * Setup slider HTML nodes.
1306       *
1307       * @param {Glide} glide
1308       */
1309      mount: function mount() {
1310        this.root = Glide.selector;
1311        this.track = this.root.querySelector(TRACK_SELECTOR);
1312        this.slides = Array.prototype.slice.call(this.wrapper.children).filter(function (slide) {
1313          return !slide.classList.contains(Glide.settings.classes.cloneSlide);
1314        });
1315      }
1316    };
1317
1318    define(Html, 'root', {
1319      /**
1320       * Gets node of the glide main element.
1321       *
1322       * @return {Object}
1323       */
1324      get: function get() {
1325        return Html._r;
1326      },
1327
1328
1329      /**
1330       * Sets node of the glide main element.
1331       *
1332       * @return {Object}
1333       */
1334      set: function set(r) {
1335        if (isString(r)) {
1336          r = document.querySelector(r);
1337        }
1338
1339        if (exist(r)) {
1340          Html._r = r;
1341        } else {
1342          warn('Root element must be a existing Html node');
1343        }
1344      }
1345    });
1346
1347    define(Html, 'track', {
1348      /**
1349       * Gets node of the glide track with slides.
1350       *
1351       * @return {Object}
1352       */
1353      get: function get() {
1354        return Html._t;
1355      },
1356
1357
1358      /**
1359       * Sets node of the glide track with slides.
1360       *
1361       * @return {Object}
1362       */
1363      set: function set(t) {
1364        if (exist(t)) {
1365          Html._t = t;
1366        } else {
1367          warn('Could not find track element. Please use ' + TRACK_SELECTOR + ' attribute.');
1368        }
1369      }
1370    });
1371
1372    define(Html, 'wrapper', {
1373      /**
1374       * Gets node of the slides wrapper.
1375       *
1376       * @return {Object}
1377       */
1378      get: function get() {
1379        return Html.track.children[0];
1380      }
1381    });
1382
1383    return Html;
1384  }
1385
1386  function Peek (Glide, Components, Events) {
1387    var Peek = {
1388      /**
1389       * Setups how much to peek based on settings.
1390       *
1391       * @return {Void}
1392       */
1393      mount: function mount() {
1394        this.value = Glide.settings.peek;
1395      }
1396    };
1397
1398    define(Peek, 'value', {
1399      /**
1400       * Gets value of the peek.
1401       *
1402       * @returns {Number|Object}
1403       */
1404      get: function get() {
1405        return Peek._v;
1406      },
1407
1408
1409      /**
1410       * Sets value of the peek.
1411       *
1412       * @param {Number|Object} value
1413       * @return {Void}
1414       */
1415      set: function set(value) {
1416        if (isObject(value)) {
1417          value.before = toInt(value.before);
1418          value.after = toInt(value.after);
1419        } else {
1420          value = toInt(value);
1421        }
1422
1423        Peek._v = value;
1424      }
1425    });
1426
1427    define(Peek, 'reductor', {
1428      /**
1429       * Gets reduction value caused by peek.
1430       *
1431       * @returns {Number}
1432       */
1433      get: function get() {
1434        var value = Peek.value;
1435        var perView = Glide.settings.perView;
1436
1437        if (isObject(value)) {
1438          return value.before / perView + value.after / perView;
1439        }
1440
1441        return value * 2 / perView;
1442      }
1443    });
1444
1445    /**
1446     * Recalculate peeking sizes on:
1447     * - when resizing window to update to proper percents
1448     */
1449    Events.on(['resize', 'update'], function () {
1450      Peek.mount();
1451    });
1452
1453    return Peek;
1454  }
1455
1456  function Move (Glide, Components, Events) {
1457    var Move = {
1458      /**
1459       * Constructs move component.
1460       *
1461       * @returns {Void}
1462       */
1463      mount: function mount() {
1464        this._o = 0;
1465      },
1466
1467
1468      /**
1469       * Calculates a movement value based on passed offset and currently active index.
1470       *
1471       * @param  {Number} offset
1472       * @return {Void}
1473       */
1474      make: function make() {
1475        var _this = this;
1476
1477        var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
1478
1479        this.offset = offset;
1480
1481        Events.emit('move', {
1482          movement: this.value
1483        });
1484
1485        Components.Transition.after(function () {
1486          Events.emit('move.after', {
1487            movement: _this.value
1488          });
1489        });
1490      }
1491    };
1492
1493    define(Move, 'offset', {
1494      /**
1495       * Gets an offset value used to modify current translate.
1496       *
1497       * @return {Object}
1498       */
1499      get: function get() {
1500        return Move._o;
1501      },
1502
1503
1504      /**
1505       * Sets an offset value used to modify current translate.
1506       *
1507       * @return {Object}
1508       */
1509      set: function set(value) {
1510        Move._o = !isUndefined(value) ? toInt(value) : 0;
1511      }
1512    });
1513
1514    define(Move, 'translate', {
1515      /**
1516       * Gets a raw movement value.
1517       *
1518       * @return {Number}
1519       */
1520      get: function get() {
1521        return Components.Sizes.slideWidth * Glide.index;
1522      }
1523    });
1524
1525    define(Move, 'value', {
1526      /**
1527       * Gets an actual movement value corrected by offset.
1528       *
1529       * @return {Number}
1530       */
1531      get: function get() {
1532        var offset = this.offset;
1533        var translate = this.translate;
1534
1535        if (Components.Direction.is('rtl')) {
1536          return translate + offset;
1537        }
1538
1539        return translate - offset;
1540      }
1541    });
1542
1543    /**
1544     * Make movement to proper slide on:
1545     * - before build, so glide will start at `startAt` index
1546     * - on each standard run to move to newly calculated index
1547     */
1548    Events.on(['build.before', 'run'], function () {
1549      Move.make();
1550    });
1551
1552    return Move;
1553  }
1554
1555  function Sizes (Glide, Components, Events) {
1556    var Sizes = {
1557      /**
1558       * Setups dimentions of slides.
1559       *
1560       * @return {Void}
1561       */
1562      setupSlides: function setupSlides() {
1563        var width = this.slideWidth + 'px';
1564        var slides = Components.Html.slides;
1565
1566        for (var i = 0; i < slides.length; i++) {
1567          slides[i].style.width = width;
1568        }
1569      },
1570
1571
1572      /**
1573       * Setups dimentions of slides wrapper.
1574       *
1575       * @return {Void}
1576       */
1577      setupWrapper: function setupWrapper(dimention) {
1578        Components.Html.wrapper.style.width = this.wrapperSize + 'px';
1579      },
1580
1581
1582      /**
1583       * Removes applied styles from HTML elements.
1584       *
1585       * @returns {Void}
1586       */
1587      remove: function remove() {
1588        var slides = Components.Html.slides;
1589
1590        for (var i = 0; i < slides.length; i++) {
1591          slides[i].style.width = '';
1592        }
1593
1594        Components.Html.wrapper.style.width = '';
1595      }
1596    };
1597
1598    define(Sizes, 'length', {
1599      /**
1600       * Gets count number of the slides.
1601       *
1602       * @return {Number}
1603       */
1604      get: function get() {
1605        return Components.Html.slides.length;
1606      }
1607    });
1608
1609    define(Sizes, 'width', {
1610      /**
1611       * Gets width value of the glide.
1612       *
1613       * @return {Number}
1614       */
1615      get: function get() {
1616        return Components.Html.root.offsetWidth;
1617      }
1618    });
1619
1620    define(Sizes, 'wrapperSize', {
1621      /**
1622       * Gets size of the slides wrapper.
1623       *
1624       * @return {Number}
1625       */
1626      get: function get() {
1627        return Sizes.slideWidth * Sizes.length + Components.Gaps.grow + Components.Clones.grow;
1628      }
1629    });
1630
1631    define(Sizes, 'slideWidth', {
1632      /**
1633       * Gets width value of the single slide.
1634       *
1635       * @return {Number}
1636       */
1637      get: function get() {
1638        return Sizes.width / Glide.settings.perView - Components.Peek.reductor - Components.Gaps.reductor;
1639      }
1640    });
1641
1642    /**
1643     * Apply calculated glide's dimensions:
1644     * - before building, so other dimentions (e.g. translate) will be calculated propertly
1645     * - when resizing window to recalculate sildes dimensions
1646     * - on updating via API, to calculate dimensions based on new options
1647     */
1648    Events.on(['build.before', 'resize', 'update'], function () {
1649      Sizes.setupSlides();
1650      Sizes.setupWrapper();
1651    });
1652
1653    /**
1654     * Remove calculated glide's dimensions:
1655     * - on destoting to bring markup to its inital state
1656     */
1657    Events.on('destroy', function () {
1658      Sizes.remove();
1659    });
1660
1661    return Sizes;
1662  }
1663
1664  function Build (Glide, Components, Events) {
1665    var Build = {
1666      /**
1667       * Init glide building. Adds classes, sets
1668       * dimensions and setups initial state.
1669       *
1670       * @return {Void}
1671       */
1672      mount: function mount() {
1673        Events.emit('build.before');
1674
1675        this.typeClass();
1676        this.activeClass();
1677
1678        Events.emit('build.after');
1679      },
1680
1681
1682      /**
1683       * Adds `type` class to the glide element.
1684       *
1685       * @return {Void}
1686       */
1687      typeClass: function typeClass() {
1688        Components.Html.root.classList.add(Glide.settings.classes[Glide.settings.type]);
1689      },
1690
1691
1692      /**
1693       * Sets active class to current slide.
1694       *
1695       * @return {Void}
1696       */
1697      activeClass: function activeClass() {
1698        var classes = Glide.settings.classes;
1699        var slide = Components.Html.slides[Glide.index];
1700
1701        if (slide) {
1702          slide.classList.add(classes.activeSlide);
1703
1704          siblings(slide).forEach(function (sibling) {
1705            sibling.classList.remove(classes.activeSlide);
1706          });
1707        }
1708      },
1709
1710
1711      /**
1712       * Removes HTML classes applied at building.
1713       *
1714       * @return {Void}
1715       */
1716      removeClasses: function removeClasses() {
1717        var classes = Glide.settings.classes;
1718
1719        Components.Html.root.classList.remove(classes[Glide.settings.type]);
1720
1721        Components.Html.slides.forEach(function (sibling) {
1722          sibling.classList.remove(classes.activeSlide);
1723        });
1724      }
1725    };
1726
1727    /**
1728     * Clear building classes:
1729     * - on destroying to bring HTML to its initial state
1730     * - on updating to remove classes before remounting component
1731     */
1732    Events.on(['destroy', 'update'], function () {
1733      Build.removeClasses();
1734    });
1735
1736    /**
1737     * Remount component:
1738     * - on resizing of the window to calculate new dimentions
1739     * - on updating settings via API
1740     */
1741    Events.on(['resize', 'update'], function () {
1742      Build.mount();
1743    });
1744
1745    /**
1746     * Swap active class of current slide:
1747     * - after each move to the new index
1748     */
1749    Events.on('move.after', function () {
1750      Build.activeClass();
1751    });
1752
1753    return Build;
1754  }
1755
1756  function Clones (Glide, Components, Events) {
1757    var Clones = {
1758      /**
1759       * Create pattern map and collect slides to be cloned.
1760       */
1761      mount: function mount() {
1762        this.items = [];
1763
1764        if (Glide.isType('carousel')) {
1765          this.items = this.collect();
1766        }
1767      },
1768
1769
1770      /**
1771       * Collect clones with pattern.
1772       *
1773       * @return {Void}
1774       */
1775      collect: function collect() {
1776        var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1777        var slides = Components.Html.slides;
1778        var _Glide$settings = Glide.settings,
1779            perView = _Glide$settings.perView,
1780            classes = _Glide$settings.classes;
1781
1782
1783        var peekIncrementer = +!!Glide.settings.peek;
1784        var part = perView + peekIncrementer;
1785        var start = slides.slice(0, part);
1786        var end = slides.slice(-part);
1787
1788        for (var r = 0; r < Math.max(1, Math.floor(perView / slides.length)); r++) {
1789          for (var i = 0; i < start.length; i++) {
1790            var clone = start[i].cloneNode(true);
1791
1792            clone.classList.add(classes.cloneSlide);
1793
1794            items.push(clone);
1795          }
1796
1797          for (var _i = 0; _i < end.length; _i++) {
1798            var _clone = end[_i].cloneNode(true);
1799
1800            _clone.classList.add(classes.cloneSlide);
1801
1802            items.unshift(_clone);
1803          }
1804        }
1805
1806        return items;
1807      },
1808
1809
1810      /**
1811       * Append cloned slides with generated pattern.
1812       *
1813       * @return {Void}
1814       */
1815      append: function append() {
1816        var items = this.items;
1817        var _Components$Html = Components.Html,
1818            wrapper = _Components$Html.wrapper,
1819            slides = _Components$Html.slides;
1820
1821
1822        var half = Math.floor(items.length / 2);
1823        var prepend = items.slice(0, half).reverse();
1824        var append = items.slice(half, items.length);
1825        var width = Components.Sizes.slideWidth + 'px';
1826
1827        for (var i = 0; i < append.length; i++) {
1828          wrapper.appendChild(append[i]);
1829        }
1830
1831        for (var _i2 = 0; _i2 < prepend.length; _i2++) {
1832          wrapper.insertBefore(prepend[_i2], slides[0]);
1833        }
1834
1835        for (var _i3 = 0; _i3 < items.length; _i3++) {
1836          items[_i3].style.width = width;
1837        }
1838      },
1839
1840
1841      /**
1842       * Remove all cloned slides.
1843       *
1844       * @return {Void}
1845       */
1846      remove: function remove() {
1847        var items = this.items;
1848
1849
1850        for (var i = 0; i < items.length; i++) {
1851          Components.Html.wrapper.removeChild(items[i]);
1852        }
1853      }
1854    };
1855
1856    define(Clones, 'grow', {
1857      /**
1858       * Gets additional dimentions value caused by clones.
1859       *
1860       * @return {Number}
1861       */
1862      get: function get() {
1863        return (Components.Sizes.slideWidth + Components.Gaps.value) * Clones.items.length;
1864      }
1865    });
1866
1867    /**
1868     * Append additional slide's clones:
1869     * - while glide's type is `carousel`
1870     */
1871    Events.on('update', function () {
1872      Clones.remove();
1873      Clones.mount();
1874      Clones.append();
1875    });
1876
1877    /**
1878     * Append additional slide's clones:
1879     * - while glide's type is `carousel`
1880     */
1881    Events.on('build.before', function () {
1882      if (Glide.isType('carousel')) {
1883        Clones.append();
1884      }
1885    });
1886
1887    /**
1888     * Remove clones HTMLElements:
1889     * - on destroying, to bring HTML to its initial state
1890     */
1891    Events.on('destroy', function () {
1892      Clones.remove();
1893    });
1894
1895    return Clones;
1896  }
1897
1898  var EventsBinder = function () {
1899    /**
1900     * Construct a EventsBinder instance.
1901     */
1902    function EventsBinder() {
1903      var listeners = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1904      classCallCheck(this, EventsBinder);
1905
1906      this.listeners = listeners;
1907    }
1908
1909    /**
1910     * Adds events listeners to arrows HTML elements.
1911     *
1912     * @param  {String|Array} events
1913     * @param  {Element|Window|Document} el
1914     * @param  {Function} closure
1915     * @param  {Boolean|Object} capture
1916     * @return {Void}
1917     */
1918
1919
1920    createClass(EventsBinder, [{
1921      key: 'on',
1922      value: function on(events, el, closure) {
1923        var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
1924
1925        if (isString(events)) {
1926          events = [events];
1927        }
1928
1929        for (var i = 0; i < events.length; i++) {
1930          this.listeners[events[i]] = closure;
1931
1932          el.addEventListener(events[i], this.listeners[events[i]], capture);
1933        }
1934      }
1935
1936      /**
1937       * Removes event listeners from arrows HTML elements.
1938       *
1939       * @param  {String|Array} events
1940       * @param  {Element|Window|Document} el
1941       * @param  {Boolean|Object} capture
1942       * @return {Void}
1943       */
1944
1945    }, {
1946      key: 'off',
1947      value: function off(events, el) {
1948        var capture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1949
1950        if (isString(events)) {
1951          events = [events];
1952        }
1953
1954        for (var i = 0; i < events.length; i++) {
1955          el.removeEventListener(events[i], this.listeners[events[i]], capture);
1956        }
1957      }
1958
1959      /**
1960       * Destroy collected listeners.
1961       *
1962       * @returns {Void}
1963       */
1964
1965    }, {
1966      key: 'destroy',
1967      value: function destroy() {
1968        delete this.listeners;
1969      }
1970    }]);
1971    return EventsBinder;
1972  }();
1973
1974  function Resize (Glide, Components, Events) {
1975    /**
1976     * Instance of the binder for DOM Events.
1977     *
1978     * @type {EventsBinder}
1979     */
1980    var Binder = new EventsBinder();
1981
1982    var Resize = {
1983      /**
1984       * Initializes window bindings.
1985       */
1986      mount: function mount() {
1987        this.bind();
1988      },
1989
1990
1991      /**
1992       * Binds `rezsize` listener to the window.
1993       * It's a costly event, so we are debouncing it.
1994       *
1995       * @return {Void}
1996       */
1997      bind: function bind() {
1998        Binder.on('resize', window, throttle(function () {
1999          Events.emit('resize');
2000        }, Glide.settings.throttle));
2001      },
2002
2003
2004      /**
2005       * Unbinds listeners from the window.
2006       *
2007       * @return {Void}
2008       */
2009      unbind: function unbind() {
2010        Binder.off('resize', window);
2011      }
2012    };
2013
2014    /**
2015     * Remove bindings from window:
2016     * - on destroying, to remove added EventListener
2017     */
2018    Events.on('destroy', function () {
2019      Resize.unbind();
2020      Binder.destroy();
2021    });
2022
2023    return Resize;
2024  }
2025
2026  var VALID_DIRECTIONS = ['ltr', 'rtl'];
2027  var FLIPED_MOVEMENTS = {
2028    '>': '<',
2029    '<': '>',
2030    '=': '='
2031  };
2032
2033  function Direction (Glide, Components, Events) {
2034    var Direction = {
2035      /**
2036       * Setups gap value based on settings.
2037       *
2038       * @return {Void}
2039       */
2040      mount: function mount() {
2041        this.value = Glide.settings.direction;
2042      },
2043
2044
2045      /**
2046       * Resolves pattern based on direction value
2047       *
2048       * @param {String} pattern
2049       * @returns {String}
2050       */
2051      resolve: function resolve(pattern) {
2052        var token = pattern.slice(0, 1);
2053
2054        if (this.is('rtl')) {
2055          return pattern.split(token).join(FLIPED_MOVEMENTS[token]);
2056        }
2057
2058        return pattern;
2059      },
2060
2061
2062      /**
2063       * Checks value of direction mode.
2064       *
2065       * @param {String} direction
2066       * @returns {Boolean}
2067       */
2068      is: function is(direction) {
2069        return this.value === direction;
2070      },
2071
2072
2073      /**
2074       * Applies direction class to the root HTML element.
2075       *
2076       * @return {Void}
2077       */
2078      addClass: function addClass() {
2079        Components.Html.root.classList.add(Glide.settings.classes.direction[this.value]);
2080      },
2081
2082
2083      /**
2084       * Removes direction class from the root HTML element.
2085       *
2086       * @return {Void}
2087       */
2088      removeClass: function removeClass() {
2089        Components.Html.root.classList.remove(Glide.settings.classes.direction[this.value]);
2090      }
2091    };
2092
2093    define(Direction, 'value', {
2094      /**
2095       * Gets value of the direction.
2096       *
2097       * @returns {Number}
2098       */
2099      get: function get() {
2100        return Direction._v;
2101      },
2102
2103
2104      /**
2105       * Sets value of the direction.
2106       *
2107       * @param {String} value
2108       * @return {Void}
2109       */
2110      set: function set(value) {
2111        if (VALID_DIRECTIONS.indexOf(value) > -1) {
2112          Direction._v = value;
2113        } else {
2114          warn('Direction value must be `ltr` or `rtl`');
2115        }
2116      }
2117    });
2118
2119    /**
2120     * Clear direction class:
2121     * - on destroy to bring HTML to its initial state
2122     * - on update to remove class before reappling bellow
2123     */
2124    Events.on(['destroy', 'update'], function () {
2125      Direction.removeClass();
2126    });
2127
2128    /**
2129     * Remount component:
2130     * - on update to reflect changes in direction value
2131     */
2132    Events.on('update', function () {
2133      Direction.mount();
2134    });
2135
2136    /**
2137     * Apply direction class:
2138     * - before building to apply class for the first time
2139     * - on updating to reapply direction class that may changed
2140     */
2141    Events.on(['build.before', 'update'], function () {
2142      Direction.addClass();
2143    });
2144
2145    return Direction;
2146  }
2147
2148  /**
2149   * Reflects value of glide movement.
2150   *
2151   * @param  {Object} Glide
2152   * @param  {Object} Components
2153   * @return {Object}
2154   */
2155  function Rtl (Glide, Components) {
2156    return {
2157      /**
2158       * Negates the passed translate if glide is in RTL option.
2159       *
2160       * @param  {Number} translate
2161       * @return {Number}
2162       */
2163      modify: function modify(translate) {
2164        if (Components.Direction.is('rtl')) {
2165          return -translate;
2166        }
2167
2168        return translate;
2169      }
2170    };
2171  }
2172
2173  /**
2174   * Updates glide movement with a `gap` settings.
2175   *
2176   * @param  {Object} Glide
2177   * @param  {Object} Components
2178   * @return {Object}
2179   */
2180  function Gap (Glide, Components) {
2181    return {
2182      /**
2183       * Modifies passed translate value with number in the `gap` settings.
2184       *
2185       * @param  {Number} translate
2186       * @return {Number}
2187       */
2188      modify: function modify(translate) {
2189        return translate + Components.Gaps.value * Glide.index;
2190      }
2191    };
2192  }
2193
2194  /**
2195   * Updates glide movement with width of additional clones width.
2196   *
2197   * @param  {Object} Glide
2198   * @param  {Object} Components
2199   * @return {Object}
2200   */
2201  function Grow (Glide, Components) {
2202    return {
2203      /**
2204       * Adds to the passed translate width of the half of clones.
2205       *
2206       * @param  {Number} translate
2207       * @return {Number}
2208       */
2209      modify: function modify(translate) {
2210        return translate + Components.Clones.grow / 2;
2211      }
2212    };
2213  }
2214
2215  /**
2216   * Updates glide movement with a `peek` settings.
2217   *
2218   * @param  {Object} Glide
2219   * @param  {Object} Components
2220   * @return {Object}
2221   */
2222  function Peeking (Glide, Components) {
2223    return {
2224      /**
2225       * Modifies passed translate value with a `peek` setting.
2226       *
2227       * @param  {Number} translate
2228       * @return {Number}
2229       */
2230      modify: function modify(translate) {
2231        if (Glide.settings.focusAt >= 0) {
2232          var peek = Components.Peek.value;
2233
2234          if (isObject(peek)) {
2235            return translate - peek.before;
2236          }
2237
2238          return translate - peek;
2239        }
2240
2241        return translate;
2242      }
2243    };
2244  }
2245
2246  /**
2247   * Updates glide movement with a `focusAt` settings.
2248   *
2249   * @param  {Object} Glide
2250   * @param  {Object} Components
2251   * @return {Object}
2252   */
2253  function Focusing (Glide, Components) {
2254    return {
2255      /**
2256       * Modifies passed translate value with index in the `focusAt` setting.
2257       *
2258       * @param  {Number} translate
2259       * @return {Number}
2260       */
2261      modify: function modify(translate) {
2262        var gap = Components.Gaps.value;
2263        var width = Components.Sizes.width;
2264        var focusAt = Glide.settings.focusAt;
2265        var slideWidth = Components.Sizes.slideWidth;
2266
2267        if (focusAt === 'center') {
2268          return translate - (width / 2 - slideWidth / 2);
2269        }
2270
2271        return translate - slideWidth * focusAt - gap * focusAt;
2272      }
2273    };
2274  }
2275
2276  /**
2277   * Applies diffrent transformers on translate value.
2278   *
2279   * @param  {Object} Glide
2280   * @param  {Object} Components
2281   * @return {Object}
2282   */
2283  function mutator (Glide, Components, Events) {
2284    /**
2285     * Merge instance transformers with collection of default transformers.
2286     * It's important that the Rtl component be last on the list,
2287     * so it reflects all previous transformations.
2288     *
2289     * @type {Array}
2290     */
2291    var TRANSFORMERS = [Gap, Grow, Peeking, Focusing].concat(Glide._t, [Rtl]);
2292
2293    return {
2294      /**
2295       * Piplines translate value with registered transformers.
2296       *
2297       * @param  {Number} translate
2298       * @return {Number}
2299       */
2300      mutate: function mutate(translate) {
2301        for (var i = 0; i < TRANSFORMERS.length; i++) {
2302          var transformer = TRANSFORMERS[i];
2303
2304          if (isFunction(transformer) && isFunction(transformer().modify)) {
2305            translate = transformer(Glide, Components, Events).modify(translate);
2306          } else {
2307            warn('Transformer should be a function that returns an object with `modify()` method');
2308          }
2309        }
2310
2311        return translate;
2312      }
2313    };
2314  }
2315
2316  function Translate (Glide, Components, Events) {
2317    var Translate = {
2318      /**
2319       * Sets value of translate on HTML element.
2320       *
2321       * @param {Number} value
2322       * @return {Void}
2323       */
2324      set: function set(value) {
2325        var transform = mutator(Glide, Components).mutate(value);
2326
2327        Components.Html.wrapper.style.transform = 'translate3d(' + -1 * transform + 'px, 0px, 0px)';
2328      },
2329
2330
2331      /**
2332       * Removes value of translate from HTML element.
2333       *
2334       * @return {Void}
2335       */
2336      remove: function remove() {
2337        Components.Html.wrapper.style.transform = '';
2338      }
2339    };
2340
2341    /**
2342     * Set new translate value:
2343     * - on move to reflect index change
2344     * - on updating via API to reflect possible changes in options
2345     */
2346    Events.on('move', function (context) {
2347      var gap = Components.Gaps.value;
2348      var length = Components.Sizes.length;
2349      var width = Components.Sizes.slideWidth;
2350
2351      if (Glide.isType('carousel') && Components.Run.isOffset('<')) {
2352        Components.Transition.after(function () {
2353          Events.emit('translate.jump');
2354
2355          Translate.set(width * (length - 1));
2356        });
2357
2358        return Translate.set(-width - gap * length);
2359      }
2360
2361      if (Glide.isType('carousel') && Components.Run.isOffset('>')) {
2362        Components.Transition.after(function () {
2363          Events.emit('translate.jump');
2364
2365          Translate.set(0);
2366        });
2367
2368        return Translate.set(width * length + gap * length);
2369      }
2370
2371      return Translate.set(context.movement);
2372    });
2373
2374    /**
2375     * Remove translate:
2376     * - on destroying to bring markup to its inital state
2377     */
2378    Events.on('destroy', function () {
2379      Translate.remove();
2380    });
2381
2382    return Translate;
2383  }
2384
2385  function Transition (Glide, Components, Events) {
2386    /**
2387     * Holds inactivity status of transition.
2388     * When true transition is not applied.
2389     *
2390     * @type {Boolean}
2391     */
2392    var disabled = false;
2393
2394    var Transition = {
2395      /**
2396       * Composes string of the CSS transition.
2397       *
2398       * @param {String} property
2399       * @return {String}
2400       */
2401      compose: function compose(property) {
2402        var settings = Glide.settings;
2403
2404        if (!disabled) {
2405          return property + ' ' + this.duration + 'ms ' + settings.animationTimingFunc;
2406        }
2407
2408        return property + ' 0ms ' + settings.animationTimingFunc;
2409      },
2410
2411
2412      /**
2413       * Sets value of transition on HTML element.
2414       *
2415       * @param {String=} property
2416       * @return {Void}
2417       */
2418      set: function set() {
2419        var property = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'transform';
2420
2421        Components.Html.wrapper.style.transition = this.compose(property);
2422      },
2423
2424
2425      /**
2426       * Removes value of transition from HTML element.
2427       *
2428       * @return {Void}
2429       */
2430      remove: function remove() {
2431        Components.Html.wrapper.style.transition = '';
2432      },
2433
2434
2435      /**
2436       * Runs callback after animation.
2437       *
2438       * @param  {Function} callback
2439       * @return {Void}
2440       */
2441      after: function after(callback) {
2442        setTimeout(function () {
2443          callback();
2444        }, this.duration);
2445      },
2446
2447
2448      /**
2449       * Enable transition.
2450       *
2451       * @return {Void}
2452       */
2453      enable: function enable() {
2454        disabled = false;
2455
2456        this.set();
2457      },
2458
2459
2460      /**
2461       * Disable transition.
2462       *
2463       * @return {Void}
2464       */
2465      disable: function disable() {
2466        disabled = true;
2467
2468        this.set();
2469      }
2470    };
2471
2472    define(Transition, 'duration', {
2473      /**
2474       * Gets duration of the transition based
2475       * on currently running animation type.
2476       *
2477       * @return {Number}
2478       */
2479      get: function get() {
2480        var settings = Glide.settings;
2481
2482        if (Glide.isType('slider') && Components.Run.offset) {
2483          return settings.rewindDuration;
2484        }
2485
2486        return settings.animationDuration;
2487      }
2488    });
2489
2490    /**
2491     * Set transition `style` value:
2492     * - on each moving, because it may be cleared by offset move
2493     */
2494    Events.on('move', function () {
2495      Transition.set();
2496    });
2497
2498    /**
2499     * Disable transition:
2500     * - before initial build to avoid transitioning from `0` to `startAt` index
2501     * - while resizing window and recalculating dimentions
2502     * - on jumping from offset transition at start and end edges in `carousel` type
2503     */
2504    Events.on(['build.before', 'resize', 'translate.jump'], function () {
2505      Transition.disable();
2506    });
2507
2508    /**
2509     * Enable transition:
2510     * - on each running, because it may be disabled by offset move
2511     */
2512    Events.on('run', function () {
2513      Transition.enable();
2514    });
2515
2516    /**
2517     * Remove transition:
2518     * - on destroying to bring markup to its inital state
2519     */
2520    Events.on('destroy', function () {
2521      Transition.remove();
2522    });
2523
2524    return Transition;
2525  }
2526
2527  /**
2528   * Test via a getter in the options object to see
2529   * if the passive property is accessed.
2530   *
2531   * @see https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
2532   */
2533
2534  var supportsPassive = false;
2535
2536  try {
2537    var opts = Object.defineProperty({}, 'passive', {
2538      get: function get() {
2539        supportsPassive = true;
2540      }
2541    });
2542
2543    window.addEventListener('testPassive', null, opts);
2544    window.removeEventListener('testPassive', null, opts);
2545  } catch (e) {}
2546
2547  var supportsPassive$1 = supportsPassive;
2548
2549  var START_EVENTS = ['touchstart', 'mousedown'];
2550  var MOVE_EVENTS = ['touchmove', 'mousemove'];
2551  var END_EVENTS = ['touchend', 'touchcancel', 'mouseup', 'mouseleave'];
2552  var MOUSE_EVENTS = ['mousedown', 'mousemove', 'mouseup', 'mouseleave'];
2553
2554  function Swipe (Glide, Components, Events) {
2555    /**
2556     * Instance of the binder for DOM Events.
2557     *
2558     * @type {EventsBinder}
2559     */
2560    var Binder = new EventsBinder();
2561
2562    var swipeSin = 0;
2563    var swipeStartX = 0;
2564    var swipeStartY = 0;
2565    var disabled = false;
2566    var capture = supportsPassive$1 ? { passive: true } : false;
2567
2568    var Swipe = {
2569      /**
2570       * Initializes swipe bindings.
2571       *
2572       * @return {Void}
2573       */
2574      mount: function mount() {
2575        this.bindSwipeStart();
2576      },
2577
2578
2579      /**
2580       * Handler for `swipestart` event. Calculates entry points of the user's tap.
2581       *
2582       * @param {Object} event
2583       * @return {Void}
2584       */
2585      start: function start(event) {
2586        if (!disabled && !Glide.disabled) {
2587          this.disable();
2588
2589          var swipe = this.touches(event);
2590
2591          swipeSin = null;
2592          swipeStartX = toInt(swipe.pageX);
2593          swipeStartY = toInt(swipe.pageY);
2594
2595          this.bindSwipeMove();
2596          this.bindSwipeEnd();
2597
2598          Events.emit('swipe.start');
2599        }
2600      },
2601
2602
2603      /**
2604       * Handler for `swipemove` event. Calculates user's tap angle and distance.
2605       *
2606       * @param {Object} event
2607       */
2608      move: function move(event) {
2609        if (!Glide.disabled) {
2610          var _Glide$settings = Glide.settings,
2611              touchAngle = _Glide$settings.touchAngle,
2612              touchRatio = _Glide$settings.touchRatio,
2613              classes = _Glide$settings.classes;
2614
2615
2616          var swipe = this.touches(event);
2617
2618          var subExSx = toInt(swipe.pageX) - swipeStartX;
2619          var subEySy = toInt(swipe.pageY) - swipeStartY;
2620          var powEX = Math.abs(subExSx << 2);
2621          var powEY = Math.abs(subEySy << 2);
2622          var swipeHypotenuse = Math.sqrt(powEX + powEY);
2623          var swipeCathetus = Math.sqrt(powEY);
2624
2625          swipeSin = Math.asin(swipeCathetus / swipeHypotenuse);
2626
2627          if (swipeSin * 180 / Math.PI < touchAngle) {
2628            event.stopPropagation();
2629
2630            Components.Move.make(subExSx * toFloat(touchRatio));
2631
2632            Components.Html.root.classList.add(classes.dragging);
2633
2634            Events.emit('swipe.move');
2635          } else {
2636            return false;
2637          }
2638        }
2639      },
2640
2641
2642      /**
2643       * Handler for `swipeend` event. Finitializes user's tap and decides about glide move.
2644       *
2645       * @param {Object} event
2646       * @return {Void}
2647       */
2648      end: function end(event) {
2649        if (!Glide.disabled) {
2650          var settings = Glide.settings;
2651
2652          var swipe = this.touches(event);
2653          var threshold = this.threshold(event);
2654
2655          var swipeDistance = swipe.pageX - swipeStartX;
2656          var swipeDeg = swipeSin * 180 / Math.PI;
2657          var steps = Math.round(swipeDistance / Components.Sizes.slideWidth);
2658
2659          this.enable();
2660
2661          if (swipeDistance > threshold && swipeDeg < settings.touchAngle) {
2662            // While swipe is positive and greater than threshold move backward.
2663            if (settings.perTouch) {
2664              steps = Math.min(steps, toInt(settings.perTouch));
2665            }
2666
2667            if (Components.Direction.is('rtl')) {
2668              steps = -steps;
2669            }
2670
2671            Components.Run.make(Components.Direction.resolve('<' + steps));
2672          } else if (swipeDistance < -threshold && swipeDeg < settings.touchAngle) {
2673            // While swipe is negative and lower than negative threshold move forward.
2674            if (settings.perTouch) {
2675              steps = Math.max(steps, -toInt(settings.perTouch));
2676            }
2677
2678            if (Components.Direction.is('rtl')) {
2679              steps = -steps;
2680            }
2681
2682            Components.Run.make(Components.Direction.resolve('>' + steps));
2683          } else {
2684            // While swipe don't reach distance apply previous transform.
2685            Components.Move.make();
2686          }
2687
2688          Components.Html.root.classList.remove(settings.classes.dragging);
2689
2690          this.unbindSwipeMove();
2691          this.unbindSwipeEnd();
2692
2693          Events.emit('swipe.end');
2694        }
2695      },
2696
2697
2698      /**
2699       * Binds swipe's starting event.
2700       *
2701       * @return {Void}
2702       */
2703      bindSwipeStart: function bindSwipeStart() {
2704        var _this = this;
2705
2706        var settings = Glide.settings;
2707
2708        if (settings.swipeThreshold) {
2709          Binder.on(START_EVENTS[0], Components.Html.wrapper, function (event) {
2710            _this.start(event);
2711          }, capture);
2712        }
2713
2714        if (settings.dragThreshold) {
2715          Binder.on(START_EVENTS[1], Components.Html.wrapper, function (event) {
2716            _this.start(event);
2717          }, capture);
2718        }
2719      },
2720
2721
2722      /**
2723       * Unbinds swipe's starting event.
2724       *
2725       * @return {Void}
2726       */
2727      unbindSwipeStart: function unbindSwipeStart() {
2728        Binder.off(START_EVENTS[0], Components.Html.wrapper, capture);
2729        Binder.off(START_EVENTS[1], Components.Html.wrapper, capture);
2730      },
2731
2732
2733      /**
2734       * Binds swipe's moving event.
2735       *
2736       * @return {Void}
2737       */
2738      bindSwipeMove: function bindSwipeMove() {
2739        var _this2 = this;
2740
2741        Binder.on(MOVE_EVENTS, Components.Html.wrapper, throttle(function (event) {
2742          _this2.move(event);
2743        }, Glide.settings.throttle), capture);
2744      },
2745
2746
2747      /**
2748       * Unbinds swipe's moving event.
2749       *
2750       * @return {Void}
2751       */
2752      unbindSwipeMove: function unbindSwipeMove() {
2753        Binder.off(MOVE_EVENTS, Components.Html.wrapper, capture);
2754      },
2755
2756
2757      /**
2758       * Binds swipe's ending event.
2759       *
2760       * @return {Void}
2761       */
2762      bindSwipeEnd: function bindSwipeEnd() {
2763        var _this3 = this;
2764
2765        Binder.on(END_EVENTS, Components.Html.wrapper, function (event) {
2766          _this3.end(event);
2767        });
2768      },
2769
2770
2771      /**
2772       * Unbinds swipe's ending event.
2773       *
2774       * @return {Void}
2775       */
2776      unbindSwipeEnd: function unbindSwipeEnd() {
2777        Binder.off(END_EVENTS, Components.Html.wrapper);
2778      },
2779
2780
2781      /**
2782       * Normalizes event touches points accorting to different types.
2783       *
2784       * @param {Object} event
2785       */
2786      touches: function touches(event) {
2787        if (MOUSE_EVENTS.indexOf(event.type) > -1) {
2788          return event;
2789        }
2790
2791        return event.touches[0] || event.changedTouches[0];
2792      },
2793
2794
2795      /**
2796       * Gets value of minimum swipe distance settings based on event type.
2797       *
2798       * @return {Number}
2799       */
2800      threshold: function threshold(event) {
2801        var settings = Glide.settings;
2802
2803        if (MOUSE_EVENTS.indexOf(event.type) > -1) {
2804          return settings.dragThreshold;
2805        }
2806
2807        return settings.swipeThreshold;
2808      },
2809
2810
2811      /**
2812       * Enables swipe event.
2813       *
2814       * @return {self}
2815       */
2816      enable: function enable() {
2817        disabled = false;
2818
2819        Components.Transition.enable();
2820
2821        return this;
2822      },
2823
2824
2825      /**
2826       * Disables swipe event.
2827       *
2828       * @return {self}
2829       */
2830      disable: function disable() {
2831        disabled = true;
2832
2833        Components.Transition.disable();
2834
2835        return this;
2836      }
2837    };
2838
2839    /**
2840     * Add component class:
2841     * - after initial building
2842     */
2843    Events.on('build.after', function () {
2844      Components.Html.root.classList.add(Glide.settings.classes.swipeable);
2845    });
2846
2847    /**
2848     * Remove swiping bindings:
2849     * - on destroying, to remove added EventListeners
2850     */
2851    Events.on('destroy', function () {
2852      Swipe.unbindSwipeStart();
2853      Swipe.unbindSwipeMove();
2854      Swipe.unbindSwipeEnd();
2855      Binder.destroy();
2856    });
2857
2858    return Swipe;
2859  }
2860
2861  function Images (Glide, Components, Events) {
2862    /**
2863     * Instance of the binder for DOM Events.
2864     *
2865     * @type {EventsBinder}
2866     */
2867    var Binder = new EventsBinder();
2868
2869    var Images = {
2870      /**
2871       * Binds listener to glide wrapper.
2872       *
2873       * @return {Void}
2874       */
2875      mount: function mount() {
2876        this.bind();
2877      },
2878
2879
2880      /**
2881       * Binds `dragstart` event on wrapper to prevent dragging images.
2882       *
2883       * @return {Void}
2884       */
2885      bind: function bind() {
2886        Binder.on('dragstart', Components.Html.wrapper, this.dragstart);
2887      },
2888
2889
2890      /**
2891       * Unbinds `dragstart` event on wrapper.
2892       *
2893       * @return {Void}
2894       */
2895      unbind: function unbind() {
2896        Binder.off('dragstart', Components.Html.wrapper);
2897      },
2898
2899
2900      /**
2901       * Event handler. Prevents dragging.
2902       *
2903       * @return {Void}
2904       */
2905      dragstart: function dragstart(event) {
2906        event.preventDefault();
2907      }
2908    };
2909
2910    /**
2911     * Remove bindings from images:
2912     * - on destroying, to remove added EventListeners
2913     */
2914    Events.on('destroy', function () {
2915      Images.unbind();
2916      Binder.destroy();
2917    });
2918
2919    return Images;
2920  }
2921
2922  function Anchors (Glide, Components, Events) {
2923    /**
2924     * Instance of the binder for DOM Events.
2925     *
2926     * @type {EventsBinder}
2927     */
2928    var Binder = new EventsBinder();
2929
2930    /**
2931     * Holds detaching status of anchors.
2932     * Prevents detaching of already detached anchors.
2933     *
2934     * @private
2935     * @type {Boolean}
2936     */
2937    var detached = false;
2938
2939    /**
2940     * Holds preventing status of anchors.
2941     * If `true` redirection after click will be disabled.
2942     *
2943     * @private
2944     * @type {Boolean}
2945     */
2946    var prevented = false;
2947
2948    var Anchors = {
2949      /**
2950       * Setups a initial state of anchors component.
2951       *
2952       * @returns {Void}
2953       */
2954      mount: function mount() {
2955        /**
2956         * Holds collection of anchors elements.
2957         *
2958         * @private
2959         * @type {HTMLCollection}
2960         */
2961        this._a = Components.Html.wrapper.querySelectorAll('a');
2962
2963        this.bind();
2964      },
2965
2966
2967      /**
2968       * Binds events to anchors inside a track.
2969       *
2970       * @return {Void}
2971       */
2972      bind: function bind() {
2973        Binder.on('click', Components.Html.wrapper, this.click);
2974      },
2975
2976
2977      /**
2978       * Unbinds events attached to anchors inside a track.
2979       *
2980       * @return {Void}
2981       */
2982      unbind: function unbind() {
2983        Binder.off('click', Components.Html.wrapper);
2984      },
2985
2986
2987      /**
2988       * Handler for click event. Prevents clicks when glide is in `prevent` status.
2989       *
2990       * @param  {Object} event
2991       * @return {Void}
2992       */
2993      click: function click(event) {
2994        if (prevented) {
2995          event.stopPropagation();
2996          event.preventDefault();
2997        }
2998      },
2999
3000
3001      /**
3002       * Detaches anchors click event inside glide.
3003       *
3004       * @return {self}
3005       */
3006      detach: function detach() {
3007        prevented = true;
3008
3009        if (!detached) {
3010          for (var i = 0; i < this.items.length; i++) {
3011            this.items[i].draggable = false;
3012
3013            this.items[i].setAttribute('data-href', this.items[i].getAttribute('href'));
3014
3015            this.items[i].removeAttribute('href');
3016          }
3017
3018          detached = true;
3019        }
3020
3021        return this;
3022      },
3023
3024
3025      /**
3026       * Attaches anchors click events inside glide.
3027       *
3028       * @return {self}
3029       */
3030      attach: function attach() {
3031        prevented = false;
3032
3033        if (detached) {
3034          for (var i = 0; i < this.items.length; i++) {
3035            this.items[i].draggable = true;
3036
3037            this.items[i].setAttribute('href', this.items[i].getAttribute('data-href'));
3038          }
3039
3040          detached = false;
3041        }
3042
3043        return this;
3044      }
3045    };
3046
3047    define(Anchors, 'items', {
3048      /**
3049       * Gets collection of the arrows HTML elements.
3050       *
3051       * @return {HTMLElement[]}
3052       */
3053      get: function get() {
3054        return Anchors._a;
3055      }
3056    });
3057
3058    /**
3059     * Detach anchors inside slides:
3060     * - on swiping, so they won't redirect to its `href` attributes
3061     */
3062    Events.on('swipe.move', function () {
3063      Anchors.detach();
3064    });
3065
3066    /**
3067     * Attach anchors inside slides:
3068     * - after swiping and transitions ends, so they can redirect after click again
3069     */
3070    Events.on('swipe.end', function () {
3071      Components.Transition.after(function () {
3072        Anchors.attach();
3073      });
3074    });
3075
3076    /**
3077     * Unbind anchors inside slides:
3078     * - on destroying, to bring anchors to its initial state
3079     */
3080    Events.on('destroy', function () {
3081      Anchors.attach();
3082      Anchors.unbind();
3083      Binder.destroy();
3084    });
3085
3086    return Anchors;
3087  }
3088
3089  var NAV_SELECTOR = '[data-glide-el="controls[nav]"]';
3090  var CONTROLS_SELECTOR = '[data-glide-el^="controls"]';
3091
3092  function Controls (Glide, Components, Events) {
3093    /**
3094     * Instance of the binder for DOM Events.
3095     *
3096     * @type {EventsBinder}
3097     */
3098    var Binder = new EventsBinder();
3099
3100    var capture = supportsPassive$1 ? { passive: true } : false;
3101
3102    var Controls = {
3103      /**
3104       * Inits arrows. Binds events listeners
3105       * to the arrows HTML elements.
3106       *
3107       * @return {Void}
3108       */
3109      mount: function mount() {
3110        /**
3111         * Collection of navigation HTML elements.
3112         *
3113         * @private
3114         * @type {HTMLCollection}
3115         */
3116        this._n = Components.Html.root.querySelectorAll(NAV_SELECTOR);
3117
3118        /**
3119         * Collection of controls HTML elements.
3120         *
3121         * @private
3122         * @type {HTMLCollection}
3123         */
3124        this._c = Components.Html.root.querySelectorAll(CONTROLS_SELECTOR);
3125
3126        this.addBindings();
3127      },
3128
3129
3130      /**
3131       * Sets active class to current slide.
3132       *
3133       * @return {Void}
3134       */
3135      setActive: function setActive() {
3136        for (var i = 0; i < this._n.length; i++) {
3137          this.addClass(this._n[i].children);
3138        }
3139      },
3140
3141
3142      /**
3143       * Removes active class to current slide.
3144       *
3145       * @return {Void}
3146       */
3147      removeActive: function removeActive() {
3148        for (var i = 0; i < this._n.length; i++) {
3149          this.removeClass(this._n[i].children);
3150        }
3151      },
3152
3153
3154      /**
3155       * Toggles active class on items inside navigation.
3156       *
3157       * @param  {HTMLElement} controls
3158       * @return {Void}
3159       */
3160      addClass: function addClass(controls) {
3161        var settings = Glide.settings;
3162        var item = controls[Glide.index];
3163
3164        if (item) {
3165          item.classList.add(settings.classes.activeNav);
3166
3167          siblings(item).forEach(function (sibling) {
3168            sibling.classList.remove(settings.classes.activeNav);
3169          });
3170        }
3171      },
3172
3173
3174      /**
3175       * Removes active class from active control.
3176       *
3177       * @param  {HTMLElement} controls
3178       * @return {Void}
3179       */
3180      removeClass: function removeClass(controls) {
3181        var item = controls[Glide.index];
3182
3183        if (item) {
3184          item.classList.remove(Glide.settings.classes.activeNav);
3185        }
3186      },
3187
3188
3189      /**
3190       * Adds handles to the each group of controls.
3191       *
3192       * @return {Void}
3193       */
3194      addBindings: function addBindings() {
3195        for (var i = 0; i < this._c.length; i++) {
3196          this.bind(this._c[i].children);
3197        }
3198      },
3199
3200
3201      /**
3202       * Removes handles from the each group of controls.
3203       *
3204       * @return {Void}
3205       */
3206      removeBindings: function removeBindings() {
3207        for (var i = 0; i < this._c.length; i++) {
3208          this.unbind(this._c[i].children);
3209        }
3210      },
3211
3212
3213      /**
3214       * Binds events to arrows HTML elements.
3215       *
3216       * @param {HTMLCollection} elements
3217       * @return {Void}
3218       */
3219      bind: function bind(elements) {
3220        for (var i = 0; i < elements.length; i++) {
3221          Binder.on('click', elements[i], this.click);
3222          Binder.on('touchstart', elements[i], this.click, capture);
3223        }
3224      },
3225
3226
3227      /**
3228       * Unbinds events binded to the arrows HTML elements.
3229       *
3230       * @param {HTMLCollection} elements
3231       * @return {Void}
3232       */
3233      unbind: function unbind(elements) {
3234        for (var i = 0; i < elements.length; i++) {
3235          Binder.off(['click', 'touchstart'], elements[i]);
3236        }
3237      },
3238
3239
3240      /**
3241       * Handles `click` event on the arrows HTML elements.
3242       * Moves slider in driection precised in
3243       * `data-glide-dir` attribute.
3244       *
3245       * @param {Object} event
3246       * @return {Void}
3247       */
3248      click: function click(event) {
3249        event.preventDefault();
3250
3251        Components.Run.make(Components.Direction.resolve(event.currentTarget.getAttribute('data-glide-dir')));
3252      }
3253    };
3254
3255    define(Controls, 'items', {
3256      /**
3257       * Gets collection of the controls HTML elements.
3258       *
3259       * @return {HTMLElement[]}
3260       */
3261      get: function get() {
3262        return Controls._c;
3263      }
3264    });
3265
3266    /**
3267     * Swap active class of current navigation item:
3268     * - after mounting to set it to initial index
3269     * - after each move to the new index
3270     */
3271    Events.on(['mount.after', 'move.after'], function () {
3272      Controls.setActive();
3273    });
3274
3275    /**
3276     * Remove bindings and HTML Classes:
3277     * - on destroying, to bring markup to its initial state
3278     */
3279    Events.on('destroy', function () {
3280      Controls.removeBindings();
3281      Controls.removeActive();
3282      Binder.destroy();
3283    });
3284
3285    return Controls;
3286  }
3287
3288  function Keyboard (Glide, Components, Events) {
3289    /**
3290     * Instance of the binder for DOM Events.
3291     *
3292     * @type {EventsBinder}
3293     */
3294    var Binder = new EventsBinder();
3295
3296    var Keyboard = {
3297      /**
3298       * Binds keyboard events on component mount.
3299       *
3300       * @return {Void}
3301       */
3302      mount: function mount() {
3303        if (Glide.settings.keyboard) {
3304          this.bind();
3305        }
3306      },
3307
3308
3309      /**
3310       * Adds keyboard press events.
3311       *
3312       * @return {Void}
3313       */
3314      bind: function bind() {
3315        Binder.on('keyup', document, this.press);
3316      },
3317
3318
3319      /**
3320       * Removes keyboard press events.
3321       *
3322       * @return {Void}
3323       */
3324      unbind: function unbind() {
3325        Binder.off('keyup', document);
3326      },
3327
3328
3329      /**
3330       * Handles keyboard's arrows press and moving glide foward and backward.
3331       *
3332       * @param  {Object} event
3333       * @return {Void}
3334       */
3335      press: function press(event) {
3336        if (event.keyCode === 39) {
3337          Components.Run.make(Components.Direction.resolve('>'));
3338        }
3339
3340        if (event.keyCode === 37) {
3341          Components.Run.make(Components.Direction.resolve('<'));
3342        }
3343      }
3344    };
3345
3346    /**
3347     * Remove bindings from keyboard:
3348     * - on destroying to remove added events
3349     * - on updating to remove events before remounting
3350     */
3351    Events.on(['destroy', 'update'], function () {
3352      Keyboard.unbind();
3353    });
3354
3355    /**
3356     * Remount component
3357     * - on updating to reflect potential changes in settings
3358     */
3359    Events.on('update', function () {
3360      Keyboard.mount();
3361    });
3362
3363    /**
3364     * Destroy binder:
3365     * - on destroying to remove listeners
3366     */
3367    Events.on('destroy', function () {
3368      Binder.destroy();
3369    });
3370
3371    return Keyboard;
3372  }
3373
3374  function Autoplay (Glide, Components, Events) {
3375    /**
3376     * Instance of the binder for DOM Events.
3377     *
3378     * @type {EventsBinder}
3379     */
3380    var Binder = new EventsBinder();
3381
3382    var Autoplay = {
3383      /**
3384       * Initializes autoplaying and events.
3385       *
3386       * @return {Void}
3387       */
3388      mount: function mount() {
3389        this.start();
3390
3391        if (Glide.settings.hoverpause) {
3392          this.bind();
3393        }
3394      },
3395
3396
3397      /**
3398       * Starts autoplaying in configured interval.
3399       *
3400       * @param {Boolean|Number} force Run autoplaying with passed interval regardless of `autoplay` settings
3401       * @return {Void}
3402       */
3403      start: function start() {
3404        var _this = this;
3405
3406        if (Glide.settings.autoplay) {
3407          if (isUndefined(this._i)) {
3408            this._i = setInterval(function () {
3409              _this.stop();
3410
3411              Components.Run.make('>');
3412
3413              _this.start();
3414            }, this.time);
3415          }
3416        }
3417      },
3418
3419
3420      /**
3421       * Stops autorunning of the glide.
3422       *
3423       * @return {Void}
3424       */
3425      stop: function stop() {
3426        this._i = clearInterval(this._i);
3427      },
3428
3429
3430      /**
3431       * Stops autoplaying while mouse is over glide's area.
3432       *
3433       * @return {Void}
3434       */
3435      bind: function bind() {
3436        var _this2 = this;
3437
3438        Binder.on('mouseover', Components.Html.root, function () {
3439          _this2.stop();
3440        });
3441
3442        Binder.on('mouseout', Components.Html.root, function () {
3443          _this2.start();
3444        });
3445      },
3446
3447
3448      /**
3449       * Unbind mouseover events.
3450       *
3451       * @returns {Void}
3452       */
3453      unbind: function unbind() {
3454        Binder.off(['mouseover', 'mouseout'], Components.Html.root);
3455      }
3456    };
3457
3458    define(Autoplay, 'time', {
3459      /**
3460       * Gets time period value for the autoplay interval. Prioritizes
3461       * times in `data-glide-autoplay` attrubutes over options.
3462       *
3463       * @return {Number}
3464       */
3465      get: function get() {
3466        var autoplay = Components.Html.slides[Glide.index].getAttribute('data-glide-autoplay');
3467
3468        if (autoplay) {
3469          return toInt(autoplay);
3470        }
3471
3472        return toInt(Glide.settings.autoplay);
3473      }
3474    });
3475
3476    /**
3477     * Stop autoplaying and unbind events:
3478     * - on destroying, to clear defined interval
3479     * - on updating via API to reset interval that may changed
3480     */
3481    Events.on(['destroy', 'update'], function () {
3482      Autoplay.unbind();
3483    });
3484
3485    /**
3486     * Stop autoplaying:
3487     * - before each run, to restart autoplaying
3488     * - on pausing via API
3489     * - on destroying, to clear defined interval
3490     * - while starting a swipe
3491     * - on updating via API to reset interval that may changed
3492     */
3493    Events.on(['run.before', 'pause', 'destroy', 'swipe.start', 'update'], function () {
3494      Autoplay.stop();
3495    });
3496
3497    /**
3498     * Start autoplaying:
3499     * - after each run, to restart autoplaying
3500     * - on playing via API
3501     * - while ending a swipe
3502     */
3503    Events.on(['run.after', 'play', 'swipe.end'], function () {
3504      Autoplay.start();
3505    });
3506
3507    /**
3508     * Remount autoplaying:
3509     * - on updating via API to reset interval that may changed
3510     */
3511    Events.on('update', function () {
3512      Autoplay.mount();
3513    });
3514
3515    /**
3516     * Destroy a binder:
3517     * - on destroying glide instance to clearup listeners
3518     */
3519    Events.on('destroy', function () {
3520      Binder.destroy();
3521    });
3522
3523    return Autoplay;
3524  }
3525
3526  /**
3527   * Sorts keys of breakpoint object so they will be ordered from lower to bigger.
3528   *
3529   * @param {Object} points
3530   * @returns {Object}
3531   */
3532  function sortBreakpoints(points) {
3533    if (isObject(points)) {
3534      return sortKeys(points);
3535    } else {
3536      warn('Breakpoints option must be an object');
3537    }
3538
3539    return {};
3540  }
3541
3542  function Breakpoints (Glide, Components, Events) {
3543    /**
3544     * Instance of the binder for DOM Events.
3545     *
3546     * @type {EventsBinder}
3547     */
3548    var Binder = new EventsBinder();
3549
3550    /**
3551     * Holds reference to settings.
3552     *
3553     * @type {Object}
3554     */
3555    var settings = Glide.settings;
3556
3557    /**
3558     * Holds reference to breakpoints object in settings. Sorts breakpoints
3559     * from smaller to larger. It is required in order to proper
3560     * matching currently active breakpoint settings.
3561     *
3562     * @type {Object}
3563     */
3564    var points = sortBreakpoints(settings.breakpoints);
3565
3566    /**
3567     * Cache initial settings before overwritting.
3568     *
3569     * @type {Object}
3570     */
3571    var defaults = _extends({}, settings);
3572
3573    var Breakpoints = {
3574      /**
3575       * Matches settings for currectly matching media breakpoint.
3576       *
3577       * @param {Object} points
3578       * @returns {Object}
3579       */
3580      match: function match(points) {
3581        if (typeof window.matchMedia !== 'undefined') {
3582          for (var point in points) {
3583            if (points.hasOwnProperty(point)) {
3584              if (window.matchMedia('(max-width: ' + point + 'px)').matches) {
3585                return points[point];
3586              }
3587            }
3588          }
3589        }
3590
3591        return defaults;
3592      }
3593    };
3594
3595    /**
3596     * Overwrite instance settings with currently matching breakpoint settings.
3597     * This happens right after component initialization.
3598     */
3599    _extends(settings, Breakpoints.match(points));
3600
3601    /**
3602     * Update glide with settings of matched brekpoint:
3603     * - window resize to update slider
3604     */
3605    Binder.on('resize', window, throttle(function () {
3606      Glide.settings = mergeOptions(settings, Breakpoints.match(points));
3607    }, Glide.settings.throttle));
3608
3609    /**
3610     * Resort and update default settings:
3611     * - on reinit via API, so breakpoint matching will be performed with options
3612     */
3613    Events.on('update', function () {
3614      points = sortBreakpoints(points);
3615
3616      defaults = _extends({}, settings);
3617    });
3618
3619    /**
3620     * Unbind resize listener:
3621     * - on destroying, to bring markup to its initial state
3622     */
3623    Events.on('destroy', function () {
3624      Binder.off('resize', window);
3625    });
3626
3627    return Breakpoints;
3628  }
3629
3630  var COMPONENTS = {
3631    // Required
3632    Html: Html,
3633    Translate: Translate,
3634    Transition: Transition,
3635    Direction: Direction,
3636    Peek: Peek,
3637    Sizes: Sizes,
3638    Gaps: Gaps,
3639    Move: Move,
3640    Clones: Clones,
3641    Resize: Resize,
3642    Build: Build,
3643    Run: Run,
3644
3645    // Optional
3646    Swipe: Swipe,
3647    Images: Images,
3648    Anchors: Anchors,
3649    Controls: Controls,
3650    Keyboard: Keyboard,
3651    Autoplay: Autoplay,
3652    Breakpoints: Breakpoints
3653  };
3654
3655  var Glide$1 = function (_Core) {
3656    inherits(Glide$$1, _Core);
3657
3658    function Glide$$1() {
3659      classCallCheck(this, Glide$$1);
3660      return possibleConstructorReturn(this, (Glide$$1.__proto__ || Object.getPrototypeOf(Glide$$1)).apply(this, arguments));
3661    }
3662
3663    createClass(Glide$$1, [{
3664      key: 'mount',
3665      value: function mount() {
3666        var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3667
3668        return get(Glide$$1.prototype.__proto__ || Object.getPrototypeOf(Glide$$1.prototype), 'mount', this).call(this, _extends({}, COMPONENTS, extensions));
3669      }
3670    }]);
3671    return Glide$$1;
3672  }(Glide);
3673
3674  return Glide$1;
3675
3676})));

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.