[javascript] How to advance to the next form input when the current input has a value?

I am having a form with lots of entries. I would like to change my focus to the next textbox, once I entered the value in the current textbox. and want to continue this process up to the last field. My question is, is it possible to simulate what happens when pressing the tab key through Javascript coding once I enter the value in the text box.

Without pressing the tab key in keyboard, I would like to bring the same functionality through Javascript. Is this possible?

This question is related to javascript dom-events

The answer is


This should work. Working with and without tabindex.

_x000D_
_x000D_
var currentlyFocused = undefined;_x000D_
var tabableElements = undefined;_x000D_
_x000D_
/**_x000D_
 * Compare function for element sort_x000D_
 * @param {string | null} a_x000D_
 * @param {string | null} b_x000D_
 * @param {boolean} asc_x000D_
 */_x000D_
function sortCompare(a, b, asc = true) {_x000D_
  let result = null;_x000D_
  if (a == null) result = 1;_x000D_
  else if (b == null) result = -1;_x000D_
  else if (parseInt(a) > parseInt(b)) result = 1;_x000D_
  else if (parseInt(a) < parseInt(b)) result = -1;_x000D_
  else result = 0;_x000D_
  return result * (asc ? 1 : -1);_x000D_
}_x000D_
_x000D_
/**_x000D_
 * When an element is focused assign it to the currentlyFocused variable_x000D_
 * @param {Element} element_x000D_
 */_x000D_
function registerOnElementFocus(element) {_x000D_
  element.addEventListener("focus", function(el) {_x000D_
    currentlyFocused = el.srcElement;_x000D_
  });_x000D_
}_x000D_
_x000D_
/**_x000D_
 * Tab Trigger_x000D_
 */_x000D_
function onTabClick() {_x000D_
  //Select currently focused element_x000D_
  let currentIndex;_x000D_
  tabableElements.forEach((el, idx) => {_x000D_
    //return if no element is focused_x000D_
    if (!currentlyFocused) return;_x000D_
    if (currentlyFocused.isEqualNode(el)) {_x000D_
      //assign current index and return_x000D_
      currentIndex = idx;_x000D_
      return;_x000D_
    }_x000D_
  });_x000D_
  //if theres no focused element or the current focused element is last start over_x000D_
  let lastIndex = tabableElements.length - 1;_x000D_
  let nextElementidx = currentIndex === undefined || currentIndex == lastIndex ? 0 : currentIndex + 1;_x000D_
  //Focus_x000D_
  currentlyFocused = tabableElements[nextElementidx];_x000D_
  currentlyFocused.focus();_x000D_
}_x000D_
/**_x000D_
 * Init must be run after all elements are loadead in the dom_x000D_
 */_x000D_
function init() {_x000D_
  //Get all tab-able elements_x000D_
  let nodeList = document.querySelectorAll("input, button, a, area, object, select, textarea, [tabindex]");_x000D_
  //To array for easier manipulation_x000D_
  tabableElements = Array.prototype.slice.call(nodeList, 0);_x000D_
  //Correcting tabindexes to ensure correct order_x000D_
  tabableElements.forEach((el, idx, list) => {_x000D_
    let tabindex = el.getAttribute("tabindex");_x000D_
    //-1 tabindex will not receive focus_x000D_
    if (tabindex == -1) list.splice(idx, 1);_x000D_
    //null or 0 tabindex in normal source order_x000D_
    else if (tabindex == null || tabindex == 0) {_x000D_
      list[idx].setAttribute("tabindex", 9999 + idx);_x000D_
    }_x000D_
  });_x000D_
  //sort elements by their tabindex in ascending order_x000D_
  tabableElements.sort((elementA, elementB) => sortCompare(elementA.getAttribute("tabindex"), elementB.getAttribute("tabindex")));_x000D_
  //register focus event to elements_x000D_
  tabableElements.forEach(el => registerOnElementFocus(el));_x000D_
}
_x000D_
<!doctype html>_x000D_
<html lang="en">_x000D_
_x000D_
<head>_x000D_
  <!-- Required meta tags -->_x000D_
  <meta charset="utf-8">_x000D_
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">_x000D_
_x000D_
  <!-- Bootstrap CSS -->_x000D_
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">_x000D_
_x000D_
  <title>Virtual tab</title>_x000D_
</head>_x000D_
_x000D_
<body onload="init()">_x000D_
  <div class="container">_x000D_
    <h3>Virtual Tab Demo</h3>_x000D_
    <form>_x000D_
      <div class="btn btn-primary" style="position: fixed;" onclick="onTabClick()">_x000D_
        Tab!_x000D_
      </div>_x000D_
      <br>_x000D_
      <br>_x000D_
      <button id="button1" type="button" onclick="alert('button 1')">Button1</button>_x000D_
      <button id="button2" type="button" onclick="alert('button 2')">Button2</button>_x000D_
      <br>_x000D_
      <br>_x000D_
      <input id="text" type='text'>text_x000D_
      <br>_x000D_
      <input id="password" type='password' tabindex="-1">password_x000D_
      <br>_x000D_
      <input id="number" type='number' tabindex="5">number_x000D_
      <br>_x000D_
      <input id="checkbox" type='checkbox'>checkbox_x000D_
      <br>_x000D_
      <input id="radio" type='radio'>radio_x000D_
      <br>_x000D_
      <br>_x000D_
      <button id="button3" type="button" onclick="alert('button 3')">Button3</button>_x000D_
      <button id="button4" type="button" onclick="alert('button 4')">Button4</button>_x000D_
      <br>_x000D_
      <br>_x000D_
      <select id="select">_x000D_
        <option value="volvo">Volvo</option>_x000D_
        <option value="saab">Saab</option>_x000D_
        <option value="mercedes">Mercedes</option>_x000D_
        <option value="audi">Audi</option>_x000D_
      </select>_x000D_
      <br>_x000D_
      <br> textarea_x000D_
      <br>_x000D_
      <textarea id="textarea"></textarea>_x000D_
        <br>_x000D_
        <br>_x000D_
        <span id="span" tabindex="1">Focus other elements.</span>_x000D_
    </form>_x000D_
  </div>_x000D_
  <!-- Optional JavaScript -->_x000D_
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->_x000D_
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>_x000D_
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>_x000D_
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


Needed to emulate the tab functionality a while ago, and now I've released it as a library that uses .

EmulateTab: A jQuery plugin to emulate tabbing between elements on a page.

You can see how it works in the demo.

if (myTextHasBeenFilledWithText) {
  // Tab to the next input after #my-text-input
  $("#my-text-input").emulateTab();
}

In vanilla JS:

function keydownFunc(event) {
      var x = event.keyCode;        
      if (x == 13) {
        try{
            var nextInput = event.target.parentElement.nextElementSibling.childNodes[0];
            nextInput.focus();
          }catch (error){
            console.log(error)
          }
    }

In the first question, you don't need an event listener on every input that would be wasteful.

Instead, listen for the enter key and to find the currently focused element use document.activeElement

window.onkeypress = function(e) {
    if (e.which == 13) {
       e.preventDefault();
       var nextInput = inputs.get(inputs.index(document.activeElement) + 1);
       if (nextInput) {
          nextInput.focus();
       }
    }
};

One event listener is better than many, especially on low power / mobile browsers.


I couldn't find an answer that could do what I wanted. I had a problem where there were some link elements that I didn't want users tabbing to. This is what I came up with:

(Note that in my own code I used a:not(.dropdown-item) instead of a on the allElements line, in order to prevent users tabbing to a.dropdown-item.)

function(event){
        //Note that this doesn't honour tab-indexes

        event.preventDefault();

        //Isolate the node that we're after
        const currentNode = event.target;

        //find all tab-able elements
        const allElements = document.querySelectorAll('input, button, a, area, object, select, textarea, [contenteditable]');

        //Find the current tab index.
        const currentIndex = [...allElements].findIndex(el => currentNode.isEqualNode(el))

        //focus the following element
        const targetIndex = (currentIndex + 1) % allElements.length;
        allElements[targetIndex].focus();
}

function nextField(current){
    for (i = 0; i < current.form.elements.length; i++){
        if (current.form.elements[i].tabIndex - current.tabIndex == 1){
            current.form.elements[i].focus();
            if (current.form.elements[i].type == "text"){
                current.form.elements[i].select();
            }
        }
    }
}

This, when supplied with the current field, will jump focus to the field with the next tab index. Usage would be as follows

<input type="text" onEvent="nextField(this);" />

you just need to give focus to the next input field (by invoking focus()method on that input element), for example if you're using jQuery this code will simulate the tab key when enter is pressed:

var inputs = $(':input').keypress(function(e){ 
    if (e.which == 13) {
       e.preventDefault();
       var nextInput = inputs.get(inputs.index(this) + 1);
       if (nextInput) {
          nextInput.focus();
       }
    }
});

I've adapter the answer of ltiong_sh to work for me:

function nextField(current){
    var elements = document.getElementById("my-form").elements;
    var exit = false;
    for(i = 0; i < elements.length; i++){   
        if (exit) {
            elements[i].focus();
            if (elements[i].type == 'text'){
                elements[i].select();
            }   
            break;
        }
        if (elements[i].isEqualNode(current)) { 
            exit = true;
        }       
    }
}

If you have jQuery UI this little function allows basic tabbing

handlePseudoTab(direction) {
    if (!document.hasFocus() || !document.activeElement) {
        return;
    }
    const focusList = $(":focusable", $yourHTMLElement);
    const i = focusList.index(document.activeElement);
    if (i < 0) {
        focusList[0].focus(); // nothing is focussed so go to list item 0
    } else if (direction === 'next' && i + 1 < focusList.length) {
        focusList[i + 1].focus(); // advance one
    } else if (direction === 'prev' && i - 1 > -1) {
        focusList[i - 1].focus(); // go back one
    }
}

This simulates a tab through a form and gives focus to the next input when the enter key is pressed.

window.onkeypress = function(e) {
    if (e.which == 13) {
        e.preventDefault();
        var inputs = document.getElementsByClassName('input');
        for (var i = 0; i < inputs.length; i++) {
        if (document.activeElement.id == inputs[i].id && i+1 < inputs.length ) {
            inputs[i+1].focus();
            break;   
        }
    }