New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.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 3.0.0 to 3.0.1

docs/custom-offset/index.html

480

build/scrollama.js

@@ -23,2 +23,48 @@ (function (global, factory) {

// SETUP
function create(className) {
const el = document.createElement("div");
el.className = `scrollama__debug-step ${className}`;
el.style.position = "fixed";
el.style.left = "0";
el.style.width = "100%";
el.style.zIndex = "9999";
el.style.borderTop = "2px solid black";
el.style.borderBottom = "2px solid black";
const p = document.createElement("p");
p.style.position = "absolute";
p.style.left = "0";
p.style.height = "1px";
p.style.width = "100%";
p.style.borderTop = "1px dashed black";
el.appendChild(p);
document.body.appendChild(el);
return el;
}
// UPDATE
function update({ id, step, marginTop }) {
const { index, height } = step;
const className = `scrollama__debug-step--${id}-${index}`;
let el = document.querySelector(`.${className}`);
if (!el) el = create(className);
el.style.top = `${marginTop * -1}px`;
el.style.height = `${height}px`;
el.querySelector("p").style.top = `${height / 2}px`;
}
function generateId() {
const alphabet = "abcdefghijklmnopqrstuvwxyz";
const date = Date.now();
const result = [];
for (let i = 0; i < 6; i += 1) {
const char = alphabet[Math.floor(Math.random() * alphabet.length)];
result.push(char);
}
return `${result.join("")}${date}`;
}
function err$1(msg) {

@@ -88,261 +134,267 @@ console.error(`scrollama error: ${msg}`);

function scrollama() {
let cb = {};
let steps = [];
let globalOffset;
let cb = {};
let progressThreshold = 0;
let id = generateId();
let steps = [];
let globalOffset;
let isEnabled = false;
let isProgressMode = false;
let isTriggerOnce = false;
let progressThreshold = 0;
let exclude = [];
let isEnabled = false;
let isProgress = false;
let isDebug = false;
let isTriggerOnce = false;
/* HELPERS */
function reset() {
cb = {
stepEnter: () => {},
stepExit: () => {},
stepProgress: () => {},
};
exclude = [];
}
let exclude = [];
function handleEnable(shouldEnable) {
if (shouldEnable && !isEnabled) updateObservers();
if (!shouldEnable && isEnabled) disconnectObservers();
isEnabled = shouldEnable;
}
/* HELPERS */
function reset() {
cb = {
stepEnter: () => { },
stepExit: () => { },
stepProgress: () => { },
};
exclude = [];
}
/* 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);
}
function handleEnable(shouldEnable) {
if (shouldEnable && !isEnabled) updateObservers();
if (!shouldEnable && isEnabled) disconnectObservers();
isEnabled = shouldEnable;
}
function notifyStepEnter(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
/* 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);
}
step.direction = direction;
step.state = "enter";
function notifyStepEnter(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "above");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "below");
step.direction = direction;
step.state = "enter";
if (!exclude[index]) cb.stepEnter(response);
if (isTriggerOnce) exclude[index] = true;
}
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "above");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "below");
function notifyStepExit(element, check = true) {
const index = getIndex(element);
const step = steps[index];
if (!exclude[index]) cb.stepEnter(response);
if (isTriggerOnce) exclude[index] = true;
}
if (!step.state) return false;
function notifyStepExit(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
if (!step.state) return false;
if (isProgressMode) {
if (direction === "down" && step.progress < 1) notifyProgress(element, 1);
else if (direction === "up" && step.progress > 0)
notifyProgress(element, 0);
}
const response = { element, index, direction };
step.direction = direction;
step.state = "exit";
if (isProgress) {
if (direction === "down" && step.progress < 1) notifyProgress(element, 1);
else if (direction === "up" && step.progress > 0)
notifyProgress(element, 0);
}
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "below");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "above");
step.direction = direction;
step.state = "exit";
cb.stepExit(response);
}
cb.stepExit(response);
}
/* 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);
}
}
/* 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);
}
}
function intersectStep([entry]) {
onScroll();
function intersectStep([entry]) {
onScroll();
const { isIntersecting, target } = entry;
if (isIntersecting) notifyStepEnter(target);
else notifyStepExit(target);
}
const { isIntersecting, target } = entry;
if (isIntersecting) notifyStepEnter(target);
else notifyStepExit(target);
}
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);
}
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);
}
/* OBSERVERS - CREATION */
function disconnectObserver({ observers }) {
Object.keys(observers).map((name) => {
observers[name].disconnect();
});
}
/* OBSERVERS - CREATION */
function disconnectObserver({ observers }) {
Object.keys(observers).map((name) => {
observers[name].disconnect();
});
}
function disconnectObservers() {
steps.forEach(disconnectObserver);
}
function disconnectObservers() {
steps.forEach(disconnectObserver);
}
function updateResizeObserver(step) {
const observer = new ResizeObserver(resizeStep);
observer.observe(step.node);
step.observers.resize = observer;
}
function updateResizeObserver(step) {
const observer = new ResizeObserver(resizeStep);
observer.observe(step.node);
step.observers.resize = observer;
}
function updateResizeObservers() {
steps.forEach(updateResizeObserver);
}
function updateResizeObservers() {
steps.forEach(updateResizeObserver);
}
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 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`;
const threshold = 0.5;
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectStep, options);
const threshold = 0.5;
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectStep, options);
observer.observe(step.node);
step.observers.step = observer;
}
observer.observe(step.node);
step.observers.step = observer;
function updateStepObservers() {
steps.forEach(updateStepObserver);
}
if (isDebug) update({ id, step, marginTop, marginBottom });
}
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 updateStepObservers() {
steps.forEach(updateStepObserver);
}
const threshold = createProgressThreshold(step.height, progressThreshold);
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectProgress, options);
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`;
observer.observe(step.node);
step.observers.progress = observer;
}
const threshold = createProgressThreshold(step.height, progressThreshold);
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectProgress, options);
function updateProgressObservers() {
steps.forEach(updateProgressObserver);
}
observer.observe(step.node);
step.observers.progress = observer;
}
function updateObservers() {
disconnectObservers();
updateResizeObservers();
updateStepObservers();
if (isProgressMode) updateProgressObservers();
}
function updateProgressObservers() {
steps.forEach(updateProgressObserver);
}
/* SETUP */
const S = {};
function updateObservers() {
disconnectObservers();
updateResizeObservers();
updateStepObservers();
if (isProgress) updateProgressObservers();
}
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,
}));
/* SETUP */
const S = {};
if (!steps.length) {
err$1("no step elements");
return S;
}
S.setup = ({
step,
parent,
offset = 0.5,
threshold = 4,
progress = 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,
}));
isProgressMode = progress;
isTriggerOnce = once;
progressThreshold = Math.max(1, +threshold);
globalOffset = parseOffset(offset);
reset();
indexSteps(steps);
handleEnable(true);
return S;
};
if (!steps.length) {
err$1("no step elements");
return S;
}
S.enable = () => {
handleEnable(true);
return S;
};
isProgress = progress;
isTriggerOnce = once;
isDebug = debug;
progressThreshold = Math.max(1, +threshold);
globalOffset = parseOffset(offset);
S.disable = () => {
handleEnable(false);
return S;
};
reset();
indexSteps(steps);
handleEnable(true);
return S;
};
S.destroy = () => {
handleEnable(false);
reset();
return S;
};
S.enable = () => {
handleEnable(true);
return S;
};
S.offset = (x) => {
if (x === null || x === undefined) return globalOffset.value;
globalOffset = parseOffset(x);
updateObservers();
return S;
};
S.disable = () => {
handleEnable(false);
return S;
};
S.onStepEnter = (f) => {
if (typeof f === "function") cb.stepEnter = f;
else err$1("onStepEnter requires a function");
return S;
};
S.destroy = () => {
handleEnable(false);
reset();
return S;
};
S.onStepExit = (f) => {
if (typeof f === "function") cb.stepExit = f;
else err$1("onStepExit requires a function");
return S;
};
S.resize = () => {
updateObservers();
return S;
};
S.onStepProgress = (f) => {
if (typeof f === "function") cb.stepProgress = f;
else err$1("onStepProgress requires a function");
return S;
};
return S;
S.offset = (x) => {
if (x === null || x === undefined) return globalOffset.value;
globalOffset = parseOffset(x);
updateObservers();
return S;
};
S.onStepEnter = (f) => {
if (typeof f === "function") cb.stepEnter = f;
else err$1("onStepEnter requires a function");
return S;
};
S.onStepExit = (f) => {
if (typeof f === "function") cb.stepExit = f;
else err$1("onStepExit requires a function");
return S;
};
S.onStepProgress = (f) => {
if (typeof f === "function") cb.stepProgress = f;
else err$1("onStepProgress requires a function");
return S;
};
return S;
}

@@ -349,0 +401,0 @@

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

!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}});
!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 $({id:e,step:t,marginTop:n}){var{index:o,height:t}=t,o=`scrollama__debug-step--${e}-${o}`;let r=document.querySelector(`.${o}`);r=r||function(e){const t=document.createElement("div");t.className=`scrollama__debug-step ${e}`,t.style.position="fixed",t.style.left="0",t.style.width="100%",t.style.zIndex="9999",t.style.borderTop="2px solid black",t.style.borderBottom="2px solid black";const n=document.createElement("p");return n.style.position="absolute",n.style.left="0",n.style.height="1px",n.style.width="100%",n.style.borderTop="1px dashed black",t.appendChild(n),document.body.appendChild(t),t}(o),r.style.top=`${-1*n}px`,r.style.height=`${t}px`,r.querySelector("p").style.top=`${t/2}px`}function S(e){console.error(`scrollama error: ${e}`)}function k(e){return+e.getAttribute("data-scrollama-index")}function M(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,O;function q(){e!==window.pageYOffset&&(e=window.pageYOffset,e>t?O="down":e<t&&(O="up"),t=e)}return document.addEventListener("scroll",q),function(){let r={},s=function(){var t="abcdefghijklmnopqrstuvwxyz",e=Date.now();const n=[];for(let e=0;e<6;e+=1){var o=t[Math.floor(Math.random()*t.length)];n.push(o)}return`${n.join("")}${e}`}(),a=[],c,f=0,t=!1,l=!1,p=!1,u=!1,o=[];function d(){r={stepEnter:()=>{},stepExit:()=>{},stepProgress:()=>{}},o=[]}function h(e){e&&!t&&w(),!e&&t&&v(),t=e}function i(e,t){var n=k(e);const o=a[n];void 0!==t&&(o.progress=t);t={element:e,index:n,progress:t,direction:O};"enter"===o.state&&r.stepProgress(t)}function n([e]){var t=k(e.target);const n=a[t];e=e.target.offsetHeight;e!==n.height&&(n.height=e,x(n),y(n),b(n))}function g([e]){q();var{isIntersecting:t,target:e}=e;(t?function(e){var t=k(e);const n=a[t];e={element:e,index:t,direction:O},n.direction=O,n.state="enter",o[t]||r.stepEnter(e),u&&(o[t]=!0)}:function(e){var t=k(e);const n=a[t];n.state&&(t={element:e,index:t,direction:O},l&&("down"===O&&n.progress<1?i(e,1):"up"===O&&0<n.progress&&i(e,0)),n.direction=O,n.state="exit",r.stepExit(t))})(e)}function m([e]){var t=k(e.target),n=a[t],{isIntersecting:o,intersectionRatio:t,target:e}=e;o&&"enter"===n.state&&i(e,t)}function x({observers:t}){Object.keys(t).map(e=>{t[e].disconnect()})}function v(){a.forEach(x)}function b(e){const t=new ResizeObserver(n);t.observe(e.node),e.observers.resize=t}function y(e){var t=window.innerHeight,n=e.offset||c,o="pixels"===n.format?1:t,n=n.value*o,o=e.height/2-n,n=e.height/2-(t-n);const r=new IntersectionObserver(g,{rootMargin:`${o}px 0px ${n}px 0px`,threshold:.5});r.observe(e.node),e.observers.step=r,p&&$({id:s,step:e,marginTop:o,marginBottom:n})}function e(e){var t=window.innerHeight,n=e.offset||c,o="pixels"===n.format?1:t,o=n.value*o,o=`${-o+e.height}px 0px ${o-t}px 0px`,t=function(e,t){var n=Math.ceil(e/t);const o=[];var r=1/n;for(let e=0;e<n+1;e+=1)o.push(e*r);return o}(e.height,f);const r=new IntersectionObserver(m,{rootMargin:o,threshold:t});r.observe(e.node),e.observers.progress=r}function w(){v(),a.forEach(b),a.forEach(y),l&&a.forEach(e)}const E={};return E.setup=({step:e,parent:t,offset:n=.5,threshold:o=4,progress:r=!1,once:s=!1,debug:i=!1})=>{return a=([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:M(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}))),a.length?(l=r,u=s,p=i,f=Math.max(1,+o),c=M(n),d(),a.forEach(e=>e.node.setAttribute("data-scrollama-index",e.index)),h(!0)):S("no step elements"),E},E.enable=()=>(h(!0),E),E.disable=()=>(h(!1),E),E.destroy=()=>(h(!1),d(),E),E.resize=()=>(w(),E),E.offset=e=>null==e?c.value:(c=M(e),w(),E),E.onStepEnter=e=>("function"==typeof e?r.stepEnter=e:S("onStepEnter requires a function"),E),E.onStepExit=e=>("function"==typeof e?r.stepExit=e:S("onStepExit requires a function"),E),E.onStepProgress=e=>("function"==typeof e?r.stepProgress=e:S("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=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}});
!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 $({id:e,step:t,marginTop:n}){var{index:o,height:t}=t,o=`scrollama__debug-step--${e}-${o}`;let r=document.querySelector(`.${o}`);r=r||function(e){const t=document.createElement("div");t.className=`scrollama__debug-step ${e}`,t.style.position="fixed",t.style.left="0",t.style.width="100%",t.style.zIndex="9999",t.style.borderTop="2px solid black",t.style.borderBottom="2px solid black";const n=document.createElement("p");return n.style.position="absolute",n.style.left="0",n.style.height="1px",n.style.width="100%",n.style.borderTop="1px dashed black",t.appendChild(n),document.body.appendChild(t),t}(o),r.style.top=`${-1*n}px`,r.style.height=`${t}px`,r.querySelector("p").style.top=`${t/2}px`}function S(e){console.error(`scrollama error: ${e}`)}function k(e){return+e.getAttribute("data-scrollama-index")}function M(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,O;function q(){e!==window.pageYOffset&&(e=window.pageYOffset,e>t?O="down":e<t&&(O="up"),t=e)}return document.addEventListener("scroll",q),function(){let r={},s=function(){var t="abcdefghijklmnopqrstuvwxyz",e=Date.now();const n=[];for(let e=0;e<6;e+=1){var o=t[Math.floor(Math.random()*t.length)];n.push(o)}return`${n.join("")}${e}`}(),a=[],c,f=0,t=!1,l=!1,p=!1,u=!1,o=[];function d(){r={stepEnter:()=>{},stepExit:()=>{},stepProgress:()=>{}},o=[]}function h(e){e&&!t&&w(),!e&&t&&v(),t=e}function i(e,t){var n=k(e);const o=a[n];void 0!==t&&(o.progress=t);t={element:e,index:n,progress:t,direction:O};"enter"===o.state&&r.stepProgress(t)}function n([e]){var t=k(e.target);const n=a[t];e=e.target.offsetHeight;e!==n.height&&(n.height=e,x(n),y(n),b(n))}function g([e]){q();var{isIntersecting:t,target:e}=e;(t?function(e){var t=k(e);const n=a[t];e={element:e,index:t,direction:O},n.direction=O,n.state="enter",o[t]||r.stepEnter(e),u&&(o[t]=!0)}:function(e){var t=k(e);const n=a[t];n.state&&(t={element:e,index:t,direction:O},l&&("down"===O&&n.progress<1?i(e,1):"up"===O&&0<n.progress&&i(e,0)),n.direction=O,n.state="exit",r.stepExit(t))})(e)}function m([e]){var t=k(e.target),n=a[t],{isIntersecting:o,intersectionRatio:t,target:e}=e;o&&"enter"===n.state&&i(e,t)}function x({observers:t}){Object.keys(t).map(e=>{t[e].disconnect()})}function v(){a.forEach(x)}function b(e){const t=new ResizeObserver(n);t.observe(e.node),e.observers.resize=t}function y(e){var t=window.innerHeight,n=e.offset||c,o="pixels"===n.format?1:t,n=n.value*o,o=e.height/2-n,n=e.height/2-(t-n);const r=new IntersectionObserver(g,{rootMargin:`${o}px 0px ${n}px 0px`,threshold:.5});r.observe(e.node),e.observers.step=r,p&&$({id:s,step:e,marginTop:o,marginBottom:n})}function e(e){var t=window.innerHeight,n=e.offset||c,o="pixels"===n.format?1:t,o=n.value*o,o=`${-o+e.height}px 0px ${o-t}px 0px`,t=function(e,t){var n=Math.ceil(e/t);const o=[];var r=1/n;for(let e=0;e<n+1;e+=1)o.push(e*r);return o}(e.height,f);const r=new IntersectionObserver(m,{rootMargin:o,threshold:t});r.observe(e.node),e.observers.progress=r}function w(){v(),a.forEach(b),a.forEach(y),l&&a.forEach(e)}const E={};return E.setup=({step:e,parent:t,offset:n=.5,threshold:o=4,progress:r=!1,once:s=!1,debug:i=!1})=>{return a=([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:M(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}))),a.length?(l=r,u=s,p=i,f=Math.max(1,+o),c=M(n),d(),a.forEach(e=>e.node.setAttribute("data-scrollama-index",e.index)),h(!0)):S("no step elements"),E},E.enable=()=>(h(!0),E),E.disable=()=>(h(!1),E),E.destroy=()=>(h(!1),d(),E),E.resize=()=>(w(),E),E.offset=e=>null==e?c.value:(c=M(e),w(),E),E.onStepEnter=e=>("function"==typeof e?r.stepEnter=e:S("onStepEnter requires a function"),E),E.onStepExit=e=>("function"==typeof e?r.stepExit=e:S("onStepExit requires a function"),E),E.onStepProgress=e=>("function"==typeof e?r.stepProgress=e:S("onStepProgress requires a function"),E),E}});
{
"name": "scrollama",
"version": "3.0.0",
"version": "3.0.1",
"description": "Lightweight scrollytelling library using IntersectionObserver",

@@ -5,0 +5,0 @@ "main": "build/scrollama.js",

@@ -1,21 +0,5 @@

# v3 roadmap
<pre>
<a href="https://github.com/russellgoldenberg/scrollama/tree/v3#readme">Get ready for the next release of Scrollama! 🚀</a>
</pre>
- 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"/>

@@ -28,6 +12,17 @@

**Current version**: 2.2.1
**Current version**: 3.0.1
#### Important Changes
## 3.0
#### Why 3.0?
The core parts of the Scrollama code base are being refactored for 3.0 to simplfy and clarify the logic. The goal behind this to ease make future maintainance, bug fixing, and feature additions easier moving forward. If you would like to try out a pre-release of 3.0, use the next tag during installation `npm install scrollama@next`.
#### New Fetaures
* Built-in resize using resize observers.
* Custom offsets on steps with data attributes
#### Deprecated Features
* the `order` option
## Important Changes
- **Version 3.0.0+**: `order` has been deprecated.
- **Version 2.0.0+**: `.onContainerEnter` and `.onContainerExit` have been deprecated in favor of CSS property `position: sticky;`. [How to use position sticky.](https://pudding.cool/process/scrollytelling-sticky/)

@@ -38,3 +33,3 @@ - **Version 1.4.0+**: you must manually add the IntersectionObserver polyfill for cross-browser support. See [installation](https://github.com/russellgoldenberg/scrollama#installation) for details.

### Why?
## Why?

@@ -49,3 +44,3 @@ Scrollytelling can be complicated to implement and difficult to make performant.

### Examples
## Examples

@@ -63,6 +58,8 @@ _Note: most of these examples use D3 to keep the code concise, but this can be used

using CSS `position: sticky;` to create a fixed graphic with fullscreen graphic with text overlayed.
- [Custom Offset](https://russellgoldenberg.github.io/scrollama/custom-offset) -
Adding a data attribute to an element to provide a unique offset for a step.
- [Mobile Pattern](https://russellgoldenberg.github.io/scrollama/mobile-pattern) -
using pixels instead of percent for offset value so it doesn't jump around on scroll direction change
### Installation
## Installation

@@ -74,3 +71,2 @@ **Note: As of version 1.4.0, the IntersectionObserver polyfill has been removed from the build. You must include it yourself for cross-browser support.** Check [here](https://caniuse.com/#feat=intersectionobserver) to see if you need to include the polyfill.

```html
<script src="https://unpkg.com/intersection-observer"></script>
<script src="https://unpkg.com/scrollama"></script>

@@ -88,3 +84,2 @@ ```

```js
import "intersection-observer";
import scrollama from "scrollama"; // or...

@@ -94,3 +89,3 @@ const scrollama = require("scrollama");

### How to use
## How to use

@@ -129,8 +124,5 @@ #### Basic

});
// setup resize event
window.addEventListener("resize", scroller.resize);
```
### API
## API

@@ -147,3 +139,2 @@ #### scrollama.setup([options])

- `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: false)**
- `once` (boolean): Only trigger the step to enter once then remove listener. **(default: false)**

@@ -200,3 +191,3 @@ - `debug` (boolean): Whether to show visual debugging tools or not. **(default:

Tell scrollama to get latest dimensions the browser/DOM. It is best practice to
**This is no longer necessary with the addition of a built-in resize observer**. Tell scrollama to get latest dimensions the browser/DOM. It is best practice to
throttle resize in your code, update the DOM elements, then call this function

@@ -218,15 +209,26 @@ at the end.

### Tips
## Scrollama In The Wild
* [The Billionaire Playbook - ProPublica](https://www.propublica.org/article/the-billionaire-playbook-how-sports-owners-use-their-teams-to-avoid-millions-in-taxes)
* [Women's Pockets are Inferior - The Pudding](https://pudding.cool/2018/08/pockets/)
* [Trump approval rating - Politico](https://www.politico.com/interactives/2019/trump-approval-rating-polls/)
* [How the opioid epidemic evolved - Washington Post](https://www.washingtonpost.com/graphics/2019/investigations/opioid-pills-overdose-analysis/)
* [US Covid-19 deaths, explained in 8 charts and maps - Vox](https://www.vox.com/22252693/covid-19-deaths-us-who-died)
* [Life After Death on Wikipedia - The Pudding](https://pudding.cool/2018/08/wiki-death/)
* [YouTube With Me - YouTube](https://youtube.com/trends/articles/with-me-interactive/)
* [Unchecked Power - ProPublica](https://projects.propublica.org/nypd-unchecked-power/)
* [Trump's environmental policies rule only part of America - Politico](https://www.politico.com/interactives/2018/trump-environmental-policies-rollbacks/)
* [The story of New Zealand’s Covid-19 lockdown, in graphs - Stuff](https://interactives.stuff.co.nz/2020/05/coronavirus-covid-19-data-new-zealand/)
* [Trump and Biden's Paths to Victory in the 2020 Election - Wall Street Journal](https://www.wsj.com/graphics/the-paths-to-victory/)
* [The sicence of superspreading - Science](https://vis.sciencemag.org/covid-clusters/)
* [El dominio histórico de la derecha en Madrid - elDiario.es](https://www.eldiario.es/madrid/gana-derecha-elecciones-madrid-mayoritaria-30-rico_1_7347696.html)
* [The Permutation Test - Jared Wilber](https://www.jwilber.me/permutationtest/)
* [Constellations - Nadieh Bremer](https://nbremer.github.io/planet-constellations/)
* [Remote Triggering of Earthquakes - Will Chase](https://www.williamrchase.com/vizrisk/vizrisk_main/)
* [Scrollytelling - Mapbox](https://demos.mapbox.com/scrollytelling/)
- Always call `scrollama.resize()` after a window resize event to ensure scroll
triggers update with new dimensions.
- Avoid using `viewport height` (vh) in your CSS because scrolling up and down
constantly triggers vh to change, which will also trigger a window resize.
## Tips
- Avoid using `viewport height` (vh) in your CSS because scrolling up and down constantly triggers vh to change, which will also trigger a window resize.
### Known Issues
## Alternatives
The `.onStepProgress` function does not perform desirably in Safari, returning infrequent updates.
### Alternatives
- [Waypoints](http://imakewebthings.com/waypoints/)

@@ -238,7 +240,7 @@ - [ScrollMagic](http://scrollmagic.io/)

### Logo
## Logo
Logo by the awesome [Elaina Natario](https://twitter.com/elainanatario)
### Contributors
## Contributors

@@ -263,3 +265,3 @@ - [russellgoldenberg](https://github.com/russellgoldenberg)

### License
## License

@@ -266,0 +268,0 @@ MIT License

@@ -1,52 +0,37 @@

function getOffsetId(id) {
return `scrollama__debug-offset--${id}`;
}
// SETUP
function setupOffset({ id, offsetVal, stepClass }) {
const 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";
function create(className) {
const el = document.createElement("div");
el.className = `scrollama__debug-step ${className}`;
el.style.position = "fixed";
el.style.left = "0";
el.style.width = "100%";
el.style.zIndex = "9999";
el.style.borderTop = "2px solid black";
el.style.borderBottom = "2px solid black";
const 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);
}
const p = document.createElement("p");
p.style.position = "absolute";
p.style.left = "0";
p.style.height = "1px";
p.style.width = "100%";
p.style.borderTop = "1px dashed black";
function setup({ id, offsetVal, stepEl }) {
const stepClass = stepEl[0].className;
setupOffset({ id, offsetVal, stepClass });
el.appendChild(p);
document.body.appendChild(el);
return el;
}
// UPDATE
function update({ id, offsetMargin, offsetVal, format }) {
const post = format === "pixels" ? "px" : "";
const idVal = getOffsetId(id);
const el = document.getElementById(idVal);
el.style.top = `${offsetMargin}px`;
el.querySelector("span").innerText = `${offsetVal}${post}`;
}
function update({ id, step, marginTop }) {
const { index, height } = step;
const className = `scrollama__debug-step--${id}-${index}`;
let el = document.querySelector(`.${className}`);
if (!el) el = create(className);
function notifyStep({ id, index, state }) {
const prefix = `scrollama__debug-step--${id}-${index}`;
const elA = document.getElementById(`${prefix}_above`);
const elB = document.getElementById(`${prefix}_below`);
const display = state === "enter" ? "block" : "none";
if (elA) elA.style.display = display;
if (elB) elB.style.display = display;
el.style.top = `${marginTop * -1}px`;
el.style.height = `${height}px`;
el.querySelector("p").style.top = `${height / 2}px`;
}
export { setup, update, notifyStep };
export { update };

@@ -13,304 +13,304 @@ import { selectAll } from "./dom";

function scrollama() {
let cb = {};
let cb = {};
let id = undefined;
let steps = [];
let globalOffset;
let id = generateId();
let steps = [];
let globalOffset;
let progressThreshold = 0;
let progressThreshold = 0;
let isEnabled = false;
let isProgressMode = false;
let isPreserveOrder = false;
let isTriggerOnce = false;
let isEnabled = false;
let isProgress = false;
let isDebug = false;
let isTriggerOnce = false;
let exclude = [];
let exclude = [];
/* HELPERS */
function reset() {
cb = {
stepEnter: () => {},
stepExit: () => {},
stepProgress: () => {},
};
exclude = [];
}
/* HELPERS */
function reset() {
cb = {
stepEnter: () => { },
stepExit: () => { },
stepProgress: () => { },
};
exclude = [];
}
function handleEnable(shouldEnable) {
if (shouldEnable && !isEnabled) updateObservers();
if (!shouldEnable && isEnabled) disconnectObservers();
isEnabled = shouldEnable;
}
function handleEnable(shouldEnable) {
if (shouldEnable && !isEnabled) updateObservers();
if (!shouldEnable && isEnabled) disconnectObservers();
isEnabled = shouldEnable;
}
/* 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);
}
/* 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);
}
function notifyOthers(index, location) {
console.log(index, location, direction, currentScrollY, previousScrollY);
if (location === "above") {
let i = direction === "down" ? 0 : index - 1;
let end = direction === "down" ? i < index : i >= 0;
let inc = direction === "down" ? 1 : -1;
for (i; end; inc) {
const step = steps[i];
console.log(
Object.keys(step)
.map((p) => `${p} - ${step[p]}`)
.join("\n ")
);
if (direction === "down") {
if (step.state !== "enter" && step.direction !== "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
} else if (step.state === "enter") notifyStepExit(step.node, false);
} else if (direction === "up") {
if (step.state !== "enter" && step.direction === "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
} else if (step.state === "enter") notifyStepExit(step.node, false);
}
}
} else if (location === "below") {
for (let i = steps.length - 1; i > index; i -= 1) {
const step = steps[i];
if (step.state === "enter") notifyStepExit(step.node);
if (step.direction === "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
}
}
}
}
function notifyOthers(index, location) {
console.log(index, location, direction, currentScrollY, previousScrollY);
if (location === "above") {
let i = direction === "down" ? 0 : index - 1;
let end = direction === "down" ? i < index : i >= 0;
let inc = direction === "down" ? 1 : -1;
for (i; end; inc) {
const step = steps[i];
console.log(
Object.keys(step)
.map((p) => `${p} - ${step[p]}`)
.join("\n ")
);
if (direction === "down") {
if (step.state !== "enter" && step.direction !== "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
} else if (step.state === "enter") notifyStepExit(step.node, false);
} else if (direction === "up") {
if (step.state !== "enter" && step.direction === "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
} else if (step.state === "enter") notifyStepExit(step.node, false);
}
}
} else if (location === "below") {
for (let i = steps.length - 1; i > index; i -= 1) {
const step = steps[i];
if (step.state === "enter") notifyStepExit(step.node);
if (step.direction === "down") {
notifyStepEnter(step.node, false);
notifyStepExit(step.node, false);
}
}
}
}
function notifyStepEnter(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
function notifyStepEnter(element, check = true) {
const index = getIndex(element);
const step = steps[index];
const response = { element, index, direction };
step.direction = direction;
step.state = "enter";
step.direction = direction;
step.state = "enter";
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "above");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "below");
// 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;
}
if (!exclude[index]) cb.stepEnter(response);
if (isTriggerOnce) exclude[index] = true;
}
function notifyStepExit(element, check = true) {
const index = getIndex(element);
const step = steps[index];
function notifyStepExit(element, check = true) {
const index = getIndex(element);
const step = steps[index];
if (!step.state) return false;
if (!step.state) return false;
const response = { element, index, direction };
const response = { element, index, direction };
if (isProgressMode) {
if (direction === "down" && step.progress < 1) notifyProgress(element, 1);
else if (direction === "up" && step.progress > 0)
notifyProgress(element, 0);
}
if (isProgress) {
if (direction === "down" && step.progress < 1) notifyProgress(element, 1);
else if (direction === "up" && step.progress > 0)
notifyProgress(element, 0);
}
step.direction = direction;
step.state = "exit";
step.direction = direction;
step.state = "exit";
// if (isPreserveOrder && check && direction !== "up")
// notifyOthers(index, "below");
// if (isPreserveOrder && check && direction === "up")
// notifyOthers(index, "above");
cb.stepExit(response);
}
cb.stepExit(response);
}
/* 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);
}
}
/* 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);
}
}
function intersectStep([entry]) {
onScroll();
function intersectStep([entry]) {
onScroll();
const { isIntersecting, target } = entry;
if (isIntersecting) notifyStepEnter(target);
else notifyStepExit(target);
}
const { isIntersecting, target } = entry;
if (isIntersecting) notifyStepEnter(target);
else notifyStepExit(target);
}
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);
}
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);
}
/* OBSERVERS - CREATION */
function disconnectObserver({ observers }) {
Object.keys(observers).map((name) => {
observers[name].disconnect();
});
}
/* OBSERVERS - CREATION */
function disconnectObserver({ observers }) {
Object.keys(observers).map((name) => {
observers[name].disconnect();
});
}
function disconnectObservers() {
steps.forEach(disconnectObserver);
}
function disconnectObservers() {
steps.forEach(disconnectObserver);
}
function updateResizeObserver(step) {
const observer = new ResizeObserver(resizeStep);
observer.observe(step.node);
step.observers.resize = observer;
}
function updateResizeObserver(step) {
const observer = new ResizeObserver(resizeStep);
observer.observe(step.node);
step.observers.resize = observer;
}
function updateResizeObservers() {
steps.forEach(updateResizeObserver);
}
function updateResizeObservers() {
steps.forEach(updateResizeObserver);
}
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 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`;
const threshold = 0.5;
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectStep, options);
const threshold = 0.5;
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectStep, options);
observer.observe(step.node);
step.observers.step = observer;
observer.observe(step.node);
step.observers.step = observer;
}
if (isDebug) bug.update({ id, step, marginTop, marginBottom });
}
function updateStepObservers() {
steps.forEach(updateStepObserver);
}
function updateStepObservers() {
steps.forEach(updateStepObserver);
}
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 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`;
const threshold = createProgressThreshold(step.height, progressThreshold);
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectProgress, options);
const threshold = createProgressThreshold(step.height, progressThreshold);
const options = { rootMargin, threshold };
const observer = new IntersectionObserver(intersectProgress, options);
observer.observe(step.node);
step.observers.progress = observer;
}
observer.observe(step.node);
step.observers.progress = observer;
}
function updateProgressObservers() {
steps.forEach(updateProgressObserver);
}
function updateProgressObservers() {
steps.forEach(updateProgressObserver);
}
function updateObservers() {
disconnectObservers();
updateResizeObservers();
updateStepObservers();
if (isProgressMode) updateProgressObservers();
}
function updateObservers() {
disconnectObservers();
updateResizeObservers();
updateStepObservers();
if (isProgress) updateProgressObservers();
}
/* SETUP */
const S = {};
/* SETUP */
const S = {};
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,
}));
S.setup = ({
step,
parent,
offset = 0.5,
threshold = 4,
progress = 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,
}));
if (!steps.length) {
err("no step elements");
return S;
}
if (!steps.length) {
err("no step elements");
return S;
}
isProgressMode = progress;
isPreserveOrder = order;
isTriggerOnce = once;
progressThreshold = Math.max(1, +threshold);
isProgress = progress;
isTriggerOnce = once;
isDebug = debug;
progressThreshold = Math.max(1, +threshold);
globalOffset = parseOffset(offset);
id = generateId();
globalOffset = parseOffset(offset);
reset();
indexSteps(steps);
handleEnable(true);
return S;
};
reset();
indexSteps(steps);
handleEnable(true);
return S;
};
S.enable = () => {
handleEnable(true);
return S;
};
S.enable = () => {
handleEnable(true);
return S;
};
S.disable = () => {
handleEnable(false);
return S;
};
S.disable = () => {
handleEnable(false);
return S;
};
S.destroy = () => {
handleEnable(false);
reset();
return S;
};
S.destroy = () => {
handleEnable(false);
reset();
return S;
};
S.offset = (x) => {
if (x === null || x === undefined) return globalOffset.value;
globalOffset = parseOffset(x);
updateObservers();
return S;
};
S.resize = () => {
updateObservers();
return S;
};
S.onStepEnter = (f) => {
if (typeof f === "function") cb.stepEnter = f;
else err("onStepEnter requires a function");
return S;
};
S.offset = (x) => {
if (x === null || x === undefined) return globalOffset.value;
globalOffset = parseOffset(x);
updateObservers();
return S;
};
S.onStepExit = (f) => {
if (typeof f === "function") cb.stepExit = f;
else err("onStepExit requires a function");
return S;
};
S.onStepEnter = (f) => {
if (typeof f === "function") cb.stepEnter = f;
else err("onStepEnter requires a function");
return S;
};
S.onStepProgress = (f) => {
if (typeof f === "function") cb.stepProgress = f;
else err("onStepProgress requires a function");
return S;
};
return S;
S.onStepExit = (f) => {
if (typeof f === "function") cb.stepExit = f;
else err("onStepExit requires a function");
return S;
};
S.onStepProgress = (f) => {
if (typeof f === "function") cb.stepProgress = f;
else err("onStepProgress requires a function");
return S;
};
return S;
}

@@ -317,0 +317,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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