Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions DateTime.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ var Datetime = createClass({
getUpdateOn: function( formats ) {
if ( formats.date.match(/[lLD]/) ) {
return 'days';
} else if ( formats.date.indexOf('M') !== -1 ) {
} else if ( formats.date.match(/[MQ]/) ) {
return 'months';
} else if ( formats.date.indexOf('Y') !== -1 ) {
return 'years';
Expand Down Expand Up @@ -314,6 +314,16 @@ var Datetime = createClass({
.month( currentDate.month() )
.date( currentDate.date() )
.year( parseInt( target.getAttribute('data-value'), 10 ) );
} else if (target.className.indexOf('rdtTodayButton') !== -1) {
var now = moment(new Date());
date = viewDate.clone()
.month( now.month() )
.date( now.date() )
.year( now.year() );

this.setState({
currentView: 'days'
});
}

date.hours( currentDate.hours() )
Expand All @@ -331,7 +341,7 @@ var Datetime = createClass({
selectedDate: date,
viewDate: date.clone().startOf('month'),
inputValue: date.format( this.state.inputFormat ),
open: open
open: open,
});
} else {
if ( this.props.closeOnSelect && close ) {
Expand Down Expand Up @@ -373,10 +383,37 @@ var Datetime = createClass({
return m;
},

goToToday: function (e) {
this.updateSelectedDate(e);
},

alwaysValidDate: function () {
return true;
},

renderTodayButton: function (key) {
var now = moment(new Date());
var date = this.state.viewDate.clone()
.month( now.month() )
.date( now.date() )
.year( now.year() );

var isValidDate = this.props.isValidDate || this.alwaysValidDate;

var isValid = date.isValid && isValidDate(date);
var classes = isValid ? 'rdtTodayButton' : 'rdtTodayButton rdtDisabled';

return this.props.showTodayButton ? React.createElement(
'button',
{key: key, className: classes, onClick: isValid ? this.goToToday : undefined, 'data-automation': 'actionSelectToday', 'data-status': isValid ? 'enabled' : 'disabled' },
'Today'
) : undefined;
},

componentProps: {
fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear', 'timeConstraints'],
fromState: ['viewDate', 'selectedDate', 'updateOn'],
fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside']
fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside', 'renderTodayButton']
},

getComponentProps: function() {
Expand All @@ -402,8 +439,7 @@ var Datetime = createClass({
// TODO: Make a function or clean up this code,
// logic right now is really hard to follow
var className = 'rdt' + (this.props.className ?
( Array.isArray( this.props.className ) ?
' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
( Array.isArray( this.props.className ) ? ' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
children = [];

if ( this.props.input ) {
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ render: function() {
| **closeOnTab** | `boolean` | `true` | When `true` and the input is focused, pressing the `tab` key will close the datepicker.
| **timeConstraints** | `object` | `null` | Add some constraints to the timepicker. It accepts an `object` with the format `{ hours: { min: 9, max: 15, step: 2 }}`, this example means the hours can't be lower than `9` and higher than `15`, and it will change adding or subtracting `2` hours everytime the buttons are clicked. The constraints can be added to the `hours`, `minutes`, `seconds` and `milliseconds`.
| **disableOnClickOutside** | `boolean` | `false` | When `true`, keep the datepicker open when click event is triggered outside of component. When `false`, close it.
**showTodayButton** | `boolean` | `false` | When true, adds a 'Today' button at the bottom of the date picker.

## i18n
Different language and date formats are supported by react-datetime. React uses [Moment.js](http://momentjs.com/) to format the dates, and the easiest way of changing the language of the calendar is [changing the Moment.js locale](http://momentjs.com/docs/#/i18n/changing-locale/).
Expand Down
22 changes: 21 additions & 1 deletion css/react-datetime.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*!
/*/
* https://github.com/YouCanBookMe/react-datetime
*/

Expand Down Expand Up @@ -213,6 +213,26 @@ td.rdtYear:hover {
margin-top: 37px;
}

.rdtTodayButton {
display: block;
width: 100%;
height: 30px;
line-height: 30px;
border: none;
border-radius: 0;
font-weight: bold;
font-size: 14px;
}

.rdtTodayButton:focus {
outline: none;
}

.rdtTodayButton.rdtDisabled {
color: #999999;
cursor: not-allowed;
}

.rdtTime td {
cursor: default;
}
88 changes: 66 additions & 22 deletions dist/react-datetime.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
react-datetime v2.12.0
react-datetime v2.13.0
https://github.com/YouCanBookMe/react-datetime
MIT: https://github.com/YouCanBookMe/react-datetime/raw/master/LICENSE
*/
Expand Down Expand Up @@ -155,7 +155,7 @@ return /******/ (function(modules) { // webpackBootstrap
getUpdateOn: function( formats ) {
if ( formats.date.match(/[lLD]/) ) {
return 'days';
} else if ( formats.date.indexOf('M') !== -1 ) {
} else if ( formats.date.match(/[MQ]/) ) {
return 'months';
} else if ( formats.date.indexOf('Y') !== -1 ) {
return 'years';
Expand Down Expand Up @@ -375,6 +375,16 @@ return /******/ (function(modules) { // webpackBootstrap
.month( currentDate.month() )
.date( currentDate.date() )
.year( parseInt( target.getAttribute('data-value'), 10 ) );
} else if (target.className.indexOf('rdtTodayButton') !== -1) {
var now = moment(new Date());
date = viewDate.clone()
.month( now.month() )
.date( now.date() )
.year( now.year() );

this.setState({
currentView: 'days'
});
}

date.hours( currentDate.hours() )
Expand All @@ -392,7 +402,7 @@ return /******/ (function(modules) { // webpackBootstrap
selectedDate: date,
viewDate: date.clone().startOf('month'),
inputValue: date.format( this.state.inputFormat ),
open: open
open: open,
});
} else {
if ( this.props.closeOnSelect && close ) {
Expand Down Expand Up @@ -434,10 +444,37 @@ return /******/ (function(modules) { // webpackBootstrap
return m;
},

goToToday: function (e) {
this.updateSelectedDate(e);
},

alwaysValidDate: function () {
return true;
},

renderTodayButton: function (key) {
var now = moment(new Date());
var date = this.state.viewDate.clone()
.month( now.month() )
.date( now.date() )
.year( now.year() );

var isValidDate = this.props.isValidDate || this.alwaysValidDate;

var isValid = date.isValid && isValidDate(date);
var classes = isValid ? 'rdtTodayButton' : 'rdtTodayButton rdtDisabled';

return this.props.showTodayButton ? React.createElement(
'button',
{key: key, className: classes, onClick: isValid ? this.goToToday : undefined, 'data-automation': 'actionSelectToday', 'data-status': isValid ? 'enabled' : 'disabled' },
'Today'
) : undefined;
},

componentProps: {
fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear', 'timeConstraints'],
fromState: ['viewDate', 'selectedDate', 'updateOn'],
fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside']
fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside', 'renderTodayButton']
},

getComponentProps: function() {
Expand All @@ -463,8 +500,7 @@ return /******/ (function(modules) { // webpackBootstrap
// TODO: Make a function or clean up this code,
// logic right now is really hard to follow
var className = 'rdt' + (this.props.className ?
( Array.isArray( this.props.className ) ?
' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
( Array.isArray( this.props.className ) ? ' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
children = [];

if ( this.props.input ) {
Expand Down Expand Up @@ -2870,7 +2906,7 @@ return /******/ (function(modules) { // webpackBootstrap
days: DaysView,
months: MonthsView,
years: YearsView,
time: TimeView
time: TimeView,
},

render: function() {
Expand Down Expand Up @@ -2904,9 +2940,9 @@ return /******/ (function(modules) { // webpackBootstrap
tableChildren = [
React.createElement('thead', { key: 'th' }, [
React.createElement('tr', { key: 'h' }, [
React.createElement('th', { key: 'p', className: 'rdtPrev', onClick: this.props.subtractTime( 1, 'months' )}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 's', className: 'rdtSwitch', onClick: this.props.showView( 'months' ), colSpan: 5, 'data-value': this.props.viewDate.month() }, locale.months( date ) + ' ' + date.year() ),
React.createElement('th', { key: 'n', className: 'rdtNext', onClick: this.props.addTime( 1, 'months' )}, React.createElement('span', {}, '›' ))
React.createElement('th', { key: 'p', className: 'rdtPrev', onClick: this.props.subtractTime( 1, 'months' ), 'data-automation': 'actionPrevMonth'}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 's', className: 'rdtSwitch', onClick: this.props.showView( 'months' ), 'data-automation': 'actionSwitchToMonthsView', colSpan: 5, 'data-value': this.props.viewDate.month() }, locale.months( date ) + ' ' + date.year() ),
React.createElement('th', { key: 'n', className: 'rdtNext', onClick: this.props.addTime( 1, 'months' ), 'data-automation': 'actionNextMonth'}, React.createElement('span', {}, '›' ))
]),
React.createElement('tr', { key: 'd'}, this.getDaysOfWeek( locale ).map( function( day, index ) { return React.createElement('th', { key: day + index, className: 'dow'}, day ); }) )
]),
Expand All @@ -2917,7 +2953,7 @@ return /******/ (function(modules) { // webpackBootstrap
tableChildren.push( footer );

return React.createElement('div', { className: 'rdtDays' },
React.createElement('table', {}, tableChildren )
[React.createElement('table', {key: 'daysTable'}, tableChildren ), this.props.renderTodayButton('todayDays')]
);
},

Expand Down Expand Up @@ -2979,7 +3015,9 @@ return /******/ (function(modules) { // webpackBootstrap
dayProps = {
key: prevMonth.format( 'M_D' ),
'data-value': prevMonth.date(),
className: classes
className: classes,
'data-automation': currentDate.year() + '_' + (currentDate.month() + 1) + '_' + currentDate.date(),
'data-status': classes.indexOf('rdtDisabled') === -1 ? 'enabled' : 'disabled'
};

if ( !isDisabled )
Expand Down Expand Up @@ -3409,11 +3447,12 @@ return /******/ (function(modules) { // webpackBootstrap
render: function() {
return React.createElement('div', { className: 'rdtMonths' }, [
React.createElement('table', { key: 'a' }, React.createElement('thead', {}, React.createElement('tr', {}, [
React.createElement('th', { key: 'prev', className: 'rdtPrev', onClick: this.props.subtractTime( 1, 'years' )}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 'year', className: 'rdtSwitch', onClick: this.props.showView( 'years' ), colSpan: 2, 'data-value': this.props.viewDate.year() }, this.props.viewDate.year() ),
React.createElement('th', { key: 'next', className: 'rdtNext', onClick: this.props.addTime( 1, 'years' )}, React.createElement('span', {}, '›' ))
React.createElement('th', { key: 'prev', className: 'rdtPrev', onClick: this.props.subtractTime( 1, 'years' ), 'data-automation': 'actionPrevYear'}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 'year', className: 'rdtSwitch', onClick: this.props.showView( 'years' ), 'data-automation': 'actionSwitchToYearsView', colSpan: 2, 'data-value': this.props.viewDate.year() }, this.props.viewDate.year() ),
React.createElement('th', { key: 'next', className: 'rdtNext', onClick: this.props.addTime( 1, 'years' ), 'data-automation': 'actionNextYear'}, React.createElement('span', {}, '›' ))
]))),
React.createElement('table', { key: 'months' }, React.createElement('tbody', { key: 'b' }, this.renderMonths()))
React.createElement('table', { key: 'months' }, React.createElement('tbody', { key: 'b' }, this.renderMonths())),
this.props.renderTodayButton('todayMonths')
]);
},

Expand Down Expand Up @@ -3457,7 +3496,9 @@ return /******/ (function(modules) { // webpackBootstrap
props = {
key: i,
'data-value': i,
className: classes
className: classes,
'data-automation': year + '_' + (i + 1),
'data-status': classes.indexOf('rdtDisabled') !== -1 ? 'enabled' : 'disabled'
};

if ( !isDisabled )
Expand Down Expand Up @@ -3524,11 +3565,12 @@ return /******/ (function(modules) { // webpackBootstrap

return React.createElement('div', { className: 'rdtYears' }, [
React.createElement('table', { key: 'a' }, React.createElement('thead', {}, React.createElement('tr', {}, [
React.createElement('th', { key: 'prev', className: 'rdtPrev', onClick: this.props.subtractTime( 10, 'years' )}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 'year', className: 'rdtSwitch', onClick: this.props.showView( 'years' ), colSpan: 2 }, year + '-' + ( year + 9 ) ),
React.createElement('th', { key: 'next', className: 'rdtNext', onClick: this.props.addTime( 10, 'years' )}, React.createElement('span', {}, '›' ))
React.createElement('th', { key: 'prev', className: 'rdtPrev', onClick: this.props.subtractTime( 10, 'years' ), 'data-automation': 'actionPrevDecade'}, React.createElement('span', {}, '‹' )),
React.createElement('th', { key: 'year', className: 'rdtSwitch', onClick: this.props.showView( 'years' ), 'data-automation': 'buttonTopView', colSpan: 2 }, year + '-' + ( year + 9 ) ),
React.createElement('th', { key: 'next', className: 'rdtNext', onClick: this.props.addTime( 10, 'years' ), 'data-automation': 'actionNextDecade'}, React.createElement('span', {}, '›' ))
]))),
React.createElement('table', { key: 'years' }, React.createElement('tbody', {}, this.renderYears( year )))
React.createElement('table', { key: 'years' }, React.createElement('tbody', {}, this.renderYears( year ))),
this.props.renderTodayButton('todayYears')
]);
},

Expand Down Expand Up @@ -3577,7 +3619,9 @@ return /******/ (function(modules) { // webpackBootstrap
props = {
key: year,
'data-value': year,
className: classes
className: classes,
'data-automation': year,
'data-status': classes.indexOf('rdtDisabled') !== -1 ? 'enabled' : 'disabled'
};

if ( !isDisabled )
Expand Down
6 changes: 3 additions & 3 deletions dist/react-datetime.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/react-datetime.min.js.map

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
React.createElement(DateTime, {
viewMode: 'months',
dateFormat: 'MMMM',
isValidDate: function(current) {
return current.isBefore(DateTime.moment().startOf('month'));
}
}),
document.getElementById('datetime')
React.createElement(DateTime, {
viewMode: 'days',
dateFormat: 'MM/DD/YY',
showTodayButton: true,
closeOnSelect: true,
isValidDate: function(current) {
return current.isBefore(DateTime.moment().startOf('month'));
}
}),
document.getElementById('datetime')
);
20 changes: 20 additions & 0 deletions example/react-datetime.css
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,26 @@ td.rdtYear:hover {
margin-top: 43px;
}

.rdtTodayButton {
display: block;
width: 100%;
height: 30px;
line-height: 30px;
border: none;
border-radius: 0;
font-weight: bold;
font-size: 14px;
}

.rdtTodayButton:focus {
outline: none;
}

.rdtTodayButton.rdtDisabled {
color: #999999;
cursor: not-allowed;
}

.rdtTime td {
cursor: default;
}
2 changes: 1 addition & 1 deletion src/CalendarContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var CalendarContainer = createClass({
days: DaysView,
months: MonthsView,
years: YearsView,
time: TimeView
time: TimeView,
},

render: function() {
Expand Down
Loading