0

I generate inputs (with a max length of 1) dynamically using JavaScript so I don't have to type them all in manually. I made them such that when I type into them, they go to the next input and when I press backspace, they delete the value inside the input, then go to the previous one.

Expected behaviour

When I press backspace, it'll delete the letter, then go to the previous input.

What actually happens

When I press backspace, it'll delete the letter, then do this weird shuffle, and then I press backspace again, and then it moves to the previous input.

Here is a JSFiddle that reproduces the issue I'm having.

Since Stack Overflow won't let me post this without code (here is the jQuery code):

function generateInputRows() {
  var inputHTML = "";
     for (var i = 0; i < 5; i++) {
       inputHTML += '<div class="inputColumn"><input maxlength="1" type="text"><div>';
       inputHTML += (i + 1);
       inputHTML += '</div></div>';
     }
     inputHTML += '</div>';
     return inputHTML;
 }

function setUpTyping(){
    $('.inputColumn input').on('input',function(event){
        var inputs = $('.inputColumn input');
        var index = inputs.index(this);
        inputs.eq(index + 1).focus();
    });

    $('.inputColumn input').on('keyup', function(e) {
        if(e.keyCode == 8 && $(this).val() == ""){
            var inputs = $('.inputColumn input');
            var index = inputs.index(this);
            inputs.eq(index - 1).focus();
        }   
    });
}

 $('#rows').html(generateInputRows());
 setUpTyping();
silverAndroid
  • 960
  • 3
  • 11
  • 29

2 Answers2

1

I think there are a lot of ways to solve this, such as tracking which input you are actively editing. However, for your current logic you just need to adjust the input event to check if the value is blank, before attempting to focus the next field.

$('.inputColumn input').on('input',function(e){
    var inputs = $('.inputColumn input');
    var index = inputs.index(this);
    if ($(this).val() != "") {
        inputs.eq(index + 1).focus();
    }
});
Mark
  • 1,564
  • 1
  • 14
  • 22
1

Why not use the same event for the logic as you can see in this Fiddle?

function generateInputRows() {
  var inputHTML = "";
  for (var i = 0; i < 5; i++) {
    inputHTML += '<div class="inputColumn"><input maxlength="1" type="text"><div>';
    inputHTML += (i + 1);
    inputHTML += '</div></div>';
  }
  inputHTML += '</div>';
  return inputHTML;
}

function setUpTyping() {
  $('.inputColumn input').on('keyup', function(e) {
    if (e.keyCode == 8 && $(this).val() == "") {
      var inputs = $('.inputColumn input');
      var index = inputs.index(this);
      inputs.eq(index - 1).focus();
    } else {
      var inputs = $('.inputColumn input');
      var index = inputs.index(this);
      inputs.eq(index + 1).focus();
    }
  });
}

$('#rows').html(generateInputRows());
setUpTyping();
dokgu
  • 4,957
  • 3
  • 39
  • 77
  • That worked! Was the issue something to do with the separate `input` event? – silverAndroid Feb 23 '17 at 19:51
  • 1
    @silverAndroid Yes - essentially it was the root of the "shuffle" you mentioned. Here's a good read on it: http://stackoverflow.com/questions/17384218/jquery-input-event – dokgu Feb 23 '17 at 19:53
  • They only down side here, is that things like shift/shift+tab will cause it move forward a box. Obviously there's other logic you could build in to prevent this, but just wanted to throw that out there. `keyup` isn't always the best, but it does have a lot of options to check. – Mark Feb 25 '17 at 01:00