<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="$t('search_placeholder')" solo full-width :placeholder="$t('search_placeholder')" ref="autocomplete" color="primary" :dense="$vuetify.breakpoint.mdAndDown" > <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">{{$t('accessibility.bm')}}</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">{{$t('accessibility.nn')}}</a> </div> <div v-else> <a href="#result0" class="accessibility_link" tabindex="0">{{$t('accessibility.main_content')}}</a> </div> <a href="#top_menu" class="accessibility_link" @click="$store.commit('toggleMenu')"> {{$t('accessibility.menu')}}</a> <v-divider vertical/> <v-menu allowOverflow: true offsetY v-model="dictMenuOpened"> <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.mdAndUp"> {{$t(`dicts.${$parent.lang}`)}} <v-icon right>{{ dictMenuOpened? 'expand_less' : 'expand_more'}}</v-icon> </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" @click="update_lang_form(item.tag)"> <v-list-item-icon v-if="$parent.lang == item.tag"><v-icon color="primary">radio_button_checked</v-icon></v-list-item-icon> <v-list-item-icon v-else><v-icon>radio_button_unchecked</v-icon></v-list-item-icon> <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 class="dict-parentheses" v-if="(get_lang()=='bm,nn')"> ({{["bokmål","nynorsk","bokmål, nynorsk"][data.item.lang-1]}}) </span> </span> </template> </v-combobox> </div> </template> <script> export default { data: function() { return { loading: false, items: [], search: null, select: this.$route.query? this.$route.query.q : null, suggesting: null, menuDialog: false, dictMenuOpened: 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 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.search!=this.$route.query.q && !this.items[0]) { this.submit({q: this.search, match: this.search, time: Date.now()}) } else { this.$parent.reload_params() } }, 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 let self = this let params = {q, dict: self.get_lang(), n: 6, dform: 'int', meta: 'n', include: "e", wc: self.$parent.pos_selected} this.$parent.api.get('api/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})) } 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}] } } }) }, 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() } } document.addEventListener("keyup", e => { if (e.key !== "/") return; if (e.altKey || e.ctrlKey || e.metaKey); if (/^(?:input|textarea|select)$/i.test(e.target.tagName)) return; this.$refs.autocomplete.$refs.input.focus() }); } } </script> <style scoped> .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>