Kedar Javalkar
Kedar Javalkar

Reputation: 343

Focus next element if validation function returns true

I have multiple inputs which allow a single digit numeric value. The script below confirms the the value is a number.

How can I move focus to the next input when a valid number has been input?

<input type="text" maxlength="1" onkeypress="return isNumber(event)" required>
function isNumber(evt) {
    evt = (evt) ? evt : window.event;
    var charCode = (evt.which) ? evt.which : evt.keyCode;
    if (charCode > 31 && (charCode < 49 || charCode > 53)) {
        return false;
    }
    return true;
}

Upvotes: 3

Views: 4407

Answers (2)

user4639281
user4639281

Reputation:

You can find the next element by using Node.nextElementSibling then assign focus using HTMLElement.focus()

To make it iterate to the next row, you have to check whether currently focused element is the last element in the current row. If so then move to the next line.

It is better to use Event.preventDefault() in the Element.onkeydown property and then check to see if the element has been filled in the Element.onkeyup property as the keypress event is fired both when the key is pressed down and again when it is released.

var validChar;
var inputs = document.querySelectorAll('td input[type=text]'), i;
for(i = inputs.length - 1; i >= 0; i--) {
    inputs[i].onkeydown = checkNumber;
    inputs[i].onkeyup   = checkFilled;
}
function checkNumber(event) {
    event = (event) ? event : window.event;
    var charCode = (event.which) ? event.which : event.keyCode;
    if (!(charCode >= 48 && charCode <= 53) 
     && !(charCode >= 96 && charCode <= 101)
     && !(charCode == 16 || charCode == 9)) {
            event.preventDefault();
            return false;
    } else if(!(charCode == 16 || charCode == 9)) {
        validChar = true;
    }
}
function checkFilled(event) {
    if(validChar && event.target.value.length === 1) {
        validChar = false;
        nextInput(event.target.parentNode);
    }
}
function nextInput(el) {
    if(el.nextElementSibling) {
        if(!el.nextElementSibling.firstElementChild) {
            nextInput(el.nextElementSibling);
            return false;
        }
        var nextSibling = el.nextElementSibling.firstElementChild;
    } else {
        if(!el.parentNode.nextElementSibling) {
            return false;
        }
        var nextRow = el.parentNode.nextElementSibling;
        if(!nextRow.firstElementChild.firstElementChild) {
            nextInput(nextRow.firstElementChild);
            return false;
        }
        var nextSibling = nextRow.firstElementChild.firstElementChild;
    }
    var nextType = nextSibling.tagName.toLowerCase();
    if(nextType !== "input") {
        nextInput(nextSibling);
        return false;
    }
    nextSibling.focus();
}
<table>
     <tr>
         <td>some text</td>
         <td>some text</td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
     </tr>
     <tr>
         <td>some text</td>
         <td>some text</td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
         <td><input type="text" maxlength="1" required></td>
     </tr>
</table>

Upvotes: 4

Mike Robinson
Mike Robinson

Reputation: 8945

In this case, I suggest that you expand the definition of what's now being called an isNumber() function. Pass a second parameter to it, giving the ID of the control that should be moved-to if the input is a number. Then, in that subroutine, quash the event and then setFocus to the proper "next control." Each onkeypress handler would call the same routine, but with a different next-control-id parameter, so that each control sends us on to the proper next-one.

I would counsel you: don't try to simulate pressing the Tab key.

Upvotes: 0

Related Questions