Layne Anderson
2017-09-30 39b8275f9b2bbd8f11ffecba94fce7d339c4d577
commit | author | age
d76f7b 1 'use strict';
M 2
bc8e0f 3 var React = require('react'),
cf3d92 4     createClass = require('create-react-class'),
11612b 5     assign = require('object-assign'),
39b827 6     onClickOutside = require('react-onclickoutside').default
cf3d92 7     ;
d76f7b 8
84755c 9 var DateTimePickerTime = onClickOutside( createClass({
cf1e72 10     getInitialState: function() {
c658ad 11         return this.calculateState( this.props );
M 12     },
f0ec5a 13
cf1e72 14     calculateState: function( props ) {
62fd2f 15         var date = props.selectedDate || props.viewDate,
c658ad 16             format = props.timeFormat,
d76f7b 17             counters = []
cf3d92 18             ;
d76f7b 19
cf1e72 20         if ( format.toLowerCase().indexOf('h') !== -1 ) {
d76f7b 21             counters.push('hours');
cf1e72 22             if ( format.indexOf('m') !== -1 ) {
d76f7b 23                 counters.push('minutes');
cf1e72 24                 if ( format.indexOf('s') !== -1 ) {
d76f7b 25                     counters.push('seconds');
M 26                 }
27             }
28         }
29
fa70cd 30         var daypart = false;
f0ec5a 31         if ( this.state !== null && this.props.timeFormat.toLowerCase().indexOf( ' a' ) !== -1 ) {
SE 32             if ( this.props.timeFormat.indexOf( ' A' ) !== -1 ) {
cf1e72 33                 daypart = ( this.state.hours >= 12 ) ? 'PM' : 'AM';
SE 34             } else {
35                 daypart = ( this.state.hours >= 12 ) ? 'pm' : 'am';
36             }
a17593 37         }
MK 38
d76f7b 39         return {
f0ec5a 40             hours: date.format( 'H' ),
SE 41             minutes: date.format( 'mm' ),
42             seconds: date.format( 'ss' ),
43             milliseconds: date.format( 'SSS' ),
a17593 44             daypart: daypart,
d76f7b 45             counters: counters
M 46         };
47     },
1a0429 48
f0ec5a 49     renderCounter: function( type ) {
SE 50         if ( type !== 'daypart' ) {
51             var value = this.state[ type ];
52             if ( type === 'hours' && this.props.timeFormat.toLowerCase().indexOf( ' a' ) !== -1 ) {
53                 value = ( value - 1 ) % 12 + 1;
54
55                 if ( value === 0 ) {
7c7053 56                     value = 12;
ER 57                 }
a17593 58             }
a50b2e 59             return React.createElement('div', { key: type, className: 'rdtCounter' }, [
GL 60                 React.createElement('span', { key: 'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'increase', type ) }, '▲' ),
61                 React.createElement('div', { key: 'c', className: 'rdtCount' }, value ),
62                 React.createElement('span', { key: 'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'decrease', type ) }, '▼' )
a17593 63             ]);
MK 64         }
65         return '';
d76f7b 66     },
f0ec5a 67
3bf154 68     renderDayPart: function() {
a50b2e 69         return React.createElement('div', { key: 'dayPart', className: 'rdtCounter' }, [
GL 70             React.createElement('span', { key: 'up', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours') }, '▲' ),
71             React.createElement('div', { key: this.state.daypart, className: 'rdtCount' }, this.state.daypart ),
72             React.createElement('span', { key: 'do', className: 'rdtBtn', onMouseDown: this.onStartClicking( 'toggleDayPart', 'hours') }, '▼' )
3bf154 73         ]);
DF 74     },
f0ec5a 75
d76f7b 76     render: function() {
M 77         var me = this,
78             counters = []
79         ;
80
f0ec5a 81         this.state.counters.forEach( function( c ) {
462115 82             if ( counters.length )
a50b2e 83                 counters.push( React.createElement('div', { key: 'sep' + counters.length, className: 'rdtCounterSeparator' }, ':' ) );
d76f7b 84             counters.push( me.renderCounter( c ) );
M 85         });
a17593 86
f0ec5a 87         if ( this.state.daypart !== false ) {
3bf154 88             counters.push( me.renderDayPart() );
a17593 89         }
MK 90
f0ec5a 91         if ( this.state.counters.length === 3 && this.props.timeFormat.indexOf( 'S' ) !== -1 ) {
a50b2e 92             counters.push( React.createElement('div', { className: 'rdtCounterSeparator', key: 'sep5' }, ':' ) );
d76f7b 93             counters.push(
a50b2e 94                 React.createElement('div', { className: 'rdtCounter rdtMilli', key: 'm' },
GL 95                     React.createElement('input', { value: this.state.milliseconds, type: 'text', onChange: this.updateMilli } )
d76f7b 96                     )
M 97                 );
98         }
99
a50b2e 100         return React.createElement('div', { className: 'rdtTime' },
GL 101             React.createElement('table', {}, [
a3a33b 102                 this.renderHeader(),
a50b2e 103                 React.createElement('tbody', { key: 'b'}, React.createElement('tr', {}, React.createElement('td', {},
GL 104                     React.createElement('div', { className: 'rdtCounters' }, counters )
a3a33b 105                 )))
M 106             ])
d76f7b 107         );
c658ad 108     },
f0ec5a 109
bc8e0f 110     componentWillMount: function() {
LG 111         var me = this;
9c55be 112         me.timeConstraints = {
AG 113             hours: {
114                 min: 0,
115                 max: 23,
116                 step: 1
117             },
118             minutes: {
119                 min: 0,
120                 max: 59,
121                 step: 1
122             },
123             seconds: {
124                 min: 0,
125                 max: 59,
cf1e72 126                 step: 1
9c55be 127             },
AG 128             milliseconds: {
129                 min: 0,
130                 max: 999,
131                 step: 1
132             }
133         };
f0ec5a 134         ['hours', 'minutes', 'seconds', 'milliseconds'].forEach( function( type ) {
cf1e72 135             assign(me.timeConstraints[ type ], me.props.timeConstraints[ type ]);
bc8e0f 136         });
79e319 137         this.setState( this.calculateState( this.props ) );
bc8e0f 138     },
f0ec5a 139
cf1e72 140     componentWillReceiveProps: function( nextProps ) {
c658ad 141         this.setState( this.calculateState( nextProps ) );
d76f7b 142     },
f0ec5a 143
cf1e72 144     updateMilli: function( e ) {
462115 145         var milli = parseInt( e.target.value, 10 );
cf1e72 146         if ( milli === e.target.value && milli >= 0 && milli < 1000 ) {
d76f7b 147             this.props.setTime( 'milliseconds', milli );
cf1e72 148             this.setState( { milliseconds: milli } );
d76f7b 149         }
M 150     },
f0ec5a 151
cf1e72 152     renderHeader: function() {
462115 153         if ( !this.props.dateFormat )
49a27b 154             return null;
d76f7b 155
62fd2f 156         var date = this.props.selectedDate || this.props.viewDate;
a50b2e 157         return React.createElement('thead', { key: 'h' }, React.createElement('tr', {},
GL 158             React.createElement('th', { className: 'rdtSwitch', colSpan: 4, onClick: this.props.showView( 'days' ) }, date.format( this.props.dateFormat ) )
d76f7b 159         ));
M 160     },
f0ec5a 161
cf1e72 162     onStartClicking: function( action, type ) {
462115 163         var me = this;
59314a 164
cf1e72 165         return function() {
d76f7b 166             var update = {};
M 167             update[ type ] = me[ action ]( type );
168             me.setState( update );
169
cf1e72 170             me.timer = setTimeout( function() {
SE 171                 me.increaseTimer = setInterval( function() {
d76f7b 172                     update[ type ] = me[ action ]( type );
M 173                     me.setState( update );
462115 174                 }, 70);
d76f7b 175             }, 500);
M 176
cf1e72 177             me.mouseUpListener = function() {
d76f7b 178                 clearTimeout( me.timer );
M 179                 clearInterval( me.increaseTimer );
180                 me.props.setTime( type, me.state[ type ] );
f0ec5a 181                 document.body.removeEventListener( 'mouseup', me.mouseUpListener );
4e9d38 182             };
M 183
f0ec5a 184             document.body.addEventListener( 'mouseup', me.mouseUpListener );
d76f7b 185         };
0b3475 186     },
f0ec5a 187
0b3475 188     padValues: {
LG 189         hours: 1,
190         minutes: 2,
191         seconds: 2,
192         milliseconds: 3
d76f7b 193     },
f0ec5a 194
cf1e72 195     toggleDayPart: function( type ) { // type is always 'hours'
f0ec5a 196         var value = parseInt( this.state[ type ], 10) + 12;
0b3475 197         if ( value > this.timeConstraints[ type ].max )
cf1e72 198             value = this.timeConstraints[ type ].min + ( value - ( this.timeConstraints[ type ].max + 1 ) );
d76f7b 199         return this.pad( type, value );
M 200     },
f0ec5a 201
SE 202     increase: function( type ) {
203         var value = parseInt( this.state[ type ], 10) + this.timeConstraints[ type ].step;
204         if ( value > this.timeConstraints[ type ].max )
205             value = this.timeConstraints[ type ].min + ( value - ( this.timeConstraints[ type ].max + 1 ) );
206         return this.pad( type, value );
207     },
208
cf1e72 209     decrease: function( type ) {
f0ec5a 210         var value = parseInt( this.state[ type ], 10) - this.timeConstraints[ type ].step;
0b3475 211         if ( value < this.timeConstraints[ type ].min )
4ed404 212             value = this.timeConstraints[ type ].max + 1 - ( this.timeConstraints[ type ].min - value );
d76f7b 213         return this.pad( type, value );
M 214     },
f0ec5a 215
cf1e72 216     pad: function( type, value ) {
d76f7b 217         var str = value + '';
462115 218         while ( str.length < this.padValues[ type ] )
d76f7b 219             str = '0' + str;
M 220         return str;
11612b 221     },
JM 222
cf3d92 223     handleClickOutside: function() {
SE 224         this.props.handleClickOutside();
225     }
11612b 226 }));
d76f7b 227
M 228 module.exports = DateTimePickerTime;