diff --git a/README.md b/README.md index 16d2445f95..93063f5fc2 100644 --- a/README.md +++ b/README.md @@ -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} */ @@ -213,6 +208,8 @@ npm run test:watch # developer mode, test only #### Usage ```html + +Or ``` diff --git a/components/SearchBox.js b/components/SearchBox.js deleted file mode 100644 index 7c499659e6..0000000000 --- a/components/SearchBox.js +++ /dev/null @@ -1,68 +0,0 @@ -var React = require('react'); - -var PoweredBy = require('./PoweredBy'); -var bem = require('../lib/utils').bemHelper('as-search-box'); -var cx = require('classnames'); - -class SearchBox extends React.Component { - constructor(props) { - super(props); - this.state = { - value: props.value - }; - } - - componentWillReceiveProps(newProps) { - this.setState({value: newProps.value}); - } - - handleChange(e) { - var newValue = e.target.value; - this.props.setQuery(newValue); - this.props.search(); - this.setState({value: newValue}); - } - - render() { - return ( -
- - -
- ); - } -} - -SearchBox.defaultProps = { - onBlur() {}, - onFocus() {} -}; - -SearchBox.propTypes = { - placeholder: React.PropTypes.string, - cssClasses: React.PropTypes.shape({ - input: React.PropTypes.oneOfType([ - React.PropTypes.string, - React.PropTypes.arrayOf(React.PropTypes.string) - ]) - }), - poweredBy: React.PropTypes.bool, - setQuery: React.PropTypes.func, - search: React.PropTypes.func, - onFocus: React.PropTypes.func, - onBlur: React.PropTypes.func, - value: React.PropTypes.string -}; - -module.exports = SearchBox; diff --git a/example/app.js b/example/app.js index 2d353e229a..83eefd3727 100644 --- a/example/app.js +++ b/example/app.js @@ -17,9 +17,6 @@ search.addWidget( instantsearch.widgets.searchBox({ container: '#search-box', placeholder: 'Search for products', - cssClasses: { - input: 'form-control' - }, poweredBy: true }) ); diff --git a/example/index.html b/example/index.html index f1107dd89c..93066ef665 100644 --- a/example/index.html +++ b/example/index.html @@ -20,7 +20,9 @@

Instant search demo using instantsearch.js

- +
+ +
diff --git a/widgets/search-box.js b/widgets/search-box.js index 3490f42322..626bf9b4a4 100644 --- a/widgets/search-box.js +++ b/widgets/search-box.js @@ -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( - { 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(, poweredByContainer); } } };