Something went wrong on our end
Forked from
Språksamlingane / beta.ordbok.uib.no
2045 commits behind the upstream repository.
-
Ole Voldsæter authoredOle Voldsæter authored
App.vue 10.34 KiB
<template>
<main id="app">
<header>
<h1>Søk i Ordbøkene</h1>
<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>
<autocomplete :debounceTime="100" :auto-select="true" :search="search" @submit="select_result" placeholder="søk..." ref="search">
<template #result="{result, props}">
<Preview v-bind="props" :searchHit="result">
</Preview>
</template>
</autocomplete>
<span class="lang-select-intro">SØK PÅ</span>
<input type="radio" id="radio_both" value="bob,nob" v-model="lang">
<label for="radio_both">Begge</label>
<input type="radio" id="radio_bob" value="bob" v-model="lang">
<label for="radio_bob">Bokmål</label>
<input type="radio" id="radio_nob" value="nob" v-model="lang">
<label for="radio_nob">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" v-show="! waiting" />
<Article :key="article_key" :article="article" @article-click="article_link_click" />
<div class="welcome" v-show="! (article.error || article.lemmas.length || search_results.length || waiting)">
<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>
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
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>
<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>
</main>
</template>
<script>
import axios from "axios"
import entities from './utils/entities.js'
import Article from './components/Article.vue'
import Preview from './components/Preview.vue'
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'
axios.interceptors.request.use(function (config) {
config.headers["x-api-key"] = "ZkYiyRVXxH86ijsvhx3cH4SY5Iik2ijI3BKVJGMm"
return config;
}, function (error) {
return Promise.reject(error);
});
window.onpopstate = function (event) {
if (event.state) {
// eslint-disable-next-line
app.__vue__._data.article = event.state.article
// eslint-disable-next-line
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, article_id) {
axios.get(self.api_pref + '' + article_id)
.then(function(response){
self.article = response.data
})
.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){
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: self.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
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang}, '')
})
}
export default {
name: 'app',
data: function() {
return {
article_key: 0,
search_results: [],
lang: 'bob,nob',
waiting_for_articles: true,
waiting_for_bob_metadata: true,
waiting_for_nob_metadata: true,
article: {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
}
},
computed: {
waiting: function() {
return this.waiting_for_articles || this.waiting_for_bob_metadata || this.waiting_for_nob_metadata
},
api_pref: function() {
return api_endpoint + '/' + this.lang + '/article/'
},
search: function() {
let self = this
return function(q) {
return new Promise(resolve => {
return axios.get(self.api_pref + 'suggest?q=' + q).then(
function(response) {
let hits = q.length ? [{q: q}] : []
hits = hits.concat(response.data)
resolve(hits)
})
})
}
}
},
components: {
Article,
Autocomplete,
SearchResults,
Preview
},
methods: {
select_result: function(event) {
this.$refs.search.value = ''
document.activeElement.blur()
if(event.body){
this.$router.push('/' + event.dictionary + '/' + event.article_id)
this.search_results = []
this.article = event
history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang}, '')
}else{
this.waiting_for_articles = true
this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
this.$router.push(`/search?q=${event.q}&lang=${this.lang}`)
navigate_to_search(this, event.q)
}
},
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}, '')
}else{
this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
this.waiting_for_articles = true
navigate_to_article(this, item.article_id)
}
},
search_hit_click: function(article){
this.search_results = []
this.article = article
history.replaceState({article: article, search_results: [], lang: this.lang}, '')
}
},
mounted: function(){
console.log(document.referrer)
let self = this
axios.get(api_endpoint + '/bob').then(function(response){
let concepts = response.data.concepts
entities.bob = concepts
self.waiting_for_bob_metadata = false
})
axios.get(api_endpoint + '/nob').then(function(response){
let concepts = response.data.concepts
entities.nob = concepts
self.waiting_for_nob_metadata = false
})
this.lang = this.$route.params.lang || this.$route.query.lang || 'bob,nob'
if(this.$route.query.q) {
navigate_to_search(this, this.$route.query.q)
}
else if(this.$route.params.id){
navigate_to_article(this, this.$route.params.id)
}
else {
this.waiting_for_articles = false
history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang}, '')
}
},
watch: {
$route() {
this.lang = this.$route.params.lang || this.$route.query.lang || 'bob,nob'
}
}
}
</script>
<style>
@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');
#app {
font-family: 'Noto Sans', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
body {
margin: 0px;
}
h1 {
font-family: Inria Serif;
font-size: 36px;
color: #560027;
}
main {
background-image: url('./assets/beta.png');
background-repeat: no-repeat;
background-attachment: fixed;
}
header, #search_results, #spinner, article, footer, div.welcome {
padding-left: calc((100vw - 1000px) / 2);
padding-right: calc((100vw - 1000px) / 2);
background-image: url('./assets/beta.png');
background-repeat: no-repeat;
background-attachment: fixed;
}
header {
padding-top: 60px;
padding-bottom: 20px;
background-color: #FDF4F5;
}
section#search_results, article {
background-color: #FFFFFF;
}
div.welcome {
font-size: 20px;
}
.top {
color: #560027;
font-weight: bold;
font-size: smaller;
border-bottom: solid;
border-color: #BC477B;
}
.mission-statement {
font-size: 24px;
}
.show {
display: block;
}
.hide {
display: none;
}
.autocomplete {
width: 25em;
border-bottom: solid #BC477B;
border-radius: 0px;
margin-bottom: 8px;
}
.autocomplete-result-list {
max-height: 500px;
}
input[type=radio] {
display: none;
}
input[type=radio]:checked + label {
border: solid 1px #560027;
box-shadow: inset 0 0 2px #000000;
}
label {
margin: 4px 4px 4px 8px;
border: solid 1px #FDF4F5;
border-radius: 4px;
padding: 2px 8px 2px 8px;
background-color: #DDDDDD
}
.lang-select-intro {
font-size: smaller;
font-weight: bold;
}
footer {
font-size: smaller;
display: flex;
flex-direction: row;
background-color: #570B27;
color: #ffffff;
padding-bottom: 20px;
}
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;
}
</style>