Spaces:
Running
Running
Commit ·
b40e616
1
Parent(s): 5017b6c
Implement JavaScript-based sticky table header
Browse files- Created initStickyHeader() function that clones the header
- Cloned header is fixed at top of viewport when scrolling
- Dynamically matches column widths of original header
- Shows/hides based on scroll position
- Header appears when original scrolls out of view
- Works around overflow-x: auto limitation of pure CSS sticky
- index.html +43 -0
index.html
CHANGED
|
@@ -3349,6 +3349,46 @@ function filterByBenchmarks(selectedBenchmarks) {
|
|
| 3349 |
});
|
| 3350 |
}
|
| 3351 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3352 |
function init() {
|
| 3353 |
// Initialize benchmark filter (defaults to 10 benchmarks selected, excluding vision and embedding)
|
| 3354 |
initBenchmarkFilter();
|
|
@@ -3356,6 +3396,9 @@ function init() {
|
|
| 3356 |
// Initialize size filter
|
| 3357 |
initSizeFilter();
|
| 3358 |
|
|
|
|
|
|
|
|
|
|
| 3359 |
// Load dark mode preference
|
| 3360 |
if (localStorage.getItem('dark') === 'true') {
|
| 3361 |
document.body.classList.add('dark');
|
|
|
|
| 3349 |
});
|
| 3350 |
}
|
| 3351 |
|
| 3352 |
+
function initStickyHeader() {
|
| 3353 |
+
const table = document.getElementById('leaderboardTable');
|
| 3354 |
+
const thead = table.querySelector('thead');
|
| 3355 |
+
const tableWrapper = document.querySelector('.tw');
|
| 3356 |
+
|
| 3357 |
+
// Clone the header for sticky version
|
| 3358 |
+
const stickyHeader = thead.cloneNode(true);
|
| 3359 |
+
stickyHeader.id = 'stickyHeader';
|
| 3360 |
+
stickyHeader.style.cssText = 'position: fixed; top: 0; left: 0; right: 0; z-index: 1000; visibility: hidden; background: var(--surface-alt); box-shadow: 0 2px 8px rgba(0,0,0,0.15);';
|
| 3361 |
+
|
| 3362 |
+
// Match the width of columns
|
| 3363 |
+
const updateHeaderWidths = () => {
|
| 3364 |
+
const originalCells = thead.querySelectorAll('th');
|
| 3365 |
+
const stickyCells = stickyHeader.querySelectorAll('th');
|
| 3366 |
+
originalCells.forEach((cell, i) => {
|
| 3367 |
+
if (stickyCells[i]) {
|
| 3368 |
+
stickyCells[i].style.width = cell.offsetWidth + 'px';
|
| 3369 |
+
}
|
| 3370 |
+
});
|
| 3371 |
+
};
|
| 3372 |
+
|
| 3373 |
+
document.body.appendChild(stickyHeader);
|
| 3374 |
+
|
| 3375 |
+
// Show/hide sticky header based on scroll
|
| 3376 |
+
const handleScroll = () => {
|
| 3377 |
+
const tableRect = table.getBoundingClientRect();
|
| 3378 |
+
const theadRect = thead.getBoundingClientRect();
|
| 3379 |
+
|
| 3380 |
+
if (theadRect.top < 0 && tableRect.bottom > 50) {
|
| 3381 |
+
stickyHeader.style.visibility = 'visible';
|
| 3382 |
+
updateHeaderWidths();
|
| 3383 |
+
} else {
|
| 3384 |
+
stickyHeader.style.visibility = 'hidden';
|
| 3385 |
+
}
|
| 3386 |
+
};
|
| 3387 |
+
|
| 3388 |
+
window.addEventListener('scroll', handleScroll);
|
| 3389 |
+
window.addEventListener('resize', updateHeaderWidths);
|
| 3390 |
+
}
|
| 3391 |
+
|
| 3392 |
function init() {
|
| 3393 |
// Initialize benchmark filter (defaults to 10 benchmarks selected, excluding vision and embedding)
|
| 3394 |
initBenchmarkFilter();
|
|
|
|
| 3396 |
// Initialize size filter
|
| 3397 |
initSizeFilter();
|
| 3398 |
|
| 3399 |
+
// Initialize sticky header
|
| 3400 |
+
initStickyHeader();
|
| 3401 |
+
|
| 3402 |
// Load dark mode preference
|
| 3403 |
if (localStorage.getItem('dark') === 'true') {
|
| 3404 |
document.body.classList.add('dark');
|