Skip to content

Commit

Permalink
fix(searchBox): allow searchBox to reuse an <input>
Browse files Browse the repository at this point in the history
This no longer uses React for the `input` display (it still uses it
for the optionnal `PoweredBy` widget).

All HTML attributes already set on the `input` are kept, but sensible
defaults (like `autocorrect`, etc) are added. It listens to the
`keyup` event only to start the search.

There is no `render` method because it does not need to be updated on
results, only triggering it.
  • Loading branch information
pixelastic committed Sep 28, 2015
1 parent 53605d9 commit e820cc3
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 125 deletions.
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,7 @@ npm run test:watch # developer mode, test only
* Instantiate a searchbox
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
* @param {String} [options.placeholder='Search here'] Input's placeholder
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, input
* @param {String|String[]} [options.cssClasses.root=null]
* @param {String|String[]} [options.cssClasses.input=null]
* @param {Object} [options.templates] Templates to use for the widget
* @param {String|Function} [options.templates.header=''] Header template
* @param {String|Function} [options.templates.footer=''] Footer template
* @param {Object} [options.cssClass] CSS classes to add to the input
* @param {boolean} [poweredBy=false] Show a powered by Algolia link below the input
* @return {Object}
*/
Expand All @@ -213,6 +208,8 @@ npm run test:watch # developer mode, test only
#### Usage

```html
<input id="search-box" />
Or
<div id="search-box"></div>
```

Expand Down
68 changes: 0 additions & 68 deletions components/SearchBox.js

This file was deleted.

3 changes: 0 additions & 3 deletions example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ search.addWidget(
instantsearch.widgets.searchBox({
container: '#search-box',
placeholder: 'Search for products',
cssClasses: {
input: 'form-control'
},
poweredBy: true
})
);
Expand Down
4 changes: 3 additions & 1 deletion example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ <h1>Instant search demo <small>using instantsearch.js</small></h1>
<div class="row">
<div class="col-md-3">
<div class="panel">
<div class="panel-body" id="search-box"></div>
<div class="panel-body">
<input id="search-box" class="form-control" />
</div>
</div>

<div class="panel panel-default" id="categories"></div>
Expand Down
89 changes: 42 additions & 47 deletions widgets/search-box.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,58 @@
var React = require('react');

var utils = require('../lib/utils.js');
var headerFooter = require('../decorators/headerFooter');
var SearchBox = headerFooter(require('../components/SearchBox'));
var forEach = require('lodash/collection/forEach');

/**
* Instantiate a searchbox
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
* @param {String} [options.placeholder='Search here'] Input's placeholder
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, input
* @param {String|String[]} [options.cssClasses.root=null]
* @param {String|String[]} [options.cssClasses.input=null]
* @param {Object} [options.templates] Templates to use for the widget
* @param {String|Function} [options.templates.header=''] Header template
* @param {String|Function} [options.templates.footer=''] Footer template
* @param {Object} [options.cssClass] CSS classes to add to the input
* @param {boolean} [poweredBy=false] Show a powered by Algolia link below the input
* @return {Object}
*/
function searchbox({
container = null,
placeholder = 'Search here',
cssClasses = {
input: null,
root: null
},
templates = {
header: '',
footer: ''
},
poweredBy = false
}) {
var containerNode = utils.getContainerNode(container);
var isFocused = false;
function searchbox(params) {
// Hook on an existing input, or add one if none targeted
var input = utils.getContainerNode(params.container);
if (input.tagName !== 'INPUT') {
input = input.appendChild(document.createElement('input'));
}

return {
_render(state, helper) {
React.render(
<SearchBox
onFocus={()=> { isFocused = true; }}
onBlur={()=> { isFocused = false; }}
setQuery={helper.setQuery.bind(helper)}
search={helper.search.bind(helper)}
placeholder={placeholder}
templates={templates}
cssClasses={cssClasses}
value={state.query}
poweredBy={poweredBy}
/>,
containerNode
);
},
init: function(initialState, helper) {
var defaultAttributes = {
autocapitalize: 'off',
autocomplete: 'off',
autocorrect: 'off',
autofocus: 'autofocus',
className: params.cssClass,
placeholder: params.placeholder,
role: 'textbox',
spellcheck: 'false',
type: 'text',
value: initialState.query
};

// Overrides attributes if not already set
forEach(defaultAttributes, (value, key) => {
if (input.getAttribute(key)) {
return;
}
input.setAttribute(key, value);
});

// Always add our own classes
input.classList.add('as-search-box__input');

init(initialState, helper) {
this._render(initialState, helper);
},
input.addEventListener('keyup', () => {
helper.setQuery(input.value).search();
});

render({state, helper}) {
if (!isFocused) {
this._render(state, helper);
// Optional "powered by Algolia" widget
if (params.poweredBy) {
var React = require('react');
var PoweredBy = require('../components/PoweredBy');
var poweredByContainer = document.createElement('div');
input.parentNode.appendChild(poweredByContainer);
React.render(<PoweredBy display />, poweredByContainer);
}
}
};
Expand Down

0 comments on commit e820cc3

Please sign in to comment.