]> git.immae.eu Git - github/fretlink/time-picker.git/blame - src/Combobox.jsx
Fixed unwanted exception on missed value
[github/fretlink/time-picker.git] / src / Combobox.jsx
CommitLineData
4984ed85 1import React, { PropTypes } from 'react';
02de449a 2import Select from './Select';
3
518b852e
M
4const formatOption = (option, disabledOptions) => {
5 let value = `${option}`;
02de449a 6 if (option < 10) {
518b852e 7 value = `0${option}`;
02de449a 8 }
518b852e
M
9
10 let disabled = false;
0e62bf0b 11 if (disabledOptions && disabledOptions.indexOf(option) >= 0) {
518b852e
M
12 disabled = true;
13 }
14
15 return {
16 value,
17 disabled,
18 };
02de449a 19};
20
21const Combobox = React.createClass({
22 propTypes: {
4984ed85 23 format: PropTypes.string,
24 defaultOpenValue: PropTypes.object,
02de449a 25 prefixCls: PropTypes.string,
26 value: PropTypes.object,
27 onChange: PropTypes.func,
28 showHour: PropTypes.bool,
37c36c09 29 showMinute: PropTypes.bool,
02de449a 30 showSecond: PropTypes.bool,
31 hourOptions: PropTypes.array,
32 minuteOptions: PropTypes.array,
33 secondOptions: PropTypes.array,
71bd9bc1
M
34 disabledHours: PropTypes.func,
35 disabledMinutes: PropTypes.func,
36 disabledSeconds: PropTypes.func,
182e9fcc 37 onCurrentSelectPanelChange: PropTypes.func,
dd275f7d 38 use12Hours: PropTypes.bool,
02de449a 39 },
40
41 onItemChange(type, itemValue) {
dd275f7d 42 const { onChange, defaultOpenValue, use12Hours } = this.props;
4984ed85 43 const value = (this.props.value || defaultOpenValue).clone();
95699887 44
11b97949 45 if (type === 'hour') {
dd275f7d 46 if (use12Hours) {
dd2f6abd
AS
47 if (this.isAM()) {
48 value.hour(+itemValue % 12);
95699887 49 } else {
dd2f6abd 50 value.hour((+itemValue % 12) + 12);
95699887
AS
51 }
52 } else {
53 value.hour(+itemValue);
54 }
11b97949 55 } else if (type === 'minute') {
95699887
AS
56 value.minute(+itemValue);
57 } else if (type === 'ampm') {
c1b40cab 58 const ampm = itemValue.toUpperCase();
dd275f7d 59 if (use12Hours) {
c1b40cab 60 if (ampm === 'PM' && value.hour() < 12) {
2a8cf5ae 61 value.hour((value.hour() % 12) + 12);
95699887
AS
62 }
63
c1b40cab 64 if (ampm === 'AM') {
2a8cf5ae 65 if (value.hour() >= 12) {
95699887
AS
66 value.hour(value.hour() - 12);
67 }
68 }
69 }
11b97949 70 } else {
95699887 71 value.second(+itemValue);
02de449a 72 }
02de449a 73 onChange(value);
74 },
75
182e9fcc 76 onEnterSelectPanel(range) {
77 this.props.onCurrentSelectPanelChange(range);
78 },
79
02de449a 80 getHourSelect(hour) {
dd275f7d 81 const { prefixCls, hourOptions, disabledHours, showHour, use12Hours } = this.props;
02de449a 82 if (!showHour) {
83 return null;
84 }
71bd9bc1 85 const disabledOptions = disabledHours();
95699887 86 let hourOptionsAdj;
dd2f6abd 87 let hourAdj;
dd275f7d 88 if (use12Hours) {
dd2f6abd
AS
89 hourOptionsAdj = [12].concat(hourOptions.filter(h => h < 12 && h > 0));
90 hourAdj = (hour % 12) || 12;
95699887
AS
91 } else {
92 hourOptionsAdj = hourOptions;
dd2f6abd 93 hourAdj = hour;
95699887 94 }
71bd9bc1 95
02de449a 96 return (
97 <Select
98 prefixCls={prefixCls}
95699887
AS
99 options={hourOptionsAdj.map(option => formatOption(option, disabledOptions))}
100 selectedIndex={hourOptionsAdj.indexOf(hourAdj)}
02de449a 101 type="hour"
102 onSelect={this.onItemChange}
182e9fcc 103 onMouseEnter={this.onEnterSelectPanel.bind(this, 'hour')}
02de449a 104 />
105 );
106 },
107
108 getMinuteSelect(minute) {
37c36c09 109 const { prefixCls, minuteOptions, disabledMinutes, defaultOpenValue, showMinute } = this.props;
110 if (!showMinute) {
111 return null;
112 }
4984ed85 113 const value = this.props.value || defaultOpenValue;
114 const disabledOptions = disabledMinutes(value.hour());
71bd9bc1 115
02de449a 116 return (
117 <Select
118 prefixCls={prefixCls}
71bd9bc1 119 options={minuteOptions.map(option => formatOption(option, disabledOptions))}
02de449a 120 selectedIndex={minuteOptions.indexOf(minute)}
121 type="minute"
122 onSelect={this.onItemChange}
182e9fcc 123 onMouseEnter={this.onEnterSelectPanel.bind(this, 'minute')}
02de449a 124 />
125 );
126 },
127
182e9fcc 128 getSecondSelect(second) {
4984ed85 129 const { prefixCls, secondOptions, disabledSeconds, showSecond, defaultOpenValue } = this.props;
02de449a 130 if (!showSecond) {
131 return null;
132 }
4984ed85 133 const value = this.props.value || defaultOpenValue;
134 const disabledOptions = disabledSeconds(value.hour(), value.minute());
71bd9bc1 135
02de449a 136 return (
137 <Select
138 prefixCls={prefixCls}
71bd9bc1 139 options={secondOptions.map(option => formatOption(option, disabledOptions))}
02de449a 140 selectedIndex={secondOptions.indexOf(second)}
141 type="second"
142 onSelect={this.onItemChange}
182e9fcc 143 onMouseEnter={this.onEnterSelectPanel.bind(this, 'second')}
02de449a 144 />
145 );
146 },
147
95699887 148 getAMPMSelect() {
eb3c19e2 149 const { prefixCls, use12Hours, format } = this.props;
dd275f7d 150 if (!use12Hours) {
95699887
AS
151 return null;
152 }
eb3c19e2
AS
153
154 const AMPMOptions = ['am', 'pm'] // If format has A char, then we should uppercase AM/PM
155 .map(c => format.match(/\sA/) ? c.toUpperCase() : c)
156 .map(c => ({ value: c }));
157
dd2f6abd 158 const selected = this.isAM() ? 0 : 1;
95699887
AS
159
160 return (
161 <Select
162 prefixCls={prefixCls}
163 options={AMPMOptions}
164 selectedIndex={selected}
165 type="ampm"
166 onSelect={this.onItemChange}
167 onMouseEnter={this.onEnterSelectPanel.bind(this, 'ampm')}
168 />
169 );
170 },
171
dd2f6abd 172 isAM() {
4f26f23b 173 const value = (this.props.value || this.props.defaultOpenValue);
dd2f6abd
AS
174 return value.hour() >= 0 && value.hour() < 12;
175 },
176
8133e8cf 177 render() {
4984ed85 178 const { prefixCls, defaultOpenValue } = this.props;
179 const value = this.props.value || defaultOpenValue;
02de449a 180 return (
181 <div className={`${prefixCls}-combobox`}>
4984ed85 182 {this.getHourSelect(value.hour())}
183 {this.getMinuteSelect(value.minute())}
184 {this.getSecondSelect(value.second())}
95699887 185 {this.getAMPMSelect(value.hour())}
02de449a 186 </div>
187 );
188 },
189});
190
191export default Combobox;