Skip to content

Commit dfdfece

Browse files
matkrzymartijnrusschen
authored andcommitted
Fix blur events (Hacker0x01#1522)
* Fix blur events * Clear input value on close
1 parent 4a91ae6 commit dfdfece

File tree

2 files changed

+137
-68
lines changed

2 files changed

+137
-68
lines changed

docs-site/bundle.js

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -35240,6 +35240,7 @@
3524035240
onFocus: function onFocus() {},
3524135241
onBlur: function onBlur() {},
3524235242
onKeyDown: function onKeyDown() {},
35243+
onInputClick: function onInputClick() {},
3524335244
onSelect: function onSelect() {},
3524435245
onClickOutside: function onClickOutside() {},
3524535246
onMonthChange: function onMonthChange() {},
@@ -35317,15 +35318,58 @@
3531735318
}
3531835319
};
3531935320

35321+
_this.setBlur = function() {
35322+
if (_this.input && _this.input.blur) {
35323+
_this.input.blur();
35324+
}
35325+
35326+
if (_this.props.onBlur) {
35327+
_this.props.onBlur();
35328+
}
35329+
35330+
_this.cancelFocusInput();
35331+
};
35332+
3532035333
_this.setOpen = function(open) {
35321-
_this.setState({
35322-
open: open,
35323-
preSelection:
35324-
open && _this.state.open
35325-
? _this.state.preSelection
35326-
: _this.calcInitialState().preSelection,
35327-
lastPreSelectChange: PRESELECT_CHANGE_VIA_NAVIGATE
35328-
});
35334+
var skipSetBlur =
35335+
arguments.length > 1 && arguments[1] !== undefined
35336+
? arguments[1]
35337+
: false;
35338+
35339+
_this.setState(
35340+
{
35341+
open: open,
35342+
preSelection:
35343+
open && _this.state.open
35344+
? _this.state.preSelection
35345+
: _this.calcInitialState().preSelection,
35346+
lastPreSelectChange: PRESELECT_CHANGE_VIA_NAVIGATE
35347+
},
35348+
function() {
35349+
if (!open) {
35350+
_this.setState(
35351+
function(prev) {
35352+
return {
35353+
focused: skipSetBlur ? prev.focused : false
35354+
};
35355+
},
35356+
function() {
35357+
!skipSetBlur && _this.setBlur();
35358+
35359+
_this.setState({ inputValue: null, preSelection: null });
35360+
}
35361+
);
35362+
}
35363+
}
35364+
);
35365+
};
35366+
35367+
_this.isCalendarOpen = function() {
35368+
return _this.props.open === undefined
35369+
? _this.state.open &&
35370+
!_this.props.disabled &&
35371+
!_this.props.readOnly
35372+
: _this.props.open;
3532935373
};
3533035374

3533135375
_this.handleFocus = function(event) {
@@ -35421,9 +35465,6 @@
3542135465
) {
3542235466
_this.setPreSelection(date);
3542335467
} else if (!_this.props.inline) {
35424-
_this.props.onBlur(date);
35425-
_this.cancelFocusInput();
35426-
3542735468
_this.setOpen(false);
3542835469
}
3542935470
};
@@ -35438,10 +35479,6 @@
3543835479
if ((0, _date_utils.isOutOfBounds)(changedDate, _this.props)) {
3543935480
_this.props.onChange(date, event);
3544035481
_this.props.onSelect(changedDate, event);
35441-
_this.setState({
35442-
inputValue: changedDate,
35443-
preSelection: changedDate
35444-
});
3544535482
}
3544635483

3544735484
return;
@@ -35525,6 +35562,8 @@
3552535562
if (!_this.props.disabled && !_this.props.readOnly) {
3552635563
_this.setOpen(true);
3552735564
}
35565+
35566+
_this.props.onInputClick();
3552835567
};
3552935568

3553035569
_this.onInputKeyDown = function(event) {
@@ -35552,22 +35591,14 @@
3555235591
_this.handleSelect(copy, event);
3555335592
!_this.props.shouldCloseOnSelect && _this.setPreSelection(copy);
3555435593
} else {
35555-
_this.input.blur();
35556-
_this.props.onBlur(copy);
35557-
_this.cancelFocusInput();
35558-
3555935594
_this.setOpen(false);
3556035595
}
3556135596
} else if (eventKey === "Escape") {
3556235597
event.preventDefault();
3556335598

35564-
_this.input.blur();
35565-
_this.props.onBlur(copy);
35566-
_this.cancelFocusInput();
35567-
3556835599
_this.setOpen(false);
3556935600
} else if (eventKey === "Tab") {
35570-
_this.setOpen(false);
35601+
_this.setOpen(false, true);
3557135602
} else if (!_this.props.disabledKeyboardNavigation) {
3557235603
var newSelection = void 0;
3557335604
switch (eventKey) {
@@ -35623,12 +35654,7 @@
3562335654
};
3562435655

3562535656
_this.renderCalendar = function() {
35626-
if (
35627-
!_this.props.inline &&
35628-
(!_this.state.open ||
35629-
_this.props.disabled ||
35630-
_this.props.readOnly)
35631-
) {
35657+
if (!_this.props.inline && !_this.isCalendarOpen()) {
3563235658
return null;
3563335659
}
3563435660
return _react2.default.createElement(
@@ -35838,8 +35864,7 @@
3583835864

3583935865
return _react2.default.createElement(_popper_component2.default, {
3584035866
className: this.props.popperClassName,
35841-
hidePopper:
35842-
!this.state.open || this.props.disabled || this.props.readOnly,
35867+
hidePopper: !this.isCalendarOpen(),
3584335868
popperModifiers: this.props.popperModifiers,
3584435869
targetComponent: _react2.default.createElement(
3584535870
"div",
@@ -35902,9 +35927,11 @@
3590235927
onClickOutside: _propTypes2.default.func,
3590335928
onChangeRaw: _propTypes2.default.func,
3590435929
onFocus: _propTypes2.default.func,
35930+
onInputClick: _propTypes2.default.func,
3590535931
onKeyDown: _propTypes2.default.func,
3590635932
onMonthChange: _propTypes2.default.func,
3590735933
onYearChange: _propTypes2.default.func,
35934+
open: _propTypes2.default.bool,
3590835935
openToDate: _propTypes2.default.object,
3590935936
peekNextMonth: _propTypes2.default.bool,
3591035937
placeholderText: _propTypes2.default.string,
@@ -35933,7 +35960,7 @@
3593335960
tabIndex: _propTypes2.default.number,
3593435961
timeCaption: _propTypes2.default.string,
3593535962
title: _propTypes2.default.string,
35936-
todayButton: _propTypes2.default.string,
35963+
todayButton: _propTypes2.default.node,
3593735964
useWeekdaysShort: _propTypes2.default.bool,
3593835965
formatWeekDay: _propTypes2.default.func,
3593935966
utcOffset: _propTypes2.default.oneOfType([
@@ -36819,7 +36846,10 @@
3681936846
};
3682036847

3682136848
_this.renderTimeSection = function() {
36822-
if (_this.props.showTimeSelect) {
36849+
if (
36850+
_this.props.showTimeSelect &&
36851+
(_this.state.monthContainer || _this.props.showTimeSelectOnly)
36852+
) {
3682336853
return _react2.default.createElement(_time2.default, {
3682436854
selected: _this.props.selected,
3682536855
onChange: _this.props.onTimeChange,
@@ -36844,7 +36874,7 @@
3684436874
_this.state = {
3684536875
date: _this.localizeDate(_this.getDateInView()),
3684636876
selectingDate: null,
36847-
monthContainer: _this.monthContainer
36877+
monthContainer: null
3684836878
};
3684936879
return _this;
3685036880
}
@@ -36970,7 +37000,7 @@
3697037000
showWeekNumbers: _propTypes2.default.bool,
3697137001
showYearDropdown: _propTypes2.default.bool,
3697237002
startDate: _propTypes2.default.object,
36973-
todayButton: _propTypes2.default.string,
37003+
todayButton: _propTypes2.default.node,
3697437004
useWeekdaysShort: _propTypes2.default.bool,
3697537005
formatWeekDay: _propTypes2.default.func,
3697637006
withPortal: _propTypes2.default.bool,
@@ -58854,7 +58884,17 @@
5885458884
{
5885558885
key: i,
5885658886
onClick: _this.handleClick.bind(_this, time),
58857-
className: _this.liClasses(time, currH, currM)
58887+
className: _this.liClasses(time, currH, currM),
58888+
ref: function ref(li) {
58889+
if (
58890+
(currH === (0, _date_utils.getHour)(time) &&
58891+
currM === (0, _date_utils.getMinute)(time)) ||
58892+
(currH === (0, _date_utils.getHour)(time) &&
58893+
!_this.centerLi)
58894+
) {
58895+
_this.centerLi = li;
58896+
}
58897+
}
5885858898
},
5885958899
(0, _date_utils.formatDate)(time, format)
5886058900
);
@@ -58867,19 +58907,21 @@
5886758907

5886858908
Time.prototype.componentDidMount = function componentDidMount() {
5886958909
// code to ensure selected time will always be in focus within time window when it first appears
58870-
var multiplier = 60 / this.props.intervals;
58871-
var currH = this.props.selected
58872-
? (0, _date_utils.getHour)(this.props.selected)
58873-
: (0, _date_utils.getHour)((0, _date_utils.newDate)());
58874-
this.list.scrollTop = 30 * (multiplier * currH);
58910+
this.list.scrollTop = Time.calcCenterPosition(
58911+
this.props.monthRef
58912+
? this.props.monthRef.clientHeight - this.header.clientHeight
58913+
: this.list.clientHeight,
58914+
this.centerLi
58915+
);
5887558916
};
5887658917

5887758918
Time.prototype.render = function render() {
5887858919
var _this2 = this;
5887958920

5888058921
var height = null;
58881-
if (this.props.monthRef) {
58882-
height = this.props.monthRef.clientHeight - 39;
58922+
if (this.props.monthRef && this.header) {
58923+
height =
58924+
this.props.monthRef.clientHeight - this.header.clientHeight;
5888358925
}
5888458926

5888558927
return _react2.default.createElement(
@@ -58895,7 +58937,10 @@
5889558937
"div",
5889658938
{
5889758939
className:
58898-
"react-datepicker__header react-datepicker__header--time"
58940+
"react-datepicker__header react-datepicker__header--time",
58941+
ref: function ref(header) {
58942+
_this2.header = header;
58943+
}
5889958944
},
5890058945
_react2.default.createElement(
5890158946
"div",
@@ -58948,14 +58993,22 @@
5894858993
intervals: _propTypes2.default.number,
5894958994
selected: _propTypes2.default.object,
5895058995
onChange: _propTypes2.default.func,
58951-
todayButton: _propTypes2.default.string,
58996+
todayButton: _propTypes2.default.node,
5895258997
minTime: _propTypes2.default.object,
5895358998
maxTime: _propTypes2.default.object,
5895458999
excludeTimes: _propTypes2.default.array,
5895559000
monthRef: _propTypes2.default.object,
5895659001
timeCaption: _propTypes2.default.string,
5895759002
injectTimes: _propTypes2.default.array
5895859003
};
59004+
59005+
Time.calcCenterPosition = function(listHeight, centerLiRef) {
59006+
return (
59007+
centerLiRef.offsetTop -
59008+
(listHeight / 2 - centerLiRef.clientHeight / 2)
59009+
);
59010+
};
59011+
5895959012
exports.default = Time;
5896059013

5896159014
/***/

src/index.jsx

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,43 @@ export default class DatePicker extends React.Component {
274274
}
275275
};
276276

277-
setOpen = open => {
278-
this.setState({
279-
open: open,
280-
preSelection:
281-
open && this.state.open
282-
? this.state.preSelection
283-
: this.calcInitialState().preSelection,
284-
lastPreSelectChange: PRESELECT_CHANGE_VIA_NAVIGATE
285-
});
277+
setBlur = () => {
278+
if (this.input && this.input.blur) {
279+
this.input.blur();
280+
}
281+
282+
if (this.props.onBlur) {
283+
this.props.onBlur();
284+
}
285+
286+
this.cancelFocusInput();
287+
};
288+
289+
setOpen = (open, skipSetBlur = false) => {
290+
this.setState(
291+
{
292+
open: open,
293+
preSelection:
294+
open && this.state.open
295+
? this.state.preSelection
296+
: this.calcInitialState().preSelection,
297+
lastPreSelectChange: PRESELECT_CHANGE_VIA_NAVIGATE
298+
},
299+
() => {
300+
if (!open) {
301+
this.setState(
302+
prev => ({
303+
focused: skipSetBlur ? prev.focused : false
304+
}),
305+
() => {
306+
!skipSetBlur && this.setBlur();
307+
308+
this.setState({ inputValue: null });
309+
}
310+
);
311+
}
312+
}
313+
);
286314
};
287315
inputOk = () =>
288316
isMoment(this.state.preSelection) || isDate(this.state.preSelection);
@@ -370,9 +398,6 @@ export default class DatePicker extends React.Component {
370398
if (!this.props.shouldCloseOnSelect || this.props.showTimeSelect) {
371399
this.setPreSelection(date);
372400
} else if (!this.props.inline) {
373-
this.props.onBlur(date);
374-
this.cancelFocusInput();
375-
376401
this.setOpen(false);
377402
}
378403
};
@@ -384,7 +409,6 @@ export default class DatePicker extends React.Component {
384409
if (isOutOfBounds(changedDate, this.props)) {
385410
this.props.onChange(date, event);
386411
this.props.onSelect(changedDate, event);
387-
this.setState({ inputValue: changedDate, preSelection: changedDate });
388412
}
389413

390414
return;
@@ -486,25 +510,17 @@ export default class DatePicker extends React.Component {
486510
this.handleSelect(copy, event);
487511
!this.props.shouldCloseOnSelect && this.setPreSelection(copy);
488512
} else {
489-
this.input.blur();
490-
this.props.onBlur(copy);
491-
this.cancelFocusInput();
492-
493513
this.setOpen(false);
494514
}
495515
} else if (eventKey === "Escape") {
496516
event.preventDefault();
497517

498-
this.input.blur();
499-
this.props.onBlur(copy);
500-
this.cancelFocusInput();
501-
502518
this.setOpen(false);
503519
if (!this.inputOk()) {
504520
this.props.onInputError({ code: 1, msg: INPUT_ERR_1 });
505521
}
506522
} else if (eventKey === "Tab") {
507-
this.setOpen(false);
523+
this.setOpen(false, true);
508524
} else if (!this.props.disabledKeyboardNavigation) {
509525
let newSelection;
510526
switch (eventKey) {

0 commit comments

Comments
 (0)