<template> <div class="autocomplete-container" :class="$vuetify.breakpoint.name"> <v-combobox v-model="select" :loading="loading" :items="items" :search-input.sync="search" item-text="match" :menu-props="{maxHeight: $vuetify.breakpoint.name === 'xs' ? 190 : 500, transition: 'fade-transition', allowOverflow: true}" prepend-inner-icon="search" return-object rounded clearable hide-no-data no-filter auto-select-first hide-details label="Søk her" solo full-width placeholder="Søk her" ref="autocomplete" color="primary" :dense="$vuetify.breakpoint.smAndDown" > <template v-slot:append> <div v-if="!$parent.error && $parent.lang=='bm,nn'"> <a v-if="$parent.search_results.bm && $parent.search_results.bm.length > 0" href="#result0" class="accessibility_link" tabindex="0">Gå til treff i Bokmålsordboka</a> <a :v-if="$parent.search_results.nn && $parent.search_results.nn.length > 0" :href="'#result'+($parent.search_results.bm? $parent.search_results.bm.length : 0)" class="accessibility_link" tabindex="0">Gå til treff i Nynorskordboka</a> </div> <div v-else> <a href="#result0" class="accessibility_link" tabindex="0">Gå til hovedinnhold</a> </div> <a href="#top_menu" class="accessibility_link" @click="$store.commit('toggleMenu')" aria-label="Hopp til toppmeny" > Åpne toppmeny</a> <v-divider vertical/> <v-menu allowOverflow: true offsetY> <template v-slot:activator="{ on, attrs }"> <v-btn class="search-field-button" v-bind="attrs" v-on="on" plain depressed color = "primary" text @click.native="items=[]"> <v-icon left>book</v-icon> <span v-if="!$vuetify.breakpoint.smAndDown"> {{$t(`dicts.${$parent.lang}`)}} </span><span v-if="$vuetify.breakpoint.smAndDown">{{$t(`dicts_short.${$parent.lang}`)}}</span></v-btn> </template> <v-list> <v-list-item v-for="item in ['bm,nn','bm','nn'].map(l => {return {label: $t(`dicts.${l}`), tag: l}})" :key="item.tag" active-class="v-list-item--active" :class="$parent.lang == item.tag ? 'v-list-item--active' : ''" @click="update_lang_form(item.tag)"> <v-list-item-title >{{ item.label }}</v-list-item-title> </v-list-item> </v-list> </v-menu> </template> <template v-slot:item="data"> <span v-if="!data.item.lang"> Søk: <strong>{{data.item.match}}</strong> </span> <span v-if="data.item.lang"> <span class="searchLemma"> {{data.item.match}} </span> <span v-if="(get_lang()=='bm,nn')"> ({{["bm","nn","bm,nn"][data.item.lang-1]}}) </span> </span> </template> </v-combobox> </div> </template> <script> export default { props: { api: Function, }, data: function() { return { loading: false, items: [], inflection_suggestions: null, similar: null, search: null, select: this.$route.query? this.$route.query.q : null, suggesting: null, menuDialog: false } }, 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 item.inflection_suggestions = this.inflection_suggestions item.similar = this.similar this.submit(item) } } }, $route (to, from) { this.select = to.query.q } }, methods: { update_lang_form(lang) { this.$emit('update-lang-form', lang) // Submit if switching on front page if (this.search && !this.items[0]) { this.submit({q: this.search, match: this.search, time: Date.now()}) } }, get_lang() { return this.$parent.lang }, run_query(q, time) { q = q.trim() if (this.items[0]) { if (this.items[0].time < time) { // Whitespace necessary in case option already exists in dropdown this.items.splice(0,1, {q, match: q, time}) } } else { this.items.push({q, match: q, time}) } this.suggesting = true if (!/[_*%|]/.test(q)) { let self = this let params = {q, dict: self.get_lang(), n: 6, dform: 'int', meta: 'n', scope: "wb"} self.api.get('suggest?', {params}) .then(async (response) => { if (self.$refs.autocomplete.searchInput == q & self.suggesting) { let suggestions = [] if (response.data.a.exact) { suggestions = response.data.a.exact.map(item => ({q: q, match: item[0], time: time, lang: [item[1]], w: true})) } self.inflection_suggestions = response.data.a.inflect self.similar = response.data.a.similar if (suggestions.length) { if (suggestions[0].q != suggestions[0].match) { suggestions.unshift({q, match: q, time}) } self.items = suggestions } else { self.items = [{q, match: q, time}] } } }) } else { this.similar = [] this.inflection_suggestions = [] this.items = [{q, match: q, time}] } }, submit(item) { this.$emit('submit', item) let self = this setTimeout(() => { if (!self.$store.state.noMouse && this.$vuetify.breakpoint.mdAndUp) self.$refs.autocomplete.$refs.input.select() else self.$refs.autocomplete.$refs.input.blur() self.suggesting = false }, 1) } }, mounted: function() { if (!this.$route.hash) { if(!this.$store.state.noMouse && this.$vuetify.breakpoint.mdAndUp) { this.$refs.autocomplete.$refs.input.focus() } } } } </script> <style scoped> v-toolbar { z-index: 2000 !important; } .searchResult { margin-right: 5px; } .searchLemma { color: var(--v-primary-base); font-weight: bold; } .autocomplete-container { padding-left: 10px; padding-right: 10px; } .search-field-button { padding-right: 0px !important; } .accessibility_link { display: inline; position: absolute; left: -10000px; } .accessibility_link:focus { position: absolute; left: 48px; top : 48px; background-color: white; padding: 10px; z-index: 10000; } </style>