Navigation Menu

Skip to content

Commit

Permalink
[fixed] Modal won't steal focus from children
Browse files Browse the repository at this point in the history
fixes #903
  • Loading branch information
jquense committed Jun 29, 2015
1 parent a8b177a commit 97ef415
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
25 changes: 22 additions & 3 deletions src/Modal.js
Expand Up @@ -101,6 +101,7 @@ const Modal = React.createClass({
animation: React.PropTypes.bool,
onRequestHide: React.PropTypes.func.isRequired,
dialogClassName: React.PropTypes.string,
autoFocus: React.PropTypes.bool,
enforceFocus: React.PropTypes.bool
},

Expand All @@ -111,6 +112,8 @@ const Modal = React.createClass({
keyboard: true,
animation: true,
closeButton: true,

autoFocus: true,
enforceFocus: true
};
},
Expand Down Expand Up @@ -205,6 +208,10 @@ const Modal = React.createClass({
React.findDOMNode(this.refs.backdrop).onclick = function () {};
},

componentWillMount(){
this.checkForFocus();
},

componentDidMount() {
const doc = domUtils.ownerDocument(this);
const win = domUtils.ownerWindow(this);
Expand Down Expand Up @@ -286,11 +293,23 @@ const Modal = React.createClass({
this.setState(this._getStyles());
},

checkForFocus(){
if ( domUtils.canUseDom ) {
try {
this.lastFocus = document.activeElement;
}
catch (e) {}
}
},

focusModalContent () {
if (this.props.enforceFocus) {
this.lastFocus = domUtils.activeElement(this);
let modalContent = React.findDOMNode(this.refs.modal);
let current = domUtils.activeElement(this);
let focusInModal = current && domUtils.contains(modalContent, current);

if (this.props.autoFocus && !focusInModal) {
this.lastFocus = current;

let modalContent = React.findDOMNode(this.refs.modal);
modalContent.focus();
}
},
Expand Down
36 changes: 34 additions & 2 deletions test/ModalSpec.js
Expand Up @@ -156,7 +156,7 @@ describe('Modal', function () {
}, 0);
});

it('Should not focus on the Modal when enforceFocus is false', function (done) {
it('Should not focus on the Modal when autoFocus is false', function (done) {

document.activeElement.should.equal(focusableContainer);

Expand All @@ -167,7 +167,7 @@ describe('Modal', function () {
render() {
if (this.state.modalOpen) {
return (
<Modal enforceFocus={false} onRequestHide={()=>{}} container={this}>
<Modal autoFocus={false} onRequestHide={()=>{}} container={this}>
<strong>Message</strong>
</Modal>
);
Expand All @@ -185,6 +185,38 @@ describe('Modal', function () {
done();
}, 0);
});

it('Should not focus Modal when child has focus', function (done) {

document.activeElement.should.equal(focusableContainer);

let Container = React.createClass({
getInitialState() {
return {modalOpen: true};
},
render() {
if (this.state.modalOpen) {
return (
<Modal onRequestHide={()=>{}} container={this}>
<input autoFocus />
</Modal>
);
} else {
return <span/>;
}
}
});

var instance = React.render(<Container />, focusableContainer);

setTimeout(function () {
let input = React.findDOMNode(
ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'input'))

document.activeElement.should.equal(input);
done();
}, 0);
});
});


Expand Down

2 comments on commit 97ef415

@taion
Copy link
Member

@taion taion commented on 97ef415 Jun 30, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This re-opens #842 because autoFocus isn't set to false on the ModalStatic.js example.

@jquense
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doh

Please sign in to comment.