locomotive-scroll
Version:
Detection of elements in viewport & smooth scrolling with parallax effects.
1,652 lines (1,419 loc) • 104 kB
JavaScript
/* 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