From e67d9c6d4f04bc518f18af413bc72252c4b2b3f2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 18 Dec 2018 14:29:42 +0100 Subject: [PATCH] forward checkOverflow to AutoHideScrollbar, fix over/underflow detection the overflow/underflow events are not always reliable in nooverlay browsers (FF), so forward the checkOverflow call we need anyway for the scroll indicator gradients to see if we need to do the margin trick for the on-hover scrollbar we use in nooverlay browsers. this fixes on hover jumping in a subroomlist --- .../structures/AutoHideScrollbar.js | 33 ++++++++++++----- .../structures/IndicatorScrollbar.js | 37 ++++++++++++------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/components/structures/AutoHideScrollbar.js b/src/components/structures/AutoHideScrollbar.js index a328d478bc..1098f96a76 100644 --- a/src/components/structures/AutoHideScrollbar.js +++ b/src/components/structures/AutoHideScrollbar.js @@ -69,6 +69,7 @@ export default class AutoHideScrollbar extends React.Component { this.onOverflow = this.onOverflow.bind(this); this.onUnderflow = this.onUnderflow.bind(this); this._collectContainerRef = this._collectContainerRef.bind(this); + this._needsOverflowListener = null; } onOverflow() { @@ -81,21 +82,32 @@ export default class AutoHideScrollbar extends React.Component { this.containerRef.classList.add("mx_AutoHideScrollbar_underflow"); } + checkOverflow() { + if (!this._needsOverflowListener) { + return; + } + if (this.containerRef.scrollHeight > this.containerRef.clientHeight) { + this.onOverflow(); + } else { + this.onUnderflow(); + } + } + + componentDidUpdate() { + this.checkOverflow(); + } + + componentDidMount() { + this.checkOverflow(); + } + _collectContainerRef(ref) { if (ref && !this.containerRef) { this.containerRef = ref; - const needsOverflowListener = - document.body.classList.contains("mx_scrollbar_nooverlay"); - - if (needsOverflowListener) { + if (this._needsOverflowListener) { this.containerRef.addEventListener("overflow", this.onOverflow); this.containerRef.addEventListener("underflow", this.onUnderflow); } - if (ref.scrollHeight > ref.clientHeight) { - this.onOverflow(); - } else { - this.onUnderflow(); - } } if (this.props.wrappedRef) { this.props.wrappedRef(ref); @@ -111,6 +123,9 @@ export default class AutoHideScrollbar extends React.Component { render() { installBodyClassesIfNeeded(); + if (this._needsOverflowListener === null) { + this._needsOverflowListener = document.body.classList.contains("mx_scrollbar_nooverlay"); + } return (
0; - const hasBottomOverflow = this._scroller.scrollHeight > - (this._scroller.scrollTop + this._scroller.clientHeight); + const hasTopOverflow = this._scrollElement.scrollTop > 0; + const hasBottomOverflow = this._scrollElement.scrollHeight > + (this._scrollElement.scrollTop + this._scrollElement.clientHeight); if (hasTopOverflow) { - this._scroller.classList.add("mx_IndicatorScrollbar_topOverflow"); + this._scrollElement.classList.add("mx_IndicatorScrollbar_topOverflow"); } else { - this._scroller.classList.remove("mx_IndicatorScrollbar_topOverflow"); + this._scrollElement.classList.remove("mx_IndicatorScrollbar_topOverflow"); } if (hasBottomOverflow) { - this._scroller.classList.add("mx_IndicatorScrollbar_bottomOverflow"); + this._scrollElement.classList.add("mx_IndicatorScrollbar_bottomOverflow"); } else { - this._scroller.classList.remove("mx_IndicatorScrollbar_bottomOverflow"); + this._scrollElement.classList.remove("mx_IndicatorScrollbar_bottomOverflow"); + } + + if (this._autoHideScrollbar) { + this._autoHideScrollbar.checkOverflow(); } } componentWillUnmount() { - if (this._scroller) { - this._scroller.removeEventListener("scroll", this.checkOverflow); + if (this._scrollElement) { + this._scrollElement.removeEventListener("scroll", this.checkOverflow); } } render() { - return ( + return ( { this.props.children } ); }