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