santosh
santosh

Reputation: 892

Keep focus looping on inputs of form when using tab instead of moving to second form

I want to restrict the focus to a single form when tab is pressed.
By that I mean focus on form 1's tab index 1, 2, and 3, and then move back to 1 within the same form, then 2, etc., never going to form 2's inputs. I also don't want to change the tab indices.

<form style="background-color:red">
    <input tabindex="01"/>
    <input tabindex="02"/>
    <input tabindex="03"/>
</form>

<form style="background-color:blue">
    <input tabindex="01"/>
    <input tabindex="02"/>
    <input tabindex="03"/>
</form>

Upvotes: 2

Views: 3074

Answers (3)

CJH
CJH

Reputation: 187

I actually found a simple solution to this.

First, I set up the inputs with tabindex attributes to control the progression, and with unique IDs. Then I did getElementById() for the first and last input elements, and set up an event listener on the last input element which then just switched focus to the first one.

   let tk_first_input = document.getElementById("first_input");
   let tk_last_input = document.getElementById("last_input");

   tk_last_input.addEventListener("keydown", (e) => {
      if (e.key ==="Tab") {
         e.preventDefault();
         tk_first_input.focus();
      }
   })

This worked well for me on a page where I had multiple DIVs each with a form.

Upvotes: 0

Dharmendra RD
Dharmendra RD

Reputation: 1

<input type="text" class="first-index"/>

<input type="text" />

<button type="button" class="last-index">save</button>
<script>
    $(document).on('blur','.last-index',function() {
      $('.first-index').focus();
    });
</script>

Upvotes: 0

Zach Saucier
Zach Saucier

Reputation: 26014

This isn't good practice, so don't do it unless there is really good reason to do it...


But there's no built in HTML way to do this, so we need to use some JavaScript along with a custom data attribute.

I think it's easiest to use a data attribute to the parent (the <form>) so that way we don't have to add it to each input individually. I named mine data-tabgroup.

Then we need some JS:

// Select the tab groups based on the data attribute we added
var tabgroups = document.querySelectorAll("[data-tabgroup]");

// Loop through each to attach the listeners we need
for (var i = 0; i < tabgroups.length; i++) {
  var inputs = tabgroups[i].querySelectorAll("[tabindex]");

  // Loop through all of the elements we want the tab to be changed for
  for (var j = 0; j < inputs.length; j++) {

    // Listen for the tab pressed on these elements
    inputs[j].addEventListener("keydown", function(myIndex, inputs, e) {
      if (e.key === "Tab") {
        // Prevent the default tab behavior
        e.preventDefault();

        // Focus the next one in the group
        if (inputs[myIndex + 1]) {
          inputs[myIndex + 1].focus();
        } else { // Or focus the first one again
          inputs[0].focus();
        }
      }
    }.bind(null, j, inputs)) // Make a copy of the variables to use in the addEventListener
  }
}
<form style="background-color: red" data-tabgroup>
  <input tabindex="01" />
  <input tabindex="02" />
  <input tabindex="03" />
</form>

<form style="background-color: blue" data-tabgroup>
  <input tabindex="01" />
  <input tabindex="02" />
  <input tabindex="03" />
</form>

And that's it! Here's the demo.


Some notes:

  • The current implementation ignores the value of the tabindex within the group (it just selects the next one in the HTML). To take that into account, you just need to put the elements in the array in order of their tabindexes or sort them by the tabindexes after you add them to the array.
  • The current implementation requires that a tabindex be applied to children that you want this to affect. If you want it to apply to all inputs by default, just change the querySelectorAll value for inputs to input. If you want something more complex, you'll have to change it as needed.

Upvotes: 3

Related Questions