Skip to content
Snippets Groups Projects
Commit fc28f5cd authored by Ole Voldsæter's avatar Ole Voldsæter
Browse files

visning av flere artikler samtidig

parent 7a59dfe1
No related branches found
No related tags found
No related merge requests found
......@@ -5,23 +5,26 @@
<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>
<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" @search-hit-click="search_hit_click" v-show="! waiting" />
<Article :key="article_key" :article="article" @article-click="article_link_click" />
<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)">
<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>
......@@ -75,14 +78,11 @@ window.onpopstate = function (event) {
}
}
function navigate_to_article(self, article_id, origin_article, origin_lemma) {
if (origin_article) {
self.$plausible.trackEvent('internal link incoming', {props: {origin: `/${self.$route.params.lang}/${origin_article}/${origin_lemma || '_'}`}})
}
axios.get(self.api_pref + '' + article_id)
function navigate_to_article(self) {
axios.get(api_endpoint + '/' + self.$route.params.lang + '/article/' + self.$route.params.id)
.then(function(response){
self.article = response.data
self.search_results = []
})
.catch(function(error){
if (error.response && error.response.status == 404) {
......@@ -100,7 +100,7 @@ function navigate_to_article(self, article_id, origin_article, origin_lemma) {
})
.then(function(response){
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang}, '')
history.replaceState({article: self.article, search_results: [], lang: self.lang}, '')
})
}
......@@ -113,6 +113,15 @@ function navigate_to_search(self, query) {
})
}
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}, '')
})
}
export default {
name: 'app',
data: function() {
......@@ -139,9 +148,15 @@ export default {
return new Promise(resolve => {
return axios.get(self.api_pref + 'suggest?q=' + q).then(
function(response) {
let hits = q.length ? [{}] : []
hits = hits.concat(response.data)
resolve(hits.map(h => Object.assign(h, {q: q})))
let hits = q.length ? [{q: q, label: q + ' (alt)'}] : []
response.data.forEach((item, i) => {
if (hits[0].label != item.match) {
hits.splice(0, 0, {q: q, label: item.match, articles: []})
}
hits[0].articles.push(item)
});
hits.reverse()
resolve(hits)
})
})
}
......@@ -157,10 +172,10 @@ export default {
select_result: function(event) {
this.$refs.search.value = ''
document.activeElement.blur()
if(event.body){
this.$router.push('/' + event.dictionary + '/' + event.article_id + '/' + event.match)
this.search_results = []
this.article = event
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}})
}else{
......@@ -175,11 +190,9 @@ export default {
this.article_key++
history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang}, '')
}else{
let current_art_id = this.article.article_id
let current_lemma = this.article.lemmas[0].lemma
this.article = {lemmas: [], body:{pronunciation: [], definitions: [], etymology: []}}
this.waiting_for_articles = true
navigate_to_article(this, item.article_id, current_art_id, current_lemma)
navigate_to_article(this)
}
},
search_hit_click: function(article){
......@@ -202,22 +215,18 @@ export default {
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)
this.lang = 'bob,nob'
if(this.$route.name == 'word') {
navigate_to_word(this, this.$route.params.word)
}
else if(this.$route.params.id){
else if(this.$route.name == 'lookup'){
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>
......@@ -249,7 +258,7 @@ main {
background-attachment: fixed;
}
header, #search_results, #spinner, article, footer, div.welcome {
header, #search_results, #spinner, #single_article_container, footer, div.welcome {
padding-left: calc((100vw - 1000px) / 2);
padding-right: calc((100vw - 1000px) / 2);
background-image: url('./assets/beta.png');
......@@ -333,6 +342,15 @@ footer {
padding-bottom: 20px;
}
.search_container {
display: flex;
flex-direction: row;
}
li.suggestion {
font-weight: bold;
}
footer p {
padding-left: 20px;
padding-right: 20px;
......@@ -350,4 +368,24 @@ footer p {
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%;
}
</style>
src/assets/down_arrow.png

319 B

<template>
<article v-show="article.lemmas.length || article.error">
<Header :lemmas="article.lemmas" />
<Header :lemmas="article.lemmas" :dictionary="dictionary" />
<section v-if="! article.error && article.body.pronunciation && article.body.pronunciation.length">
<h3>Uttale</h3>
<ul>
<DefElement v-for="(element, index) in article.body.pronunciation" :key="index" :body='element' @article-click="article_link_click" />
<DefElement v-for="(element, index) in article.body.pronunciation" :dictionary="dictionary" :key="index" :body='element' @article-click="article_link_click" />
</ul>
</section>
<section v-if="! article.error && article.body.etymology && article.body.etymology.length">
<h3>Etymologi</h3>
<ul>
<DefElement v-for="(element, index) in article.body.etymology" :key="index" :body='element' @article-click="article_link_click" />
<DefElement v-for="(element, index) in article.body.etymology" :dictionary="dictionary" :key="index" :body='element' @article-click="article_link_click" />
</ul>
</section>
<section v-if="! article.error">
<h3>Definisjoner</h3>
<ol>
<Definition v-for="definition in article.body.definitions" :level="1" :key="definition.id" :body='definition' @article-click="article_link_click" />
<Definition v-for="definition in article.body.definitions" :dictionary="dictionary" :level="1" :key="definition.id" :body='definition' @article-click="article_link_click" />
</ol>
</section>
<section v-if="article.error">
......@@ -36,6 +36,11 @@ export default {
props: {
article: Object
},
computed: {
dictionary: function() {
return this.article.dictionary || this.$route.params.lang
}
},
components: {
DefElement,
Definition,
......@@ -72,6 +77,10 @@ li.level1.definition {
list-style: upper-alpha;
}
li.level2.definition {
list-style: decimal;
}
li.level3.definition {
list-style: lower-alpha;
}
......
<template>
<li class="compound_list">
<ul>
<DefElement :body="body.intro" v-if="body.intro" />
<DefElement :body="body.intro" v-if="body.intro" :dictionary="dictionary" />
<li :key="index" v-for="(item, index) in body.elements">
<router-link :to="item.article_id + (item.definition_id ? '#def'+item.definition_id : '')" @click.native="article_link_click(item)">
<router-link :to="'/' + dictionary + '/' + item.article_id + (item.definition_id ? '#def'+item.definition_id : '')" @click.native="article_link_click(item)">
<span class="homograph" :key="index">{{item.lemmas[0].hgno ? String.fromCharCode(0x215f + item.lemmas[0].hgno) : ''}}</span>
{{item.lemmas[0].lemma}};
</router-link>
......@@ -18,7 +18,8 @@ import DefElement from './DefElement.vue'
export default {
name: 'CompoundList',
props: {
body: Object
body: Object,
dictionary: String
},
components: {
DefElement
......
......@@ -21,11 +21,12 @@ export default {
tag: {
type: String,
default: 'li'
}
},
dictionary: String
},
computed: {
unparsed: function(){
let lang = this.$route.params.lang
let lang = this.dictionary
let path_lemma = this.$route.params.lemma
return this.body.items.map(
function(item){
......@@ -34,7 +35,7 @@ export default {
type: item.type_,
html: '',
link_text: item.word_form || item.lemmas[0].lemma,
ref: (path_lemma ? '../' : '') + item.article_id + '/' + (item.word_form || item.lemmas[0].lemma) + (item.definition_id ? '#def' + item.definition_id : ''),
ref: '/' + lang + '/' + item.article_id + '/' + (item.word_form || item.lemmas[0].lemma) + (item.definition_id ? '#def' + item.definition_id : ''),
article_id: item.article_id,
definition_id: item.definition_id,
definition_order: item.definition_order
......
<template>
<li :class="['definition', 'level'+level]" :ref="'def' + body.id" :id="'def' + body.id">
<ul class="explanation">
<li :is="element_wrapper.template" :body="element_wrapper.element" v-for="(element_wrapper, index) in template_name_added" :key="index" @article-click="article_link_click">{{element_wrapper.element}}</li>
<li :is="element_wrapper.template" :body="element_wrapper.element" :dictionary="element_wrapper.dictionary" v-for="(element_wrapper, index) in template_name_added" :key="index" @article-click="article_link_click">{{element_wrapper.element}}</li>
</ul>
<div :is="level < 3 ? 'ol' : 'ul'" class="sub_definitions" v-if="subdefs.length">
<Definition :level="level+1" :body="subdef" v-for="(subdef, index) in subdefs" :key="index" @article-click="article_link_click" />
<Definition :level="level+1" :body="subdef" v-for="(subdef, index) in subdefs" :dictionary="dictionary" :key="index" @article-click="article_link_click" />
</div>
<ul class="sub_articles" v-if="subArticles.length">
<SubArticle :body="subart" v-for="(subart, index) in subArticles" :key="index" @article-click="article_link_click" />
<SubArticle :body="subart" v-for="(subart, index) in subArticles" :dictionary="dictionary" :key="index" @article-click="article_link_click" />
</ul>
</li>
</template>
......@@ -22,7 +22,8 @@ var Definition = {
name: 'Definition',
props: {
body: Object,
level: Number
level: Number,
dictionary: String
},
components: {
DefElement,
......@@ -33,6 +34,7 @@ var Definition = {
},
computed: {
template_name_added: function(){
let dictionary = this.dictionary
return this.body.elements.filter(el => ! ['definition', 'sub_article'].includes(el.type_)).map(
function(element){
return {
......@@ -41,7 +43,8 @@ var Definition = {
'example': 'Example',
'compound_list': 'CompoundList'
}[element.type_] || 'li',
'element': element
'element': element,
'dictionary': dictionary
}
})
},
......
<template>
<li class="example">
<DefElement tag="q" :body="body.quote" @article-click="article_link_click" /><span v-if="body.explanation && body.explanation.content.length"> - </span>
<DefElement tag="span" :body="body.explanation" v-if="body.explanation && body.explanation.content.length" @article-click="article_link_click" />
<DefElement tag="q" :body="body.quote" @article-click="article_link_click" :dictionary="dictionary" /><span v-if="body.explanation && body.explanation.content.length"> - </span>
<DefElement tag="span" :body="body.explanation" v-if="body.explanation && body.explanation.content.length" @article-click="article_link_click" :dictionary="dictionary" />
</li>
</template>
......@@ -11,7 +11,8 @@ import DefElement from './DefElement.vue'
export default {
name: 'Example',
props: {
body: Object
body: Object,
dictionary: String
},
components: {
DefElement
......
......@@ -11,6 +11,7 @@
<component v-for="grp in Object.keys(lemma.inflection_groups)"
:key="grp.replace('/', '_')"
:is="grp.replace('/', '_')"
:dictionary="dictionary"
:standardisations="lemma.inflection_groups[grp]"></component>
</div>
</div>
......@@ -36,7 +37,8 @@ import VERB_sPass from './inflection/VerbSPass.vue'
export default {
name: 'Header',
props: {
lemmas: Array
lemmas: Array,
dictionary: String
},
computed: {
group_list: function() {
......
......@@ -4,25 +4,24 @@
<div class="flex-container">
<ul class="hits" v-if="results_bob.length">
<li><h4>Bokmål</h4></li>
<Preview v-for="(result, index) in results_bob" :key="index" :searchHit="result" @click.native="article_link_click(result)">
</Preview>
<li class="article_container" v-for="(result, index) in results_bob" :key="index">
<Article :article="result" @article-click="article_link_click">
</Article>
</li>
</ul>
<ul class="hits" v-if="results_nob.length">
<li><h4>Nynorsk</h4></li>
<Preview v-for="(result, index) in results_nob" :key="index" :searchHit="result" @click.native="article_link_click(result)">
</Preview>
</ul>
<ul class="hits" v-if="results_norsk.length">
<li><h4>Norsk Ordbok</h4></li>
<Preview v-for="(result, index) in results_norsk" :key="index" :searchHit="result" @click.native="article_link_click(result)">
</Preview>
<li class="article_container" v-for="(result, index) in results_nob" :key="index">
<Article :article="result" @article-click="article_link_click">
</Article>
</li>
</ul>
</div>
</section>
</template>
<script>
import Preview from './Preview.vue'
import Article from './Article.vue'
export default {
name: 'SearchResults',
......@@ -36,19 +35,15 @@ export default {
},
results_nob: function(){
return this.hits.filter(hit => hit.dictionary == 'nob')
},
results_norsk: function(){
return this.hits.filter(hit => hit.dictionary == 'norsk_ordbok')
}
},
methods: {
article_link_click: function(result) {
this.$router.push('/' + result.dictionary + '/' + result.article_id)
this.$emit('search-hit-click', result)
article_link_click: function(item) {
this.$emit('article-click', item)
}
},
components: {
Preview
Article
}
}
......@@ -71,6 +66,8 @@ export default {
.hits {
margin-top:0px;
margin-left: 20px;
margin-right: 20px;
}
.flex-container {
......@@ -84,4 +81,8 @@ export default {
.flex-container h4 {
margin: 0px;
}
li.article_container {
border-bottom: solid 2px #560027;
}
</style>
<template>
<li class="sub_article">
<span class="sub_article_header">
<router-link :to="link_prefix + body.article_id" @click.native="article_link_click(body)">
<router-link :to="'/' + dictionary + '/' + body.article_id" @click.native="article_link_click(body)">
{{body.lemmas[0]}}
</router-link>
</span>
<ul>
<DefElement :body="body.intro" v-if="body.intro" @article-click="article_link_click" />
<Definition :level="9" :body="body.article.body.definitions[0]" @article-click="article_link_click" />
<DefElement :body="body.intro" v-if="body.intro" :dictionary="dictionary" @article-click="article_link_click" />
<Definition :level="9" :body="body.article.body.definitions[0]" :dictionary="dictionary" @article-click="article_link_click" />
</ul>
</li>
</template>
......@@ -18,7 +18,8 @@ import DefElement from './DefElement.vue'
export default {
name: 'SubArticle',
props: {
body: Object
body: Object,
dictionary: String
},
components: {
DefElement
......
......@@ -32,14 +32,15 @@
export default {
name: "ADJ",
props: {
standardisations: Array
standardisations: Array,
dictionary: String
},
computed: {
i18n: function() {
return {
bob: ['Entall', 'Flertall', 'Hun', 'Intet', 'estemt'],
nob: ['Eintal', 'Fleirtal', 'Ho', 'Inkje', 'unden']
}[this.$route.params.lang]
}[this.dictionary]
}
}
}
......
......@@ -34,14 +34,15 @@
export default {
name: "ADJ_masc_fem",
props: {
standardisations: Array
standardisations: Array,
dictionary: String
},
computed: {
i18n: function() {
return {
bob: ['Entall', 'Flertall', 'Hun', 'Intet', 'estemt'],
nob: ['Eintal', 'Fleirtal', 'Ho', 'Inkje', 'unden']
}[this.$route.params.lang]
}[this.dictionary]
}
}
}
......
......@@ -20,14 +20,15 @@
export default {
name: "NOUN",
props: {
standardisations: Array
standardisations: Array,
dictionary: String
},
computed: {
i18n: function() {
return {
bob: ['Entall', 'Flertall', 'Ubestemt', 'Bestemt', {Masc: ['mask.', 'en'], Fem: ['fem.', 'ei'], Neuter: ['nøytr.', 'et']}],
nob: ['Eintal', 'Fleirtal', 'Ubunden', 'Bunden', {Masc: ['mask.', 'ein'], Fem: ['fem.', 'ei'], Neuter: ['nøytr.', 'eit']}]
}[this.$route.params.lang]
}[this.dictionary]
}
}
}
......
......@@ -36,14 +36,15 @@
export default {
name: "VERB",
props: {
standardisations: Array
standardisations: Array,
dictionary: String
},
computed: {
i18n: function() {
return {
bob: ['hun', 'Intet', 'Bestemt', 'Flertall'],
nob: ['ho', 'Inkje', 'Bunden', 'Fleirtal']
}[this.$route.params.lang]
}[this.dictionary]
}
}
}
......
......@@ -19,6 +19,10 @@ const router = new VueRouter({
name: 'root',
path: '/',
component: App }, // No props, no nothing
{
name: 'word',
path: '/:lang/w/:word'
},
{
name: 'lookup',
path: '/:lang/:id(\\d+)/:lemma?',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment