105 lines
2.1 KiB
Vue
105 lines
2.1 KiB
Vue
<template>
|
|
<div class="autocomplete">
|
|
<input type="text" @input="option_open" v-model="xvalue" @keydown.down="option_down" @keydown.up="option_up" @keydown.enter="option_enter" />
|
|
<ul id="autocomplete-results" v-show="open" class="autocomplete-results">
|
|
<li class="loading" v-if="!items">Loading results...</li>
|
|
<li v-else v-for="(result, i) in results" :key="i" @click="option_click(result)" class="autocomplete-result" :class="{ 'is-active': i === index }">{{ result }}</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.autocomplete {
|
|
position: relative;
|
|
}
|
|
|
|
.autocomplete-results {
|
|
padding: 0;
|
|
margin: 0;
|
|
border: 1px solid #eeeeee;
|
|
height: 120px;
|
|
overflow: auto;
|
|
}
|
|
|
|
.autocomplete-result {
|
|
list-style: none;
|
|
text-align: left;
|
|
padding: 4px 2px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.autocomplete-result.is-active,
|
|
.autocomplete-result:hover {
|
|
background-color: #4AAE9B;
|
|
color: white;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
items: {
|
|
type: Array,
|
|
required: false,
|
|
default: () => [],
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
xvalue: '',
|
|
results: [],
|
|
open: false,
|
|
index: -1,
|
|
};
|
|
},
|
|
watch: {
|
|
value(val) {
|
|
this.xvalue = val;
|
|
},
|
|
xvalue(val) {
|
|
this.$emit('update:value', val);
|
|
}
|
|
},
|
|
mounted() {
|
|
this.xvalue = this.value;
|
|
document.addEventListener('click', this.option_close)
|
|
},
|
|
destroyed() {
|
|
document.removeEventListener('click', this.option_close)
|
|
},
|
|
methods: {
|
|
option_open() {
|
|
if(this.items) {
|
|
this.results = this.items.filter((item) => item.toLowerCase().indexOf(this.xvalue.toLowerCase()) > -1);
|
|
this.open = true;
|
|
}
|
|
},
|
|
option_down() {
|
|
if(this.index < this.results.length) this.index++;
|
|
},
|
|
option_up() {
|
|
if(this.index > 0) this.index--;
|
|
},
|
|
option_enter() {
|
|
this.xvalue = this.results[this.index];
|
|
this.open = false;
|
|
this.index = -1;
|
|
},
|
|
option_click(result) {
|
|
this.xvalue = result;
|
|
this.open = false;
|
|
},
|
|
option_close(evt) {
|
|
if(!this.$el.contains(evt.target)) {
|
|
this.open = false;
|
|
this.index = -1;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
</script>
|