-
Notifications
You must be signed in to change notification settings - Fork 498
/
RefinementList.js
112 lines (99 loc) · 3.2 KB
/
RefinementList.js
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
109
110
111
112
var React = require('react');
var Template = require('./Template');
var autoHide = require('../decorators/autoHide');
var cx = require('classnames');
class RefinementList extends React.Component {
refine(value) {
this.props.toggleRefinement(value);
}
// Click events on DOM tree like LABEL > INPUT will result in two click events
// instead of one. No matter the framework: see
// a label, you will get two click events instead of one.
// No matter the framework, see https://www.google.com/search?q=click+label+twice
//
// Thus making it hard to distinguish activation from deactivation because both click events
// are very close. Debounce is a solution but hacky.
//
// So the code here checks if the click was done on or in a LABEL. If this LABEL
// has a checkbox inside, we ignore the first click event because we will get another one.
handleClick(value, e) {
if (e.target.tagName === 'A' && e.target.href) {
e.preventDefault();
}
if (e.target.tagName === 'INPUT') {
this.refine(value);
return;
}
var parent = e.target;
while (parent !== e.currentTarget) {
if (parent.tagName === 'LABEL' && parent.querySelector('input[type="checkbox"]')) {
return;
}
parent = parent.parentNode;
}
this.refine(value);
}
render() {
var facetValues = this.props.facetValues;
var templates = this.props.templates;
var rootClass = cx(this.props.cssClasses.root);
var listClass = cx(this.props.cssClasses.list);
var itemClass = cx(this.props.cssClasses.item);
return (
<div className={rootClass}>
<Template template={templates.header} />
<div className={listClass}>
{facetValues.map(facetValue => {
return (
<div className={itemClass} key={facetValue.name} onClick={this.handleClick.bind(this, facetValue.name)}>
<Template data={(this.props.transformData) ? this.props.transformData(facetValue) : facetValue} template={templates.item} />
</div>
);
})}
</div>
<Template template={templates.footer} />
</div>
);
}
}
RefinementList.propTypes = {
cssClasses: React.PropTypes.shape({
root: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.arrayOf(React.PropTypes.string)
]),
item: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.arrayOf(React.PropTypes.string)
]),
list: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.arrayOf(React.PropTypes.string)
])
}),
facetValues: React.PropTypes.array,
templates: React.PropTypes.shape({
header: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.func
]),
item: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.func
]).isRequired,
footer: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.func
])
}),
transformData: React.PropTypes.func,
toggleRefinement: React.PropTypes.func.isRequired
};
RefinementList.defaultProps = {
cssClasses: {
root: null,
item: null,
list: null
}
};
module.exports = autoHide(RefinementList);