| | |
| | | 'use strict'; |
| | | |
| | | var React = require('react'), |
| | | createClass = require('create-react-class'), |
| | | assign = require('object-assign'), |
| | | onClickOutside = require('react-onclickoutside').default |
| | | ; |
| | | createClass = require('create-react-class'), |
| | | assign = require('object-assign'), |
| | | onClickOutside = require('react-onclickoutside').default; |
| | | |
| | | var DateTimePickerTime = onClickOutside( createClass({ |
| | | getInitialState: function() { |
| | | return this.calculateState( this.props ); |
| | | }, |
| | | var DateTimePickerTime = onClickOutside( |
| | | createClass({ |
| | | getInitialState: function() { |
| | | return this.calculateState(this.props); |
| | | }, |
| | | |
| | | calculateState: function( props ) { |
| | | var date = props.selectedDate || props.viewDate, |
| | | format = props.timeFormat, |
| | | counters = [] |
| | | ; |
| | | calculateState: function(props) { |
| | | var date = props.selectedDate || props.viewDate, |
| | | format = props.timeFormat, |
| | | counters = []; |
| | | |
| | | if ( format.toLowerCase().indexOf('h') !== -1 ) { |
| | | counters.push('hours'); |
| | | if ( format.indexOf('m') !== -1 ) { |
| | | counters.push('minutes'); |
| | | if ( format.indexOf('s') !== -1 ) { |
| | | counters.push('seconds'); |
| | | } |
| | | } |
| | | } |
| | | if (format.toLowerCase().indexOf('h') !== -1) { |
| | | counters.push('hours'); |
| | | if (format.indexOf('m') !== -1) { |
| | | counters.push('minutes'); |
| | | 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'; |
| | | } |
| | | } |
| | | var hours = date.format('H'); |
| | | |
| | | return { |
| | | hours: hours, |
| | | minutes: date.format( 'mm' ), |
| | | seconds: date.format( 'ss' ), |
| | | milliseconds: date.format( 'SSS' ), |
| | | daypart: daypart, |
| | | counters: counters |
| | | }; |
| | | }, |
| | | 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'; |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | return { |
| | | hours: hours, |
| | | minutes: date.format('mm'), |
| | | seconds: date.format('ss'), |
| | | milliseconds: date.format('SSS'), |
| | | daypart: daypart, |
| | | counters: counters |
| | | }; |
| | | }, |
| | | |
| | | 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 ''; |
| | | }, |
| | | 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; |
| | | |
| | | 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 }, '▼' ) |
| | | ]); |
| | | }, |
| | | 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 ''; |
| | | }, |
| | | |
| | | render: function() { |
| | | var me = this, |
| | | counters = [] |
| | | ; |
| | | 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 |
| | | }, |
| | | '▼' |
| | | ) |
| | | ] |
| | | ); |
| | | }, |
| | | |
| | | 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 ) ); |
| | | }); |
| | | render: function() { |
| | | var me = this, |
| | | counters = []; |
| | | |
| | | if ( this.state.daypart !== false ) { |
| | | counters.push( me.renderDayPart() ); |
| | | } |
| | | 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( React.createElement('div', { className: 'rdtCounterSeparator', key: 'sep5' }, ':' ) ); |
| | | counters.push( |
| | | React.createElement('div', { className: 'rdtCounter rdtMilli', key: 'm' }, |
| | | React.createElement('input', { value: this.state.milliseconds, type: 'text', onChange: this.updateMilli } ) |
| | | ) |
| | | ); |
| | | } |
| | | if (this.state.daypart !== false) { |
| | | counters.push(me.renderDayPart()); |
| | | } |
| | | |
| | | return React.createElement('div', { className: 'rdtTime' }, |
| | | React.createElement('table', {}, [ |
| | | this.renderHeader(), |
| | | React.createElement('tbody', { key: 'b'}, React.createElement('tr', {}, React.createElement('td', {}, |
| | | React.createElement('div', { className: 'rdtCounters' }, counters ) |
| | | ))) |
| | | ]) |
| | | ); |
| | | }, |
| | | if ( |
| | | this.state.counters.length === 3 && |
| | | this.props.timeFormat.indexOf('S') !== -1 |
| | | ) { |
| | | counters.push( |
| | | React.createElement( |
| | | 'div', |
| | | { className: 'rdtCounterSeparator', key: 'sep5' }, |
| | | ':' |
| | | ) |
| | | ); |
| | | counters.push( |
| | | React.createElement( |
| | | 'div', |
| | | { className: 'rdtCounter rdtMilli', key: 'm' }, |
| | | React.createElement('input', { |
| | | value: this.state.milliseconds, |
| | | type: 'text', |
| | | onChange: this.updateMilli |
| | | }) |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | 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 ) ); |
| | | }, |
| | | return React.createElement( |
| | | 'div', |
| | | { className: 'rdtTime' }, |
| | | React.createElement('table', {}, [ |
| | | this.renderHeader(), |
| | | React.createElement( |
| | | 'tbody', |
| | | { key: 'b' }, |
| | | React.createElement( |
| | | 'tr', |
| | | {}, |
| | | React.createElement( |
| | | 'td', |
| | | {}, |
| | | React.createElement( |
| | | 'div', |
| | | { className: 'rdtCounters' }, |
| | | counters |
| | | ) |
| | | ) |
| | | ) |
| | | ) |
| | | ]) |
| | | ); |
| | | }, |
| | | |
| | | componentWillReceiveProps: function( nextProps ) { |
| | | this.setState( this.calculateState( nextProps ) ); |
| | | }, |
| | | 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)); |
| | | }, |
| | | |
| | | 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 } ); |
| | | } |
| | | }, |
| | | componentWillReceiveProps: function(nextProps) { |
| | | this.setState(this.calculateState(nextProps)); |
| | | }, |
| | | |
| | | renderHeader: function() { |
| | | if ( !this.props.dateFormat ) |
| | | return null; |
| | | 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 }); |
| | | } |
| | | }, |
| | | |
| | | 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 ) ) |
| | | )); |
| | | }, |
| | | renderHeader: function() { |
| | | if (!this.props.dateFormat) return null; |
| | | |
| | | onStartClicking: function( action, type ) { |
| | | var me = this; |
| | | 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) |
| | | ) |
| | | ) |
| | | ); |
| | | }, |
| | | |
| | | return function() { |
| | | var update = {}; |
| | | update[ type ] = me[ action ]( type ); |
| | | me.setState( update ); |
| | | onStartClicking: function(action, type) { |
| | | var me = this; |
| | | |
| | | me.timer = setTimeout( function() { |
| | | me.increaseTimer = setInterval( function() { |
| | | update[ type ] = me[ action ]( type ); |
| | | me.setState( update ); |
| | | }, 70); |
| | | }, 500); |
| | | return function() { |
| | | var update = {}; |
| | | update[type] = me[action](type); |
| | | me.setState(update); |
| | | |
| | | me.mouseUpListener = function() { |
| | | clearTimeout( me.timer ); |
| | | clearInterval( me.increaseTimer ); |
| | | me.props.setTime( type, me.state[ type ] ); |
| | | document.body.removeEventListener( 'mouseup', me.mouseUpListener ); |
| | | }; |
| | | me.timer = setTimeout(function() { |
| | | me.increaseTimer = setInterval(function() { |
| | | update[type] = me[action](type); |
| | | me.setState(update); |
| | | }, 70); |
| | | }, 500); |
| | | |
| | | document.body.addEventListener( 'mouseup', me.mouseUpListener ); |
| | | }; |
| | | }, |
| | | me.mouseUpListener = function() { |
| | | clearTimeout(me.timer); |
| | | clearInterval(me.increaseTimer); |
| | | me.props.setTime(type, me.state[type]); |
| | | document.body.removeEventListener('mouseup', me.mouseUpListener); |
| | | }; |
| | | |
| | | disableContextMenu: function( event ) { |
| | | event.preventDefault(); |
| | | return false; |
| | | }, |
| | | document.body.addEventListener('mouseup', me.mouseUpListener); |
| | | }; |
| | | }, |
| | | |
| | | padValues: { |
| | | hours: 1, |
| | | minutes: 2, |
| | | seconds: 2, |
| | | milliseconds: 3 |
| | | }, |
| | | disableContextMenu: function(event) { |
| | | event.preventDefault(); |
| | | return false; |
| | | }, |
| | | |
| | | 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 ); |
| | | }, |
| | | padValues: { |
| | | hours: 1, |
| | | minutes: 2, |
| | | seconds: 2, |
| | | milliseconds: 3 |
| | | }, |
| | | |
| | | 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 ); |
| | | }, |
| | | 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 ], 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 ); |
| | | }, |
| | | 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 ) { |
| | | var str = value + ''; |
| | | while ( str.length < this.padValues[ type ] ) |
| | | str = '0' + str; |
| | | return str; |
| | | }, |
| | | 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); |
| | | }, |
| | | |
| | | handleClickOutside: function() { |
| | | this.props.handleClickOutside(); |
| | | } |
| | | })); |
| | | pad: function(type, value) { |
| | | var str = value + ''; |
| | | while (str.length < this.padValues[type]) str = '0' + str; |
| | | return str; |
| | | }, |
| | | |
| | | handleClickOutside: function() { |
| | | this.props.handleClickOutside(); |
| | | } |
| | | }) |
| | | ); |
| | | |
| | | module.exports = DateTimePickerTime; |