Moving to next input automatically
Asked Answered
H

5

6

I have many <input>s which accept at most three characters, as shown.

<input type="text" id="0" maxlength="3"/>
<input type="text" id="1" maxlength="3"/>
<input type="text" id="2" maxlength="3"/>
<input type="text" id="3" maxlength="3"/>

Can we:

  • allow the user to move textboxes by pressing the Enter key?
  • automatically move the user to the next text box after entering three or more characters?

I have seen a few questions on this topic using JQuery, but I am looking for an exclusively JavaScript solution, if at all possible.

Hardunn answered 7/6, 2020 at 21:27 Comment(1)
Why not use an input event listener and do whatever logic you want in there?Clingy
D
12

You can iterate through elements of the same class name and detect two different events.

var elts = document.getElementsByClassName('test')
Array.from(elts).forEach(function(elt){
  elt.addEventListener("keyup", function(event) {
    // Number 13 is the "Enter" key on the keyboard
    if (event.keyCode === 13 || elt.value.length == 3) {
      // Focus on the next sibling
      elt.nextElementSibling.focus()
    }
  });
})
<input type="text" class="test" id="0" maxlength="3"/>
<input type="text" class="test" id="1" maxlength="3"/>
<input type="text" class="test" id="2" maxlength="3"/>
<input type="text" class="test" id="3" maxlength="3"/>
Derivative answered 7/6, 2020 at 21:36 Comment(2)
Hi, Im trying your solution, but its not work with table, have you got any advice? - FiddleBalkh
It's because the elements are scattered all over the cells, so there is no sibling. Just read the error message in the console.Derivative
D
2

Comments in code below. Basically for loop to iterate through input tags, then an event listener function on keyup to check a few conditionals. We check maxlength set in input attribute and check it against the values length and we also check if the 'enterkey aka '13 is pressed. While loop for the elements next sibling. Check if the element is on the last element using null on set nextElementSibling.

var container = document.getElementsByTagName("input");
// for loop to iterate through elements
for (let i = 0; i < container.length; i++) {
  // create function event for keyup in input fields
  container[i].onkeyup = function(e) {
    //create variable for events source element
    var target = e.srcElement;
    //create variable for the max length attribute in the input field
    var maxLength = parseInt(target.attributes["maxlength"].value, 10);
    //create variable for the length of the targets value in the input
    var myLength = target.value.length;
    //conditional that sees if the elements value is equal tot he maxlength value 
    //or if the enter key is pressed
    if (e.keyCode === 13 || myLength >= maxLength) {
      //set variable for next
      var next = target;
      //loop for the next element of the target
      while (next = next.nextElementSibling) {
        //conditional if the next is not present, so last element we break the code
        if (next == null)
          break;
        //conditional to for the next element that is actually an input tag
        if (next.tagName.toLowerCase() == "input") {
          next.focus();
          break;
        }
      }
    }
  }
}
<input type="text" id="0" maxlength="3" />
<input type="text" id="1" maxlength="3" />
<input type="text" id="2" maxlength="3" />
<input type="text" id="3" maxlength="3" />
Durstin answered 7/6, 2020 at 22:31 Comment(0)
C
1

Thanks for this.

I took taht, but I had some problems with it when coming back on an full input through keyboard navigation. First, I tried to filter Shift and Tab keys, but I still had a problem with quick key strokes : when releasing quickly two keystrokes, the first keyup move to next input field and the second keyup is processed on the input field I just came back to. If the field is also full, then I just pass to next input (while the user may want to modify it).

The solution I use consists of moving to next input if the keyup is processed after a key has been pressed on the input field. I've also seperated the logic of listeners, testing moving conditions (in this case : enter and field complete) and moving to next input.

var setChangeInputWhenComplete = function() {
    document.getElementsByTagName("input").forEach(elt => {
        // Variable to trace if a key has been pressed on input since arriving on it
        var keyPressed = false;

        // Records if a key has been pressed on input field in order not to pass to next field if the keyup event occurs on a field we've juste arrived on
        elt.addEventListener("keypress", function(event) {
            keyPressed = true;
        });
        
        // Clears previous keypressed recording when we come back on input field
        elt.addEventListener("focus", function(event) {
            keyPressed = false;
        });
        
        elt.addEventListener("keyup", function(event) {
            // When quickly releasing a second key, pressed on previous field, when arriving on a new field, we should not pass to next field even if the field is already full
            if (keyPressed) {
                // If field is full, pass to next input
                      if (mustMoveToNextInput(event)) {
                          moveToNextInput(event);
                      }
            }
        });
    });
};

var moveToNextInput = function(event) {
    //set variable for next
    var next = event.srcElement;
    //loop for the next element of the inputField
    while (next = next.nextElementSibling) {
      //conditional if the next is not present, so last element we break the code
      if (next == null)
        break;
      //conditional to for the next element that is actually an input tag
      if (next.tagName.toLowerCase() == "input") {
        next.focus();
        break;
      }
    }
};

var mustMoveToNextInput = function(event) {
  var inputField = event.srcElement;
  var maxLength = parseInt(inputField.attributes["maxlength"].value, 10);
  
  return (event.keyCode === 13 || inputField.value.length >= maxLength);
};
 
setChangeInputWhenComplete();
Compton answered 3/3, 2022 at 13:5 Comment(0)
A
0

The code of djcaesar9114 works perfectly. I would just add an exception for the tab key, as the tab key moves already to the next field. And use maxLength in the code.

The if line would then look like this:

if (event.keyCode !== 9 && (event.keyCode === 13 || elt.value.length == elt.maxLength))
Armstrong answered 28/9, 2022 at 16:43 Comment(0)
M
0

in RtL templates maybe you have problem to use : elt.nextElementSibling.focus()

In these formats, with the above command, you will be transferred to a field that is considered as previous in your format. I use the following code to solve this problem in Farsi formats or other languages ​​that are written from the right. Note: In the code snippet, it was not possible to change the language and meta on the page. For this reason, the file is executed LtR and you will encounter an error in the first house. The reason is exactly the difference between the LtR and RtL format

var elts = document.getElementsByClassName('initInput')
Array.from(elts).forEach(function(elt){
elt.addEventListener("keyup", function(event) {
    // Number 13 is the "Enter" key on the keyboard
    if (elt.value.length == 1) {
    // Focus on the next sibling
    elt.previousElementSibling.focus()
    } else if (event.keyCode === 8) {
    elt.nextElementSibling.focus()
    }
});
})
<input type="text" id="0" maxlength="1" size='1' class='initInput' />
<input type="text" id="1" maxlength="1" size='1' class='initInput' />
<input type="text" id="2" maxlength="1" size='1' class='initInput' />
<input type="text" id="3" maxlength="1" size='1' class='initInput' />
Monocot answered 4/8, 2024 at 12:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.