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