Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

scrollama

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scrollama - npm Package Compare versions

Comparing version 2.2.2 to 3.0.0

src/createProgressThreshold.js

886

build/scrollama.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.scrollama = factory());
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.scrollama = factory());
}(this, (function () { 'use strict';
// DOM helper functions
// DOM helper functions
// public
function selectAll(selector, parent) {
if ( parent === void 0 ) parent = document;
// public
function selectAll(selector, parent = document) {
if (typeof selector === 'string') {
return Array.from(parent.querySelectorAll(selector));
} else if (selector instanceof Element) {
return [selector];
} else if (selector instanceof NodeList) {
return Array.from(selector);
} else if (selector instanceof Array) {
return selector;
}
return [];
}
if (typeof selector === 'string') {
return Array.from(parent.querySelectorAll(selector));
} else if (selector instanceof Element) {
return [selector];
} else if (selector instanceof NodeList) {
return Array.from(selector);
} else if (selector instanceof Array) {
return selector;
function err$1(msg) {
console.error(`scrollama error: ${msg}`);
}
return [];
}
function getOffsetId(id) {
return ("scrollama__debug-offset--" + id);
}
function getIndex(node) {
return +node.getAttribute("data-scrollama-index");
}
// SETUP
function setupOffset(ref) {
var id = ref.id;
var offsetVal = ref.offsetVal;
var stepClass = ref.stepClass;
function createProgressThreshold(height, threshold) {
const count = Math.ceil(height / threshold);
const t = [];
const ratio = 1 / count;
for (let i = 0; i < count + 1; i += 1) {
t.push(i * ratio);
}
return t;
}
var el = document.createElement("div");
el.id = getOffsetId(id);
el.className = "scrollama__debug-offset";
el.style.position = "fixed";
el.style.left = "0";
el.style.width = "100%";
el.style.height = "0";
el.style.borderTop = "2px dashed black";
el.style.zIndex = "9999";
var p = document.createElement("p");
p.innerHTML = "\"." + stepClass + "\" trigger: <span>" + offsetVal + "</span>";
p.style.fontSize = "12px";
p.style.fontFamily = "monospace";
p.style.color = "black";
p.style.margin = "0";
p.style.padding = "6px";
el.appendChild(p);
document.body.appendChild(el);
}
function setup(ref) {
var id = ref.id;
var offsetVal = ref.offsetVal;
var stepEl = ref.stepEl;
var stepClass = stepEl[0].className;
setupOffset({ id: id, offsetVal: offsetVal, stepClass: stepClass });
}
// UPDATE
function update(ref) {
var id = ref.id;
var offsetMargin = ref.offsetMargin;
var offsetVal = ref.offsetVal;
var format = ref.format;
var post = format === "pixels" ? "px" : "";
var idVal = getOffsetId(id);
var el = document.getElementById(idVal);
el.style.top = offsetMargin + "px";
el.querySelector("span").innerText = "" + offsetVal + post;
}
function notifyStep(ref) {
var id = ref.id;
var index = ref.index;
var state = ref.state;
var prefix = "scrollama__debug-step--" + id + "-" + index;
var elA = document.getElementById((prefix + "_above"));
var elB = document.getElementById((prefix + "_below"));
var display = state === "enter" ? "block" : "none";
if (elA) { elA.style.display = display; }
if (elB) { elB.style.display = display; }
}
function scrollama() {
var OBSERVER_NAMES = [
"stepAbove",
"stepBelow",
"stepProgress",
"viewportAbove",
"viewportBelow"
];
var cb = {};
var io = {};
var id = null;
var stepEl = [];
var stepOffsetHeight = [];
var stepOffsetTop = [];
var stepStates = [];
var offsetVal = 0;
var offsetMargin = 0;
var viewH = 0;
var pageH = 0;
var previousYOffset = 0;
var progressThreshold = 0;
var isReady = false;
var isEnabled = false;
var isDebug = false;
var progressMode = false;
var preserveOrder = false;
var triggerOnce = false;
var direction = "down";
var format = "percent";
var exclude = [];
/* HELPERS */
function err(msg) {
console.error(("scrollama error: " + msg));
function parseOffset(x) {
if (typeof x === "string" && x.indexOf("px") > 0) {
const v = +x.replace("px", "");
if (!isNaN(v)) return { format: "pixels", value: v };
else {
err("offset value must be in 'px' format. Fallback to 0.5.");
return { format: "percent", value: 0.5 };
}
} else if (typeof x === "number" || !isNaN(+x)) {
if (x > 1) err("offset value is greater than 1. Fallback to 1.");
if (x < 0) err("offset value is lower than 0. Fallback to 0.");
return { format: "percent", value: Math.min(Math.max(0, x), 1) };
}
return null;
}
function reset() {
cb = {
stepEnter: function () {},
stepExit: function () {},
stepProgress: function () {}
};
io = {};
function indexSteps(steps) {
steps.forEach((step) =>
step.node.setAttribute("data-scrollama-index", step.index)
);
}
function generateInstanceID() {
var a = "abcdefghijklmnopqrstuv";
var l = a.length;
var t = Date.now();
var r = [0, 0, 0].map(function (d) { return a[Math.floor(Math.random() * l)]; }).join("");
return ("" + r + t);
}
function getOffsetTop(el) {
var ref = el.getBoundingClientRect();
var top = ref.top;
var scrollTop = window.pageYOffset;
var clientTop = document.body.clientTop || 0;
function getOffsetTop(node) {
const { top } = node.getBoundingClientRect();
const scrollTop = window.pageYOffset;
const clientTop = document.body.clientTop || 0;
return top + scrollTop - clientTop;
}
function getPageHeight() {
var body = document.body;
var html = document.documentElement;
let currentScrollY = 0;
let comparisonScrollY = 0;
let direction;
return Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight
);
function onScroll() {
if (currentScrollY === window.pageYOffset) return;
currentScrollY = window.pageYOffset;
if (currentScrollY > comparisonScrollY) direction = "down";
else if (currentScrollY < comparisonScrollY) direction = "up";
comparisonScrollY = currentScrollY;
}
function getIndex(element) {
return +element.getAttribute("data-scrollama-index");
function setupScroll() {
document.addEventListener("scroll", onScroll);
}
function updateDirection() {
if (window.pageYOffset > previousYOffset) { direction = "down"; }
else if (window.pageYOffset < previousYOffset) { direction = "up"; }
previousYOffset = window.pageYOffset;
}
function scrollama() {
let cb = {};
let steps = [];
let globalOffset;
function disconnectObserver(name) {
if (io[name]) { io[name].forEach(function (d) { return d.disconnect(); }); }
}
let progressThreshold = 0;
function handleResize() {
viewH = window.innerHeight;
pageH = getPageHeight();
let isEnabled = false;
let isProgressMode = false;
let isTriggerOnce = false;
var mult = format === "pixels" ? 1 : viewH;
offsetMargin = offsetVal * mult;
let exclude = [];
if (isReady) {
stepOffsetHeight = stepEl.map(function (el) { return el.getBoundingClientRect().height; });
stepOffsetTop = stepEl.map(getOffsetTop);
if (isEnabled) { updateIO(); }
/* HELPERS */
function reset() {
cb = {
stepEnter: () => {},
stepExit: () => {},
stepProgress: () => {},
};
exclude = [];
}
if (isDebug) { update({ id: id, offsetMargin: offsetMargin, offsetVal: offsetVal, format: format }); }
}
function handleEnable(enable) {
if (enable && !isEnabled) {
// enable a disabled scroller
if (isReady) {
// enable a ready scroller
updateIO();
} else {
// can't enable an unready scroller
err("scrollama error: enable() called before scroller was ready");
isEnabled = false;
return; // all is not well, don't set the requested state
}
function handleEnable(shouldEnable) {
if (shouldEnable && !isEnabled) updateObservers();
if (!shouldEnable && isEnabled) disconnectObservers();
isEnabled = shouldEnable;
}
if (!enable && isEnabled) {
// disable an enabled scroller
OBSERVER_NAMES.forEach(disconnectObserver);
}
isEnabled = enable; // all is well, set requested state
}
function createThreshold(height) {
var count = Math.ceil(height / progressThreshold);
var t = [];
var ratio = 1 / count;
for (var i = 0; i < count; i += 1) {
t.push(i * ratio);
/* NOTIFY CALLBACKS */
function notifyProgress(element, progress) {
const index = getIndex(element);
const step = steps[index];
if (progress !== undefined) step.progress = progress;
const response = { element, index, progress, direction };
if (step.state === "enter") cb.stepProgress(response);
}
return t;
}
/* NOTIFY CALLBACKS */
function notifyStepProgress(element, progress) {
var index = getIndex(element);
if (progress !== undefined) { stepStates[index].progress = progress; }
var resp = { element: element, index: index, progress: stepStates[index].progress };
function notifyStepEnter(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
if (stepStates[index].state === "enter") { cb.stepProgress(resp); }
}
step.direction = direction;
step.state = "enter";
function notifyOthers(index, location) {
if (location === "above") {
// check if steps above/below were skipped and should be notified first
for (var i = 0; i < index; i += 1) {
var ss = stepStates[i];
if (ss.state !== "enter" && ss.direction !== "down") {
notifyStepEnter(stepEl[i], "down", false);
notifyStepExit(stepEl[i], "down");
} else if (ss.state === "enter") { notifyStepExit(stepEl[i], "down"); }
// else if (ss.direction === 'up') {
// notifyStepEnter(stepEl[i], 'down', false);
// notifyStepExit(stepEl[i], 'down');
// }
}
} else if (location === "below") {
for (var i$1 = stepStates.length - 1; i$1 > index; i$1 -= 1) {
var ss$1 = stepStates[i$1];
if (ss$1.state === "enter") {
notifyStepExit(stepEl[i$1], "up");
}
if (ss$1.direction === "down") {
notifyStepEnter(stepEl[i$1], "up", false);
notifyStepExit(stepEl[i$1], "up");
}
}
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "above");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "below");
if (!exclude[index]) cb.stepEnter(response);
if (isTriggerOnce) exclude[index] = true;
}
}
function notifyStepEnter(element, dir, check) {
if ( check === void 0 ) check = true;
function notifyStepExit(element, check = true) {
const index = getIndex(element);
const step = steps[index];
var index = getIndex(element);
var resp = { element: element, index: index, direction: dir };
if (!step.state) return false;
// store most recent trigger
stepStates[index].direction = dir;
stepStates[index].state = "enter";
if (preserveOrder && check && dir === "down") { notifyOthers(index, "above"); }
const response = { element, index, direction };
if (preserveOrder && check && dir === "up") { notifyOthers(index, "below"); }
if (isProgressMode) {
if (direction === "down" && step.progress < 1) notifyProgress(element, 1);
else if (direction === "up" && step.progress > 0)
notifyProgress(element, 0);
}
if (cb.stepEnter && !exclude[index]) {
cb.stepEnter(resp, stepStates);
if (isDebug) { notifyStep({ id: id, index: index, state: "enter" }); }
if (triggerOnce) { exclude[index] = true; }
}
step.direction = direction;
step.state = "exit";
if (progressMode) { notifyStepProgress(element); }
}
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "below");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "above");
function notifyStepExit(element, dir) {
var index = getIndex(element);
var resp = { element: element, index: index, direction: dir };
cb.stepExit(response);
}
if (progressMode) {
if (dir === "down" && stepStates[index].progress < 1)
{ notifyStepProgress(element, 1); }
else if (dir === "up" && stepStates[index].progress > 0)
{ notifyStepProgress(element, 0); }
/* OBSERVERS - HANDLING */
function resizeStep([entry]) {
const index = getIndex(entry.target);
const step = steps[index];
const h = entry.target.offsetHeight;
if (h !== step.height) {
step.height = h;
disconnectObserver(step);
updateStepObserver(step);
updateResizeObserver(step);
}
}
// store most recent trigger
stepStates[index].direction = dir;
stepStates[index].state = "exit";
function intersectStep([entry]) {
onScroll();
cb.stepExit(resp, stepStates);
if (isDebug) { notifyStep({ id: id, index: index, state: "exit" }); }
}
const { isIntersecting, target } = entry;
if (isIntersecting) notifyStepEnter(target);
else notifyStepExit(target);
}
/* OBSERVER - INTERSECT HANDLING */
// this is good for entering while scrolling down + leaving while scrolling up
function intersectStepAbove(ref) {
var entry = ref[0];
function intersectProgress([entry]) {
const index = getIndex(entry.target);
const step = steps[index];
const { isIntersecting, intersectionRatio, target } = entry;
if (isIntersecting && step.state === "enter")
notifyProgress(target, intersectionRatio);
}
updateDirection();
var isIntersecting = entry.isIntersecting;
var boundingClientRect = entry.boundingClientRect;
var target = entry.target;
/* OBSERVERS - CREATION */
function disconnectObserver({ observers }) {
Object.keys(observers).map((name) => {
observers[name].disconnect();
});
}
// bottom = bottom edge of element from top of viewport
// bottomAdjusted = bottom edge of element from trigger
var top = boundingClientRect.top;
var bottom = boundingClientRect.bottom;
var topAdjusted = top - offsetMargin;
var bottomAdjusted = bottom - offsetMargin;
var index = getIndex(target);
var ss = stepStates[index];
// entering above is only when topAdjusted is negative
// and bottomAdjusted is positive
if (
isIntersecting &&
topAdjusted <= 0 &&
bottomAdjusted >= 0 &&
direction === "down" &&
ss.state !== "enter"
)
{ notifyStepEnter(target, direction); }
// exiting from above is when topAdjusted is positive and not intersecting
if (
!isIntersecting &&
topAdjusted > 0 &&
direction === "up" &&
ss.state === "enter"
)
{ notifyStepExit(target, direction); }
}
// this is good for entering while scrolling up + leaving while scrolling down
function intersectStepBelow(ref) {
var entry = ref[0];
updateDirection();
var isIntersecting = entry.isIntersecting;
var boundingClientRect = entry.boundingClientRect;
var target = entry.target;
// bottom = bottom edge of element from top of viewport
// bottomAdjusted = bottom edge of element from trigger
var top = boundingClientRect.top;
var bottom = boundingClientRect.bottom;
var topAdjusted = top - offsetMargin;
var bottomAdjusted = bottom - offsetMargin;
var index = getIndex(target);
var ss = stepStates[index];
// entering below is only when bottomAdjusted is positive
// and topAdjusted is negative
if (
isIntersecting &&
topAdjusted <= 0 &&
bottomAdjusted >= 0 &&
direction === "up" &&
ss.state !== "enter"
)
{ notifyStepEnter(target, direction); }
// exiting from above is when bottomAdjusted is negative and not intersecting
if (
!isIntersecting &&
bottomAdjusted < 0 &&
direction === "down" &&
ss.state === "enter"
)
{ notifyStepExit(target, direction); }
}
/*
if there is a scroll event where a step never intersects (therefore
skipping an enter/exit trigger), use this fallback to detect if it is
in view
*/
function intersectViewportAbove(ref) {
var entry = ref[0];
updateDirection();
var isIntersecting = entry.isIntersecting;
var target = entry.target;
var index = getIndex(target);
var ss = stepStates[index];
if (
isIntersecting &&
direction === "down" &&
ss.direction !== "down" &&
ss.state !== "enter"
) {
notifyStepEnter(target, "down");
notifyStepExit(target, "down");
function disconnectObservers() {
steps.forEach(disconnectObserver);
}
}
function intersectViewportBelow(ref) {
var entry = ref[0];
updateDirection();
var isIntersecting = entry.isIntersecting;
var target = entry.target;
var index = getIndex(target);
var ss = stepStates[index];
if (
isIntersecting &&
direction === "up" &&
ss.direction === "down" &&
ss.state !== "enter"
) {
notifyStepEnter(target, "up");
notifyStepExit(target, "up");
function updateResizeObserver(step) {
const observer = new ResizeObserver(resizeStep);
observer.observe(step.node);
step.observers.resize = observer;
}
}
function intersectStepProgress(ref) {
var entry = ref[0];
updateDirection();
var isIntersecting = entry.isIntersecting;
var intersectionRatio = entry.intersectionRatio;
var boundingClientRect = entry.boundingClientRect;
var target = entry.target;
var bottom = boundingClientRect.bottom;
var bottomAdjusted = bottom - offsetMargin;
if (isIntersecting && bottomAdjusted >= 0) {
notifyStepProgress(target, +intersectionRatio);
function updateResizeObservers() {
steps.forEach(updateResizeObserver);
}
}
/* OBSERVER - CREATION */
// jump into viewport
function updateViewportAboveIO() {
io.viewportAbove = stepEl.map(function (el, i) {
var marginTop = pageH - stepOffsetTop[i];
var marginBottom = offsetMargin - viewH - stepOffsetHeight[i];
var rootMargin = marginTop + "px 0px " + marginBottom + "px 0px";
var options = { rootMargin: rootMargin };
// console.log(options);
var obs = new IntersectionObserver(intersectViewportAbove, options);
obs.observe(el);
return obs;
});
}
function updateStepObserver(step) {
const h = window.innerHeight;
const off = step.offset || globalOffset;
const factor = off.format === "pixels" ? 1 : h;
const offset = off.value * factor;
const marginTop = step.height / 2 - offset;
const marginBottom = step.height / 2 - (h - offset);
const rootMargin = `${marginTop}px 0px ${marginBottom}px 0px`;
function updateViewportBelowIO() {
io.viewportBelow = stepEl.map(function (el, i) {
var marginTop = -offsetMargin - stepOffsetHeight[i];
var marginBottom = offsetMargin - viewH + stepOffsetHeight[i] + pageH;
var rootMargin = marginTop + "px 0px " + marginBottom + "px 0px";
var options = { rootMargin: rootMargin };
// console.log(options);
var obs = new IntersectionObserver(intersectViewportBelow, options);
obs.observe(el);
return obs;
});
}
const threshold = 0.5;
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectStep, options);
// look above for intersection
function updateStepAboveIO() {
io.stepAbove = stepEl.map(function (el, i) {
var marginTop = -offsetMargin + stepOffsetHeight[i];
var marginBottom = offsetMargin - viewH;
var rootMargin = marginTop + "px 0px " + marginBottom + "px 0px";
var options = { rootMargin: rootMargin };
// console.log(options);
var obs = new IntersectionObserver(intersectStepAbove, options);
obs.observe(el);
return obs;
});
}
observer.observe(step.node);
step.observers.step = observer;
}
// look below for intersection
function updateStepBelowIO() {
io.stepBelow = stepEl.map(function (el, i) {
var marginTop = -offsetMargin;
var marginBottom = offsetMargin - viewH + stepOffsetHeight[i];
var rootMargin = marginTop + "px 0px " + marginBottom + "px 0px";
var options = { rootMargin: rootMargin };
// console.log(options);
var obs = new IntersectionObserver(intersectStepBelow, options);
obs.observe(el);
return obs;
});
}
function updateStepObservers() {
steps.forEach(updateStepObserver);
}
// progress progress tracker
function updateStepProgressIO() {
io.stepProgress = stepEl.map(function (el, i) {
var marginTop = stepOffsetHeight[i] - offsetMargin;
var marginBottom = -viewH + offsetMargin;
var rootMargin = marginTop + "px 0px " + marginBottom + "px 0px";
var threshold = createThreshold(stepOffsetHeight[i]);
var options = { rootMargin: rootMargin, threshold: threshold };
// console.log(options);
var obs = new IntersectionObserver(intersectStepProgress, options);
obs.observe(el);
return obs;
});
}
function updateProgressObserver(step) {
const h = window.innerHeight;
const off = step.offset || globalOffset;
const factor = off.format === "pixels" ? 1 : h;
const offset = off.value * factor;
const marginTop = -offset + step.height;
const marginBottom = offset - h;
const rootMargin = `${marginTop}px 0px ${marginBottom}px 0px`;
function updateIO() {
OBSERVER_NAMES.forEach(disconnectObserver);
const threshold = createProgressThreshold(step.height, progressThreshold);
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectProgress, options);
updateViewportAboveIO();
updateViewportBelowIO();
updateStepAboveIO();
updateStepBelowIO();
if (progressMode) { updateStepProgressIO(); }
}
/* SETUP FUNCTIONS */
function indexSteps() {
stepEl.forEach(function (el, i) { return el.setAttribute("data-scrollama-index", i); });
}
function setupStates() {
stepStates = stepEl.map(function () { return ({
direction: null,
state: null,
progress: 0
}); });
}
function addDebug() {
if (isDebug) { setup({ id: id, stepEl: stepEl, offsetVal: offsetVal }); }
}
function isYScrollable(element) {
var style = window.getComputedStyle(element);
return (
(style.overflowY === "scroll" || style.overflowY === "auto") &&
element.scrollHeight > element.clientHeight
);
}
// recursively search the DOM for a parent container with overflowY: scroll and fixed height
// ends at document
function anyScrollableParent(element) {
if (element && element.nodeType === 1) {
// check dom elements only, stop at document
// if a scrollable element is found return the element
// if not continue to next parent
return isYScrollable(element)
? element
: anyScrollableParent(element.parentNode);
observer.observe(step.node);
step.observers.progress = observer;
}
return false; // didn't find a scrollable parent
}
var S = {};
S.setup = function (ref) {
var step = ref.step;
var parent = ref.parent;
var offset = ref.offset; if ( offset === void 0 ) offset = 0.5;
var progress = ref.progress; if ( progress === void 0 ) progress = false;
var threshold = ref.threshold; if ( threshold === void 0 ) threshold = 4;
var debug = ref.debug; if ( debug === void 0 ) debug = false;
var order = ref.order; if ( order === void 0 ) order = true;
var once = ref.once; if ( once === void 0 ) once = false;
reset();
// create id unique to this scrollama instance
id = generateInstanceID();
stepEl = selectAll(step, parent);
if (!stepEl.length) {
err("no step elements");
return S;
function updateProgressObservers() {
steps.forEach(updateProgressObserver);
}
// ensure that no step has a scrollable parent element in the dom tree
// check current step for scrollable parent
// assume no scrollable parents to start
var scrollableParent = stepEl.reduce(
function (foundScrollable, s) { return foundScrollable || anyScrollableParent(s.parentNode); },
false
);
if (scrollableParent) {
console.error(
"scrollama error: step elements cannot be children of a scrollable element. Remove any css on the parent element with overflow: scroll; or overflow: auto; on elements with fixed height.",
scrollableParent
);
function updateObservers() {
disconnectObservers();
updateResizeObservers();
updateStepObservers();
if (isProgressMode) updateProgressObservers();
}
// options
isDebug = debug;
progressMode = progress;
preserveOrder = order;
triggerOnce = once;
/* SETUP */
const S = {};
S.offsetTrigger(offset);
progressThreshold = Math.max(1, +threshold);
S.setup = ({
step,
parent,
offset = 0.5,
threshold = 4,
progress = false,
order = false,
once = false,
debug = false,
}) => {
steps = selectAll(step, parent).map((node, index) => ({
index,
direction: undefined,
height: node.offsetHeight,
node,
observers: {},
offset: parseOffset(node.dataset.offset),
top: getOffsetTop(node),
progress: 0,
state: undefined,
}));
isReady = true;
if (!steps.length) {
err$1("no step elements");
return S;
}
// customize
addDebug();
indexSteps();
setupStates();
handleResize();
S.enable();
return S;
};
isProgressMode = progress;
isTriggerOnce = once;
progressThreshold = Math.max(1, +threshold);
globalOffset = parseOffset(offset);
reset();
indexSteps(steps);
handleEnable(true);
return S;
};
S.resize = function () {
handleResize();
return S;
};
S.enable = () => {
handleEnable(true);
return S;
};
S.enable = function () {
handleEnable(true);
return S;
};
S.disable = () => {
handleEnable(false);
return S;
};
S.disable = function () {
handleEnable(false);
return S;
};
S.destroy = () => {
handleEnable(false);
reset();
return S;
};
S.destroy = function () {
handleEnable(false);
reset();
};
S.offset = (x) => {
if (x === null || x === undefined) return globalOffset.value;
globalOffset = parseOffset(x);
updateObservers();
return S;
};
S.offsetTrigger = function (x) {
if (x === null) { return offsetVal; }
S.onStepEnter = (f) => {
if (typeof f === "function") cb.stepEnter = f;
else err$1("onStepEnter requires a function");
return S;
};
if (typeof x === "number") {
format = "percent";
if (x > 1) { err("offset value is greater than 1. Fallback to 1."); }
if (x < 0) { err("offset value is lower than 0. Fallback to 0."); }
offsetVal = Math.min(Math.max(0, x), 1);
} else if (typeof x === "string" && x.indexOf("px") > 0) {
var v = +x.replace("px", "");
if (!isNaN(v)) {
format = "pixels";
offsetVal = v;
} else {
err("offset value must be in 'px' format. Fallback to 0.5.");
offsetVal = 0.5;
}
} else {
err("offset value does not include 'px'. Fallback to 0.5.");
offsetVal = 0.5;
}
return S;
};
S.onStepExit = (f) => {
if (typeof f === "function") cb.stepExit = f;
else err$1("onStepExit requires a function");
return S;
};
S.onStepEnter = function (f) {
if (typeof f === "function") { cb.stepEnter = f; }
else { err("onStepEnter requires a function"); }
S.onStepProgress = (f) => {
if (typeof f === "function") cb.stepProgress = f;
else err$1("onStepProgress requires a function");
return S;
};
return S;
};
}
S.onStepExit = function (f) {
if (typeof f === "function") { cb.stepExit = f; }
else { err("onStepExit requires a function"); }
return S;
};
setupScroll();
S.onStepProgress = function (f) {
if (typeof f === "function") { cb.stepProgress = f; }
else { err("onStepProgress requires a function"); }
return S;
};
return scrollama;
return S;
}
return scrollama;
})));

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.scrollama=t()}(this,function(){"use strict";function e(e){return"scrollama__debug-offset--"+e}function t(t){!function(t){var n=t.id,o=t.offsetVal,r=t.stepClass,i=document.createElement("div");i.id=e(n),i.className="scrollama__debug-offset",i.style.position="fixed",i.style.left="0",i.style.width="100%",i.style.height="0",i.style.borderTop="2px dashed black",i.style.zIndex="9999";var s=document.createElement("p");s.innerHTML='".'+r+'" trigger: <span>'+o+"</span>",s.style.fontSize="12px",s.style.fontFamily="monospace",s.style.color="black",s.style.margin="0",s.style.padding="6px",i.appendChild(s),document.body.appendChild(i)}({id:t.id,offsetVal:t.offsetVal,stepClass:t.stepEl[0].className})}function n(e){var t=e.id,n=e.index,o=e.state,r="scrollama__debug-step--"+t+"-"+n,i=document.getElementById(r+"_above"),s=document.getElementById(r+"_below"),a="enter"===o?"block":"none";i&&(i.style.display=a),s&&(s.style.display=a)}return function(){var o=["stepAbove","stepBelow","stepProgress","viewportAbove","viewportBelow"],r={},i={},s=null,a=[],f=[],c=[],l=[],u=0,p=0,d=0,v=0,g=0,m=0,x=!1,b=!1,w=!1,h=!1,y=!1,E=!1,M="down",I="percent",A=[];function C(e){console.error("scrollama error: "+e)}function O(){r={stepEnter:function(){},stepExit:function(){},stepProgress:function(){}},i={}}function S(e){return e.getBoundingClientRect().top+window.pageYOffset-(document.body.clientTop||0)}function B(e){return+e.getAttribute("data-scrollama-index")}function H(){window.pageYOffset>g?M="down":window.pageYOffset<g&&(M="up"),g=window.pageYOffset}function k(e){i[e]&&i[e].forEach(function(e){return e.disconnect()})}function _(){var t,n;d=window.innerHeight,t=document.body,n=document.documentElement,v=Math.max(t.scrollHeight,t.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight),p=u*("pixels"===I?1:d),x&&(f=a.map(function(e){return e.getBoundingClientRect().height}),c=a.map(S),b&&D()),w&&function(t){var n=t.id,o=t.offsetMargin,r=t.offsetVal,i="pixels"===t.format?"px":"",s=e(n),a=document.getElementById(s);a.style.top=o+"px",a.querySelector("span").innerText=""+r+i}({id:s,offsetMargin:p,offsetVal:u,format:I})}function N(e){if(e&&!b){if(!x)return C("scrollama error: enable() called before scroller was ready"),void(b=!1);D()}!e&&b&&o.forEach(k),b=e}function P(e,t){var n=B(e);void 0!==t&&(l[n].progress=t);var o={element:e,index:n,progress:l[n].progress};"enter"===l[n].state&&r.stepProgress(o)}function R(e,t){if("above"===t)for(var n=0;n<e;n+=1){var o=l[n];"enter"!==o.state&&"down"!==o.direction?(T(a[n],"down",!1),q(a[n],"down")):"enter"===o.state&&q(a[n],"down")}else if("below"===t)for(var r=l.length-1;r>e;r-=1){var i=l[r];"enter"===i.state&&q(a[r],"up"),"down"===i.direction&&(T(a[r],"up",!1),q(a[r],"up"))}}function T(e,t,o){void 0===o&&(o=!0);var i=B(e),a={element:e,index:i,direction:t};l[i].direction=t,l[i].state="enter",y&&o&&"down"===t&&R(i,"above"),y&&o&&"up"===t&&R(i,"below"),r.stepEnter&&!A[i]&&(r.stepEnter(a,l),w&&n({id:s,index:i,state:"enter"}),E&&(A[i]=!0)),h&&P(e)}function q(e,t){var o=B(e),i={element:e,index:o,direction:t};h&&("down"===t&&l[o].progress<1?P(e,1):"up"===t&&l[o].progress>0&&P(e,0)),l[o].direction=t,l[o].state="exit",r.stepExit(i,l),w&&n({id:s,index:o,state:"exit"})}function V(e){var t=e[0];H();var n=t.isIntersecting,o=t.boundingClientRect,r=t.target,i=o.top,s=o.bottom,a=i-p,f=s-p,c=B(r),u=l[c];n&&a<=0&&f>=0&&"down"===M&&"enter"!==u.state&&T(r,M),!n&&a>0&&"up"===M&&"enter"===u.state&&q(r,M)}function Y(e){var t=e[0];H();var n=t.isIntersecting,o=t.boundingClientRect,r=t.target,i=o.top,s=o.bottom,a=i-p,f=s-p,c=B(r),u=l[c];n&&a<=0&&f>=0&&"up"===M&&"enter"!==u.state&&T(r,M),!n&&f<0&&"down"===M&&"enter"===u.state&&q(r,M)}function F(e){var t=e[0];H();var n=t.isIntersecting,o=t.target,r=B(o),i=l[r];n&&"down"===M&&"down"!==i.direction&&"enter"!==i.state&&(T(o,"down"),q(o,"down"))}function j(e){var t=e[0];H();var n=t.isIntersecting,o=t.target,r=B(o),i=l[r];n&&"up"===M&&"down"===i.direction&&"enter"!==i.state&&(T(o,"up"),q(o,"up"))}function z(e){var t=e[0];H();var n=t.isIntersecting,o=t.intersectionRatio,r=t.boundingClientRect,i=t.target,s=r.bottom;n&&s-p>=0&&P(i,+o)}function L(){i.stepProgress=a.map(function(e,t){var n=f[t]-p+"px 0px "+(-d+p)+"px 0px",o=function(e){for(var t=Math.ceil(e/m),n=[],o=1/t,r=0;r<t;r+=1)n.push(r*o);return n}(f[t]),r=new IntersectionObserver(z,{rootMargin:n,threshold:o});return r.observe(e),r})}function D(){o.forEach(k),i.viewportAbove=a.map(function(e,t){var n=v-c[t],o=p-d-f[t],r=new IntersectionObserver(F,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),i.viewportBelow=a.map(function(e,t){var n=-p-f[t],o=p-d+f[t]+v,r=new IntersectionObserver(j,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),i.stepAbove=a.map(function(e,t){var n=-p+f[t],o=new IntersectionObserver(V,{rootMargin:n+"px 0px "+(p-d)+"px 0px"});return o.observe(e),o}),i.stepBelow=a.map(function(e,t){var n=-p,o=p-d+f[t],r=new IntersectionObserver(Y,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),h&&L()}function G(e){return!(!e||1!==e.nodeType)&&(function(e){var t=window.getComputedStyle(e);return("scroll"===t.overflowY||"auto"===t.overflowY)&&e.scrollHeight>e.clientHeight}(e)?e:G(e.parentNode))}var J={};return J.setup=function(e){var n=e.step,o=e.parent,r=e.offset;void 0===r&&(r=.5);var i=e.progress;void 0===i&&(i=!1);var f=e.threshold;void 0===f&&(f=4);var c=e.debug;void 0===c&&(c=!1);var p=e.order;void 0===p&&(p=!0);var d,v,g,b=e.once;if(void 0===b&&(b=!1),O(),v=(d="abcdefghijklmnopqrstuv").length,g=Date.now(),s=""+[0,0,0].map(function(e){return d[Math.floor(Math.random()*v)]}).join("")+g,!(a=function(e,t){return void 0===t&&(t=document),"string"==typeof e?Array.from(t.querySelectorAll(e)):e instanceof Element?[e]:e instanceof NodeList?Array.from(e):e instanceof Array?e:[]}(n,o)).length)return C("no step elements"),J;var M=a.reduce(function(e,t){return e||G(t.parentNode)},!1);return M&&console.error("scrollama error: step elements cannot be children of a scrollable element. Remove any css on the parent element with overflow: scroll; or overflow: auto; on elements with fixed height.",M),w=c,h=i,y=p,E=b,J.offsetTrigger(r),m=Math.max(1,+f),x=!0,w&&t({id:s,stepEl:a,offsetVal:u}),a.forEach(function(e,t){return e.setAttribute("data-scrollama-index",t)}),l=a.map(function(){return{direction:null,state:null,progress:0}}),_(),J.enable(),J},J.resize=function(){return _(),J},J.enable=function(){return N(!0),J},J.disable=function(){return N(!1),J},J.destroy=function(){N(!1),O()},J.offsetTrigger=function(e){if(null===e)return u;if("number"==typeof e)I="percent",e>1&&C("offset value is greater than 1. Fallback to 1."),e<0&&C("offset value is lower than 0. Fallback to 0."),u=Math.min(Math.max(0,e),1);else if("string"==typeof e&&e.indexOf("px")>0){var t=+e.replace("px","");isNaN(t)?(C("offset value must be in 'px' format. Fallback to 0.5."),u=.5):(I="pixels",u=t)}else C("offset value does not include 'px'. Fallback to 0.5."),u=.5;return J},J.onStepEnter=function(e){return"function"==typeof e?r.stepEnter=e:C("onStepEnter requires a function"),J},J.onStepExit=function(e){return"function"==typeof e?r.stepExit=e:C("onStepExit requires a function"),J},J.onStepProgress=function(e){return"function"==typeof e?r.stepProgress=e:C("onStepProgress requires a function"),J},J}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).scrollama=t()}(this,function(){"use strict";function w(e){console.error(`scrollama error: ${e}`)}function y(e){return+e.getAttribute("data-scrollama-index")}function O(e){if("string"==typeof e&&0<e.indexOf("px")){var t=+e.replace("px","");return isNaN(t)?(err("offset value must be in 'px' format. Fallback to 0.5."),{format:"percent",value:.5}):{format:"pixels",value:t}}return"number"!=typeof e&&isNaN(+e)?null:(1<e&&err("offset value is greater than 1. Fallback to 1."),e<0&&err("offset value is lower than 0. Fallback to 0."),{format:"percent",value:Math.min(Math.max(0,e),1)})}let e=0,t=0,S;function A(){e!==window.pageYOffset&&(e=window.pageYOffset,e>t?S="down":e<t&&(S="up"),t=e)}return document.addEventListener("scroll",A),function(){let o={},i=[],a,f=0,t=!1,c=!1,u=!1,r=[];function p(){o={stepEnter:()=>{},stepExit:()=>{},stepProgress:()=>{}},r=[]}function l(e){e&&!t&&b(),!e&&t&&v(),t=e}function s(e,t){var n=y(e);const r=i[n];void 0!==t&&(r.progress=t);t={element:e,index:n,progress:t,direction:S};"enter"===r.state&&o.stepProgress(t)}function n([e]){var t=y(e.target);const n=i[t];e=e.target.offsetHeight;e!==n.height&&(n.height=e,h(n),m(n),x(n))}function d([e]){A();var{isIntersecting:t,target:e}=e;(t?function(e){var t=y(e);const n=i[t];e={element:e,index:t,direction:S},n.direction=S,n.state="enter",r[t]||o.stepEnter(e),u&&(r[t]=!0)}:function(e){var t=y(e);const n=i[t];n.state&&(t={element:e,index:t,direction:S},c&&("down"===S&&n.progress<1?s(e,1):"up"===S&&0<n.progress&&s(e,0)),n.direction=S,n.state="exit",o.stepExit(t))})(e)}function g([e]){var t=y(e.target),n=i[t],{isIntersecting:r,intersectionRatio:t,target:e}=e;r&&"enter"===n.state&&s(e,t)}function h({observers:t}){Object.keys(t).map(e=>{t[e].disconnect()})}function v(){i.forEach(h)}function x(e){const t=new ResizeObserver(n);t.observe(e.node),e.observers.resize=t}function m(e){var t=window.innerHeight,n=e.offset||a,r="pixels"===n.format?1:t,n=n.value*r,r=e.height/2-n,n=e.height/2-(t-n);const o=new IntersectionObserver(d,{rootMargin:`${r}px 0px ${n}px 0px`,threshold:.5});o.observe(e.node),e.observers.step=o}function e(e){var t=window.innerHeight,n=e.offset||a,r="pixels"===n.format?1:t,r=n.value*r,r=`${-r+e.height}px 0px ${r-t}px 0px`,t=function(e,t){var n=Math.ceil(e/t);const r=[];var o=1/n;for(let e=0;e<n+1;e+=1)r.push(e*o);return r}(e.height,f);const o=new IntersectionObserver(g,{rootMargin:r,threshold:t});o.observe(e.node),e.observers.progress=o}function b(){v(),i.forEach(x),i.forEach(m),c&&i.forEach(e)}const E={};return E.setup=({step:e,parent:t,offset:n=.5,threshold:r=4,progress:o=!1,once:s=!1})=>{return i=([e,t=document]=[e,t],("string"==typeof e?Array.from(t.querySelectorAll(e)):e instanceof Element?[e]:e instanceof NodeList?Array.from(e):e instanceof Array?e:[]).map((e,t)=>({index:t,direction:void 0,height:e.offsetHeight,node:e,observers:{},offset:O(e.dataset.offset),top:function(e){var{top:e}=e.getBoundingClientRect();return e+window.pageYOffset-(document.body.clientTop||0)}(e),progress:0,state:void 0}))),i.length?(c=o,u=s,f=Math.max(1,+r),a=O(n),p(),i.forEach(e=>e.node.setAttribute("data-scrollama-index",e.index)),l(!0)):w("no step elements"),E},E.enable=()=>(l(!0),E),E.disable=()=>(l(!1),E),E.destroy=()=>(l(!1),p(),E),E.offset=e=>null==e?a.value:(a=O(e),b(),E),E.onStepEnter=e=>("function"==typeof e?o.stepEnter=e:w("onStepEnter requires a function"),E),E.onStepExit=e=>("function"==typeof e?o.stepExit=e:w("onStepExit requires a function"),E),E.onStepProgress=e=>("function"==typeof e?o.stepProgress=e:w("onStepProgress requires a function"),E),E}});

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.scrollama=t()}(this,function(){"use strict";function e(e){return"scrollama__debug-offset--"+e}function t(t){!function(t){var n=t.id,o=t.offsetVal,r=t.stepClass,i=document.createElement("div");i.id=e(n),i.className="scrollama__debug-offset",i.style.position="fixed",i.style.left="0",i.style.width="100%",i.style.height="0",i.style.borderTop="2px dashed black",i.style.zIndex="9999";var s=document.createElement("p");s.innerHTML='".'+r+'" trigger: <span>'+o+"</span>",s.style.fontSize="12px",s.style.fontFamily="monospace",s.style.color="black",s.style.margin="0",s.style.padding="6px",i.appendChild(s),document.body.appendChild(i)}({id:t.id,offsetVal:t.offsetVal,stepClass:t.stepEl[0].className})}function n(e){var t=e.id,n=e.index,o=e.state,r="scrollama__debug-step--"+t+"-"+n,i=document.getElementById(r+"_above"),s=document.getElementById(r+"_below"),a="enter"===o?"block":"none";i&&(i.style.display=a),s&&(s.style.display=a)}return function(){var o=["stepAbove","stepBelow","stepProgress","viewportAbove","viewportBelow"],r={},i={},s=null,a=[],f=[],c=[],l=[],u=0,p=0,d=0,v=0,g=0,m=0,x=!1,b=!1,w=!1,h=!1,y=!1,E=!1,M="down",I="percent",A=[];function C(e){console.error("scrollama error: "+e)}function O(){r={stepEnter:function(){},stepExit:function(){},stepProgress:function(){}},i={}}function S(e){return e.getBoundingClientRect().top+window.pageYOffset-(document.body.clientTop||0)}function B(e){return+e.getAttribute("data-scrollama-index")}function H(){window.pageYOffset>g?M="down":window.pageYOffset<g&&(M="up"),g=window.pageYOffset}function k(e){i[e]&&i[e].forEach(function(e){return e.disconnect()})}function _(){var t,n;d=window.innerHeight,t=document.body,n=document.documentElement,v=Math.max(t.scrollHeight,t.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight),p=u*("pixels"===I?1:d),x&&(f=a.map(function(e){return e.getBoundingClientRect().height}),c=a.map(S),b&&D()),w&&function(t){var n=t.id,o=t.offsetMargin,r=t.offsetVal,i="pixels"===t.format?"px":"",s=e(n),a=document.getElementById(s);a.style.top=o+"px",a.querySelector("span").innerText=""+r+i}({id:s,offsetMargin:p,offsetVal:u,format:I})}function N(e){if(e&&!b){if(!x)return C("scrollama error: enable() called before scroller was ready"),void(b=!1);D()}!e&&b&&o.forEach(k),b=e}function P(e,t){var n=B(e);void 0!==t&&(l[n].progress=t);var o={element:e,index:n,progress:l[n].progress};"enter"===l[n].state&&r.stepProgress(o)}function R(e,t){if("above"===t)for(var n=0;n<e;n+=1){var o=l[n];"enter"!==o.state&&"down"!==o.direction?(T(a[n],"down",!1),q(a[n],"down")):"enter"===o.state&&q(a[n],"down")}else if("below"===t)for(var r=l.length-1;r>e;r-=1){var i=l[r];"enter"===i.state&&q(a[r],"up"),"down"===i.direction&&(T(a[r],"up",!1),q(a[r],"up"))}}function T(e,t,o){void 0===o&&(o=!0);var i=B(e),a={element:e,index:i,direction:t};l[i].direction=t,l[i].state="enter",y&&o&&"down"===t&&R(i,"above"),y&&o&&"up"===t&&R(i,"below"),r.stepEnter&&!A[i]&&(r.stepEnter(a,l),w&&n({id:s,index:i,state:"enter"}),E&&(A[i]=!0)),h&&P(e)}function q(e,t){var o=B(e),i={element:e,index:o,direction:t};h&&("down"===t&&l[o].progress<1?P(e,1):"up"===t&&l[o].progress>0&&P(e,0)),l[o].direction=t,l[o].state="exit",r.stepExit(i,l),w&&n({id:s,index:o,state:"exit"})}function V(e){var t=e[0];H();var n=t.isIntersecting,o=t.boundingClientRect,r=t.target,i=o.top,s=o.bottom,a=i-p,f=s-p,c=B(r),u=l[c];n&&a<=0&&f>=0&&"down"===M&&"enter"!==u.state&&T(r,M),!n&&a>0&&"up"===M&&"enter"===u.state&&q(r,M)}function Y(e){var t=e[0];H();var n=t.isIntersecting,o=t.boundingClientRect,r=t.target,i=o.top,s=o.bottom,a=i-p,f=s-p,c=B(r),u=l[c];n&&a<=0&&f>=0&&"up"===M&&"enter"!==u.state&&T(r,M),!n&&f<0&&"down"===M&&"enter"===u.state&&q(r,M)}function F(e){var t=e[0];H();var n=t.isIntersecting,o=t.target,r=B(o),i=l[r];n&&"down"===M&&"down"!==i.direction&&"enter"!==i.state&&(T(o,"down"),q(o,"down"))}function j(e){var t=e[0];H();var n=t.isIntersecting,o=t.target,r=B(o),i=l[r];n&&"up"===M&&"down"===i.direction&&"enter"!==i.state&&(T(o,"up"),q(o,"up"))}function z(e){var t=e[0];H();var n=t.isIntersecting,o=t.intersectionRatio,r=t.boundingClientRect,i=t.target,s=r.bottom;n&&s-p>=0&&P(i,+o)}function L(){i.stepProgress=a.map(function(e,t){var n=f[t]-p+"px 0px "+(-d+p)+"px 0px",o=function(e){for(var t=Math.ceil(e/m),n=[],o=1/t,r=0;r<t;r+=1)n.push(r*o);return n}(f[t]),r=new IntersectionObserver(z,{rootMargin:n,threshold:o});return r.observe(e),r})}function D(){o.forEach(k),i.viewportAbove=a.map(function(e,t){var n=v-c[t],o=p-d-f[t],r=new IntersectionObserver(F,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),i.viewportBelow=a.map(function(e,t){var n=-p-f[t],o=p-d+f[t]+v,r=new IntersectionObserver(j,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),i.stepAbove=a.map(function(e,t){var n=-p+f[t],o=new IntersectionObserver(V,{rootMargin:n+"px 0px "+(p-d)+"px 0px"});return o.observe(e),o}),i.stepBelow=a.map(function(e,t){var n=-p,o=p-d+f[t],r=new IntersectionObserver(Y,{rootMargin:n+"px 0px "+o+"px 0px"});return r.observe(e),r}),h&&L()}function G(e){return!(!e||1!==e.nodeType)&&(function(e){var t=window.getComputedStyle(e);return("scroll"===t.overflowY||"auto"===t.overflowY)&&e.scrollHeight>e.clientHeight}(e)?e:G(e.parentNode))}var J={};return J.setup=function(e){var n=e.step,o=e.parent,r=e.offset;void 0===r&&(r=.5);var i=e.progress;void 0===i&&(i=!1);var f=e.threshold;void 0===f&&(f=4);var c=e.debug;void 0===c&&(c=!1);var p=e.order;void 0===p&&(p=!0);var d,v,g,b=e.once;if(void 0===b&&(b=!1),O(),v=(d="abcdefghijklmnopqrstuv").length,g=Date.now(),s=""+[0,0,0].map(function(e){return d[Math.floor(Math.random()*v)]}).join("")+g,!(a=function(e,t){return void 0===t&&(t=document),"string"==typeof e?Array.from(t.querySelectorAll(e)):e instanceof Element?[e]:e instanceof NodeList?Array.from(e):e instanceof Array?e:[]}(n,o)).length)return C("no step elements"),J;var M=a.reduce(function(e,t){return e||G(t.parentNode)},!1);return M&&console.error("scrollama error: step elements cannot be children of a scrollable element. Remove any css on the parent element with overflow: scroll; or overflow: auto; on elements with fixed height.",M),w=c,h=i,y=p,E=b,J.offsetTrigger(r),m=Math.max(1,+f),x=!0,w&&t({id:s,stepEl:a,offsetVal:u}),a.forEach(function(e,t){return e.setAttribute("data-scrollama-index",t)}),l=a.map(function(){return{direction:null,state:null,progress:0}}),_(),J.enable(),J},J.resize=function(){return _(),J},J.enable=function(){return N(!0),J},J.disable=function(){return N(!1),J},J.destroy=function(){N(!1),O()},J.offsetTrigger=function(e){if(null===e)return u;if("number"==typeof e)I="percent",e>1&&C("offset value is greater than 1. Fallback to 1."),e<0&&C("offset value is lower than 0. Fallback to 0."),u=Math.min(Math.max(0,e),1);else if("string"==typeof e&&e.indexOf("px")>0){var t=+e.replace("px","");isNaN(t)?(C("offset value must be in 'px' format. Fallback to 0.5."),u=.5):(I="pixels",u=t)}else C("offset value does not include 'px'. Fallback to 0.5."),u=.5;return J},J.onStepEnter=function(e){return"function"==typeof e?r.stepEnter=e:C("onStepEnter requires a function"),J},J.onStepExit=function(e){return"function"==typeof e?r.stepExit=e:C("onStepExit requires a function"),J},J.onStepProgress=function(e){return"function"==typeof e?r.stepProgress=e:C("onStepProgress requires a function"),J},J}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).scrollama=t()}(this,function(){"use strict";function w(e){console.error(`scrollama error: ${e}`)}function y(e){return+e.getAttribute("data-scrollama-index")}function O(e){if("string"==typeof e&&0<e.indexOf("px")){var t=+e.replace("px","");return isNaN(t)?(err("offset value must be in 'px' format. Fallback to 0.5."),{format:"percent",value:.5}):{format:"pixels",value:t}}return"number"!=typeof e&&isNaN(+e)?null:(1<e&&err("offset value is greater than 1. Fallback to 1."),e<0&&err("offset value is lower than 0. Fallback to 0."),{format:"percent",value:Math.min(Math.max(0,e),1)})}let e=0,t=0,S;function A(){e!==window.pageYOffset&&(e=window.pageYOffset,e>t?S="down":e<t&&(S="up"),t=e)}return document.addEventListener("scroll",A),function(){let o={},i=[],a,f=0,t=!1,c=!1,u=!1,r=[];function p(){o={stepEnter:()=>{},stepExit:()=>{},stepProgress:()=>{}},r=[]}function l(e){e&&!t&&b(),!e&&t&&v(),t=e}function s(e,t){var n=y(e);const r=i[n];void 0!==t&&(r.progress=t);t={element:e,index:n,progress:t,direction:S};"enter"===r.state&&o.stepProgress(t)}function n([e]){var t=y(e.target);const n=i[t];e=e.target.offsetHeight;e!==n.height&&(n.height=e,h(n),m(n),x(n))}function d([e]){A();var{isIntersecting:t,target:e}=e;(t?function(e){var t=y(e);const n=i[t];e={element:e,index:t,direction:S},n.direction=S,n.state="enter",r[t]||o.stepEnter(e),u&&(r[t]=!0)}:function(e){var t=y(e);const n=i[t];n.state&&(t={element:e,index:t,direction:S},c&&("down"===S&&n.progress<1?s(e,1):"up"===S&&0<n.progress&&s(e,0)),n.direction=S,n.state="exit",o.stepExit(t))})(e)}function g([e]){var t=y(e.target),n=i[t],{isIntersecting:r,intersectionRatio:t,target:e}=e;r&&"enter"===n.state&&s(e,t)}function h({observers:t}){Object.keys(t).map(e=>{t[e].disconnect()})}function v(){i.forEach(h)}function x(e){const t=new ResizeObserver(n);t.observe(e.node),e.observers.resize=t}function m(e){var t=window.innerHeight,n=e.offset||a,r="pixels"===n.format?1:t,n=n.value*r,r=e.height/2-n,n=e.height/2-(t-n);const o=new IntersectionObserver(d,{rootMargin:`${r}px 0px ${n}px 0px`,threshold:.5});o.observe(e.node),e.observers.step=o}function e(e){var t=window.innerHeight,n=e.offset||a,r="pixels"===n.format?1:t,r=n.value*r,r=`${-r+e.height}px 0px ${r-t}px 0px`,t=function(e,t){var n=Math.ceil(e/t);const r=[];var o=1/n;for(let e=0;e<n+1;e+=1)r.push(e*o);return r}(e.height,f);const o=new IntersectionObserver(g,{rootMargin:r,threshold:t});o.observe(e.node),e.observers.progress=o}function b(){v(),i.forEach(x),i.forEach(m),c&&i.forEach(e)}const E={};return E.setup=({step:e,parent:t,offset:n=.5,threshold:r=4,progress:o=!1,once:s=!1})=>{return i=([e,t=document]=[e,t],("string"==typeof e?Array.from(t.querySelectorAll(e)):e instanceof Element?[e]:e instanceof NodeList?Array.from(e):e instanceof Array?e:[]).map((e,t)=>({index:t,direction:void 0,height:e.offsetHeight,node:e,observers:{},offset:O(e.dataset.offset),top:function(e){var{top:e}=e.getBoundingClientRect();return e+window.pageYOffset-(document.body.clientTop||0)}(e),progress:0,state:void 0}))),i.length?(c=o,u=s,f=Math.max(1,+r),a=O(n),p(),i.forEach(e=>e.node.setAttribute("data-scrollama-index",e.index)),l(!0)):w("no step elements"),E},E.enable=()=>(l(!0),E),E.disable=()=>(l(!1),E),E.destroy=()=>(l(!1),p(),E),E.offset=e=>null==e?a.value:(a=O(e),b(),E),E.onStepEnter=e=>("function"==typeof e?o.stepEnter=e:w("onStepEnter requires a function"),E),E.onStepExit=e=>("function"==typeof e?o.stepExit=e:w("onStepExit requires a function"),E),E.onStepProgress=e=>("function"==typeof e?o.stepProgress=e:w("onStepProgress requires a function"),E),E}});

@@ -1,3 +0,3 @@

import init from './src/init.js';
import entry from "./src/entry";
export default init;
export default entry;
{
"name": "scrollama",
"version": "2.2.2",
"version": "3.0.0",
"description": "Lightweight scrollytelling library using IntersectionObserver",

@@ -38,17 +38,10 @@ "main": "build/scrollama.js",

"devDependencies": {
"babel-eslint": "10.0.3",
"cross-env": "^5.1.3",
"eslint": "6.6.0",
"eslint-config-airbnb-base": "14.0.0",
"eslint-config-prettier": "6.6.0",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-prettier": "3.1.1",
"prettier": "1.19.1",
"rollup": "^0.55.3",
"rollup-plugin-buble": "^0.18.0",
"rollup-plugin-commonjs": "^8.3.0",
"rollup-plugin-filesize": "^1.5.0",
"rollup-plugin-node-resolve": "^3.0.2",
"rollup-plugin-uglify": "^3.0.0"
"cross-env": "^7.0.3",
"rollup": "^1.32.1",
"rollup-plugin-buble": "^0.19.8",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-filesize": "^9.1.1",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-uglify": "^6.0.4"
}
}

@@ -1,3 +0,21 @@

###### scrollama.js
# v3 roadmap
- revamp intersection observer
- use resize observer for auto resize (polyfill note)
- offset
- progress
- custom offset trigger
- progress enter/exit
- sinngle rAF scroll updates
- deprecate resize
- auto-update on offset trigger date (rename to offset)
- better debugger
- dont disconnect resize
- update docs
- update examples (no stickyfill, mobile pattern obsolete?)
- scrollable check needed? (maybe a soft warning)
- preserve order: try adding queue, store how it was detected last time or position, position jump checks? (only works with ordered steps + global offset?)
<img src="https://russellgoldenberg.github.io/scrollama/logo.png" width="160" alt="scrollama.js"/>

@@ -121,7 +139,7 @@

- `threshold` (number, 1+): The granularity of the progress interval in pixels (smaller = more granular). **(default: 4)**
- `order` (boolean): Fire previous step triggers if they were jumped. **(default: true)**
- `order` (boolean): Fire previous step triggers if they were jumped. **(default: false)**
- `once` (boolean): Only trigger the step to enter once then remove listener. **(default: false)**
- `debug` (boolean): Whether to show visual debugging tools or not. **(default:
false)**
- `parent` (HTMLElement[]): Parent element for step selector (use if you steps are in shadow DOM) **(default: undefined)**
- parent (HTMLElement[]): Parent element for step selector (use if you steps are in shadow DOM). **(default: undefined)**

@@ -166,2 +184,4 @@ #### scrollama.onStepEnter(callback)

`direction`: 'up' or 'down'
#### scrollama.offsetTrigger([number or string])

@@ -231,2 +251,3 @@

- [tuckergordon](https://github.com/tuckergordon)
- [emma-k-alexandra](https://github.com/emma-k-alexandra)

@@ -237,3 +258,3 @@ ### License

Copyright (c) 2020 Russell Goldenberg
Copyright (c) 2021 Russell Goldenberg

@@ -240,0 +261,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of

@@ -1,10 +0,9 @@

import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';
import buble from 'rollup-plugin-buble';
import uglify from 'rollup-plugin-uglify';
import filesize from 'rollup-plugin-filesize';
import commonjs from "rollup-plugin-commonjs";
import resolve from "rollup-plugin-node-resolve";
import { uglify } from "rollup-plugin-uglify";
import filesize from "rollup-plugin-filesize";
const isProd = process.env.NODE_ENV === 'production';
const isProd = process.env.NODE_ENV === "production";
const file = `build/scrollama${isProd ? '.min' : ''}.js`;
const file = `build/scrollama${isProd ? ".min" : ""}.js`;

@@ -14,21 +13,19 @@ const plugins = [

jsnext: true,
main: true
main: true,
}),
commonjs({
sourceMap: false
sourceMap: false,
}),
buble(),
filesize()
filesize(),
isProd && uglify(),
];
isProd && plugins.push(uglify());
export default {
input: 'index.js',
input: "index.js",
output: {
file,
format: 'umd',
name: 'scrollama'
format: "umd",
name: "scrollama",
},
plugins
plugins,
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc