Files
overleaf-cep/services/web/frontend/js/features/faq-search/index.js
T
Thomas 00b54abb77 Migrate portals and learn wiki to BS5 (#26852)
* Convert and add portals and learn wiki .less to .scss

* Convert learn wiki to BS5 and update search JS

* Convert portals to BS5

* Move gallery page padding to seperate class, to avoid forcing padding to the gallery included on portal pages

---------

Co-authored-by: Rebeka Dekany <50901361+rebekadekany@users.noreply.github.com>
GitOrigin-RevId: 3a93d56280ccdcf7fb1837511a3efe54b2efd428
2025-07-25 08:05:40 +00:00

115 lines
3.1 KiB
JavaScript

import _ from 'lodash'
import { formatWikiHit, searchWiki } from '../algolia-search/search-wiki'
function setupSearch(formEl) {
const inputEl = formEl.querySelector('[data-ol-search-input]')
const resultsEl = formEl.querySelector('[data-ol-search-results]')
const wrapperEl = formEl.querySelector('[data-ol-search-results-wrapper]')
const noResultsEl = formEl.querySelector('[data-ol-search-no-results]')
const srHelpMsgEl = formEl.querySelector('[data-ol-search-sr-help-message]')
function hideResultsPane() {
wrapperEl.hidden = true
}
function showResultsPane() {
wrapperEl.hidden = false
hideNoResultsMsg()
}
function hideNoResultsMsg() {
noResultsEl.hidden = true
}
function showNoResultsMsg() {
noResultsEl.hidden = false
hideResultsPane()
}
let lastValue = ''
async function handleChange() {
const value = inputEl.value
if (value === lastValue) return
lastValue = value
if (value.length === 0) {
hideResultsPane()
hideNoResultsMsg()
return
}
try {
const { hits, nbHits } = await searchWiki(value, {
hitsPerPage: 20,
})
if (nbHits === 0) {
showNoResultsMsg()
return
}
if (nbHits > 20) {
srHelpMsgEl.innerText = `Showing first 20 results of ${nbHits} for ${value}`
} else {
srHelpMsgEl.innerText = `${nbHits} results for ${value}`
}
resultsEl.innerText = ''
for (const hit of hits) {
const { url, pageName, content } = formatWikiHit(hit)
const linkEl = document.createElement('a')
linkEl.className = 'search-result card'
linkEl.href = url
const cardBodyEl = document.createElement('div')
cardBodyEl.className = 'card-body'
const headerEl = document.createElement('span')
headerEl.className = 'search-result-header'
headerEl.innerHTML = pageName
cardBodyEl.append(headerEl)
if (content) {
const contentEl = document.createElement('div')
contentEl.className = 'search-result-content'
contentEl.innerHTML = content
cardBodyEl.append(contentEl)
}
linkEl.append(cardBodyEl)
resultsEl.append(linkEl)
}
showResultsPane()
} catch (e) {
showNoResultsMsg()
}
}
function updateClearBtnVisibility() {
const value = inputEl.value
formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
el.hidden = value === ''
})
}
function handleClear() {
inputEl.value = ''
hideResultsPane()
hideNoResultsMsg()
updateClearBtnVisibility()
}
formEl.querySelectorAll('[data-ol-clear-search]').forEach(el => {
el.addEventListener('click', handleClear)
})
formEl.addEventListener('submit', evt => {
evt.preventDefault()
return false
})
inputEl.addEventListener('input', _.debounce(handleChange, 100))
inputEl.addEventListener('input', updateClearBtnVisibility)
// display initial results
handleChange()
updateClearBtnVisibility()
}
document.querySelectorAll('[data-ol-faq-search]').forEach(setupSearch)