<template> <main id="app"> <img alt="Vue logo" src="./assets/logo.png"> <header> <autocomplete :debounceTime="50" :auto-select="true" :search="search" :get-result-value="result_view" @submit="select_result" placeholder="søk..." ref="search"></autocomplete> <input type="radio" id="radio_nob" value="nob" v-model="lang"> <label for="radio_nob">Bokmål</label> <input type="radio" id="radio_nno" value="nno" v-model="lang"> <label for="radio_nno">Nynorsk</label> </header> <img id="spinner" :class="waiting ? 'show' : 'hide'" src="./assets/spinner.gif" alt="Venter på innhold" /> <SearchResults :hits="search_results" :lang="lang" @search-hit-click="search_hit_click" /> <Article :article="article" @article-click="article_link_click" /> </main> </template> <script> import axios from "axios" import Article from './components/Article.vue' import SearchResults from './components/SearchResults.vue' import Autocomplete from '@trevoreyre/autocomplete-vue' import '@trevoreyre/autocomplete-vue/dist/style.css' var api_endpoint = 'https://ordbok-dev.aws.uib.no/cache/article' window.onpopstate = function (event) { if (event.state) { app.__vue__._data.article = event.state.article app.__vue__._data.search_results = event.state.search_results } } export default { name: 'app', data: function() { return { search_results: [], lang: 'nob', waiting: true, article: {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}, result_view: function(result) { if (result._source) return result._source.lemmas.map(x => x.lemma).join(', ') else return 'Alle søkeresultater...' } } }, computed: { search: function() { let self = this return function(q) { return new Promise(resolve => { return axios.post(api_endpoint + '/' + self.lang + '/_search/', { "suggest": { "suggest" : { "prefix" : q, "completion" : { "field" : "suggest" } } } }).then(function(response) { let hits = response.data.suggest.suggest[0].options if(q.length) hits = hits.concat({q: q}) resolve(hits) }) }) } } }, components: { Article, Autocomplete, SearchResults }, methods: { select_result: function(event) { this.$refs.search.value = '' document.activeElement.blur() if(event._source){ this.search_results = [] this.article = event._source history.pushState({article: this.article, search_results: this.search_results}, '', '/' + this.lang + '/' + event._id) }else{ var self = this self.waiting = true self.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}} axios.get(api_endpoint + '/' + self.lang + '/_search?q=' + event.q) .then(function(response){ self.search_results = response.data.hits.hits history.pushState({article: self.article, search_results: self.search_results}, '', '/' + self.lang + '/_search?q=' + event.q) self.waiting = false }) } }, article_link_click: function(item) { var self = this self.waiting = true axios.get(api_endpoint + '/' + self.lang + '/' + item.article_id) .then(function(response){ self.article = response.data._source self.waiting = false history.replaceState({article: self.article, search_results: self.search_results}, '') }) }, search_hit_click: function(article){ this.search_results = [] this.article = article history.replaceState({article: article, search_results: []}, '') } }, mounted: function(){ this.lang = this.$route.params.lang || 'nob' var self = this; if(this.$route.query.q) { axios.get(api_endpoint + '/' + self.lang + '/_search?q=' + self.$route.query.q) .then(function(response){ self.search_results = response.data.hits.hits self.waiting = false }) } else if(this.$route.params.id){ axios.get(api_endpoint + '/' + self.lang + '/' + self.$route.params.id) .then(function(response){ self.article = response.data._source self.waiting = false history.replaceState({article: self.article, search_results: self.search_results}, '') }) } else { this.waiting = false } }, watch: { $route(to, from) { this.lang = this.$route.params.lang || 'nob' } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; margin-top: 60px; margin-left: 30%; margin-right: 10%; } .show { display: block; } .hide { display: none; } .autocomplete { width: 25em; } </style>