Skip to content

Commit 22b4183

Browse files
Merge #653
653: feat: accept dom element r=bidoubiwa a=ColinFrick # Pull Request ## Related issue Fixes #652 ## What does this PR do? - Accept dom element with property `inputElement` ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: Colin Frick <[email protected]>
2 parents 96aa702 + 979055c commit 22b4183

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Add the following code to one of your `HTML` files.
141141

142142
The `hostUrl` and the `apiKey` (_optional_) fields are the credentials of your Meilisearch instance.<br>
143143
`indexUid` is the index identifier in your Meilisearch instance in which your website content is stored.<br>
144-
`inputSelector` is the `id` attribute of the HTML search input tag.
144+
`inputSelector` is the `id` attribute of the HTML search input tag. As an alternative the dom element can be supplied with `inputElement` directly.
145145

146146
_Your documentation content is not indexed yet? Check out [this tutorial](https://docs.meilisearch.com/create/how_to/search_bar_for_docs.html)._
147147

src/lib/DocsSearchBar.js

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { constructClientAgents } from './agents'
1111
* @param {string} options.hostUrl URL where Meilisearch instance is hosted
1212
* @param {string} options.apiKey Read-only API key
1313
* @param {string} options.indexUid UID of the index to target
14-
* @param {string} options.inputSelector CSS selector that targets the input
14+
* @param {string} [options.inputSelector] CSS selector that targets the input
15+
* @param {Element} [options.inputElement] Input element
1516
* @param {boolean} [options.debug] When set to true, the dropdown will not be closed on blur
1617
* @param {Object} [options.meilisearchOptions] Options to pass the underlying Meilisearch client
1718
* @param {function} [options.queryDataCallback] This function will be called when querying Meilisearch
@@ -29,7 +30,8 @@ const usage = `Usage:
2930
hostUrl,
3031
apiKey,
3132
indexUid,
32-
inputSelector,
33+
[ inputSelector ],
34+
[ inputElement ],
3335
[ debug ],
3436
[ meilisearchOptions ],
3537
[ queryDataCallback ],
@@ -46,7 +48,8 @@ class DocsSearchBar {
4648
hostUrl,
4749
apiKey,
4850
indexUid,
49-
inputSelector,
51+
inputSelector = '',
52+
inputElement = null,
5053
debug = false,
5154
meilisearchOptions = {},
5255
queryDataCallback = null,
@@ -64,6 +67,7 @@ class DocsSearchBar {
6467
apiKey,
6568
indexUid,
6669
inputSelector,
70+
inputElement,
6771
debug,
6872
meilisearchOptions,
6973
queryDataCallback,
@@ -80,7 +84,9 @@ class DocsSearchBar {
8084
this.apiKey = apiKey
8185
this.hostUrl = hostUrl
8286
this.indexUid = indexUid
83-
this.input = DocsSearchBar.getInputFromSelector(inputSelector)
87+
this.input = inputElement
88+
? $(inputElement)
89+
: DocsSearchBar.getInputFromSelector(inputSelector)
8490
this.meilisearchOptions = {
8591
limit: 5,
8692
attributesToHighlight: ['*'],
@@ -121,7 +127,11 @@ class DocsSearchBar {
121127
clientAgents: constructClientAgents(clientAgents),
122128
})
123129

124-
DocsSearchBar.addThemeWrapper(inputSelector, this.enableDarkMode)
130+
DocsSearchBar.addThemeWrapper(
131+
inputElement,
132+
inputSelector,
133+
this.enableDarkMode,
134+
)
125135

126136
if (enhancedSearchInput) {
127137
this.input = DocsSearchBar.injectSearchBox(this.input)
@@ -176,17 +186,18 @@ class DocsSearchBar {
176186
/**
177187
* Wraps input selector in a docs-searchbar-js div
178188
* @function addThemeWrapper
189+
* @param {Element} inputElement Input Element
179190
* @param {string} inputSelector Selector of the input element
180191
* @param {boolean|'auto'} enableDarkMode Allows you to enforce, light theme, dark theme, or auto mode on the searchbar.
181192
* @returns {void}
182193
*/
183-
static addThemeWrapper(inputSelector, enableDarkMode) {
184-
const inputElement = document.querySelector(inputSelector)
185-
const parent = inputElement.parentNode
194+
static addThemeWrapper(inputElement, inputSelector, enableDarkMode) {
195+
const input = inputElement || document.querySelector(inputSelector)
196+
const parent = input.parentNode
186197
const wrapper = document.createElement('div')
187198
wrapper.className += 'docs-searchbar-js'
188-
parent.replaceChild(wrapper, inputElement)
189-
wrapper.appendChild(inputElement)
199+
parent.replaceChild(wrapper, input)
200+
wrapper.appendChild(input)
190201

191202
let isSystemInDarkMode = Boolean(enableDarkMode)
192203
if (enableDarkMode === 'auto' && window.matchMedia) {
@@ -219,17 +230,24 @@ class DocsSearchBar {
219230
* @returns {void}
220231
*/
221232
static checkArguments(args) {
222-
if (!args.inputSelector || !args.indexUid || !args.hostUrl) {
233+
if (
234+
(!args.inputSelector && !args.inputElement) ||
235+
!args.indexUid ||
236+
!args.hostUrl
237+
) {
223238
throw new Error(usage)
224239
}
225240

226-
if (typeof args.inputSelector !== 'string') {
241+
if (args.inputSelector !== null && typeof args.inputSelector !== 'string') {
227242
throw new Error(
228243
`Error: inputSelector:${args.inputSelector} must be a string. Each selector must match only one element and separated by ','`,
229244
)
230245
}
231246

232-
if (!DocsSearchBar.getInputFromSelector(args.inputSelector)) {
247+
if (
248+
!args.inputElement &&
249+
!DocsSearchBar.getInputFromSelector(args.inputSelector)
250+
) {
233251
throw new Error(
234252
`Error: No input element in the page matches ${args.inputSelector}`,
235253
)
@@ -342,7 +360,7 @@ class DocsSearchBar {
342360
* @function getInputFromSelector
343361
* @param {string} selector CSS selector that matches the search
344362
* input of the page
345-
* @returns {void}
363+
* @returns {zepto.Z|null} Matching input or null
346364
*/
347365
static getInputFromSelector(selector) {
348366
const input = $(selector).filter('input')

src/lib/__tests__/DocsSearchBar-test.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,19 @@ describe('DocsSearchBar', () => {
249249
}),
250250
).toBe(true)
251251
})
252+
253+
it('should accept the input element directly', () => {
254+
const inputElement = document.getElementById('input')
255+
const options = { ...defaultOptions, inputElement }
256+
delete options.inputSelector
257+
258+
// When
259+
const actual = new DocsSearchBar(options)
260+
261+
// Then
262+
const $inputs = actual.input
263+
expect($inputs[0]).toEqual(inputElement)
264+
})
252265
})
253266

254267
describe('checkArguments', () => {
@@ -291,7 +304,7 @@ describe('DocsSearchBar', () => {
291304
checkArguments(options)
292305
}).toThrow(/^Usage:/)
293306
})
294-
it('should throw an error if no inputSelector defined', () => {
307+
it('should throw an error if no inputSelector or inputElement defined', () => {
295308
// Given
296309
const options = defaultOptions
297310
delete options.inputSelector

0 commit comments

Comments
 (0)