algolia-search.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*************************************************
  2. * Wowchemy
  3. * https://github.com/wowchemy/wowchemy-hugo-themes
  4. *
  5. * Algolia based search algorithm.
  6. **************************************************/
  7. import {algoliaConfig, i18n, content_type} from '@params';
  8. import algoliasearch from 'https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch.esm.browser.js';
  9. // import instantsearch from 'https://cdn.jsdelivr.net/npm/instantsearch.js@4/es/index.js'
  10. // import {searchBox, infiniteHits} from 'https://cdn.jsdelivr.net/npm/instantsearch.js@4/es/widgets/index.js';
  11. function getTemplate(templateName) {
  12. return document.querySelector(`#${templateName}-template`).innerHTML;
  13. }
  14. // Get query from URI.
  15. function getSearchQuery(name) {
  16. return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' ');
  17. }
  18. // On page load, check for search query in URL.
  19. document.addEventListener('DOMContentLoaded', () => {
  20. let queryURL = getSearchQuery('q');
  21. if (queryURL) {
  22. $('body').addClass('searching');
  23. $('.search-results').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 200);
  24. let commonQueries = document.querySelector('#search-common-queries');
  25. commonQueries.style.display = 'none';
  26. }
  27. if (typeof instantsearch === 'function' && $('#search-box').length) {
  28. const search = instantsearch({
  29. indexName: algoliaConfig.indexName,
  30. searchClient: algoliasearch(algoliaConfig.appId, algoliaConfig.apiKey), //'appId', 'apiKey'),
  31. routing: {
  32. router: instantsearch.routers.history({
  33. parseURL() {
  34. return {
  35. q: getSearchQuery('q'),
  36. };
  37. },
  38. }),
  39. stateMapping: {
  40. stateToRoute(uiState) {
  41. const indexUiState = uiState[algoliaConfig.indexName];
  42. return {
  43. q: indexUiState.query,
  44. };
  45. },
  46. routeToState(routeState) {
  47. return {
  48. [algoliaConfig.indexName]: {
  49. query: routeState.q,
  50. },
  51. };
  52. },
  53. },
  54. },
  55. });
  56. // Initialize search box.
  57. search.addWidget(
  58. instantsearch.widgets.searchBox({
  59. container: '#search-box',
  60. autofocus: true,
  61. showReset: true,
  62. //poweredBy: algoliaConfig.poweredBy,
  63. placeholder: i18n.placeholder,
  64. queryHook(query, search) {
  65. let searchResults = document.querySelector('#search-hits');
  66. let commonQueries = document.querySelector('#search-common-queries');
  67. if (query === '') {
  68. searchResults.style.display = 'none';
  69. commonQueries.style.display = 'block';
  70. return;
  71. }
  72. search(query);
  73. commonQueries.style.display = 'none';
  74. searchResults.style.display = 'block';
  75. },
  76. }),
  77. );
  78. // Initialize search results.
  79. search.addWidget(
  80. instantsearch.widgets.infiniteHits({
  81. container: '#search-hits',
  82. escapeHTML: true,
  83. templates: {
  84. empty: '<div class="search-no-results">' + i18n.no_results + '</div>',
  85. item: getTemplate('search-hit-algolia'),
  86. },
  87. cssClasses: {
  88. loadMore: 'btn btn-outline-primary',
  89. },
  90. }),
  91. );
  92. // On render search results, localize the content type metadata.
  93. search.on('render', function () {
  94. $('.search-hit-type').each(function () {
  95. let content_key = $(this).text();
  96. if (content_key in content_type) {
  97. $(this).text(content_type[content_key]);
  98. }
  99. });
  100. });
  101. // Start search.
  102. search.start();
  103. }
  104. });