From aa2690ae8af09be9cdb368f9263004ffa7ddd2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Volds=C3=A6ter?= <ole.voldsater@uib.no> Date: Wed, 3 Feb 2021 13:28:30 +0100 Subject: [PATCH] re meta#254 ikon, debounce, loading, dense --- package-lock.json | 16 +++++++ package.json | 3 ++ src/components/Autocomplete.vue | 79 +++++++++++++++++++-------------- src/plugins/vuetify.js | 10 ++++- 4 files changed, 73 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 711fd65b..e5a49fab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4974,6 +4974,11 @@ "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", "dev": true }, + "debounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -8093,6 +8098,12 @@ "object-visit": "^1.0.0" } }, + "material-design-icons-iconfont": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/material-design-icons-iconfont/-/material-design-icons-iconfont-6.1.0.tgz", + "integrity": "sha512-wRJtOo1v1ch+gN8PRsj0IGJznk+kQ8mz13ds/nuhLI+Qyf/931ZlRpd92oq0IRPpZIb+bhX8pRjzIVdcPDKmiQ==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -12286,6 +12297,11 @@ "vue-style-loader": "^4.1.0" } }, + "vue-material-design-icons": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/vue-material-design-icons/-/vue-material-design-icons-4.11.0.tgz", + "integrity": "sha512-3Tyeqi9jtONQ/x8WkJqiBs4t5Bd5O1t7RdM/GIPKVYoVdaRy0oy3nbRjnMGyONBlqC/NpPjzhWeoZWUMEI04nA==" + }, "vue-plausible": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vue-plausible/-/vue-plausible-1.0.0.tgz", diff --git a/package.json b/package.json index 5c6f082a..67312573 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "dependencies": { "axios": "^0.19.2", "core-js": "^2.6.11", + "debounce": "^1.2.0", "vue": "^2.6.11", "vue-awesome": "^3.5.4", + "vue-material-design-icons": "^4.11.0", "vue-plausible": "^1.0.0", "vue-router": "^3.4.1", "vuetify": "^2.4.0" @@ -23,6 +25,7 @@ "babel-eslint": "^10.1.0", "eslint": "^5.16.0", "eslint-plugin-vue": "^5.0.0", + "material-design-icons-iconfont": "^6.1.0", "sass": "^1.32.0", "sass-loader": "^10.0.0", "vue-cli-plugin-vuetify": "~2.1.0", diff --git a/src/components/Autocomplete.vue b/src/components/Autocomplete.vue index d6e484cc..e5ff55d4 100644 --- a/src/components/Autocomplete.vue +++ b/src/components/Autocomplete.vue @@ -5,14 +5,19 @@ :items="items" :search-input.sync="search" item-text="label" + :menu-props="{maxHeight: 500, transition: 'fade-transition'}" + append-icon="search" return-object hide-no-data + no-filter hide-details label="Søk..." solo auto-select-first placeholder="Søk..." ref="autocomplete" + color="rgb(188, 71, 123)" + dense > <template v-slot:item="data"> {{data.item.label + ' (' + (data.item.lang_set ? Array.from(data.item.lang_set).sort().join(', ') : 'fritekstsøk' ) + ')'}} @@ -22,6 +27,7 @@ <script> import axios from "axios" + import debounce from "debounce" export default { props: { @@ -32,12 +38,47 @@ loading: false, items: [], search: null, - select: null + select: null, + debounced: debounce(function(q, self) { + self.loading = true + return axios.get(self.endpoint + 'suggest?q=' + encodeURIComponent(q)) + .then( + function(response) { + let hits = [] + if (q == self.search) { + response.data.forEach((item, i) => { + let match = encodeURIComponent(item.match) + + if (! hits[0] || hits[0].word != match) { + hits.splice(0, 0, {q: encodeURIComponent(q), lang_set: new Set(), word: match, articles: []}) + } + hits[0].lang_set.add(item.dictionary == 'bob' ? 'bm' : 'nn') + hits[0].articles.push(item) + }); + hits.forEach(function (hit) { + if (hit.lang_set) { + hit.label = decodeURIComponent(hit.word) + } + }); + hits.reverse() + hits = hits.slice(0, 9) + if (q) { + hits.push({q: encodeURIComponent(q), label: q + ' '}) + } + } + self.items = hits + self.loading = false + }) + }, 150) } }, watch: { search (val) { - val && val !== this.select && this.run_query(val) + if (! val) { + this.items = [] + } else { + this.run_query(val) + } }, select(item) { this.$emit('submit', item) @@ -45,42 +86,12 @@ }, methods: { run_query(q) { - let self = this - this.loading = true - return axios.get(self.endpoint + 'suggest?q=' + encodeURIComponent(q)) - .then( - function(response) { - let hits = [] - response.data.forEach((item, i) => { - let match = encodeURIComponent(item.match) - - if (! hits[0] || hits[0].word != match) { - hits.splice(0, 0, {q: encodeURIComponent(q), lang_set: new Set(), word: match, articles: []}) - } - hits[0].lang_set.add(item.dictionary == 'bob' ? 'bm' : 'nn') - hits[0].articles.push(item) - }); - hits.forEach(function (hit) { - if (hit.lang_set) { - hit.label = decodeURIComponent(hit.word) - } - }); - hits.reverse() - hits = hits.slice(0, 5) - if (q) { - hits.push({q: encodeURIComponent(q), label: q + ' '}) - } - self.items = hits - self.loading = false - }) + this.debounced(q, this) } }, } </script> -<style scoped> - div.v-input { - margin: 0px; - } +<style> </style> diff --git a/src/plugins/vuetify.js b/src/plugins/vuetify.js index 2df5c86c..5c8db531 100644 --- a/src/plugins/vuetify.js +++ b/src/plugins/vuetify.js @@ -1,8 +1,16 @@ import Vue from 'vue'; +import 'material-design-icons-iconfont/dist/material-design-icons.css'; import Vuetify from 'vuetify/lib/framework'; Vue.use(Vuetify); export default new Vuetify({ - theme: { disable: true } + theme: { disable: true }, + defaultAssets: { + font: true, + icons: 'md' + }, + icons: { + iconfont: 'md', +} }); -- GitLab