marquex
2015-10-14 692390104a4e1409fb99a1be69026af876ecac06
DateTime.js
@@ -9,6 +9,7 @@
   moment = require('moment')
;
var TYPES = React.PropTypes;
var Datetime = React.createClass({
   mixins: [
      require('react-onclickoutside')
@@ -20,99 +21,130 @@
      time: TimeView
   },
   propTypes: {
      date: React.PropTypes.object,
      onChange: React.PropTypes.func,
      input: React.PropTypes.bool,
      dateFormat: React.PropTypes.string,
      timeFormat: React.PropTypes.string,
      inputProps: React.PropTypes.object,
      viewMode: React.PropTypes.oneOf(['years', 'months', 'days', 'time']),
      minDate: React.PropTypes.object,
      maxDate: React.PropTypes.object
      // value: TYPES.object | TYPES.string,
      // defaultValue: TYPES.object | TYPES.string,
      onBlur: TYPES.func,
      onChange: TYPES.func,
      locale: TYPES.string,
      input: TYPES.bool,
      // dateFormat: TYPES.string | TYPES.bool,
      // timeFormat: TYPES.string | TYPES.bool,
      inputProps: TYPES.object,
      viewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),
      isValidDate: TYPES.func,
      open: TYPES.bool,
      strictParsing: TYPES.bool
   },
   getDefaultProps: function() {
   getDefaultProps: function() {
      var nof = function(){};
      return {
         date: new Date(),
         className: '',
         defaultValue: '',
         viewMode: 'days',
         inputProps: {},
         input: true,
         onChange: function (x) {
            console.log(x);
         }
         onBlur: nof,
         onChange: nof,
         timeFormat: true,
         dateFormat: true,
         strictParsing: true
      };
   },
   getInitialState: function() {
      var formats = this.getFormats( this.props ),
         date = this.props.date
      var state = this.getStateFromProps( this.props );
      if( state.open == undefined )
         state.open = !this.props.input;
      state.currentView = this.props.dateFormat ? this.props.viewMode : 'time';
      return state;
   },
   getStateFromProps: function( props ){
      var formats = this.getFormats( props ),
         date = props.value || props.defaultValue,
         selectedDate, viewDate
      ;
      if( date && typeof date == 'string' )
         selectedDate = this.localMoment( date, formats.datetime );
      else if( date )
         selectedDate = this.localMoment( date );
      if( selectedDate && !selectedDate.isValid() )
         selectedDate = null;
      viewDate = selectedDate ?
         selectedDate.clone().startOf("month") :
         this.localMoment().startOf("month")
      ;
      return {
         currentView: this.props.viewMode,
         open: !this.props.input,
         inputFormat: formats.datetime,
         viewDate: moment(date).startOf("month"),
         selectedDate: moment(date),
         inputValue: moment(date).format( formats.datetime )
         viewDate: viewDate,
         selectedDate: selectedDate,
         inputValue: selectedDate ? selectedDate.format( formats.datetime ) : (date || ''),
         open: props.open != undefined ? props.open : this.state && this.state.open
      };
   },
   getFormats: function( props ){
      var formats = {
         date: '',
         time: '',
         datetime: ''
      };
            date: props.dateFormat || '',
            time: props.timeFormat || ''
         },
         locale = this.localMoment( props.date ).localeData()
      ;
      if( props.dateFormat ){
         formats.date = props.dateFormat;
      if( formats.date === true ){
         formats.date = locale.longDateFormat('L');
      }
      if( props.timeFormat ){
         formats.time = props.timeFormat;
      if( formats.time === true ){
         formats.time = locale.longDateFormat('LT');
      }
      if( !formats.date && !formats.time ){
         formats.date = 'MM/DD/YY';
         formats.time = 'H:mm';
         formats.datetime = 'MM/DD/YY H:mm';
      }
      else {
         if( props.dateFormat ){
            formats.date = props.dateFormat;
            formats.datetime = formats.date;
         }
         if( props.timeFormat ){
            if( formats.date )
               formats.datetime += ' ';
            formats.time = props.timeFormat;
            formats.datetime += formats.time;
         }
      }
      formats.datetime = formats.date && formats.time ?
         formats.date + ' ' + formats.time :
         formats.date || formats.time
      ;
      return formats;
   },
   componentWillReceiveProps: function(nextProps) {
      var formats = this.getFormats( nextProps );
      if ( formats.datetime !== this.getFormats(this.props).datetime ) {
         return this.setState({
            inputFormat: nextProps.inputFormat
         });
      var formats = this.getFormats( nextProps ),
         update = {}
      ;
      if( nextProps.value != this.props.value ){
         update = this.getStateFromProps( nextProps );
      }
      if ( formats.datetime !== this.getFormats( this.props ).datetime ) {
         update.inputFormat = formats.datetime;
      }
      this.setState( update );
   },
   onChange: function(event) {
      var value = event.target == null ? event : event.target.value;
      if (moment(value).isValid()) {
         this.setState({
            selectedDate: moment(value),
            viewDate: moment(value).startOf("month")
         });
   onInputChange: function( e ) {
      var value = e.target == null ? e : e.target.value,
         localMoment = this.localMoment( value, this.state.inputFormat ),
         update = { inputValue: value }
      ;
      if ( localMoment.isValid() && !this.props.value ) {
         update.selectedDate = localMoment;
         update.viewDate = localMoment.clone().startOf("month");
      }
      else {
         update.selectedDate = null;
      }
      return this.setState({
         inputValue: value
      }, function() {
         return this.props.onChange(moment(this.state.inputValue, this.state.inputFormat, true).format( this.state.inputFormat ));
      return this.setState( update, function() {
         return this.props.onChange( localMoment.isValid() ? localMoment : this.state.inputValue );
      });
   },
@@ -132,7 +164,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.getAttribute('data-value')) ).startOf( type ),
            currentView: nextViews[ type ]
         });
      };
@@ -163,7 +195,8 @@
   allowedSetTime: ['hours','minutes','seconds', 'milliseconds'],
   setTime: function( type, value ){
      var index = this.allowedSetTime.indexOf( type ) + 1,
         date = this.state.selectedDate.clone(),
         state = this.state,
         date = (state.selectedDate || state.viewDate).clone(),
         nextType
      ;
@@ -175,21 +208,21 @@
         date[ nextType ]( date[nextType]() );
      }
      this.setState({
         selectedDate: date,
         inputValue: date.format( this.state.inputFormat )
      }, this.callOnChange );
      if( !this.props.value ){
         this.setState({
            selectedDate: date,
            inputValue: date.format( state.inputFormat )
         });
      }
      this.props.onChange( date );
   },
   callOnChange: function(){
      this.props.onChange(this.state.selectedDate.format( this.state.inputFormat ));
   },
   updateDate: function( e ) {
   updateSelectedDate: function( e ) {
      var target = e.target,
      modifier = 0,
      currentDate = this.state.selectedDate,
      date
         modifier = 0,
         viewDate = this.state.viewDate,
         currentDate = this.state.selectedDate || viewDate,
         date
      ;
      if(target.className.indexOf("new") != -1)
@@ -197,20 +230,24 @@
      else if(target.className.indexOf("old") != -1)
         modifier = -1;
      date = this.state.viewDate.clone()
         .month( this.state.viewDate.month() + modifier )
         .date( parseInt( target.innerHTML ) )
      date = viewDate.clone()
         .month( viewDate.month() + modifier )
         .date( parseInt( target.getAttribute('data-value') ) )
         .hours( currentDate.hours() )
         .minutes( currentDate.minutes() )
         .seconds( currentDate.seconds() )
         .milliseconds( currentDate.milliseconds() )
      ;
      this.setState({
         selectedDate: date,
         viewDate: date.clone().startOf('month'),
         inputValue: date.format( this.state.inputFormat )
      });
      if( !this.props.value ){
         this.setState({
            selectedDate: date,
            viewDate: date.clone().startOf('month'),
            inputValue: date.format( this.state.inputFormat )
         });
      }
      this.props.onChange( date );
   },
   openCalendar: function() {
@@ -218,14 +255,23 @@
   },
   handleClickOutside: function(){
      if( this.props.input && this.state.open )
      if( this.props.input && this.state.open && !this.props.open ){
         this.setState({ open: false });
         this.props.onBlur( this.state.selectedDate || this.state.inputValue );
      }
   },
   localMoment: function( date, format ){
      var m = moment( date, format, this.props.strictParsing );
      if( this.props.locale )
         m.locale( this.props.locale );
      return m;
   },
   componentProps: {
      fromProps: ['viewMode', 'minDate', 'maxDate'],
      fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear'],
      fromState: ['viewDate', 'selectedDate' ],
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateDate']
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment']
   },
   getComponentProps: function(){
@@ -250,7 +296,7 @@
   render: function() {
      var Component = this.viewComponents[ this.state.currentView ],
         DOM = React.DOM,
         className = 'rdt',
         className = 'rdt ' + this.props.className,
         children = []
      ;
@@ -258,9 +304,9 @@
         children = [ DOM.input( assign({
            key: 'i',
            type:'text',
            className:'form-control',
            className: 'form-control',
            onFocus: this.openCalendar,
            onChange: this.onChange,
            onChange: this.onInputChange,
            value: this.state.inputValue
         }, this.props.inputProps ))];
      }
@@ -280,4 +326,7 @@
   }
});
// Make moment accessible through the Datetime class
Datetime.moment = moment;
module.exports = Datetime;