From eba92bd9c24111756afb06f05b8478130a3beef0 Mon Sep 17 00:00:00 2001
From: marquex <javi@arqex.com>
Date: Mon, 06 Jul 2015 20:09:50 +0200
Subject: [PATCH] Add the render props to customize appearance

---
 dist/react-datetime.min.js |    4 
 src/MonthsView.js          |   39 ++++++---
 dist/react-datetime.js     |   10 +-
 package.json               |    2 
 src/DaysView.js            |   16 +++
 src/YearsView.js           |   68 ++++++++++------
 DateTime.js                |    6 
 README.md                  |   37 ++++++++
 8 files changed, 126 insertions(+), 56 deletions(-)

diff --git a/DateTime.js b/DateTime.js
index 8eb3495..347145d 100644
--- a/DateTime.js
+++ b/DateTime.js
@@ -139,7 +139,7 @@
 		;
 		return function( e ){
 			me.setState({
-				viewDate: me.state.viewDate.clone()[ type ]( e.target.innerHTML ).startOf( type ),
+				viewDate: me.state.viewDate.clone()[ type ]( parseInt(e.target.dataset.value) ).startOf( type ),
 				currentView: nextViews[ type ]
 			});
 		};
@@ -206,7 +206,7 @@
 
 		date = this.state.viewDate.clone()
 			.month( this.state.viewDate.month() + modifier )
-			.date( parseInt( target.innerHTML ) )
+			.date( parseInt( target.dataset.value ) )
 			.hours( currentDate.hours() )
 			.minutes( currentDate.minutes() )
 			.seconds( currentDate.seconds() )
@@ -237,7 +237,7 @@
 	},
 
 	componentProps: {
-		fromProps: ['viewMode', 'minDate', 'maxDate'],
+		fromProps: ['viewMode', 'minDate', 'maxDate', 'renderDay', 'renderMonth', 'renderYear'],
 		fromState: ['viewDate', 'selectedDate' ],
 		fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateDate', 'localMoment']
 	},
diff --git a/README.md b/README.md
index 6d2bbbc..738ba94 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
 ===============================
 A date and time picker in the same React.js component. It can be used as a datepicker, timepicker or both at the same time.
 
+It allows to edit even date's milliseconds.
+
 This project started as a fork of https://github.com/quri/react-bootstrap-datetimepicker but the code and the API has changed a lot.
 
 Usage
@@ -30,8 +32,8 @@
 | Name         | Type    | Default | Description |
 | ------------ | ------- | ------- | ----------- |
 | **date** | Date  | new Date() | Represents the inital dateTime, this string is then parsed by moment.js |
-| **dateFormat**   | string  | "MM/DD/YY"     | Defines the format moment.js should use to parse and output the date. The default is only set if there is not `timeFormat` defined. |
-| **timeFormat**   | string  | "MM/DD/YY"     | Defines the format moment.js should use to parse and output the time. The default is only set if there is not `dateFormat` defined. |
+| **dateFormat**   | string  | Locale default | Defines the format moment.js should use to parse and output the date. The default is only set if there is not `timeFormat` defined. |
+| **timeFormat**   | string  | Locale default | Defines the format moment.js should use to parse and output the time. The default is only set if there is not `dateFormat` defined. |
 | **input** | boolean | true | Wether to show an input field to edit the date manually. |
 | **locale** | string | null | Manually set the locale for the react-datetime instance. Moment.js locale needs to be loaded to be used, see [i18n docs](#i18n).
 | **onChange** | function | x => console.log(x) | Callback trigger when the date changes |
@@ -39,6 +41,9 @@
 | **inputProps** | object | undefined | Defines additional attributes for the input element of the component. |
 | **minDate** | moment | undefined | The earliest date allowed for entry in the calendar view. |
 | **maxDate** | moment | undefined | The latest date allowed for entry in the calendar view. |
+| **renderDay** | function | DOM.td( day ) | Customize the way that the days are shown in the day picker. The accepted function has the `selectedDate`, the current date and the default calculated `props` for the cell, and must return a React component. See [appearance customization](#appearance_customization) |
+| **renderMonth** | function | DOM.td( month ) | Customize the way that the months are shown in the month picker. The accepted function has the `selectedDate`, the current date and the default calculated `props` for the cell, and must return a React component. See [appearance customization](#appearance_customization) |
+| **renderYear** | function | DOM.td( year ) | Customize the way that the years are shown in the year picker. The accepted function has the `selectedDate`, the current date and the default calculated `props` for the cell, and must return a React component. See [appearance customization](#appearance_customization) |
 
 ## 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/).
@@ -56,6 +61,34 @@
 ```
 [Here you can see the i18n example working](http://codepen.io/arqex/pen/PqJMQV).
 
+## Appearance customization
+It is possible to customize the way that the datetime picker display the days, months and years in the calendar. To adapt the calendar to every need it is possible to use the props `renderDay( props, currentDate, selectedDate )`, `renderMonth( props, month, year, selectedDate )` and `renderYear( props, year, selectedDate )` of react-datetime.
+
+```js
+var MyDTPicker = React.createClass({
+    render: function(){
+        return <Datetime
+            renderDay={ this.renderDay } 
+            renderMonth={ this.renderMonth } 
+            renderYear={ this.renderYear }
+        />;
+    },
+    renderDay: function( selectedDate, currentDate, props ){
+        return <td {...props}>{ currentDate.date() }</td>;
+    },
+    renderMonth: function( selectedDate, currentMonthDate, props ){
+        return <td {...props}>{ month }</td>;
+    },
+    renderDay: function( selectedDate, year, props ){
+        return <td {...props}>{ currentDate.date() }</td>;
+    }
+});
+```
+
+* `props` is the object that react-date picker has calculated for this object. It is convenient to use this object as the props for your custom component, since it knows how to handle the click event and its `className` attribute is used by the default styles.
+* `selectedDate` and `currentDate` are Moment.js objects and can be used to change the output depending on the selected date, or the date for the current day.
+* `month` and `year` are the numeric representation of the current month and year to be displayed. Notice that the possible `month` values go from `0` to `11`.
+
 Contributions
 ===============================
 Any help is always welcome :)
diff --git a/dist/react-datetime.js b/dist/react-datetime.js
index 4fe0d3e..81d5095 100644
--- a/dist/react-datetime.js
+++ b/dist/react-datetime.js
@@ -1,5 +1,5 @@
 /*
-react-datetime v0.3.1
+react-datetime v0.4.0
 https://github.com/arqex/react-datetime
 MIT: https://github.com/arqex/react-datetime/raw/master/LICENSE
 */
@@ -59,13 +59,13 @@
 /* 0 */
 /***/ function(module, exports, __webpack_require__) {
 
-	eval("'use strict';\r\n\r\nvar assign = __webpack_require__(3),\r\n\tReact = __webpack_require__(2),\r\n\tDaysView = __webpack_require__(4),\r\n\tMonthsView = __webpack_require__(6),\r\n\tYearsView = __webpack_require__(1),\r\n\tTimeView = __webpack_require__(7),\r\n\tmoment = __webpack_require__(5)\r\n;\r\n\r\nvar TYPES = React.PropTypes;\r\nvar Datetime = React.createClass({\r\n\tmixins: [\r\n\t\t__webpack_require__(8)\r\n\t],\r\n\tviewComponents: {\r\n\t\tdays: DaysView,\r\n\t\tmonths: MonthsView,\r\n\t\tyears: YearsView,\r\n\t\ttime: TimeView\r\n\t},\r\n\tpropTypes: {\r\n\t\tdate: TYPES.object,\r\n\t\tonChange: TYPES.func,\r\n\t\tlocale: TYPES.string,\r\n\t\tinput: TYPES.bool,\r\n\t\tdateFormat: TYPES.string,\r\n\t\ttimeFormat: TYPES.string,\r\n\t\tinputProps: TYPES.object,\r\n\t\tviewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),\r\n\t\tminDate: TYPES.object,\r\n\t\tmaxDate: TYPES.object\r\n\t},\r\n\tgetDefaultProps: function() {\r\n\r\n\t\treturn {\r\n\t\t\tdate: new Date(),\r\n\t\t\tviewMode: 'days',\r\n\t\t\tinputProps: {},\r\n\t\t\tinput: true,\r\n\t\t\tonChange: function (x) {\r\n\t\t\t\tconsole.log(x);\r\n\t\t\t}\r\n\t\t};\r\n\t},\r\n\tgetInitialState: function() {\r\n\t\tvar formats = this.getFormats( this.props ),\r\n\t\t\tdate = this.props.date\r\n\t\t;\r\n\t\treturn {\r\n\t\t\tcurrentView: this.props.viewMode,\r\n\t\t\topen: !this.props.input,\r\n\t\t\tinputFormat: formats.datetime,\r\n\t\t\tviewDate: this.localMoment(date).startOf(\"month\"),\r\n\t\t\tselectedDate: this.localMoment(date),\r\n\t\t\tinputValue: this.localMoment(date).format( formats.datetime )\r\n\t\t};\r\n\t},\r\n\r\n\tgetFormats: function( props ){\r\n\t\tvar formats = {\r\n\t\t\t\tdate: '',\r\n\t\t\t\ttime: '',\r\n\t\t\t\tdatetime: ''\r\n\t\t\t},\r\n\t\t\tlocale = this.localMoment( props.date ).localeData()\r\n\t\t;\r\n\r\n\t\tif( props.dateFormat ){\r\n\t\t\tformats.date = props.dateFormat;\r\n\t\t}\r\n\t\tif( props.timeFormat ){\r\n\t\t\tformats.time = props.timeFormat;\r\n\t\t}\r\n\r\n\t\tif( !formats.date && !formats.time ){\r\n\t\t\tformats.date = locale.longDateFormat('L');\r\n\t\t\tformats.time = locale.longDateFormat('LT');\r\n\t\t\tformats.datetime = formats.date + ' ' + formats.time;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tif( props.dateFormat ){\r\n\t\t\t\tformats.date = props.dateFormat;\r\n\t\t\t\tformats.datetime = formats.date;\r\n\t\t\t}\r\n\t\t\tif( props.timeFormat ){\r\n\t\t\t\tif( formats.date )\r\n\t\t\t\t\tformats.datetime += ' ';\r\n\t\t\t\tformats.time = props.timeFormat;\r\n\t\t\t\tformats.datetime += formats.time;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn formats;\r\n\t},\r\n\r\n\tcomponentWillReceiveProps: function(nextProps) {\r\n\t\tvar formats = this.getFormats( nextProps );\r\n\t\tif ( formats.datetime !== this.getFormats(this.props).datetime ) {\r\n\t\t\treturn this.setState({\r\n\t\t\t\tinputFormat: nextProps.inputFormat\r\n\t\t\t});\r\n\t\t}\r\n\t},\r\n\r\n\tonChange: function(event) {\r\n\t\tvar value = event.target == null ? event : event.target.value,\r\n\t\t\tlocalMoment = this.localMoment( date )\r\n\t\t;\r\n\r\n\t\tif (localMoment.isValid()) {\r\n\t\t\tthis.setState({\r\n\t\t\t\tselectedDate: localMoment,\r\n\t\t\t\tviewDate: localMoment.clone().startOf(\"month\")\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn this.setState({\r\n\t\t\tinputValue: value\r\n\t\t}, function() {\r\n\t\t\treturn this.props.onChange( localMoment.toDate() );\r\n\t\t});\r\n\t},\r\n\r\n\tshowView: function( view ){\r\n\t\tvar me = this;\r\n\t\treturn function( e ){\r\n\t\t\tme.setState({ currentView: view });\r\n\t\t};\r\n\t},\r\n\r\n\tsetDate: function( type ){\r\n\t\tvar me = this,\r\n\t\t\tnextViews = {\r\n\t\t\t\tmonth: 'days',\r\n\t\t\t\tyear: 'months'\r\n\t\t\t}\r\n\t\t;\r\n\t\treturn function( e ){\r\n\t\t\tme.setState({\r\n\t\t\t\tviewDate: me.state.viewDate.clone()[ type ]( e.target.innerHTML ).startOf( type ),\r\n\t\t\t\tcurrentView: nextViews[ type ]\r\n\t\t\t});\r\n\t\t};\r\n\t},\r\n\r\n\taddTime: function( amount, type, toSelected ){\r\n\t\treturn this.updateTime( 'add', amount, type, toSelected );\r\n\t},\r\n\r\n\tsubtractTime: function( amount, type, toSelected ){\r\n\t\treturn this.updateTime( 'subtract', amount, type, toSelected );\r\n\t},\r\n\r\n\tupdateTime: function( op, amount, type, toSelected ){\r\n\t\tvar me = this;\r\n\r\n\t\treturn function(){\r\n\t\t\tvar update = {},\r\n\t\t\t\tdate = toSelected ? 'selectedDate' : 'viewDate'\r\n\t\t\t;\r\n\r\n\t\t\tupdate[ date ] = me.state[ date ].clone()[ op ]( amount, type );\r\n\r\n\t\t\tme.setState( update );\r\n\t\t};\r\n\t},\r\n\r\n\tallowedSetTime: ['hours','minutes','seconds', 'milliseconds'],\r\n\tsetTime: function( type, value ){\r\n\t\tvar index = this.allowedSetTime.indexOf( type ) + 1,\r\n\t\t\tdate = this.state.selectedDate.clone(),\r\n\t\t\tnextType\r\n\t\t;\r\n\r\n\t\t// It is needed to set all the time properties\r\n\t\t// to not to reset the time\r\n\t\tdate[ type ]( value );\r\n\t\tfor (; index < this.allowedSetTime.length; index++) {\r\n\t\t\tnextType = this.allowedSetTime[index];\r\n\t\t\tdate[ nextType ]( date[nextType]() );\r\n\t\t}\r\n\r\n\t\tthis.setState({\r\n\t\t\tselectedDate: date,\r\n\t\t\tinputValue: date.format( this.state.inputFormat )\r\n\t\t}, this.callOnChange );\r\n\t},\r\n\r\n\tcallOnChange: function(){\r\n\t\tthis.props.onChange(this.state.selectedDate.format( this.state.inputFormat ));\r\n\t},\r\n\r\n\tupdateDate: function( e ) {\r\n\t\tvar target = e.target,\r\n\t\t\tmodifier = 0,\r\n\t\t\tcurrentDate = this.state.selectedDate,\r\n\t\t\tdate\r\n\t\t;\r\n\r\n\t\tif(target.className.indexOf(\"new\") != -1)\r\n\t\t\tmodifier = 1;\r\n\t\telse if(target.className.indexOf(\"old\") != -1)\r\n\t\t\tmodifier = -1;\r\n\r\n\t\tdate = this.state.viewDate.clone()\r\n\t\t\t.month( this.state.viewDate.month() + modifier )\r\n\t\t\t.date( parseInt( target.innerHTML ) )\r\n\t\t\t.hours( currentDate.hours() )\r\n\t\t\t.minutes( currentDate.minutes() )\r\n\t\t\t.seconds( currentDate.seconds() )\r\n\t\t\t.milliseconds( currentDate.milliseconds() )\r\n\t\t;\r\n\r\n\t\tthis.setState({\r\n\t\t\tselectedDate: date,\r\n\t\t\tviewDate: date.clone().startOf('month'),\r\n\t\t\tinputValue: date.format( this.state.inputFormat )\r\n\t\t});\r\n\t},\r\n\r\n\topenCalendar: function() {\r\n\t\tthis.setState({ open: true });\r\n\t},\r\n\r\n\thandleClickOutside: function(){\r\n\t\tif( this.props.input && this.state.open )\r\n\t\t\tthis.setState({ open: false });\r\n\t},\r\n\r\n\tlocalMoment: function( date ){\r\n\t\tvar m = moment( date );\r\n\t\tif( this.props.locale )\r\n\t\t\tm.locale( this.props.locale );\r\n\t\treturn m;\r\n\t},\r\n\r\n\tcomponentProps: {\r\n\t\tfromProps: ['viewMode', 'minDate', 'maxDate'],\r\n\t\tfromState: ['viewDate', 'selectedDate' ],\r\n\t\tfromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateDate', 'localMoment']\r\n\t},\r\n\r\n\tgetComponentProps: function(){\r\n\t\tvar me = this,\r\n\t\t\tformats = this.getFormats( this.props ),\r\n\t\t\tprops = {dateFormat: formats.date, timeFormat: formats.time}\r\n\t\t;\r\n\r\n\t\tthis.componentProps.fromProps.forEach( function( name ){\r\n\t\t\tprops[ name ] = me.props[ name ];\r\n\t\t});\r\n\t\tthis.componentProps.fromState.forEach( function( name ){\r\n\t\t\tprops[ name ] = me.state[ name ];\r\n\t\t});\r\n\t\tthis.componentProps.fromThis.forEach( function( name ){\r\n\t\t\tprops[ name ] = me[ name ];\r\n\t\t});\r\n\r\n\t\treturn props;\r\n\t},\r\n\r\n\trender: function() {\r\n\t\tvar Component = this.viewComponents[ this.state.currentView ],\r\n\t\t\tDOM = React.DOM,\r\n\t\t\tclassName = 'rdt',\r\n\t\t\tchildren = []\r\n\t\t;\r\n\r\n\t\tif( this.props.input ){\r\n\t\t\tchildren = [ DOM.input( assign({\r\n\t\t\t\tkey: 'i',\r\n\t\t\t\ttype:'text',\r\n\t\t\t\tclassName:'form-control',\r\n\t\t\t\tonFocus: this.openCalendar,\r\n\t\t\t\tonChange: this.onChange,\r\n\t\t\t\tvalue: this.state.inputValue\r\n\t\t\t}, this.props.inputProps ))];\r\n\t\t}\r\n\t\telse {\r\n\t\t\tclassName += ' rdtStatic';\r\n\t\t}\r\n\r\n\t\tif( this.state.open )\r\n\t\t\tclassName += ' rdtOpen';\r\n\r\n\t\treturn DOM.div({className: className}, children.concat(\r\n\t\t\tDOM.div(\r\n\t\t\t\t{ key: 'dt', className: 'rdtPicker' },\r\n\t\t\t\tReact.createElement( Component, this.getComponentProps())\r\n\t\t\t)\r\n\t\t));\r\n\t}\r\n});\r\n\r\nmodule.exports = Datetime;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./Datetime.js\n ** module id = 0\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./Datetime.js?");
+	eval("'use strict';\r\n\r\nvar assign = __webpack_require__(3),\r\n\tReact = __webpack_require__(2),\r\n\tDaysView = __webpack_require__(4),\r\n\tMonthsView = __webpack_require__(6),\r\n\tYearsView = __webpack_require__(1),\r\n\tTimeView = __webpack_require__(7),\r\n\tmoment = __webpack_require__(5)\r\n;\r\n\r\nvar TYPES = React.PropTypes;\r\nvar Datetime = React.createClass({\r\n\tmixins: [\r\n\t\t__webpack_require__(8)\r\n\t],\r\n\tviewComponents: {\r\n\t\tdays: DaysView,\r\n\t\tmonths: MonthsView,\r\n\t\tyears: YearsView,\r\n\t\ttime: TimeView\r\n\t},\r\n\tpropTypes: {\r\n\t\tdate: TYPES.object,\r\n\t\tonChange: TYPES.func,\r\n\t\tlocale: TYPES.string,\r\n\t\tinput: TYPES.bool,\r\n\t\tdateFormat: TYPES.string,\r\n\t\ttimeFormat: TYPES.string,\r\n\t\tinputProps: TYPES.object,\r\n\t\tviewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),\r\n\t\tminDate: TYPES.object,\r\n\t\tmaxDate: TYPES.object\r\n\t},\r\n\tgetDefaultProps: function() {\r\n\r\n\t\treturn {\r\n\t\t\tdate: new Date(),\r\n\t\t\tviewMode: 'days',\r\n\t\t\tinputProps: {},\r\n\t\t\tinput: true,\r\n\t\t\tonChange: function (x) {\r\n\t\t\t\tconsole.log(x);\r\n\t\t\t}\r\n\t\t};\r\n\t},\r\n\tgetInitialState: function() {\r\n\t\tvar formats = this.getFormats( this.props ),\r\n\t\t\tdate = this.props.date\r\n\t\t;\r\n\t\treturn {\r\n\t\t\tcurrentView: this.props.viewMode,\r\n\t\t\topen: !this.props.input,\r\n\t\t\tinputFormat: formats.datetime,\r\n\t\t\tviewDate: this.localMoment(date).startOf(\"month\"),\r\n\t\t\tselectedDate: this.localMoment(date),\r\n\t\t\tinputValue: this.localMoment(date).format( formats.datetime )\r\n\t\t};\r\n\t},\r\n\r\n\tgetFormats: function( props ){\r\n\t\tvar formats = {\r\n\t\t\t\tdate: '',\r\n\t\t\t\ttime: '',\r\n\t\t\t\tdatetime: ''\r\n\t\t\t},\r\n\t\t\tlocale = this.localMoment( props.date ).localeData()\r\n\t\t;\r\n\r\n\t\tif( props.dateFormat ){\r\n\t\t\tformats.date = props.dateFormat;\r\n\t\t}\r\n\t\tif( props.timeFormat ){\r\n\t\t\tformats.time = props.timeFormat;\r\n\t\t}\r\n\r\n\t\tif( !formats.date && !formats.time ){\r\n\t\t\tformats.date = locale.longDateFormat('L');\r\n\t\t\tformats.time = locale.longDateFormat('LT');\r\n\t\t\tformats.datetime = formats.date + ' ' + formats.time;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tif( props.dateFormat ){\r\n\t\t\t\tformats.date = props.dateFormat;\r\n\t\t\t\tformats.datetime = formats.date;\r\n\t\t\t}\r\n\t\t\tif( props.timeFormat ){\r\n\t\t\t\tif( formats.date )\r\n\t\t\t\t\tformats.datetime += ' ';\r\n\t\t\t\tformats.time = props.timeFormat;\r\n\t\t\t\tformats.datetime += formats.time;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn formats;\r\n\t},\r\n\r\n\tcomponentWillReceiveProps: function(nextProps) {\r\n\t\tvar formats = this.getFormats( nextProps );\r\n\t\tif ( formats.datetime !== this.getFormats(this.props).datetime ) {\r\n\t\t\treturn this.setState({\r\n\t\t\t\tinputFormat: nextProps.inputFormat\r\n\t\t\t});\r\n\t\t}\r\n\t},\r\n\r\n\tonChange: function(event) {\r\n\t\tvar value = event.target == null ? event : event.target.value,\r\n\t\t\tlocalMoment = this.localMoment( date )\r\n\t\t;\r\n\r\n\t\tif (localMoment.isValid()) {\r\n\t\t\tthis.setState({\r\n\t\t\t\tselectedDate: localMoment,\r\n\t\t\t\tviewDate: localMoment.clone().startOf(\"month\")\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn this.setState({\r\n\t\t\tinputValue: value\r\n\t\t}, function() {\r\n\t\t\treturn this.props.onChange( localMoment.toDate() );\r\n\t\t});\r\n\t},\r\n\r\n\tshowView: function( view ){\r\n\t\tvar me = this;\r\n\t\treturn function( e ){\r\n\t\t\tme.setState({ currentView: view });\r\n\t\t};\r\n\t},\r\n\r\n\tsetDate: function( type ){\r\n\t\tvar me = this,\r\n\t\t\tnextViews = {\r\n\t\t\t\tmonth: 'days',\r\n\t\t\t\tyear: 'months'\r\n\t\t\t}\r\n\t\t;\r\n\t\treturn function( e ){\r\n\t\t\tme.setState({\r\n\t\t\t\tviewDate: me.state.viewDate.clone()[ type ]( parseInt(e.target.dataset.value) ).startOf( type ),\r\n\t\t\t\tcurrentView: nextViews[ type ]\r\n\t\t\t});\r\n\t\t};\r\n\t},\r\n\r\n\taddTime: function( amount, type, toSelected ){\r\n\t\treturn this.updateTime( 'add', amount, type, toSelected );\r\n\t},\r\n\r\n\tsubtractTime: function( amount, type, toSelected ){\r\n\t\treturn this.updateTime( 'subtract', amount, type, toSelected );\r\n\t},\r\n\r\n\tupdateTime: function( op, amount, type, toSelected ){\r\n\t\tvar me = this;\r\n\r\n\t\treturn function(){\r\n\t\t\tvar update = {},\r\n\t\t\t\tdate = toSelected ? 'selectedDate' : 'viewDate'\r\n\t\t\t;\r\n\r\n\t\t\tupdate[ date ] = me.state[ date ].clone()[ op ]( amount, type );\r\n\r\n\t\t\tme.setState( update );\r\n\t\t};\r\n\t},\r\n\r\n\tallowedSetTime: ['hours','minutes','seconds', 'milliseconds'],\r\n\tsetTime: function( type, value ){\r\n\t\tvar index = this.allowedSetTime.indexOf( type ) + 1,\r\n\t\t\tdate = this.state.selectedDate.clone(),\r\n\t\t\tnextType\r\n\t\t;\r\n\r\n\t\t// It is needed to set all the time properties\r\n\t\t// to not to reset the time\r\n\t\tdate[ type ]( value );\r\n\t\tfor (; index < this.allowedSetTime.length; index++) {\r\n\t\t\tnextType = this.allowedSetTime[index];\r\n\t\t\tdate[ nextType ]( date[nextType]() );\r\n\t\t}\r\n\r\n\t\tthis.setState({\r\n\t\t\tselectedDate: date,\r\n\t\t\tinputValue: date.format( this.state.inputFormat )\r\n\t\t}, this.callOnChange );\r\n\t},\r\n\r\n\tcallOnChange: function(){\r\n\t\tthis.props.onChange(this.state.selectedDate.format( this.state.inputFormat ));\r\n\t},\r\n\r\n\tupdateDate: function( e ) {\r\n\t\tvar target = e.target,\r\n\t\t\tmodifier = 0,\r\n\t\t\tcurrentDate = this.state.selectedDate,\r\n\t\t\tdate\r\n\t\t;\r\n\r\n\t\tif(target.className.indexOf(\"new\") != -1)\r\n\t\t\tmodifier = 1;\r\n\t\telse if(target.className.indexOf(\"old\") != -1)\r\n\t\t\tmodifier = -1;\r\n\r\n\t\tdate = this.state.viewDate.clone()\r\n\t\t\t.month( this.state.viewDate.month() + modifier )\r\n\t\t\t.date( parseInt( target.dataset.value ) )\r\n\t\t\t.hours( currentDate.hours() )\r\n\t\t\t.minutes( currentDate.minutes() )\r\n\t\t\t.seconds( currentDate.seconds() )\r\n\t\t\t.milliseconds( currentDate.milliseconds() )\r\n\t\t;\r\n\r\n\t\tthis.setState({\r\n\t\t\tselectedDate: date,\r\n\t\t\tviewDate: date.clone().startOf('month'),\r\n\t\t\tinputValue: date.format( this.state.inputFormat )\r\n\t\t});\r\n\t},\r\n\r\n\topenCalendar: function() {\r\n\t\tthis.setState({ open: true });\r\n\t},\r\n\r\n\thandleClickOutside: function(){\r\n\t\tif( this.props.input && this.state.open )\r\n\t\t\tthis.setState({ open: false });\r\n\t},\r\n\r\n\tlocalMoment: function( date ){\r\n\t\tvar m = moment( date );\r\n\t\tif( this.props.locale )\r\n\t\t\tm.locale( this.props.locale );\r\n\t\treturn m;\r\n\t},\r\n\r\n\tcomponentProps: {\r\n\t\tfromProps: ['viewMode', 'minDate', 'maxDate', 'renderDay', 'renderMonth', 'renderYear'],\r\n\t\tfromState: ['viewDate', 'selectedDate' ],\r\n\t\tfromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateDate', 'localMoment']\r\n\t},\r\n\r\n\tgetComponentProps: function(){\r\n\t\tvar me = this,\r\n\t\t\tformats = this.getFormats( this.props ),\r\n\t\t\tprops = {dateFormat: formats.date, timeFormat: formats.time}\r\n\t\t;\r\n\r\n\t\tthis.componentProps.fromProps.forEach( function( name ){\r\n\t\t\tprops[ name ] = me.props[ name ];\r\n\t\t});\r\n\t\tthis.componentProps.fromState.forEach( function( name ){\r\n\t\t\tprops[ name ] = me.state[ name ];\r\n\t\t});\r\n\t\tthis.componentProps.fromThis.forEach( function( name ){\r\n\t\t\tprops[ name ] = me[ name ];\r\n\t\t});\r\n\r\n\t\treturn props;\r\n\t},\r\n\r\n\trender: function() {\r\n\t\tvar Component = this.viewComponents[ this.state.currentView ],\r\n\t\t\tDOM = React.DOM,\r\n\t\t\tclassName = 'rdt',\r\n\t\t\tchildren = []\r\n\t\t;\r\n\r\n\t\tif( this.props.input ){\r\n\t\t\tchildren = [ DOM.input( assign({\r\n\t\t\t\tkey: 'i',\r\n\t\t\t\ttype:'text',\r\n\t\t\t\tclassName:'form-control',\r\n\t\t\t\tonFocus: this.openCalendar,\r\n\t\t\t\tonChange: this.onChange,\r\n\t\t\t\tvalue: this.state.inputValue\r\n\t\t\t}, this.props.inputProps ))];\r\n\t\t}\r\n\t\telse {\r\n\t\t\tclassName += ' rdtStatic';\r\n\t\t}\r\n\r\n\t\tif( this.state.open )\r\n\t\t\tclassName += ' rdtOpen';\r\n\r\n\t\treturn DOM.div({className: className}, children.concat(\r\n\t\t\tDOM.div(\r\n\t\t\t\t{ key: 'dt', className: 'rdtPicker' },\r\n\t\t\t\tReact.createElement( Component, this.getComponentProps())\r\n\t\t\t)\r\n\t\t));\r\n\t}\r\n});\r\n\r\nmodule.exports = Datetime;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./Datetime.js\n ** module id = 0\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./Datetime.js?");
 
 /***/ },
 /* 1 */
 /***/ function(module, exports, __webpack_require__) {
 
-	eval("'use strict';\r\n\r\nvar React = __webpack_require__(2);\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerYears = React.createClass({\r\n\trenderYears: function( year ) {\r\n\t\tvar years = [],\r\n\t\t\ti = -1,\r\n\t\t\trows = [],\r\n\t\t\tclasses\r\n\t\t;\r\n\r\n\t\tyear--;\r\n\t\twhile (i < 11) {\r\n\t\t\tclasses = 'year';\r\n\t\t\tif( i === -1 | i === 10 )\r\n\t\t\t\tclasses += ' old';\r\n\t\t\tif( this.props.selectedDate.year() === year )\r\n\t\t\t\tclasses += ' active';\r\n\r\n\t\t\tyears.push( DOM.td({ key: year, className: classes, onClick: this.props.setDate('year') }, year ));\r\n\t\t\t// years.push(<td key={year} className={ classes } onClick={this.props.setDate('year')}>{year}</td>);\r\n\t\t\tif( years.length == 4 ){\r\n\t\t\t\trows.push( DOM.tr({ key: i }, years ) );\r\n\t\t\t\tyears = [];\r\n\t\t\t}\r\n\r\n\t\t\tyear++;\r\n\t\t\ti++;\r\n\t\t}\r\n\t\treturn rows;\r\n\t},\r\n\trender: function() {\r\n\t\tvar year = parseInt(this.props.viewDate.year() / 10, 10) * 10;\r\n\r\n\t\treturn DOM.div({ className: 'rdtYears' },[\r\n\t\t\tDOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[\r\n\t\t\t\tDOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(10, 'years')}, '���')),\r\n\t\t\t\tDOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, year + '-' + (year + 9) ),\r\n\t\t\t\tDOM.th({ key: 'next', className: 'next'}, DOM.button({onClick: this.props.addTime(10, 'years')}, '���'))\r\n\t\t\t\t]))),\r\n\t\t\tDOM.table({ key: 'years'}, DOM.tbody({}, this.renderYears( year )))\r\n\t\t]);\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerYears;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/YearsView.js\n ** module id = 1\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/YearsView.js?");
+	eval("'use strict';\r\n\r\nvar React = __webpack_require__(2);\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerYears = React.createClass({\r\n\trender: function() {\r\n\t\tvar year = parseInt(this.props.viewDate.year() / 10, 10) * 10;\r\n\r\n\t\treturn DOM.div({ className: 'rdtYears' },[\r\n\t\t\tDOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[\r\n\t\t\t\tDOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(10, 'years')}, '���')),\r\n\t\t\t\tDOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, year + '-' + (year + 9) ),\r\n\t\t\t\tDOM.th({ key: 'next', className: 'next'}, DOM.button({onClick: this.props.addTime(10, 'years')}, '���'))\r\n\t\t\t\t]))),\r\n\t\t\tDOM.table({ key: 'years'}, DOM.tbody({}, this.renderYears( year )))\r\n\t\t]);\r\n\t},\r\n\r\n\trenderYears: function( year ) {\r\n\t\tvar years = [],\r\n\t\t\ti = -1,\r\n\t\t\trows = [],\r\n\t\t\trenderer = this.props.renderYear || this.renderYear,\r\n\t\t\tclasses, props\r\n\t\t;\r\n\r\n\t\tyear--;\r\n\t\twhile (i < 11) {\r\n\t\t\tclasses = 'year';\r\n\t\t\tif( i === -1 | i === 10 )\r\n\t\t\t\tclasses += ' old';\r\n\t\t\tif( this.props.selectedDate.year() === year )\r\n\t\t\t\tclasses += ' active';\r\n\r\n\t\t\tprops = {\r\n\t\t\t\tkey: year,\r\n\t\t\t\t'data-value': year,\r\n\t\t\t\tclassName: classes,\r\n\t\t\t\tonClick: this.props.setDate('year')\r\n\t\t\t};\r\n\r\n\t\t\tyears.push( renderer( props, year, this.props.selectedDate.clone() ));\r\n\r\n\t\t\tif( years.length == 4 ){\r\n\t\t\t\trows.push( DOM.tr({ key: i }, years ) );\r\n\t\t\t\tyears = [];\r\n\t\t\t}\r\n\r\n\t\t\tyear++;\r\n\t\t\ti++;\r\n\t\t}\r\n\r\n\t\treturn rows;\r\n\t},\r\n\r\n\trenderYear: function( props, year, selectedDate ){\r\n\t\treturn DOM.td( props, year );\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerYears;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/YearsView.js\n ** module id = 1\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/YearsView.js?");
 
 /***/ },
 /* 2 */
@@ -83,7 +83,7 @@
 /* 4 */
 /***/ function(module, exports, __webpack_require__) {
 
-	eval("var React = __webpack_require__(2),\r\n\tmoment = __webpack_require__(5)\r\n;\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerDays = React.createClass({\r\n\r\n\trender: function() {\r\n\t\tvar footer = this.renderFooter(),\r\n\t\t\tdate = this.props.viewDate,\r\n\t\t\tlocale = date.localeData(),\r\n\t\t\ttableChildren\r\n\t\t;\r\n\r\n\t\ttableChildren = [\r\n\t\t\tDOM.thead({ key: 'th'}, [\r\n\t\t\t\tDOM.tr({ key: 'h'},[\r\n\t\t\t\t\tDOM.th({ key: 'p', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'months')}, '���')),\r\n\t\t\t\t\tDOM.th({ key: 's', className: 'switch', onClick: this.props.showView('months'), colSpan: 5 }, locale.months( date ) + ' ' + date.year() ),\r\n\t\t\t\t\tDOM.th({ key: 'n', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'months')}, '���'))\r\n\t\t\t\t]),\r\n\t\t\t\tDOM.tr({ key: 'd'}, this.getDaysOfWeek( locale ).map( function( day ){ return DOM.th({ key: day, className: 'dow'}, day ); }) )\r\n\t\t\t]),\r\n\t\t\tDOM.tbody({key: 'tb'}, this.renderDays())\r\n\t\t];\r\n\r\n\t\tif( footer )\r\n\t\t\ttableChildren.push( footer );\r\n\r\n\t\treturn DOM.div({ className: 'rdtDays' },\r\n\t\t\tDOM.table({}, tableChildren )\r\n\t\t);\r\n\t},\r\n\r\n\t/**\r\n\t * Get a list of the days of the week\r\n\t * depending on the current locale\r\n\t * @return {array} A list with the shortname of the days\r\n\t */\r\n\tgetDaysOfWeek: function( locale ){\r\n\t\tvar days = locale._weekdaysMin,\r\n\t\t\tfirst = locale.firstDayOfWeek(),\r\n\t\t\tdow = [],\r\n\t\t\ti = 0\r\n\t\t;\r\n\r\n\t\tdays.forEach( function( day ){\r\n\t\t\tdow[ (7 + (i++) - first) % 7 ] = day;\r\n\t\t});\r\n\r\n\t\treturn dow;\r\n\t},\r\n\r\n\trenderDays: function() {\r\n\t\tvar date = this.props.viewDate,\r\n\t\t\tselected = this.props.selectedDate,\r\n\t\t\tprevMonth = date.clone().subtract( 1, 'months' ),\r\n\t\t\tcurrentYear = date.year(),\r\n\t\t\tcurrentMonth = date.month(),\r\n\t\t\tselectedDate = {y: selected.year(), M: selected.month(), d: selected.date()},\r\n\t\t\tminDate = this.props.minDate,\r\n\t\t\tmaxDate = this.props.maxDate,\r\n\t\t\tweeks = [],\r\n\t\t\tdays = [],\r\n\t\t\tclasses, disabled, dayProps\r\n\t\t;\r\n\r\n\t\t// Go to the last week of the previous month\r\n\t\tprevMonth.date( prevMonth.daysInMonth() ).startOf('week');\r\n\t\tvar lastDay = prevMonth.clone().add(42, 'd');\r\n\r\n\t\twhile( prevMonth.isBefore( lastDay ) ){\r\n\t\t\tclasses = 'day';\r\n\r\n\t\t\tif( prevMonth.year() < currentYear || prevMonth.month() < currentMonth )\r\n\t\t\t\tclasses += ' old';\r\n\t\t\telse if( prevMonth.year() > currentYear || prevMonth.month() > currentMonth )\r\n\t\t\t\tclasses += ' new';\r\n\r\n\t\t\tif( prevMonth.isSame( selectedDate ) )\r\n\t\t\t\tclasses += ' active';\r\n\r\n\t\t\tif (prevMonth.isSame(moment(), 'day') )\r\n\t\t\t\tclasses += ' today';\r\n\r\n\t\t\tdisabled = minDate && prevMonth.isBefore(minDate) || maxDate && prevMonth.isAfter(maxDate);\r\n\t\t\tif( disabled )\r\n\t\t\t\tclasses += ' disabled';\r\n\r\n\t\t\tdayProps = { key: prevMonth.format('M_D'), className: classes };\r\n\t\t\tif( !disabled )\r\n\t\t\t\tdayProps.onClick = this.props.updateDate;\r\n\r\n\t\t\tdays.push( DOM.td( dayProps, prevMonth.date() ));\r\n\t\t\tif( days.length == 7 ){\r\n\t\t\t\tweeks.push( DOM.tr( {key: prevMonth.format('M_D')}, days ) );\r\n\t\t\t\tdays = [];\r\n\t\t\t}\r\n\r\n\t\t\tprevMonth.add( 1, 'd' );\r\n\t\t}\r\n\r\n\t\treturn weeks;\r\n\t},\r\n\r\n\trenderFooter: function(){\r\n\t\tif( !this.props.timeFormat )\r\n\t\t\treturn '';\r\n\r\n\t\treturn DOM.tfoot({ key: 'tf'},\r\n\t\t\tDOM.tr({},\r\n\t\t\t\tDOM.td({ onClick: this.props.showView('time'), colSpan: 7, className: 'timeToggle'}, this.props.selectedDate.format( this.props.timeFormat ))\r\n\t\t\t)\r\n\t\t);\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerDays;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/DaysView.js\n ** module id = 4\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/DaysView.js?");
+	eval("var React = __webpack_require__(2),\r\n\tmoment = __webpack_require__(5)\r\n;\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerDays = React.createClass({\r\n\r\n\trender: function() {\r\n\t\tvar footer = this.renderFooter(),\r\n\t\t\tdate = this.props.viewDate,\r\n\t\t\tlocale = date.localeData(),\r\n\t\t\ttableChildren\r\n\t\t;\r\n\r\n\t\ttableChildren = [\r\n\t\t\tDOM.thead({ key: 'th'}, [\r\n\t\t\t\tDOM.tr({ key: 'h'},[\r\n\t\t\t\t\tDOM.th({ key: 'p', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'months')}, '���')),\r\n\t\t\t\t\tDOM.th({ key: 's', className: 'switch', onClick: this.props.showView('months'), colSpan: 5 }, locale.months( date ) + ' ' + date.year() ),\r\n\t\t\t\t\tDOM.th({ key: 'n', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'months')}, '���'))\r\n\t\t\t\t]),\r\n\t\t\t\tDOM.tr({ key: 'd'}, this.getDaysOfWeek( locale ).map( function( day ){ return DOM.th({ key: day, className: 'dow'}, day ); }) )\r\n\t\t\t]),\r\n\t\t\tDOM.tbody({key: 'tb'}, this.renderDays())\r\n\t\t];\r\n\r\n\t\tif( footer )\r\n\t\t\ttableChildren.push( footer );\r\n\r\n\t\treturn DOM.div({ className: 'rdtDays' },\r\n\t\t\tDOM.table({}, tableChildren )\r\n\t\t);\r\n\t},\r\n\r\n\t/**\r\n\t * Get a list of the days of the week\r\n\t * depending on the current locale\r\n\t * @return {array} A list with the shortname of the days\r\n\t */\r\n\tgetDaysOfWeek: function( locale ){\r\n\t\tvar days = locale._weekdaysMin,\r\n\t\t\tfirst = locale.firstDayOfWeek(),\r\n\t\t\tdow = [],\r\n\t\t\ti = 0\r\n\t\t;\r\n\r\n\t\tdays.forEach( function( day ){\r\n\t\t\tdow[ (7 + (i++) - first) % 7 ] = day;\r\n\t\t});\r\n\r\n\t\treturn dow;\r\n\t},\r\n\r\n\trenderDays: function() {\r\n\t\tvar date = this.props.viewDate,\r\n\t\t\tselected = this.props.selectedDate.clone(),\r\n\t\t\tprevMonth = date.clone().subtract( 1, 'months' ),\r\n\t\t\tcurrentYear = date.year(),\r\n\t\t\tcurrentMonth = date.month(),\r\n\t\t\tselectedDate = {y: selected.year(), M: selected.month(), d: selected.date()},\r\n\t\t\tminDate = this.props.minDate,\r\n\t\t\tmaxDate = this.props.maxDate,\r\n\t\t\tweeks = [],\r\n\t\t\tdays = [],\r\n\t\t\trenderer = this.props.renderDay || this.renderDay,\r\n\t\t\tclasses, disabled, dayProps\r\n\t\t;\r\n\r\n\t\t// Go to the last week of the previous month\r\n\t\tprevMonth.date( prevMonth.daysInMonth() ).startOf('week');\r\n\t\tvar lastDay = prevMonth.clone().add(42, 'd');\r\n\r\n\t\twhile( prevMonth.isBefore( lastDay ) ){\r\n\t\t\tclasses = 'day';\r\n\r\n\t\t\tif( prevMonth.year() < currentYear || prevMonth.month() < currentMonth )\r\n\t\t\t\tclasses += ' old';\r\n\t\t\telse if( prevMonth.year() > currentYear || prevMonth.month() > currentMonth )\r\n\t\t\t\tclasses += ' new';\r\n\r\n\t\t\tif( prevMonth.isSame( selectedDate ) )\r\n\t\t\t\tclasses += ' active';\r\n\r\n\t\t\tif (prevMonth.isSame(moment(), 'day') )\r\n\t\t\t\tclasses += ' today';\r\n\r\n\t\t\tdisabled = minDate && prevMonth.isBefore(minDate) || maxDate && prevMonth.isAfter(maxDate);\r\n\t\t\tif( disabled )\r\n\t\t\t\tclasses += ' disabled';\r\n\r\n\t\t\tdayProps = {\r\n\t\t\t\tkey: prevMonth.format('M_D'),\r\n\t\t\t\t'data-value': prevMonth.date(),\r\n\t\t\t\tclassName: classes\r\n\t\t\t};\r\n\t\t\tif( !disabled )\r\n\t\t\t\tdayProps.onClick = this.props.updateDate;\r\n\r\n\t\t\tdays.push( renderer( dayProps, prevMonth.clone(), selected ) );\r\n\r\n\t\t\tif( days.length == 7 ){\r\n\t\t\t\tweeks.push( DOM.tr( {key: prevMonth.format('M_D')}, days ) );\r\n\t\t\t\tdays = [];\r\n\t\t\t}\r\n\r\n\t\t\tprevMonth.add( 1, 'd' );\r\n\t\t}\r\n\r\n\t\treturn weeks;\r\n\t},\r\n\r\n\trenderDay: function( props, currentDate, selectedDate ){\r\n\t\treturn DOM.td( props, currentDate.date() );\r\n\t},\r\n\r\n\trenderFooter: function(){\r\n\t\tif( !this.props.timeFormat )\r\n\t\t\treturn '';\r\n\r\n\t\treturn DOM.tfoot({ key: 'tf'},\r\n\t\t\tDOM.tr({},\r\n\t\t\t\tDOM.td({ onClick: this.props.showView('time'), colSpan: 7, className: 'timeToggle'}, this.props.selectedDate.format( this.props.timeFormat ))\r\n\t\t\t)\r\n\t\t);\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerDays;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/DaysView.js\n ** module id = 4\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/DaysView.js?");
 
 /***/ },
 /* 5 */
@@ -95,7 +95,7 @@
 /* 6 */
 /***/ function(module, exports, __webpack_require__) {
 
-	eval("'use strict';\r\n\r\nvar React = __webpack_require__(2),\r\nmoment = __webpack_require__(5)\r\n;\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerMonths = React.createClass({\r\n\trenderMonths: function() {\r\n\t\tvar date = this.props.selectedDate,\r\n\t\t\tmonth = date.month(),\r\n\t\t\tmonthsShort = date.localeData()._monthsShort,\r\n\t\t\trows = [],\r\n\t\t\ti = 0,\r\n\t\t\tmonths = [],\r\n\t\t\tclasses\r\n\t\t;\r\n\r\n\t\twhile (i < 12) {\r\n\t\t\tclasses = \"month\";\r\n\t\t\tif( i === month && this.props.viewDate.year() === date.year() )\r\n\t\t\t\tclasses += \" active\";\r\n\r\n\t\t\tmonths.push( DOM.td( {key: i, className: classes, onClick: this.props.setDate('month') }, monthsShort[ i ] ));\r\n\t\t\tif( months.length == 4 ){\r\n\t\t\t\trows.push( DOM.tr({ key: month + '_' + rows.length }, months) );\r\n\t\t\t\tmonths = [];\r\n\t\t\t}\r\n\r\n\t\t\ti++;\r\n\t\t}\r\n\r\n\t\treturn rows;\r\n\t},\r\n\r\n\trender: function() {\r\n\t\treturn DOM.div({ className: 'rdtMonths' },[\r\n\t\t\tDOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[\r\n\t\t\t\tDOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'years')}, '���')),\r\n\t\t\t\tDOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, this.props.viewDate.year() ),\r\n\t\t\t\tDOM.th({ key: 'next', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'years')}, '���'))\r\n\t\t\t]))),\r\n\t\t\tDOM.table({ key: 'months'}, DOM.tbody({ key: 'b'}, this.renderMonths()))\r\n\t\t]);\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerMonths;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/MonthsView.js\n ** module id = 6\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/MonthsView.js?");
+	eval("'use strict';\r\n\r\nvar React = __webpack_require__(2),\r\nmoment = __webpack_require__(5)\r\n;\r\n\r\nvar DOM = React.DOM;\r\nvar DateTimePickerMonths = React.createClass({\r\n\trender: function() {\r\n\t\treturn DOM.div({ className: 'rdtMonths' },[\r\n\t\t\tDOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[\r\n\t\t\t\tDOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'years')}, '���')),\r\n\t\t\t\tDOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, this.props.viewDate.year() ),\r\n\t\t\t\tDOM.th({ key: 'next', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'years')}, '���'))\r\n\t\t\t]))),\r\n\t\t\tDOM.table({ key: 'months'}, DOM.tbody({ key: 'b'}, this.renderMonths()))\r\n\t\t]);\r\n\t},\r\n\r\n\trenderMonths: function() {\r\n\t\tvar date = this.props.selectedDate,\r\n\t\t\tmonth = date.month(),\r\n\t\t\tyear = this.props.viewDate.year(),\r\n\t\t\trows = [],\r\n\t\t\ti = 0,\r\n\t\t\tmonths = [],\r\n\t\t\trenderer = this.props.renderMonth || this.renderMonth,\r\n\t\t\tclasses, props\r\n\t\t;\r\n\r\n\t\twhile (i < 12) {\r\n\t\t\tclasses = \"month\";\r\n\t\t\tif( i === month && year === date.year() )\r\n\t\t\t\tclasses += \" active\";\r\n\r\n\t\t\tprops = {\r\n\t\t\t\tkey: i,\r\n\t\t\t\t'data-value': i,\r\n\t\t\t\tclassName: classes,\r\n\t\t\t\tonClick: this.props.setDate('month')\r\n\t\t\t};\r\n\r\n\t\t\tmonths.push( renderer( props, i, year, date.clone() ));\r\n\r\n\t\t\tif( months.length == 4 ){\r\n\t\t\t\trows.push( DOM.tr({ key: month + '_' + rows.length }, months) );\r\n\t\t\t\tmonths = [];\r\n\t\t\t}\r\n\r\n\t\t\ti++;\r\n\t\t}\r\n\r\n\t\treturn rows;\r\n\t},\r\n\r\n\trenderMonth: function( props, month, year, selectedDate ) {\r\n\t\treturn DOM.td( props, selectedDate.localeData()._monthsShort[ month ] );\r\n\t}\r\n});\r\n\r\nmodule.exports = DateTimePickerMonths;\r\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/MonthsView.js\n ** module id = 6\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/MonthsView.js?");
 
 /***/ },
 /* 7 */
diff --git a/dist/react-datetime.min.js b/dist/react-datetime.min.js
index cf93274..83b3ac8 100644
--- a/dist/react-datetime.min.js
+++ b/dist/react-datetime.min.js
@@ -1,6 +1,6 @@
 /*
-react-datetime v0.3.1
+react-datetime v0.4.0
 https://github.com/arqex/react-datetime
 MIT: https://github.com/arqex/react-datetime/raw/master/LICENSE
 */
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require(void 0),require(void 0)):"function"==typeof define&&define.amd?define([,],e):"object"==typeof exports?exports.Datetime=e(require(void 0),require(void 0)):t.Datetime=e(t.React,t.moment)}(this,function(t,e){return function(t){function e(n){if(s[n])return s[n].exports;var a=s[n]={exports:{},id:n,loaded:!1};return t[n].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var s={};return e.m=t,e.c=s,e.p="",e(0)}([function(t,e,s){"use strict";var n=s(3),a=s(2),r=s(4),o=s(6),i=s(1),c=s(7),u=s(5),d=a.PropTypes,l=a.createClass({mixins:[s(8)],viewComponents:{days:r,months:o,years:i,time:c},propTypes:{date:d.object,onChange:d.func,locale:d.string,input:d.bool,dateFormat:d.string,timeFormat:d.string,inputProps:d.object,viewMode:d.oneOf(["years","months","days","time"]),minDate:d.object,maxDate:d.object},getDefaultProps:function(){return{date:new Date,viewMode:"days",inputProps:{},input:!0,onChange:function(t){console.log(t)}}},getInitialState:function(){var t=this.getFormats(this.props),e=this.props.date;return{currentView:this.props.viewMode,open:!this.props.input,inputFormat:t.datetime,viewDate:this.localMoment(e).startOf("month"),selectedDate:this.localMoment(e),inputValue:this.localMoment(e).format(t.datetime)}},getFormats:function(t){var e={date:"",time:"",datetime:""},s=this.localMoment(t.date).localeData();return t.dateFormat&&(e.date=t.dateFormat),t.timeFormat&&(e.time=t.timeFormat),e.date||e.time?(t.dateFormat&&(e.date=t.dateFormat,e.datetime=e.date),t.timeFormat&&(e.date&&(e.datetime+=" "),e.time=t.timeFormat,e.datetime+=e.time)):(e.date=s.longDateFormat("L"),e.time=s.longDateFormat("LT"),e.datetime=e.date+" "+e.time),e},componentWillReceiveProps:function(t){var e=this.getFormats(t);return e.datetime!==this.getFormats(this.props).datetime?this.setState({inputFormat:t.inputFormat}):void 0},onChange:function(t){var e=null==t.target?t:t.target.value,s=this.localMoment(date);return s.isValid()&&this.setState({selectedDate:s,viewDate:s.clone().startOf("month")}),this.setState({inputValue:e},function(){return this.props.onChange(s.toDate())})},showView:function(t){var e=this;return function(s){e.setState({currentView:t})}},setDate:function(t){var e=this,s={month:"days",year:"months"};return function(n){e.setState({viewDate:e.state.viewDate.clone()[t](n.target.innerHTML).startOf(t),currentView:s[t]})}},addTime:function(t,e,s){return this.updateTime("add",t,e,s)},subtractTime:function(t,e,s){return this.updateTime("subtract",t,e,s)},updateTime:function(t,e,s,n){var a=this;return function(){var r={},o=n?"selectedDate":"viewDate";r[o]=a.state[o].clone()[t](e,s),a.setState(r)}},allowedSetTime:["hours","minutes","seconds","milliseconds"],setTime:function(t,e){var s,n=this.allowedSetTime.indexOf(t)+1,a=this.state.selectedDate.clone();for(a[t](e);n<this.allowedSetTime.length;n++)s=this.allowedSetTime[n],a[s](a[s]());this.setState({selectedDate:a,inputValue:a.format(this.state.inputFormat)},this.callOnChange)},callOnChange:function(){this.props.onChange(this.state.selectedDate.format(this.state.inputFormat))},updateDate:function(t){var e,s=t.target,n=0,a=this.state.selectedDate;-1!=s.className.indexOf("new")?n=1:-1!=s.className.indexOf("old")&&(n=-1),e=this.state.viewDate.clone().month(this.state.viewDate.month()+n).date(parseInt(s.innerHTML)).hours(a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds()),this.setState({selectedDate:e,viewDate:e.clone().startOf("month"),inputValue:e.format(this.state.inputFormat)})},openCalendar:function(){this.setState({open:!0})},handleClickOutside:function(){this.props.input&&this.state.open&&this.setState({open:!1})},localMoment:function(t){var e=u(t);return this.props.locale&&e.locale(this.props.locale),e},componentProps:{fromProps:["viewMode","minDate","maxDate"],fromState:["viewDate","selectedDate"],fromThis:["setDate","setTime","showView","addTime","subtractTime","updateDate","localMoment"]},getComponentProps:function(){var t=this,e=this.getFormats(this.props),s={dateFormat:e.date,timeFormat:e.time};return this.componentProps.fromProps.forEach(function(e){s[e]=t.props[e]}),this.componentProps.fromState.forEach(function(e){s[e]=t.state[e]}),this.componentProps.fromThis.forEach(function(e){s[e]=t[e]}),s},render:function(){var t=this.viewComponents[this.state.currentView],e=a.DOM,s="rdt",r=[];return this.props.input?r=[e.input(n({key:"i",type:"text",className:"form-control",onFocus:this.openCalendar,onChange:this.onChange,value:this.state.inputValue},this.props.inputProps))]:s+=" rdtStatic",this.state.open&&(s+=" rdtOpen"),e.div({className:s},r.concat(e.div({key:"dt",className:"rdtPicker"},a.createElement(t,this.getComponentProps()))))}});t.exports=l},function(t,e,s){"use strict";var n=s(2),a=n.DOM,r=n.createClass({renderYears:function(t){var e,s=[],n=-1,r=[];for(t--;11>n;)e="year",-1===n|10===n&&(e+=" old"),this.props.selectedDate.year()===t&&(e+=" active"),s.push(a.td({key:t,className:e,onClick:this.props.setDate("year")},t)),4==s.length&&(r.push(a.tr({key:n},s)),s=[]),t++,n++;return r},render:function(){var t=10*parseInt(this.props.viewDate.year()/10,10);return a.div({className:"rdtYears"},[a.table({key:"a"},a.thead({},a.tr({},[a.th({key:"prev",className:"prev"},a.button({onClick:this.props.subtractTime(10,"years")},"���")),a.th({key:"year",className:"switch",onClick:this.props.showView("years"),colSpan:2},t+"-"+(t+9)),a.th({key:"next",className:"next"},a.button({onClick:this.props.addTime(10,"years")},"���"))]))),a.table({key:"years"},a.tbody({},this.renderYears(t)))])}});t.exports=r},function(e,s){e.exports=t},function(t,e){"use strict";function s(t){if(null==t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(t){var e=Object.getOwnPropertyNames(t);return Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(t))),e.filter(function(e){return a.call(t,e)})}var a=Object.prototype.propertyIsEnumerable;t.exports=Object.assign||function(t,e){for(var a,r,o=s(t),i=1;i<arguments.length;i++){a=arguments[i],r=n(Object(a));for(var c=0;c<r.length;c++)o[r[c]]=a[r[c]]}return o}},function(t,e,s){var n=s(2),a=s(5),r=n.DOM,o=n.createClass({render:function(){var t,e=this.renderFooter(),s=this.props.viewDate,n=s.localeData();return t=[r.thead({key:"th"},[r.tr({key:"h"},[r.th({key:"p",className:"prev"},r.button({onClick:this.props.subtractTime(1,"months")},"���")),r.th({key:"s",className:"switch",onClick:this.props.showView("months"),colSpan:5},n.months(s)+" "+s.year()),r.th({key:"n",className:"next"},r.button({onClick:this.props.addTime(1,"months")},"���"))]),r.tr({key:"d"},this.getDaysOfWeek(n).map(function(t){return r.th({key:t,className:"dow"},t)}))]),r.tbody({key:"tb"},this.renderDays())],e&&t.push(e),r.div({className:"rdtDays"},r.table({},t))},getDaysOfWeek:function(t){var e=t._weekdaysMin,s=t.firstDayOfWeek(),n=[],a=0;return e.forEach(function(t){n[(7+a++-s)%7]=t}),n},renderDays:function(){var t,e,s,n=this.props.viewDate,o=this.props.selectedDate,i=n.clone().subtract(1,"months"),c=n.year(),u=n.month(),d={y:o.year(),M:o.month(),d:o.date()},l=this.props.minDate,p=this.props.maxDate,h=[],m=[];i.date(i.daysInMonth()).startOf("week");for(var f=i.clone().add(42,"d");i.isBefore(f);)t="day",i.year()<c||i.month()<u?t+=" old":(i.year()>c||i.month()>u)&&(t+=" new"),i.isSame(d)&&(t+=" active"),i.isSame(a(),"day")&&(t+=" today"),e=l&&i.isBefore(l)||p&&i.isAfter(p),e&&(t+=" disabled"),s={key:i.format("M_D"),className:t},e||(s.onClick=this.props.updateDate),m.push(r.td(s,i.date())),7==m.length&&(h.push(r.tr({key:i.format("M_D")},m)),m=[]),i.add(1,"d");return h},renderFooter:function(){return this.props.timeFormat?r.tfoot({key:"tf"},r.tr({},r.td({onClick:this.props.showView("time"),colSpan:7,className:"timeToggle"},this.props.selectedDate.format(this.props.timeFormat)))):""}});t.exports=o},function(t,s){t.exports=e},function(t,e,s){"use strict";var n=s(2),a=(s(5),n.DOM),r=n.createClass({renderMonths:function(){for(var t,e=this.props.selectedDate,s=e.month(),n=e.localeData()._monthsShort,r=[],o=0,i=[];12>o;)t="month",o===s&&this.props.viewDate.year()===e.year()&&(t+=" active"),i.push(a.td({key:o,className:t,onClick:this.props.setDate("month")},n[o])),4==i.length&&(r.push(a.tr({key:s+"_"+r.length},i)),i=[]),o++;return r},render:function(){return a.div({className:"rdtMonths"},[a.table({key:"a"},a.thead({},a.tr({},[a.th({key:"prev",className:"prev"},a.button({onClick:this.props.subtractTime(1,"years")},"���")),a.th({key:"year",className:"switch",onClick:this.props.showView("years"),colSpan:2},this.props.viewDate.year()),a.th({key:"next",className:"next"},a.button({onClick:this.props.addTime(1,"years")},"���"))]))),a.table({key:"months"},a.tbody({key:"b"},this.renderMonths()))])}});t.exports=r},function(t,e,s){"use strict";var n=s(2),a=n.DOM,r=n.createClass({getInitialState:function(){var t=this.props.selectedDate,e=this.props.timeFormat,s=[];return(-1!=e.indexOf("H")||-1!=e.indexOf("h"))&&(s.push("hours"),-1!=e.indexOf("m")&&(s.push("minutes"),-1!=e.indexOf("s")&&s.push("seconds"))),{hours:t.format("H"),minutes:t.format("mm"),seconds:t.format("ss"),milliseconds:t.format("SSS"),counters:s}},renderCounter:function(t){return a.div({key:t,className:"rdtCounter"},[a.button({key:"up",className:"btn",onMouseDown:this.onStartClicking("increase",t)},"���"),a.div({key:"c",className:"rdtCount"},this.state[t]),a.button({key:"do",className:"btn",onMouseDown:this.onStartClicking("decrease",t)},"���")])},render:function(){var t=this,e=[];return this.state.counters.forEach(function(s){e.length&&e.push(a.div({key:"sep"+e.length,className:"rdtCounterSeparator"},":")),e.push(t.renderCounter(s))}),3==this.state.counters.length&&-1!=this.props.timeFormat.indexOf("S")&&(e.push(a.div({className:"rdtCounterSeparator",key:"sep5"},":")),e.push(a.div({className:"rdtCounter rdtMilli",key:"m"},a.input({value:this.state.milliseconds,type:"text",onChange:this.updateMilli})))),a.div({className:"rdtTime"},a.table({},[this.renderHeader(),a.tbody({key:"b"},a.tr({},a.td({},a.div({className:"rdtCounters"},e))))]))},updateMilli:function(t){var e=parseInt(t.target.value);e==t.target.value&&e>=0&&1e3>e&&(this.props.setTime("milliseconds",e),this.setState({milliseconds:e}))},renderHeader:function(){return this.props.dateFormat?a.thead({key:"h"},a.tr({},a.th({colSpan:4,onClick:this.props.showView("days")},this.props.selectedDate.format(this.props.dateFormat)))):""},onStartClicking:function(t,e){var s=this;return function(){var n={};n[e]=s[t](e),s.setState(n),s.timer=setTimeout(function(){s.increaseTimer=setInterval(function(){n[e]=s[t](e),s.setState(n)},80)},500),document.body.addEventListener("mouseup",function(){clearTimeout(s.timer),clearInterval(s.increaseTimer),s.props.setTime(e,s.state[e])})}},maxValues:{hours:23,minutes:59,seconds:59,milliseconds:999},padValues:{hours:1,minutes:2,seconds:2,milliseconds:3},increase:function(t){var e=parseInt(this.state[t])+1;return e>this.maxValues[t]&&(e=0),this.pad(t,e)},decrease:function(t){var e=parseInt(this.state[t])-1;return 0>e&&(e=this.maxValues[t]),this.pad(t,e)},pad:function(t,e){for(var s=e+"";s.length<this.padValues[t];)s="0"+s;return s}});t.exports=r},function(t,e,s){var n,a,r;!function(s,o){a=[],n=o,r="function"==typeof n?n.apply(e,a):n,!(void 0!==r&&(t.exports=r))}(this,function(){"use strict";var t=[],e=[],s="ignore-react-onclickoutside";return{componentDidMount:function(){if(!this.handleClickOutside)throw new Error("Component lacks a handleClickOutside(event) function for processing outside click events.");var n=this.__outsideClickHandler=function(t,e){return function(n){for(var a=n.target,r=!1;a.parentNode;){if(r=a===t||a.classList.contains(s))return;a=a.parentNode}e(n)}}(this.getDOMNode(),this.handleClickOutside),a=t.length;t.push(this),e[a]=n,this.props.disableOnClickOutside||this.enableOnClickOutside()},componentWillUnmount:function(){this.disableOnClickOutside(),this.__outsideClickHandler=!1;var s=t.indexOf(this);s>-1&&e[s]&&(e.splice(s,1),t.splice(s,1))},enableOnClickOutside:function(){var t=this.__outsideClickHandler;document.addEventListener("mousedown",t),document.addEventListener("touchstart",t)},disableOnClickOutside:function(t){var t=this.__outsideClickHandler;document.removeEventListener("mousedown",t),document.removeEventListener("touchstart",t)}}})}])});
\ No newline at end of file
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require(void 0),require(void 0)):"function"==typeof define&&define.amd?define([,],e):"object"==typeof exports?exports.Datetime=e(require(void 0),require(void 0)):t.Datetime=e(t.React,t.moment)}(this,function(t,e){return function(t){function e(n){if(s[n])return s[n].exports;var a=s[n]={exports:{},id:n,loaded:!1};return t[n].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var s={};return e.m=t,e.c=s,e.p="",e(0)}([function(t,e,s){"use strict";var n=s(3),a=s(2),r=s(4),o=s(6),i=s(1),c=s(7),u=s(5),d=a.PropTypes,l=a.createClass({mixins:[s(8)],viewComponents:{days:r,months:o,years:i,time:c},propTypes:{date:d.object,onChange:d.func,locale:d.string,input:d.bool,dateFormat:d.string,timeFormat:d.string,inputProps:d.object,viewMode:d.oneOf(["years","months","days","time"]),minDate:d.object,maxDate:d.object},getDefaultProps:function(){return{date:new Date,viewMode:"days",inputProps:{},input:!0,onChange:function(t){console.log(t)}}},getInitialState:function(){var t=this.getFormats(this.props),e=this.props.date;return{currentView:this.props.viewMode,open:!this.props.input,inputFormat:t.datetime,viewDate:this.localMoment(e).startOf("month"),selectedDate:this.localMoment(e),inputValue:this.localMoment(e).format(t.datetime)}},getFormats:function(t){var e={date:"",time:"",datetime:""},s=this.localMoment(t.date).localeData();return t.dateFormat&&(e.date=t.dateFormat),t.timeFormat&&(e.time=t.timeFormat),e.date||e.time?(t.dateFormat&&(e.date=t.dateFormat,e.datetime=e.date),t.timeFormat&&(e.date&&(e.datetime+=" "),e.time=t.timeFormat,e.datetime+=e.time)):(e.date=s.longDateFormat("L"),e.time=s.longDateFormat("LT"),e.datetime=e.date+" "+e.time),e},componentWillReceiveProps:function(t){var e=this.getFormats(t);return e.datetime!==this.getFormats(this.props).datetime?this.setState({inputFormat:t.inputFormat}):void 0},onChange:function(t){var e=null==t.target?t:t.target.value,s=this.localMoment(date);return s.isValid()&&this.setState({selectedDate:s,viewDate:s.clone().startOf("month")}),this.setState({inputValue:e},function(){return this.props.onChange(s.toDate())})},showView:function(t){var e=this;return function(s){e.setState({currentView:t})}},setDate:function(t){var e=this,s={month:"days",year:"months"};return function(n){e.setState({viewDate:e.state.viewDate.clone()[t](parseInt(n.target.dataset.value)).startOf(t),currentView:s[t]})}},addTime:function(t,e,s){return this.updateTime("add",t,e,s)},subtractTime:function(t,e,s){return this.updateTime("subtract",t,e,s)},updateTime:function(t,e,s,n){var a=this;return function(){var r={},o=n?"selectedDate":"viewDate";r[o]=a.state[o].clone()[t](e,s),a.setState(r)}},allowedSetTime:["hours","minutes","seconds","milliseconds"],setTime:function(t,e){var s,n=this.allowedSetTime.indexOf(t)+1,a=this.state.selectedDate.clone();for(a[t](e);n<this.allowedSetTime.length;n++)s=this.allowedSetTime[n],a[s](a[s]());this.setState({selectedDate:a,inputValue:a.format(this.state.inputFormat)},this.callOnChange)},callOnChange:function(){this.props.onChange(this.state.selectedDate.format(this.state.inputFormat))},updateDate:function(t){var e,s=t.target,n=0,a=this.state.selectedDate;-1!=s.className.indexOf("new")?n=1:-1!=s.className.indexOf("old")&&(n=-1),e=this.state.viewDate.clone().month(this.state.viewDate.month()+n).date(parseInt(s.dataset.value)).hours(a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds()),this.setState({selectedDate:e,viewDate:e.clone().startOf("month"),inputValue:e.format(this.state.inputFormat)})},openCalendar:function(){this.setState({open:!0})},handleClickOutside:function(){this.props.input&&this.state.open&&this.setState({open:!1})},localMoment:function(t){var e=u(t);return this.props.locale&&e.locale(this.props.locale),e},componentProps:{fromProps:["viewMode","minDate","maxDate","renderDay","renderMonth","renderYear"],fromState:["viewDate","selectedDate"],fromThis:["setDate","setTime","showView","addTime","subtractTime","updateDate","localMoment"]},getComponentProps:function(){var t=this,e=this.getFormats(this.props),s={dateFormat:e.date,timeFormat:e.time};return this.componentProps.fromProps.forEach(function(e){s[e]=t.props[e]}),this.componentProps.fromState.forEach(function(e){s[e]=t.state[e]}),this.componentProps.fromThis.forEach(function(e){s[e]=t[e]}),s},render:function(){var t=this.viewComponents[this.state.currentView],e=a.DOM,s="rdt",r=[];return this.props.input?r=[e.input(n({key:"i",type:"text",className:"form-control",onFocus:this.openCalendar,onChange:this.onChange,value:this.state.inputValue},this.props.inputProps))]:s+=" rdtStatic",this.state.open&&(s+=" rdtOpen"),e.div({className:s},r.concat(e.div({key:"dt",className:"rdtPicker"},a.createElement(t,this.getComponentProps()))))}});t.exports=l},function(t,e,s){"use strict";var n=s(2),a=n.DOM,r=n.createClass({render:function(){var t=10*parseInt(this.props.viewDate.year()/10,10);return a.div({className:"rdtYears"},[a.table({key:"a"},a.thead({},a.tr({},[a.th({key:"prev",className:"prev"},a.button({onClick:this.props.subtractTime(10,"years")},"���")),a.th({key:"year",className:"switch",onClick:this.props.showView("years"),colSpan:2},t+"-"+(t+9)),a.th({key:"next",className:"next"},a.button({onClick:this.props.addTime(10,"years")},"���"))]))),a.table({key:"years"},a.tbody({},this.renderYears(t)))])},renderYears:function(t){var e,s,n=[],r=-1,o=[],i=this.props.renderYear||this.renderYear;for(t--;11>r;)e="year",-1===r|10===r&&(e+=" old"),this.props.selectedDate.year()===t&&(e+=" active"),s={key:t,"data-value":t,className:e,onClick:this.props.setDate("year")},n.push(i(s,t,this.props.selectedDate.clone())),4==n.length&&(o.push(a.tr({key:r},n)),n=[]),t++,r++;return o},renderYear:function(t,e,s){return a.td(t,e)}});t.exports=r},function(e,s){e.exports=t},function(t,e){"use strict";function s(t){if(null==t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(t){var e=Object.getOwnPropertyNames(t);return Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(t))),e.filter(function(e){return a.call(t,e)})}var a=Object.prototype.propertyIsEnumerable;t.exports=Object.assign||function(t,e){for(var a,r,o=s(t),i=1;i<arguments.length;i++){a=arguments[i],r=n(Object(a));for(var c=0;c<r.length;c++)o[r[c]]=a[r[c]]}return o}},function(t,e,s){var n=s(2),a=s(5),r=n.DOM,o=n.createClass({render:function(){var t,e=this.renderFooter(),s=this.props.viewDate,n=s.localeData();return t=[r.thead({key:"th"},[r.tr({key:"h"},[r.th({key:"p",className:"prev"},r.button({onClick:this.props.subtractTime(1,"months")},"���")),r.th({key:"s",className:"switch",onClick:this.props.showView("months"),colSpan:5},n.months(s)+" "+s.year()),r.th({key:"n",className:"next"},r.button({onClick:this.props.addTime(1,"months")},"���"))]),r.tr({key:"d"},this.getDaysOfWeek(n).map(function(t){return r.th({key:t,className:"dow"},t)}))]),r.tbody({key:"tb"},this.renderDays())],e&&t.push(e),r.div({className:"rdtDays"},r.table({},t))},getDaysOfWeek:function(t){var e=t._weekdaysMin,s=t.firstDayOfWeek(),n=[],a=0;return e.forEach(function(t){n[(7+a++-s)%7]=t}),n},renderDays:function(){var t,e,s,n=this.props.viewDate,o=this.props.selectedDate.clone(),i=n.clone().subtract(1,"months"),c=n.year(),u=n.month(),d={y:o.year(),M:o.month(),d:o.date()},l=this.props.minDate,p=this.props.maxDate,h=[],m=[],f=this.props.renderDay||this.renderDay;i.date(i.daysInMonth()).startOf("week");for(var v=i.clone().add(42,"d");i.isBefore(v);)t="day",i.year()<c||i.month()<u?t+=" old":(i.year()>c||i.month()>u)&&(t+=" new"),i.isSame(d)&&(t+=" active"),i.isSame(a(),"day")&&(t+=" today"),e=l&&i.isBefore(l)||p&&i.isAfter(p),e&&(t+=" disabled"),s={key:i.format("M_D"),"data-value":i.date(),className:t},e||(s.onClick=this.props.updateDate),m.push(f(s,i.clone(),o)),7==m.length&&(h.push(r.tr({key:i.format("M_D")},m)),m=[]),i.add(1,"d");return h},renderDay:function(t,e,s){return r.td(t,e.date())},renderFooter:function(){return this.props.timeFormat?r.tfoot({key:"tf"},r.tr({},r.td({onClick:this.props.showView("time"),colSpan:7,className:"timeToggle"},this.props.selectedDate.format(this.props.timeFormat)))):""}});t.exports=o},function(t,s){t.exports=e},function(t,e,s){"use strict";var n=s(2),a=(s(5),n.DOM),r=n.createClass({render:function(){return a.div({className:"rdtMonths"},[a.table({key:"a"},a.thead({},a.tr({},[a.th({key:"prev",className:"prev"},a.button({onClick:this.props.subtractTime(1,"years")},"���")),a.th({key:"year",className:"switch",onClick:this.props.showView("years"),colSpan:2},this.props.viewDate.year()),a.th({key:"next",className:"next"},a.button({onClick:this.props.addTime(1,"years")},"���"))]))),a.table({key:"months"},a.tbody({key:"b"},this.renderMonths()))])},renderMonths:function(){for(var t,e,s=this.props.selectedDate,n=s.month(),r=this.props.viewDate.year(),o=[],i=0,c=[],u=this.props.renderMonth||this.renderMonth;12>i;)t="month",i===n&&r===s.year()&&(t+=" active"),e={key:i,"data-value":i,className:t,onClick:this.props.setDate("month")},c.push(u(e,i,r,s.clone())),4==c.length&&(o.push(a.tr({key:n+"_"+o.length},c)),c=[]),i++;return o},renderMonth:function(t,e,s,n){return a.td(t,n.localeData()._monthsShort[e])}});t.exports=r},function(t,e,s){"use strict";var n=s(2),a=n.DOM,r=n.createClass({getInitialState:function(){var t=this.props.selectedDate,e=this.props.timeFormat,s=[];return(-1!=e.indexOf("H")||-1!=e.indexOf("h"))&&(s.push("hours"),-1!=e.indexOf("m")&&(s.push("minutes"),-1!=e.indexOf("s")&&s.push("seconds"))),{hours:t.format("H"),minutes:t.format("mm"),seconds:t.format("ss"),milliseconds:t.format("SSS"),counters:s}},renderCounter:function(t){return a.div({key:t,className:"rdtCounter"},[a.button({key:"up",className:"btn",onMouseDown:this.onStartClicking("increase",t)},"���"),a.div({key:"c",className:"rdtCount"},this.state[t]),a.button({key:"do",className:"btn",onMouseDown:this.onStartClicking("decrease",t)},"���")])},render:function(){var t=this,e=[];return this.state.counters.forEach(function(s){e.length&&e.push(a.div({key:"sep"+e.length,className:"rdtCounterSeparator"},":")),e.push(t.renderCounter(s))}),3==this.state.counters.length&&-1!=this.props.timeFormat.indexOf("S")&&(e.push(a.div({className:"rdtCounterSeparator",key:"sep5"},":")),e.push(a.div({className:"rdtCounter rdtMilli",key:"m"},a.input({value:this.state.milliseconds,type:"text",onChange:this.updateMilli})))),a.div({className:"rdtTime"},a.table({},[this.renderHeader(),a.tbody({key:"b"},a.tr({},a.td({},a.div({className:"rdtCounters"},e))))]))},updateMilli:function(t){var e=parseInt(t.target.value);e==t.target.value&&e>=0&&1e3>e&&(this.props.setTime("milliseconds",e),this.setState({milliseconds:e}))},renderHeader:function(){return this.props.dateFormat?a.thead({key:"h"},a.tr({},a.th({colSpan:4,onClick:this.props.showView("days")},this.props.selectedDate.format(this.props.dateFormat)))):""},onStartClicking:function(t,e){var s=this;return function(){var n={};n[e]=s[t](e),s.setState(n),s.timer=setTimeout(function(){s.increaseTimer=setInterval(function(){n[e]=s[t](e),s.setState(n)},80)},500),document.body.addEventListener("mouseup",function(){clearTimeout(s.timer),clearInterval(s.increaseTimer),s.props.setTime(e,s.state[e])})}},maxValues:{hours:23,minutes:59,seconds:59,milliseconds:999},padValues:{hours:1,minutes:2,seconds:2,milliseconds:3},increase:function(t){var e=parseInt(this.state[t])+1;return e>this.maxValues[t]&&(e=0),this.pad(t,e)},decrease:function(t){var e=parseInt(this.state[t])-1;return 0>e&&(e=this.maxValues[t]),this.pad(t,e)},pad:function(t,e){for(var s=e+"";s.length<this.padValues[t];)s="0"+s;return s}});t.exports=r},function(t,e,s){var n,a,r;!function(s,o){a=[],n=o,r="function"==typeof n?n.apply(e,a):n,!(void 0!==r&&(t.exports=r))}(this,function(){"use strict";var t=[],e=[],s="ignore-react-onclickoutside";return{componentDidMount:function(){if(!this.handleClickOutside)throw new Error("Component lacks a handleClickOutside(event) function for processing outside click events.");var n=this.__outsideClickHandler=function(t,e){return function(n){for(var a=n.target,r=!1;a.parentNode;){if(r=a===t||a.classList.contains(s))return;a=a.parentNode}e(n)}}(this.getDOMNode(),this.handleClickOutside),a=t.length;t.push(this),e[a]=n,this.props.disableOnClickOutside||this.enableOnClickOutside()},componentWillUnmount:function(){this.disableOnClickOutside(),this.__outsideClickHandler=!1;var s=t.indexOf(this);s>-1&&e[s]&&(e.splice(s,1),t.splice(s,1))},enableOnClickOutside:function(){var t=this.__outsideClickHandler;document.addEventListener("mousedown",t),document.addEventListener("touchstart",t)},disableOnClickOutside:function(t){var t=this.__outsideClickHandler;document.removeEventListener("mousedown",t),document.removeEventListener("touchstart",t)}}})}])});
\ No newline at end of file
diff --git a/package.json b/package.json
index 5294f1c..c13927d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "react-datetime",
-  "version": "0.3.1",
+  "version": "0.4.0",
   "description": "A lightweight but complete datetime picker React.js component.",
   "homepage": "https://github.com/arqex/react-datetime",
   "repository": {
diff --git a/src/DaysView.js b/src/DaysView.js
index 744df10..d0ee05b 100644
--- a/src/DaysView.js
+++ b/src/DaysView.js
@@ -53,7 +53,7 @@
 
 	renderDays: function() {
 		var date = this.props.viewDate,
-			selected = this.props.selectedDate,
+			selected = this.props.selectedDate.clone(),
 			prevMonth = date.clone().subtract( 1, 'months' ),
 			currentYear = date.year(),
 			currentMonth = date.month(),
@@ -62,6 +62,7 @@
 			maxDate = this.props.maxDate,
 			weeks = [],
 			days = [],
+			renderer = this.props.renderDay || this.renderDay,
 			classes, disabled, dayProps
 		;
 
@@ -87,11 +88,16 @@
 			if( disabled )
 				classes += ' disabled';
 
-			dayProps = { key: prevMonth.format('M_D'), className: classes };
+			dayProps = {
+				key: prevMonth.format('M_D'),
+				'data-value': prevMonth.date(),
+				className: classes
+			};
 			if( !disabled )
 				dayProps.onClick = this.props.updateDate;
 
-			days.push( DOM.td( dayProps, prevMonth.date() ));
+			days.push( renderer( dayProps, prevMonth.clone(), selected ) );
+
 			if( days.length == 7 ){
 				weeks.push( DOM.tr( {key: prevMonth.format('M_D')}, days ) );
 				days = [];
@@ -103,6 +109,10 @@
 		return weeks;
 	},
 
+	renderDay: function( props, currentDate, selectedDate ){
+		return DOM.td( props, currentDate.date() );
+	},
+
 	renderFooter: function(){
 		if( !this.props.timeFormat )
 			return '';
diff --git a/src/MonthsView.js b/src/MonthsView.js
index 2f2b40c..08fe50e 100644
--- a/src/MonthsView.js
+++ b/src/MonthsView.js
@@ -6,22 +6,42 @@
 
 var DOM = React.DOM;
 var DateTimePickerMonths = React.createClass({
+	render: function() {
+		return DOM.div({ className: 'rdtMonths' },[
+			DOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[
+				DOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'years')}, '���')),
+				DOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, this.props.viewDate.year() ),
+				DOM.th({ key: 'next', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'years')}, '���'))
+			]))),
+			DOM.table({ key: 'months'}, DOM.tbody({ key: 'b'}, this.renderMonths()))
+		]);
+	},
+
 	renderMonths: function() {
 		var date = this.props.selectedDate,
 			month = date.month(),
-			monthsShort = date.localeData()._monthsShort,
+			year = this.props.viewDate.year(),
 			rows = [],
 			i = 0,
 			months = [],
-			classes
+			renderer = this.props.renderMonth || this.renderMonth,
+			classes, props
 		;
 
 		while (i < 12) {
 			classes = "month";
-			if( i === month && this.props.viewDate.year() === date.year() )
+			if( i === month && year === date.year() )
 				classes += " active";
 
-			months.push( DOM.td( {key: i, className: classes, onClick: this.props.setDate('month') }, monthsShort[ i ] ));
+			props = {
+				key: i,
+				'data-value': i,
+				className: classes,
+				onClick: this.props.setDate('month')
+			};
+
+			months.push( renderer( props, i, year, date.clone() ));
+
 			if( months.length == 4 ){
 				rows.push( DOM.tr({ key: month + '_' + rows.length }, months) );
 				months = [];
@@ -33,15 +53,8 @@
 		return rows;
 	},
 
-	render: function() {
-		return DOM.div({ className: 'rdtMonths' },[
-			DOM.table({ key: 'a'}, DOM.thead({}, DOM.tr({},[
-				DOM.th({ key: 'prev', className: 'prev' }, DOM.button({onClick: this.props.subtractTime(1, 'years')}, '���')),
-				DOM.th({ key: 'year', className: 'switch', onClick: this.props.showView('years'), colSpan: 2 }, this.props.viewDate.year() ),
-				DOM.th({ key: 'next', className: 'next' }, DOM.button({onClick: this.props.addTime(1, 'years')}, '���'))
-			]))),
-			DOM.table({ key: 'months'}, DOM.tbody({ key: 'b'}, this.renderMonths()))
-		]);
+	renderMonth: function( props, month, year, selectedDate ) {
+		return DOM.td( props, selectedDate.localeData()._monthsShort[ month ] );
 	}
 });
 
diff --git a/src/YearsView.js b/src/YearsView.js
index 8701aa1..6d36d32 100644
--- a/src/YearsView.js
+++ b/src/YearsView.js
@@ -4,33 +4,6 @@
 
 var DOM = React.DOM;
 var DateTimePickerYears = React.createClass({
-	renderYears: function( year ) {
-		var years = [],
-			i = -1,
-			rows = [],
-			classes
-		;
-
-		year--;
-		while (i < 11) {
-			classes = 'year';
-			if( i === -1 | i === 10 )
-				classes += ' old';
-			if( this.props.selectedDate.year() === year )
-				classes += ' active';
-
-			years.push( DOM.td({ key: year, className: classes, onClick: this.props.setDate('year') }, year ));
-			// years.push(<td key={year} className={ classes } onClick={this.props.setDate('year')}>{year}</td>);
-			if( years.length == 4 ){
-				rows.push( DOM.tr({ key: i }, years ) );
-				years = [];
-			}
-
-			year++;
-			i++;
-		}
-		return rows;
-	},
 	render: function() {
 		var year = parseInt(this.props.viewDate.year() / 10, 10) * 10;
 
@@ -42,6 +15,47 @@
 				]))),
 			DOM.table({ key: 'years'}, DOM.tbody({}, this.renderYears( year )))
 		]);
+	},
+
+	renderYears: function( year ) {
+		var years = [],
+			i = -1,
+			rows = [],
+			renderer = this.props.renderYear || this.renderYear,
+			classes, props
+		;
+
+		year--;
+		while (i < 11) {
+			classes = 'year';
+			if( i === -1 | i === 10 )
+				classes += ' old';
+			if( this.props.selectedDate.year() === year )
+				classes += ' active';
+
+			props = {
+				key: year,
+				'data-value': year,
+				className: classes,
+				onClick: this.props.setDate('year')
+			};
+
+			years.push( renderer( props, year, this.props.selectedDate.clone() ));
+
+			if( years.length == 4 ){
+				rows.push( DOM.tr({ key: i }, years ) );
+				years = [];
+			}
+
+			year++;
+			i++;
+		}
+
+		return rows;
+	},
+
+	renderYear: function( props, year, selectedDate ){
+		return DOM.td( props, year );
 	}
 });
 

--
Gitblit v1.9.3