Skip to content
Snippets Groups Projects
App.vue 11.6 KiB
Newer Older
Ole Voldsæter's avatar
Ole Voldsæter committed
      <span class="top">EID AV UNIVERSITETET I BERGEN OG SPRÅKRÅDET</span>
      <p class="mission-statement">Bokmålsordboka og Nynorskordboka er dei einaste fritt tilgjengelege ordbøkene som gjer svar på korleis ord skal skrivast og bøyast
      i norsk i tråd med gjeldande rettskriving.</p>
      <div class="search_container">
        <autocomplete :debounceTime="100" :auto-select="true" :search="search"  @submit="select_result" placeholder="søk..." ref="search">
          <template #result="{result, props}">
            <li class="suggestion" v-bind="props">{{result.label}}</li>
          </template>
        </autocomplete>
        <div class="lang_select_container">
          <select class="lang_select" name="lang"  v-model="lang">
            <option value="bob,nob">Begge målformer </option>
            <option value="bob">Bokmål</option>
            <option value="nob">Nynorsk</option>
          </select>
        </div>
      </div>
    </header>
    <img id="spinner" :class="waiting ? 'show' : 'hide'" src="./assets/spinner.gif" alt="Venter på innhold" />
    <SearchResults :hits="search_results" :lang="lang" @article-click="article_link_click" v-show="! waiting" />
    <div id="single_article_container">
      <Article :key="article_key" :article="article" @article-click="article_link_click" />
    </div>
    <div class="welcome" v-show="! (article.error || article.lemmas.length || search_results.length || waiting)">
Ole Voldsæter's avatar
Ole Voldsæter committed
      <p>Bør ordet <em>crew</em> inn i dei norske standardordbøkene? Korleis definerar vi <em>c-kjendis</em>, og korleis
        bøyar vi eigentleg <em>abaya</em> på nynorsk - er det fleire <em>abayaer</em> eller <em>abayaar</em>? Blir <em>en vegetar</em>
Ole Voldsæter's avatar
Ole Voldsæter committed
        framleis brukt som ein rettskrivingsvariant av <em>en vegetarianer</em> i bokmål? Og bør <em>tjuesesse</em> bli eit opplsagsord i Bokmålsordboka
Ole Voldsæter's avatar
Ole Voldsæter committed
        når ein tilsvarande ordartikklel allereie finst i Nynorskordboka?
      </p>
      <p>Slike spørsmål skal ei gruppe ordbokredaktørar ved UiB arbeide med i den mest omfattande innhaldsrevisjonen av Bokmålsordboka og Nynorskordboka
      på over 30 år.</p>
    </div>
Ole Voldsæter's avatar
Ole Voldsæter committed
    <footer>
      <div>
        <img id="uiblogo" src="./assets/uib-logo.svg" alt="">
        <p>Ordbøkene eies av Universitetet i Bergen sammen med Språkrådet, under ledelse frå Språksamlingane</p>
        <p><strong>REDAKTØRANSVAR: HF-FAKULTETET VED UiB</strong></p>
      </div>
      <div>
        <img id="srlogo" src="./assets/Sprakradet_logo_neg.png" alt="">
        <p> Språkrådet er statens fagorgan i språkspørsmål og følger opp den norske språkpolitikken på oppdrag fra Kulturdepartementet.
        Språkrådet forvalter rettskrivningen i nynorsk og bokmål.</p>
      </div>
    </footer>
Ole Voldsæter's avatar
Ole Voldsæter committed
</template>

<script>
Ole Voldsæter's avatar
Ole Voldsæter committed
import axios from "axios"
import entities from './utils/entities.js'
Ole Voldsæter's avatar
Ole Voldsæter committed
import Article from './components/Article.vue'
Ole Voldsæter's avatar
Ole Voldsæter committed
import Preview from './components/Preview.vue'
Ole Voldsæter's avatar
Ole Voldsæter committed
import SearchResults from './components/SearchResults.vue'
import Autocomplete from '@trevoreyre/autocomplete-vue'
import '@trevoreyre/autocomplete-vue/dist/style.css'
var api_endpoint = 'https://beta.ordbok.uib.no/api/dict'
Ole Voldsæter's avatar
Ole Voldsæter committed

axios.interceptors.request.use(function (config) {
    config.headers["x-api-key"] = "ZkYiyRVXxH86ijsvhx3cH4SY5Iik2ijI3BKVJGMm"
    return config;
  }, function (error) {
    return Promise.reject(error);
  });

Ole Voldsæter's avatar
Ole Voldsæter committed
window.onpopstate = function (event) {
  if (event.state) {
    // eslint-disable-next-line
Ole Voldsæter's avatar
Ole Voldsæter committed
    app.__vue__._data.article = event.state.article
    // eslint-disable-next-line
Ole Voldsæter's avatar
Ole Voldsæter committed
    app.__vue__._data.search_results = event.state.search_results
    // eslint-disable-next-line
    app.__vue__._data.lang = event.state.lang
function navigate_to_article(self) {
  axios.get(api_endpoint + '/' + self.$route.params.lang + '/article/' + self.$route.params.id)
Ole Voldsæter's avatar
Ole Voldsæter committed
    self.article = response.data
    self.search_results = []
  })
  .catch(function(error){
    if (error.response && error.response.status == 404) {
      self.article = {
        lemmas: [],
        error: "Vi har ingen artikkel med id " + article_id
      }
    } else {
      self.article = {
        lemmas: [],
        error: "Noe gikk galt..."
      }
      console.log(error)
    }
  })
  .then(function(response){
    history.replaceState({article: self.article, search_results: [], lang: self.lang}, '')
  })
}

function navigate_to_search(self, query) {
  axios.get(self.api_pref + 'search?q=' + query)
  .then(function(response){
    self.search_results = response.data
    history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang}, '')
  })
}

function navigate_to_word(self, word) {
  axios.get(self.api_pref + 'suggest?q=' + word)
  .then(function(response){
    self.search_results = response.data.filter(result => result.match.length == word.length)
    self.waiting_for_articles = false
    history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang}, '')
  })
}

Ole Voldsæter's avatar
Ole Voldsæter committed
export default {
  name: 'app',
  data: function() {
    return {
Ole Voldsæter's avatar
Ole Voldsæter committed
      search_results: [],
Ole Voldsæter's avatar
Ole Voldsæter committed
      lang: 'bob,nob',
      waiting_for_metadata: true,
Ole Voldsæter's avatar
Ole Voldsæter committed
      article: {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
Ole Voldsæter's avatar
Ole Voldsæter committed
  computed: {
      return this.waiting_for_articles || this.waiting_for_metadata
    api_pref: function() {
      return api_endpoint + '/' + this.lang + '/article/'
    },
Ole Voldsæter's avatar
Ole Voldsæter committed
    search: function() {
      let self = this
      return function(q) {
                return new Promise(resolve => {
                  return axios.get(self.api_pref + 'suggest?q=' + q).then(
Ole Voldsæter's avatar
Ole Voldsæter committed
                                        let hits = []
                                        response.data.forEach((item, i) => {
Ole Voldsæter's avatar
Ole Voldsæter committed
                                          if (! hits[0] || hits[0].label != item.match) {
                                            hits.splice(0, 0, {q: q, label: item.match, articles: []})
                                          }
                                          hits[0].articles.push(item)
                                        });
                                        hits.reverse()
Ole Voldsæter's avatar
Ole Voldsæter committed
                                        resolve(hits.slice(0, 10))
Ole Voldsæter's avatar
Ole Voldsæter committed
  components: {
Ole Voldsæter's avatar
Ole Voldsæter committed
    SearchResults,
    Preview
  },
  methods: {
    select_result: function(event) {
      this.$refs.search.value = ''
      document.activeElement.blur()
      if(event.articles){
        this.$router.push('/' + this.lang + '/w/' + event.label)
        this.search_results = event.articles
        this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
        history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang}, '')
        this.$plausible.trackEvent('dropdown selection', {props: {query: event.q, dictionary: event.dictionary, match: event.match}})
Ole Voldsæter's avatar
Ole Voldsæter committed
      }else{
        this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
        this.$router.push(`/search?q=${event.q}&lang=${this.lang}`)
        navigate_to_search(this, event.q)
Ole Voldsæter's avatar
Ole Voldsæter committed
      }
Ole Voldsæter's avatar
Ole Voldsæter committed
    },
    article_link_click: function(item) {
      if (this.article.article_id == item.article_id){
        this.article_key++
        history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang}, '')
        this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
        navigate_to_article(this)
Ole Voldsæter's avatar
Ole Voldsæter committed
    },
    search_hit_click: function(article){
      this.search_results = []
      this.article = article
      history.replaceState({article: article, search_results: [], lang: this.lang}, '')
    }
  },
  mounted: function(){
    this.lang = 'bob,nob'

    Promise.all([
      axios.get(api_endpoint + '/bob').then(function(response){
        let concepts = response.data.concepts
        entities.bob = concepts
      }),
      axios.get(api_endpoint + '/nob').then(function(response){
        let concepts = response.data.concepts
        entities.nob = concepts
      })
    ]).then(function(_) {
      self.waiting_for_metadata = false
      if(self.$route.name == 'word') {
        navigate_to_word(self, self.$route.params.word)
      }
      else if(self.$route.name == 'lookup'){
        navigate_to_article(self, self.$route.params.id)
      }
      else {
        self.waiting_for_articles = false
        history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang}, '')
      }
    })
Ole Voldsæter's avatar
Ole Voldsæter committed
  }
}
</script>

<style>
Ole Voldsæter's avatar
Ole Voldsæter committed
  @import url('https://fonts.googleapis.com/css2?family=Inria+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap');
  @import url('https://fonts.googleapis.com/css2?family=Inria+Serif:ital,wght@0,400;0,700;1,400;1,700&family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap');

Ole Voldsæter's avatar
Ole Voldsæter committed
#app {
Ole Voldsæter's avatar
Ole Voldsæter committed
  font-family: 'Noto Sans', Helvetica, Arial, sans-serif;
Ole Voldsæter's avatar
Ole Voldsæter committed
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
Ole Voldsæter's avatar
Ole Voldsæter committed
}

body {
  margin: 0px;
}

h1 {
  font-family: Inria Serif;
  font-size: 36px;
  color: #560027;
}

Ole Voldsæter's avatar
Ole Voldsæter committed
main {
  background-image: url('./assets/beta.png');
  background-repeat: no-repeat;
  background-attachment: fixed;
}

header, #search_results, #spinner, #single_article_container, footer, div.welcome {
Ole Voldsæter's avatar
Ole Voldsæter committed
  padding-left: calc((100vw - 1000px) / 2);
  padding-right: calc((100vw - 1000px) / 2);
Ole Voldsæter's avatar
Ole Voldsæter committed
  background-image: url('./assets/beta.png');
  background-repeat: no-repeat;
Ole Voldsæter's avatar
Ole Voldsæter committed
  background-attachment: fixed;
header {
  padding-top: 60px;
  padding-bottom: 20px;
  background-color: #FDF4F5;
}

section#search_results, article {
div.welcome {
  font-size: 20px;
}

Ole Voldsæter's avatar
Ole Voldsæter committed
.top {
  color: #560027;
  font-weight: bold;
  font-size: smaller;
  border-bottom: solid;
  border-color: #BC477B;
}

.mission-statement {
  font-size: 24px;
Ole Voldsæter's avatar
Ole Voldsæter committed
}
.show {
  display: block;
}

.hide {
  display: none;
}

.autocomplete {
  width: 25em;
Ole Voldsæter's avatar
Ole Voldsæter committed
  border-bottom: solid  #BC477B;
  border-radius: 0px;
Ole Voldsæter's avatar
Ole Voldsæter committed
  margin-bottom: 8px;

.autocomplete-result-list {
  max-height: 500px;
}
Ole Voldsæter's avatar
Ole Voldsæter committed

input[type=radio] {
  display: none;
}

input[type=radio]:checked + label {
  border: solid 1px #560027;
  box-shadow: inset 0 0 2px #000000;
Ole Voldsæter's avatar
Ole Voldsæter committed
}

label {
  margin: 4px 4px 4px 8px;
Ole Voldsæter's avatar
Ole Voldsæter committed
  border-radius: 4px;
  padding: 2px 8px 2px 8px;
  background-color: #DDDDDD
}

.lang-select-intro {
  font-size: smaller;
  font-weight: bold;
}
Ole Voldsæter's avatar
Ole Voldsæter committed

footer {
  font-size: smaller;
  display: flex;
  flex-direction: row;
  background-color: #570B27;
  color: #ffffff;
  padding-bottom: 20px;
}

.search_container {
  display: flex;
  flex-direction: row;
}

li.suggestion {
  font-weight: bold;
}

Ole Voldsæter's avatar
Ole Voldsæter committed
footer p {
  padding-left: 20px;
  padding-right: 20px;
  margin: 0px;
}

#srlogo {
  height: 20px;
  padding-top: 50px;
  padding-left: 20px;
}

#uiblogo {
  height: 60px;
  padding: 10px;
  padding-left: 20px;
}

select.lang_select {
  appearance: none;
  background-color: transparent;
  border: none;
  padding: 0 1em 0 0;
  margin: 0;
  width: 100%;
  height: 100%;
  font-family: inherit;
  font-size: inherit;
  font-weight: bold;
  cursor: inherit;
  line-height: inherit;
  background-image: url('./assets/down_arrow.png');
	background-position: 98% center;
	background-repeat: no-repeat;
  background-size: 10%;
}

Ole Voldsæter's avatar
Ole Voldsæter committed
</style>