Created
February 20, 2024 17:21
-
-
Save xTCry/fea4889c7f26ac650f0a375b6fb55b58 to your computer and use it in GitHub Desktop.
Revisions
-
xTCry created this gist
Feb 20, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,31 @@ # Sticky Scrollbar to bottom for table ```html <div class="table-responsive"> <table class="table"> <thead class="table-primary"> <tr> <th>ID</th> <th>Name</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Test 1</td> </tr> <tr> <td>2</td> <td>Test 2</td> </tr> </tbody> </table> </div> <script> // import './xtt.scroller-sticky.js'; $(() => { xtt_scrollerSticky('.table-responsive'); }); </script> ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,102 @@ function xtt_scrollerSticky(selectors = '') { if (!selectors) return; if (!this.styleInited) { const style = document.createElement('style'); style.innerHTML = ` .xtt-scroller { position: fixed; left: 0; right: 0; bottom: 0; overflow-x: scroll; display: none; } `; document.head.appendChild(style); this.styleInited = true; } const $containers = document.querySelectorAll(selectors); for (const $container of $containers) { if ($container.getElementsByClassName('xtt-scroller').length > 0) { break; } const $scroller = document.createElement('div'); $scroller.className = 'xtt-scroller'; $container.appendChild($scroller); const $scrollerContent = document.createElement('div'); $scrollerContent.style.height = '1px'; $scroller.appendChild($scrollerContent); let needUpdate = true; const scrollbarPositioner = () => { const scrollTop = document.scrollingElement.scrollTop; const wrapperTop = $container.offsetTop; const wrapperBottom = wrapperTop + $container.offsetHeight; const topMatch = window.innerHeight + scrollTop >= wrapperTop; const bottomMatch = scrollTop <= wrapperBottom; const hasHorizontalScrollbar = $container.scrollWidth > $container.clientWidth; const hasVerticalScrollbar = $container.scrollHeight > $container.clientHeight; if (topMatch && bottomMatch && hasHorizontalScrollbar) { const inside = wrapperBottom >= scrollTop && window.innerHeight + scrollTop <= wrapperBottom; if (inside) { // $scroller.style.bottom = "0px"; $scroller.style.display = 'block'; if (needUpdate) { $scroller.scrollLeft = $container.scrollLeft; needUpdate = false; } } else { needUpdate = true; // const offset = scrollTop + window.innerHeight - wrapperBottom; // $scroller.style.bottom = offset + "px"; $scroller.style.display = 'none'; } const pos = $container.getBoundingClientRect(); $scroller.style.width = ($container.offsetWidth - (hasVerticalScrollbar ? 17 : 0)) + "px"; $scroller.style.left = (pos.left /* + (pos.right - pos.width) */) + "px"; $scrollerContent.style.width = ($container.scrollWidth) + "px"; } else { $scroller.style.display = 'none'; } requestAnimationFrame(scrollbarPositioner); }; requestAnimationFrame(scrollbarPositioner); // Sync scrolling let ignoreScrollEvent = false; let animation = null; $scroller.addEventListener("scroll", (e) => { if (ignoreScrollEvent) return false; if (animation) cancelAnimationFrame(animation); animation = requestAnimationFrame(() => { ignoreScrollEvent = true; $container.scrollLeft = $scroller.scrollLeft; ignoreScrollEvent = false; }); }); $container.addEventListener("scroll", (e) => { if (ignoreScrollEvent) return false; if (animation) cancelAnimationFrame(animation); animation = requestAnimationFrame(() => { ignoreScrollEvent = true; $scroller.scrollLeft = $container.scrollLeft; ignoreScrollEvent = false; }); }); } } xtt_scrollerSticky.prototype.styleInited = false;