OwlCyberSecurity - MANAGER
Edit File: spectra-block-positioning.js
const UAGBBlockPositioning = { // Initialize the required positioning functionality. init( attr, selector ) { const element = document.querySelector( selector ); if ( element?.classList.contains( 'uagb-position__sticky' ) ) { UAGBBlockPositioning.handleSticky( element, attr ); } }, // Function to handle the sticky positioned element. handleSticky( element, attr ) { // Add the Adminbar height if needed. const getAdminbarHeight = () => { const adminBar = document.querySelector( '#wpadminbar' ); return adminBar?.offsetHeight || 0; } // Create a filler element for sticky. const createStickyFiller = ( elementNode, elementDimensions, elementParent ) => { const fillerElement = document.createElement( 'div' ); fillerElement.style.height = `${ elementDimensions.height }px`; fillerElement.style.boxSizing = 'border-box'; const elementStyles = window.getComputedStyle( elementNode ); // If the sticky element is not restricted to the parent container, then set the width and margin. if ( ! elementParent ) { fillerElement.style.width = `${ elementDimensions.width }px`; fillerElement.style.margin = elementStyles.getPropertyValue( 'margin' ) || 0; // If the sticky element is restricted to the parent container, then set the maxWidth as was intended for the stuck element. } else { fillerElement.style.width = '100%'; fillerElement.style.maxWidth = elementStyles.getPropertyValue( 'max-width' ) || `${ elementDimensions.width }px`; fillerElement.style.padding = elementStyles.getPropertyValue( 'padding' ) || 0; fillerElement.style.margin = elementStyles.getPropertyValue( 'margin' ) || 0; fillerElement.style.border = elementStyles.getPropertyValue( 'border' ) || 0; fillerElement.style.borderColor = 'transparent'; } return fillerElement; }; // Add the animation attributes to the element and refresh the animations if this was an animated element. const applyAnimationData = () => { if ( 'undefined' === typeof AOS || ! attr?.UAGAnimationType ) { return; } element.dataset.aos = attr?.UAGAnimationType; element.dataset.aosDuration = attr?.UAGAnimationTime; element.dataset.aosDelay = attr?.UAGAnimationDelay; element.dataset.aosEasing = attr?.UAGAnimationEasing; element.dataset.aosOnce = true; setTimeout( () => { AOS.refreshHard(); }, 100 ); } // Get the dimensions of the sticky element. const stickyDimensions = element.getBoundingClientRect(); const parentContainer = ! attr?.isBlockRootParent ? element.parentElement : null; const fillerElement = createStickyFiller( element, stickyDimensions, parentContainer ); let haltAt, haltAtPosition, scrollPosition, parentRect; // Create the ParentHaltAt and ParentInnerPositions variables. const parentHaltAt = { top: 0, bottom: 0 }; const parentInnerPositions = { top: 0, right: 0, bottom: 0, left: 0 }; if ( attr?.UAGStickyRestricted ) { parentRect = parentContainer.getBoundingClientRect(); const parentStyles = window.getComputedStyle( parentContainer ); parentInnerPositions.top = parseInt( parentStyles.getPropertyValue( 'padding-top' ) || 0, 10 ); parentInnerPositions.bottom = parseInt( parentStyles.getPropertyValue( 'padding-bottom' ) || 0, 10 ); // To calculate the top position needed for the inner sticky container: // Start with the parent's top position. // Add the current scroll offset. // Add the parent's top padding if any. parentHaltAt.top = parentRect.top + ( window.pageYOffset || 0 ) + parentInnerPositions.top; // To calculate the top position needed for the inner sticky container: // Start with the parent's bottom position. // Add the current scroll offset. // Subtract the parent's bottom padding if any. // Subtract the sticky element's height. // Subtract the adminbar height if it exists. // Subtract the offset. parentHaltAt.bottom = parentRect.bottom + ( window.pageYOffset || 0 ) - parentInnerPositions.bottom - stickyDimensions.height - getAdminbarHeight() - ( attr?.UAGStickyOffset || 0 ); } // Handle the sticky element when it is positioned at the bottom, else handle top. if ( 'bottom' === attr?.UAGStickyLocation ) { // Stop whn the scroll makes the entire element visible on the current screen. haltAt = stickyDimensions.top + ( window.pageYOffset || 0 ) - window.innerHeight + stickyDimensions.height + ( attr?.UAGStickyOffset || 0 ); // Position the element to the bottom, considering the adminbar. haltAtPosition = `${ ( attr?.UAGStickyOffset || 0 ) }px`; scrollPosition = ( window.pageYOffset !== undefined ) ? window.pageYOffset : document.body.scrollTop; if ( scrollPosition <= haltAt && ! element.classList.contains( 'uagb-position__sticky--stuck' ) ) { element.parentNode.insertBefore( fillerElement, element ); element.classList.add( 'uagb-position__sticky--stuck' ); element.style.bottom = `calc(${ haltAtPosition } - ${ window.innerHeight }px)`; element.style.left = `${ stickyDimensions.left }px`; element.style.width = `${ stickyDimensions.width }px`; element.style.zIndex = '999'; setTimeout( () => { element.style.bottom = haltAtPosition; } , 50 ); } // Check if this sticky container was animated. applyAnimationData(); // Check when this needsto be stuck on the bottom, and when it doesn't. window.addEventListener( 'scroll', () => { scrollPosition = ( window.pageYOffset !== undefined ) ? window.pageYOffset : document.body.scrollTop; if ( scrollPosition <= haltAt ) { if ( ! element.classList.contains( 'uagb-position__sticky--stuck' ) ) { element.parentNode.insertBefore( fillerElement, element ); element.classList.add( 'uagb-position__sticky--stuck' ); element.style.bottom = haltAtPosition; element.style.left = `${ stickyDimensions.left }px`; element.style.width = `${ stickyDimensions.width }px`; element.style.zIndex = '999'; } } else if ( scrollPosition > haltAt && element.classList.contains( 'uagb-position__sticky--stuck' ) ) { element.parentNode.removeChild( fillerElement ); element.classList.remove( 'uagb-position__sticky--stuck' ); element.style.bottom = ''; element.style.left = ''; element.style.width = ''; element.style.zIndex = ''; } } ); } else { // Stop whn the scroll is at the top of the element. haltAt = stickyDimensions.top + ( window.pageYOffset || 0 ) - getAdminbarHeight() - ( attr?.UAGStickyOffset || 0 ); // Position the element to the top, considering the adminbar. haltAtPosition = `${ getAdminbarHeight() + ( attr?.UAGStickyOffset || 0 ) }px`; scrollPosition = ( window.pageYOffset !== undefined ) ? window.pageYOffset : document.body.scrollTop; if ( scrollPosition >= haltAt && ! element.classList.contains( 'uagb-position__sticky--stuck' ) ) { element.parentNode.insertBefore( fillerElement, element ); // Add and Remove Opacity for Sticky Containers. element.classList.add( 'uagb-position__sticky--stuck' ); // If this restricted container has crossed the bottom of the parent container on load, then restrict it. if ( attr?.UAGStickyRestricted && scrollPosition >= parentHaltAt.bottom ) { element.classList.remove( 'uagb-position__sticky--stuck' ); element.classList.add( 'uagb-position__sticky--restricted' ); element.style.top = ''; element.style.bottom = `${ parentInnerPositions.bottom }px`; element.style.left = `${ fillerElement?.offsetLeft || 0 }px`; // Else, just stick it to the top and transition it to the halt position. } else { element.style.top = `calc(${ haltAtPosition } - ${ window.innerHeight }px)` element.style.left = `${ stickyDimensions.left }px`; element.style.top = haltAtPosition; } element.style.width = `${ stickyDimensions.width }px`; element.style.zIndex = '999'; } // Check if this sticky container was animated. applyAnimationData(); // Check when this needsto be stuck on the top, and when it doesn't. window.addEventListener( 'scroll', () => { scrollPosition = ( window.pageYOffset !== undefined ) ? window.pageYOffset : document.body.scrollTop; // If the scroll position is greater than the current sticky height. if ( scrollPosition >= haltAt ) { // If the sticky class doesn't yet exist, add the filler and the sticky class. if ( ! element.classList.contains( 'uagb-position__sticky--stuck' ) && ! element.classList.contains( 'uagb-position__sticky--restricted' ) ) { element.parentNode.insertBefore( fillerElement, element ); element.classList.add( 'uagb-position__sticky--stuck' ); element.style.top = haltAtPosition; element.style.left = `${ stickyDimensions.left }px`; element.style.width = `${ stickyDimensions.width }px`; element.style.zIndex = '999'; // Else if the container is struck and the scroll is at the parent bottom, restrict it there. } else if ( attr?.UAGStickyRestricted && ! element.classList.contains( 'uagb-position__sticky--restricted' ) && scrollPosition >= parentHaltAt.bottom ) { element.classList.remove( 'uagb-position__sticky--stuck' ); element.classList.add( 'uagb-position__sticky--restricted' ); element.style.top = ''; element.style.bottom = `${ parentInnerPositions.bottom }px`; element.style.left = `${ fillerElement?.offsetLeft || 0 }px`; // Else if the container is already restricted and the scroll has returned above the parent bottom, stick it again. } else if ( element.classList.contains( 'uagb-position__sticky--restricted' ) && scrollPosition < parentHaltAt.bottom ) { element.classList.remove( 'uagb-position__sticky--restricted' ); element.classList.add( 'uagb-position__sticky--stuck' ); element.style.top = haltAtPosition; element.style.bottom = ''; element.style.left = `${ stickyDimensions.left }px`; element.style.width = `${ stickyDimensions.width }px`; element.style.zIndex = '999'; } } else if ( scrollPosition < haltAt && element.classList.contains( 'uagb-position__sticky--stuck' ) ) { element.parentNode.removeChild( fillerElement ); element.classList.remove( 'uagb-position__sticky--stuck' ); element.style.top = ''; element.style.left = ''; element.style.width = ''; element.style.zIndex = ''; } } ); } }, };