Simon Egersand
2018-02-11 d4bf16e299f8ea25477ed9c15a336bce36affe4b
DateTime.js
@@ -1,31 +1,30 @@
'use strict';
var assign = require('object-assign'),
   PropTypes = require('prop-types'),
   createClass = require('create-react-class'),
   moment = require('moment'),
   React = require('react'),
   DaysView = require('./src/DaysView'),
   MonthsView = require('./src/MonthsView'),
   YearsView = require('./src/YearsView'),
   TimeView = require('./src/TimeView')
;
   CalendarContainer = require('./src/CalendarContainer')
   ;
var TYPES = React.PropTypes;
var Datetime = React.createClass({
   mixins: [
      require('./src/onClickOutside')
   ],
   viewComponents: {
      days: DaysView,
      months: MonthsView,
      years: YearsView,
      time: TimeView
   },
var viewModes = Object.freeze({
   YEARS: 'years',
   MONTHS: 'months',
   DAYS: 'days',
   TIME: 'time',
});
var TYPES = PropTypes;
var Datetime = createClass({
   propTypes: {
      // value: TYPES.object | TYPES.string,
      // defaultValue: TYPES.object | TYPES.string,
      // viewDate: TYPES.object | TYPES.string,
      onFocus: TYPES.func,
      onBlur: TYPES.func,
      onChange: TYPES.func,
      onViewModeChange: TYPES.func,
      locale: TYPES.string,
      utc: TYPES.bool,
      input: TYPES.bool,
@@ -33,32 +32,12 @@
      // timeFormat: TYPES.string | TYPES.bool,
      inputProps: TYPES.object,
      timeConstraints: TYPES.object,
      viewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),
      viewMode: TYPES.oneOf([viewModes.YEARS, viewModes.MONTHS, viewModes.DAYS, viewModes.TIME]),
      isValidDate: TYPES.func,
      open: TYPES.bool,
      strictParsing: TYPES.bool,
      closeOnSelect: TYPES.bool,
      closeOnTab: TYPES.bool
   },
   getDefaultProps: function() {
      var nof = function() {};
      return {
         className: '',
         defaultValue: '',
         inputProps: {},
         input: true,
         onFocus: nof,
         onBlur: nof,
         onChange: nof,
         timeFormat: true,
         timeConstraints: {},
         dateFormat: true,
         strictParsing: true,
         closeOnSelect: false,
         closeOnTab: true,
         utc: false
      };
   },
   getInitialState: function() {
@@ -67,29 +46,39 @@
      if ( state.open === undefined )
         state.open = !this.props.input;
      state.currentView = this.props.dateFormat ? (this.props.viewMode || state.updateOn || 'days') : 'time';
      state.currentView = this.props.dateFormat ?
         (this.props.viewMode || state.updateOn || viewModes.DAYS) : viewModes.TIME;
      return state;
   },
   parseDate: function (date, formats) {
      var parsedDate;
      if (date && typeof date === 'string')
         parsedDate = this.localMoment(date, formats.datetime);
      else if (date)
         parsedDate = this.localMoment(date);
      if (parsedDate && !parsedDate.isValid())
         parsedDate = null;
      return parsedDate;
   },
   getStateFromProps: function( props ) {
      var formats = this.getFormats( props ),
         date = props.value || props.defaultValue,
         selectedDate, viewDate, updateOn, inputValue
      ;
         ;
      if ( date && typeof date === 'string' )
         selectedDate = this.localMoment( date, formats.datetime );
      else if ( date )
         selectedDate = this.localMoment( date );
      selectedDate = this.parseDate(date, formats);
      if ( selectedDate && !selectedDate.isValid() )
         selectedDate = null;
      viewDate = this.parseDate(props.viewDate, formats);
      viewDate = selectedDate ?
         selectedDate.clone().startOf('month') :
         this.localMoment().startOf('month')
      ;
         viewDate ? viewDate.clone().startOf('month') : this.localMoment().startOf('month');
      updateOn = this.getUpdateOn(formats);
@@ -112,16 +101,14 @@
   getUpdateOn: function( formats ) {
      if ( formats.date.match(/[lLD]/) ) {
         return 'days';
      }
      else if ( formats.date.indexOf('M') !== -1 ) {
         return 'months';
      }
      else if ( formats.date.indexOf('Y') !== -1 ) {
         return 'years';
         return viewModes.DAYS;
      } else if ( formats.date.indexOf('M') !== -1 ) {
         return viewModes.MONTHS;
      } else if ( formats.date.indexOf('Y') !== -1 ) {
         return viewModes.YEARS;
      }
      return 'days';
      return viewModes.DAYS;
   },
   getFormats: function( props ) {
@@ -130,12 +117,12 @@
            time: props.timeFormat || ''
         },
         locale = this.localMoment( props.date, null, props ).localeData()
      ;
         ;
      if ( formats.date === true ) {
         formats.date = locale.longDateFormat('L');
      }
      else if ( this.getUpdateOn(formats) !== 'days' ) {
      else if ( this.getUpdateOn(formats) !== viewModes.DAYS ) {
         formats.time = '';
      }
@@ -162,7 +149,13 @@
      }
      if ( updatedState.open === undefined ) {
         updatedState.open = this.state.open;
         if ( typeof nextProps.open !== 'undefined' ) {
            updatedState.open = nextProps.open;
         } else if ( this.props.closeOnSelect && this.state.currentView !== viewModes.TIME ) {
            updatedState.open = false;
         } else {
            updatedState.open = this.state.open;
         }
      }
      if ( nextProps.viewMode !== this.props.viewMode ) {
@@ -199,6 +192,16 @@
         }
      }
      if ( nextProps.viewDate !== this.props.viewDate ) {
         updatedState.viewDate = moment(nextProps.viewDate);
      }
      //we should only show a valid date if we are provided a isValidDate function. Removed in 2.10.3
      /*if (this.props.isValidDate) {
         updatedState.viewDate = updatedState.viewDate || this.state.viewDate;
         while (!this.props.isValidDate(updatedState.viewDate)) {
            updatedState.viewDate = updatedState.viewDate.add(1, 'day');
         }
      }*/
      this.setState( updatedState );
   },
@@ -206,13 +209,12 @@
      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 {
      } else {
         update.selectedDate = null;
      }
@@ -230,6 +232,7 @@
   showView: function( view ) {
      var me = this;
      return function() {
         me.state.currentView !== view && me.props.onViewModeChange( view );
         me.setState({ currentView: view });
      };
   },
@@ -237,8 +240,8 @@
   setDate: function( type ) {
      var me = this,
         nextViews = {
            month: 'days',
            year: 'months'
            month: viewModes.DAYS,
            year: viewModes.MONTHS,
         }
      ;
      return function( e ) {
@@ -246,6 +249,7 @@
            viewDate: me.state.viewDate.clone()[ type ]( parseInt(e.target.getAttribute('data-value'), 10) ).startOf( type ),
            currentView: nextViews[ type ]
         });
         me.props.onViewModeChange( nextViews[ type ] );
      };
   },
@@ -277,7 +281,7 @@
         state = this.state,
         date = (state.selectedDate || state.viewDate).clone(),
         nextType
      ;
         ;
      // It is needed to set all the time properties
      // to not to reset the time
@@ -302,7 +306,7 @@
         viewDate = this.state.viewDate,
         currentDate = this.state.selectedDate || viewDate,
         date
    ;
         ;
      if (target.className.indexOf('rdtDay') !== -1) {
         if (target.className.indexOf('rdtNew') !== -1)
@@ -330,14 +334,19 @@
         .milliseconds( currentDate.milliseconds() );
      if ( !this.props.value ) {
         var open = !( this.props.closeOnSelect && close );
         if ( !open ) {
            this.props.onBlur( date );
         }
         this.setState({
            selectedDate: date,
            viewDate: date.clone().startOf('month'),
            inputValue: date.format( this.state.inputFormat ),
            open: !(this.props.closeOnSelect && close )
            open: open
         });
      } else {
         if (this.props.closeOnSelect && close) {
         if ( this.props.closeOnSelect && close ) {
            this.closeCalendar();
         }
      }
@@ -345,10 +354,10 @@
      this.props.onChange( date );
   },
   openCalendar: function() {
      if (!this.state.open) {
   openCalendar: function( e ) {
      if ( !this.state.open ) {
         this.setState({ open: true }, function() {
            this.props.onFocus();
            this.props.onFocus( e );
         });
      }
   },
@@ -360,7 +369,7 @@
   },
   handleClickOutside: function() {
      if ( this.props.input && this.state.open && !this.props.open ) {
      if ( this.props.input && this.state.open && !this.props.open && !this.props.disableOnClickOutside ) {
         this.setState({ open: false }, function() {
            this.props.onBlur( this.state.selectedDate || this.state.inputValue );
         });
@@ -379,14 +388,14 @@
   componentProps: {
      fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear', 'timeConstraints'],
      fromState: ['viewDate', 'selectedDate', 'updateOn'],
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment']
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside']
   },
   getComponentProps: function() {
      var me = this,
         formats = this.getFormats( this.props ),
         props = {dateFormat: formats.date, timeFormat: formats.time}
      ;
         ;
      this.componentProps.fromProps.forEach( function( name ) {
         props[ name ] = me.props[ name ];
@@ -402,24 +411,28 @@
   },
   render: function() {
      var Component = this.viewComponents[ this.state.currentView ],
         DOM = React.DOM,
         className = 'rdt' + (this.props.className ?
      // TODO: Make a function or clean up this code,
      // logic right now is really hard to follow
      var className = 'rdt' + (this.props.className ?
                  ( Array.isArray( this.props.className ) ?
                  ' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
         children = []
      ;
         children = [];
      if ( this.props.input ) {
         children = [ DOM.input( assign({
            key: 'i',
         var finalInputProps = assign({
            type: 'text',
            className: 'form-control',
            onClick: this.openCalendar,
            onFocus: this.openCalendar,
            onChange: this.onInputChange,
            onKeyDown: this.onInputKey,
            value: this.state.inputValue
         }, this.props.inputProps ))];
            value: this.state.inputValue,
         }, this.props.inputProps);
         if ( this.props.renderInput ) {
            children = [ React.createElement('div', { key: 'i' }, this.props.renderInput( finalInputProps, this.openCalendar, this.closeCalendar )) ];
         } else {
            children = [ React.createElement('input', assign({ key: 'i' }, finalInputProps ))];
         }
      } else {
         className += ' rdtStatic';
      }
@@ -427,15 +440,33 @@
      if ( this.state.open )
         className += ' rdtOpen';
      return DOM.div({className: className}, children.concat(
         DOM.div(
      return React.createElement( 'div', { className: className }, children.concat(
         React.createElement( 'div',
            { key: 'dt', className: 'rdtPicker' },
            React.createElement( Component, this.getComponentProps())
            React.createElement( CalendarContainer, { view: this.state.currentView, viewProps: this.getComponentProps(), onClickOutside: this.handleClickOutside })
         )
      ));
   }
});
Datetime.defaultProps = {
   className: '',
   defaultValue: '',
   inputProps: {},
   input: true,
   onFocus: function() {},
   onBlur: function() {},
   onChange: function() {},
   onViewModeChange: function() {},
   timeFormat: true,
   timeConstraints: {},
   dateFormat: true,
   strictParsing: true,
   closeOnSelect: false,
   closeOnTab: true,
   utc: false
};
// Make moment accessible through the Datetime class
Datetime.moment = moment;