Anna Kurylo
2018-10-17 ccc40e94e2da9fe9aa1cb560b97e3e618cefb1da
DateTime.js
@@ -1,31 +1,35 @@
/* eslint-disable */
'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'),
   moment = require('moment')
;
   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({
   displayName: 'DateTime',
   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,
      onNavigateBack: TYPES.func,
      onNavigateForward: TYPES.func,
      locale: TYPES.string,
      utc: TYPES.bool,
      input: TYPES.bool,
@@ -33,32 +37,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 +51,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;
   },
   getStateFromProps: function( props ){
   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);
@@ -110,36 +104,34 @@
      };
   },
   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';
   getUpdateOn: function( formats ) {
      if ( formats.date.match(/[lLD]/) ) {
         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 ){
   getFormats: function( props ) {
      var formats = {
            date: props.dateFormat || '',
            time: props.timeFormat || ''
         },
         locale = this.localMoment( props.date ).localeData()
      ;
         locale = this.localMoment( props.date, null, props ).localeData()
         ;
      if ( formats.date === true ){
      if ( formats.date === true ) {
         formats.date = locale.longDateFormat('L');
      }
      else if ( this.getUpdateOn(formats) !== 'days' ){
      else if ( this.getUpdateOn(formats) !== viewModes.DAYS ) {
         formats.time = '';
      }
      if ( formats.time === true ){
      if ( formats.time === true ) {
         formats.time = locale.longDateFormat('LT');
      }
@@ -151,43 +143,83 @@
      return formats;
   },
   componentWillReceiveProps: function(nextProps) {
   componentWillReceiveProps: function( nextProps ) {
      var formats = this.getFormats( nextProps ),
         update = {}
         updatedState = {}
      ;
      if ( nextProps.value !== this.props.value ||
            formats.datetime !== this.getFormats( this.props ).datetime ) {
            update = this.getStateFromProps( nextProps );
         formats.datetime !== this.getFormats( this.props ).datetime ) {
         updatedState = this.getStateFromProps( nextProps );
      }
      if ( update.open === undefined ) {
         if ( this.props.closeOnSelect && this.state.currentView !== 'time' ) {
            update.open = false;
         }
         else {
            update.open = this.state.open;
      if ( updatedState.open === undefined ) {
         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 ) {
         update.currentView = nextProps.viewMode;
         updatedState.currentView = nextProps.viewMode;
      }
      this.setState( update );
      if ( nextProps.locale !== this.props.locale ) {
         if ( this.state.viewDate ) {
            var updatedViewDate = this.state.viewDate.clone().locale( nextProps.locale );
            updatedState.viewDate = updatedViewDate;
         }
         if ( this.state.selectedDate ) {
            var updatedSelectedDate = this.state.selectedDate.clone().locale( nextProps.locale );
            updatedState.selectedDate = updatedSelectedDate;
            updatedState.inputValue = updatedSelectedDate.format( formats.datetime );
         }
      }
      if ( nextProps.utc !== this.props.utc ) {
         if ( nextProps.utc ) {
            if ( this.state.viewDate )
               updatedState.viewDate = this.state.viewDate.clone().utc();
            if ( this.state.selectedDate ) {
               updatedState.selectedDate = this.state.selectedDate.clone().utc();
               updatedState.inputValue = updatedState.selectedDate.format( formats.datetime );
            }
         } else {
            if ( this.state.viewDate )
               updatedState.viewDate = this.state.viewDate.clone().local();
            if ( this.state.selectedDate ) {
               updatedState.selectedDate = this.state.selectedDate.clone().local();
               updatedState.inputValue = updatedState.selectedDate.format(formats.datetime);
            }
         }
      }
      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 );
   },
   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 {
      } else {
         update.selectedDate = null;
      }
@@ -196,63 +228,68 @@
      });
   },
   onInputKey: function( e ){
      if ( e.which === 9 && this.props.closeOnTab ){
   onInputKey: function( e ) {
      if ( e.which === 9 && this.props.closeOnTab ) {
         this.closeCalendar();
      }
   },
   showView: function( view ){
   showView: function( view ) {
      var me = this;
      return function(){
      return function() {
         me.state.currentView !== view && me.props.onViewModeChange( view );
         me.setState({ currentView: view });
      };
   },
   setDate: function( type ){
   setDate: function( type ) {
      var me = this,
         nextViews = {
            month: 'days',
            year: 'months'
            month: viewModes.DAYS,
            year: viewModes.MONTHS,
         }
      ;
      return function( e ){
      return function( e ) {
         me.setState({
            viewDate: me.state.viewDate.clone()[ type ]( parseInt(e.target.getAttribute('data-value'), 10) ).startOf( type ),
            currentView: nextViews[ type ]
         });
         me.props.onViewModeChange( nextViews[ type ] );
      };
   },
   addTime: function( amount, type, toSelected ){
      return this.updateTime( 'add', amount, type, toSelected );
   },
   subtractTime: function( amount, type, toSelected ){
      return this.updateTime( 'subtract', amount, type, toSelected );
   },
   updateTime: function( op, amount, type, toSelected ){
   subtractTime: function( amount, type, toSelected ) {
      var me = this;
      return function(){
         var update = {},
            date = toSelected ? 'selectedDate' : 'viewDate'
         ;
         update[ date ] = me.state[ date ].clone()[ op ]( amount, type );
         me.setState( update );
      return function() {
         me.props.onNavigateBack( amount, type );
         me.updateTime( 'subtract', amount, type, toSelected );
      };
   },
   addTime: function( amount, type, toSelected ) {
      var me = this;
      return function() {
         me.props.onNavigateForward( amount, type );
         me.updateTime( 'add', amount, type, toSelected );
      };
   },
   updateTime: function( op, amount, type, toSelected ) {
      var update = {},
         date = toSelected ? 'selectedDate' : 'viewDate';
      update[ date ] = this.state[ date ].clone()[ op ]( amount, type );
      this.setState( update );
   },
   allowedSetTime: ['hours', 'minutes', 'seconds', 'milliseconds'],
   setTime: function( type, value ){
   setTime: function( type, value ) {
      var index = this.allowedSetTime.indexOf( type ) + 1,
         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
@@ -262,7 +299,7 @@
         date[ nextType ]( date[nextType]() );
      }
      if ( !this.props.value ){
      if ( !this.props.value ) {
         this.setState({
            selectedDate: date,
            inputValue: date.format( state.inputFormat )
@@ -277,9 +314,9 @@
         viewDate = this.state.viewDate,
         currentDate = this.state.selectedDate || viewDate,
         date
    ;
         ;
      if (target.className.indexOf('rdtDay') !== -1){
      if (target.className.indexOf('rdtDay') !== -1) {
         if (target.className.indexOf('rdtNew') !== -1)
            modifier = 1;
         else if (target.className.indexOf('rdtOld') !== -1)
@@ -288,11 +325,11 @@
         date = viewDate.clone()
            .month( viewDate.month() + modifier )
            .date( parseInt( target.getAttribute('data-value'), 10 ) );
      } else if (target.className.indexOf('rdtMonth') !== -1){
      } else if (target.className.indexOf('rdtMonth') !== -1) {
         date = viewDate.clone()
            .month( parseInt( target.getAttribute('data-value'), 10 ) )
            .date( currentDate.date() );
      } else if (target.className.indexOf('rdtYear') !== -1){
      } else if (target.className.indexOf('rdtYear') !== -1) {
         date = viewDate.clone()
            .month( currentDate.month() )
            .date( currentDate.date() )
@@ -304,15 +341,20 @@
         .seconds( currentDate.seconds() )
         .milliseconds( currentDate.milliseconds() );
      if ( !this.props.value ){
      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();
         }
      }
@@ -320,10 +362,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 );
         });
      }
   },
@@ -334,41 +376,42 @@
      });
   },
   handleClickOutside: function(){
      if ( this.props.input && this.state.open && !this.props.open ){
   handleClickOutside: function() {
      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 );
         });
      }
   },
   localMoment: function( date, format ){
      var momentFn = this.props.utc ? moment.utc : moment;
      var m = momentFn( date, format, this.props.strictParsing );
      if ( this.props.locale )
         m.locale( this.props.locale );
   localMoment: function( date, format, props ) {
      props = props || this.props;
      var momentFn = props.utc ? moment.utc : moment;
      var m = momentFn( date, format, props.strictParsing );
      if ( props.locale )
         m.locale( props.locale );
      return m;
   },
   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(){
   getComponentProps: function() {
      var me = this,
         formats = this.getFormats( this.props ),
         props = {dateFormat: formats.date, timeFormat: formats.time}
      ;
         ;
      this.componentProps.fromProps.forEach( function( name ){
      this.componentProps.fromProps.forEach( function( name ) {
         props[ name ] = me.props[ name ];
      });
      this.componentProps.fromState.forEach( function( name ){
      this.componentProps.fromState.forEach( function( name ) {
         props[ name ] = me.state[ name ];
      });
      this.componentProps.fromThis.forEach( function( name ){
      this.componentProps.fromThis.forEach( function( name ) {
         props[ name ] = me[ name ];
      });
@@ -376,24 +419,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',
            type:'text',
      if ( this.props.input ) {
         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';
      }
@@ -401,16 +448,37 @@
      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() {},
   onNavigateBack: function() {},
   onNavigateForward: function() {},
   timeFormat: true,
   timeConstraints: {},
   dateFormat: true,
   strictParsing: true,
   closeOnSelect: false,
   closeOnTab: true,
   utc: false
};
// Make moment accessible through the Datetime class
Datetime.moment = moment;
module.exports = Datetime;
/* eslint-enable */