🔧 🌱 Complete the algolia search feature, Close #9.
This commit is contained in:
parent
9a4883832f
commit
c1e7e59646
130
assets/js/third-party/search/algolia-search.js
vendored
130
assets/js/third-party/search/algolia-search.js
vendored
@ -1,130 +0,0 @@
|
|||||||
/* global instantsearch, algoliasearch, CONFIG, pjax */
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const { indexName, appID, apiKey, hits } = CONFIG.algolia;
|
|
||||||
|
|
||||||
const search = instantsearch({
|
|
||||||
indexName,
|
|
||||||
searchClient : algoliasearch(appID, apiKey),
|
|
||||||
searchFunction: helper => {
|
|
||||||
if (document.querySelector('.search-input').value) {
|
|
||||||
helper.search();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof pjax === 'object') {
|
|
||||||
search.on('render', () => {
|
|
||||||
pjax.refresh(document.querySelector('.algolia-hits'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Registering Widgets
|
|
||||||
search.addWidgets([
|
|
||||||
instantsearch.widgets.configure({
|
|
||||||
hitsPerPage: hits.per_page || 10
|
|
||||||
}),
|
|
||||||
|
|
||||||
instantsearch.widgets.searchBox({
|
|
||||||
container : '.search-input-container',
|
|
||||||
placeholder : CONFIG.i18n.placeholder,
|
|
||||||
// Hide default icons of algolia search
|
|
||||||
showReset : false,
|
|
||||||
showSubmit : false,
|
|
||||||
showLoadingIndicator: false,
|
|
||||||
cssClasses : {
|
|
||||||
input: 'search-input'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
instantsearch.widgets.stats({
|
|
||||||
container: '.algolia-stats',
|
|
||||||
templates: {
|
|
||||||
text: data => {
|
|
||||||
const stats = CONFIG.i18n.hits_time
|
|
||||||
.replace('${hits}', data.nbHits)
|
|
||||||
.replace('${time}', data.processingTimeMS);
|
|
||||||
return `<span>${stats}</span>
|
|
||||||
<img src="${CONFIG.images}/logo-algolia-nebula-blue-full.svg" alt="Algolia">`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cssClasses: {
|
|
||||||
text: 'search-stats'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
instantsearch.widgets.hits({
|
|
||||||
container : '.algolia-hits',
|
|
||||||
escapeHTML: false,
|
|
||||||
templates : {
|
|
||||||
item: data => {
|
|
||||||
const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult;
|
|
||||||
let result = `<a href="${data.permalink}" class="search-result-title">${title.value}</a>`;
|
|
||||||
const content = excerpt || excerptStrip || contentStripTruncate;
|
|
||||||
if (content && content.value) {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.innerHTML = content.value;
|
|
||||||
result += `<a href="${data.permalink}"><p class="search-result">${div.textContent.substring(0, 100)}...</p></a>`;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
empty: data => {
|
|
||||||
return `<div class="algolia-hits-empty">
|
|
||||||
${CONFIG.i18n.empty.replace('${query}', data.query)}
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cssClasses: {
|
|
||||||
list: 'search-result-list'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
instantsearch.widgets.pagination({
|
|
||||||
container: '.algolia-pagination',
|
|
||||||
scrollTo : false,
|
|
||||||
showFirst: false,
|
|
||||||
showLast : false,
|
|
||||||
templates: {
|
|
||||||
first : '<i class="fa fa-angle-double-left"></i>',
|
|
||||||
last : '<i class="fa fa-angle-double-right"></i>',
|
|
||||||
previous: '<i class="fa fa-angle-left"></i>',
|
|
||||||
next : '<i class="fa fa-angle-right"></i>'
|
|
||||||
},
|
|
||||||
cssClasses: {
|
|
||||||
list : ['pagination', 'algolia-pagination'],
|
|
||||||
item : 'pagination-item',
|
|
||||||
link : 'page-number',
|
|
||||||
selectedItem: 'current',
|
|
||||||
disabledItem: 'disabled-item'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
|
|
||||||
search.start();
|
|
||||||
|
|
||||||
// Handle and trigger popup window
|
|
||||||
document.querySelectorAll('.popup-trigger').forEach(element => {
|
|
||||||
element.addEventListener('click', () => {
|
|
||||||
document.body.classList.add('search-active');
|
|
||||||
setTimeout(() => document.querySelector('.search-input').focus(), 500);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Monitor main search box
|
|
||||||
const onPopupClose = () => {
|
|
||||||
document.body.classList.remove('search-active');
|
|
||||||
};
|
|
||||||
|
|
||||||
document.querySelector('.search-pop-overlay').addEventListener('click', event => {
|
|
||||||
if (event.target === document.querySelector('.search-pop-overlay')) {
|
|
||||||
onPopupClose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose);
|
|
||||||
document.addEventListener('pjax:success', onPopupClose);
|
|
||||||
window.addEventListener('keyup', event => {
|
|
||||||
if (event.key === 'Escape') {
|
|
||||||
onPopupClose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
141
assets/js/third-party/search/algolia.js
vendored
Normal file
141
assets/js/third-party/search/algolia.js
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/* global instantsearch, algoliasearch, CONFIG, pjax */
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
|
const algoiajs = NexT.utils.getCDNResource(NexT.CONFIG.algolia.js);
|
||||||
|
const instantschjs = NexT.utils.getCDNResource(NexT.CONFIG.algolia.instantjs);
|
||||||
|
|
||||||
|
NexT.utils.getScript(algoiajs, {});
|
||||||
|
NexT.utils.getScript(instantschjs, {}).then(() => {
|
||||||
|
|
||||||
|
const { indexname, appid, apikey, hits } = NexT.CONFIG.algolia.cfg;
|
||||||
|
const indexName = indexname;
|
||||||
|
|
||||||
|
const search = instantsearch({
|
||||||
|
indexName,
|
||||||
|
searchClient: algoliasearch(appid, apikey),
|
||||||
|
searchFunction: helper => {
|
||||||
|
if (document.querySelector('.search-input').value) {
|
||||||
|
helper.search();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof pjax === 'object') {
|
||||||
|
search.on('render', () => {
|
||||||
|
pjax.refresh(document.querySelector('.algolia-hits'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registering Widgets
|
||||||
|
search.addWidgets([
|
||||||
|
instantsearch.widgets.configure({
|
||||||
|
hitsPerPage: hits.perpage || 10
|
||||||
|
}),
|
||||||
|
|
||||||
|
instantsearch.widgets.searchBox({
|
||||||
|
container: '.search-input-container',
|
||||||
|
placeholder: NexT.CONFIG.i18n.placeholder,
|
||||||
|
// Hide default icons of algolia search
|
||||||
|
showReset: false,
|
||||||
|
showSubmit: false,
|
||||||
|
showLoadingIndicator: false,
|
||||||
|
cssClasses: {
|
||||||
|
input: 'search-input'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
instantsearch.widgets.stats({
|
||||||
|
container: '.algolia-stats',
|
||||||
|
templates: {
|
||||||
|
text: data => {
|
||||||
|
const stats = NexT.CONFIG.i18n.hits_time
|
||||||
|
.replace('${hits}', data.nbHits)
|
||||||
|
.replace('${time}', data.processingTimeMS);
|
||||||
|
return `<span>${stats}</span>`;
|
||||||
|
//<img src="${CONFIG.images}/logo-algolia-nebula-blue-full.svg" alt="Algolia">`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cssClasses: {
|
||||||
|
text: 'search-stats'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
instantsearch.widgets.hits({
|
||||||
|
container: '.algolia-hits',
|
||||||
|
escapeHTML: false,
|
||||||
|
templates: {
|
||||||
|
item: data => {
|
||||||
|
const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult;
|
||||||
|
let result = `<a href="${data.permalink}" class="search-result-title">${title.value}</a>`;
|
||||||
|
const content = excerpt || excerptStrip || contentStripTruncate;
|
||||||
|
if (content && content.value) {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.innerHTML = content.value;
|
||||||
|
result += `<a href="${data.permalink}"><p class="search-result">${div.textContent.substring(0, 100)}...</p></a>`;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
empty: data => {
|
||||||
|
return `<div class="algolia-hits-empty">
|
||||||
|
${NexT.CONFIG.i18n.empty.replace('${query}', data.query)}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cssClasses: {
|
||||||
|
list: 'search-result-list'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
instantsearch.widgets.pagination({
|
||||||
|
container: '.algolia-pagination',
|
||||||
|
scrollTo: false,
|
||||||
|
showFirst: false,
|
||||||
|
showLast: false,
|
||||||
|
templates: {
|
||||||
|
first: '<i class="fa fa-angle-double-left"></i>',
|
||||||
|
last: '<i class="fa fa-angle-double-right"></i>',
|
||||||
|
previous: '<i class="fa fa-angle-left"></i>',
|
||||||
|
next: '<i class="fa fa-angle-right"></i>'
|
||||||
|
},
|
||||||
|
cssClasses: {
|
||||||
|
list: ['pagination', 'algolia-pagination'],
|
||||||
|
item: 'pagination-item',
|
||||||
|
link: 'page-number',
|
||||||
|
selectedItem: 'current',
|
||||||
|
disabledItem: 'disabled-item'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
search.start();
|
||||||
|
|
||||||
|
// Handle and trigger popup window
|
||||||
|
document.querySelectorAll('.popup-trigger').forEach(element => {
|
||||||
|
element.addEventListener('click', () => {
|
||||||
|
document.body.classList.add('search-active');
|
||||||
|
setTimeout(() => document.querySelector('.search-input').focus(), 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Monitor main search box
|
||||||
|
const onPopupClose = () => {
|
||||||
|
document.body.classList.remove('search-active');
|
||||||
|
};
|
||||||
|
|
||||||
|
document.querySelector('.search-pop-overlay').addEventListener('click', event => {
|
||||||
|
if (event.target === document.querySelector('.search-pop-overlay')) {
|
||||||
|
onPopupClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose);
|
||||||
|
document.addEventListener('pjax:success', onPopupClose);
|
||||||
|
window.addEventListener('keyup', event => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
onPopupClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});;
|
||||||
|
|
||||||
|
|
||||||
|
});
|
@ -39,8 +39,8 @@ analytics:
|
|||||||
addthis:
|
addthis:
|
||||||
js: https://s7.addthis.com/js/300/addthis_widget.js
|
js: https://s7.addthis.com/js/300/addthis_widget.js
|
||||||
|
|
||||||
# 评论组件资源
|
# 评论组件
|
||||||
# Comment component Resources
|
# Comment component
|
||||||
waline:
|
waline:
|
||||||
js:
|
js:
|
||||||
name: '@waline/client'
|
name: '@waline/client'
|
||||||
@ -71,3 +71,14 @@ utterances:
|
|||||||
|
|
||||||
livere:
|
livere:
|
||||||
js: https://cdn-city.livere.com/js/embed.dist.js
|
js: https://cdn-city.livere.com/js/embed.dist.js
|
||||||
|
|
||||||
|
# 全文搜索
|
||||||
|
# Full text search
|
||||||
|
algolia:
|
||||||
|
name: algoliasearch
|
||||||
|
version: 4.13.0
|
||||||
|
file: dist/algoliasearch-lite.umd.js
|
||||||
|
instant:
|
||||||
|
name: instantsearch.js
|
||||||
|
version: 4.40.5
|
||||||
|
file: dist/instantsearch.production.min.js
|
@ -898,15 +898,17 @@ params:
|
|||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# TODO
|
# 内容搜索服务
|
||||||
# 内容搜索服务(暂时未实现)
|
|
||||||
# Search Services
|
# Search Services
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
# Algolia Search
|
# Algolia Search
|
||||||
# For more information: https://www.algolia.com
|
# For more information: https://www.algolia.com
|
||||||
algoliaSearch:
|
algoliaSearch:
|
||||||
enable: false
|
enable: true
|
||||||
|
appId: #<algolia app id>
|
||||||
|
apiKey: #<algolia api key>
|
||||||
|
indexName: #<algolia index name>
|
||||||
hits:
|
hits:
|
||||||
perPage: 10
|
perPage: 10
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
"bookmark" .Site.Params.bookmark
|
"bookmark" .Site.Params.bookmark
|
||||||
"lazyload" .Site.Params.lazyload
|
"lazyload" .Site.Params.lazyload
|
||||||
"motion" .Site.Params.motion
|
"motion" .Site.Params.motion
|
||||||
"localSearch" .Site.Params.localSearch
|
|
||||||
"i18n" (dict
|
"i18n" (dict
|
||||||
"placeholder" (T "SearchPh")
|
"placeholder" (T "SearchPh")
|
||||||
"empty" (T "SearchEmpty")
|
"empty" (T "SearchEmpty")
|
||||||
@ -44,6 +43,20 @@
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
{{ if .Site.Params.localSearch.enable }}
|
||||||
|
{{ $localSearch := dict "localSearch" .Site.Params.localSearch }}
|
||||||
|
{{ $config = merge $config $localSearch }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .Site.Params.algoliaSearch.enable }}
|
||||||
|
{{ $algoliaSearch := dict
|
||||||
|
"js" .Site.Data.resources.algolia
|
||||||
|
"instantjs" .Site.Data.resources.instant
|
||||||
|
"cfg" .Site.Params.algoliaSearch
|
||||||
|
}}
|
||||||
|
{{ $config = merge $config (dict "algolia" $algoliaSearch) }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ with .Site.Params.waline }}
|
{{ with .Site.Params.waline }}
|
||||||
{{ $waline := dict
|
{{ $waline := dict
|
||||||
"js" $.Site.Data.resources.waline.js
|
"js" $.Site.Data.resources.waline.js
|
||||||
|
@ -64,11 +64,17 @@
|
|||||||
{{- $utterancesjs := resources.Get "js/third-party/comments/utterances.js" }}
|
{{- $utterancesjs := resources.Get "js/third-party/comments/utterances.js" }}
|
||||||
{{- $nextjs = $nextjs | append $utterancesjs }}
|
{{- $nextjs = $nextjs | append $utterancesjs }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Site.Params.localSearch.enable }}
|
||||||
|
{{- $search := resources.Get "js/third-party/search/local.js" }}
|
||||||
|
{{- $nextjs = $nextjs | append $search }}
|
||||||
|
{{ end }}
|
||||||
|
{{- if .Site.Params.algoliaSearch.enable }}
|
||||||
|
{{- $search := resources.Get "js/third-party/search/algolia.js" }}
|
||||||
|
{{- $nextjs = $nextjs | append $search }}
|
||||||
|
{{ end }}
|
||||||
{{- $nextjs = $nextjs | resources.Concat "js/main.js"}}
|
{{- $nextjs = $nextjs | resources.Concat "js/main.js"}}
|
||||||
{{ if hugo.IsProduction }}
|
{{ if hugo.IsProduction }}
|
||||||
{{- $nextjs = $nextjs | minify | fingerprint }}
|
{{- $nextjs = $nextjs | minify | fingerprint }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<script type="text/javascript" src="{{ $nextjs.RelPermalink }}" defer></script>
|
<script type="text/javascript" src="{{ $nextjs.RelPermalink }}" defer></script>
|
||||||
{{- $search := resources.Get "js/third-party/search/local-search.js" }}
|
|
||||||
<script type="text/javascript" src="{{ $search.RelPermalink }}" defer></script>
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user