Layne Anderson
2018-07-03 49de8cf59095fa3fb450f7ec938c68af4ea9961a
src/TimeView.js
@@ -1,151 +1,237 @@
'use strict';
var React = require('react');
var React = require('react'),
   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.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 ){
      return DOM.div({ key: type, className: 'rdtCounter'}, [
         DOM.button({ key:'up', className: 'btn', onMouseDown: this.onStartClicking( 'increase', type ), type: 'button' }, '▲' ),
         DOM.div({ key:'c', className: 'rdtCount' }, this.state[ type ] ),
         DOM.button({ key:'do', className: 'btn', onMouseDown: this.onStartClicking( 'decrease', type ), type: 'button' }, '▼' )
   renderCounter: function( type ) {
      if ( type !== 'daypart' ) {
         var value = this.state[ type ];
         if ( type === 'hours' && this.props.timeFormat.toLowerCase().indexOf( ' a' ) !== -1 ) {
            value = ( value - 1 ) % 12 + 1;
            if ( value === 0 ) {
               value = 12;
            }
         }
         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 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){
         if( counters.length )
            counters.push( DOM.div( {key: 'sep' + counters.length, className: 'rdtCounterSeparator' }, ':' ));
      this.state.counters.forEach( function( c ) {
         if ( counters.length )
            counters.push( React.createElement('div', { key: 'sep' + counters.length, className: 'rdtCounterSeparator' }, ':' ) );
         counters.push( me.renderCounter( c ) );
      });
      if( this.state.counters.length == 3 && this.props.timeFormat.indexOf('S') != -1 ){
         counters.push( DOM.div( {className: 'rdtCounterSeparator', key: 'sep5' }, ':' ));
      if ( this.state.daypart !== false ) {
         counters.push( me.renderDayPart() );
      }
      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 )
            )))
         ])
      );
   },
   componentWillReceiveProps: function( nextProps, nextState ){
   componentWillMount: function() {
      var me = this;
      me.timeConstraints = {
         hours: {
            min: 0,
            max: 23,
            step: 1
         },
         minutes: {
            min: 0,
            max: 59,
            step: 1
         },
         seconds: {
            min: 0,
            max: 59,
            step: 1
         },
         milliseconds: {
            min: 0,
            max: 999,
            step: 1
         }
      };
      ['hours', 'minutes', 'seconds', 'milliseconds'].forEach( function( type ) {
         assign(me.timeConstraints[ type ], me.props.timeConstraints[ type ]);
      });
      this.setState( this.calculateState( this.props ) );
   },
   componentWillReceiveProps: function( nextProps ) {
      this.setState( this.calculateState( nextProps ) );
   },
   updateMilli: function( e ){
      var milli = parseInt( e.target.value );
      if( milli == e.target.value && milli >= 0 && milli < 1000 ){
   updateMilli: function( e ) {
      var milli = parseInt( e.target.value, 10 );
      if ( milli === e.target.value && milli >= 0 && milli < 1000 ) {
         this.props.setTime( 'milliseconds', milli );
         this.setState({ milliseconds: milli });
         this.setState( { milliseconds: milli } );
      }
   },
   renderHeader: function(){
      if( !this.props.dateFormat )
         return '';
   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: 'switch', 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 ){
      var me = this,
         update = {},
         value = this.state[ 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);
            }, 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 );
      };
   },
   maxValues: {
      hours: 23,
      minutes: 59,
      seconds: 59,
      milliseconds: 999
   disableContextMenu: function( event ) {
      event.preventDefault();
      return false;
   },
   padValues: {
      hours: 1,
      minutes: 2,
      seconds: 2,
      milliseconds: 3
   },
   increase: function( type ){
      var value = parseInt(this.state[ type ]) + 1;
      if( value > this.maxValues[ type ] )
         value = 0;
   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 ) );
      return this.pad( type, value );
   },
   decrease: function( type ){
      var value = parseInt(this.state[ type ]) - 1;
      if( value < 0 )
         value = this.maxValues[ type ];
   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 ) );
      return this.pad( type, value );
   },
   pad: function( type, value ){
   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 ) {
      var str = value + '';
      while( str.length < this.padValues[ type ] )
      while ( str.length < this.padValues[ type ] )
         str = '0' + str;
      return str;
   },
   handleClickOutside: function() {
      this.props.handleClickOutside();
   }
});
}));
module.exports = DateTimePickerTime;