Skip to content
Snippets Groups Projects
Autocomplete.vue 6.89 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="{rounded: 'b-xl', maxHeight: $vuetify.breakpoint.name === 'xs' ? 190 : 500, transition: 'fade-transition', allowOverflow: true}"
        prepend-inner-icon="search"
        return-object
        :class="($refs.autocomplete && $refs.autocomplete.hasDisplayedItems && $refs.autocomplete.isMenuActive && 'rounded-t-xl') || 'rounded-xl'"
        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('toggle', 'menuOpen')"
                   aria-label="Hopp til toppmeny"
                   
               >
            Åpne toppmeny</a>
        
                
        <v-menu allowOverflow: true offsetY>
        <template v-slot:activator="{ on, attrs }">
        <v-btn min-width="0px" 
               v-bind="attrs" 
               v-on="on" 
               plain
               depressed color = "primary" text @click.native="items=[]">
          <span v-if="!$vuetify.breakpoint.smAndDown">
          {{$t(`dicts.${$parent.lang}`)}}
          </span><span v-if="$vuetify.breakpoint.smAndDown">{{$parent.lang}}</span><v-icon>expand_more</v-icon></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="$parent.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>
import Menu from './Menu.vue'

  export default {
    props: {
      api: Function,
    },
    data: function() {
      return {
        loading: false,
        items: [],
        inflection_suggestions: 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
          if (this.inflection_suggestions && this.inflection_suggestions.length) {
            item.inflection_suggestions = this.inflection_suggestions
          }
            
          this.submit(item)
          }
        }
      },
      $route (to, from) {
        this.select = to.query.q
      }
    },
    methods: {
      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 = []
                          suggestions = response.data.a.w.map(item => ({q: q, match: item[0], time: time, lang: [item[1]], w: true}))
                          self.inflection_suggestions = response.data.a.b
                          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}]
                          }
                          

                        }
                      self.loading = false
                    })

        }


      },
      submit(item) {
          this.$emit('submit', item)
          let self = this

          setTimeout(() => {
          if (self.$vuetify.breakpoint.mdAndUp) self.$refs.autocomplete.$refs.input.select()
          else self.$refs.autocomplete.$refs.input.blur()
          this.suggesting = false
          }, 1)

      }
    },
    mounted: function() {
      if (! this.$route.hash) {
        window.scrollTo(0,0)
        if(this.$vuetify.breakpoint.mdAndUp) {
          this.$refs.autocomplete.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;
    padding-left: 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>