DEV Community

Masui Masanori
Masui Masanori

Posted on

3

[TypeScript] Select HTMLElements by tabindex

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

<!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>
Enter fullscreen mode Exit fullscreen mode

selectElem.page.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;
}
Enter fullscreen mode Exit fullscreen mode

Resources

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs