Skip to content

Commit

Permalink
add back focus test. Another solution to fixing firefox bug using the…
Browse files Browse the repository at this point in the history
… onFocus of the overlay to always make the DaypickerInput focused, but do we wanth this?
  • Loading branch information
Bart Peeters committed Jan 20, 2018
1 parent dfb0b34 commit 73066ab
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 34 deletions.
64 changes: 30 additions & 34 deletions src/DayPickerInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ export default class DayPickerInput extends React.Component {
this.state.showOverlay = props.showOverlay;

this.hideAfterDayClick = this.hideAfterDayClick.bind(this);
this.handleContainerMouseDown = this.handleContainerMouseDown.bind(this);
this.handleInputClick = this.handleInputClick.bind(this);
this.handleInputFocus = this.handleInputFocus.bind(this);
this.handleInputBlur = this.handleInputBlur.bind(this);
Expand All @@ -123,6 +122,7 @@ export default class DayPickerInput extends React.Component {
this.handleInputKeyUp = this.handleInputKeyUp.bind(this);
this.handleDayClick = this.handleDayClick.bind(this);
this.handleMonthChange = this.handleMonthChange.bind(this);
this.handleOverlayFocus = this.handleOverlayFocus.bind(this);
}

componentWillReceiveProps(nextProps) {
Expand Down Expand Up @@ -203,7 +203,7 @@ export default class DayPickerInput extends React.Component {

input = null;
daypicker = null;
clickedInside = false;
overlayNode = null;
clickTimeout = null;
hideTimeout = null;

Expand Down Expand Up @@ -265,15 +265,6 @@ export default class DayPickerInput extends React.Component {
this.hideTimeout = setTimeout(() => this.hideDayPicker(), HIDE_TIMEOUT);
}

handleContainerMouseDown() {
this.clickedInside = true;
// The input's onBlur method is called from a queue right after the onMouseDown event.
// setTimeout adds another callback in the queue, which is called after the onBlur event.
this.clickTimeout = setTimeout(() => {
this.clickedInside = false;
}, 0);
}

handleInputClick(e) {
this.showDayPicker();
if (this.props.inputProps.onClick) {
Expand All @@ -291,19 +282,23 @@ export default class DayPickerInput extends React.Component {
}

handleInputBlur(e) {
if (this.clickedInside) {
this.showDayPicker();
// Force input's focus if blur event was caused by clicking inside the overlay
this.blurTimeout = setTimeout(() => this.input.focus(), 0);
} else {
this.hideDayPicker();
}
this.setState({
showOverlay: this.overlayNode && this.overlayNode.contains(e.relatedTarget),
});
if (this.props.inputProps.onBlur) {
e.persist();
this.props.inputProps.onBlur(e);
}
}

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();
}

handleInputChange(e) {
const {
dayPickerProps,
Expand Down Expand Up @@ -438,22 +433,24 @@ export default class DayPickerInput extends React.Component {
}
const Overlay = this.props.overlayComponent;
return (
<Overlay
classNames={classNames}
month={this.state.month}
selectedDay={selectedDay}
input={this.input}
>
<DayPicker
ref={el => (this.daypicker = el)}
onTodayButtonClick={onTodayButtonClick}
{...dayPickerProps}
<span onFocus={this.handleOverlayFocus} ref={(el) => this.overlayNode = el}>
<Overlay
classNames={classNames}
month={this.state.month}
selectedDays={selectedDay}
onDayClick={this.handleDayClick}
onMonthChange={this.handleMonthChange}
/>
</Overlay>
selectedDay={selectedDay}
input={this.input}
>
<DayPicker
ref={el => (this.daypicker = el)}
onTodayButtonClick={onTodayButtonClick}
{...dayPickerProps}
month={this.state.month}
selectedDays={selectedDay}
onDayClick={this.handleDayClick}
onMonthChange={this.handleMonthChange}
/>
</Overlay>
</span>
);
}

Expand All @@ -462,7 +459,6 @@ export default class DayPickerInput extends React.Component {
return (
<div
className={this.props.classNames.container}
onMouseDown={this.handleContainerMouseDown}
>
<Input
ref={el => (this.input = el)}
Expand Down
13 changes: 13 additions & 0 deletions test/daypickerinput/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ 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('change', () => {
Expand Down

0 comments on commit 73066ab

Please sign in to comment.