24

I've got four inputs that each take one number. What I want to do is set the focus automatically to the next input once the number has been set. They all have the class "inputs".

This didn't quite work:

$(".inputs").keydown(function () {

            $(this).next().focus();
        });
domino
  • 7,271
  • 12
  • 36
  • 48
  • See this post [1]: http://stackoverflow.com/questions/1232379/setting-the-focus-to-the-next-input-in-jquery – BinBin May 10 '12 at 17:21
  • See [updated post](http://stackoverflow.com/a/10539258/297641) for some new features.. more like `autotab` [DEMO](http://jsfiddle.net/skram/qygB2/4/) – Selvakumar Arumugam May 10 '12 at 17:46

12 Answers12

64

I would suggest setting maxlength as 1 to each textbox and switch to next one once the val.length and the maxlength is same.

DEMO

$(".inputs").keyup(function () {
    if (this.value.length == this.maxLength) {
      $(this).next('.inputs').focus();
    }
});

Edit: Spent some time for the following (not fully tested, but basic tests worked fine)

   1. Allowing just numeric chars  
   2. Allow some control like del, backspace, e.t.c
   3. Backspace on empty textbox will move to prev textbox
   4. charLimit var to dynamically decide how many char you want to restrict.

Code:

$(function() {
    var charLimit = 1;
    $(".inputs").keydown(function(e) {

        var keys = [8, 9, /*16, 17, 18,*/ 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 144, 145];

        if (e.which == 8 && this.value.length == 0) {
            $(this).prev('.inputs').focus();
        } else if ($.inArray(e.which, keys) >= 0) {
            return true;
        } else if (this.value.length >= charLimit) {
            $(this).next('.inputs').focus();
            return false;
        } else if (e.shiftKey || e.which <= 48 || e.which >= 58) {
            return false;
        }
    }).keyup (function () {
        if (this.value.length >= charLimit) {
            $(this).next('.inputs').focus();
            return false;
        }
    });
});

DEMO

Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
  • 2
    Wow this is excellent. I'll combine that with click(), so it resets the value when the user selects an already filled textbox. Right now if the user selects a filled input and types a number it focuses on the not the next input but the one after it (assuming all textboxes are filled). In an ideal scenario I guess it would not require deleting the number before typing a new one (it would replace it automatically). I can see how this would become problematic to implement with more than 1 char limit though. Just my thoughts. click() will do the trick for me anyway :) – domino May 10 '12 at 21:37
  • @domino Nice find, but just couldn't let go of that.. so here the fix >> http://jsfiddle.net/skram/qygB2/5/ << . Please try and let me know. – Selvakumar Arumugam May 10 '12 at 22:08
  • if there are input type disabled what should i modify to make it working ? – Freddy Sidauruk Feb 13 '17 at 11:03
  • Is it accepting the zero value? I tried but it's not accepting. Also, what is the meaning of the keys number? – user9437856 Jun 23 '21 at 03:59
7

try this

jQuery.extend(jQuery.expr[':'], {
    focusable: function (el, index, selector) {
        return $(el).is('a, button, :input,[tabindex]');
    }
});
$(document).on('keypress', 'input,select', function (e) {
    if (e.which == 13) {
        e.preventDefault();
        // Get all focusable elements on the page
        var $canfocus = $(':focusable');
        var index = $canfocus.index(document.activeElement) + 1;
        if (index >= $canfocus.length) index = 0;
        $canfocus.eq(index).focus();
    }
});
sathish gowda
  • 71
  • 1
  • 1
  • 1
    Best solution I have seen for mimicking a keypress. For some reason the `$(':focusable')` selector worked for me without extending jQuery, so the only code I needed was the four lines following the `//Get all ...` comment. – mike Mar 02 '20 at 01:25
5

That will just get the next element, whatever it is. You probably want:

$(".inputs").keyup(function () {
  $(this).next(".inputs").focus();
});

Also, key up not keydown or it will change too soon.

Jivings
  • 22,834
  • 6
  • 60
  • 101
2

Here is the code I use for making enter key to behave as tab, i.e, focus to next element when pressing the Enter key or focusing previous element when pressing shift+Enter.

1) Essentially:

tabables = $("*[tabindex != '-1']:visible");
var index = tabables.index(element);
tabables.eq(index + 1).focus();

2) Here you are a "class" that encapsulates the behaviour, having in mind fordward and backwards and valid focusable elements.

I hope it helps and if some code suits your needs, feel free to adapt to your needs :)

EnterAsTab = function () {
    this.ENTER_KEY = 13;
};

EnterAsTab.prototype.init = function () {
    this.listenOnEnterKey();
};

EnterAsTab.prototype.listenOnEnterKey = function () {

    var me = this;
    $('form input').on('keypress', function (event) {

            if (event.which === me.ENTER_KEY) {

                if (!event.shiftKey)
                    me.findNextFocusableElement(this);
                else
                    me.findPreviousFocusableElement(this);

                event.preventDefault();
            }
        }
    );
};

EnterAsTab.prototype.findNextFocusableElement = function (element) {
    this.findFocusableElement(element, this.increaseIndex);
};

EnterAsTab.prototype.findPreviousFocusableElement = function (element) {
    this.findFocusableElement(element, this.decreaseIndex);
};

EnterAsTab.prototype.findFocusableElement = function (element, callable) {

    var tabables = $("*[tabindex != '-1']:visible");
    var index = tabables.index(element);
    var counter = 1;
    var nextElement = undefined;

    try {

        while (true) {

            if ((nextElement = tabables.eq(index + counter)).length === 0) {
                break;
            }

            if (this.isFocusableElement(nextElement)) {

                var newIndex = callable.call(this, index, counter);
                tabables.eq(newIndex).focus();

                break;
            } else {
                counter++;
            }
        }
    } catch (error) {
        console.log(error);
    }

};

EnterAsTab.prototype.increaseIndex = function (index, counter) {
    return (index + counter);
};

EnterAsTab.prototype.decreaseIndex = function (index, counter) {
    return index - counter;
};

EnterAsTab.prototype.isFocusableElement = function (element) {

    return ['SELECT', 'TEXTAREA'].indexOf(element.prop('tagName')) > -1 ||
        element.is(':text') ||
        element.is(':checkbox') ||
        element.is(':radio');
};

var enterAsTab = new EnterAsTab();
enterAsTab.init();
Samuel Vicent
  • 991
  • 10
  • 16
1

After searching and developing I end up in a crossbrowser snippet which makes it possible to focus the next input field with same class depending on maxlength (tested with 1 character) also with the ability to focus back via backspace button:

Javascript (jquery):

var codeCharInput = 'input.code-char';
$(codeCharInput+':first').focus();
$(codeCharInput).keyup(function(e) {
  if ((e.which == 8 || e.which == 46)) {
    $(this).prev(codeCharInput).focus().val($(this).prev().val());
  } else {
    if (this.value.length == this.maxLength) {
      $(this).next(codeCharInput).focus();
    }
  }
});

HTML:

<input type="text" name="chars[]" maxlength="1" class="code-char" />
<input type="text" name="chars[]" maxlength="1" class="code-char" />
<input type="text" name="chars[]" maxlength="1" class="code-char" />
<input type="text" name="chars[]" maxlength="1" class="code-char" />
ggzone
  • 3,661
  • 8
  • 36
  • 59
1

If you just want to look at the next input but you have say separators in the way like this

<input type="number" pattern="[0-9]*" inputmode="numeric" maxlength="2" placeholder="DD" name="dobday" id="dobday">
<div class="separator">/</div>
<input type="number" pattern="[0-9]*" inputmode="numeric" maxlength="2" placeholder="MM" name="dobmonth" id="dobmonth">
<div class="separator">/</div>
<input type="number" pattern="[0-9]*" inputmode="numeric" maxlength="4" placeholder="YYYY" name="dobyear" id="dobyear">

You will need to you the this code to get all the next items and settle on the first input found:

$('input#dobday,input#dobmonth,input#dobyear').on('input', function(e) {
    if (jQuery(this).val().length >= parseInt(jQuery(this).attr("maxlength"), 10)) {
            if (jQuery(this).attr('id') === 'dobyear') {
                jQuery(this).blur();
            } else {
                jQuery(this).nextAll('input:first').focus();
            }
    }
}
Phil Cook
  • 2,025
  • 19
  • 25
1

This works perfectly It also checks if the middle inputs are filled

$(".inputs").keyup( function () {

    if (this.value.length == this.maxLength) {
    var n=$(this).next('.inputs');
    n.focus();
   if(n.val().length==n.prop('maxlength')) n.next('.inputs').focus(); 
    }

});
The concise
  • 444
  • 4
  • 12
0

Use keyup e.g.

$(".inputs").keyup(function () {
    $(this).next().focus();
});​

See it in action http://jsfiddle.net/qygB2/

Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
0

If you're using the latest jQuery version, I strongly recommend you to use the on method. If you go to the jQuery source code, you'll notice that all the other event methods now redirect to this method, so why don't use it directly:

$(document).ready(function () {
        $('.inputs').on('keyup', function(){
            $(this).next().focus();
        })
});
marcos.borunda
  • 1,486
  • 1
  • 17
  • 34
0

This will keep focus on the text box, after using next without naming the class or id.

 $(this).hide();        
 $(this).next().show();
 $('input[type=text]').focus();
Mikeys4u
  • 1,494
  • 18
  • 26
0

Building on @Vega's answer

inputs.keydown(function(e) {
    var keys = [8, 9, /*16, 17, 18,*/ 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 144, 145];

    $(this).val('');

    if (e.which == 8 && this.value.length == 0) {
        $(this).prev(inputs).focus();
    } else if ($.inArray(e.which, keys) >= 0) {
        return true;
    } else if (this.value.length > charLimit) {
        $(this).next(inputs).focus();
        return false;
    } else if (e.shiftKey || e.which <= 48 || e.which >= 58) {
        return false;
    }
}).keyup (function () {
    if (this.value.length >= charLimit && $(this).next(inputs).attr('type') === 'text') {
        $(this).next(inputs).focus();
        return false;
    }
});

If a user clicks on an input that already has a value it will override it, instead of going to the next input, it will also only focus on text inputs. I had a situation where I had a submit input next to the text inputs and if using backspace could accidentally redirect the page.

Melbourne2991
  • 11,707
  • 12
  • 44
  • 82
0

This is the code that complete your all needs.

$(".input").keyup(function(e) {

if (e.which == 8 || e.which == 46){ 
    //backspace / Delete
    $(this).val('');
    $(this).prevAll('input:first').focus();
}
else
{ 
    var spcl_arr = ["~","!","@", "#", "$", "%", "^", "&", "*", "(", ")", "+","-", "=", "." ,"/"];
   if(e.which == 13){ // Enter Kay
      return false;
   }
  else if(jQuery.inArray($(this).val(), spcl_arr) !== -1 ){ 
         $(this).val('');
         $(this).focus();
        return false;
   }else{ 
       var regex = new RegExp("^[a-zA-Z0-9]+$");
        var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
        if (regex.test(str)) { 
             if (this.value.length == this.maxLength) {
                 $(this).next('.input').focus();
             }
        }else{
            $(this).val('');
            $(this).focus();
            return false;
        }
    }
}

});

Sandeep Sherpur
  • 2,418
  • 25
  • 27