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',
|
||||
indexName: 'react-native',
|
||||
inputSelector: '#search-input',
|
||||
autocompleteOptions: {
|
||||
debug: true
|
||||
}
|
||||
debug: true
|
||||
});
|
||||
|
||||
document.getElementById('search-input').focus();
|
||||
|
|
|
|||
|
|
@ -40,9 +40,12 @@ class DocSearch {
|
|||
debug: false,
|
||||
hint: false,
|
||||
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.appId = appId;
|
||||
|
|
@ -52,15 +55,25 @@ class DocSearch {
|
|||
let autocompleteOptionsDebug = autocompleteOptions && autocompleteOptions.debug ? autocompleteOptions.debug: false;
|
||||
autocompleteOptions.debug = debug || autocompleteOptionsDebug;
|
||||
this.autocompleteOptions = autocompleteOptions;
|
||||
this.autocompleteOptions.cssClasses = {
|
||||
prefix: 'ds'
|
||||
};
|
||||
|
||||
this.isSimpleLayout = (layout === 'simple');
|
||||
|
||||
this.client = algoliasearch(this.appId, this.apiKey);
|
||||
this.client.addAlgoliaAgent('docsearch.js ' + version);
|
||||
|
||||
if (enhancedSearchInput) {
|
||||
DocSearch.injectSearchBox(this.input);
|
||||
}
|
||||
|
||||
this.autocomplete = autocomplete(this.input, autocompleteOptions, [{
|
||||
source: this.getAutocompleteSource(),
|
||||
source: this.getAutocompleteSource(transformData),
|
||||
templates: {
|
||||
suggestion: DocSearch.getSuggestionTemplate(),
|
||||
footer: templates.footer
|
||||
suggestion: DocSearch.getSuggestionTemplate(this.isSimpleLayout),
|
||||
footer: templates.footer,
|
||||
empty: DocSearch.getEmptyTemplate()
|
||||
}
|
||||
}]);
|
||||
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
|
||||
* @function getInputFromSelector
|
||||
|
|
@ -108,14 +126,18 @@ class DocSearch {
|
|||
* @returns {function} Method to be passed as the `source` option of
|
||||
* autocomplete
|
||||
*/
|
||||
getAutocompleteSource() {
|
||||
getAutocompleteSource(transformData) {
|
||||
return (query, callback) => {
|
||||
this.client.search([{
|
||||
indexName: this.indexName,
|
||||
query: query,
|
||||
params: this.algoliaOptions
|
||||
}]).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;
|
||||
}
|
||||
|
||||
static getSuggestionTemplate() {
|
||||
static getEmptyTemplate() {
|
||||
return (args) => {
|
||||
return Hogan.compile(templates.empty).render(args);
|
||||
};
|
||||
}
|
||||
|
||||
static getSuggestionTemplate(isSimpleLayout) {
|
||||
const template = Hogan.compile(templates.suggestion);
|
||||
return (suggestion) => {
|
||||
return template.render(suggestion);
|
||||
isSimpleLayout = isSimpleLayout || false;
|
||||
return template.render({isSimpleLayout, ...suggestion});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ let templates = {
|
|||
<div class="${suggestionPrefix}
|
||||
{{#isCategoryHeader}}${suggestionPrefix}__main{{/isCategoryHeader}}
|
||||
{{#isSubCategoryHeader}}${suggestionPrefix}__secondary{{/isSubCategoryHeader}}
|
||||
{{#isSimpleLayout}}suggestion-layout-simple{{/isSimpleLayout}}
|
||||
">
|
||||
<div class="${suggestionPrefix}--category-header">{{{category}}}</div>
|
||||
<div class="${suggestionPrefix}--wrapper">
|
||||
|
|
@ -27,6 +28,55 @@ let templates = {
|
|||
<div class="${footerPrefix}">
|
||||
Search by <a class="${footerPrefix}--logo" href="https://www.algolia.com/docsearch">Algolia</a>
|
||||
</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
|
||||
|
||||
// Main autocomplete wrapper
|
||||
.aa-dropdown-menu {
|
||||
.ds-dropdown-menu {
|
||||
background-color: #FFF;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
|
|
@ -56,10 +56,10 @@
|
|||
}
|
||||
|
||||
// Selected suggestion
|
||||
.aa-cursor .algolia-docsearch-suggestion--content {
|
||||
.ds-cursor .algolia-docsearch-suggestion--content {
|
||||
color: $color-selected-text;
|
||||
}
|
||||
.aa-cursor .algolia-docsearch-suggestion {
|
||||
.ds-cursor .algolia-docsearch-suggestion {
|
||||
background: $color-selected-background;
|
||||
}
|
||||
|
||||
|
|
@ -79,10 +79,10 @@
|
|||
border-top: 1px solid lighten($color-border, 60%);
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--content,
|
||||
.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--content {
|
||||
border-top: 0;
|
||||
}
|
||||
.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--content,
|
||||
.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--content {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--subcategory-inline {
|
||||
display: inline-block;
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
// BREAKPOINT 1:
|
||||
// Screen is big enough to display the text snippets
|
||||
@media (min-width: $breakpoint-medium) {
|
||||
.aa-dropdown-menu {
|
||||
.ds-dropdown-menu {
|
||||
min-width: $dropdown-min-width-medium;
|
||||
}
|
||||
.algolia-docsearch-suggestion--text {
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
// BREAKPOINT 2:
|
||||
// Screen is big enough to display results in two columns
|
||||
@media (min-width: $breakpoint-large) {
|
||||
.aa-dropdown-menu {
|
||||
.ds-dropdown-menu {
|
||||
min-width: $dropdown-min-width-large;
|
||||
}
|
||||
.algolia-docsearch-suggestion {
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ describe('DocSearch', () => {
|
|||
// Then
|
||||
expect(typeof actual.algoliaOptions).toEqual('object');
|
||||
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', () => {
|
||||
// Given
|
||||
|
|
@ -205,7 +205,7 @@ describe('DocSearch', () => {
|
|||
|
||||
// Then
|
||||
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', () => {
|
||||
// Given
|
||||
|
|
@ -980,11 +980,11 @@ describe('DocSearch', () => {
|
|||
let actual = DocSearch.getSuggestionTemplate();
|
||||
|
||||
// When
|
||||
actual('foo');
|
||||
actual({'foo': 'bar'});
|
||||
|
||||
// Then
|
||||
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