@randstad-design/orbit-multitheme
Version:
multitheme Front-end code based on Randstad Human Forward components
105 lines (88 loc) • 2.18 kB
JavaScript
/**
* Sticky.js
* Script to make a component sticky
*/
/**
* Declare constants
*/
const attributeBase = 'data-rs-sticky';
export class Sticky {
constructor(element) {
this.element = element;
this.addEventHandlers();
this.makeElementSticky();
this.stickyHeight = this.element.offsetHeight;
}
/**
* Declare attribute constants
*/
get attributes() {
return {};
}
/**
* Declare classes
*/
get classes() {
return {
sticky: this.element.dataset.rsSticky
? this.element.dataset.rsSticky
: 'is-sticky'
};
}
/**
* Add event handlers
*/
addEventHandlers() {
window.addEventListener('resize', () => {
this.makeElementSticky();
});
}
makeElementSticky() {
const elementIsVisible =
getComputedStyle(this.element).getPropertyValue('display') !== 'none';
if (elementIsVisible) {
const elementPos = this.element.offsetTop;
const windowScrollStartPos = window.scrollY;
if (windowScrollStartPos > elementPos) {
this.element.classList.add(this.classes.sticky);
this.addExtraSpacingToNextElement();
}
window.addEventListener('scroll', () => {
const windowScrollPos = window.scrollY;
if (windowScrollPos > elementPos) {
this.element.classList.add(this.classes.sticky);
this.addExtraSpacingToNextElement();
} else {
this.element.classList.remove(this.classes.sticky);
this.removeExtraSpacingNextElement();
}
});
}
}
addExtraSpacingToNextElement() {
const nextElement = this.next(this.element);
nextElement.setAttribute(
'style',
`top: ${this.stickyHeight}px; position: relative;`
);
}
removeExtraSpacingNextElement() {
const nextElement = this.next(this.element);
nextElement.removeAttribute('style');
}
/*
* Function to get the next elements node instead of text node
*/
next(elem) {
do {
elem = elem.nextSibling;
} while (elem && elem.nodeType !== 1);
return elem;
}
/**
* Get selector
*/
static getSelector() {
return `[${attributeBase}]`;
}
}