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