-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathMenuOptions.js
More file actions
108 lines (91 loc) · 2.64 KB
/
MenuOptions.js
File metadata and controls
108 lines (91 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/** @jsx React.DOM */
var React = require('react');
var cloneWithProps = React.addons.cloneWithProps;
var MenuOption = require('./MenuOption');
var buildClassName = require('../mixins/buildClassName');
var MenuOptions = module.exports = React.createClass({
contextTypes: {
id: React.PropTypes.string,
active: React.PropTypes.bool
},
getInitialState: function() {
return {activeIndex: 0}
},
mixins: [buildClassName],
onSelectionMade: function() {
this.props.onSelectionMade();
},
moveSelectionUp: function() {
this.updateFocusIndexBy(-1);
},
moveSelectionDown: function() {
this.updateFocusIndexBy(1);
},
handleKeys: function(e) {
var options = {
'ArrowDown': this.moveSelectionDown,
'ArrowUp': this.moveSelectionUp,
'Escape': this.closeMenu
}
if(options[e.key]){
options[e.key].call(this);
}
},
normalizeSelectedBy: function(delta, numOptions){
this.selectedIndex += delta;
if (this.selectedIndex > numOptions - 1) {
this.selectedIndex = 0;
} else if (this.selectedIndex < 0) {
this.selectedIndex = numOptions - 1;
}
},
focusOption: function(index) {
this.selectedIndex = index;
this.updateFocusIndexBy(0);
},
updateFocusIndexBy: function(delta) {
var optionNodes = this.getDOMNode().querySelectorAll('.Menu__MenuOption');
this.normalizeSelectedBy(delta, optionNodes.length);
this.setState({activeIndex: this.selectedIndex}, function () {
optionNodes[this.selectedIndex].focus();
});
},
renderOptions: function() {
var index = 0;
return React.Children.map(this.props.children, function(c){
var clonedOption = c;
if (c.type === MenuOption.type) {
var active = this.state.activeIndex === index;
clonedOption = cloneWithProps(c, {
active: active,
index: index,
_internalFocus: this.focusOption,
_internalSelect: this.onSelectionMade
});
index++;
}
return clonedOption;
}.bind(this));
},
buildName: function() {
var cn = this.buildClassName('Menu__MenuOptions');
cn += ' Menu__MenuOptions--horizontal-' + this.props.horizontalPlacement;
cn += ' Menu__MenuOptions--vertical-' + this.props.verticalPlacement;
return cn;
},
render: function() {
return (
<div
id={this.context.id}
role="menu"
tabIndex="-1"
aria-expanded={this.context.active}
style={{visibility: this.context.active ? 'visible' : 'hidden'}}
className={this.buildName()}
onKeyDown={this.handleKeys}
>
{this.renderOptions()}
</div>
)
}
});