2
0
mirror of https://github.com/frappe/books.git synced 2024-12-27 12:42:44 +00:00
books/ui/components/controls/Autocomplete.vue

143 lines
3.4 KiB
Vue
Raw Normal View History

2018-06-27 14:38:27 +00:00
<script>
import Data from './Data';
export default {
extends: Data,
data() {
return {
popupOpen: false,
popupItems: [],
highlightedItem: -1
2018-06-27 14:38:27 +00:00
}
},
2018-09-26 15:07:59 +00:00
render(h) {
return this.getWrapperElement(h);
},
watch: {
// prop change does not change the value of input
// this only happens for Autocomplete
value(newValue) {
this.$refs.input.value = newValue;
}
},
2018-06-27 14:38:27 +00:00
methods: {
getInputListeners() {
return {
2018-09-06 08:18:58 +00:00
input: e => {
this.updateList(e.target.value);
2018-06-27 14:38:27 +00:00
},
keydown: e => {
if (e.keyCode === 38) {
// up
this.highlightAboveItem();
}
if (e.keyCode === 40) {
// down
this.highlightBelowItem();
}
if (e.keyCode === 13) {
if (this.highlightedItem > -1) {
this.onItemClick(this.popupItems[this.highlightedItem]);
this.popupOpen = false;
}
}
2018-09-06 08:18:58 +00:00
},
focus: async e => {
await this.updateList();
},
blur: () => {
setTimeout(() => {
this.popupOpen = false;
}, 200);
2018-06-27 14:38:27 +00:00
}
}
},
highlightBelowItem() {
this.highlightedItem += 1;
if (this.highlightedItem > this.popupItems.length - 1) {
this.highlightedItem = this.popupItems.length - 1;
}
this.scrollToItem(this.highlightedItem);
},
highlightAboveItem() {
this.highlightedItem -= 1;
if (this.highlightedItem < 0) {
this.highlightedItem = 0;
}
this.scrollToItem(this.highlightedItem);
},
getChildrenElement(h) {
return [
2018-09-26 15:07:59 +00:00
this.onlyInput ? null : this.getLabelElement(h),
this.getInputElement(h),
this.getDropdownElement(h)
];
2018-09-06 08:18:58 +00:00
},
getDropdownElement(h) {
return h('div', {
class: ['dropdown-menu w-100', this.popupOpen ? 'show' : ''],
ref: 'dropdown-menu'
}, this.getDropdownItems(h));
2018-06-27 14:38:27 +00:00
},
getDropdownItems(h) {
return this.popupItems.map((item, i) => {
return h('a', {
class: ['dropdown-item', this.highlightedItem === i ? 'active text-dark' : ''],
attrs: {
href: '#',
'data-value': item.value
},
ref: i,
on: {
click: e => {
e.preventDefault();
this.onItemClick(item);
this.popupOpen = false;
}
},
domProps: {
innerHTML: item.label
}
})
2018-06-27 14:38:27 +00:00
});
},
onItemClick(item) {
this.handleChange(item.value);
2018-06-27 14:38:27 +00:00
},
scrollToItem(i) {
const scrollTo = this.$refs[i].offsetTop - 5;
this.$refs['dropdown-menu'].scrollTop = scrollTo;
},
async updateList(keyword) {
this.popupItems = await this.getList(keyword);
this.popupOpen = this.popupItems.length > 0;
2018-06-27 14:38:27 +00:00
},
async getList(text='') {
let list = await this.docfield.getList(text);
list = list.map(item => {
if (typeof item === 'string') {
return {
label: item,
value: item
}
}
return item;
});
return list.filter(item => {
const string = (item.label + ' ' + item.value).toLowerCase();
return string.includes(text.toLowerCase());
});
2018-06-27 14:38:27 +00:00
}
}
};
</script>
<style>
.form-group[data-fieldtype="Link"] .dropdown-menu {
max-height: 200px;
overflow: auto;
}
</style>