diff --git a/frontend/src/Components/Form/EnhancedSelectInput.js b/frontend/src/Components/Form/EnhancedSelectInput.js index 87b799a1b..80ee78e81 100644 --- a/frontend/src/Components/Form/EnhancedSelectInput.js +++ b/frontend/src/Components/Form/EnhancedSelectInput.js @@ -4,7 +4,7 @@ import React, { Component } from 'react'; import { Manager, Popper, Reference } from 'react-popper'; import classNames from 'classnames'; import getUniqueElememtId from 'Utilities/getUniqueElementId'; -import isMobileUtil from 'Utilities/isMobile'; +import { isMobile as isMobileUtil } from 'Utilities/mobile'; import * as keyCodes from 'Utilities/Constants/keyCodes'; import { icons, sizes, scrollDirections } from 'Helpers/Props'; import Icon from 'Components/Icon'; diff --git a/frontend/src/Components/Modal/Modal.css b/frontend/src/Components/Modal/Modal.css index b9d702f86..d7269ea46 100644 --- a/frontend/src/Components/Modal/Modal.css +++ b/frontend/src/Components/Modal/Modal.css @@ -29,6 +29,12 @@ overflow: hidden !important; } +.modalOpenIOS { + position: fixed; + right: 0; + left: 0; +} + /* * Sizes */ diff --git a/frontend/src/Components/Modal/Modal.js b/frontend/src/Components/Modal/Modal.js index 8dfe43433..ab2f58daa 100644 --- a/frontend/src/Components/Modal/Modal.js +++ b/frontend/src/Components/Modal/Modal.js @@ -4,6 +4,8 @@ import ReactDOM from 'react-dom'; import classNames from 'classnames'; import elementClass from 'element-class'; import getUniqueElememtId from 'Utilities/getUniqueElementId'; +import { isIOS } from 'Utilities/mobile'; +import { setScrollLock } from 'Utilities/scrollLock'; import * as keyCodes from 'Utilities/Constants/keyCodes'; import { sizes } from 'Helpers/Props'; import ErrorBoundary from 'Components/Error/ErrorBoundary'; @@ -69,7 +71,14 @@ class Modal extends Component { window.addEventListener('keydown', this.onKeyDown); if (openModals.length === 1) { - elementClass(document.body).add(styles.modalOpen); + if (isIOS()) { + setScrollLock(true); + const offset = document.body.scrollTop; + document.body.style.top = `${offset * -1}px`; + elementClass(document.body).add(styles.modalOpenIOS); + } else { + elementClass(document.body).add(styles.modalOpen); + } } } @@ -78,7 +87,15 @@ class Modal extends Component { window.removeEventListener('keydown', this.onKeyDown); if (openModals.length === 0) { - elementClass(document.body).remove(styles.modalOpen); + setScrollLock(false); + + if (isIOS()) { + const offset = parseInt(document.body.style.top); + elementClass(document.body).remove(styles.modalOpenIOS); + document.body.scrollTop = (offset * -1); + } else { + elementClass(document.body).remove(styles.modalOpen); + } } } diff --git a/frontend/src/Components/Page/PageContentBody.js b/frontend/src/Components/Page/PageContentBody.js index 81bd9b29b..5c277d8f5 100644 --- a/frontend/src/Components/Page/PageContentBody.js +++ b/frontend/src/Components/Page/PageContentBody.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import { isLocked } from 'Utilities/scrollLock'; import { scrollDirections } from 'Helpers/Props'; import OverlayScroller from 'Components/Scroller/OverlayScroller'; import Scroller from 'Components/Scroller/Scroller'; @@ -7,6 +8,17 @@ import styles from './PageContentBody.css'; class PageContentBody extends Component { + // + // Listeners + + onScroll = (props) => { + const { onScroll } = this.props; + + if (this.props.onScroll && !isLocked()) { + onScroll(props); + } + } + // // Render @@ -27,6 +39,7 @@ class PageContentBody extends Component { className={className} scrollDirection={scrollDirections.VERTICAL} {...otherProps} + onScroll={this.onScroll} >
{children} @@ -41,6 +54,7 @@ PageContentBody.propTypes = { innerClassName: PropTypes.string, isSmallScreen: PropTypes.bool.isRequired, children: PropTypes.node.isRequired, + onScroll: PropTypes.func, dispatch: PropTypes.func }; diff --git a/frontend/src/Components/Table/VirtualTable.js b/frontend/src/Components/Table/VirtualTable.js index a13807647..258d31b00 100644 --- a/frontend/src/Components/Table/VirtualTable.js +++ b/frontend/src/Components/Table/VirtualTable.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import { WindowScroller } from 'react-virtualized'; +import { isLocked } from 'Utilities/scrollLock'; import { scrollDirections } from 'Helpers/Props'; import Measure from 'Components/Measure'; import Scroller from 'Components/Scroller/Scroller'; @@ -83,6 +84,16 @@ class VirtualTable extends Component { } } + onScroll = (props) => { + if (isLocked()) { + return; + } + + const { onScroll } = this.props; + + onScroll(props); + } + // // Render @@ -107,7 +118,7 @@ class VirtualTable extends Component { {({ height, isScrolling }) => { return ( diff --git a/frontend/src/Components/Tooltip/Tooltip.js b/frontend/src/Components/Tooltip/Tooltip.js index ce9decc5a..3f8b5ad06 100644 --- a/frontend/src/Components/Tooltip/Tooltip.js +++ b/frontend/src/Components/Tooltip/Tooltip.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { Manager, Popper, Reference } from 'react-popper'; import classNames from 'classnames'; -import isMobileUtil from 'Utilities/isMobile'; +import { isMobile as isMobileUtil } from 'Utilities/mobile'; import { kinds, tooltipPositions } from 'Helpers/Props'; import Portal from 'Components/Portal'; import styles from './Tooltip.css'; diff --git a/frontend/src/Utilities/isMobile.js b/frontend/src/Utilities/isMobile.js deleted file mode 100644 index 489020a23..000000000 --- a/frontend/src/Utilities/isMobile.js +++ /dev/null @@ -1,7 +0,0 @@ -import MobileDetect from 'mobile-detect'; - -export default function isMobile() { - const mobileDetect = new MobileDetect(window.navigator.userAgent); - - return mobileDetect.mobile() != null; -} diff --git a/frontend/src/Utilities/mobile.js b/frontend/src/Utilities/mobile.js new file mode 100644 index 000000000..e52975963 --- /dev/null +++ b/frontend/src/Utilities/mobile.js @@ -0,0 +1,12 @@ +import MobileDetect from 'mobile-detect'; + +const mobileDetect = new MobileDetect(window.navigator.userAgent); + +export function isMobile() { + + return mobileDetect.mobile() != null; +} + +export function isIOS() { + return mobileDetect.is('iOS'); +} diff --git a/frontend/src/Utilities/scrollLock.js b/frontend/src/Utilities/scrollLock.js new file mode 100644 index 000000000..cff50a34b --- /dev/null +++ b/frontend/src/Utilities/scrollLock.js @@ -0,0 +1,13 @@ +// Allow iOS devices to disable scrolling of the body/virtual table +// when a modal is open. This will prevent focusing an input in a +// modal causing the modal to close due to scrolling. + +let scrollLock = false; + +export function isLocked() { + return scrollLock; +} + +export function setScrollLock(locked) { + scrollLock = locked; +}