index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import _ from 'lodash'
  2. import { formatWikiHit, searchWiki } from '../algolia-search/search-wiki'
  3. function setupSearch(formEl) {
  4. const inputEl = formEl.querySelector('input[type="search"]')
  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 card-thin'
  51. linkEl.href = url
  52. const headerEl = document.createElement('span')
  53. headerEl.innerHTML = pageName
  54. linkEl.append(headerEl)
  55. if (content) {
  56. const contentEl = document.createElement('div')
  57. contentEl.className = 'search-result-content'
  58. contentEl.innerHTML = content
  59. linkEl.append(contentEl)
  60. }
  61. resultsEl.append(linkEl)
  62. }
  63. showResultsPane()
  64. } catch (e) {
  65. showNoResultsMsg()
  66. }
  67. }
  68. function updateClearBtnVisibility() {
  69. const value = inputEl.value
  70. formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
  71. el.hidden = value === ''
  72. })
  73. }
  74. function handleClear() {
  75. inputEl.value = ''
  76. hideResultsPane()
  77. hideNoResultsMsg()
  78. updateClearBtnVisibility()
  79. }
  80. formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
  81. el.addEventListener('click', handleClear)
  82. })
  83. formEl.addEventListener('submit', evt => {
  84. evt.preventDefault()
  85. return false
  86. })
  87. inputEl.addEventListener('input', _.debounce(handleChange, 100))
  88. inputEl.addEventListener('input', updateClearBtnVisibility)
  89. // display initial results
  90. handleChange()
  91. }
  92. document.querySelectorAll('[data-ol-faq-search]').forEach(setupSearch)