index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import _ from 'lodash'
  2. import { formatWikiHit, searchWiki } from '../algolia-search/search-wiki'
  3. function setupSearch(formEl) {
  4. const inputEl = formEl.querySelector('[data-ol-search-input]')
  5. const resultsEl = formEl.querySelector('[data-ol-search-results]')
  6. const wrapperEl = formEl.querySelector('[data-ol-search-results-wrapper]')
  7. const noResultsEl = formEl.querySelector('[data-ol-search-no-results]')
  8. const srHelpMsgEl = formEl.querySelector('[data-ol-search-sr-help-message]')
  9. function hideResultsPane() {
  10. wrapperEl.hidden = true
  11. }
  12. function showResultsPane() {
  13. wrapperEl.hidden = false
  14. hideNoResultsMsg()
  15. }
  16. function hideNoResultsMsg() {
  17. noResultsEl.hidden = true
  18. }
  19. function showNoResultsMsg() {
  20. noResultsEl.hidden = false
  21. hideResultsPane()
  22. }
  23. let lastValue = ''
  24. async function handleChange() {
  25. const value = inputEl.value
  26. if (value === lastValue) return
  27. lastValue = value
  28. if (value.length === 0) {
  29. hideResultsPane()
  30. hideNoResultsMsg()
  31. return
  32. }
  33. try {
  34. const { hits, nbHits } = await searchWiki(value, {
  35. hitsPerPage: 20,
  36. })
  37. if (nbHits === 0) {
  38. showNoResultsMsg()
  39. return
  40. }
  41. if (nbHits > 20) {
  42. srHelpMsgEl.innerText = `Showing first 20 results of ${nbHits} for ${value}`
  43. } else {
  44. srHelpMsgEl.innerText = `${nbHits} results for ${value}`
  45. }
  46. resultsEl.innerText = ''
  47. for (const hit of hits) {
  48. const { url, pageName, content } = formatWikiHit(hit)
  49. const linkEl = document.createElement('a')
  50. linkEl.className = 'search-result card'
  51. linkEl.href = url
  52. const cardBodyEl = document.createElement('div')
  53. cardBodyEl.className = 'card-body'
  54. const headerEl = document.createElement('span')
  55. headerEl.className = 'search-result-header'
  56. headerEl.innerHTML = pageName
  57. cardBodyEl.append(headerEl)
  58. if (content) {
  59. const contentEl = document.createElement('div')
  60. contentEl.className = 'search-result-content'
  61. contentEl.innerHTML = content
  62. cardBodyEl.append(contentEl)
  63. }
  64. linkEl.append(cardBodyEl)
  65. resultsEl.append(linkEl)
  66. }
  67. showResultsPane()
  68. } catch (e) {
  69. showNoResultsMsg()
  70. }
  71. }
  72. function updateClearBtnVisibility() {
  73. const value = inputEl.value
  74. formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
  75. el.hidden = value === ''
  76. })
  77. }
  78. function handleClear() {
  79. inputEl.value = ''
  80. hideResultsPane()
  81. hideNoResultsMsg()
  82. updateClearBtnVisibility()
  83. }
  84. formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
  85. el.addEventListener('click', handleClear)
  86. })
  87. formEl.addEventListener('submit', evt => {
  88. evt.preventDefault()
  89. return false
  90. })
  91. inputEl.addEventListener('input', _.debounce(handleChange, 100))
  92. inputEl.addEventListener('input', updateClearBtnVisibility)
  93. // display initial results
  94. handleChange()
  95. updateClearBtnVisibility()
  96. }
  97. document.querySelectorAll('[data-ol-faq-search]').forEach(setupSearch)