]>
Commit | Line | Data |
---|---|---|
1 | import React, {PropTypes} from 'react'; | |
2 | import Trigger from 'rc-trigger'; | |
3 | import Panel from './module/Panel'; | |
4 | import placements from './util/placements'; | |
5 | import CommonMixin from './mixin/CommonMixin'; | |
6 | import {getFormatter} from './util/index'; | |
7 | import defaultGregorianCalendarLocale from 'gregorian-calendar/lib/locale/en_US'; | |
8 | ||
9 | function noop() { | |
10 | } | |
11 | ||
12 | function refFn(field, component) { | |
13 | this[field] = component; | |
14 | } | |
15 | ||
16 | const Picker = React.createClass({ | |
17 | propTypes: { | |
18 | prefixCls: PropTypes.string, | |
19 | locale: PropTypes.object, | |
20 | value: PropTypes.object, | |
21 | disabled: PropTypes.bool, | |
22 | allowEmpty: PropTypes.bool, | |
23 | defaultValue: PropTypes.object, | |
24 | open: PropTypes.bool, | |
25 | defaultOpen: PropTypes.bool, | |
26 | align: PropTypes.object, | |
27 | placement: PropTypes.any, | |
28 | transitionName: PropTypes.string, | |
29 | getPopupContainer: PropTypes.func, | |
30 | gregorianCalendarLocale: PropTypes.object, | |
31 | placeholder: PropTypes.string, | |
32 | formatter: PropTypes.any, | |
33 | showHour: PropTypes.bool, | |
34 | style: PropTypes.object, | |
35 | showSecond: PropTypes.bool, | |
36 | hourOptions: PropTypes.array, | |
37 | minuteOptions: PropTypes.array, | |
38 | secondOptions: PropTypes.array, | |
39 | onChange: PropTypes.func, | |
40 | onOpen: PropTypes.func, | |
41 | onClose: PropTypes.func, | |
42 | }, | |
43 | ||
44 | mixins: [CommonMixin], | |
45 | ||
46 | getDefaultProps() { | |
47 | return { | |
48 | defaultOpen: false, | |
49 | style: {}, | |
50 | gregorianCalendarLocale: defaultGregorianCalendarLocale, | |
51 | align: {}, | |
52 | allowEmpty: true, | |
53 | showHour: true, | |
54 | showSecond: true, | |
55 | placement: 'bottomLeft', | |
56 | onChange: noop, | |
57 | onOpen: noop, | |
58 | onClose: noop, | |
59 | }; | |
60 | }, | |
61 | ||
62 | getInitialState() { | |
63 | this.savePanelRef = refFn.bind(this, 'panelInstance'); | |
64 | const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this.props; | |
65 | return { | |
66 | open, | |
67 | value, | |
68 | }; | |
69 | }, | |
70 | ||
71 | componentWillReceiveProps(nextProps) { | |
72 | const { value, open } = nextProps; | |
73 | if (value !== undefined) { | |
74 | this.setState({ | |
75 | value, | |
76 | }); | |
77 | } | |
78 | if (open !== undefined) { | |
79 | this.setState({open}); | |
80 | } | |
81 | }, | |
82 | ||
83 | onPanelChange(value) { | |
84 | this.setValue(value); | |
85 | }, | |
86 | ||
87 | onPanelClear() { | |
88 | this.setValue(null); | |
89 | this.setOpen(false); | |
90 | }, | |
91 | ||
92 | onVisibleChange(open) { | |
93 | this.setOpen(open); | |
94 | }, | |
95 | ||
96 | onEsc() { | |
97 | this.setOpen(false); | |
98 | this.refs.picker.focus(); | |
99 | }, | |
100 | ||
101 | onKeyDown(e) { | |
102 | if (e.keyCode === 40) { | |
103 | this.setOpen(true); | |
104 | } | |
105 | }, | |
106 | ||
107 | setValue(value) { | |
108 | if (!('value' in this.props)) { | |
109 | this.setState({ | |
110 | value, | |
111 | }); | |
112 | } | |
113 | this.props.onChange(value); | |
114 | }, | |
115 | ||
116 | getFormatter() { | |
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 | } | |
155 | return ( | |
156 | <Panel | |
157 | prefixCls={`${prefixCls}-panel`} | |
158 | ref={this.savePanelRef} | |
159 | value={this.state.value} | |
160 | onChange={this.onPanelChange} | |
161 | gregorianCalendarLocale={calendarLocale} | |
162 | onClear={this.onPanelClear} | |
163 | defaultValue={defaultValue} | |
164 | showHour={showHour} | |
165 | onEsc={this.onEsc} | |
166 | showSecond={showSecond} | |
167 | locale={locale} | |
168 | allowEmpty={allowEmpty} | |
169 | formatter={this.getFormatter()} | |
170 | placeholder={placeholder} | |
171 | hourOptions={hourOptions} | |
172 | minuteOptions={minuteOptions} | |
173 | secondOptions={secondOptions} | |
174 | /> | |
175 | ); | |
176 | }, | |
177 | ||
178 | setOpen(open, callback) { | |
179 | const {onOpen, onClose} = this.props; | |
180 | if (this.state.open !== open) { | |
181 | this.setState({ | |
182 | open, | |
183 | }, callback); | |
184 | const event = { | |
185 | open, | |
186 | }; | |
187 | if (open) { | |
188 | onOpen(event); | |
189 | } else { | |
190 | onClose(event); | |
191 | } | |
192 | } | |
193 | }, | |
194 | ||
195 | render() { | |
196 | const { prefixCls, placeholder, placement, align, disabled, transitionName, style, showHour, showSecond, getPopupContainer } = this.props; | |
197 | const { open, value } = this.state; | |
198 | let popupClassName; | |
199 | if (!showHour || !showSecond) { | |
200 | popupClassName = `${prefixCls}-panel-narrow}`; | |
201 | } | |
202 | return ( | |
203 | <Trigger | |
204 | prefixCls={`${prefixCls}-panel`} | |
205 | popupClassName={popupClassName} | |
206 | popup={this.getPanelElement()} | |
207 | popupAlign={align} | |
208 | builtinPlacements={placements} | |
209 | popupPlacement={placement} | |
210 | action={disabled ? [] : ['click']} | |
211 | destroyPopupOnHide | |
212 | getPopupContainer={getPopupContainer} | |
213 | popupTransitionName={transitionName} | |
214 | popupVisible={open} | |
215 | onPopupVisibleChange={this.onVisibleChange} | |
216 | > | |
217 | <span className={`${prefixCls}`} style={style}> | |
218 | <input className={`${prefixCls}-input`} | |
219 | ref="picker" type="text" placeholder={placeholder} | |
220 | readOnly | |
221 | onKeyDown={this.onKeyDown} | |
222 | disabled={disabled} value={value && this.getFormatter().format(value)}/> | |
223 | <span className={`${prefixCls}-icon`}/> | |
224 | </span> | |
225 | </Trigger> | |
226 | ); | |
227 | }, | |
228 | }); | |
229 | ||
230 | export default Picker; |