diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2018-02-21 16:52:19 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2018-02-21 16:52:19 +0100 |
| commit | 722d5770606046137e2db42bdcf22928cf7d374e (patch) | |
| tree | f40bc8d35d90718cdaa2cea191efdae57b5ff32d | |
| parent | de0e4d9353c9e1fadd219fc794cf8809a0ce1904 (diff) | |
| parent | 7055d1b54171b95c1e29ca6b826c293bf87de9c2 (diff) | |
| download | mullvadvpn-722d5770606046137e2db42bdcf22928cf7d374e.tar.xz mullvadvpn-722d5770606046137e2db42bdcf22928cf7d374e.zip | |
Merge branch 'drop-non-standard-scrolling'
| -rw-r--r-- | app/components/Accordion.js | 17 | ||||
| -rw-r--r-- | app/components/CustomScrollbars.js | 40 | ||||
| -rw-r--r-- | app/components/SelectLocation.js | 14 |
3 files changed, 57 insertions, 14 deletions
diff --git a/app/components/Accordion.js b/app/components/Accordion.js index cdc6a69515..396f3455e1 100644 --- a/app/components/Accordion.js +++ b/app/components/Accordion.js @@ -24,17 +24,22 @@ export default class Accordion extends React.Component<AccordionProps, Accordion _containerElement: ?HTMLElement; _contentElement: ?HTMLElement; + constructor(props: AccordionProps) { + super(props); + + // set the initial height if it's known + if(props.height !== 'auto') { + this.state = { + computedHeight: props.height + }; + } + } + componentDidMount() { const containerElement = this._containerElement; if(!containerElement) { throw new Error('containerElement cannot be null'); } - - // update initial state - if(this.props.height !== Accordion.defaultProps.height) { - this._updateHeight(); - } - containerElement.addEventListener('transitionend', this._onTransitionEnd); } diff --git a/app/components/CustomScrollbars.js b/app/components/CustomScrollbars.js index 97c78f4ab9..cb1014fd0a 100644 --- a/app/components/CustomScrollbars.js +++ b/app/components/CustomScrollbars.js @@ -20,6 +20,8 @@ type State = { showScrollIndicators: boolean, }; +type ScrollPosition = 'top' | 'bottom' | 'middle'; + export default class CustomScrollbars extends React.Component<Props, State> { static defaultProps = { autoHide: true, @@ -35,6 +37,28 @@ export default class CustomScrollbars extends React.Component<Props, State> { _thumbElement: ?HTMLElement; _autoHideTimer: ?TimeoutID; + scrollTo(x: number, y: number) { + const scrollable = this._scrollableElement; + if(scrollable) { + scrollable.scrollLeft = x; + scrollable.scrollTop = y; + } + } + + scrollToElement(child: HTMLElement, scrollPosition: ScrollPosition) { + const scrollable = this._scrollableElement; + if(scrollable) { + // throw if child is not a descendant of scroll view + if(!scrollable.contains(child)) { + throw new Error('Cannot scroll to an element which is not a descendant of CustomScrollbars.'); + } + + const scrollTop = this._computeScrollTop(scrollable, child, scrollPosition); + + this.scrollTo(0, scrollTop); + } + } + componentDidMount() { this._updateScrollbarsHelper({ position: true, @@ -118,6 +142,22 @@ export default class CustomScrollbars extends React.Component<Props, State> { } } + _computeScrollTop(scrollable: HTMLElement, child: HTMLElement, scrollPosition: ScrollPosition) { + switch(scrollPosition) { + case 'top': + return child.offsetTop; + + case 'bottom': + return child.offsetTop - (scrollable.offsetHeight - child.clientHeight); + + case 'middle': + return child.offsetTop - ((scrollable.offsetHeight - child.clientHeight) * 0.5); + + default: + throw new Error(`Unknown enum type for ScrollPosition: ${ scrollPosition }`); + } + } + _computeThumbPosition(scrollable: HTMLElement, thumb: HTMLElement) { // the content height of the scroll view const scrollHeight = scrollable.scrollHeight; diff --git a/app/components/SelectLocation.js b/app/components/SelectLocation.js index 946a275146..88f1415b01 100644 --- a/app/components/SelectLocation.js +++ b/app/components/SelectLocation.js @@ -23,6 +23,7 @@ type State = { export default class SelectLocation extends React.Component<SelectLocationProps, State> { _selectedCell: ?HTMLElement; + _scrollView: ?CustomScrollbars; state = { expanded: [], @@ -48,13 +49,10 @@ export default class SelectLocation extends React.Component<SelectLocationProps, componentDidMount() { // restore scroll to selected cell const cell = this._selectedCell; - if(cell) { - // this is non-standard webkit method but it works great! - if(typeof(cell.scrollIntoViewIfNeeded) !== 'function') { - console.warn('HTMLElement.scrollIntoViewIfNeeded() is not available anymore! Please replace it with viable alternative.'); - return; - } - cell.scrollIntoViewIfNeeded(true); + const scrollView = this._scrollView; + + if(scrollView && cell) { + scrollView.scrollToElement(cell, 'middle'); } } @@ -70,7 +68,7 @@ export default class SelectLocation extends React.Component<SelectLocationProps, <h2 className="select-location__title">Select location</h2> </div> - <CustomScrollbars autoHide={ true }> + <CustomScrollbars autoHide={ true } ref={ (ref) => this._scrollView = ref }> <div> <div className="select-location__subtitle"> While connected, your real location is masked with a private and secure location in the selected region |
