|
| 1 | +<script setup lang="ts"> |
| 2 | +const searchContainer = ref<HTMLElement>() |
| 3 | +
|
| 4 | +onMounted(async () => { |
| 5 | + const loadScript = (src: string, integrity?: string): Promise<void> => |
| 6 | + new Promise((resolve, reject) => { |
| 7 | + if (document.querySelector(`script[src="${src}"]`)) { resolve(); return } |
| 8 | + const script = document.createElement('script') |
| 9 | + script.src = src |
| 10 | + if (integrity) { script.integrity = integrity; script.crossOrigin = 'anonymous' } |
| 11 | + script.onload = () => resolve() |
| 12 | + script.onerror = reject |
| 13 | + document.head.appendChild(script) |
| 14 | + }) |
| 15 | +
|
| 16 | + const loadLink = (href: string, integrity?: string) => { |
| 17 | + if (document.querySelector(`link[href="${href}"]`)) return |
| 18 | + const link = document.createElement('link') |
| 19 | + link.rel = 'stylesheet' |
| 20 | + link.href = href |
| 21 | + if (integrity) { link.integrity = integrity; link.crossOrigin = 'anonymous' } |
| 22 | + document.head.appendChild(link) |
| 23 | + } |
| 24 | +
|
| 25 | + loadLink('https://cdn.jsdelivr.net/npm/instantsearch.css@8.5.1/themes/reset-min.css', 'sha256-KvFgFCzgqSErAPu6y9gz/AhZAvzK48VJASu3DpNLCEQ=') |
| 26 | + loadLink('https://cdn.jsdelivr.net/npm/@algolia/autocomplete-theme-classic@1.6.1') |
| 27 | +
|
| 28 | + await loadScript( |
| 29 | + 'https://cdn.jsdelivr.net/npm/algoliasearch@4.24.0/dist/algoliasearch-lite.umd.js', |
| 30 | + 'sha256-b2n6oSgG4C1stMT/yc/ChGszs9EY/Mhs6oltEjQbFCQ=' |
| 31 | + ) |
| 32 | + await loadScript('https://cdn.jsdelivr.net/npm/@algolia/autocomplete-js@1.6.1') |
| 33 | +
|
| 34 | + const win = window as any |
| 35 | + const { autocomplete, getAlgoliaResults } = win['@algolia/autocomplete-js'] |
| 36 | + const searchClient = win.algoliasearch('ISKYOHIT7D', '68d4032f487d66423c37e6483e067272') |
| 37 | +
|
| 38 | + const initialHitsPerPage = 5 |
| 39 | + let hitsPerPage = initialHitsPerPage |
| 40 | + let prevQuery = '' |
| 41 | + let totalHits = 0 |
| 42 | +
|
| 43 | + autocomplete({ |
| 44 | + container: searchContainer.value!, |
| 45 | + placeholder: 'Search in Handbook...', |
| 46 | + getSources ({ query }: { query: string }) { |
| 47 | + if (query !== prevQuery) { |
| 48 | + prevQuery = query |
| 49 | + hitsPerPage = initialHitsPerPage |
| 50 | + } |
| 51 | + return [{ |
| 52 | + sourceId: 'handbook', |
| 53 | + getItems: () => getAlgoliaResults({ |
| 54 | + searchClient, |
| 55 | + queries: [{ |
| 56 | + indexName: 'prod_netlify', |
| 57 | + params: { query, hitsPerPage, attributesToSnippet: ['content:50'] }, |
| 58 | + attributesToHighlight: '*', |
| 59 | + filters: 'category:handbook' |
| 60 | + }], |
| 61 | + transformResponse ({ hits, results }: any) { |
| 62 | + totalHits = results[0].nbHits |
| 63 | + return hits |
| 64 | + } |
| 65 | + }), |
| 66 | + templates: { |
| 67 | + item ({ item, components, html }: any) { |
| 68 | + return html` |
| 69 | + <a href="#" data-href="${item.url}" class="aa-ItemWrapper"> |
| 70 | + <div class="aa-ItemContent"> |
| 71 | + <div class="aa-ItemIcon aa-ItemIcon--alignTop"> |
| 72 | + <img src="#" data-src="${item.image}" alt="${item.name}" width="40" height="40" /> |
| 73 | + </div> |
| 74 | + <div class="aa-ItemContentBody"> |
| 75 | + <div class="aa-ItemContentTitle"> |
| 76 | + ${components.Highlight({ hit: item, attribute: ['hierarchy', 'lvl0'] })} |
| 77 | + </div> |
| 78 | + <div class="aa-ItemContentSubTitle ${item.type === 'lvl0' ? 'hidden' : ''}"> |
| 79 | + ${components.Highlight({ hit: item, attribute: ['hierarchy', item.type] })} |
| 80 | + </div> |
| 81 | + <div class="aa-ItemContentDescription"> |
| 82 | + ${item.content?.trim().length > 0 |
| 83 | + ? components.Snippet({ hit: item, attribute: 'content' }) |
| 84 | + : components.Snippet({ hit: item, attribute: 'description' })} |
| 85 | + </div> |
| 86 | + </div> |
| 87 | + </div> |
| 88 | + </a>` |
| 89 | + }, |
| 90 | + footer ({ items, html }: any) { |
| 91 | + if (!items.length || items.length >= totalHits) return null |
| 92 | + return html`<button type="button" class="aa-LoadMore load-more-btn">Load more...</button>` |
| 93 | + } |
| 94 | + } |
| 95 | + }] |
| 96 | + }, |
| 97 | + onStateChange ({ refresh }: any) { |
| 98 | + document.querySelectorAll('.aa-Panel a').forEach((el: any) => { |
| 99 | + el.href = el.getAttribute('data-href') |
| 100 | + }) |
| 101 | + document.querySelectorAll('.aa-Panel img').forEach((img: any) => { |
| 102 | + img.src = img.getAttribute('data-src') |
| 103 | + }) |
| 104 | + const btn = document.querySelector<HTMLElement>('.load-more-btn') |
| 105 | + if (btn) { |
| 106 | + btn.onclick = (e) => { |
| 107 | + e.preventDefault() |
| 108 | + e.stopPropagation() |
| 109 | + hitsPerPage += initialHitsPerPage |
| 110 | + refresh() |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | + }) |
| 115 | +}) |
| 116 | +</script> |
| 117 | + |
| 118 | +<template> |
| 119 | + <div ref="searchContainer" id="algolia-search" class="border rounded"></div> |
| 120 | +</template> |
0 commit comments