Roving Tabindex - Radio Buttons example

by tohuwabohu_io

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Roving Tabindex - Radio Buttons example</title>
</head>
<body>
<main>
    <h1>Please submit your favorite food choice.</h1>
    <form>
        <label for="name">Name:</label>
        <input id="name" type="text">

        <p>Favorite type of food</p>

        <div>
            <label for="chinese">Chinese</label>
            <input type="radio" id="chinese" name="favFood" tabindex="-1">
            <label for="italian">Italian</label>
            <input type="radio" id="italian" name="favFood" tabindex="0" checked="checked">
            <label for="thai">Thai</label>
            <input type="radio" id="thai" name="favFood" tabindex="-1">
        </div>

        <button onclick="submitFoodChoice()">
            Submit
        </button>
    </form>
</main>
</body>
</html>

JavaScript

const group = Array.from(document.querySelectorAll("input[name='favFood']"));

group.forEach(radio => {
  radio.addEventListener("keydown", (e) => {
    console.log(e.key);

    if (e.key !== 'Tab') {
      e.preventDefault();
    }

    const radios = Array
    .from(document
          .querySelectorAll("input[name='favFood']"));

    const thisIndex = radios.indexOf(e.target);

    switch (e.key) {
      case 'ArrowLeft': {
        roveTabindex(radios, thisIndex, -1);
      }
        break;
      case 'ArrowRight': {
        roveTabindex(radios, thisIndex, 1);
      }
        break;
      default:
        return;
    }
  });
});

const roveTabindex = (radios, index, inc) => {
  let nextIndex = index + inc;

  if (nextIndex < 0) {
    nextIndex = radios.length - 1;
  } else if (nextIndex >= radios.length) {
    nextIndex = 0;
  }

  console.log(`roving tabindex to index ${nextIndex}`);

  radios[index].setAttribute("tabindex", "-1");
  radios[index].setAttribute("checked", "false");

  radios[nextIndex].setAttribute("tabindex", "0");
  radios[nextIndex].setAttribute("checked", "checked");

  radios[nextIndex].focus();
}

const submitFoodChoice = () => {
  console.log('submit!');
}