From 1176db5593743de9d06bf426f3c03a1d96c34d6b Mon Sep 17 00:00:00 2001 From: Brian Dunn Date: Thu, 11 Jan 2018 14:31:10 -0700 Subject: [PATCH 1/5] chore: modal resize working, but removeEventListener has issues --- demo/ModalPage.js | 6 +++++- package.json | 1 + src/js/Modal.js | 47 ++++++++++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/demo/ModalPage.js b/demo/ModalPage.js index 0b895c1..5ce82ea 100644 --- a/demo/ModalPage.js +++ b/demo/ModalPage.js @@ -84,7 +84,11 @@ class ModalPage extends Component { footerVisible={false} cancelBtnHandler={() => this.setState({secondModalIsShown:false})} successBtnHandler={() => this.setState({secondModalIsShown:false})}> -

{text.bodyText}

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestias reprehenderit illum, incidunt corrupti laborum. Qui necessitatibus quisquam incidunt. Quos, inventore ullam? Odio delectus eum, quisquam nisi dolor eveniet laboriosam ab? + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestias reprehenderit illum, incidunt corrupti laborum. Qui necessitatibus quisquam incidunt. Quos, inventore ullam? Odio delectus eum, quisquam nisi dolor eveniet laboriosam ab? + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestias reprehenderit illum, incidunt corrupti laborum. Qui necessitatibus quisquam incidunt. Quos, inventore ullam? Odio delectus eum, quisquam nisi dolor eveniet laboriosam ab? +

{ - modalBody.className = (modalBody.offsetHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; - } - -}; + modalBody.className = (contentHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; +} export function _applyWrapper() { From 833eb73cdfffba946ce5fe397a62b3660bcd2832 Mon Sep 17 00:00:00 2001 From: Brian Dunn Date: Fri, 12 Jan 2018 11:09:07 -0700 Subject: [PATCH 2/5] chore: removeEventListener issue; small refactor --- src/js/Modal.js | 283 +++++++++++++++++++++++------------------------- 1 file changed, 133 insertions(+), 150 deletions(-) diff --git a/src/js/Modal.js b/src/js/Modal.js index 52b3b8b..5817895 100644 --- a/src/js/Modal.js +++ b/src/js/Modal.js @@ -17,18 +17,6 @@ export default class Modal extends Component { shiftTab: false, tab: false }; - - this.onClose = _onClose.bind(this); - this.renderFooter = _renderFooter.bind(this); - this.afterOpen = _afterOpen.bind(this); - this.setDimensions = _setDimensions.bind(this); - this.applyWrapper = _applyWrapper.bind(this); - this.removeWrapper = _removeWrapper.bind(this); - this.successBtnHandler = _successBtnHandler.bind(this); - this.cancelBtnHandler = _cancelBtnHandler.bind(this); - this.removeOverlayStyle = _removeOverlayStyle.bind(this); - this.handleKeyDown = _handleKeyDown.bind(this); - }; componentWillReceiveProps(nextProps) { @@ -39,11 +27,141 @@ export default class Modal extends Component { } componentWillUnmount() { - window.removeEventListener("resize", this.setDimensions); + window.removeEventListener("resize", this.resizeModal); } - + + handleKeyDown = (event) => { + if (!event.shiftKey && event.which === 9 && !this.state.tab) { + this.state.tab = true; + return; + } + + if (event.shiftKey && event.which === 9 && !this.state.shiftTab && !this.state.tab) { + event.preventDefault(); + this.state.shiftTab = true; + const tabbableConfig = { context: '.modalContent' }; + const tabbableElements = ally.query.tabbable(tabbableConfig); + tabbableElements[tabbableElements.length-1].focus(); + } + }; + + afterOpen = () => { + const modalContent = document.getElementsByClassName('modalContent')[0]; + + // apply accessibility wrapper if no appElement is given + if (!this.props.appElement) { + this.applyWrapper(); + } + + // apply Focus to close button on open... + modalContent.focus(); + modalContent.addEventListener('keydown', this.handleKeyDown); + + window.addEventListener("resize", this.resizeModal); + this.setDimensions(); + }; + + onClose = () => { + this.cancelBtnHandler(); + this.state.shiftTab = false; + this.state.tab = false; + window.removeEventListener("resize", this.resizeModal); + }; + + successBtnHandler = () => { + this.removeOverlayStyle(); + this.removeWrapper(); + this.props.successBtnHandler.call(this); + }; + + cancelBtnHandler = () => { + this.removeOverlayStyle(); + this.removeWrapper(); + this.props.cancelBtnHandler.call(this); + }; + + removeOverlayStyle = () => { + const modalBody = document.getElementsByClassName('modalBody')[0]; + const modalOverlay = document.getElementsByClassName('modalOverlay')[0]; + + modalBody.style.maxHeight = ''; + modalOverlay.style.paddingTop = ''; + modalOverlay.style.paddingBottom = ''; + }; + + resizeModal = debounce(() => { + this.setDimensions(); + }, 100); + + setDimensions = () => { + const modalBody = document.getElementsByClassName('modalBody')[0]; + const headerCloseButton = document.getElementsByClassName('modalClose')[0]; + const modalContent = document.getElementsByClassName('modalContent')[0]; + const modalOverlay = document.getElementsByClassName('modalOverlay')[0]; + const header = document.getElementsByClassName('modalHeader')[0]; + const footer = document.getElementsByClassName('modalFooter')[0]; + + // apply padding based on clientHeight... + const windowHeight = window.innerHeight; + const contentHeight = modalContent.offsetHeight; + const paddingHeight = (windowHeight - contentHeight) / 2; + const headerHeight = header.getBoundingClientRect().height; + const footerHeight = footer ? footer.getBoundingClientRect().height : 0; + + modalBody.style.maxHeight = this.props.scrollWithPage ? 'none' : `${windowHeight - (headerHeight + footerHeight + 120)}px`; + modalOverlay.style.paddingTop = paddingHeight > 0 ? `${paddingHeight}px` : '2%'; + + // conditional borders on modalbody if scrollbar is present... + modalBody.className = (contentHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; + }; + + applyWrapper = () => { + if (!document.getElementById('wrapper')) { + const wrapper = document.createElement('div'); + wrapper.id = 'wrapper'; + wrapper.setAttribute('aria-hidden', true); + + const excludedElement = document.getElementsByClassName('modalOverlay')[0].parentElement; + + while (document.body.firstChild) { + wrapper.appendChild(document.body.firstChild); + } + + document.body.appendChild(wrapper); + document.body.appendChild(excludedElement); + } + }; + + removeWrapper = () => { + const wrapper = document.getElementById('wrapper'); + if (!wrapper) { return; } + + wrapper.setAttribute('aria-hidden', false); + + const excludedElement = document.getElementsByClassName('modalOverlay')[0].parentElement; + + while (wrapper.firstChild) { + document.body.appendChild(wrapper.firstChild); + } + + document.body.removeChild(wrapper); + document.body.appendChild(excludedElement); + }; + + renderFooter = (footerVisible, text, disableSuccessBtn) => { + if (footerVisible) { + return ( +
+ + +
+ ) + } + }; + render() { - const { isShown, footerVisible, text, children, disableSuccessBtn, shouldCloseOnOverlayClick, hideCloseButton, srHeaderText, headerClass, scrollWithPage } = this.props; @@ -124,138 +242,3 @@ Modal.defaultProps = { scrollWithPage: false }; -function _handleKeyDown(event) { - - if (!event.shiftKey && event.which === 9 && !this.state.tab) { - this.state.tab = true; - return; - } - - if (event.shiftKey && event.which === 9 && !this.state.shiftTab && !this.state.tab) { - event.preventDefault(); - this.state.shiftTab = true; - const tabbableConfig = { context: '.modalContent' }; - const tabbableElements = ally.query.tabbable(tabbableConfig); - tabbableElements[tabbableElements.length-1].focus(); - } - -} - -export function _onClose() { - this.cancelBtnHandler(); - this.state.shiftTab = false; - this.state.tab = false; - window.removeEventListener("resize", this.setDimensions); -} - -export function _successBtnHandler() { - this.removeOverlayStyle(); - this.removeWrapper(); - this.props.successBtnHandler.call(this); -} - -export function _cancelBtnHandler() { - this.removeOverlayStyle(); - this.removeWrapper(); - this.props.cancelBtnHandler.call(this); -} - -export function _removeOverlayStyle() { - const modalBody = document.getElementsByClassName('modalBody')[0]; - const modalOverlay = document.getElementsByClassName('modalOverlay')[0]; - - modalBody.style.maxHeight = ''; - modalOverlay.style.paddingTop = ''; - modalOverlay.style.paddingBottom = ''; -} - -export function _afterOpen() { - const modalContent = document.getElementsByClassName('modalContent')[0]; - - // apply accessibility wrapper if no appElement is given - if (!this.props.appElement) { - this.applyWrapper(); - } - - // apply Focus to close button on open... - modalContent.focus(); - modalContent.addEventListener('keydown', this.handleKeyDown); - window.addEventListener("resize", debounce(this.setDimensions, 100)); - this.setDimensions(); -} - -export function _setDimensions() { - console.log('sizing...'); - if (!this.props.isShown) { - return; - } - const modalBody = document.getElementsByClassName('modalBody')[0]; - const headerCloseButton = document.getElementsByClassName('modalClose')[0]; - const modalContent = document.getElementsByClassName('modalContent')[0]; - const modalOverlay = document.getElementsByClassName('modalOverlay')[0]; - const header = document.getElementsByClassName('modalHeader')[0]; - const footer = document.getElementsByClassName('modalFooter')[0]; - - // apply padding based on clientHeight... - const windowHeight = window.innerHeight; - const contentHeight = modalContent.offsetHeight; - const paddingHeight = (windowHeight - contentHeight) / 2; - const padding = paddingHeight > 60 ? paddingHeight : 60; - const headerHeight = header.getBoundingClientRect().height; - const footerHeight = footer ? footer.getBoundingClientRect().height : 0; - - modalBody.style.maxHeight = this.props.scrollWithPage ? 'none' : `${windowHeight - (headerHeight + footerHeight + 120)}px`; - modalOverlay.style.paddingTop = `${padding}px`; - modalOverlay.style.paddingBottom = `${padding}px`; - - // conditional borders on modalbody if scrollbar is present... - modalBody.className = (contentHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; -} - -export function _applyWrapper() { - - if (!document.getElementById('wrapper')) { - - const wrapper = document.createElement('div'); - wrapper.id = 'wrapper'; - wrapper.setAttribute('aria-hidden', true); - - const excludedElement = document.getElementsByClassName('modalOverlay')[0].parentElement; - - while (document.body.firstChild) { - wrapper.appendChild(document.body.firstChild); - } - - document.body.appendChild(wrapper); - document.body.appendChild(excludedElement); - } - -}; - -export function _removeWrapper() { - const wrapper = document.getElementById('wrapper'); - if (!wrapper) { return; } - - wrapper.setAttribute('aria-hidden', false); - - const excludedElement = document.getElementsByClassName('modalOverlay')[0].parentElement; - - while (wrapper.firstChild) { - document.body.appendChild(wrapper.firstChild); - } - - document.body.removeChild(wrapper); - document.body.appendChild(excludedElement); -}; - -export function _renderFooter(footerVisible, text, disableSuccessBtn) { - if (footerVisible) { - return( -
- - -
- ) - }; - -}; From 83c3dedf18d87bc80cbb5c25c00a6772c7effaef Mon Sep 17 00:00:00 2001 From: Brian Dunn Date: Fri, 12 Jan 2018 14:44:21 -0700 Subject: [PATCH 3/5] fix: removing debounce since it looks way cooler without --- src/js/Modal.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/js/Modal.js b/src/js/Modal.js index 5817895..4f136b0 100644 --- a/src/js/Modal.js +++ b/src/js/Modal.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import { default as BaseModal } from 'react-modal'; import { Icon } from 'pearson-compounds'; import ally from 'ally.js'; -import debounce from 'lodash.debounce'; import '../scss/Modal.scss'; @@ -27,7 +26,7 @@ export default class Modal extends Component { } componentWillUnmount() { - window.removeEventListener("resize", this.resizeModal); + window.removeEventListener("resize", this.setDimensions); } handleKeyDown = (event) => { @@ -57,7 +56,7 @@ export default class Modal extends Component { modalContent.focus(); modalContent.addEventListener('keydown', this.handleKeyDown); - window.addEventListener("resize", this.resizeModal); + window.addEventListener("resize", this.setDimensions); this.setDimensions(); }; @@ -65,7 +64,7 @@ export default class Modal extends Component { this.cancelBtnHandler(); this.state.shiftTab = false; this.state.tab = false; - window.removeEventListener("resize", this.resizeModal); + window.removeEventListener("resize", this.setDimensions); }; successBtnHandler = () => { @@ -89,10 +88,6 @@ export default class Modal extends Component { modalOverlay.style.paddingBottom = ''; }; - resizeModal = debounce(() => { - this.setDimensions(); - }, 100); - setDimensions = () => { const modalBody = document.getElementsByClassName('modalBody')[0]; const headerCloseButton = document.getElementsByClassName('modalClose')[0]; From 5b5ba9c6806ce909d245f9fa998525aea026c918 Mon Sep 17 00:00:00 2001 From: Brian Dunn Date: Wed, 17 Jan 2018 15:55:25 -0700 Subject: [PATCH 4/5] fix: downgraded version of webpack-dev-server to work in all browsers, including IE 11 --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4072b57..b192dfd 100644 --- a/package.json +++ b/package.json @@ -90,16 +90,15 @@ "url-loader": "^0.5.7", "uuid": "2.0.2", "webpack": "^2.2.1", - "webpack-dev-server": "^2.3.0" + "webpack-dev-server": "~2.9.0" }, "keywords": [ "pearson-components" ], "dependencies": { "ally.js": "^1.4.1", - "lodash.debounce": "^4.0.8", "npm-scripts": "^1.4.0", - "pearson-compounds": "0.14.x", + "pearson-compounds": "0.17.x", "react-modal": "3.1.7" } } From 79981659830c12bb5591c7eef2d40d56f76eb8c3 Mon Sep 17 00:00:00 2001 From: Brian Dunn Date: Thu, 18 Jan 2018 15:20:17 -0700 Subject: [PATCH 5/5] fix: scrolling content not showing top and bottom border --- src/js/Modal.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/js/Modal.js b/src/js/Modal.js index 4f136b0..21ab6ab 100644 --- a/src/js/Modal.js +++ b/src/js/Modal.js @@ -98,8 +98,7 @@ export default class Modal extends Component { // apply padding based on clientHeight... const windowHeight = window.innerHeight; - const contentHeight = modalContent.offsetHeight; - const paddingHeight = (windowHeight - contentHeight) / 2; + const paddingHeight = (windowHeight - modalContent.offsetHeight) / 2; const headerHeight = header.getBoundingClientRect().height; const footerHeight = footer ? footer.getBoundingClientRect().height : 0; @@ -107,7 +106,7 @@ export default class Modal extends Component { modalOverlay.style.paddingTop = paddingHeight > 0 ? `${paddingHeight}px` : '2%'; // conditional borders on modalbody if scrollbar is present... - modalBody.className = (contentHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; + modalBody.className = (modalBody.offsetHeight < modalBody.scrollHeight && !headerCloseButton) ? 'modalBody modalBody_border' : 'modalBody modalBody_border_normal'; }; applyWrapper = () => {