UNPKG

locomotive-scroll

Version:

Detection of elements in viewport & smooth scrolling with parallax effects.

1,652 lines (1,419 loc) 104 kB
/* locomotive-scroll v4.1.3 | MIT License | https://github.com/locomotivemtl/locomotive-scroll */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.LocomotiveScroll = factory()); }(this, (function () { 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var defaults = { el: document, name: 'scroll', offset: [0, 0], repeat: false, smooth: false, initPosition: { x: 0, y: 0 }, direction: 'vertical', gestureDirection: 'vertical', reloadOnContextChange: false, lerp: 0.1, "class": 'is-inview', scrollbarContainer: false, scrollbarClass: 'c-scrollbar', scrollingClass: 'has-scroll-scrolling', draggingClass: 'has-scroll-dragging', smoothClass: 'has-scroll-smooth', initClass: 'has-scroll-init', getSpeed: false, getDirection: false, scrollFromAnywhere: false, multiplier: 1, firefoxMultiplier: 50, touchMultiplier: 2, resetNativeScroll: true, tablet: { smooth: false, direction: 'vertical', gestureDirection: 'vertical', breakpoint: 1024 }, smartphone: { smooth: false, direction: 'vertical', gestureDirection: 'vertical' } }; var _default = /*#__PURE__*/function () { function _default() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, _default); Object.assign(this, defaults, options); this.smartphone = defaults.smartphone; if (options.smartphone) Object.assign(this.smartphone, options.smartphone); this.tablet = defaults.tablet; if (options.tablet) Object.assign(this.tablet, options.tablet); this.namespace = 'locomotive'; this.html = document.documentElement; this.windowHeight = window.innerHeight; this.windowWidth = window.innerWidth; this.windowMiddle = { x: this.windowWidth / 2, y: this.windowHeight / 2 }; this.els = {}; this.currentElements = {}; this.listeners = {}; this.hasScrollTicking = false; this.hasCallEventSet = false; this.checkScroll = this.checkScroll.bind(this); this.checkResize = this.checkResize.bind(this); this.checkEvent = this.checkEvent.bind(this); this.instance = { scroll: { x: 0, y: 0 }, limit: { x: this.html.offsetWidth, y: this.html.offsetHeight }, currentElements: this.currentElements }; if (this.isMobile) { if (this.isTablet) { this.context = 'tablet'; } else { this.context = 'smartphone'; } } else { this.context = 'desktop'; } if (this.isMobile) this.direction = this[this.context].direction; if (this.direction === 'horizontal') { this.directionAxis = 'x'; } else { this.directionAxis = 'y'; } if (this.getDirection) { this.instance.direction = null; } if (this.getDirection) { this.instance.speed = 0; } this.html.classList.add(this.initClass); window.addEventListener('resize', this.checkResize, false); } _createClass(_default, [{ key: "init", value: function init() { this.initEvents(); } }, { key: "checkScroll", value: function checkScroll() { this.dispatchScroll(); } }, { key: "checkResize", value: function checkResize() { var _this = this; if (!this.resizeTick) { this.resizeTick = true; requestAnimationFrame(function () { _this.resize(); _this.resizeTick = false; }); } } }, { key: "resize", value: function resize() {} }, { key: "checkContext", value: function checkContext() { if (!this.reloadOnContextChange) return; this.isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 || this.windowWidth < this.tablet.breakpoint; this.isTablet = this.isMobile && this.windowWidth >= this.tablet.breakpoint; var oldContext = this.context; if (this.isMobile) { if (this.isTablet) { this.context = 'tablet'; } else { this.context = 'smartphone'; } } else { this.context = 'desktop'; } if (oldContext != this.context) { var oldSmooth = oldContext == 'desktop' ? this.smooth : this[oldContext].smooth; var newSmooth = this.context == 'desktop' ? this.smooth : this[this.context].smooth; if (oldSmooth != newSmooth) window.location.reload(); } } }, { key: "initEvents", value: function initEvents() { var _this2 = this; this.scrollToEls = this.el.querySelectorAll("[data-".concat(this.name, "-to]")); this.setScrollTo = this.setScrollTo.bind(this); this.scrollToEls.forEach(function (el) { el.addEventListener('click', _this2.setScrollTo, false); }); } }, { key: "setScrollTo", value: function setScrollTo(event) { event.preventDefault(); this.scrollTo(event.currentTarget.getAttribute("data-".concat(this.name, "-href")) || event.currentTarget.getAttribute('href'), { offset: event.currentTarget.getAttribute("data-".concat(this.name, "-offset")) }); } }, { key: "addElements", value: function addElements() {} }, { key: "detectElements", value: function detectElements(hasCallEventSet) { var _this3 = this; var scrollTop = this.instance.scroll.y; var scrollBottom = scrollTop + this.windowHeight; var scrollLeft = this.instance.scroll.x; var scrollRight = scrollLeft + this.windowWidth; Object.entries(this.els).forEach(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), i = _ref2[0], el = _ref2[1]; if (el && (!el.inView || hasCallEventSet)) { if (_this3.direction === 'horizontal') { if (scrollRight >= el.left && scrollLeft < el.right) { _this3.setInView(el, i); } } else { if (scrollBottom >= el.top && scrollTop < el.bottom) { _this3.setInView(el, i); } } } if (el && el.inView) { if (_this3.direction === 'horizontal') { var width = el.right - el.left; el.progress = (_this3.instance.scroll.x - (el.left - _this3.windowWidth)) / (width + _this3.windowWidth); if (scrollRight < el.left || scrollLeft > el.right) { _this3.setOutOfView(el, i); } } else { var height = el.bottom - el.top; el.progress = (_this3.instance.scroll.y - (el.top - _this3.windowHeight)) / (height + _this3.windowHeight); if (scrollBottom < el.top || scrollTop > el.bottom) { _this3.setOutOfView(el, i); } } } }); // this.els = this.els.filter((current, i) => { // return current !== null; // }); this.hasScrollTicking = false; } }, { key: "setInView", value: function setInView(current, i) { this.els[i].inView = true; current.el.classList.add(current["class"]); this.currentElements[i] = current; if (current.call && this.hasCallEventSet) { this.dispatchCall(current, 'enter'); if (!current.repeat) { this.els[i].call = false; } } // if (!current.repeat && !current.speed && !current.sticky) { // if (!current.call || current.call && this.hasCallEventSet) { // this.els[i] = null // } // } } }, { key: "setOutOfView", value: function setOutOfView(current, i) { var _this4 = this; // if (current.repeat || current.speed !== undefined) { this.els[i].inView = false; // } Object.keys(this.currentElements).forEach(function (el) { el === i && delete _this4.currentElements[el]; }); if (current.call && this.hasCallEventSet) { this.dispatchCall(current, 'exit'); } if (current.repeat) { current.el.classList.remove(current["class"]); } } }, { key: "dispatchCall", value: function dispatchCall(current, way) { this.callWay = way; this.callValue = current.call.split(',').map(function (item) { return item.trim(); }); this.callObj = current; if (this.callValue.length == 1) this.callValue = this.callValue[0]; var callEvent = new Event(this.namespace + 'call'); this.el.dispatchEvent(callEvent); } }, { key: "dispatchScroll", value: function dispatchScroll() { var scrollEvent = new Event(this.namespace + 'scroll'); this.el.dispatchEvent(scrollEvent); } }, { key: "setEvents", value: function setEvents(event, func) { if (!this.listeners[event]) { this.listeners[event] = []; } var list = this.listeners[event]; list.push(func); if (list.length === 1) { this.el.addEventListener(this.namespace + event, this.checkEvent, false); } if (event === 'call') { this.hasCallEventSet = true; this.detectElements(true); } } }, { key: "unsetEvents", value: function unsetEvents(event, func) { if (!this.listeners[event]) return; var list = this.listeners[event]; var index = list.indexOf(func); if (index < 0) return; list.splice(index, 1); if (list.index === 0) { this.el.removeEventListener(this.namespace + event, this.checkEvent, false); } } }, { key: "checkEvent", value: function checkEvent(event) { var _this5 = this; var name = event.type.replace(this.namespace, ''); var list = this.listeners[name]; if (!list || list.length === 0) return; list.forEach(function (func) { switch (name) { case 'scroll': return func(_this5.instance); case 'call': return func(_this5.callValue, _this5.callWay, _this5.callObj); default: return func(); } }); } }, { key: "startScroll", value: function startScroll() {} }, { key: "stopScroll", value: function stopScroll() {} }, { key: "setScroll", value: function setScroll(x, y) { this.instance.scroll = { x: 0, y: 0 }; } }, { key: "destroy", value: function destroy() { var _this6 = this; window.removeEventListener('resize', this.checkResize, false); Object.keys(this.listeners).forEach(function (event) { _this6.el.removeEventListener(_this6.namespace + event, _this6.checkEvent, false); }); this.listeners = {}; this.scrollToEls.forEach(function (el) { el.removeEventListener('click', _this6.setScrollTo, false); }); this.html.classList.remove(this.initClass); } }]); return _default; }(); var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var smoothscroll = createCommonjsModule(function (module, exports) { /* smoothscroll v0.4.4 - 2019 - Dustan Kasten, Jeremias Menichelli - MIT License */ (function () { // polyfill function polyfill() { // aliases var w = window; var d = document; // return if scroll behavior is supported and polyfill is not forced if ( 'scrollBehavior' in d.documentElement.style && w.__forceSmoothScrollPolyfill__ !== true ) { return; } // globals var Element = w.HTMLElement || w.Element; var SCROLL_TIME = 468; // object gathering original scroll methods var original = { scroll: w.scroll || w.scrollTo, scrollBy: w.scrollBy, elementScroll: Element.prototype.scroll || scrollElement, scrollIntoView: Element.prototype.scrollIntoView }; // define timing method var now = w.performance && w.performance.now ? w.performance.now.bind(w.performance) : Date.now; /** * indicates if a the current browser is made by Microsoft * @method isMicrosoftBrowser * @param {String} userAgent * @returns {Boolean} */ function isMicrosoftBrowser(userAgent) { var userAgentPatterns = ['MSIE ', 'Trident/', 'Edge/']; return new RegExp(userAgentPatterns.join('|')).test(userAgent); } /* * IE has rounding bug rounding down clientHeight and clientWidth and * rounding up scrollHeight and scrollWidth causing false positives * on hasScrollableSpace */ var ROUNDING_TOLERANCE = isMicrosoftBrowser(w.navigator.userAgent) ? 1 : 0; /** * changes scroll position inside an element * @method scrollElement * @param {Number} x * @param {Number} y * @returns {undefined} */ function scrollElement(x, y) { this.scrollLeft = x; this.scrollTop = y; } /** * returns result of applying ease math function to a number * @method ease * @param {Number} k * @returns {Number} */ function ease(k) { return 0.5 * (1 - Math.cos(Math.PI * k)); } /** * indicates if a smooth behavior should be applied * @method shouldBailOut * @param {Number|Object} firstArg * @returns {Boolean} */ function shouldBailOut(firstArg) { if ( firstArg === null || typeof firstArg !== 'object' || firstArg.behavior === undefined || firstArg.behavior === 'auto' || firstArg.behavior === 'instant' ) { // first argument is not an object/null // or behavior is auto, instant or undefined return true; } if (typeof firstArg === 'object' && firstArg.behavior === 'smooth') { // first argument is an object and behavior is smooth return false; } // throw error when behavior is not supported throw new TypeError( 'behavior member of ScrollOptions ' + firstArg.behavior + ' is not a valid value for enumeration ScrollBehavior.' ); } /** * indicates if an element has scrollable space in the provided axis * @method hasScrollableSpace * @param {Node} el * @param {String} axis * @returns {Boolean} */ function hasScrollableSpace(el, axis) { if (axis === 'Y') { return el.clientHeight + ROUNDING_TOLERANCE < el.scrollHeight; } if (axis === 'X') { return el.clientWidth + ROUNDING_TOLERANCE < el.scrollWidth; } } /** * indicates if an element has a scrollable overflow property in the axis * @method canOverflow * @param {Node} el * @param {String} axis * @returns {Boolean} */ function canOverflow(el, axis) { var overflowValue = w.getComputedStyle(el, null)['overflow' + axis]; return overflowValue === 'auto' || overflowValue === 'scroll'; } /** * indicates if an element can be scrolled in either axis * @method isScrollable * @param {Node} el * @param {String} axis * @returns {Boolean} */ function isScrollable(el) { var isScrollableY = hasScrollableSpace(el, 'Y') && canOverflow(el, 'Y'); var isScrollableX = hasScrollableSpace(el, 'X') && canOverflow(el, 'X'); return isScrollableY || isScrollableX; } /** * finds scrollable parent of an element * @method findScrollableParent * @param {Node} el * @returns {Node} el */ function findScrollableParent(el) { while (el !== d.body && isScrollable(el) === false) { el = el.parentNode || el.host; } return el; } /** * self invoked function that, given a context, steps through scrolling * @method step * @param {Object} context * @returns {undefined} */ function step(context) { var time = now(); var value; var currentX; var currentY; var elapsed = (time - context.startTime) / SCROLL_TIME; // avoid elapsed times higher than one elapsed = elapsed > 1 ? 1 : elapsed; // apply easing to elapsed time value = ease(elapsed); currentX = context.startX + (context.x - context.startX) * value; currentY = context.startY + (context.y - context.startY) * value; context.method.call(context.scrollable, currentX, currentY); // scroll more if we have not reached our destination if (currentX !== context.x || currentY !== context.y) { w.requestAnimationFrame(step.bind(w, context)); } } /** * scrolls window or element with a smooth behavior * @method smoothScroll * @param {Object|Node} el * @param {Number} x * @param {Number} y * @returns {undefined} */ function smoothScroll(el, x, y) { var scrollable; var startX; var startY; var method; var startTime = now(); // define scroll context if (el === d.body) { scrollable = w; startX = w.scrollX || w.pageXOffset; startY = w.scrollY || w.pageYOffset; method = original.scroll; } else { scrollable = el; startX = el.scrollLeft; startY = el.scrollTop; method = scrollElement; } // scroll looping over a frame step({ scrollable: scrollable, method: method, startTime: startTime, startX: startX, startY: startY, x: x, y: y }); } // ORIGINAL METHODS OVERRIDES // w.scroll and w.scrollTo w.scroll = w.scrollTo = function() { // avoid action when no arguments are passed if (arguments[0] === undefined) { return; } // avoid smooth behavior if not required if (shouldBailOut(arguments[0]) === true) { original.scroll.call( w, arguments[0].left !== undefined ? arguments[0].left : typeof arguments[0] !== 'object' ? arguments[0] : w.scrollX || w.pageXOffset, // use top prop, second argument if present or fallback to scrollY arguments[0].top !== undefined ? arguments[0].top : arguments[1] !== undefined ? arguments[1] : w.scrollY || w.pageYOffset ); return; } // LET THE SMOOTHNESS BEGIN! smoothScroll.call( w, d.body, arguments[0].left !== undefined ? ~~arguments[0].left : w.scrollX || w.pageXOffset, arguments[0].top !== undefined ? ~~arguments[0].top : w.scrollY || w.pageYOffset ); }; // w.scrollBy w.scrollBy = function() { // avoid action when no arguments are passed if (arguments[0] === undefined) { return; } // avoid smooth behavior if not required if (shouldBailOut(arguments[0])) { original.scrollBy.call( w, arguments[0].left !== undefined ? arguments[0].left : typeof arguments[0] !== 'object' ? arguments[0] : 0, arguments[0].top !== undefined ? arguments[0].top : arguments[1] !== undefined ? arguments[1] : 0 ); return; } // LET THE SMOOTHNESS BEGIN! smoothScroll.call( w, d.body, ~~arguments[0].left + (w.scrollX || w.pageXOffset), ~~arguments[0].top + (w.scrollY || w.pageYOffset) ); }; // Element.prototype.scroll and Element.prototype.scrollTo Element.prototype.scroll = Element.prototype.scrollTo = function() { // avoid action when no arguments are passed if (arguments[0] === undefined) { return; } // avoid smooth behavior if not required if (shouldBailOut(arguments[0]) === true) { // if one number is passed, throw error to match Firefox implementation if (typeof arguments[0] === 'number' && arguments[1] === undefined) { throw new SyntaxError('Value could not be converted'); } original.elementScroll.call( this, // use left prop, first number argument or fallback to scrollLeft arguments[0].left !== undefined ? ~~arguments[0].left : typeof arguments[0] !== 'object' ? ~~arguments[0] : this.scrollLeft, // use top prop, second argument or fallback to scrollTop arguments[0].top !== undefined ? ~~arguments[0].top : arguments[1] !== undefined ? ~~arguments[1] : this.scrollTop ); return; } var left = arguments[0].left; var top = arguments[0].top; // LET THE SMOOTHNESS BEGIN! smoothScroll.call( this, this, typeof left === 'undefined' ? this.scrollLeft : ~~left, typeof top === 'undefined' ? this.scrollTop : ~~top ); }; // Element.prototype.scrollBy Element.prototype.scrollBy = function() { // avoid action when no arguments are passed if (arguments[0] === undefined) { return; } // avoid smooth behavior if not required if (shouldBailOut(arguments[0]) === true) { original.elementScroll.call( this, arguments[0].left !== undefined ? ~~arguments[0].left + this.scrollLeft : ~~arguments[0] + this.scrollLeft, arguments[0].top !== undefined ? ~~arguments[0].top + this.scrollTop : ~~arguments[1] + this.scrollTop ); return; } this.scroll({ left: ~~arguments[0].left + this.scrollLeft, top: ~~arguments[0].top + this.scrollTop, behavior: arguments[0].behavior }); }; // Element.prototype.scrollIntoView Element.prototype.scrollIntoView = function() { // avoid smooth behavior if not required if (shouldBailOut(arguments[0]) === true) { original.scrollIntoView.call( this, arguments[0] === undefined ? true : arguments[0] ); return; } // LET THE SMOOTHNESS BEGIN! var scrollableParent = findScrollableParent(this); var parentRects = scrollableParent.getBoundingClientRect(); var clientRects = this.getBoundingClientRect(); if (scrollableParent !== d.body) { // reveal element inside parent smoothScroll.call( this, scrollableParent, scrollableParent.scrollLeft + clientRects.left - parentRects.left, scrollableParent.scrollTop + clientRects.top - parentRects.top ); // reveal parent in viewport unless is fixed if (w.getComputedStyle(scrollableParent).position !== 'fixed') { w.scrollBy({ left: parentRects.left, top: parentRects.top, behavior: 'smooth' }); } } else { // reveal element in viewport w.scrollBy({ left: clientRects.left, top: clientRects.top, behavior: 'smooth' }); } }; } { // commonjs module.exports = { polyfill: polyfill }; } }()); }); var smoothscroll_1 = smoothscroll.polyfill; var _default$1 = /*#__PURE__*/function (_Core) { _inherits(_default, _Core); var _super = _createSuper(_default); function _default() { var _this; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, _default); _this = _super.call(this, options); if (_this.resetNativeScroll) { if (history.scrollRestoration) { history.scrollRestoration = 'manual'; } window.scrollTo(0, 0); } window.addEventListener('scroll', _this.checkScroll, false); if (window.smoothscrollPolyfill === undefined) { window.smoothscrollPolyfill = smoothscroll; window.smoothscrollPolyfill.polyfill(); } return _this; } _createClass(_default, [{ key: "init", value: function init() { this.instance.scroll.y = window.pageYOffset; this.addElements(); this.detectElements(); _get(_getPrototypeOf(_default.prototype), "init", this).call(this); } }, { key: "checkScroll", value: function checkScroll() { var _this2 = this; _get(_getPrototypeOf(_default.prototype), "checkScroll", this).call(this); if (this.getDirection) { this.addDirection(); } if (this.getSpeed) { this.addSpeed(); this.speedTs = Date.now(); } this.instance.scroll.y = window.pageYOffset; if (Object.entries(this.els).length) { if (!this.hasScrollTicking) { requestAnimationFrame(function () { _this2.detectElements(); }); this.hasScrollTicking = true; } } } }, { key: "addDirection", value: function addDirection() { if (window.pageYOffset > this.instance.scroll.y) { if (this.instance.direction !== 'down') { this.instance.direction = 'down'; } } else if (window.pageYOffset < this.instance.scroll.y) { if (this.instance.direction !== 'up') { this.instance.direction = 'up'; } } } }, { key: "addSpeed", value: function addSpeed() { if (window.pageYOffset != this.instance.scroll.y) { this.instance.speed = (window.pageYOffset - this.instance.scroll.y) / Math.max(1, Date.now() - this.speedTs); } else { this.instance.speed = 0; } } }, { key: "resize", value: function resize() { if (Object.entries(this.els).length) { this.windowHeight = window.innerHeight; this.updateElements(); } } }, { key: "addElements", value: function addElements() { var _this3 = this; this.els = {}; var els = this.el.querySelectorAll('[data-' + this.name + ']'); els.forEach(function (el, index) { var BCR = el.getBoundingClientRect(); var cl = el.dataset[_this3.name + 'Class'] || _this3["class"]; var id = typeof el.dataset[_this3.name + 'Id'] === 'string' ? el.dataset[_this3.name + 'Id'] : index; var top; var left; var offset = typeof el.dataset[_this3.name + 'Offset'] === 'string' ? el.dataset[_this3.name + 'Offset'].split(',') : _this3.offset; var repeat = el.dataset[_this3.name + 'Repeat']; var call = el.dataset[_this3.name + 'Call']; var target = el.dataset[_this3.name + 'Target']; var targetEl; if (target !== undefined) { targetEl = document.querySelector("".concat(target)); } else { targetEl = el; } var targetElBCR = targetEl.getBoundingClientRect(); top = targetElBCR.top + _this3.instance.scroll.y; left = targetElBCR.left + _this3.instance.scroll.x; var bottom = top + targetEl.offsetHeight; var right = left + targetEl.offsetWidth; if (repeat == 'false') { repeat = false; } else if (repeat != undefined) { repeat = true; } else { repeat = _this3.repeat; } var relativeOffset = _this3.getRelativeOffset(offset); top = top + relativeOffset[0]; bottom = bottom - relativeOffset[1]; var mappedEl = { el: el, targetEl: targetEl, id: id, "class": cl, top: top, bottom: bottom, left: left, right: right, offset: offset, progress: 0, repeat: repeat, inView: false, call: call }; _this3.els[id] = mappedEl; if (el.classList.contains(cl)) { _this3.setInView(_this3.els[id], id); } }); } }, { key: "updateElements", value: function updateElements() { var _this4 = this; Object.entries(this.els).forEach(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), i = _ref2[0], el = _ref2[1]; var top = el.targetEl.getBoundingClientRect().top + _this4.instance.scroll.y; var bottom = top + el.targetEl.offsetHeight; var relativeOffset = _this4.getRelativeOffset(el.offset); _this4.els[i].top = top + relativeOffset[0]; _this4.els[i].bottom = bottom - relativeOffset[1]; }); this.hasScrollTicking = false; } }, { key: "getRelativeOffset", value: function getRelativeOffset(offset) { var relativeOffset = [0, 0]; if (offset) { for (var i = 0; i < offset.length; i++) { if (typeof offset[i] == 'string') { if (offset[i].includes('%')) { relativeOffset[i] = parseInt(offset[i].replace('%', '') * this.windowHeight / 100); } else { relativeOffset[i] = parseInt(offset[i]); } } else { relativeOffset[i] = offset[i]; } } } return relativeOffset; } /** * Scroll to a desired target. * * @param Available options : * target {node, string, "top", "bottom", int} - The DOM element we want to scroll to * options {object} - Options object for additionnal settings. * @return {void} */ }, { key: "scrollTo", value: function scrollTo(target) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // Parse options var offset = parseInt(options.offset) || 0; // An offset to apply on top of given `target` or `sourceElem`'s target var callback = options.callback ? options.callback : false; // function called when scrollTo completes (note that it won't wait for lerp to stabilize) if (typeof target === 'string') { // Selector or boundaries if (target === 'top') { target = this.html; } else if (target === 'bottom') { target = this.html.offsetHeight - window.innerHeight; } else { target = document.querySelector(target); // If the query fails, abort if (!target) { return; } } } else if (typeof target === 'number') { // Absolute coordinate target = parseInt(target); } else if (target && target.tagName) ; else { console.warn('`target` parameter is not valid'); return; } // We have a target that is not a coordinate yet, get it if (typeof target !== 'number') { offset = target.getBoundingClientRect().top + offset + this.instance.scroll.y; } else { offset = target + offset; } var isTargetReached = function isTargetReached() { return parseInt(window.pageYOffset) === parseInt(offset); }; if (callback) { if (isTargetReached()) { callback(); return; } else { var onScroll = function onScroll() { if (isTargetReached()) { window.removeEventListener('scroll', onScroll); callback(); } }; window.addEventListener('scroll', onScroll); } } window.scrollTo({ top: offset, behavior: options.duration === 0 ? 'auto' : 'smooth' }); } }, { key: "update", value: function update() { this.addElements(); this.detectElements(); } }, { key: "destroy", value: function destroy() { _get(_getPrototypeOf(_default.prototype), "destroy", this).call(this); window.removeEventListener('scroll', this.checkScroll, false); } }]); return _default; }(_default); /* object-assign (c) Sindre Sorhus @license MIT */ /* eslint-disable no-unused-vars */ var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === undefined) { throw new TypeError('Object.assign cannot be called with null or undefined'); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } // Detect buggy property enumeration order in older V8 versions. // https://bugs.chromium.org/p/v8/issues/detail?id=4118 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers test1[5] = 'de'; if (Object.getOwnPropertyNames(test1)[0] === '5') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test2 = {}; for (var i = 0; i < 10; i++) { test2['_' + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function (n) { return test2[n]; }); if (order2.join('') !== '0123456789') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test3 = {}; 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { return false; } return true; } catch (err) { // We don't expect any of the above to throw, but better to be safe. return false; } } var objectAssign = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; function E () { // Keep this empty so it's easier to inherit from // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3) } E.prototype = { on: function (name, callback, ctx) { var e = this.e || (this.e = {}); (e[name] || (e[name] = [])).push({ fn: callback, ctx: ctx }); return this; }, once: function (name, callback, ctx) { var self = this; function listener () { self.off(name, listener); callback.apply(ctx, arguments); } listener._ = callback; return this.on(name, listener, ctx); }, emit: function (name) { var data = [].slice.call(arguments, 1); var evtArr = ((this.e || (this.e = {}))[name] || []).slice(); var i = 0; var len = evtArr.length; for (i; i < len; i++) { evtArr[i].fn.apply(evtArr[i].ctx, data); } return this; }, off: function (name, callback) { var e = this.e || (this.e = {}); var evts = e[name]; var liveEvents = []; if (evts && callback) { for (var i = 0, len = evts.length; i < len; i++) { if (evts[i].fn !== callback && evts[i].fn._ !== callback) liveEvents.push(evts[i]); } } // Remove event from queue to prevent memory leak // Suggested by https://github.com/lazd // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910 (liveEvents.length) ? e[name] = liveEvents : delete e[name]; return this; } }; var tinyEmitter = E; var lethargy = createCommonjsModule(function (module, exports) { // Generated by CoffeeScript 1.9.2 (function() { var root; root = exports !== null ? exports : this; root.Lethargy = (function() { function Lethargy(stability, sensitivity, tolerance, delay) { this.stability = stability != null ? Math.abs(stability) : 8; this.sensitivity = sensitivity != null ? 1 + Math.abs(sensitivity) : 100; this.tolerance = tolerance != null ? 1 + Math.abs(tolerance) : 1.1; this.delay = delay != null ? delay : 150; this.lastUpDeltas = (function() { var i, ref, results; results = []; for (i = 1, ref = this.stability * 2; 1 <= ref ? i <= ref : i >= ref; 1 <= ref ? i++ : i--) { results.push(null); } return results; }).call(this); this.lastDownDeltas = (function() { var i, ref, results; results = []; for (i = 1, ref = this.stability * 2; 1 <= ref ? i <= ref : i >= ref; 1 <= ref ? i++ : i--) { results.push(null); } return results; }).call(this); this.deltasTimestamp = (function() { var i, ref, results; results = []; for (i = 1, ref = this.stability * 2; 1 <= ref ? i <= ref : i >= ref; 1 <= ref ? i++ : i--) { results.push(null); } return results; }).call(this); } Lethargy.prototype.check = function(e) { var lastDelta; e = e.originalEvent || e; if (e.wheelDelta != null) { lastDelta = e.wheelDelta; } else if (e.deltaY != null) { lastDelta = e.deltaY * -40; } else if ((e.detail != null) || e.detail === 0) { lastDelta = e.detail * -40; } this.deltasTimestamp.push(Date.now()); this.deltasTimestamp.shift(); if (lastDelta > 0) { this.lastUpDeltas.push(lastDelta); this.lastUpDeltas.shift(); return this.isInertia(1); } else { this.lastDownDeltas.push(lastDelta); this.lastDownDeltas.shift(); return this.isInertia(-1); } }; Lethargy.prototype.isInertia = function(direction) { var lastDeltas, lastDeltasNew, lastDeltasOld, newAverage, newSum, oldAverage, oldSum; lastDeltas = direction === -1 ? this.lastDownDeltas : this.lastUpDeltas; if (lastDeltas[0] === null) { return direction; } if (this.deltasTimestamp[(this.stability * 2) - 2] + this.delay > Date.now() && lastDeltas[0] === lastDeltas[(this.stability * 2) - 1]) { return false; } lastDeltasOld = lastDeltas.slice(0, this.stability); lastDeltasNew = lastDeltas.slice(this.stability, this.stability * 2); oldSum = lastDeltasOld.reduce(function(t, s) { return t + s; }); newSum = lastDeltasNew.reduce(function(t, s) { return t + s; }); oldAverage = oldSum / lastDeltasOld.length; newAverage = newSum / lastDeltasNew.length; if (Math.abs(oldAverage) < Math.abs(newAverage * this.tolerance) && (this.sensitivity < Math.abs(newAverage))) { return direction; } else { return false; } }; Lethargy.prototype.showLastUpDeltas = function() { return this.lastUpDeltas; }; Lethargy.prototype.showLastDownDeltas = function() { return this.lastDownDeltas; }; return Lethargy; })(); }).call(commonjsGlobal); }); var support = (function getSupport() { return { hasWheelEvent: 'onwheel' in document, hasMouseWheelEvent: 'onmousewheel' in document, hasTouch: ('ontouchstart' in window) || window.TouchEvent || window.DocumentTouch && document instanceof DocumentTouch, hasTouchWin: navigator.msMaxTouchPoints && navigator.msMaxTouchPoints > 1, hasPointer: !!window.navigator.msPointerEnabled, hasKeyDown: 'onkeydown' in document, isFirefox: navigator.userAgent.indexOf('Firefox') > -1 }; })(); var toString = Object.prototype.toString, hasOwnProperty$1 = Object.prototype.hasOwnProperty; var bindallStandalone = function(object) { if(!object) return console.warn('bindAll requires at least one argument.'); var functions = Array.prototype.slice.call(arguments, 1); if (functions.length === 0) { for (var method in object) { if(hasOwnProperty$1.call(object, method)) { if(typeof object[met