diff options
Diffstat (limited to 'src/TimePicker.jsx')
-rw-r--r-- | src/TimePicker.jsx | 134 |
1 files changed, 96 insertions, 38 deletions
diff --git a/src/TimePicker.jsx b/src/TimePicker.jsx index e82b46f..2694cb0 100644 --- a/src/TimePicker.jsx +++ b/src/TimePicker.jsx | |||
@@ -1,10 +1,10 @@ | |||
1 | import React, {PropTypes} from 'react'; | 1 | import React, {PropTypes} from 'react'; |
2 | import ReactDOM from 'react-dom'; | ||
3 | import Trigger from 'rc-trigger'; | 2 | import Trigger from 'rc-trigger'; |
4 | import {createChainedFunction} from 'rc-util'; | ||
5 | import Panel from './module/Panel'; | 3 | import Panel from './module/Panel'; |
6 | import placements from './util/placements'; | 4 | import placements from './util/placements'; |
7 | import CommonMixin from './mixin/CommonMixin'; | 5 | import CommonMixin from './mixin/CommonMixin'; |
6 | import {getFormatter} from './util/index'; | ||
7 | import defaultGregorianCalendarLocale from 'gregorian-calendar/lib/locale/en_US'; | ||
8 | 8 | ||
9 | function noop() { | 9 | function noop() { |
10 | } | 10 | } |
@@ -16,18 +16,23 @@ function refFn(field, component) { | |||
16 | const Picker = React.createClass({ | 16 | const Picker = React.createClass({ |
17 | propTypes: { | 17 | propTypes: { |
18 | prefixCls: PropTypes.string, | 18 | prefixCls: PropTypes.string, |
19 | inputClassName: PropTypes.string, | ||
20 | locale: PropTypes.object, | 19 | locale: PropTypes.object, |
21 | value: PropTypes.object, | 20 | value: PropTypes.object, |
22 | children: PropTypes.func, | ||
23 | disabled: PropTypes.bool, | 21 | disabled: PropTypes.bool, |
22 | allowEmpty: PropTypes.bool, | ||
24 | defaultValue: PropTypes.object, | 23 | defaultValue: PropTypes.object, |
25 | open: PropTypes.bool, | 24 | open: PropTypes.bool, |
25 | defaultOpen: PropTypes.bool, | ||
26 | align: PropTypes.object, | 26 | align: PropTypes.object, |
27 | placement: PropTypes.any, | 27 | placement: PropTypes.any, |
28 | transitionName: PropTypes.string, | 28 | transitionName: PropTypes.string, |
29 | getPopupContainer: PropTypes.func, | ||
30 | gregorianCalendarLocale: PropTypes.object, | ||
29 | placeholder: PropTypes.string, | 31 | placeholder: PropTypes.string, |
30 | formatter: PropTypes.object, | 32 | formatter: PropTypes.any, |
33 | showHour: PropTypes.bool, | ||
34 | style: PropTypes.object, | ||
35 | showSecond: PropTypes.bool, | ||
31 | hourOptions: PropTypes.array, | 36 | hourOptions: PropTypes.array, |
32 | minuteOptions: PropTypes.array, | 37 | minuteOptions: PropTypes.array, |
33 | secondOptions: PropTypes.array, | 38 | secondOptions: PropTypes.array, |
@@ -40,8 +45,13 @@ const Picker = React.createClass({ | |||
40 | 45 | ||
41 | getDefaultProps() { | 46 | getDefaultProps() { |
42 | return { | 47 | return { |
43 | open: false, | 48 | defaultOpen: false, |
49 | style: {}, | ||
50 | gregorianCalendarLocale: defaultGregorianCalendarLocale, | ||
44 | align: {}, | 51 | align: {}, |
52 | allowEmpty: true, | ||
53 | showHour: true, | ||
54 | showSecond: true, | ||
45 | placement: 'bottomLeft', | 55 | placement: 'bottomLeft', |
46 | onChange: noop, | 56 | onChange: noop, |
47 | onOpen: noop, | 57 | onOpen: noop, |
@@ -51,10 +61,10 @@ const Picker = React.createClass({ | |||
51 | 61 | ||
52 | getInitialState() { | 62 | getInitialState() { |
53 | this.savePanelRef = refFn.bind(this, 'panelInstance'); | 63 | this.savePanelRef = refFn.bind(this, 'panelInstance'); |
54 | const { open, defaultValue, value } = this.props; | 64 | const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this.props; |
55 | return { | 65 | return { |
56 | open: open, | 66 | open, |
57 | value: value || defaultValue, | 67 | value, |
58 | }; | 68 | }; |
59 | }, | 69 | }, |
60 | 70 | ||
@@ -80,12 +90,18 @@ const Picker = React.createClass({ | |||
80 | }, | 90 | }, |
81 | 91 | ||
82 | onVisibleChange(open) { | 92 | onVisibleChange(open) { |
83 | this.setOpen(open, () => { | 93 | this.setOpen(open); |
84 | if (open) { | 94 | }, |
85 | ReactDOM.findDOMNode(this.refs.picker).blur(); | 95 | |
86 | ReactDOM.findDOMNode(this.panelInstance).focus(); | 96 | onEsc() { |
87 | } | 97 | this.setOpen(false); |
88 | }); | 98 | this.refs.picker.focus(); |
99 | }, | ||
100 | |||
101 | onKeyDown(e) { | ||
102 | if (e.keyCode === 40) { | ||
103 | this.setOpen(true); | ||
104 | } | ||
89 | }, | 105 | }, |
90 | 106 | ||
91 | setValue(value) { | 107 | setValue(value) { |
@@ -97,14 +113,60 @@ const Picker = React.createClass({ | |||
97 | this.props.onChange(value); | 113 | this.props.onChange(value); |
98 | }, | 114 | }, |
99 | 115 | ||
100 | getPanel() { | 116 | getFormatter() { |
101 | const { prefixCls, defaultValue, locale, formatter, placeholder, hourOptions, minuteOptions, secondOptions } = this.props; | 117 | const formatter = this.props.formatter; |
118 | const locale = this.props.locale; | ||
119 | if (formatter) { | ||
120 | if (formatter === this.lastFormatter) { | ||
121 | return this.normalFormatter; | ||
122 | } | ||
123 | this.normalFormatter = getFormatter(formatter, locale); | ||
124 | this.lastFormatter = formatter; | ||
125 | return this.normalFormatter; | ||
126 | } | ||
127 | if (!this.props.showSecond) { | ||
128 | if (!this.notShowSecondFormatter) { | ||
129 | this.notShowSecondFormatter = getFormatter('HH:mm', locale); | ||
130 | } | ||
131 | return this.notShowSecondFormatter; | ||
132 | } | ||
133 | if (!this.props.showHour) { | ||
134 | if (!this.notShowHourFormatter) { | ||
135 | this.notShowHourFormatter = getFormatter('mm:ss', locale); | ||
136 | } | ||
137 | return this.notShowHourFormatter; | ||
138 | } | ||
139 | if (!this.normalFormatter) { | ||
140 | this.normalFormatter = getFormatter('HH:mm:ss', locale); | ||
141 | } | ||
142 | return this.normalFormatter; | ||
143 | }, | ||
144 | |||
145 | getPanelElement() { | ||
146 | const { prefixCls, defaultValue, locale, placeholder, hourOptions, minuteOptions, secondOptions, allowEmpty, showHour, showSecond, gregorianCalendarLocale, value } = this.props; | ||
147 | let calendarLocale; | ||
148 | if (value) { | ||
149 | calendarLocale = value.locale; | ||
150 | } else if (defaultValue) { | ||
151 | calendarLocale = defaultValue.locale; | ||
152 | } else { | ||
153 | calendarLocale = gregorianCalendarLocale; | ||
154 | } | ||
102 | return ( | 155 | return ( |
103 | <Panel | 156 | <Panel |
104 | prefixCls={prefixCls} | 157 | prefixCls={`${prefixCls}-panel`} |
158 | ref={this.savePanelRef} | ||
159 | value={this.state.value} | ||
160 | onChange={this.onPanelChange} | ||
161 | gregorianCalendarLocale={calendarLocale} | ||
162 | onClear={this.onPanelClear} | ||
105 | defaultValue={defaultValue} | 163 | defaultValue={defaultValue} |
164 | showHour={showHour} | ||
165 | onEsc={this.onEsc} | ||
166 | showSecond={showSecond} | ||
106 | locale={locale} | 167 | locale={locale} |
107 | formatter={formatter} | 168 | allowEmpty={allowEmpty} |
169 | formatter={this.getFormatter()} | ||
108 | placeholder={placeholder} | 170 | placeholder={placeholder} |
109 | hourOptions={hourOptions} | 171 | hourOptions={hourOptions} |
110 | minuteOptions={minuteOptions} | 172 | minuteOptions={minuteOptions} |
@@ -113,26 +175,14 @@ const Picker = React.createClass({ | |||
113 | ); | 175 | ); |
114 | }, | 176 | }, |
115 | 177 | ||
116 | getPanelElement() { | ||
117 | const panel = this.getPanel(); | ||
118 | const extraProps = { | ||
119 | ref: this.savePanelRef, | ||
120 | value: this.state.value, | ||
121 | onChange: createChainedFunction(panel.props.onChange, this.onPanelChange), | ||
122 | onClear: createChainedFunction(panel.props.onClear, this.onPanelClear), | ||
123 | }; | ||
124 | |||
125 | return React.cloneElement(panel, extraProps); | ||
126 | }, | ||
127 | |||
128 | setOpen(open, callback) { | 178 | setOpen(open, callback) { |
129 | const {onOpen, onClose} = this.props; | 179 | const {onOpen, onClose} = this.props; |
130 | if (this.state.open !== open) { | 180 | if (this.state.open !== open) { |
131 | this.setState({ | 181 | this.setState({ |
132 | open: open, | 182 | open, |
133 | }, callback); | 183 | }, callback); |
134 | const event = { | 184 | const event = { |
135 | open: open, | 185 | open, |
136 | }; | 186 | }; |
137 | if (open) { | 187 | if (open) { |
138 | onOpen(event); | 188 | onOpen(event); |
@@ -143,25 +193,33 @@ const Picker = React.createClass({ | |||
143 | }, | 193 | }, |
144 | 194 | ||
145 | render() { | 195 | render() { |
146 | const { prefixCls, placeholder, placement, align, disabled, transitionName, formatter, inputClassName } = this.props; | 196 | const { prefixCls, placeholder, placement, align, disabled, transitionName, style, showHour, showSecond, getPopupContainer } = this.props; |
147 | const { open, value } = this.state; | 197 | const { open, value } = this.state; |
148 | 198 | let popupClassName; | |
199 | if (!showHour || !showSecond) { | ||
200 | popupClassName = `${prefixCls}-panel-narrow}`; | ||
201 | } | ||
149 | return ( | 202 | return ( |
150 | <Trigger | 203 | <Trigger |
151 | prefixCls={`${prefixCls}-panel`} | 204 | prefixCls={`${prefixCls}-panel`} |
205 | popupClassName={popupClassName} | ||
152 | popup={this.getPanelElement()} | 206 | popup={this.getPanelElement()} |
153 | popupAlign={align} | 207 | popupAlign={align} |
154 | builtinPlacements={placements} | 208 | builtinPlacements={placements} |
155 | popupPlacement={placement} | 209 | popupPlacement={placement} |
156 | action={disabled ? [] : ['click']} | 210 | action={disabled ? [] : ['click']} |
157 | destroyPopupOnHide | 211 | destroyPopupOnHide |
212 | getPopupContainer={getPopupContainer} | ||
158 | popupTransitionName={transitionName} | 213 | popupTransitionName={transitionName} |
159 | popupVisible={open} | 214 | popupVisible={open} |
160 | onPopupVisibleChange={this.onVisibleChange} | 215 | onPopupVisibleChange={this.onVisibleChange} |
161 | > | 216 | > |
162 | <span className={`${prefixCls}`}> | 217 | <span className={`${prefixCls}`} style={style}> |
163 | <input className={inputClassName} ref="picker" type="text" placeholder={placeholder} readOnly | 218 | <input className={`${prefixCls}-input`} |
164 | disabled={disabled} value={value && formatter.format(value)}/> | 219 | ref="picker" type="text" placeholder={placeholder} |
220 | readOnly | ||
221 | onKeyDown={this.onKeyDown} | ||
222 | disabled={disabled} value={value && this.getFormatter().format(value)}/> | ||
165 | <span className={`${prefixCls}-icon`}/> | 223 | <span className={`${prefixCls}-icon`}/> |
166 | </span> | 224 | </span> |
167 | </Trigger> | 225 | </Trigger> |