Untitled
unknown
javascript
10 months ago
5.2 kB
11
Indexable
/**
* Stores only the original vertical position of each header cell.
* If the screen width is below 992px, resets the header tile positions.
*/
const initializeHeaderTilePositions = () => {
if (!window.matchMedia('(min-width: 992px)').matches) {
resetHeaderTilePositions();
return;
}
const headerCells = document.querySelectorAll('thead .bundle-table__wrapper--cell');
if (!headerCells.length) return;
headerCells.forEach(headerCell => {
const cellRect = headerCell.getBoundingClientRect();
headerCell.dataset.originalTop = Math.round(cellRect.top + window.scrollY);
headerCell.style.setProperty('--fixed-header-height', `${Math.round(cellRect.height)}px`);
});
};
/**
* Removes stored originalTop positions from the dataset.
*/
const resetHeaderTilePositions = () => {
const headerCells = document.querySelectorAll('thead .bundle-table__wrapper--cell');
if (!headerCells.length) return;
headerCells.forEach(headerCell => {
delete headerCell.dataset.originalTop;
delete headerCell.dataset.originalBottom;
headerCell.style.removeProperty('--fixed-header-height');
});
};
/**
* Indicates whether the user is currently scrolling.
*/
let isUserScrolling = false;
/**
* Updates the position of header tiles for a sticky header effect.
*/
const updateHeaderTilePositions = () => {
// Prevent reentry if already scrolling
if (isUserScrolling) return;
isUserScrolling = true;
requestAnimationFrame(() => {
const headerCells = document.querySelectorAll('thead .bundle-table__wrapper--cell');
const tableContainer = document.querySelector('.bundle-table-container');
const priceCell = document.querySelector('.bundle-table__wrapper--cell--price');
if (!headerCells.length || !tableContainer || !priceCell) {
isUserScrolling = false;
return;
}
const containerRect = tableContainer.getBoundingClientRect();
const priceRect = priceCell.getBoundingClientRect();
const priceDistanceToTop = Math.round(priceRect.top);
headerCells.forEach(headerCell => {
const headerTile = headerCell.querySelector('.bundle-table__header-tile');
const originalTop = parseFloat(headerCell.dataset.originalTop);
if (!headerTile || isNaN(originalTop)) return;
const cellRect = headerCell.getBoundingClientRect();
const cellHeight = cellRect.height;
const offsetLeft = cellRect.left - containerRect.left;
const shouldFixHeader = window.scrollY > originalTop;
headerTile.classList.toggle('fixed', shouldFixHeader);
if (shouldFixHeader) {
// variable for parent left padding
const LEFT_OFFSET = 6;
headerTile.style.setProperty('--fixed-header-left', `${offsetLeft + LEFT_OFFSET}px`);
} else {
headerTile.style.removeProperty('--fixed-header-left');
}
const heightDifference = priceDistanceToTop - cellHeight;
if (cellHeight > priceDistanceToTop) {
const fixedHeaderTop = Math.max(heightDifference, -cellHeight);
headerTile.style.setProperty('--fixed-header-top', `${fixedHeaderTop}px`);
} else {
headerTile.style.removeProperty('--fixed-header-top');
}
});
isUserScrolling = false;
});
};
/**
* Monitors scroll events in the table container and updates header tiles accordingly.
*/
const monitorTableContainerScroll = () => {
const tableContainer = document.querySelector('.bundle-table-container');
if (!tableContainer) return;
tableContainer.addEventListener('scroll', () => {
if (window.matchMedia('(min-width: 992px)').matches) {
initializeHeaderTilePositions();
updateHeaderTilePositions();
} else {
resetHeaderTilePositions();
resetHeaderTileStyles();
}
});
};
/**
* Resets the styles applied to header tiles (removes the 'fixed' class and inline styles).
*/
const resetHeaderTileStyles = () => {
const headerCells = document.querySelectorAll('thead .bundle-table__wrapper--cell');
if (!headerCells.length) return;
headerCells.forEach(headerCell => {
const headerTile = headerCell.querySelector('.bundle-table__header-tile');
if (!headerTile) return;
headerTile.classList.remove('fixed');
headerTile.style.removeProperty('--fixed-header-left');
headerTile.style.removeProperty('--fixed-header-top');
});
};
/**
* Handles window resize events to re-initialize or reset header tile positions/styles.
*/
const handleWindowResize = () => {
if (window.matchMedia('(min-width: 992px)').matches) {
initializeHeaderTilePositions();
updateHeaderTilePositions();
} else {
resetHeaderTilePositions();
resetHeaderTileStyles();
}
};
Editor is loading...
Leave a Comment