Vue.component("combo-box", { props: ["name", "title", "placeholder", "size", "v-items", "v-value"], data: function () { let items = this.vItems if (items == null || !(items instanceof Array)) { items = [] } // 自动使用ID作为值 items.forEach(function (v) { if (v.value == null) { v.value = v.id } }) // 当前选中项 let selectedItem = null if (this.vValue != null) { let that = this items.forEach(function (v) { if (v.value == that.vValue) { selectedItem = v } }) } return { allItems: items, items: items.$copy(), selectedItem: selectedItem, keyword: "", visible: false, hideTimer: null, hoverIndex: 0 } }, methods: { reset: function () { this.selectedItem = null this.change() this.hoverIndex = 0 let that = this setTimeout(function () { if (that.$refs.searchBox) { that.$refs.searchBox.focus() } }) }, changeKeyword: function () { this.hoverIndex = 0 let keyword = this.keyword if (keyword.length == 0) { this.items = this.allItems.$copy() return } this.items = this.allItems.$copy().filter(function (v) { return teaweb.match(v.name, keyword) }) }, selectItem: function (item) { this.selectedItem = item this.change() this.hoverIndex = 0 this.keyword = "" this.changeKeyword() }, confirm: function () { if (this.items.length > this.hoverIndex) { this.selectItem(this.items[this.hoverIndex]) } }, show: function () { this.visible = true // 不要重置hoverIndex,以便焦点可以在输入框和可选项之间切换 }, hide: function () { let that = this this.hideTimer = setTimeout(function () { that.visible = false }, 500) }, downItem: function () { this.hoverIndex++ if (this.hoverIndex > this.items.length - 1) { this.hoverIndex = 0 } this.focusItem() }, upItem: function () { this.hoverIndex-- if (this.hoverIndex < 0) { this.hoverIndex = 0 } this.focusItem() }, focusItem: function () { if (this.hoverIndex < this.items.length) { this.$refs.itemRef[this.hoverIndex].focus() let that = this setTimeout(function () { that.$refs.searchBox.focus() if (that.hideTimer != null) { clearTimeout(that.hideTimer) that.hideTimer = null } }) } }, change: function () { this.$emit("change", this.selectedItem) } }, template: `
` })