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.