Skip to content

Commit 5974a88

Browse files
author
vvo
committed
feat(searchBox): add headerFooter decorator to the Component
Added to searchBox: - templates.header - templates.footer - cssClasses.input BREAKING CHANGE: - removed: inputClass
1 parent 4291014 commit 5974a88

File tree

7 files changed

+88
-46
lines changed

7 files changed

+88
-46
lines changed

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,27 @@ npm run test:watch # developer mode, test only
191191

192192
![Example of the searchBox widget][searchBox]
193193

194+
195+
#### API
196+
197+
```js
198+
/**
199+
* Instantiate a searchbox
200+
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
201+
* @param {String} [options.placeholder='Search here'] Input's placeholder
202+
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, input
203+
* @param {String|String[]} [options.cssClasses.root=null]
204+
* @param {String|String[]} [options.cssClasses.input=null]
205+
* @param {Object} [options.templates] Templates to use for the widget
206+
* @param {String|Function} [options.templates.header=''] Header template
207+
* @param {String|Function} [options.templates.footer=''] Footer template
208+
* @param {boolean} [poweredBy=false] Show a powered by Algolia link below the input
209+
* @return {Object}
210+
*/
211+
```
212+
213+
#### Usage
214+
194215
```html
195216
<div id="search-box"></div>
196217
```

components/SearchBox.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
var React = require('react');
22

33
var PoweredBy = require('./PoweredBy');
4+
var headerFooter = require('../decorators/headerFooter');
45
var bem = require('../lib/utils').bemHelper('as-search-box');
56
var cx = require('classnames');
67

@@ -24,14 +25,12 @@ class SearchBox extends React.Component {
2425
}
2526

2627
render() {
27-
var classNames = cx(bem('input'), this.props.inputClass);
28-
2928
return (
3029
<div>
3130
<input type="text"
3231
placeholder={this.props.placeholder}
3332
name="algolia-query"
34-
className={classNames}
33+
className={cx(bem('input'), this.props.cssClasses.input)}
3534
autoComplete="off"
3635
autoFocus="autofocus"
3736
onChange={this.handleChange.bind(this)}
@@ -47,16 +46,18 @@ class SearchBox extends React.Component {
4746
}
4847

4948
SearchBox.defaultProps = {
50-
onBlur: function() {},
51-
onFocus: function() {}
49+
onBlur() {},
50+
onFocus() {}
5251
};
5352

5453
SearchBox.propTypes = {
5554
placeholder: React.PropTypes.string,
56-
inputClass: React.PropTypes.oneOfType([
57-
React.PropTypes.string,
58-
React.PropTypes.array
59-
]),
55+
cssClasses: React.PropTypes.shape({
56+
input: React.PropTypes.oneOfType([
57+
React.PropTypes.string,
58+
React.PropTypes.arrayOf(React.PropTypes.string)
59+
])
60+
}),
6061
poweredBy: React.PropTypes.bool,
6162
setQuery: React.PropTypes.func,
6263
search: React.PropTypes.func,
@@ -65,4 +66,4 @@ SearchBox.propTypes = {
6566
value: React.PropTypes.string
6667
};
6768

68-
module.exports = SearchBox;
69+
module.exports = headerFooter(SearchBox);

example/app.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ search.addWidget(
1717
instantsearch.widgets.searchBox({
1818
container: '#search-box',
1919
placeholder: 'Search for products',
20-
cssClass: 'form-control',
20+
cssClasses: {
21+
input: 'form-control'
22+
},
2123
poweredBy: true
2224
})
2325
);
@@ -100,7 +102,10 @@ search.addWidget(
100102
container: '#free-shipping',
101103
facetName: 'free_shipping',
102104
label: 'Free Shipping',
103-
template: require('./templates/free-shipping.html')
105+
templates: {
106+
header: '<div class="panel-heading">Shipping</div>',
107+
body: require('./templates/free-shipping.html')
108+
}
104109
})
105110
);
106111

example/index.html

+1-8
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,7 @@ <h1>Instant search demo <small>using instantsearch.js</small></h1>
2929

3030
<div class="panel panel-default" id="price-range"></div>
3131

32-
<div class="panel panel-default">
33-
<div class="panel-heading">Shipping</div>
34-
<div class="panel-body">
35-
<ul class="nav nav-stacked">
36-
<li><div id="free-shipping"></div></li>
37-
</ul>
38-
</div>
39-
</div>
32+
<div class="panel panel-default" id="free-shipping"></div>
4033

4134
<div class="panel panel-default">
4235
<div class="panel-heading">Price</div>

example/templates/free-shipping.html

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
<div class="checkbox">
1+
<div class="checkbox panel-body">
22
<label>
33
<input type="checkbox" {{#isRefined}}checked{{/isRefined}} />
44
<span class="badge">{{label}}</span>
55
</label>
66
</div>
7-
8-
9-

widgets/search-box.js

+40-22
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,62 @@ var React = require('react');
22

33
var utils = require('../lib/utils.js');
44

5-
function searchbox(params) {
5+
/**
6+
* Instantiate a searchbox
7+
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
8+
* @param {String} [options.placeholder='Search here'] Input's placeholder
9+
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, input
10+
* @param {String|String[]} [options.cssClasses.root=null]
11+
* @param {String|String[]} [options.cssClasses.input=null]
12+
* @param {Object} [options.templates] Templates to use for the widget
13+
* @param {String|Function} [options.templates.header=''] Header template
14+
* @param {String|Function} [options.templates.footer=''] Footer template
15+
* @param {boolean} [poweredBy=false] Show a powered by Algolia link below the input
16+
* @return {Object}
17+
*/
18+
function searchbox({
19+
container = null,
20+
placeholder = 'Search here',
21+
cssClasses = {
22+
input: null,
23+
root: null
24+
},
25+
templates = {
26+
header: '',
27+
footer: ''
28+
},
29+
poweredBy = false
30+
}) {
631
var SearchBox = require('../components/SearchBox');
732

8-
var container = utils.getContainerNode(params.container);
33+
var containerNode = utils.getContainerNode(container);
934
var isFocused = false;
1035

1136
return {
12-
init: function(initialState, helper) {
37+
_render(state, helper) {
1338
React.render(
1439
<SearchBox
1540
onFocus={()=> { isFocused = true; }}
1641
onBlur={()=> { isFocused = false; }}
1742
setQuery={helper.setQuery.bind(helper)}
1843
search={helper.search.bind(helper)}
19-
placeholder={params.placeholder}
20-
inputClass={params.cssClass}
21-
value={initialState.query}
22-
poweredBy={params.poweredBy}
44+
placeholder={placeholder}
45+
templates={templates}
46+
cssClasses={cssClasses}
47+
value={state.query}
48+
poweredBy={poweredBy}
2349
/>,
24-
container
50+
containerNode
2551
);
2652
},
2753

28-
render: function({state, helper}) {
54+
init(initialState, helper) {
55+
this._render(initialState, helper);
56+
},
57+
58+
render({state, helper}) {
2959
if (!isFocused) {
30-
React.render(
31-
<SearchBox
32-
onFocus={()=> { isFocused = true; }}
33-
onBlur={()=> { isFocused = false; }}
34-
setQuery={helper.setQuery.bind(helper)}
35-
search={helper.search.bind(helper)}
36-
placeholder={params.placeholder}
37-
inputClass={params.cssClass}
38-
value={state.query}
39-
poweredBy={params.poweredBy}
40-
/>,
41-
container
42-
);
60+
this._render(state, helper);
4361
}
4462
}
4563
};

widgets/toggle.js

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ function toggle({
3838
}),
3939
render: function({helper, results}) {
4040
var isRefined = helper.hasRefinements(facetName);
41+
var values = find(results.getFacetValues(facetName), {name: isRefined.toString()});
42+
43+
var facetValue = {
44+
name: label,
45+
isRefined: isRefined,
46+
count: values && values.count || null
47+
};
4148

4249
function toggleFilter() {
4350
var methodToCall = isRefined ? 'removeFacetRefinement' : 'addFacetRefinement';

0 commit comments

Comments
 (0)