keyup事件处理程序更改焦点无法快速键入

时间:2016-05-19 17:51:25

标签: javascript jquery keyup

我想要一个PIN输入表单,其中每个字符都输入一个单独的html输入。

我正在尝试在javascript中捕获keyup事件,以便我可以将焦点更改为下一个输入元素,从而使用户无需通过鼠标单击或选项卡自行更改它。

除非用户输入非常快,否则它正在工作。例如,如果用户非常快速地键入字符“1”和“2”,我发现第一个输入现在正确地具有字符“1”,而第二个输入仍然是空的,并且焦点已移至第三个输入

为什么呢?

以下是代码:

$(document).ready(function () {

            $('.pinchar').keyup(function (e) {
				
                if (
                    (e.which == 8) //backspace
                    || (e.which == 46) // del
                    || (e.which == 9) // tab
                    || (e.which == 13) // return
                    || (e.which == 27) // esc
                    || (e.which == 37) // arrow
                    || (e.which == 38) // arrow
                    || (e.which == 39) // arrow
                    || (e.which == 40) // arrow
                    || (e.which == 27) // esc
                    || (e.which == 20) // CAPS LOCK 
                    || (e.which == 17) // Ctrl
                    || (e.which == 18) // Alt 
                    || (e.which == 16)) { //shift

                    return false;
                } else {
                    $(this).parent().next().find('.pinchar').focus();
                }
            });
  
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="enterPINTable">
      <tr>
        <td>
          <input name="txtPIN1" id="txtPIN1" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN2" id="txtPIN2" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN3" id="txtPIN3" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN4" id="txtPIN4" class="pinchar" size="1">
        </td>
      </tr>
    </table>

2 个答案:

答案 0 :(得分:3)

按下某个键时,

keyup将失败,然后在释放之前按下另一个键。然后,事件的顺序为keydown 1keydown 2keyup 1keydown 2。但是,在keydown(和keypress)之后生成字符时,在这种情况下,在第一个input事件之前,keyup中已经有两个字符。

而是尝试input事件:

  $('.pinchar').on('input', function (e) {
       // ... etc.

任何更改都会立即触发。

但要正确处理其他键,您还需要捕获keydown事件(对于箭头和退格键)。

我会建议这段代码:

function step(inp, dir, clr) {
    if (clr) $(inp).val('');
    var $next = $(inp).parent()[['prev','next'][dir]]().find('.pinchar');
    if (!$next.length) $next = $(inp);
    $next.focus();
    setTimeout(function () { 
        $next.select();
    }, 0);
    return false;
}
$(document).ready(function () {
    $('.pinchar').on('focus', function () {
        $(this).select(); // always select the "whole" (1 char) text
    });
    $('.pinchar').on('keydown', function (e) {
        // arrows
        if (e.which == 37 || e.which == 38) return step(this, 0);
        if (e.which == 39 || e.which == 40) return step(this, 1);
        // backspace
        if (e.which == 8) return step(this, 0, 1);
    });
    $('.pinchar').on('input', function (e) {
        step(this, 1);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="enterPINTable">
  <tr>
    <td>
      <input name="txtPIN1" id="txtPIN1" class="pinchar" size="1">
    </td>
    <td>
      <input name="txtPIN2" id="txtPIN2" class="pinchar" size="1">
    </td>
    <td>
      <input name="txtPIN3" id="txtPIN3" class="pinchar" size="1">
    </td>
    <td>
      <input name="txtPIN4" id="txtPIN4" class="pinchar" size="1">
    </td>
  </tr>
</table>

请注意,上面的代码旨在始终选择当前字符,因此如果您键入另一个字符,它将替换当前字符。

leftrighttabshift + tabbackspacedelete密钥也可以正常工作可以预料。

答案 1 :(得分:2)

在这种情况下,Keypress更适合。

问题是密钥被触发得很晚,即在keydown和keypress之后。

订单如下:

按下键时,会立即触发keydown事件。在该事件中,该值不会打印在屏幕上。触发该按键后,此时将打印该值。
在两个事件之后,当您将手指从钥匙上抬起时,触发了键盘。

因此,当您快速按下两个键时,它们的按键会快速连续调用(在屏幕上打印值时),因此值将打印在同一输入上,然后调用两个键,将焦点转移到下一个输入的下一个(将它们留空是因为在按键期间已经打印了值。)

&#13;
&#13;
$(document).ready(function () {

            $('.pinchar').keypress(function (e) {
				
               $(this).parent().next().find('.pinchar').focus();
               
            });
  
  });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="enterPINTable">
      <tr>
        <td>
          <input name="txtPIN1" id="txtPIN1" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN2" id="txtPIN2" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN3" id="txtPIN3" class="pinchar" size="1">
        </td>
        <td>
          <input name="txtPIN4" id="txtPIN4" class="pinchar" size="1">
        </td>
      </tr>
    </table>
&#13;
&#13;
&#13;