1
0

search.vue 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. <template>
  2. <div class="q-pa-md relative">
  3. <q-input v-model="query" dense dark standout>
  4. <template v-slot:append>
  5. <q-icon v-if="query === ''" name="search" />
  6. <q-icon v-else name="clear" class="cursor-pointer" @click="query = ''" />
  7. </template>
  8. </q-input>
  9. <q-list class="bg-primary rounded mt-2 w-64 absolute text-white z-50 max-h-[200px] overflow-y-auto">
  10. <q-item clickable v-for="result in results" :key="result.item.title" @click="goTo(result.item.url)">
  11. <q-item-section>
  12. <q-item-label>{{ result.item.title }}</q-item-label>
  13. </q-item-section>
  14. </q-item>
  15. </q-list>
  16. </div>
  17. </template>
  18. <script>
  19. export default {
  20. data() {
  21. return {
  22. query: "",
  23. results: [],
  24. searchData: [],
  25. fuse: null,
  26. };
  27. },
  28. watch: {
  29. query() {
  30. this.search();
  31. },
  32. },
  33. async created() {
  34. let response = await fetch("/static/search_index.json");
  35. if (!response.ok) {
  36. throw new Error(`HTTP error! status: ${response.status}`);
  37. }
  38. this.searchData = await response.json();
  39. let options = {
  40. keys: [
  41. { name: "title", weight: 0.7 },
  42. { name: "content", weight: 0.3 },
  43. ],
  44. };
  45. this.fuse = new Fuse(this.searchData, options);
  46. },
  47. methods: {
  48. search() {
  49. this.results = this.fuse.search(this.query);
  50. },
  51. goTo(url) {
  52. window.location.href = url;
  53. },
  54. },
  55. };
  56. </script>