| | |
| | | '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 date = this.props.selectedDate, |
| | | format = this.props.timeFormat, |
| | | var DateTimePickerTime = onClickOutside( createClass({ |
| | | getInitialState: function() { |
| | | return this.calculateState( this.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.div({ key:'up', className: 'btn', onMouseDown: this.onStartClicking( 'increase', type ) }, '▲' ), |
| | | DOM.div({ key:'c', className: 'rdtCount' }, this.state[ type ] ), |
| | | DOM.div({ key:'do', className: 'btn', onMouseDown: this.onStartClicking( 'increase', type ) }, '▼' ) |
| | | |
| | | 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 ) |
| | | ))) |
| | | ]) |
| | | ); |
| | | |
| | | }, |
| | | updateMilli: function( e ){ |
| | | var milli = parseInt( e.target.value ); |
| | | if( milli == e.target.value && milli >= 0 && milli < 1000 ){ |
| | | |
| | | 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, 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 ''; |
| | | |
| | | return DOM.thead({ key: 'h'}, DOM.tr({}, |
| | | DOM.th( {colSpan: 4, onClick: this.props.showView('days')}, this.props.selectedDate.format( this.props.dateFormat ) ) |
| | | renderHeader: function() { |
| | | if ( !this.props.dateFormat ) |
| | | return null; |
| | | |
| | | var date = this.props.selectedDate || this.props.viewDate; |
| | | 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 = {} |
| | | ; |
| | | return function(){ |
| | | |
| | | onStartClicking: function( action, type ) { |
| | | var me = this; |
| | | |
| | | 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 ); |
| | | },80); |
| | | }, 70); |
| | | }, 500); |
| | | |
| | | document.body.addEventListener('mouseup', 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( 'touchend', 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; |