Something went wrong on our end
-
Henrik Askjer authoredHenrik Askjer authored
Autocomplete.vue 7.19 KiB
<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 {
props: {
api: Function,
},
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}
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}))
}
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()
}
}
}
}
</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>