Auto Selecting the next Input field and going Back

问题: Once inputed, a user can't go back to change their input. $("form").on("keyup change paste", function(e) { e.preventDefault(); var a = $(this).find("in...

问题:

Once inputed, a user can't go back to change their input.

$("form").on("keyup change paste", function(e) {
  e.preventDefault();

  var a = $(this).find("input[type='text'].a");
  var b = $(this).find("input[type='text'].b");
  var c = $(this).find("input[type='text'].c");
  var d = $(this).find("input[type='text'].d");
  var e = $(this).find("input[type='text'].e");
  var f = $(this).find("input[type='text'].f");

  a.val(a.val().replace(/[^0-9]/g, ""));
  b.val(b.val().replace(/[^0-9]/g, ""));
  c.val(c.val().replace(/[^0-9]/g, ""));
  d.val(d.val().replace(/[^0-9]/g, ""));
  e.val(e.val().replace(/[^0-9]/g, ""));
  f.val(f.val().replace(/[^0-9]/g, ""));

  if (a.val().length == a.attr('maxlength')) {
    a.next("input").focus();
  }
  if (b.val().length == a.attr('maxlength')) {
    b.next("input").focus();
  }
  if (c.val().length == a.attr('maxlength')) {
    c.next().next("input").focus();
  }
  if (d.val().length == a.attr('maxlength')) {
    d.next("input").focus();
  }
  if (e.val().length == a.attr('maxlength')) {
    e.next("input").focus();
  }
  if (f.val().length == a.attr('maxlength')) {
    f.next("input").focus();
  }
});
input {
  width: 20px;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="code" action="*" method="post" autocomplete="off">
  <input type="text" name="code" maxlength="1" autocomplete="off" class="a">
  <input type="text" name="code" maxlength="1" autocomplete="off" class="b">
  <input type="text" name="code" maxlength="1" autocomplete="off" class="c">
  <span>—</span>
  <input type="text" name="code" maxlength="1" autocomplete="off" class="d">
  <input type="text" name="code" maxlength="1" autocomplete="off" class="e">
  <input type="text" name="code" maxlength="1" autocomplete="off" class="f last">
</form>

How can that be done?

And is there a more elegant approach to mine above?


Live: jsFiddle


回答1:

Any time you find yourself finding very repetitious code, always think LOOP.

The below will allow the user to edit their values. It also greatly reduces your code.

$('form').on('input', e => {
    var letters = ['a', 'b', 'c', 'd', 'e', 'f'];
    letters.forEach(letter => {
        let field = $(e.target);
        field.val(field.val().replace(/[^0-9]/g, ''));
        if(field.val().length == field.attr('maxlength')) { field.nextAll('input').first().focus(); }
    });
});

Fiddle.

Notes:

  • Listen for the input event; it has the advantage of covering all the events you were listening for, and, crucially, fires after keypress (meaning you can be sure of grabbing the latest, complete value from the field)
  • avoid repetitious code; the loop allows us to write the business logic once rather than repeatedly
  • there is no need to prevent the event's default action
  • by using nextAll('input').first(), we can be sure of getting the next input, whether it's the next sibling or, as is the case with the third input, separated by another type of element

回答2:

My idea would be to focus next, and loop when arriving at the last one. Replace the number in case of a new entry.

// init the html
const nbInput = 6;

let html = '';

for (let i = 0; i < nbInput; i += 1) {
  html += `<input type="text" name="code" maxlength="1" autocomplete="off" number="${i}">`;
}

$('form').html(html);

$('form input').on('keypress', function(e) {
  e.preventDefault();
  
  // Ignore bad values
  if (/^[^0-9]$/g.test(String.fromCharCode(e.which))) {
    return;
  }

  // Replace the actual value with the keypressed one
  $(this).val(String.fromCharCode(e.which));

  // Reset & focus next
  if ($(this).val() !== '' && Number($(this).attr('number')) < (nbInput - 1)) {
    $(`input[number=${Number($(this).attr('number')) + 1}]`).focus();
  } else {
    // Focus the first item when we finished
    $('input[number="0"]').focus();
  }
});
input {
  width: 20px;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="code" action="*" method="post" autocomplete="off">
</form>


回答3:

Clearing the inputs on focus would do it. (I don't use jQuery much, so apologies if I have any incorrect syntax.)

$("form").focus(function() {

    var a = $(this).find("input[type='text'].a")
    var b = $(this).find("input[type='text'].b") // ...etc  

    a.val("");
    b.val(""); // ...etc
});

That said, Utkanos is 100% correct that a loop is the right way to handle both issues (auto-advancing and allowing edits).

  • 发表于 2019-01-18 21:09
  • 阅读 ( 178 )
  • 分类:网络文章

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除