<template> <div class="autocomplete-container" :class="$vuetify.breakpoint.name"> <v-combobox accesskey="s" aria-label="søkefelt" v-model="select" :loading="loading" :items="items" :search-input.sync="search" item-text="label" :menu-props="{maxHeight: $vuetify.breakpoint.name === 'xs' ? 190 : 500, transition: 'fade-transition', allowOverflow: true}" prepend-inner-icon="search" :append-icon="null" return-object rounded hide-no-data auto-select-first no-filter hide-details label="Søk..." solo full-width flat outlined placeholder="Søk her" ref="autocomplete" color="primary" :dense="$vuetify.breakpoint.smAndDown" > <template v-slot:item="data"> <span class="search-hit"> {{data.item.label}} </span> ({{data.item.lang? data.item.lang[1] ? "bm, nn" : {"bob": "bm", "nob": "nn"}[data.item.lang[0]] : 'fritekstsøk'}}) </template> </v-combobox> </div> </template> <script> export default { props: { api: Function, }, data: function() { return { loading: false, items: [], search: null, select: null, suggesting: null, } }, watch: { search (val) { const time = Date.now() if (! val) { this.items = [] } else { this.run_query(val, time) } }, select(item) { if (item) { if (typeof item != 'string') { this.items = [] this.suggesting = false if (item.article_promise) { item.article_promise.then((response) => { item.article_ids = response.data this.submit(item) }) } else { this.submit(item) } } // If blurred else { this.items = [] } } } }, methods: { run_query(q, time) { this.suggesting = true // Keep full text search in the list while requesting suggestions if (this.items[0]) { if (this.items[0].time < time) { this.items.splice(0,1, {q: q, label: q, time: time}) } } else { this.items.push({q: q, label: q, time: time}) } let self = this self.api.get('suggest?', {params: {q: q, dict: self.$parent.lang, n: 9}}) .then(async (response) => { if (self.$refs.autocomplete.searchInput == q & self.suggesting) { let hits = [] response.data.forEach((item, i) => { let match = item[0] let hit = {q: q, match: match, label: match, time: time} hit.article_promise = self.api.get('articles?', {params: {lord: match}}) hit.lang = item[1] hits.push(hit) }); // whitespace necessary because duplicates aren't allowed in the dropdown hits.push({q: q, label: q + ' ', time: time}) self.items = hits } self.loading = false }) }, submit(item) { this.$emit('submit', item) let self = this setTimeout(() => { self.$refs.autocomplete.$refs.input.select() this.items = [] this.suggesting = false }, 1) } }, } </script> <style scoped> .search-hit { font-weight: bold; margin-right: 5px; color: var(--v-primary-base); } .autocomplete-container { padding-left: 10px; padding-right: 10px; } </style>