feat(v2): modification for v2 (#112)
- Add a no result screen. Fixes #92 - Change class prefix. Fixes #102 - Add a transformData option - Add searchBox option - Add a layout option
This commit is contained in:
parent
b70cf94564
commit
f0a7e6bc92
5 changed files with 102 additions and 25 deletions
|
|
@ -4,9 +4,7 @@ docsearch({
|
||||||
apiKey: 'e3d767b736584dbe6d4c35f7cf7d4633',
|
apiKey: 'e3d767b736584dbe6d4c35f7cf7d4633',
|
||||||
indexName: 'react-native',
|
indexName: 'react-native',
|
||||||
inputSelector: '#search-input',
|
inputSelector: '#search-input',
|
||||||
autocompleteOptions: {
|
debug: true
|
||||||
debug: true
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('search-input').focus();
|
document.getElementById('search-input').focus();
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,12 @@ class DocSearch {
|
||||||
debug: false,
|
debug: false,
|
||||||
hint: false,
|
hint: false,
|
||||||
autoselect: true
|
autoselect: true
|
||||||
}
|
},
|
||||||
|
transformData = false,
|
||||||
|
enhancedSearchInput = false,
|
||||||
|
layout = 'collumns'
|
||||||
}) {
|
}) {
|
||||||
DocSearch.checkArguments({apiKey, indexName, inputSelector, debug, algoliaOptions, autocompleteOptions});
|
DocSearch.checkArguments({apiKey, indexName, inputSelector, debug, algoliaOptions, autocompleteOptions, transformData, enhancedSearchInput, layout});
|
||||||
|
|
||||||
this.apiKey = apiKey;
|
this.apiKey = apiKey;
|
||||||
this.appId = appId;
|
this.appId = appId;
|
||||||
|
|
@ -52,15 +55,25 @@ class DocSearch {
|
||||||
let autocompleteOptionsDebug = autocompleteOptions && autocompleteOptions.debug ? autocompleteOptions.debug: false;
|
let autocompleteOptionsDebug = autocompleteOptions && autocompleteOptions.debug ? autocompleteOptions.debug: false;
|
||||||
autocompleteOptions.debug = debug || autocompleteOptionsDebug;
|
autocompleteOptions.debug = debug || autocompleteOptionsDebug;
|
||||||
this.autocompleteOptions = autocompleteOptions;
|
this.autocompleteOptions = autocompleteOptions;
|
||||||
|
this.autocompleteOptions.cssClasses = {
|
||||||
|
prefix: 'ds'
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isSimpleLayout = (layout === 'simple');
|
||||||
|
|
||||||
this.client = algoliasearch(this.appId, this.apiKey);
|
this.client = algoliasearch(this.appId, this.apiKey);
|
||||||
this.client.addAlgoliaAgent('docsearch.js ' + version);
|
this.client.addAlgoliaAgent('docsearch.js ' + version);
|
||||||
|
|
||||||
|
if (enhancedSearchInput) {
|
||||||
|
DocSearch.injectSearchBox(this.input);
|
||||||
|
}
|
||||||
|
|
||||||
this.autocomplete = autocomplete(this.input, autocompleteOptions, [{
|
this.autocomplete = autocomplete(this.input, autocompleteOptions, [{
|
||||||
source: this.getAutocompleteSource(),
|
source: this.getAutocompleteSource(transformData),
|
||||||
templates: {
|
templates: {
|
||||||
suggestion: DocSearch.getSuggestionTemplate(),
|
suggestion: DocSearch.getSuggestionTemplate(this.isSimpleLayout),
|
||||||
footer: templates.footer
|
footer: templates.footer,
|
||||||
|
empty: DocSearch.getEmptyTemplate()
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
this.autocomplete.on(
|
this.autocomplete.on(
|
||||||
|
|
@ -89,6 +102,11 @@ class DocSearch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static injectSearchBox(input) {
|
||||||
|
input.before(templates.searchBox);
|
||||||
|
input.remove();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the matching input from a CSS selector, null if none matches
|
* Returns the matching input from a CSS selector, null if none matches
|
||||||
* @function getInputFromSelector
|
* @function getInputFromSelector
|
||||||
|
|
@ -108,14 +126,18 @@ class DocSearch {
|
||||||
* @returns {function} Method to be passed as the `source` option of
|
* @returns {function} Method to be passed as the `source` option of
|
||||||
* autocomplete
|
* autocomplete
|
||||||
*/
|
*/
|
||||||
getAutocompleteSource() {
|
getAutocompleteSource(transformData) {
|
||||||
return (query, callback) => {
|
return (query, callback) => {
|
||||||
this.client.search([{
|
this.client.search([{
|
||||||
indexName: this.indexName,
|
indexName: this.indexName,
|
||||||
query: query,
|
query: query,
|
||||||
params: this.algoliaOptions
|
params: this.algoliaOptions
|
||||||
}]).then((data) => {
|
}]).then((data) => {
|
||||||
callback(DocSearch.formatHits(data.results[0].hits));
|
let hits = data.results[0].hits;
|
||||||
|
if (transformData) {
|
||||||
|
hits = transformData(hits) || hits;
|
||||||
|
}
|
||||||
|
callback(DocSearch.formatHits(hits));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -187,10 +209,17 @@ class DocSearch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSuggestionTemplate() {
|
static getEmptyTemplate() {
|
||||||
|
return (args) => {
|
||||||
|
return Hogan.compile(templates.empty).render(args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSuggestionTemplate(isSimpleLayout) {
|
||||||
const template = Hogan.compile(templates.suggestion);
|
const template = Hogan.compile(templates.suggestion);
|
||||||
return (suggestion) => {
|
return (suggestion) => {
|
||||||
return template.render(suggestion);
|
isSimpleLayout = isSimpleLayout || false;
|
||||||
|
return template.render({isSimpleLayout, ...suggestion});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ let templates = {
|
||||||
<div class="${suggestionPrefix}
|
<div class="${suggestionPrefix}
|
||||||
{{#isCategoryHeader}}${suggestionPrefix}__main{{/isCategoryHeader}}
|
{{#isCategoryHeader}}${suggestionPrefix}__main{{/isCategoryHeader}}
|
||||||
{{#isSubCategoryHeader}}${suggestionPrefix}__secondary{{/isSubCategoryHeader}}
|
{{#isSubCategoryHeader}}${suggestionPrefix}__secondary{{/isSubCategoryHeader}}
|
||||||
|
{{#isSimpleLayout}}suggestion-layout-simple{{/isSimpleLayout}}
|
||||||
">
|
">
|
||||||
<div class="${suggestionPrefix}--category-header">{{{category}}}</div>
|
<div class="${suggestionPrefix}--category-header">{{{category}}}</div>
|
||||||
<div class="${suggestionPrefix}--wrapper">
|
<div class="${suggestionPrefix}--wrapper">
|
||||||
|
|
@ -27,6 +28,55 @@ let templates = {
|
||||||
<div class="${footerPrefix}">
|
<div class="${footerPrefix}">
|
||||||
Search by <a class="${footerPrefix}--logo" href="https://www.algolia.com/docsearch">Algolia</a>
|
Search by <a class="${footerPrefix}--logo" href="https://www.algolia.com/docsearch">Algolia</a>
|
||||||
</div>
|
</div>
|
||||||
|
`,
|
||||||
|
empty: `
|
||||||
|
<div class="${suggestionPrefix}">
|
||||||
|
<div class="${suggestionPrefix}--wrapper">
|
||||||
|
<div class="${suggestionPrefix}--content ${suggestionPrefix}--no-result">
|
||||||
|
<div class="${suggestionPrefix}--title">
|
||||||
|
<div class="${suggestionPrefix}--text">
|
||||||
|
No results found for query <b>{{{query}}}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
searchBox: `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||||
|
<symbol xmlns="http://www.w3.org/2000/svg" id="sbx-icon-search-18" viewBox="0 0 40 40">
|
||||||
|
<path d="M30.776 27.146l-1.32-1.32-3.63 3.632 1.32 1.32 3.63-3.632zm1.368 1.368l6.035 6.035c.39.39.4 1.017.008 1.408l-2.23 2.23c-.387.387-1.015.387-1.41-.008l-6.035-6.035 3.63-3.63zm-8.11 1.392c-2.356 1.363-5.092 2.143-8.01 2.143C7.174 32.05 0 24.873 0 16.023S7.174 0 16.024 0c8.85 0 16.025 7.174 16.025 16.024 0 2.918-.78 5.654-2.144 8.01l8.96 8.962c1.175 1.174 1.184 3.07.008 4.246l-1.632 1.632c-1.17 1.17-3.067 1.173-4.247-.007l-8.96-8.96zm-8.01.54c7.965 0 14.422-6.457 14.422-14.422 0-7.965-6.457-14.422-14.422-14.422-7.965 0-14.422 6.457-14.422 14.422 0 7.965 6.457 14.422 14.422 14.422zm0-2.403c6.638 0 12.018-5.38 12.018-12.02 0-6.636-5.38-12.017-12.018-12.017-6.637 0-12.018 5.38-12.018 12.018 0 6.638 5.38 12.02 12.018 12.02zm0-1.402c5.863 0 10.616-4.752 10.616-10.616 0-5.863-4.753-10.616-10.616-10.616-5.863 0-10.616 4.753-10.616 10.616 0 5.864 4.753 10.617 10.616 10.617z"
|
||||||
|
fill-rule="evenodd" />
|
||||||
|
</symbol>
|
||||||
|
<symbol xmlns="http://www.w3.org/2000/svg" id="sbx-icon-clear-5" viewBox="0 0 20 20">
|
||||||
|
<path d="M10 20c5.523 0 10-4.477 10-10S15.523 0 10 0 0 4.477 0 10s4.477 10 10 10zm1.35-10.123l3.567 3.568-1.225 1.226-3.57-3.568-3.567 3.57-1.226-1.227 3.568-3.568-3.57-3.57 1.227-1.224 3.568 3.568 3.57-3.567 1.224 1.225-3.568 3.57zM10 18.272c4.568 0 8.272-3.704 8.272-8.272S14.568 1.728 10 1.728 1.728 5.432 1.728 10 5.432 18.272 10 18.272z"
|
||||||
|
fill-rule="evenodd" />
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<form action="void(0);" novalidate="novalidate" class="searchbox sbx-custom">
|
||||||
|
<div role="search" class="sbx-custom__wrapper">
|
||||||
|
<input type="search" name="search" placeholder="Search your website" autocomplete="off" required="required" class="sbx-custom__input">
|
||||||
|
<button type="submit" title="Submit your search query." class="sbx-custom__submit">
|
||||||
|
<svg role="img" aria-label="Search">
|
||||||
|
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-search-18"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button type="reset" title="Clear the search query." class="sbx-custom__reset">
|
||||||
|
<svg role="img" aria-label="Reset">
|
||||||
|
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-clear-5"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!--Js: focus search input after reset-->
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
document.querySelector('.searchbox [type="reset"]').addEventListener('click', function() {
|
||||||
|
this.parentNode.querySelector('input').focus();
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
// - Adding a second colum to let the content breath if enough room available
|
// - Adding a second colum to let the content breath if enough room available
|
||||||
|
|
||||||
// Main autocomplete wrapper
|
// Main autocomplete wrapper
|
||||||
.aa-dropdown-menu {
|
.ds-dropdown-menu {
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
border: 1px solid #333;
|
border: 1px solid #333;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
@ -56,10 +56,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selected suggestion
|
// Selected suggestion
|
||||||
.aa-cursor .algolia-docsearch-suggestion--content {
|
.ds-cursor .algolia-docsearch-suggestion--content {
|
||||||
color: $color-selected-text;
|
color: $color-selected-text;
|
||||||
}
|
}
|
||||||
.aa-cursor .algolia-docsearch-suggestion {
|
.ds-cursor .algolia-docsearch-suggestion {
|
||||||
background: $color-selected-background;
|
background: $color-selected-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,10 +79,10 @@
|
||||||
border-top: 1px solid lighten($color-border, 60%);
|
border-top: 1px solid lighten($color-border, 60%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--content,
|
.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--content,
|
||||||
.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--content {
|
.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--content {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.algolia-docsearch-suggestion--subcategory-inline {
|
.algolia-docsearch-suggestion--subcategory-inline {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
@ -121,7 +121,7 @@
|
||||||
// BREAKPOINT 1:
|
// BREAKPOINT 1:
|
||||||
// Screen is big enough to display the text snippets
|
// Screen is big enough to display the text snippets
|
||||||
@media (min-width: $breakpoint-medium) {
|
@media (min-width: $breakpoint-medium) {
|
||||||
.aa-dropdown-menu {
|
.ds-dropdown-menu {
|
||||||
min-width: $dropdown-min-width-medium;
|
min-width: $dropdown-min-width-medium;
|
||||||
}
|
}
|
||||||
.algolia-docsearch-suggestion--text {
|
.algolia-docsearch-suggestion--text {
|
||||||
|
|
@ -134,7 +134,7 @@
|
||||||
// BREAKPOINT 2:
|
// BREAKPOINT 2:
|
||||||
// Screen is big enough to display results in two columns
|
// Screen is big enough to display results in two columns
|
||||||
@media (min-width: $breakpoint-large) {
|
@media (min-width: $breakpoint-large) {
|
||||||
.aa-dropdown-menu {
|
.ds-dropdown-menu {
|
||||||
min-width: $dropdown-min-width-large;
|
min-width: $dropdown-min-width-large;
|
||||||
}
|
}
|
||||||
.algolia-docsearch-suggestion {
|
.algolia-docsearch-suggestion {
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ describe('DocSearch', () => {
|
||||||
// Then
|
// Then
|
||||||
expect(typeof actual.algoliaOptions).toEqual('object');
|
expect(typeof actual.algoliaOptions).toEqual('object');
|
||||||
expect(actual.algoliaOptions.anOption).toEqual(42);
|
expect(actual.algoliaOptions.anOption).toEqual(42);
|
||||||
expect(actual.autocompleteOptions).toEqual({debug: false, anOption: 44});
|
expect(actual.autocompleteOptions).toEqual({debug: false, "cssClasses": { "prefix": "ds" }, anOption: 44});
|
||||||
});
|
});
|
||||||
it('should instantiate algoliasearch with the correct values', () => {
|
it('should instantiate algoliasearch with the correct values', () => {
|
||||||
// Given
|
// Given
|
||||||
|
|
@ -205,7 +205,7 @@ describe('DocSearch', () => {
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(AutoComplete.calledOnce).toBe(true);
|
expect(AutoComplete.calledOnce).toBe(true);
|
||||||
expect(AutoComplete.calledWith($input, {anOption: '44', debug: false})).toBe(true);
|
expect(AutoComplete.calledWith($input, {anOption: '44', "cssClasses": { "prefix": "ds" }, debug: false})).toBe(true);
|
||||||
});
|
});
|
||||||
it('should listen to the selected and shown event of autocomplete', () => {
|
it('should listen to the selected and shown event of autocomplete', () => {
|
||||||
// Given
|
// Given
|
||||||
|
|
@ -980,11 +980,11 @@ describe('DocSearch', () => {
|
||||||
let actual = DocSearch.getSuggestionTemplate();
|
let actual = DocSearch.getSuggestionTemplate();
|
||||||
|
|
||||||
// When
|
// When
|
||||||
actual('foo');
|
actual({'foo': 'bar'});
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(render.calledOnce).toBe(true);
|
expect(render.calledOnce).toBe(true);
|
||||||
expect(render.calledWith('foo')).toBe(true);
|
expect(render.args[0][0]).toEqual({'isSimpleLayout': false, 'foo': 'bar'});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue