marquex
2015-10-14 692390104a4e1409fb99a1be69026af876ecac06
DateTime.js
@@ -1,7 +1,5 @@
'use strict';
require('classlist-polyfill');
var assign = require('object-assign'),
   React = require('react'),
   DaysView = require('./src/DaysView'),
@@ -23,107 +21,130 @@
      time: TimeView
   },
   propTypes: {
      date: TYPES.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,
      timeFormat: TYPES.string,
      // dateFormat: TYPES.string | TYPES.bool,
      // timeFormat: TYPES.string | TYPES.bool,
      inputProps: TYPES.object,
      viewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),
      minDate: TYPES.object,
      maxDate: TYPES.object
      isValidDate: TYPES.func,
      open: TYPES.bool,
      strictParsing: TYPES.bool
   },
   getDefaultProps: function() {
      var nof = function(){};
      return {
         className: 'form-control',
         date: new Date(),
         className: '',
         defaultValue: '',
         viewMode: 'days',
         inputProps: {},
         input: true,
         onBlur: nof,
         onChange: 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: this.localMoment(date).startOf("month"),
         selectedDate: this.localMoment(date),
         inputValue: this.localMoment(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 = locale.longDateFormat('L');
         formats.time = locale.longDateFormat('LT');
         formats.datetime = formats.date + ' ' + formats.time;
      }
      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
         });
      }
   },
   onChange: function(event) {
      var value = event.target == null ? event : event.target.value,
         localMoment = this.localMoment( value )
      var formats = this.getFormats( nextProps ),
         update = {}
      ;
      if (localMoment.isValid()) {
         this.setState({
            selectedDate: localMoment,
            viewDate: localMoment.clone().startOf("month")
         });
      if( nextProps.value != this.props.value ){
         update = this.getStateFromProps( nextProps );
      }
      if ( formats.datetime !== this.getFormats( this.props ).datetime ) {
         update.inputFormat = formats.datetime;
      }
      return this.setState({
         inputValue: value
      }, function() {
         if( localMoment.isValid() )
            return this.props.onChange( localMoment );
      this.setState( update );
   },
   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( update, function() {
         return this.props.onChange( localMoment.isValid() ? localMoment : this.state.inputValue );
      });
   },
@@ -174,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
      ;
@@ -186,18 +208,20 @@
         date[ nextType ]( date[nextType]() );
      }
      this.setState({
         selectedDate: date,
         inputValue: date.format( this.state.inputFormat )
      });
      if( !this.props.value ){
         this.setState({
            selectedDate: date,
            inputValue: date.format( state.inputFormat )
         });
      }
      this.props.onChange( date );
   },
   updateDate: function( e ) {
   updateSelectedDate: function( e ) {
      var target = e.target,
         modifier = 0,
         currentDate = this.state.selectedDate,
         viewDate = this.state.viewDate,
         currentDate = this.state.selectedDate || viewDate,
         date
      ;
@@ -206,8 +230,8 @@
      else if(target.className.indexOf("old") != -1)
         modifier = -1;
      date = this.state.viewDate.clone()
         .month( this.state.viewDate.month() + modifier )
      date = viewDate.clone()
         .month( viewDate.month() + modifier )
         .date( parseInt( target.getAttribute('data-value') ) )
         .hours( currentDate.hours() )
         .minutes( currentDate.minutes() )
@@ -215,11 +239,13 @@
         .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 );
   },
@@ -229,22 +255,23 @@
   },
   handleClickOutside: function(){
      this.props.onBlur( this.state.selectedDate );
      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 ){
      var m = moment( date );
   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', 'renderDay', 'renderMonth', 'renderYear'],
      fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear'],
      fromState: ['viewDate', 'selectedDate' ],
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateDate', 'localMoment']
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment']
   },
   getComponentProps: function(){
@@ -269,7 +296,7 @@
   render: function() {
      var Component = this.viewComponents[ this.state.currentView ],
         DOM = React.DOM,
         className = 'rdt',
         className = 'rdt ' + this.props.className,
         children = []
      ;
@@ -279,7 +306,7 @@
            type:'text',
            className: 'form-control',
            onFocus: this.openCalendar,
            onChange: this.onChange,
            onChange: this.onInputChange,
            value: this.state.inputValue
         }, this.props.inputProps ))];
      }