sutty-base-jekyll-theme/_packs/controllers/search_controller.js

110 lines
2.6 KiB
JavaScript
Raw Normal View History

2020-11-12 16:28:24 +00:00
import { Controller } from 'stimulus'
import { Liquid } from 'liquidjs'
const lunr = require("lunr")
require("lunr-languages/lunr.stemmer.support")(lunr)
require("lunr-languages/lunr.es")(lunr)
export default class extends Controller {
static targets = [ 'q' ]
2021-03-26 16:11:29 +00:00
get q () {
if (!this.hasQTarget) return
if (!this.qTarget.value.trim().length === 0) return
2020-11-12 16:28:24 +00:00
2021-03-26 16:11:29 +00:00
return this.qTarget.value.trim()
}
2020-11-12 16:28:24 +00:00
2021-03-26 16:11:29 +00:00
connect () {
2020-11-12 16:28:24 +00:00
const q = window.location.search.match(/^\?q=(?<q>.*)&?/)
2021-03-26 16:11:29 +00:00
if (q) {
this.qTarget.value = decodeURI(q.groups.q)
this.search()
}
2020-11-12 16:28:24 +00:00
}
2021-03-26 16:11:29 +00:00
async search (event) {
// Detiene el envío del formulario
if (event) {
event.preventDefault()
event.stopPropagation()
}
this.formDisable = true
// Obtiene el término de búsqueda
const q = this.q
// Si no hay término de búsqueda, no hay búsqueda
if (q) {
// Trae el índice de búsqueda
await this.fetch()
2020-11-12 16:28:24 +00:00
2021-03-26 16:11:29 +00:00
// Hasta que no haya índice no buscamos nada, esto evita que se
// aprete enter dos veces y se fallen cosas.
if (!window.index) return
}
2020-11-12 16:28:24 +00:00
const main = document.querySelector('main')
const results = window.index.search(q).map(r => window.data.find(a => a.id == r.ref))
const site = await this.site()
const request = await fetch('assets/templates/results.html')
const template = await request.text()
const html = await this.engine.parseAndRender(template, { q, site, results })
const title = `${site.i18n.search.title} - ${q}`
window.history.pushState({ q }, title, `?q=${encodeURI(q)}`)
document.title = title
main.innerHTML = html
2021-03-26 16:11:29 +00:00
this.formDisable = false
2020-11-12 16:28:24 +00:00
}
async fetch () {
2021-03-26 16:11:29 +00:00
// Solo permite descargar uno a la vez
if (this.fetching) return
this.fetching = true
2020-11-12 16:28:24 +00:00
let response
2021-03-26 16:11:29 +00:00
// Si no existe el índice, lo descarga y procesa Lunr
2020-11-12 16:28:24 +00:00
if (!window.data) {
response = await fetch('data.json')
window.data = await response.json()
}
if (!window.index) {
response = await fetch('idx.json')
const idx = await response.json()
window.index = lunr.Index.load(idx)
}
2021-03-26 16:11:29 +00:00
// Permitir volver a ejecutar
this.fetching = false
}
set formDisable (disable) {
this.element.elements.forEach(x => x.disabled = disable)
2020-11-12 16:28:24 +00:00
}
/*
* Liquid renderer
*
* @return Liquid
*/
get engine () {
if (!window.liquid) window.liquid = new Liquid()
return window.liquid
}
async site () {
if (!window.site) {
const data = await fetch('assets/data/site.json')
window.site = await data.json()
}
return window.site
}
}