[TypeScript] Select HTMLElements by tabindex
Tags: typescript
Published: 2023-01-15 15:46:34

## Intro
This time, I will try selecting HTMLElements by tabindex.
To do this, I use "querySelector" or "querySelectorAll" because the Document interface doesn't have a dedicated method to select elements by tabindex.
And to select the next element, I will use "ArrowUp" key and "ArrowDown" key.

## Sample code
#### selectElem.html
```html
<!DOCTYPE html>
<html>
    <head>
        <title>Select Element Sample</title>
        <meta charset="utf-8">
    </head>
    <body>
        <select tabindex="1">
            <option>sample</option>
        </select>
        <input type="text" tabindex="2">
        <div tabindex="3">Sample Label</div>
        <div tabindex="5">Sample Label2</div>
        <button>sample</button>
        <script src="./js/selectElem.page.js"></script>
        <script>Page.init();</script>
    </body>
</html>
```

#### selectElem.page.ts
```ts
export function init() {
    document.body.onkeydown = (ev) => {
        switch(ev.key) {
            case "ArrowUp":
                getPreviousElement(1, 5).focus();
                break;
            case "ArrowDown":
                getNextElement(1, 5).focus();
                break;
        }
    };    
}
function getCurrent(): number {
    return (document.activeElement as HTMLElement).tabIndex;
}
function getPreviousElement(minIndex: number, maxIndex: number): HTMLElement {
    const maxTryCount = maxIndex - minIndex;
    let tryCount = 0;
    let previousIndex = getCurrent() - 1;
    while(true) {
        previousIndex = getPreviousTabIndex(previousIndex, minIndex, maxIndex);        
        const target = document.querySelector(`[tabindex='${previousIndex}']`);
        if(target != null) {
            return target as HTMLElement;
        }
        tryCount += 1;
        if(tryCount > maxTryCount) {
            throw Error("Previous Element was not found");
        }
        previousIndex -= 1;
    }
}
function getNextElement(minIndex: number, maxIndex: number): HTMLElement {
    const maxTryCount = maxIndex - minIndex;
    let tryCount = 0;
    let nextIndex = getCurrent() + 1;
    
    while(true) {
        nextIndex = getNextTabIndex(nextIndex, minIndex, maxIndex);
        const target = document.querySelector(`[tabindex='${nextIndex}']`);
        if(target != null) {
            return target as HTMLElement;
        }
        tryCount += 1;
        if(tryCount > maxTryCount) {
            throw Error("Next Element was not found");
        }
        nextIndex += 1;
    }
}
function getPreviousTabIndex(previousIndex: number, minIndex: number, maxIndex: number): number {
    if(previousIndex < minIndex) {
        return maxIndex;
    }
    if(previousIndex > maxIndex) {
        return maxIndex;
    }
    return previousIndex;
}
function getNextTabIndex(nextIndex: number, minIndex: number, maxIndex: number): number {
    if(nextIndex < minIndex) {
        return minIndex;
    }
    if(nextIndex > maxIndex) {
        return minIndex;
    }
    return nextIndex;
}
```

## Resources
* [Document.querySelector() - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
* [How can i find an element using tabindex - Javascript not jquery - StackOverflow](https://stackoverflow.com/questions/20250397/how-can-i-find-an-element-using-tabindex-javascript-not-jquery)
* [How to get TabIndex property of currently active control? - StackOverflow](https://stackoverflow.com/questions/5093985/how-to-get-tabindex-property-of-currently-active-control)
* [KeyboardEvent.key - MDN](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
* [Key values for keyboard events - MDN](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values)