aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMG12 <wuzhao.mail@gmail.com>2015-12-16 12:19:56 +0800
committerMG12 <wuzhao.mail@gmail.com>2015-12-16 12:19:56 +0800
commit700c77e4f32e2ec18f3c63b176bf83bac24cdb74 (patch)
treedd7b0d090e946586dbc3bb5268a0a5b5619f81e4
parent182e9fccc90ae709322b7cc314c8775a9d8d46b8 (diff)
parentbec70d57f3ef17ed1ef29c660936be235804061e (diff)
downloadtime-picker-700c77e4f32e2ec18f3c63b176bf83bac24cdb74.tar.gz
time-picker-700c77e4f32e2ec18f3c63b176bf83bac24cdb74.tar.zst
time-picker-700c77e4f32e2ec18f3c63b176bf83bac24cdb74.zip
Merge pull request #10 from react-component/1.0.0-alpha7
1.0.0 alpha7
-rw-r--r--HISTORY.md14
-rw-r--r--README.md40
-rw-r--r--assets/index/Select.less10
-rw-r--r--examples/disabled.html1
-rw-r--r--examples/disabled.js66
-rw-r--r--examples/hidden.html1
-rw-r--r--examples/hidden.js37
-rw-r--r--examples/pick-time.js2
-rw-r--r--package.json2
-rw-r--r--src/TimePicker.jsx20
-rw-r--r--src/module/Combobox.jsx37
-rw-r--r--src/module/Header.jsx21
-rw-r--r--src/module/Panel.jsx33
-rw-r--r--src/module/Select.jsx10
-rw-r--r--tests/Header.spec.jsx125
-rw-r--r--tests/Select.spec.jsx153
16 files changed, 498 insertions, 74 deletions
diff --git a/HISTORY.md b/HISTORY.md
index ebc3b9e..48c386a 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,16 +2,22 @@
2 2
3--- 3---
4 4
51.0.0-alpha7 / 2015-12-12
6------------------
7
8`new` add options `disabledHours`, `disabledMinutes`, `disabledSeconds` and `hideDisabledOptions`.
9`remove` remove options `hourOptions`, `minuteOptions` and `secondOptions`.
10
51.0.0-alpha2 / 2015-12-03 111.0.0-alpha2 / 2015-12-03
6------------------ 12------------------
7 13
8`fix` IE8 compatible. 14`fixed` IE8 compatible.
9`new` add test users. 15`new` add test users.
10 16
110.7.1 / 2015-11-20 170.7.1 / 2015-11-20
12------------------ 18------------------
13 19
14`fix` change value to null when clear input content to remove the react warning. 20`fixed` change value to null when clear input content to remove the react warning.
15 21
160.7.0 / 2015-11-20 220.7.0 / 2015-11-20
17------------------ 23------------------
@@ -21,7 +27,7 @@
210.5.6 / 2015-11-19 270.5.6 / 2015-11-19
22------------------ 28------------------
23 29
24`fix` use another method to change time and fix the bug about value.getTime(). 30`fixed` use another method to change time and fix the bug about value.getTime().
25 31
260.5.4 / 2015-11-19 320.5.4 / 2015-11-19
27------------------ 33------------------
@@ -54,7 +60,7 @@
540.3.3 / 2015-11-17 600.3.3 / 2015-11-17
55------------------ 61------------------
56 62
57`fix` fix some bugs. 63`fixed` fix some bugs.
58 64
590.3.0 / 2015-11-17 650.3.0 / 2015-11-17
60------------------ 66------------------
diff --git a/README.md b/README.md
index 60e5ab0..ea0e034 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,6 @@ Usage
39 39
40``` 40```
41import TimePicker from 'rc-time-picker'; 41import TimePicker from 'rc-time-picker';
42import React from 'react';
43import ReactDOM from 'react-dom'; 42import ReactDOM from 'react-dom';
44ReactDOM.render(<TimePicker />, container); 43ReactDOM.render(<TimePicker />, container);
45``` 44```
@@ -49,25 +48,26 @@ API
49 48
50### TimePicker 49### TimePicker
51 50
52| Name | Type | Default | Description | 51| Name | Type | Default | Description |
53|----------------|----------------------------|-----------------------------------------------|--------------------------------------------------------------------------------------------| 52|-------------------------|-----------------------------------|-----------------------------------------------|--------------------------------------------------------------------------------------------|
54| prefixCls | String | | prefixCls of this component | 53| prefixCls | String | | prefixCls of this component |
55| locale | Object | import from 'rc-time-picker/lib/locale/en_US' | | 54| locale | Object | import from 'rc-time-picker/lib/locale/en_US' | |
56| disabled | Boolean | false | whether picker is disabled | 55| disabled | Boolean | false | whether picker is disabled |
57| open | Boolean | false | current open state of picker. controlled prop | 56| open | Boolean | false | current open state of picker. controlled prop |
58| defaultValue | GregorianCalendar | null | default initial value | 57| defaultValue | GregorianCalendar | null | default initial value |
59| value | GregorianCalendar | null | current value | 58| value | GregorianCalendar | null | current value |
60| gregorianCalendarLocale | GregorianCalendar locale object | null | if value and defaultValue not set, you should set this to your locale | 59| gregorianCalendarLocale | GregorianCalendar locale object | null | if value and defaultValue not set, you should set this to your locale |
61| placeholder | String | '' | time input's placeholder | 60| placeholder | String | '' | time input's placeholder |
62| showHour | Boolean | whether show hour | | 61| showHour | Boolean | whether show hour | |
63| showSecond | Boolean | whether show second | | 62| showSecond | Boolean | whether show second | |
64| formatter | String|GregorianCalendarFormatter | | | 63| formatter | String|GregorianCalendarFormatter | | |
65| hourOptions | Array<Number> | hour options | | 64| disabledHours | Function | disabled hour options | |
66| minuteOptions | Array<Number> | minute options | | 65| disabledMinutes | Function | disabled minute options | |
67| secondOptions | Array<Number> | second options | | 66| disabledSeconds | Function | disabled second options | |
68| onChange | Function | null | called when select a different value | 67| hideDisabledOptions | Boolean | whether hide disabled options | |
69| placement | String | bottomLeft | one of ['left','right','top','bottom', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'] | 68| onChange | Function | null | called when select a different value |
70| transitionName | String | '' | | 69| placement | String | bottomLeft | one of ['left','right','top','bottom', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'] |
70| transitionName | String | '' | |
71 71
72License 72License
73------- 73-------
diff --git a/assets/index/Select.less b/assets/index/Select.less
index 3e94c11..13b5b18 100644
--- a/assets/index/Select.less
+++ b/assets/index/Select.less
@@ -48,8 +48,16 @@
48 } 48 }
49 } 49 }
50 50
51 &-option-selected { 51 li&-option-selected {
52 background: #edfaff; 52 background: #edfaff;
53 color: #2db7f5; 53 color: #2db7f5;
54 } 54 }
55
56 li&-option-disabled {
57 color: #bfbfbf;
58 &:hover {
59 background: transparent;
60 cursor: not-allowed;
61 }
62 }
55} 63}
diff --git a/examples/disabled.html b/examples/disabled.html
new file mode 100644
index 0000000..48cdce8
--- /dev/null
+++ b/examples/disabled.html
@@ -0,0 +1 @@
placeholder
diff --git a/examples/disabled.js b/examples/disabled.js
new file mode 100644
index 0000000..633b8db
--- /dev/null
+++ b/examples/disabled.js
@@ -0,0 +1,66 @@
1/* eslint no-console:0 */
2
3import 'rc-time-picker/assets/index.less';
4
5import React from 'react';
6import ReactDom from 'react-dom';
7
8import GregorianCalendar from 'gregorian-calendar';
9import DateTimeFormat from 'gregorian-calendar-format';
10import zhCn from 'gregorian-calendar/lib/locale/zh_CN';
11
12import TimePicker from 'rc-time-picker';
13import TimePickerLocale from 'rc-time-picker/src/locale/zh_CN';
14
15const showSecond = true;
16const str = showSecond ? 'HH:mm:ss' : 'HH:mm';
17
18const formatter = new DateTimeFormat(str);
19
20const now = new GregorianCalendar(zhCn);
21now.setTime(Date.now());
22
23function generateOptions(length, excludedOptions) {
24 const arr = [];
25 for (let value = 0; value < length; value++) {
26 if (excludedOptions.indexOf(value) < 0) {
27 arr.push(value);
28 }
29 }
30 return arr;
31}
32
33function onChange(value) {
34 console.log(value && formatter.format(value));
35}
36
37function disabledHours() {
38 return [0, 1, 2, 3, 4, 5, 6, 7, 8, 22, 23];
39}
40
41function disabledMinutes(h) {
42 switch (h) {
43 case 9:
44 return generateOptions(60, [30]);
45 case 21:
46 return generateOptions(60, [0]);
47 default:
48 return generateOptions(60, [0, 30]);
49 }
50}
51
52function disabledSeconds(h, m) {
53 return [h + m % 60];
54}
55
56ReactDom.render(
57 <TimePicker formatter={formatter} locale={TimePickerLocale}
58 showSecond={showSecond}
59 defaultValue={now}
60 className="xxx"
61 onChange={onChange}
62 disabledHours={disabledHours}
63 disabledMinutes={disabledMinutes}
64 disabledSeconds={disabledSeconds} />,
65 document.getElementById('__react-content')
66);
diff --git a/examples/hidden.html b/examples/hidden.html
new file mode 100644
index 0000000..48cdce8
--- /dev/null
+++ b/examples/hidden.html
@@ -0,0 +1 @@
placeholder
diff --git a/examples/hidden.js b/examples/hidden.js
new file mode 100644
index 0000000..da366cc
--- /dev/null
+++ b/examples/hidden.js
@@ -0,0 +1,37 @@
1/* eslint no-console:0 */
2
3import 'rc-time-picker/assets/index.less';
4
5import React from 'react';
6import ReactDom from 'react-dom';
7
8import GregorianCalendar from 'gregorian-calendar';
9import DateTimeFormat from 'gregorian-calendar-format';
10import zhCn from 'gregorian-calendar/lib/locale/zh_CN';
11
12import TimePicker from 'rc-time-picker';
13import TimePickerLocale from 'rc-time-picker/src/locale/zh_CN';
14
15const showSecond = true;
16const str = showSecond ? 'HH:mm:ss' : 'HH:mm';
17
18const formatter = new DateTimeFormat(str);
19
20const now = new GregorianCalendar(zhCn);
21now.setTime(Date.now());
22
23function onChange(value) {
24 console.log(value && formatter.format(value));
25}
26
27ReactDom.render(
28 <TimePicker formatter={formatter} locale={TimePickerLocale}
29 showSecond={showSecond}
30 defaultValue={now}
31 className="xxx"
32 onChange={onChange}
33 disabledHours={() => [0, 1, 2, 3, 4, 5, 6, 7, 8, 22, 23]}
34 disabledMinutes={() => [0, 2, 4, 6, 8]}
35 hideDisabledOptions />,
36 document.getElementById('__react-content')
37);
diff --git a/examples/pick-time.js b/examples/pick-time.js
index dd5a2ce..f66e416 100644
--- a/examples/pick-time.js
+++ b/examples/pick-time.js
@@ -29,6 +29,6 @@ ReactDom.render(
29 showSecond={showSecond} 29 showSecond={showSecond}
30 defaultValue={now} 30 defaultValue={now}
31 className="xxx" 31 className="xxx"
32 onChange={onChange}/>, 32 onChange={onChange} />,
33 document.getElementById('__react-content') 33 document.getElementById('__react-content')
34); 34);
diff --git a/package.json b/package.json
index fa91d86..8bc0ae2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "rc-time-picker", 2 "name": "rc-time-picker",
3 "version": "1.0.0-alpha6", 3 "version": "1.0.0-alpha7",
4 "description": "React TimePicker", 4 "description": "React TimePicker",
5 "keywords": [ 5 "keywords": [
6 "react", 6 "react",
diff --git a/src/TimePicker.jsx b/src/TimePicker.jsx
index 3e331f1..ad4e834 100644
--- a/src/TimePicker.jsx
+++ b/src/TimePicker.jsx
@@ -34,9 +34,10 @@ const Picker = React.createClass({
34 style: PropTypes.object, 34 style: PropTypes.object,
35 className: PropTypes.string, 35 className: PropTypes.string,
36 showSecond: PropTypes.bool, 36 showSecond: PropTypes.bool,
37 hourOptions: PropTypes.array, 37 disabledHours: PropTypes.func,
38 minuteOptions: PropTypes.array, 38 disabledMinutes: PropTypes.func,
39 secondOptions: PropTypes.array, 39 disabledSeconds: PropTypes.func,
40 hideDisabledOptions: PropTypes.bool,
40 onChange: PropTypes.func, 41 onChange: PropTypes.func,
41 onOpen: PropTypes.func, 42 onOpen: PropTypes.func,
42 onClose: PropTypes.func, 43 onClose: PropTypes.func,
@@ -54,6 +55,10 @@ const Picker = React.createClass({
54 allowEmpty: true, 55 allowEmpty: true,
55 showHour: true, 56 showHour: true,
56 showSecond: true, 57 showSecond: true,
58 disabledHours: noop,
59 disabledMinutes: noop,
60 disabledSeconds: noop,
61 hideDisabledOptions: false,
57 placement: 'bottomLeft', 62 placement: 'bottomLeft',
58 onChange: noop, 63 onChange: noop,
59 onOpen: noop, 64 onOpen: noop,
@@ -145,7 +150,7 @@ const Picker = React.createClass({
145 }, 150 },
146 151
147 getPanelElement() { 152 getPanelElement() {
148 const { prefixCls, defaultValue, locale, placeholder, hourOptions, minuteOptions, secondOptions, allowEmpty, showHour, showSecond, gregorianCalendarLocale, value } = this.props; 153 const { prefixCls, defaultValue, locale, placeholder, disabledHours, disabledMinutes, disabledSeconds, hideDisabledOptions, allowEmpty, showHour, showSecond, gregorianCalendarLocale, value } = this.props;
149 let calendarLocale; 154 let calendarLocale;
150 if (value) { 155 if (value) {
151 calendarLocale = value.locale; 156 calendarLocale = value.locale;
@@ -170,9 +175,10 @@ const Picker = React.createClass({
170 allowEmpty={allowEmpty} 175 allowEmpty={allowEmpty}
171 formatter={this.getFormatter()} 176 formatter={this.getFormatter()}
172 placeholder={placeholder} 177 placeholder={placeholder}
173 hourOptions={hourOptions} 178 disabledHours={disabledHours}
174 minuteOptions={minuteOptions} 179 disabledMinutes={disabledMinutes}
175 secondOptions={secondOptions} 180 disabledSeconds={disabledSeconds}
181 hideDisabledOptions={hideDisabledOptions}
176 /> 182 />
177 ); 183 );
178 }, 184 },
diff --git a/src/module/Combobox.jsx b/src/module/Combobox.jsx
index a017ec9..7374b39 100644
--- a/src/module/Combobox.jsx
+++ b/src/module/Combobox.jsx
@@ -2,11 +2,21 @@ import React, {PropTypes} from 'react';
2import Select from './Select'; 2import Select from './Select';
3import GregorianCalendar from 'gregorian-calendar'; 3import GregorianCalendar from 'gregorian-calendar';
4 4
5const formatOption = (option) => { 5const formatOption = (option, disabledOptions) => {
6 let value = `${option}`;
6 if (option < 10) { 7 if (option < 10) {
7 return `0${option}`; 8 value = `0${option}`;
8 } 9 }
9 return `${option}`; 10
11 let disabled = false;
12 if (disabledOptions && disabledOptions.indexOf(option) >= 0) {
13 disabled = true;
14 }
15
16 return {
17 value,
18 disabled,
19 };
10}; 20};
11 21
12const Combobox = React.createClass({ 22const Combobox = React.createClass({
@@ -21,6 +31,9 @@ const Combobox = React.createClass({
21 hourOptions: PropTypes.array, 31 hourOptions: PropTypes.array,
22 minuteOptions: PropTypes.array, 32 minuteOptions: PropTypes.array,
23 secondOptions: PropTypes.array, 33 secondOptions: PropTypes.array,
34 disabledHours: PropTypes.func,
35 disabledMinutes: PropTypes.func,
36 disabledSeconds: PropTypes.func,
24 onCurrentSelectPanelChange: PropTypes.func, 37 onCurrentSelectPanelChange: PropTypes.func,
25 }, 38 },
26 39
@@ -47,14 +60,16 @@ const Combobox = React.createClass({
47 }, 60 },
48 61
49 getHourSelect(hour) { 62 getHourSelect(hour) {
50 const { prefixCls, hourOptions, showHour } = this.props; 63 const { prefixCls, hourOptions, disabledHours, showHour } = this.props;
51 if (!showHour) { 64 if (!showHour) {
52 return null; 65 return null;
53 } 66 }
67 const disabledOptions = disabledHours();
68
54 return ( 69 return (
55 <Select 70 <Select
56 prefixCls={prefixCls} 71 prefixCls={prefixCls}
57 options={hourOptions.map(option => formatOption(option))} 72 options={hourOptions.map(option => formatOption(option, disabledOptions))}
58 selectedIndex={hourOptions.indexOf(hour)} 73 selectedIndex={hourOptions.indexOf(hour)}
59 type="hour" 74 type="hour"
60 onSelect={this.onItemChange} 75 onSelect={this.onItemChange}
@@ -64,11 +79,13 @@ const Combobox = React.createClass({
64 }, 79 },
65 80
66 getMinuteSelect(minute) { 81 getMinuteSelect(minute) {
67 const { prefixCls, minuteOptions } = this.props; 82 const { prefixCls, minuteOptions, disabledMinutes, value } = this.props;
83 const disabledOptions = disabledMinutes(value.getHourOfDay());
84
68 return ( 85 return (
69 <Select 86 <Select
70 prefixCls={prefixCls} 87 prefixCls={prefixCls}
71 options={minuteOptions.map(option => formatOption(option))} 88 options={minuteOptions.map(option => formatOption(option, disabledOptions))}
72 selectedIndex={minuteOptions.indexOf(minute)} 89 selectedIndex={minuteOptions.indexOf(minute)}
73 type="minute" 90 type="minute"
74 onSelect={this.onItemChange} 91 onSelect={this.onItemChange}
@@ -78,14 +95,16 @@ const Combobox = React.createClass({
78 }, 95 },
79 96
80 getSecondSelect(second) { 97 getSecondSelect(second) {
81 const { prefixCls, secondOptions, showSecond } = this.props; 98 const { prefixCls, secondOptions, disabledSeconds, showSecond, value } = this.props;
82 if (!showSecond) { 99 if (!showSecond) {
83 return null; 100 return null;
84 } 101 }
102 const disabledOptions = disabledSeconds(value.getHourOfDay(), value.getMinutes());
103
85 return ( 104 return (
86 <Select 105 <Select
87 prefixCls={prefixCls} 106 prefixCls={prefixCls}
88 options={secondOptions.map(option => formatOption(option))} 107 options={secondOptions.map(option => formatOption(option, disabledOptions))}
89 selectedIndex={secondOptions.indexOf(second)} 108 selectedIndex={secondOptions.indexOf(second)}
90 type="second" 109 type="second"
91 onSelect={this.onItemChange} 110 onSelect={this.onItemChange}
diff --git a/src/module/Header.jsx b/src/module/Header.jsx
index ef88948..9a048dc 100644
--- a/src/module/Header.jsx
+++ b/src/module/Header.jsx
@@ -13,6 +13,9 @@ const Header = React.createClass({
13 hourOptions: PropTypes.array, 13 hourOptions: PropTypes.array,
14 minuteOptions: PropTypes.array, 14 minuteOptions: PropTypes.array,
15 secondOptions: PropTypes.array, 15 secondOptions: PropTypes.array,
16 disabledHours: PropTypes.func,
17 disabledMinutes: PropTypes.func,
18 disabledSeconds: PropTypes.func,
16 onChange: PropTypes.func, 19 onChange: PropTypes.func,
17 onClear: PropTypes.func, 20 onClear: PropTypes.func,
18 onEsc: PropTypes.func, 21 onEsc: PropTypes.func,
@@ -54,7 +57,7 @@ const Header = React.createClass({
54 str, 57 str,
55 }); 58 });
56 let value = null; 59 let value = null;
57 const {formatter, gregorianCalendarLocale, hourOptions, minuteOptions, secondOptions, onChange, allowEmpty} = this.props; 60 const {formatter, gregorianCalendarLocale, hourOptions, minuteOptions, secondOptions, disabledHours, disabledMinutes, disabledSeconds, onChange, allowEmpty} = this.props;
58 61
59 if (str) { 62 if (str) {
60 const originalValue = this.props.value; 63 const originalValue = this.props.value;
@@ -71,6 +74,7 @@ const Header = React.createClass({
71 } 74 }
72 75
73 if (value) { 76 if (value) {
77 // if time value not allowed, response warning.
74 if ( 78 if (
75 hourOptions.indexOf(value.getHourOfDay()) < 0 || 79 hourOptions.indexOf(value.getHourOfDay()) < 0 ||
76 minuteOptions.indexOf(value.getMinutes()) < 0 || 80 minuteOptions.indexOf(value.getMinutes()) < 0 ||
@@ -82,6 +86,21 @@ const Header = React.createClass({
82 return; 86 return;
83 } 87 }
84 88
89 // if time value is disabled, response warning.
90 const disabledHourOptions = disabledHours();
91 const disabledMinuteOptions = disabledMinutes(value.getHourOfDay());
92 const disabledSecondOptions = disabledSeconds(value.getHourOfDay(), value.getMinutes());
93 if (
94 (disabledHourOptions && disabledHourOptions.indexOf(value.getHourOfDay()) >= 0) ||
95 (disabledMinuteOptions && disabledMinuteOptions.indexOf(value.getMinutes()) >= 0) ||
96 (disabledSecondOptions && disabledSecondOptions.indexOf(value.getSeconds()) >= 0)
97 ) {
98 this.setState({
99 invalid: true,
100 });
101 return;
102 }
103
85 if (originalValue && value) { 104 if (originalValue && value) {
86 if ( 105 if (
87 originalValue.getHourOfDay() !== value.getHourOfDay() || 106 originalValue.getHourOfDay() !== value.getHourOfDay() ||
diff --git a/src/module/Panel.jsx b/src/module/Panel.jsx
index 63823ee..94d3842 100644
--- a/src/module/Panel.jsx
+++ b/src/module/Panel.jsx
@@ -6,10 +6,12 @@ import Combobox from './Combobox';
6function noop() { 6function noop() {
7} 7}
8 8
9function generateOptions(length) { 9function generateOptions(length, disabledOptions, hideDisabledOptions) {
10 const arr = []; 10 const arr = [];
11 for (let i = 0; i < length; i++) { 11 for (let value = 0; value < length; value++) {
12 arr.push(i); 12 if (!disabledOptions || disabledOptions.indexOf(value) < 0 || !hideDisabledOptions) {
13 arr.push(value);
14 }
13 } 15 }
14 return arr; 16 return arr;
15} 17}
@@ -22,9 +24,10 @@ const Panel = React.createClass({
22 placeholder: PropTypes.string, 24 placeholder: PropTypes.string,
23 gregorianCalendarLocale: PropTypes.object, 25 gregorianCalendarLocale: PropTypes.object,
24 formatter: PropTypes.object, 26 formatter: PropTypes.object,
25 hourOptions: PropTypes.array, 27 disabledHours: PropTypes.func,
26 minuteOptions: PropTypes.array, 28 disabledMinutes: PropTypes.func,
27 secondOptions: PropTypes.array, 29 disabledSeconds: PropTypes.func,
30 hideDisabledOptions: PropTypes.bool,
28 onChange: PropTypes.func, 31 onChange: PropTypes.func,
29 onEsc: PropTypes.func, 32 onEsc: PropTypes.func,
30 allowEmpty: PropTypes.bool, 33 allowEmpty: PropTypes.bool,
@@ -37,9 +40,6 @@ const Panel = React.createClass({
37 40
38 getDefaultProps() { 41 getDefaultProps() {
39 return { 42 return {
40 hourOptions: generateOptions(24),
41 minuteOptions: generateOptions(60),
42 secondOptions: generateOptions(60),
43 onChange: noop, 43 onChange: noop,
44 onClear: noop, 44 onClear: noop,
45 }; 45 };
@@ -75,8 +75,15 @@ const Panel = React.createClass({
75 }, 75 },
76 76
77 render() { 77 render() {
78 const { locale, prefixCls, placeholder, hourOptions, minuteOptions, secondOptions, allowEmpty, showHour, showSecond, formatter, gregorianCalendarLocale } = this.props; 78 const { locale, prefixCls, placeholder, disabledHours, disabledMinutes, disabledSeconds, hideDisabledOptions, allowEmpty, showHour, showSecond, formatter, gregorianCalendarLocale } = this.props;
79 const value = this.state.value; 79 const value = this.state.value;
80 const disabledHourOptions = disabledHours();
81 const disabledMinuteOptions = disabledMinutes(value.getHourOfDay());
82 const disabledSecondOptions = disabledSeconds(value.getHourOfDay(), value.getMinutes());
83 const hourOptions = generateOptions(24, disabledHourOptions, hideDisabledOptions);
84 const minuteOptions = generateOptions(60, disabledMinuteOptions, hideDisabledOptions);
85 const secondOptions = generateOptions(60, disabledSecondOptions, hideDisabledOptions);
86
80 return ( 87 return (
81 <div className={`${prefixCls}-inner`}> 88 <div className={`${prefixCls}-inner`}>
82 <Header 89 <Header
@@ -91,6 +98,9 @@ const Panel = React.createClass({
91 hourOptions={hourOptions} 98 hourOptions={hourOptions}
92 minuteOptions={minuteOptions} 99 minuteOptions={minuteOptions}
93 secondOptions={secondOptions} 100 secondOptions={secondOptions}
101 disabledHours={disabledHours}
102 disabledMinutes={disabledMinutes}
103 disabledSeconds={disabledSeconds}
94 onChange={this.onChange} 104 onChange={this.onChange}
95 onClear={this.onClear} 105 onClear={this.onClear}
96 allowEmpty={allowEmpty} 106 allowEmpty={allowEmpty}
@@ -106,6 +116,9 @@ const Panel = React.createClass({
106 hourOptions={hourOptions} 116 hourOptions={hourOptions}
107 minuteOptions={minuteOptions} 117 minuteOptions={minuteOptions}
108 secondOptions={secondOptions} 118 secondOptions={secondOptions}
119 disabledHours={disabledHours}
120 disabledMinutes={disabledMinutes}
121 disabledSeconds={disabledSeconds}
109 onCurrentSelectPanelChange={this.onCurrentSelectPanelChange} 122 onCurrentSelectPanelChange={this.onCurrentSelectPanelChange}
110 /> 123 />
111 </div> 124 </div>
diff --git a/src/module/Select.jsx b/src/module/Select.jsx
index 3659692..ab10789 100644
--- a/src/module/Select.jsx
+++ b/src/module/Select.jsx
@@ -51,11 +51,15 @@ const Select = React.createClass({
51 getOptions() { 51 getOptions() {
52 const { options, selectedIndex, prefixCls } = this.props; 52 const { options, selectedIndex, prefixCls } = this.props;
53 return options.map((item, index) => { 53 return options.map((item, index) => {
54 const selected = selectedIndex === index;
55 const cls = classnames({ 54 const cls = classnames({
56 [`${prefixCls}-select-option-selected`]: selected, 55 [`${prefixCls}-select-option-selected`]: selectedIndex === index,
56 [`${prefixCls}-select-option-disabled`]: item.disabled,
57 }); 57 });
58 return <li className={cls} key={index} onClick={this.onSelect.bind(this, +item)}>{item}</li>; 58 let onclick = null;
59 if (!item.disabled) {
60 onclick = this.onSelect.bind(this, +item.value);
61 }
62 return <li className={cls} key={index} onClick={onclick} disabled={item.disabled}>{item.value}</li>;
59 }); 63 });
60 }, 64 },
61 65
diff --git a/tests/Header.spec.jsx b/tests/Header.spec.jsx
index cc8f954..e992279 100644
--- a/tests/Header.spec.jsx
+++ b/tests/Header.spec.jsx
@@ -121,6 +121,131 @@ describe('Header', () => {
121 }); 121 });
122 }); 122 });
123 123
124 it('carry disabled correctly', (done) => {
125 const picker = renderPicker({
126 disabledMinutes(h) {
127 return [h];
128 },
129 disabledSeconds(h, m) {
130 return [h + m % 60];
131 },
132 });
133 expect(picker.state.open).not.to.be.ok();
134 const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, 'rc-time-picker-input')[0];
135 let header;
136 async.series([(next) => {
137 Simulate.click(input);
138 setTimeout(next, 100);
139 }, (next) => {
140 expect(picker.state.open).to.be(true);
141 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
142 expect(header).to.be.ok();
143 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:03');
144 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03');
145
146 ReactDOM.findDOMNode(header).value = '10:09:78';
147 Simulate.change(header);
148 setTimeout(next, 100);
149 }, (next) => {
150 expect(picker.state.open).to.be(true);
151 expect(ReactDOM.findDOMNode(header).className).to.contain('rc-time-picker-panel-input-invalid');
152 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:78');
153 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03');
154
155 ReactDOM.findDOMNode(header).value = '10:10:78';
156 Simulate.change(header);
157 setTimeout(next, 100);
158 }, (next) => {
159 expect(picker.state.open).to.be(true);
160 expect(ReactDOM.findDOMNode(header).value).to.be('10:11:18');
161 expect(ReactDOM.findDOMNode(input).value).to.be('10:11:18');
162
163 ReactDOM.findDOMNode(header).value = '10:09:19';
164 Simulate.change(header);
165 setTimeout(next, 100);
166 }, (next) => {
167 expect(picker.state.open).to.be(true);
168 expect(ReactDOM.findDOMNode(header).className).to.contain('rc-time-picker-panel-input-invalid');
169 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:19');
170 expect(ReactDOM.findDOMNode(input).value).to.be('10:11:18');
171
172 ReactDOM.findDOMNode(header).value = '10:09:20';
173 Simulate.change(header);
174 setTimeout(next, 100);
175 }, (next) => {
176 expect(picker.state.open).to.be(true);
177 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:20');
178 expect(ReactDOM.findDOMNode(input).value).to.be('10:09:20');
179
180 next();
181 }], () => {
182 done();
183 });
184 });
185
186 it('carry hidden correctly', (done) => {
187 const picker = renderPicker({
188 disabledMinutes(h) {
189 return [h];
190 },
191 disabledSeconds(h, m) {
192 return [h + m % 60];
193 },
194 hideDisabledOptions: true,
195 });
196 expect(picker.state.open).not.to.be.ok();
197 const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, 'rc-time-picker-input')[0];
198 let header;
199 async.series([(next) => {
200 Simulate.click(input);
201 setTimeout(next, 100);
202 }, (next) => {
203 expect(picker.state.open).to.be(true);
204 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
205 expect(header).to.be.ok();
206 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:03');
207 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03');
208
209 ReactDOM.findDOMNode(header).value = '10:09:78';
210 Simulate.change(header);
211 setTimeout(next, 100);
212 }, (next) => {
213 expect(picker.state.open).to.be(true);
214 expect(ReactDOM.findDOMNode(header).className).to.contain('rc-time-picker-panel-input-invalid');
215 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:78');
216 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03');
217
218 ReactDOM.findDOMNode(header).value = '10:10:78';
219 Simulate.change(header);
220 setTimeout(next, 100);
221 }, (next) => {
222 expect(picker.state.open).to.be(true);
223 expect(ReactDOM.findDOMNode(header).value).to.be('10:11:18');
224 expect(ReactDOM.findDOMNode(input).value).to.be('10:11:18');
225
226 ReactDOM.findDOMNode(header).value = '10:09:19';
227 Simulate.change(header);
228 setTimeout(next, 100);
229 }, (next) => {
230 expect(picker.state.open).to.be(true);
231 expect(ReactDOM.findDOMNode(header).className).to.contain('rc-time-picker-panel-input-invalid');
232 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:19');
233 expect(ReactDOM.findDOMNode(input).value).to.be('10:11:18');
234
235 ReactDOM.findDOMNode(header).value = '10:09:20';
236 Simulate.change(header);
237 setTimeout(next, 100);
238 }, (next) => {
239 expect(picker.state.open).to.be(true);
240 expect(ReactDOM.findDOMNode(header).value).to.be('10:09:20');
241 expect(ReactDOM.findDOMNode(input).value).to.be('10:09:20');
242
243 next();
244 }], () => {
245 done();
246 });
247 });
248
124 it('check correctly', (done) => { 249 it('check correctly', (done) => {
125 const picker = renderPicker(); 250 const picker = renderPicker();
126 expect(picker.state.open).not.to.be.ok(); 251 expect(picker.state.open).not.to.be.ok();
diff --git a/tests/Select.spec.jsx b/tests/Select.spec.jsx
index 7e53c31..f7717c7 100644
--- a/tests/Select.spec.jsx
+++ b/tests/Select.spec.jsx
@@ -29,7 +29,7 @@ describe('Select', () => {
29 formatter={formatter} 29 formatter={formatter}
30 locale={TimePickerLocale} 30 locale={TimePickerLocale}
31 showSecond={showSecond} 31 showSecond={showSecond}
32 defaultValue={formatTime('01:02:03', formatter)} 32 defaultValue={formatTime('01:02:04', formatter)}
33 {...props} 33 {...props}
34 />, container); 34 />, container);
35 } 35 }
@@ -89,19 +89,19 @@ describe('Select', () => {
89 }, (next) => { 89 }, (next) => {
90 expect(picker.state.open).to.be(true); 90 expect(picker.state.open).to.be(true);
91 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0]; 91 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
92 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[0];
93 const option = selector.getElementsByTagName('li')[19];
94 expect(header).to.be.ok(); 92 expect(header).to.be.ok();
95 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:03'); 93 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
96 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03'); 94 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
97 95
96 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[0];
97 const option = selector.getElementsByTagName('li')[19];
98 Simulate.click(option); 98 Simulate.click(option);
99 setTimeout(next, 100); 99 setTimeout(next, 100);
100 }, (next) => { 100 }, (next) => {
101 expect(change).to.be.ok(); 101 expect(change).to.be.ok();
102 expect(change.getHourOfDay()).to.be(19); 102 expect(change.getHourOfDay()).to.be(19);
103 expect(ReactDOM.findDOMNode(header).value).to.be('19:02:03'); 103 expect(ReactDOM.findDOMNode(header).value).to.be('19:02:04');
104 expect(ReactDOM.findDOMNode(input).value).to.be('19:02:03'); 104 expect(ReactDOM.findDOMNode(input).value).to.be('19:02:04');
105 expect(picker.state.open).to.be.ok(); 105 expect(picker.state.open).to.be.ok();
106 106
107 next(); 107 next();
@@ -128,19 +128,19 @@ describe('Select', () => {
128 }, (next) => { 128 }, (next) => {
129 expect(picker.state.open).to.be(true); 129 expect(picker.state.open).to.be(true);
130 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0]; 130 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
131 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[1];
132 const option = selector.getElementsByTagName('li')[19];
133 expect(header).to.be.ok(); 131 expect(header).to.be.ok();
134 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:03'); 132 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
135 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03'); 133 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
136 134
135 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[1];
136 const option = selector.getElementsByTagName('li')[19];
137 Simulate.click(option); 137 Simulate.click(option);
138 setTimeout(next, 100); 138 setTimeout(next, 100);
139 }, (next) => { 139 }, (next) => {
140 expect(change).to.be.ok(); 140 expect(change).to.be.ok();
141 expect(change.getMinutes()).to.be(19); 141 expect(change.getMinutes()).to.be(19);
142 expect(ReactDOM.findDOMNode(header).value).to.be('01:19:03'); 142 expect(ReactDOM.findDOMNode(header).value).to.be('01:19:04');
143 expect(ReactDOM.findDOMNode(input).value).to.be('01:19:03'); 143 expect(ReactDOM.findDOMNode(input).value).to.be('01:19:04');
144 expect(picker.state.open).to.be.ok(); 144 expect(picker.state.open).to.be.ok();
145 145
146 next(); 146 next();
@@ -167,12 +167,12 @@ describe('Select', () => {
167 }, (next) => { 167 }, (next) => {
168 expect(picker.state.open).to.be(true); 168 expect(picker.state.open).to.be(true);
169 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0]; 169 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
170 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[2];
171 const option = selector.getElementsByTagName('li')[19];
172 expect(header).to.be.ok(); 170 expect(header).to.be.ok();
173 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:03'); 171 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
174 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:03'); 172 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
175 173
174 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[2];
175 const option = selector.getElementsByTagName('li')[19];
176 Simulate.click(option); 176 Simulate.click(option);
177 setTimeout(next, 100); 177 setTimeout(next, 100);
178 }, (next) => { 178 }, (next) => {
@@ -187,5 +187,124 @@ describe('Select', () => {
187 done(); 187 done();
188 }); 188 });
189 }); 189 });
190
191 it('disabled correctly', (done) => {
192 let change;
193 const picker = renderPicker({
194 onChange(v) {
195 change = v;
196 },
197 disabledMinutes(h) {
198 return [h];
199 },
200 disabledSeconds(h, m) {
201 return [h + m % 60];
202 },
203 });
204 expect(picker.state.open).not.to.be.ok();
205 const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, 'rc-time-picker-input')[0];
206 let header;
207 async.series([(next) => {
208 expect(picker.state.open).to.be(false);
209
210 Simulate.click(input);
211 setTimeout(next, 100);
212 }, (next) => {
213 expect(picker.state.open).to.be(true);
214 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
215 expect(header).to.be.ok();
216 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
217 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
218
219 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[1];
220 const option = selector.getElementsByTagName('li')[1];
221 Simulate.click(option);
222 setTimeout(next, 100);
223 }, (next) => {
224 expect(change).not.to.be.ok();
225 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
226 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
227 expect(picker.state.open).to.be.ok();
228
229 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[2];
230 const option = selector.getElementsByTagName('li')[3];
231 Simulate.click(option);
232 setTimeout(next, 100);
233 }, (next) => {
234 expect(change).not.to.be.ok();
235 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
236 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
237 expect(picker.state.open).to.be.ok();
238
239 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[1];
240 const option = selector.getElementsByTagName('li')[7];
241 Simulate.click(option);
242 setTimeout(next, 100);
243 }, (next) => {
244 expect(change).to.be.ok();
245 expect(change.getMinutes()).to.be(7);
246 expect(ReactDOM.findDOMNode(header).value).to.be('01:07:04');
247 expect(ReactDOM.findDOMNode(input).value).to.be('01:07:04');
248 expect(picker.state.open).to.be.ok();
249
250 next();
251 }], () => {
252 done();
253 });
254 });
255
256 it('hidden correctly', (done) => {
257 let change;
258 const picker = renderPicker({
259 onChange(v) {
260 change = v;
261 },
262 disabledHours() {
263 return [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23];
264 },
265 hideDisabledOptions: true,
266 });
267 expect(picker.state.open).not.to.be.ok();
268 const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, 'rc-time-picker-input')[0];
269 let header;
270 async.series([(next) => {
271 expect(picker.state.open).to.be(false);
272
273 Simulate.click(input);
274 setTimeout(next, 100);
275 }, (next) => {
276 expect(picker.state.open).to.be(true);
277 header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-input')[0];
278 expect(header).to.be.ok();
279 expect(ReactDOM.findDOMNode(header).value).to.be('01:02:04');
280 expect(ReactDOM.findDOMNode(input).value).to.be('01:02:04');
281
282 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[0];
283 const option = selector.getElementsByTagName('li')[3];
284 Simulate.click(option);
285 setTimeout(next, 100);
286 }, (next) => {
287 expect(change).to.be.ok();
288 expect(change.getHourOfDay()).to.be(6);
289 expect(ReactDOM.findDOMNode(header).value).to.be('06:02:04');
290 expect(ReactDOM.findDOMNode(input).value).to.be('06:02:04');
291 expect(picker.state.open).to.be.ok();
292
293 const selector = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, 'rc-time-picker-panel-select')[0];
294 const option = selector.getElementsByTagName('li')[4];
295 Simulate.click(option);
296 setTimeout(next, 100);
297 }, (next) => {
298 expect(change).to.be.ok();
299 expect(change.getHourOfDay()).to.be(8);
300 expect(ReactDOM.findDOMNode(header).value).to.be('08:02:04');
301 expect(ReactDOM.findDOMNode(input).value).to.be('08:02:04');
302 expect(picker.state.open).to.be.ok();
303
304 next();
305 }], () => {
306 done();
307 });
308 });
190 }); 309 });
191}); 310});