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