From 47df664688958ed15a9800bcacd3f69f8e0ae832 Mon Sep 17 00:00:00 2001 From: marco Date: Mon, 17 Oct 2022 14:47:25 +0200 Subject: [PATCH 1/2] Added changes Script now has option to observer mutations by adding "mini-observer" class to any elements which may hold dynamic content. It also handles window resize to stop the contents from breaking --- parallax.js | 168 ++++++++++++++++++++++++++++++++++++------------ parallax.min.js | 2 +- 2 files changed, 129 insertions(+), 41 deletions(-) diff --git a/parallax.js b/parallax.js index 02f689c..e8e5144 100644 --- a/parallax.js +++ b/parallax.js @@ -1,54 +1,142 @@ //PARALLAX by Max Paga / 2022 - -let parallax = document.querySelectorAll('.parallax') -let VH = window.innerHeight -let parallaxSpeed = 0.25 -let posY = 0 - -parallax.forEach(function (p) { - +const parallax = document.querySelectorAll(".parallax"); +const observers = document.querySelectorAll(".mini-observer"); +const startUp = (nodes) => { + nodes.forEach(function (p) { //variables - if (!p.getAttribute('speed')) p.setAttribute('speed', parallaxSpeed) - let speed = p.getAttribute('speed') - let height = p.clientHeight - let scale = (VH - (height)) * speed + const VH = window.innerHeight; + if (!p.getAttribute("speed")) p.setAttribute("speed", 0.25); + let speed = p.getAttribute("speed"); + let height = p.clientHeight; + let scale = (VH - height) * speed; //attributes needed inside the scroll event - p.setAttribute('calc', (VH - height) * 0.5) - p.setAttribute('offset', p.getBoundingClientRect().top + window.pageYOffset) + p.setAttribute("calc", (VH - height) * 0.5); + p.setAttribute( + "offset", + p.getBoundingClientRect().top + window.pageYOffset + ); - if (p.getAttribute('noscale') == null) { - //element is scaled up to *exactly* fill the wrapper - p.style.height = height + scale + 'px' - p.style.top = scale * -0.5 + 'px' + if (p.getAttribute("noscale") == null) { + //element is scaled up to *exactly* fill the wrapper + p.style.height = height + scale + "px"; + p.style.top = scale * -0.5 + "px"; } //initialise position before scroll listener is called - if (p.getAttribute('x') !== null) { - //among X axis - p.style.transform = 'translate3d(' + (((0 - p.getAttribute('offset')) + parseInt(p.getAttribute('calc'))) * p.getAttribute('speed')) + 'px, 0, 0)' + if (p.getAttribute("x") !== null) { + //among X axis + p.style.transform = + "translate3d(" + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0, 0)"; } else { - //among Y axis - p.style.transform = 'translate3d(0,' + (((0 - p.getAttribute('offset')) + parseInt(p.getAttribute('calc'))) * p.getAttribute('speed')) + 'px, 0)' - //sets Y - needed to be individually called in scroll listener - also checks if y is already set - if (p.getAttribute('y') == null) p.setAttribute('y', '') + //among Y axis + p.style.transform = + "translate3d(0," + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0)"; + //sets Y - needed to be individually called in scroll listener - also checks if y is already set + if (p.getAttribute("y") == null) p.setAttribute("y", ""); } -}); + }); +}; + +startUp(parallax); -//needed to set direction (best solution for now) -let parX = document.querySelectorAll('.parallax[x]') -let parY = document.querySelectorAll('.parallax[y]') +function scrollFc() { + const posY = window.scrollY; + //needed to set direction (best solution for now) + const parX = document.querySelectorAll(".parallax[x]"); + const parY = document.querySelectorAll(".parallax[y]"); + + //this is calculated whenever the user scrolls (suprisingly performant) + parX.forEach(function (p) { + p.style.transform = + "translate3d(" + + (posY - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0, 0)"; + }); + parY.forEach(function (p) { + p.style.transform = + "translate3d(0," + + (posY - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0)"; + }); +} + +function cleanUp() { + window.removeEventListener("scroll", scrollFc); +} //scroll listener -window.addEventListener('scroll', function () { - posY = window.scrollY - - //this is calculated whenever the user scrolls (suprisingly performant) - parX.forEach(function (p) { - p.style.transform = 'translate3d(' + (((posY - p.getAttribute('offset')) + parseInt(p.getAttribute('calc'))) * p.getAttribute('speed')) + 'px, 0, 0)' - }) - parY.forEach(function (p) { - p.style.transform = 'translate3d(0,' + (((posY - p.getAttribute('offset')) + parseInt(p.getAttribute('calc'))) * p.getAttribute('speed')) + 'px, 0)' - }) -}) \ No newline at end of file +window.addEventListener("scroll", scrollFc); + +observers.forEach((observer) => observerSetup(observer)); + +function isElement(o) { + return typeof HTMLElement === "object" + ? o instanceof HTMLElement //DOM2 + : o && + typeof o === "object" && + o !== null && + o.nodeType === 1 && + typeof o.nodeName === "string"; +} + +function observerSetup(node) { + // Options for the observer (which mutations to observe) + const config = { + attributes: true, + childList: true, + subtree: true, + }; + + // Callback function to execute when mutations are observed + const callback = (mutationList, observer) => { + for (const mutation of mutationList) { + if (mutation.type === "childList") { + mutation.addedNodes.forEach((node) => { + isElement(node) && + (node.classList.contains("parallax") + ? startUp(node) + : startUp(node.querySelectorAll(".parallax"))); + }); + } else if (mutation.type === "attributes") { + if (mutation.attributeName === "class" && isElement(mutation.target)) { + mutation.target.classList.contains("parallax") + ? startUp(mutation.target) + : startUp(mutation.target.querySelectorAll(".parallax")); + } + } + } + }; + + // Create an observer instance linked to the callback function + const observer = new MutationObserver(callback); + + // Start observing the target node for configured mutations + observer.observe(node, config); +} + +function handleResize() { + cleanUp(); + startUp(document.querySelectorAll(".parallax")); + window.addEventListener("scroll", scrollFc); +} + +let timeout = false; +// window.resize event listener +window.addEventListener("resize", function () { + // clear the timeout + clearTimeout(timeout); + // start timing for event "completion" + timeout = setTimeout(getDimensions, 250); +}); + +getDimensions(); diff --git a/parallax.min.js b/parallax.min.js index 7986a93..250a44f 100644 --- a/parallax.min.js +++ b/parallax.min.js @@ -1 +1 @@ -let parallax=document.querySelectorAll(".parallax"),VH=window.innerHeight,parallaxSpeed=.25,posY=0;parallax.forEach((function(p){p.getAttribute("speed")||p.setAttribute("speed",parallaxSpeed);let speed=p.getAttribute("speed"),height=p.clientHeight,scale=(VH-height)*speed;p.setAttribute("calc",.5*(VH-height)),p.setAttribute("offset",p.getBoundingClientRect().top+window.pageYOffset),null==p.getAttribute("noscale")&&(p.style.height=height+scale+"px",p.style.top=-.5*scale+"px"),null!==p.getAttribute("x")?p.style.transform="translate3d("+(0-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0, 0)":(p.style.transform="translate3d(0,"+(0-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0)",null==p.getAttribute("y")&&p.setAttribute("y",""))}));let parX=document.querySelectorAll(".parallax[x]"),parY=document.querySelectorAll(".parallax[y]");window.addEventListener("scroll",(function(){posY=window.scrollY,parX.forEach((function(p){p.style.transform="translate3d("+(posY-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0, 0)"})),parY.forEach((function(p){p.style.transform="translate3d(0,"+(posY-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0)"}))})); \ No newline at end of file +const parallax=document.querySelectorAll(".parallax"),observers=document.querySelectorAll(".mini-observer"),startUp=t=>{t.forEach(function(t){let e=window.innerHeight;t.getAttribute("speed")||t.setAttribute("speed",.25);let r=t.getAttribute("speed"),l=t.clientHeight,a=(e-l)*r;t.setAttribute("calc",(e-l)*.5),t.setAttribute("offset",t.getBoundingClientRect().top+window.pageYOffset),null==t.getAttribute("noscale")&&(t.style.height=l+a+"px",t.style.top=-.5*a+"px"),null!==t.getAttribute("x")?t.style.transform="translate3d("+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0, 0)":(t.style.transform="translate3d(0,"+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0)",null==t.getAttribute("y")&&t.setAttribute("y",""))})};function scrollFc(){let t=window.scrollY,e=document.querySelectorAll(".parallax[x]"),r=document.querySelectorAll(".parallax[y]");e.forEach(function(e){e.style.transform="translate3d("+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0, 0)"}),r.forEach(function(e){e.style.transform="translate3d(0,"+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0)"})}function cleanUp(){window.removeEventListener("scroll",scrollFc)}function isElement(t){return"object"==typeof HTMLElement?t instanceof HTMLElement:t&&"object"==typeof t&&null!==t&&1===t.nodeType&&"string"==typeof t.nodeName}function observerSetup(t){let e=(t,e)=>{for(let r of t)"childList"===r.type?r.addedNodes.forEach(t=>{isElement(t)&&(t.classList.contains("parallax")?startUp(t):startUp(t.querySelectorAll(".parallax")))}):"attributes"===r.type&&"class"===r.attributeName&&isElement(r.target)&&(r.target.classList.contains("parallax")?startUp(r.target):startUp(r.target.querySelectorAll(".parallax")))},r=new MutationObserver(e);r.observe(t,{attributes:!0,childList:!0,subtree:!0})}function handleResize(){cleanUp(),startUp(document.querySelectorAll(".parallax")),window.addEventListener("scroll",scrollFc)}startUp(parallax),window.addEventListener("scroll",scrollFc),observers.forEach(t=>observerSetup(t));let timeout=!1;window.addEventListener("resize",function(){clearTimeout(timeout),timeout=setTimeout(getDimensions,250)}),getDimensions(); \ No newline at end of file From d6a01141a4570be573a0a103955c98faf5ce98c7 Mon Sep 17 00:00:00 2001 From: marco Date: Mon, 17 Oct 2022 21:18:30 +0200 Subject: [PATCH 2/2] Separate changes into new version --- parallax-dynamic.js | 142 +++++++++++++++++++++++++++++++++ parallax-dynamic.min .js | 1 + parallax.js | 168 +++++++++++---------------------------- parallax.min.js | 2 +- 4 files changed, 191 insertions(+), 122 deletions(-) create mode 100644 parallax-dynamic.js create mode 100644 parallax-dynamic.min .js diff --git a/parallax-dynamic.js b/parallax-dynamic.js new file mode 100644 index 0000000..e8e5144 --- /dev/null +++ b/parallax-dynamic.js @@ -0,0 +1,142 @@ +//PARALLAX by Max Paga / 2022 +const parallax = document.querySelectorAll(".parallax"); +const observers = document.querySelectorAll(".mini-observer"); +const startUp = (nodes) => { + nodes.forEach(function (p) { + //variables + const VH = window.innerHeight; + if (!p.getAttribute("speed")) p.setAttribute("speed", 0.25); + let speed = p.getAttribute("speed"); + let height = p.clientHeight; + let scale = (VH - height) * speed; + + //attributes needed inside the scroll event + p.setAttribute("calc", (VH - height) * 0.5); + p.setAttribute( + "offset", + p.getBoundingClientRect().top + window.pageYOffset + ); + + if (p.getAttribute("noscale") == null) { + //element is scaled up to *exactly* fill the wrapper + p.style.height = height + scale + "px"; + p.style.top = scale * -0.5 + "px"; + } + + //initialise position before scroll listener is called + if (p.getAttribute("x") !== null) { + //among X axis + p.style.transform = + "translate3d(" + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0, 0)"; + } else { + //among Y axis + p.style.transform = + "translate3d(0," + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0)"; + //sets Y - needed to be individually called in scroll listener - also checks if y is already set + if (p.getAttribute("y") == null) p.setAttribute("y", ""); + } + }); +}; + +startUp(parallax); + +function scrollFc() { + const posY = window.scrollY; + + //needed to set direction (best solution for now) + const parX = document.querySelectorAll(".parallax[x]"); + const parY = document.querySelectorAll(".parallax[y]"); + + //this is calculated whenever the user scrolls (suprisingly performant) + parX.forEach(function (p) { + p.style.transform = + "translate3d(" + + (posY - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0, 0)"; + }); + parY.forEach(function (p) { + p.style.transform = + "translate3d(0," + + (posY - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0)"; + }); +} + +function cleanUp() { + window.removeEventListener("scroll", scrollFc); +} + +//scroll listener +window.addEventListener("scroll", scrollFc); + +observers.forEach((observer) => observerSetup(observer)); + +function isElement(o) { + return typeof HTMLElement === "object" + ? o instanceof HTMLElement //DOM2 + : o && + typeof o === "object" && + o !== null && + o.nodeType === 1 && + typeof o.nodeName === "string"; +} + +function observerSetup(node) { + // Options for the observer (which mutations to observe) + const config = { + attributes: true, + childList: true, + subtree: true, + }; + + // Callback function to execute when mutations are observed + const callback = (mutationList, observer) => { + for (const mutation of mutationList) { + if (mutation.type === "childList") { + mutation.addedNodes.forEach((node) => { + isElement(node) && + (node.classList.contains("parallax") + ? startUp(node) + : startUp(node.querySelectorAll(".parallax"))); + }); + } else if (mutation.type === "attributes") { + if (mutation.attributeName === "class" && isElement(mutation.target)) { + mutation.target.classList.contains("parallax") + ? startUp(mutation.target) + : startUp(mutation.target.querySelectorAll(".parallax")); + } + } + } + }; + + // Create an observer instance linked to the callback function + const observer = new MutationObserver(callback); + + // Start observing the target node for configured mutations + observer.observe(node, config); +} + +function handleResize() { + cleanUp(); + startUp(document.querySelectorAll(".parallax")); + window.addEventListener("scroll", scrollFc); +} + +let timeout = false; +// window.resize event listener +window.addEventListener("resize", function () { + // clear the timeout + clearTimeout(timeout); + // start timing for event "completion" + timeout = setTimeout(getDimensions, 250); +}); + +getDimensions(); diff --git a/parallax-dynamic.min .js b/parallax-dynamic.min .js new file mode 100644 index 0000000..250a44f --- /dev/null +++ b/parallax-dynamic.min .js @@ -0,0 +1 @@ +const parallax=document.querySelectorAll(".parallax"),observers=document.querySelectorAll(".mini-observer"),startUp=t=>{t.forEach(function(t){let e=window.innerHeight;t.getAttribute("speed")||t.setAttribute("speed",.25);let r=t.getAttribute("speed"),l=t.clientHeight,a=(e-l)*r;t.setAttribute("calc",(e-l)*.5),t.setAttribute("offset",t.getBoundingClientRect().top+window.pageYOffset),null==t.getAttribute("noscale")&&(t.style.height=l+a+"px",t.style.top=-.5*a+"px"),null!==t.getAttribute("x")?t.style.transform="translate3d("+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0, 0)":(t.style.transform="translate3d(0,"+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0)",null==t.getAttribute("y")&&t.setAttribute("y",""))})};function scrollFc(){let t=window.scrollY,e=document.querySelectorAll(".parallax[x]"),r=document.querySelectorAll(".parallax[y]");e.forEach(function(e){e.style.transform="translate3d("+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0, 0)"}),r.forEach(function(e){e.style.transform="translate3d(0,"+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0)"})}function cleanUp(){window.removeEventListener("scroll",scrollFc)}function isElement(t){return"object"==typeof HTMLElement?t instanceof HTMLElement:t&&"object"==typeof t&&null!==t&&1===t.nodeType&&"string"==typeof t.nodeName}function observerSetup(t){let e=(t,e)=>{for(let r of t)"childList"===r.type?r.addedNodes.forEach(t=>{isElement(t)&&(t.classList.contains("parallax")?startUp(t):startUp(t.querySelectorAll(".parallax")))}):"attributes"===r.type&&"class"===r.attributeName&&isElement(r.target)&&(r.target.classList.contains("parallax")?startUp(r.target):startUp(r.target.querySelectorAll(".parallax")))},r=new MutationObserver(e);r.observe(t,{attributes:!0,childList:!0,subtree:!0})}function handleResize(){cleanUp(),startUp(document.querySelectorAll(".parallax")),window.addEventListener("scroll",scrollFc)}startUp(parallax),window.addEventListener("scroll",scrollFc),observers.forEach(t=>observerSetup(t));let timeout=!1;window.addEventListener("resize",function(){clearTimeout(timeout),timeout=setTimeout(getDimensions,250)}),getDimensions(); \ No newline at end of file diff --git a/parallax.js b/parallax.js index e8e5144..05d0122 100644 --- a/parallax.js +++ b/parallax.js @@ -1,57 +1,54 @@ //PARALLAX by Max Paga / 2022 -const parallax = document.querySelectorAll(".parallax"); -const observers = document.querySelectorAll(".mini-observer"); -const startUp = (nodes) => { - nodes.forEach(function (p) { - //variables - const VH = window.innerHeight; - if (!p.getAttribute("speed")) p.setAttribute("speed", 0.25); - let speed = p.getAttribute("speed"); - let height = p.clientHeight; - let scale = (VH - height) * speed; - //attributes needed inside the scroll event - p.setAttribute("calc", (VH - height) * 0.5); - p.setAttribute( - "offset", - p.getBoundingClientRect().top + window.pageYOffset - ); - - if (p.getAttribute("noscale") == null) { - //element is scaled up to *exactly* fill the wrapper - p.style.height = height + scale + "px"; - p.style.top = scale * -0.5 + "px"; - } - - //initialise position before scroll listener is called - if (p.getAttribute("x") !== null) { - //among X axis - p.style.transform = - "translate3d(" + - (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * - p.getAttribute("speed") + - "px, 0, 0)"; - } else { - //among Y axis - p.style.transform = - "translate3d(0," + - (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * - p.getAttribute("speed") + - "px, 0)"; - //sets Y - needed to be individually called in scroll listener - also checks if y is already set - if (p.getAttribute("y") == null) p.setAttribute("y", ""); - } - }); -}; - -startUp(parallax); +let parallax = document.querySelectorAll(".parallax"); +let VH = window.innerHeight; +let parallaxSpeed = 0.25; +let posY = 0; + +parallax.forEach(function (p) { + //variables + if (!p.getAttribute("speed")) p.setAttribute("speed", parallaxSpeed); + let speed = p.getAttribute("speed"); + let height = p.clientHeight; + let scale = (VH - height) * speed; + + //attributes needed inside the scroll event + p.setAttribute("calc", (VH - height) * 0.5); + p.setAttribute("offset", p.getBoundingClientRect().top + window.pageYOffset); + + if (p.getAttribute("noscale") == null) { + //element is scaled up to *exactly* fill the wrapper + p.style.height = height + scale + "px"; + p.style.top = scale * -0.5 + "px"; + } + + //initialise position before scroll listener is called + if (p.getAttribute("x") !== null) { + //among X axis + p.style.transform = + "translate3d(" + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0, 0)"; + } else { + //among Y axis + p.style.transform = + "translate3d(0," + + (0 - p.getAttribute("offset") + parseInt(p.getAttribute("calc"))) * + p.getAttribute("speed") + + "px, 0)"; + //sets Y - needed to be individually called in scroll listener - also checks if y is already set + if (p.getAttribute("y") == null) p.setAttribute("y", ""); + } +}); -function scrollFc() { - const posY = window.scrollY; +//needed to set direction (best solution for now) +let parX = document.querySelectorAll(".parallax[x]"); +let parY = document.querySelectorAll(".parallax[y]"); - //needed to set direction (best solution for now) - const parX = document.querySelectorAll(".parallax[x]"); - const parY = document.querySelectorAll(".parallax[y]"); +//scroll listener +window.addEventListener("scroll", function () { + posY = window.scrollY; //this is calculated whenever the user scrolls (suprisingly performant) parX.forEach(function (p) { @@ -68,75 +65,4 @@ function scrollFc() { p.getAttribute("speed") + "px, 0)"; }); -} - -function cleanUp() { - window.removeEventListener("scroll", scrollFc); -} - -//scroll listener -window.addEventListener("scroll", scrollFc); - -observers.forEach((observer) => observerSetup(observer)); - -function isElement(o) { - return typeof HTMLElement === "object" - ? o instanceof HTMLElement //DOM2 - : o && - typeof o === "object" && - o !== null && - o.nodeType === 1 && - typeof o.nodeName === "string"; -} - -function observerSetup(node) { - // Options for the observer (which mutations to observe) - const config = { - attributes: true, - childList: true, - subtree: true, - }; - - // Callback function to execute when mutations are observed - const callback = (mutationList, observer) => { - for (const mutation of mutationList) { - if (mutation.type === "childList") { - mutation.addedNodes.forEach((node) => { - isElement(node) && - (node.classList.contains("parallax") - ? startUp(node) - : startUp(node.querySelectorAll(".parallax"))); - }); - } else if (mutation.type === "attributes") { - if (mutation.attributeName === "class" && isElement(mutation.target)) { - mutation.target.classList.contains("parallax") - ? startUp(mutation.target) - : startUp(mutation.target.querySelectorAll(".parallax")); - } - } - } - }; - - // Create an observer instance linked to the callback function - const observer = new MutationObserver(callback); - - // Start observing the target node for configured mutations - observer.observe(node, config); -} - -function handleResize() { - cleanUp(); - startUp(document.querySelectorAll(".parallax")); - window.addEventListener("scroll", scrollFc); -} - -let timeout = false; -// window.resize event listener -window.addEventListener("resize", function () { - // clear the timeout - clearTimeout(timeout); - // start timing for event "completion" - timeout = setTimeout(getDimensions, 250); }); - -getDimensions(); diff --git a/parallax.min.js b/parallax.min.js index 250a44f..7986a93 100644 --- a/parallax.min.js +++ b/parallax.min.js @@ -1 +1 @@ -const parallax=document.querySelectorAll(".parallax"),observers=document.querySelectorAll(".mini-observer"),startUp=t=>{t.forEach(function(t){let e=window.innerHeight;t.getAttribute("speed")||t.setAttribute("speed",.25);let r=t.getAttribute("speed"),l=t.clientHeight,a=(e-l)*r;t.setAttribute("calc",(e-l)*.5),t.setAttribute("offset",t.getBoundingClientRect().top+window.pageYOffset),null==t.getAttribute("noscale")&&(t.style.height=l+a+"px",t.style.top=-.5*a+"px"),null!==t.getAttribute("x")?t.style.transform="translate3d("+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0, 0)":(t.style.transform="translate3d(0,"+(0-t.getAttribute("offset")+parseInt(t.getAttribute("calc")))*t.getAttribute("speed")+"px, 0)",null==t.getAttribute("y")&&t.setAttribute("y",""))})};function scrollFc(){let t=window.scrollY,e=document.querySelectorAll(".parallax[x]"),r=document.querySelectorAll(".parallax[y]");e.forEach(function(e){e.style.transform="translate3d("+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0, 0)"}),r.forEach(function(e){e.style.transform="translate3d(0,"+(t-e.getAttribute("offset")+parseInt(e.getAttribute("calc")))*e.getAttribute("speed")+"px, 0)"})}function cleanUp(){window.removeEventListener("scroll",scrollFc)}function isElement(t){return"object"==typeof HTMLElement?t instanceof HTMLElement:t&&"object"==typeof t&&null!==t&&1===t.nodeType&&"string"==typeof t.nodeName}function observerSetup(t){let e=(t,e)=>{for(let r of t)"childList"===r.type?r.addedNodes.forEach(t=>{isElement(t)&&(t.classList.contains("parallax")?startUp(t):startUp(t.querySelectorAll(".parallax")))}):"attributes"===r.type&&"class"===r.attributeName&&isElement(r.target)&&(r.target.classList.contains("parallax")?startUp(r.target):startUp(r.target.querySelectorAll(".parallax")))},r=new MutationObserver(e);r.observe(t,{attributes:!0,childList:!0,subtree:!0})}function handleResize(){cleanUp(),startUp(document.querySelectorAll(".parallax")),window.addEventListener("scroll",scrollFc)}startUp(parallax),window.addEventListener("scroll",scrollFc),observers.forEach(t=>observerSetup(t));let timeout=!1;window.addEventListener("resize",function(){clearTimeout(timeout),timeout=setTimeout(getDimensions,250)}),getDimensions(); \ No newline at end of file +let parallax=document.querySelectorAll(".parallax"),VH=window.innerHeight,parallaxSpeed=.25,posY=0;parallax.forEach((function(p){p.getAttribute("speed")||p.setAttribute("speed",parallaxSpeed);let speed=p.getAttribute("speed"),height=p.clientHeight,scale=(VH-height)*speed;p.setAttribute("calc",.5*(VH-height)),p.setAttribute("offset",p.getBoundingClientRect().top+window.pageYOffset),null==p.getAttribute("noscale")&&(p.style.height=height+scale+"px",p.style.top=-.5*scale+"px"),null!==p.getAttribute("x")?p.style.transform="translate3d("+(0-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0, 0)":(p.style.transform="translate3d(0,"+(0-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0)",null==p.getAttribute("y")&&p.setAttribute("y",""))}));let parX=document.querySelectorAll(".parallax[x]"),parY=document.querySelectorAll(".parallax[y]");window.addEventListener("scroll",(function(){posY=window.scrollY,parX.forEach((function(p){p.style.transform="translate3d("+(posY-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0, 0)"})),parY.forEach((function(p){p.style.transform="translate3d(0,"+(posY-p.getAttribute("offset")+parseInt(p.getAttribute("calc")))*p.getAttribute("speed")+"px, 0)"}))})); \ No newline at end of file