From aca70af6e6cdbb4cceef16b3fad848663beed824 Mon Sep 17 00:00:00 2001 From: Alejandro Sellero Date: Thu, 23 Apr 2015 15:27:10 +0200 Subject: [PATCH 1/3] - Bugfix selecting days from previous or next month from the current viewed month. - Bugfix adding keys to children in year and month view. - Feature adding different modes to be able to have datepicker, timepicker, or datetimepicker. --- examples/basic/basic.jsx | 104 ++++++++++++++++++++-------------- src/Constants.jsx | 5 ++ src/DateTimeField.jsx | 60 +++++++++++++------- src/DateTimePicker.jsx | 17 +++++- src/DateTimePickerHours.jsx | 16 +++++- src/DateTimePickerMinutes.jsx | 16 +++++- src/DateTimePickerMonths.jsx | 2 +- src/DateTimePickerTime.jsx | 21 ++++--- src/DateTimePickerYears.jsx | 2 +- 9 files changed, 164 insertions(+), 79 deletions(-) create mode 100644 src/Constants.jsx diff --git a/examples/basic/basic.jsx b/examples/basic/basic.jsx index b19c83c2..d14aa114 100644 --- a/examples/basic/basic.jsx +++ b/examples/basic/basic.jsx @@ -4,52 +4,70 @@ var DateTimeField = require('react-bootstrap-datetimepicker'); var Basic = React.createClass({ render: function() { - return
-
-
-

React Bootstrap DateTimePicker

- This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker for React.js -
-
-
-
- Default Basic Example - -
 {''} 
-
-
-
-
- Example with default Text - -
 {''} 
-
-
-
-
- ViewMode set to years view with custom inputFormat - +
+
+

React Bootstrap DateTimePicker

+ This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker for React.js +
+
+
+
+ Default Basic Example + +
 {''} 
+
+
+
+
+ Example with default Text + -
 {''} 
-
-
-
-
- daysOfWeekDisabled - {''} +
+
+
+
+ ViewMode set to years view with custom inputFormat + -
 {''} 
- -
-
-
; +
 {''} 
+
+
+
+
+ daysOfWeekDisabled + +
 {''} 
+
+
+
+
+ daysOfWeekDisabled + +
 {''} 
+
+
+
+
+ daysOfWeekDisabled + +
 {''} 
+
+
+ + ); } - }); diff --git a/src/Constants.jsx b/src/Constants.jsx new file mode 100644 index 00000000..9036c9d8 --- /dev/null +++ b/src/Constants.jsx @@ -0,0 +1,5 @@ +module.exports = { + MODE_DATE: 'date', + MODE_DATETIME: 'datetime', + MODE_TIME: 'time' +}; \ No newline at end of file diff --git a/src/DateTimeField.jsx b/src/DateTimeField.jsx index 0cf02890..40432364 100644 --- a/src/DateTimeField.jsx +++ b/src/DateTimeField.jsx @@ -8,32 +8,46 @@ moment = require('moment'); Glyphicon = require('react-bootstrap').Glyphicon; +Constants = require('./Constants'); + DateTimeField = React.createClass({ propTypes: { dateTime: React.PropTypes.string, onChange: React.PropTypes.func, format: React.PropTypes.string, - inputFormat: React.PropTypes.string, inputProps: React.PropTypes.object, - defaultText: React.PropTypes.string + inputFormat: React.PropTypes.string, + defaultText: React.PropTypes.string, + mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME]) }, getDefaultProps: function() { return { dateTime: moment().format('x'), format: 'x', - inputFormat: "MM/DD/YY h:mm A", showToday: true, viewMode: 'days', daysOfWeekDisabled: [], - onChange: function (x) { - console.log(x); - } + mode: Constants.MODE_DATETIME, + onChange: function (x) {} }; }, + resolvePropsInputFormat: function() { + if(this.props.inputFormat) return this.props.inputFormat; + switch(this.props.mode) { + case Constants.MODE_TIME: + return "h:mm A"; + case Constants.MODE_DATE: + return "MM/DD/YY"; + default: + return "MM/DD/YY h:mm A"; + } + }, getInitialState: function() { return { - showDatePicker: true, - showTimePicker: false, + showDatePicker: this.props.mode !== Constants.MODE_TIME, + showTimePicker: this.props.mode === Constants.MODE_TIME, + inputFormat: this.resolvePropsInputFormat(), + buttonIcon: this.props.mode === Constants.MODE_TIME ? "time" : "calendar", widgetStyle: { display: 'block', position: 'absolute', @@ -42,7 +56,7 @@ DateTimeField = React.createClass({ }, viewDate: moment(this.props.dateTime, this.props.format, true).startOf("month"), selectedDate: moment(this.props.dateTime, this.props.format, true), - inputValue: typeof this.props.defaultText != 'undefined' ? this.props.defaultText : moment(this.props.dateTime, this.props.format, true).format(this.props.inputFormat) + inputValue: typeof this.props.defaultText != 'undefined' ? this.props.defaultText : moment(this.props.dateTime, this.props.format, true).format(this.resolvePropsInputFormat()) }; }, componentWillReceiveProps: function(nextProps) { @@ -56,28 +70,33 @@ DateTimeField = React.createClass({ }, onChange: function(event) { var value = event.target == null ? event : event.target.value; - if (moment(value, this.props.inputFormat, true).isValid()) { + if (moment(value, this.state.inputFormat, true).isValid()) { this.setState({ - selectedDate: moment(value, this.props.inputFormat, true), - viewDate: moment(value, this.props.inputFormat, true).startOf("month") + selectedDate: moment(value, this.state.inputFormat, true), + viewDate: moment(value, this.state.inputFormat, true).startOf("month") }); } return this.setState({ inputValue: value }, function() { - return this.props.onChange(moment(this.state.inputValue, this.props.inputFormat, true).format(this.props.format)); + return this.props.onChange(moment(this.state.inputValue, this.state.inputFormat, true).format(this.props.format)); }); }, setSelectedDate: function(e) { + var target = e.target; + var month; + if(target.className.includes("new")) month = this.state.viewDate.month() + 1; + else if(target.className.includes("old")) month = this.state.viewDate.month() - 1; + else month = this.state.viewDate.month(); return this.setState({ - selectedDate: this.state.viewDate.clone().date(parseInt(e.target.innerHTML)).hour(this.state.selectedDate.hours()).minute(this.state.selectedDate.minutes()) + selectedDate: this.state.viewDate.clone().month(month).date(parseInt(e.target.innerHTML)).hour(this.state.selectedDate.hours()).minute(this.state.selectedDate.minutes()) }, function() { this.closePicker(); this.props.onChange(this.state.selectedDate.format(this.props.format)); return this.setState({ - inputValue: this.state.selectedDate.format(this.props.inputFormat) + inputValue: this.state.selectedDate.format(this.state.inputFormat) }); }); }, @@ -88,7 +107,7 @@ DateTimeField = React.createClass({ this.closePicker(); this.props.onChange(this.state.selectedDate.format(this.props.format)); return this.setState({ - inputValue: this.state.selectedDate.format(this.props.inputFormat) + inputValue: this.state.selectedDate.format(this.state.inputFormat) }); }); }, @@ -99,7 +118,7 @@ DateTimeField = React.createClass({ this.closePicker(); this.props.onChange(this.state.selectedDate.format(this.props.format)); return this.setState({ - inputValue: this.state.selectedDate.format(this.props.inputFormat) + inputValue: this.state.selectedDate.format(this.state.inputFormat) }); }); }, @@ -173,9 +192,9 @@ DateTimeField = React.createClass({ }, togglePeriod: function() { if (this.state.selectedDate.hour() > 12) { - return this.onChange(this.state.selectedDate.clone().subtract(12, 'hours').format(this.props.inputFormat)); + return this.onChange(this.state.selectedDate.clone().subtract(12, 'hours').format(this.state.inputFormat)); } else { - return this.onChange(this.state.selectedDate.clone().add(12, 'hours').format(this.props.inputFormat)); + return this.onChange(this.state.selectedDate.clone().add(12, 'hours').format(this.state.inputFormat)); } }, togglePicker: function() { @@ -268,6 +287,7 @@ DateTimeField = React.createClass({ showToday={this.props.showToday} viewMode={this.props.viewMode} daysOfWeekDisabled={this.props.daysOfWeekDisabled} + mode={this.props.mode} addDecade={this.addDecade} addYear={this.addYear} addMonth={this.addMonth} @@ -288,7 +308,7 @@ DateTimeField = React.createClass({ />
- +
); diff --git a/src/DateTimePicker.jsx b/src/DateTimePicker.jsx index 5df49a57..9cfddd98 100644 --- a/src/DateTimePicker.jsx +++ b/src/DateTimePicker.jsx @@ -8,6 +8,8 @@ DateTimePickerTime = require('./DateTimePickerTime'); Glyphicon = require('react-bootstrap').Glyphicon; +Constants = require('./Constants'); + DateTimePicker = React.createClass({ propTypes: { showDatePicker: React.PropTypes.bool, @@ -21,6 +23,7 @@ DateTimePicker = React.createClass({ React.PropTypes.string, React.PropTypes.number ]), + mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME]), daysOfWeekDisabled: React.PropTypes.array, setSelectedDate: React.PropTypes.func.isRequired, subtractYear: React.PropTypes.func.isRequired, @@ -73,11 +76,21 @@ DateTimePicker = React.createClass({ addMinute={this.props.addMinute} subtractMinute={this.props.subtractMinute} togglePeriod={this.props.togglePeriod} + mode={this.props.mode} /> ); } }, + renderSwitchButton: function() { + return this.props.mode === Constants.MODE_DATETIME ? + ( +
  • + +
  • + ) : + null; + }, render: function() { return (
    @@ -86,9 +99,7 @@ DateTimePicker = React.createClass({ {this.renderDatePicker()} -
  • - -
  • + {this.renderSwitchButton()} {this.renderTimePicker()} diff --git a/src/DateTimePickerHours.jsx b/src/DateTimePickerHours.jsx index 05832a1d..a404c989 100644 --- a/src/DateTimePickerHours.jsx +++ b/src/DateTimePickerHours.jsx @@ -1,14 +1,28 @@ var DateTimePickerHours, React; React = require('react'); +Glyphicon = require('react-bootstrap').Glyphicon; DateTimePickerHours = React.createClass({ propTypes: { - setSelectedHour: React.PropTypes.func.isRequired + setSelectedHour: React.PropTypes.func.isRequired, + onSwitch: React.PropTypes.func.isRequired + }, + renderSwitchButton: function() { + return this.props.mode === Constants.MODE_TIME ? + ( + + ) : + null; }, render: function() { return (
    + {this.renderSwitchButton()} diff --git a/src/DateTimePickerMinutes.jsx b/src/DateTimePickerMinutes.jsx index fe9784d7..0849b87a 100644 --- a/src/DateTimePickerMinutes.jsx +++ b/src/DateTimePickerMinutes.jsx @@ -1,14 +1,28 @@ var DateTimePickerMinutes, React; React = require('react'); +Glyphicon = require('react-bootstrap').Glyphicon; DateTimePickerMinutes = React.createClass({ propTypes: { - setSelectedMinute: React.PropTypes.func.isRequired + setSelectedMinute: React.PropTypes.func.isRequired, + onSwitch: React.PropTypes.func.isRequired + }, + renderSwitchButton: function() { + return this.props.mode === Constants.MODE_TIME ? + ( +
      +
    • + +
    • +
    + ) : + null; }, render: function() { return (
    + {this.renderSwitchButton()}
    diff --git a/src/DateTimePickerMonths.jsx b/src/DateTimePickerMonths.jsx index 6b723653..354bf16a 100644 --- a/src/DateTimePickerMonths.jsx +++ b/src/DateTimePickerMonths.jsx @@ -24,7 +24,7 @@ DateTimePickerMonths = React.createClass({ month: true, 'active': i === month && this.props.viewDate.year() === this.props.selectedDate.year() }; - months.push({monthsShort[i]}); + months.push({monthsShort[i]}); i++; } return months; diff --git a/src/DateTimePickerTime.jsx b/src/DateTimePickerTime.jsx index 66aca42a..172e804d 100644 --- a/src/DateTimePickerTime.jsx +++ b/src/DateTimePickerTime.jsx @@ -8,6 +8,8 @@ DateTimePickerHours = require('./DateTimePickerHours'); Glyphicon = require('react-bootstrap').Glyphicon; +Constants = require('./Constants'); + DateTimePickerTime = React.createClass({ propTypes: { setSelectedHour: React.PropTypes.func.isRequired, @@ -18,7 +20,8 @@ DateTimePickerTime = React.createClass({ addMinute: React.PropTypes.func.isRequired, viewDate: React.PropTypes.object.isRequired, selectedDate: React.PropTypes.object.isRequired, - togglePeriod: React.PropTypes.func.isRequired + togglePeriod: React.PropTypes.func.isRequired, + mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME]) }, getInitialState: function() { return { @@ -26,6 +29,12 @@ DateTimePickerTime = React.createClass({ hoursDisplayed: false }; }, + goBack: function() { + return this.setState({ + minutesDisplayed: false, + hoursDisplayed: false + }); + }, showMinutes: function() { return this.setState({ minutesDisplayed: true @@ -38,20 +47,14 @@ DateTimePickerTime = React.createClass({ }, renderMinutes: function() { if (this.state.minutesDisplayed) { - return ( - ); + return ; } else { return null; } }, renderHours: function() { if (this.state.hoursDisplayed) { - return ( - ); + return ; } else { return null; } diff --git a/src/DateTimePickerYears.jsx b/src/DateTimePickerYears.jsx index 663306b3..54ce7e6b 100644 --- a/src/DateTimePickerYears.jsx +++ b/src/DateTimePickerYears.jsx @@ -22,7 +22,7 @@ DateTimePickerYears = React.createClass({ old: i === -1 | i === 10, active: this.props.selectedDate.year() === year }; - years.push({year}); + years.push({year}); year++; i++; } From 5525c63f275d6bd48076fddd331f572f60d3f142 Mon Sep 17 00:00:00 2001 From: Alejandro Sellero Date: Thu, 23 Apr 2015 16:49:38 +0200 Subject: [PATCH 2/3] - Right text --- examples/basic/basic.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/basic/basic.jsx b/examples/basic/basic.jsx index d14aa114..9ae47316 100644 --- a/examples/basic/basic.jsx +++ b/examples/basic/basic.jsx @@ -49,7 +49,7 @@ var Basic = React.createClass({
    - daysOfWeekDisabled + just time picker @@ -58,7 +58,7 @@ var Basic = React.createClass({
    - daysOfWeekDisabled + just date picker From 802bee8cea85fe1c4c9bb1860bcb509e6eb0a702 Mon Sep 17 00:00:00 2001 From: Loic CHOLLIER Date: Thu, 14 May 2015 13:37:40 -0700 Subject: [PATCH 3/3] Change this.state.inputFormat when this.props.inputFormat changes --- src/DateTimeField.jsx | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/DateTimeField.jsx b/src/DateTimeField.jsx index 3690d9fe..f4a903c8 100644 --- a/src/DateTimeField.jsx +++ b/src/DateTimeField.jsx @@ -35,17 +35,6 @@ DateTimeField = React.createClass({ } }; }, - resolvePropsInputFormat: function() { - if(this.props.inputFormat) return this.props.inputFormat; - switch(this.props.mode) { - case Constants.MODE_TIME: - return "h:mm A"; - case Constants.MODE_DATE: - return "MM/DD/YY"; - default: - return "MM/DD/YY h:mm A"; - } - }, getInitialState: function() { return { showDatePicker: this.props.mode !== Constants.MODE_TIME, @@ -71,6 +60,22 @@ DateTimeField = React.createClass({ inputValue: moment(nextProps.dateTime, nextProps.format, true).format(nextProps.inputFormat) }); } + if (nextProps.inputFormat !== this.props.inputFormat) { + return this.setState({ + inputFormat: nextProps.inputFormat + }); + } + }, + resolvePropsInputFormat: function() { + if(this.props.inputFormat) return this.props.inputFormat; + switch(this.props.mode) { + case Constants.MODE_TIME: + return "h:mm A"; + case Constants.MODE_DATE: + return "MM/DD/YY"; + default: + return "MM/DD/YY h:mm A"; + } }, onChange: function(event) { var value = event.target == null ? event : event.target.value;