Layne Anderson
2018-07-03 49de8cf59095fa3fb450f7ec938c68af4ea9961a
src/TimeView.js
@@ -1,102 +1,114 @@
'use strict';
var React = require('react'),
   assign = require('object-assign');
   createClass = require('create-react-class'),
   assign = require('object-assign'),
   onClickOutside = require('react-onclickoutside').default
   ;
var DOM = React.DOM;
var DateTimePickerTime = React.createClass({
   getInitialState: function(){
var DateTimePickerTime = onClickOutside( createClass({
   getInitialState: function() {
      return this.calculateState( this.props );
   },
   calculateState: function( props ){
   calculateState: function( props ) {
      var date = props.selectedDate || props.viewDate,
         format = props.timeFormat,
         counters = []
      ;
         ;
      if ( format.indexOf('H') !== -1 || format.indexOf('h') !== -1 ){
      if ( format.toLowerCase().indexOf('h') !== -1 ) {
         counters.push('hours');
         if ( format.indexOf('m') !== -1 ){
         if ( format.indexOf('m') !== -1 ) {
            counters.push('minutes');
            if ( format.indexOf('s') !== -1 ){
            if ( format.indexOf('s') !== -1 ) {
               counters.push('seconds');
            }
         }
      }
      var hours = date.format( 'H' );
      var daypart = false;
      if ( this.props.timeFormat.indexOf(' A') !== -1  && this.state !== null ){
         daypart = ( this.state.hours >= 12 ) ? 'PM' : 'AM';
      if ( this.state !== null && this.props.timeFormat.toLowerCase().indexOf( ' a' ) !== -1 ) {
         if ( this.props.timeFormat.indexOf( ' A' ) !== -1 ) {
            daypart = ( hours >= 12 ) ? 'PM' : 'AM';
         } else {
            daypart = ( hours >= 12 ) ? 'pm' : 'am';
         }
      }
      return {
         hours: date.format('H'),
         minutes: date.format('mm'),
         seconds: date.format('ss'),
         milliseconds: date.format('SSS'),
         hours: hours,
         minutes: date.format( 'mm' ),
         seconds: date.format( 'ss' ),
         milliseconds: date.format( 'SSS' ),
         daypart: daypart,
         counters: counters
      };
   },
   renderCounter: function( type ){
      if (type !== 'daypart') {
   renderCounter: function( type ) {
      if ( type !== 'daypart' ) {
         var value = this.state[ type ];
         if (type === 'hours' && this.props.timeFormat.indexOf(' A') !== -1 && value > 12) {
            if (value > 12){
               value = value - 12;
            }
            if (value === 0) {
         if ( type === 'hours' && this.props.timeFormat.toLowerCase().indexOf( ' a' ) !== -1 ) {
            value = ( value - 1 ) % 12 + 1;
            if ( value === 0 ) {
               value = 12;
            }
         }
         return DOM.div({ key: type, className: 'rdtCounter'}, [
            DOM.span({ key:'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'increase', type ) }, '▲' ),
            DOM.div({ key:'c', className: 'rdtCount' }, value ),
            DOM.span({ key:'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'decrease', type ) }, '▼' )
         return React.createElement('div', { key: type, className: 'rdtCounter' }, [
            React.createElement('span', { key: 'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'increase', type ), onContextMenu: this.disableContextMenu }, '▲' ),
            React.createElement('div', { key: 'c', className: 'rdtCount' }, value ),
            React.createElement('span', { key: 'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'decrease', type ), onContextMenu: this.disableContextMenu }, '▼' )
         ]);
      }
      return '';
   },
   renderDayPart: function() {
      return DOM.div({ className: 'rdtCounter'}, [
         DOM.span({ key:'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours') }, '▲' ),
         DOM.div({ key: this.state.daypart, className: 'rdtCount'}, this.state.daypart ),
         DOM.span({ key:'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours') }, '▼' )
      return React.createElement('div', { key: 'dayPart', className: 'rdtCounter' }, [
         React.createElement('span', { key: 'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours'), onContextMenu: this.disableContextMenu }, '▲' ),
         React.createElement('div', { key: this.state.daypart, className: 'rdtCount' }, this.state.daypart ),
         React.createElement('span', { key: 'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours'), onContextMenu: this.disableContextMenu }, '▼' )
      ]);
   },
   render: function() {
      var me = this,
         counters = []
      ;
      this.state.counters.forEach( function(c){
      this.state.counters.forEach( function( c ) {
         if ( counters.length )
            counters.push( DOM.div( {key: 'sep' + counters.length, className: 'rdtCounterSeparator' }, ':' ));
            counters.push( React.createElement('div', { key: 'sep' + counters.length, className: 'rdtCounterSeparator' }, ':' ) );
         counters.push( me.renderCounter( c ) );
      });
      if (this.state.daypart !== false) {
      if ( this.state.daypart !== false ) {
         counters.push( me.renderDayPart() );
      }
      if ( this.state.counters.length === 3 && this.props.timeFormat.indexOf('S') !== -1 ){
         counters.push( DOM.div( {className: 'rdtCounterSeparator', key: 'sep5' }, ':' ));
      if ( this.state.counters.length === 3 && this.props.timeFormat.indexOf( 'S' ) !== -1 ) {
         counters.push( React.createElement('div', { className: 'rdtCounterSeparator', key: 'sep5' }, ':' ) );
         counters.push(
            DOM.div( {className: 'rdtCounter rdtMilli', key:'m'},
               DOM.input({ value: this.state.milliseconds, type: 'text', onChange: this.updateMilli })
            React.createElement('div', { className: 'rdtCounter rdtMilli', key: 'm' },
               React.createElement('input', { value: this.state.milliseconds, type: 'text', onChange: this.updateMilli } )
               )
            );
      }
      return DOM.div( {className: 'rdtTime'},
         DOM.table( {}, [
      return React.createElement('div', { className: 'rdtTime' },
         React.createElement('table', {}, [
            this.renderHeader(),
            DOM.tbody({key: 'b'}, DOM.tr({}, DOM.td({},
               DOM.div({ className: 'rdtCounters' }, counters )
            React.createElement('tbody', { key: 'b'}, React.createElement('tr', {}, React.createElement('td', {},
               React.createElement('div', { className: 'rdtCounters' }, counters )
            )))
         ])
      );
   },
   componentWillMount: function() {
      var me = this;
      me.timeConstraints = {
@@ -113,7 +125,7 @@
         seconds: {
            min: 0,
            max: 59,
            step: 1,
            step: 1
         },
         milliseconds: {
            min: 0,
@@ -121,84 +133,105 @@
            step: 1
         }
      };
      ['hours', 'minutes', 'seconds', 'milliseconds'].forEach(function(type) {
         assign(me.timeConstraints[type], me.props.timeConstraints[type]);
      ['hours', 'minutes', 'seconds', 'milliseconds'].forEach( function( type ) {
         assign(me.timeConstraints[ type ], me.props.timeConstraints[ type ]);
      });
      this.setState( this.calculateState( this.props ) );
   },
   componentWillReceiveProps: function( nextProps ){
   componentWillReceiveProps: function( nextProps ) {
      this.setState( this.calculateState( nextProps ) );
   },
   updateMilli: function( e ){
   updateMilli: function( e ) {
      var milli = parseInt( e.target.value, 10 );
      if ( milli === e.target.value && milli >= 0 && milli < 1000 ){
      if ( milli === e.target.value && milli >= 0 && milli < 1000 ) {
         this.props.setTime( 'milliseconds', milli );
         this.setState({ milliseconds: milli });
         this.setState( { milliseconds: milli } );
      }
   },
   renderHeader: function(){
   renderHeader: function() {
      if ( !this.props.dateFormat )
         return null;
      var date = this.props.selectedDate || this.props.viewDate;
      return DOM.thead({ key: 'h'}, DOM.tr({},
         DOM.th( {className: 'rdtSwitch', colSpan: 4, onClick: this.props.showView('days')}, date.format( this.props.dateFormat ) )
      return React.createElement('thead', { key: 'h' }, React.createElement('tr', {},
         React.createElement('th', { className: 'rdtSwitch', colSpan: 4, onClick: this.props.showView( 'days' ) }, date.format( this.props.dateFormat ) )
      ));
   },
   onStartClicking: function( action, type ){
   onStartClicking: function( action, type ) {
      var me = this;
      return function(){
      return function() {
         var update = {};
         update[ type ] = me[ action ]( type );
         me.setState( update );
         me.timer = setTimeout( function(){
            me.increaseTimer = setInterval( function(){
         me.timer = setTimeout( function() {
            me.increaseTimer = setInterval( function() {
               update[ type ] = me[ action ]( type );
               me.setState( update );
            }, 70);
         }, 500);
         me.mouseUpListener = function(){
         me.mouseUpListener = function() {
            clearTimeout( me.timer );
            clearInterval( me.increaseTimer );
            me.props.setTime( type, me.state[ type ] );
            document.body.removeEventListener('mouseup', me.mouseUpListener);
            document.body.removeEventListener( 'mouseup', me.mouseUpListener );
            document.body.removeEventListener( 'touchend', me.mouseUpListener );
         };
         document.body.addEventListener('mouseup', me.mouseUpListener);
         document.body.addEventListener( 'mouseup', me.mouseUpListener );
         document.body.addEventListener( 'touchend', me.mouseUpListener );
      };
   },
   disableContextMenu: function( event ) {
      event.preventDefault();
      return false;
   },
   padValues: {
      hours: 1,
      minutes: 2,
      seconds: 2,
      milliseconds: 3
   },
   toggleDayPart: function( type ){ // type is always 'hours'
      var value = parseInt(this.state[ type ], 10) + 12;
   toggleDayPart: function( type ) { // type is always 'hours'
      var value = parseInt( this.state[ type ], 10) + 12;
      if ( value > this.timeConstraints[ type ].max )
         value = this.timeConstraints[ type ].min + (value - (this.timeConstraints[ type ].max + 1));
         value = this.timeConstraints[ type ].min + ( value - ( this.timeConstraints[ type ].max + 1 ) );
      return this.pad( type, value );
   },
   increase: function( type ){
      var value = parseInt(this.state[ type ], 10) + this.timeConstraints[ type ].step;
   increase: function( type ) {
      var value = parseInt( this.state[ type ], 10) + this.timeConstraints[ type ].step;
      if ( value > this.timeConstraints[ type ].max )
         value = this.timeConstraints[ type ].min + ( value - ( this.timeConstraints[ type ].max  + 1) );
         value = this.timeConstraints[ type ].min + ( value - ( this.timeConstraints[ type ].max + 1 ) );
      return this.pad( type, value );
   },
   decrease: function( type ){
      var value = parseInt(this.state[ type ], 10) - this.timeConstraints[ type ].step;
   decrease: function( type ) {
      var value = parseInt( this.state[ type ], 10) - this.timeConstraints[ type ].step;
      if ( value < this.timeConstraints[ type ].min )
         value = this.timeConstraints[ type ].max + 1 - ( this.timeConstraints[ type ].min - value );
      return this.pad( type, value );
   },
   pad: function( type, value ){
   pad: function( type, value ) {
      var str = value + '';
      while ( str.length < this.padValues[ type ] )
         str = '0' + str;
      return str;
   },
   handleClickOutside: function() {
      this.props.handleClickOutside();
   }
});
}));
module.exports = DateTimePickerTime;