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