Skip to content

Commit

Permalink
Add keepFocus prop, when true focusing the overlay will focus the
Browse files Browse the repository at this point in the history
input, when false focusing the overlay will let the event through
Add onBlur on overlay that hides the overlay
when clicked outside overlay ant not on input.
Add tests for keepFocus and overlayblur, these are hard because enzyme
focus and blur don't work like in a real browser: focusing the overlay
will not let actually focus it, body will still be focused, so we check
that the input is not focused when keepFocus is false.
  • Loading branch information
Bart Peeters committed Jan 20, 2018
1 parent 73066ab commit abd1e78
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
21 changes: 14 additions & 7 deletions src/DayPickerInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default class DayPickerInput extends React.Component {
dayPickerProps: PropTypes.object,
hideOnDayClick: PropTypes.bool,
clickUnselectsDay: PropTypes.bool,
keepFocus: PropTypes.bool,
component: PropTypes.any,
overlayComponent: PropTypes.any,

Expand Down Expand Up @@ -93,6 +94,7 @@ export default class DayPickerInput extends React.Component {
showOverlay: false,
hideOnDayClick: true,
clickUnselectsDay: false,
keepFocus: true,
component: 'input',
inputProps: {},
overlayComponent: ({ children, classNames }) => (
Expand Down Expand Up @@ -123,6 +125,7 @@ export default class DayPickerInput extends React.Component {
this.handleDayClick = this.handleDayClick.bind(this);
this.handleMonthChange = this.handleMonthChange.bind(this);
this.handleOverlayFocus = this.handleOverlayFocus.bind(this);
this.handleOverlayBlur = this.handleOverlayBlur.bind(this);
}

componentWillReceiveProps(nextProps) {
Expand Down Expand Up @@ -164,7 +167,6 @@ export default class DayPickerInput extends React.Component {
componentWillUnmount() {
clearTimeout(this.clickTimeout);
clearTimeout(this.hideTimeout);
clearTimeout(this.blurTimeout);
}

getStateFromProps(props) {
Expand Down Expand Up @@ -292,11 +294,16 @@ export default class DayPickerInput extends React.Component {
}

handleOverlayFocus(e) {
// do we want to always keep the input focused when clicking inside the overlay?
// what if we have a custom overlay that contains an input? this is now unusable...
// console.log(e.target.getAttribute('tabindex'), e.target.nodeName);
e.preventDefault();
this.input.focus();
if (this.props.keepFocus === true) {
e.preventDefault();
this.input.focus();
}
}

handleOverlayBlur(e) {
this.setState({
showOverlay: this.overlayNode && this.overlayNode.contains(e.relatedTarget),
});
}

handleInputChange(e) {
Expand Down Expand Up @@ -433,7 +440,7 @@ export default class DayPickerInput extends React.Component {
}
const Overlay = this.props.overlayComponent;
return (
<span onFocus={this.handleOverlayFocus} ref={(el) => this.overlayNode = el}>
<span onFocus={this.handleOverlayFocus} ref={(el) => this.overlayNode = el} onBlur={this.handleOverlayBlur}>
<Overlay
classNames={classNames}
month={this.state.month}
Expand Down
39 changes: 27 additions & 12 deletions test/daypickerinput/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ describe('DayPickerInput', () => {
});
});

describe('overlayfocus', () => {
afterEach(() => {
document.activeElement.blur();
});
it('should focus the input if keepFocus is true', () => {
const wrapper = mount(<DayPickerInput showOverlay={true} keepFocus={true} />);
wrapper.find('.DayPickerInput-Overlay').simulate('focus');
const instance = wrapper.instance();
expect(document.activeElement).toEqual(instance.input);
});
it('should not focus the input if keepFocus is false', () => {
const wrapper = mount(<DayPickerInput showOverlay={true} keepFocus={false} />);
wrapper.find('.DayPickerInput-Overlay').simulate('focus');
const instance = wrapper.instance();
expect(document.activeElement).not.toEqual(instance.input);
});
});

describe('blur', () => {
it('should hide the overlay when the input is blurred', () => {
const wrapper = mount(<DayPickerInput value="12/15/2017" />);
Expand All @@ -52,19 +70,16 @@ describe('DayPickerInput', () => {
wrapper.find('input').simulate('blur');
expect(onBlur).toHaveBeenCalledTimes(1);
});
});

it('should focus the input if blur after clicking the overlay', done => {
const wrapper = mount(<DayPickerInput />);
wrapper.find('.DayPickerInput').simulate('mousedown');
const instance = wrapper.instance();
expect(instance.clickedInside).toBe(true);
expect(instance.clickTimeout).not.toBeNull();
wrapper.find('input').simulate('blur');
setTimeout(() => {
expect(document.activeElement).toEqual(instance.input);
done();
}, 1);
});
describe('overlayblur', () => {
it('should hide the overlay', () => {
const wrapper = mount(<DayPickerInput showOverlay={true} keepFocus={true} />);
wrapper.find('.DayPickerInput-Overlay').simulate('focus');
wrapper.find('.DayPickerInput-Overlay').simulate('blur');
const instance = wrapper.instance();
expect(wrapper.find('.DayPicker')).toHaveLength(0);
});
});

describe('change', () => {
Expand Down

0 comments on commit abd1e78

Please sign in to comment.