Files
17th-Site-Front-End-V2/17th Website/src/components/inputs/pingableTextBox.vue

134 lines
3.6 KiB
Vue

<script>
export default {
data() {
return {
search: '',
results: [],
isOpen: false,
arrowCounter: 0,
}
},
props: {
items: {
type: Array,
required: false,
default: () => [],
},
isAsync: {
type: Boolean,
required: false,
default: false,
}
},
watch: {
items: function (value, oldValue) {
if (this.isAsync) {
this.results = value;
this.isOpen = true;
this.isLoading = false;
}
}
},
methods: {
onchange() {
this.$emit('input', this.search)
if (this.isAsync) {
this.isLoading = true;
} else if(this.search.length > 0) {
this.filter();
this.isOpen = true;
} else if (this.results.length <= 2) {
this.isOpen(false);
} else {
this.isOpen = false;
}
this.arrowCounter = 0;
},
filter() {
this.results = this.items.filter(item => item.toLowerCase().indexOf(this.search.toLowerCase()) > -1);
},
setResult(result) {
this.search = result;
this.isOpen = false;
},
handleClickOutside(event) {
if (!this.$el.contains(event.target)) {
this.isOpen = false;
this.arrowCounter = 0;
}
},
bumpUp() {
console.log("bumpup")
console.log(this.arrowCounter, " ", this.results.length)
if (this.arrowCounter > 0) {
this.arrowCounter -= 1;
}
},
bumpDown() {
console.log("bumpdown")
console.log(this.arrowCounter, " ", this.results.length)
if (this.arrowCounter < this.results.length - 1) {
this.arrowCounter += 1;
}
},
select() {
this.search = this.results[this.arrowCounter];
this.arrowCounter = 0;
this.isOpen = false;
},
},
mounted() {
document.addEventListener('click', this.handleClickOutside)
},
unmounted() {
document.removeEventListener('click', this.handleClickOutside)
},
}
</script>
<template>
<div class="relative">
<input type="text" v-model="search" @input="onchange" @keydown.down="bumpDown" @keydown.up="bumpUp"
@keydown.enter="select" @keydown.tab="select" spellcheck="false"
class="bg-gray-light rounded-md text-white focus:outline-none p-1 px-2"
:class="{'outline outline-1 outline-blue':items.includes(search), 'outline outline-1 outline-red-500':!items.includes(search) && search != ''}"/>
<ul id="results" v-show="isOpen" class="shadow-2xl">
<li class="result" v-for="(result, i) in results" :key="i" @click="setResult(result)"
:class="{ 'is-active': i === arrowCounter }">
{{ result }}
</li>
</ul>
</div>
</template>
<style scoped>
#results {
position: absolute;
padding: 0;
margin: 0;
/* border: 1px solid #eeeeee; */
height: max-content;
/* min-height: 1em;
max-height: 6em; */
overflow: auto;
border-radius: 5px;
}
.result {
list-style: none;
text-align: left;
padding: 4px 2px;
cursor: pointer;
background-color: #272731;
}
.result.is-active,
.result:hover {
background-color: #01bde7;
color: white;
}
</style>