diff options
Diffstat (limited to 'src/module/Select.jsx')
-rw-r--r-- | src/module/Select.jsx | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/module/Select.jsx b/src/module/Select.jsx new file mode 100644 index 0000000..2b69623 --- /dev/null +++ b/src/module/Select.jsx | |||
@@ -0,0 +1,88 @@ | |||
1 | import React, {PropTypes} from 'react'; | ||
2 | import ReactDom from 'react-dom'; | ||
3 | import classnames from 'classnames'; | ||
4 | |||
5 | const scrollTo = (element, to, duration) => { | ||
6 | // jump to target if duration zero | ||
7 | if (duration <= 0) { | ||
8 | element.scrollTop = to; | ||
9 | return; | ||
10 | } | ||
11 | const difference = to - element.scrollTop; | ||
12 | const perTick = difference / duration * 10; | ||
13 | |||
14 | setTimeout(() => { | ||
15 | element.scrollTop = element.scrollTop + perTick; | ||
16 | if (element.scrollTop === to) return; | ||
17 | scrollTo(element, to, duration - 10); | ||
18 | }, 10); | ||
19 | }; | ||
20 | |||
21 | const Select = React.createClass({ | ||
22 | propTypes: { | ||
23 | prefixCls: PropTypes.string, | ||
24 | options: PropTypes.array, | ||
25 | selectedIndex: PropTypes.number, | ||
26 | type: PropTypes.string, | ||
27 | onSelect: PropTypes.func, | ||
28 | }, | ||
29 | |||
30 | componentDidMount() { | ||
31 | // jump to selected option | ||
32 | this.scrollToSelected(0); | ||
33 | }, | ||
34 | |||
35 | componentDidUpdate() { | ||
36 | // smooth scroll to selected option | ||
37 | this.scrollToSelected(200); | ||
38 | }, | ||
39 | |||
40 | onSelect(event) { | ||
41 | // do nothing when select selected option | ||
42 | if (event.target.getAttribute('class') === 'selected') { | ||
43 | return; | ||
44 | } | ||
45 | // change combobox selection | ||
46 | const { onSelect, type } = this.props; | ||
47 | const value = parseInt(event.target.innerHTML, 10); | ||
48 | onSelect(type, value); | ||
49 | }, | ||
50 | |||
51 | getOptions() { | ||
52 | const { options, selectedIndex } = this.props; | ||
53 | return options.map((item, index) => { | ||
54 | const cls = classnames({ selected: selectedIndex === index}); | ||
55 | const ref = selectedIndex === index ? 'selected' : null; | ||
56 | return <li ref={ref} className={cls} key={index} onClick={this.onSelect}>{item}</li>; | ||
57 | }); | ||
58 | }, | ||
59 | |||
60 | scrollToSelected(duration) { | ||
61 | // move to selected item | ||
62 | const select = ReactDom.findDOMNode(this); | ||
63 | const list = ReactDom.findDOMNode(this.refs.list); | ||
64 | let index = this.props.selectedIndex - 2; | ||
65 | if (index < 0) { | ||
66 | index = 0; | ||
67 | } | ||
68 | const topOption = list.children[index]; | ||
69 | const to = topOption.offsetTop - select.offsetTop; | ||
70 | scrollTo(select, to, duration); | ||
71 | }, | ||
72 | |||
73 | render() { | ||
74 | if (this.props.options.length === 0) { | ||
75 | return null; | ||
76 | } | ||
77 | |||
78 | const { prefixCls } = this.props; | ||
79 | |||
80 | return ( | ||
81 | <div className={`${prefixCls}-select`}> | ||
82 | <ul ref="list">{this.getOptions()}</ul> | ||
83 | </div> | ||
84 | ); | ||
85 | }, | ||
86 | }); | ||
87 | |||
88 | export default Select; | ||