diff --git a/docs/examples/ModalStatic.js b/docs/examples/ModalStatic.js index 545efbee73..f01a4d058e 100644 --- a/docs/examples/ModalStatic.js +++ b/docs/examples/ModalStatic.js @@ -1,6 +1,7 @@ const modalInstance = (
document.detachEvent('onfocusin', handler); + } else { + document.addEventListener('focus', handler, true); + remove = () => document.removeEventListener('focus', handler, true); + } + return { remove }; +} + +let scrollbarSize; if ( domUtils.canUseDom) { let scrollDiv = document.createElement('div'); @@ -60,7 +82,8 @@ const Modal = React.createClass({ closeButton: React.PropTypes.bool, animation: React.PropTypes.bool, onRequestHide: React.PropTypes.func.isRequired, - dialogClassName: React.PropTypes.string + dialogClassName: React.PropTypes.string, + enforceFocus: React.PropTypes.bool }, getDefaultProps() { @@ -69,10 +92,15 @@ const Modal = React.createClass({ backdrop: true, keyboard: true, animation: true, - closeButton: true + closeButton: true, + enforceFocus: true }; }, + getInitialState(){ + return { }; + }, + render() { let state = this.state; let modalStyle = { ...state.dialogStyles, display: 'block'}; @@ -107,7 +135,7 @@ const Modal = React.createClass({ ); return this.props.backdrop ? - this.renderBackdrop(modal) : modal; + this.renderBackdrop(modal, state.backdropStyles) : modal; }, renderBackdrop(modal) { @@ -132,8 +160,8 @@ const Modal = React.createClass({ let closeButton; if (this.props.closeButton) { closeButton = ( - - ); + + ); } return ( @@ -169,6 +197,10 @@ const Modal = React.createClass({ this._onWindowResizeListener = EventListener.listen(win, 'resize', this.handleWindowResize); + if (this.props.enforceFocus) { + this._onFocusinListener = onFocus(this, this.enforceFocus); + } + let container = getContainer(this); container.className += container.className.length ? ' modal-open' : 'modal-open'; @@ -199,6 +231,10 @@ const Modal = React.createClass({ this._onDocumentKeyupListener.remove(); this._onWindowResizeListener.remove(); + if (this._onFocusinListener) { + this._onFocusinListener.remove(); + } + let container = getContainer(this); container.className = container.className.replace(/ ?modal-open/, ''); @@ -237,6 +273,19 @@ const Modal = React.createClass({ } }, + enforceFocus() { + if ( !this.isMounted() ) { + return; + } + + let active = domUtils.activeElement(this) + , modal = React.findDOMNode(this.refs.modal); + + if (modal !== active && !domUtils.contains(modal, active)){ + modal.focus(); + } + }, + _getStyles() { if ( !domUtils.canUseDom ) { return {}; } diff --git a/src/utils/domUtils.js b/src/utils/domUtils.js index ae56eb210d..31fa7c0340 100644 --- a/src/utils/domUtils.js +++ b/src/utils/domUtils.js @@ -26,6 +26,20 @@ function ownerWindow(componentOrElement) { : doc.parentWindow; } +/** + * get the active element, safe in IE + * @return {HTMLElement} + */ +function getActiveElement(componentOrElement){ + let doc = ownerDocument(componentOrElement); + + try { + return doc.activeElement || doc.body; + } catch (e) { + return doc.body; + } +} + /** * Shortcut to compute element style * @@ -160,5 +174,6 @@ export default { getComputedStyles, getOffset, getPosition, + activeElement: getActiveElement, offsetParent: offsetParentFunc };