I have a custom-built select component in Vue/Nuxt.js seen below:
This select has arrow key functionality (pressing the arrow up and down keys makes it scroll through the options and pressing enter selects that option), and I'm trying to add "jump key" functionality to it as well (pressing a character key makes the dropdown jump to the first result which starts with that letter, then cycles through all the other results starting with that letter until it loops back around to the start).
So far, the method I've written for this purpose is here:
setPointer(event) {
if (event.key != "ArrowDown" && event.key != "ArrowUp" && event.key != "Enter" && event.key != "Escape" && event.key != "Tab") {
let filteredResults = this.sortedResults.filter(result => result.text.toUpperCase().startsWith(event.key.toUpperCase()))
let oldPointer = this.pointer
let filteredPointer = this.sortedResults.length - filteredResults.length + oldPointer
if (this.pointer == -1 || this.sortedResults[this.pointer] == filteredResults[filteredResults.length -1]) {
this.pointer = this.results.indexOf(filteredResults[0])
}
else if (this.sortedResults[this.pointer] == filteredResults[filteredPointer] && this.pointer > -1) {
this.movePointerDown()
}
let newPointer = this.pointer
if (this.pointer > oldPointer) {
this.$refs.dropdown.scrollTop += (40 * (newPointer - oldPointer))
}
else if (this.pointer == 0) {
this.$refs.dropdown.scrollTop = 0
}
else {
this.$refs.dropdown.scrollTop -= (40 * (oldPointer - newPointer))
}
}
},
sortedResults: an array of alphabetically-sorted results, which appears in my select's dropdown. The array's items are objects each containing a string called text (they have to be objects for outside-scope-of-question reasons)
filteredResults: an array of results filtered from sortedResults by whether the pressed key matches the first letter of each item's text
pointer: the currently-highlighted index of sortedResults
oldPointer: original value of pointer when starting the function
filteredPointer: where pointer sits inside filteredResults, calculated by taking the difference between sortedResults and filteredResults and adding oldPointer to it
newPointer: new value of pointer after cycling through function movePointerDown(): increments pointer by one, is also used on a down arrow key press
The plan is to generate filteredResults, oldPointer, and filteredPointer, then do the following checks:
- if pointer hasn't been set or is sitting on something outside of filteredResults, set it to the place in sortedResults where its item matches filteredResults[0]
- if pointer is already pointing to an item shared by sortedResults and filteredResults, increment pointer by 1
- UNLESS the item shared by sortedResults and filteredResults is at the end of filteredResults' array, then set pointer back to whatever the filteredResults[0] equivalent is in sortedResults
- Then afterwards check where the new pointer is relative to the old one and scroll the new one into view wherever it is.
I've tied my brain into a bit of a knot over this one, and obviously the method above is incomplete and full of holes. If anyone can help me figure out how to get the logic I need out of this function, it would be significantly appreciated. I am the only in-house front-end web developer at my place of work, so I don't have much chance to bounce questions off of people there - I manage for the most part, but it can be a struggle.
