|
1 | | -import { |
2 | | - bemHelper, |
3 | | -} from '../../lib/utils.js'; |
4 | 1 | import forEach from 'lodash/forEach'; |
5 | 2 | import isString from 'lodash/isString'; |
6 | 3 | import isFunction from 'lodash/isFunction'; |
7 | 4 | import cx from 'classnames'; |
8 | 5 | import Hogan from 'hogan.js'; |
9 | 6 |
|
10 | | -const bem = bemHelper('ais-search-box'); |
11 | | -const KEY_ENTER = 13; |
12 | | -const KEY_SUPPRESS = 8; |
13 | | - |
14 | 7 | import connectSearchBox from '../../connectors/search-box/connectSearchBox.js'; |
| 8 | +import defaultTemplates from './defaultTemplates.js'; |
15 | 9 |
|
16 | | -/** |
17 | | - * Instantiate a searchbox |
18 | | - * @function searchBox |
19 | | - * @param {string|DOMElement} options.container CSS Selector or DOMElement to insert the widget |
20 | | - * @param {string} [options.placeholder] Input's placeholder [*] |
21 | | - * @param {boolean|Object} [options.poweredBy=false] Define if a "powered by Algolia" link should be added near the input |
22 | | - * @param {function|string} [options.poweredBy.template] Template used for displaying the link. Can accept a function or a Hogan string. |
23 | | - * @param {number} [options.poweredBy.cssClasses] CSS classes to add |
24 | | - * @param {string|string[]} [options.poweredBy.cssClasses.root] CSS class to add to the root element |
25 | | - * @param {string|string[]} [options.poweredBy.cssClasses.link] CSS class to add to the link element |
26 | | - * @param {boolean} [options.wrapInput=true] Wrap the input in a `div.ais-search-box` |
27 | | - * @param {boolean|string} [autofocus='auto'] autofocus on the input |
28 | | - * @param {boolean} [options.searchOnEnterKeyPressOnly=false] If set, trigger the search |
29 | | - * once `<Enter>` is pressed only |
30 | | - * @param {Object} [options.cssClasses] CSS classes to add |
31 | | - * @param {string|string[]} [options.cssClasses.root] CSS class to add to the |
32 | | - * wrapping div (if `wrapInput` set to `true`) |
33 | | - * @param {string|string[]} [options.cssClasses.input] CSS class to add to the input |
34 | | - * @param {function} [options.queryHook] A function that will be called every time a new search would be done. You |
35 | | - * will get the query as first parameter and a search(query) function to call as the second parameter. |
36 | | - * This queryHook can be used to debounce the number of searches done from the searchBox. |
37 | | - * @return {Object} |
38 | | - */ |
| 10 | +import { |
| 11 | + bemHelper, |
| 12 | + getContainerNode, |
| 13 | +} from '../../lib/utils.js'; |
39 | 14 |
|
40 | | -export default connectSearchBox(defaultRendering); |
| 15 | +const bem = bemHelper('ais-search-box'); |
| 16 | +const KEY_ENTER = 13; |
| 17 | +const KEY_SUPPRESS = 8; |
41 | 18 |
|
42 | | -// the 'input' event is triggered when the input value changes |
43 | | -// in any case: typing, copy pasting with mouse.. |
44 | | -// 'onpropertychange' is the IE8 alternative until we support IE8 |
45 | | -// but it's flawed: http://help.dottoro.com/ljhxklln.php |
46 | | -function defaultRendering({ |
47 | | - query, |
| 19 | +const renderer = ({ |
48 | 20 | containerNode, |
49 | | - onHistoryChange, |
| 21 | + cssClasses, |
| 22 | + placeholder, |
50 | 23 | poweredBy, |
51 | | - wrapInput, |
| 24 | + templates, |
52 | 25 | autofocus, |
53 | 26 | searchOnEnterKeyPressOnly, |
54 | | - placeholder, |
55 | | - cssClasses, |
56 | | - templates, |
| 27 | + wrapInput, |
| 28 | +}) => ({ |
57 | 29 | search, |
58 | | -}, isFirstRendering) { |
| 30 | + query, |
| 31 | + onHistoryChange, |
| 32 | +}, isFirstRendering) => { |
59 | 33 | if (isFirstRendering) { |
60 | 34 | const INPUT_EVENT = window.addEventListener ? |
61 | 35 | 'input' : |
@@ -125,8 +99,93 @@ function defaultRendering({ |
125 | 99 | input.value = query; |
126 | 100 | } |
127 | 101 | } |
| 102 | +}; |
| 103 | + |
| 104 | +const usage = `Usage: |
| 105 | +searchBox({ |
| 106 | + container, |
| 107 | + [ placeholder ], |
| 108 | + [ cssClasses.{input,poweredBy} ], |
| 109 | + [ poweredBy=false || poweredBy.{template, cssClasses.{root,link}} ], |
| 110 | + [ wrapInput ], |
| 111 | + [ autofocus ], |
| 112 | + [ searchOnEnterKeyPressOnly ], |
| 113 | + [ queryHook ] |
| 114 | +})`; |
| 115 | + |
| 116 | +/** |
| 117 | + * Instantiate a searchbox |
| 118 | + * @function searchBox |
| 119 | + * @param {string|DOMElement} options.container CSS Selector or DOMElement to insert the widget |
| 120 | + * @param {string} [options.placeholder] Input's placeholder [*] |
| 121 | + * @param {boolean|Object} [options.poweredBy=false] Define if a "powered by Algolia" link should be added near the input |
| 122 | + * @param {function|string} [options.poweredBy.template] Template used for displaying the link. Can accept a function or a Hogan string. |
| 123 | + * @param {number} [options.poweredBy.cssClasses] CSS classes to add |
| 124 | + * @param {string|string[]} [options.poweredBy.cssClasses.root] CSS class to add to the root element |
| 125 | + * @param {string|string[]} [options.poweredBy.cssClasses.link] CSS class to add to the link element |
| 126 | + * @param {boolean} [options.wrapInput=true] Wrap the input in a `div.ais-search-box` |
| 127 | + * @param {boolean|string} [autofocus='auto'] autofocus on the input |
| 128 | + * @param {boolean} [options.searchOnEnterKeyPressOnly=false] If set, trigger the search |
| 129 | + * once `<Enter>` is pressed only |
| 130 | + * @param {Object} [options.cssClasses] CSS classes to add |
| 131 | + * @param {string|string[]} [options.cssClasses.root] CSS class to add to the |
| 132 | + * wrapping div (if `wrapInput` set to `true`) |
| 133 | + * @param {string|string[]} [options.cssClasses.input] CSS class to add to the input |
| 134 | + * @param {function} [options.queryHook] A function that will be called every time a new search would be done. You |
| 135 | + * will get the query as first parameter and a search(query) function to call as the second parameter. |
| 136 | + * This queryHook can be used to debounce the number of searches done from the searchBox. |
| 137 | + * @return {Object} widget |
| 138 | + */ |
| 139 | +export default function searchBox({ |
| 140 | + container, |
| 141 | + placeholder = '', |
| 142 | + cssClasses = {}, |
| 143 | + poweredBy = false, |
| 144 | + wrapInput = true, |
| 145 | + autofocus = 'auto', |
| 146 | + searchOnEnterKeyPressOnly = false, |
| 147 | + queryHook, |
| 148 | +}) { |
| 149 | + if (!container) { |
| 150 | + throw new Error(usage); |
| 151 | + } |
| 152 | + |
| 153 | + const containerNode = getContainerNode(container); |
| 154 | + |
| 155 | + // Only possible values are 'auto', true and false |
| 156 | + if (typeof autofocus !== 'boolean') { |
| 157 | + autofocus = 'auto'; |
| 158 | + } |
| 159 | + |
| 160 | + // Convert to object if only set to true |
| 161 | + if (poweredBy === true) { |
| 162 | + poweredBy = {}; |
| 163 | + } |
| 164 | + |
| 165 | + const specializedRenderer = renderer({ |
| 166 | + containerNode, |
| 167 | + cssClasses, |
| 168 | + placeholder, |
| 169 | + poweredBy, |
| 170 | + templates: defaultTemplates, |
| 171 | + autofocus, |
| 172 | + searchOnEnterKeyPressOnly, |
| 173 | + wrapInput, |
| 174 | + }); |
| 175 | + |
| 176 | + try { |
| 177 | + const makeWidget = connectSearchBox(specializedRenderer); |
| 178 | + return makeWidget({queryHook}); |
| 179 | + } catch (e) { |
| 180 | + throw new Error(usage); |
| 181 | + } |
128 | 182 | } |
129 | 183 |
|
| 184 | +// the 'input' event is triggered when the input value changes |
| 185 | +// in any case: typing, copy pasting with mouse.. |
| 186 | +// 'onpropertychange' is the IE8 alternative until we support IE8 |
| 187 | +// but it's flawed: http://help.dottoro.com/ljhxklln.php |
| 188 | + |
130 | 189 | function createInput(containerNode) { |
131 | 190 | // Returns reference to targeted input if present, or create a new one |
132 | 191 | if (containerNode.tagName === 'INPUT') { |
|
0 commit comments