diff options
Diffstat (limited to 'src/client/scripts')
| -rw-r--r-- | src/client/scripts/sticky-sidebar.ts | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/client/scripts/sticky-sidebar.ts b/src/client/scripts/sticky-sidebar.ts new file mode 100644 index 0000000000..872e162d2b --- /dev/null +++ b/src/client/scripts/sticky-sidebar.ts @@ -0,0 +1,43 @@ +export class StickySidebar { + private lastScrollTop = 0; + private el: HTMLElement; + private spacer: HTMLElement; + private marginTop: number; + private isTop = false; + private isBottom = false; + + constructor(el: StickySidebar['el'], spacer: StickySidebar['spacer'], marginTop = 0) { + this.el = el; + this.spacer = spacer; + this.marginTop = marginTop; + } + + public calc(scrollTop: number) { + if (scrollTop > this.lastScrollTop) { // downscroll + const overflow = this.el.clientHeight - window.innerHeight; + this.el.style.bottom = null; + this.el.style.top = `${-overflow}px`; + + this.isBottom = (scrollTop + window.innerHeight) >= (this.el.offsetTop + this.el.clientHeight); + + if (this.isTop) { + this.isTop = false; + this.spacer.style.marginTop = `${scrollTop}px`; + } + } else { // upscroll + const overflow = this.el.clientHeight - window.innerHeight; + this.el.style.top = null; + this.el.style.bottom = `${-overflow - this.marginTop}px`; + + this.isTop = scrollTop <= this.el.offsetTop; + + if (this.isBottom) { + this.isBottom = false; + const overflow = this.el.clientHeight - window.innerHeight; + this.spacer.style.marginTop = `${scrollTop - (overflow + this.marginTop)}px`; + } + } + + this.lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; + } +} |