Jquery 关注下一个元素的Keyup事件处理程序在键入太快时会丢失刚刚输入的字符

Jquery 关注下一个元素的Keyup事件处理程序在键入太快时会丢失刚刚输入的字符,jquery,Jquery,我有一个网页,有16个文本框,排列成4x4网格。其思想是,用户将在每个文本框中精确地键入一个字符(特别是一个字母)。您可以在以下位置在线查看此页面: 我希望发生的事情如下: 当页面加载时,左上角的文本框被聚焦 在文本框中键入字母应输入该字母,然后自动将焦点设置为网格中的下一个文本框 如果用户选择了一个文本框(通过鼠标或按住Shift键并切换回上一个文本框),则应选择文本框中的条目,以便他们只需键入新字母即可覆盖旧字母 大部分情况下,我都能做到这一点,但有一个令人烦恼的问题——即,如果用户键入

我有一个网页,有16个文本框,排列成4x4网格。其思想是,用户将在每个文本框中精确地键入一个字符(特别是一个字母)。您可以在以下位置在线查看此页面:

我希望发生的事情如下:

  • 当页面加载时,左上角的文本框被聚焦
  • 在文本框中键入字母应输入该字母,然后自动将焦点设置为网格中的下一个文本框
  • 如果用户选择了一个文本框(通过鼠标或按住Shift键并切换回上一个文本框),则应选择文本框中的条目,以便他们只需键入新字母即可覆盖旧字母
大部分情况下,我都能做到这一点,但有一个令人烦恼的问题——即,如果用户键入字母太快,某些文本框将保持为空,好像在浏览器有机会将字母提交到具有焦点的文本框(如果有意义的话)之前,就出现了将用户带到下一个文本框的代码。如果你访问我的实时演示并开始以合适的速度输入,你会看到一些文本框是空白的

我的JavaScript可以完整地看到,它有以下代码用于选择/聚焦/移动到下一个文本框:

$("input.BoggleGridCell")
    .focus(function () {
        $(this).select();
    })
    .keyup(function (event) {
        var code = (event.keyCode ? event.keyCode : event.which);

        if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
            var currentId = $(this).attr('id');

            var leftDigit = currentId.substring(1, 2);
            var rightDigit = currentId.substring(2, 3);
            if (leftDigit != 3 || rightDigit != 3) {
                if (rightDigit == 3) {
                    rightDigit = 0;
                    leftDigit++;
                }
                else {
                    rightDigit++;
                }

                var moveToId = 'c' + leftDigit + rightDigit;
                var newCell = document.getElementById(moveToId);
                if (newCell)
                    newCell.focus();
            }
            else {
                $("#solve").focus();
            }
        }
    });
$(“input.BoggleGridCell”)
.focus(函数(){
$(this.select();
})
.keyup(功能(事件){
var代码=(event.keyCode?event.keyCode:event.which);

如果((code>=65&&code=97&&code浏览器DOM和事件在一致性和可预测性方面出了名的问题,尤其是在处理键盘或鼠标事件时。我的建议是重新设计这个想法……否则,您将很长一段时间都在关注类似的问题

看了你的演示后,我不太确定该推荐什么。有一个文本框来处理输入(它甚至可能是不可见/隐藏的)然后从那里发送事件-可能挂接“更改”事件而不是单个按键可能更可靠,尽管这可能与您尝试执行的操作有太多的偏离。而且它肯定会增加额外的复杂性,以允许编辑单个单元格(挂接模糊事件)

我的另一个想法是使keyup事件尽可能快地返回-将主体的大部分封装到一个匿名函数中,该函数被传递到setTimeOut()中调用。提前预计算下一个单元格可能也会有好处,这样您就可以跳过所有逻辑。我不知道这是否会解决性能问题,但是…警告我没有测试此代码-我将其作为一个想法提供。围绕$(this)调用的闭包可能会有问题

$("input.BoggleGridCell")
.focus(function () {
    $(this).select();
})
.keyup(function (event) {
    var code = (event.keyCode ? event.keyCode : event.which);
    if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
        setTimeOut(function(){
          var currentId = $(this).attr('id');
          var leftDigit = currentId.substring(1, 2);
          var rightDigit = currentId.substring(2, 3);
          if (leftDigit != 3 || rightDigit != 3) {
              if (rightDigit == 3) {
                  rightDigit = 0;
                  leftDigit++;
              } else {
                rightDigit++;
              }
              var moveToId = 'c' + leftDigit + rightDigit;
              var newCell = document.getElementById(moveToId);
              if (newCell)
                newCell.focus();
          } else {
            $("#solve").focus();
        }, 1);
    }
});
$(“input.BoggleGridCell”)
.focus(函数(){
$(this.select();
})
.keyup(功能(事件){
var代码=(event.keyCode?event.keyCode:event.which);

如果((code>=65&&code=97&&code),则问题可能是由于用户在键入时按键重叠造成的。要了解我的意思,请按住一个键,同时按下另一个键。这似乎与您所说的效果相同

编辑:从这一点来看,似乎第二个键的keyUp事件触发,然后第一个键的keyUp事件触发。但是,中断的顺序阻止第二次按键的字母插入到相应的输入中

您可以通过添加一个keyDown事件来解决这个问题,首先检查当前是否没有持有密钥

var pressed=0;
$("input.BoggleGridCell")

.focus(function () {

  $(this).select();

})
.keydown(function(event){
  var code = (event.keyCode ? event.keyCode : event.which);
  if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
    pressed=code;
  }
})      
.keyup(function (event) {
  if(pressed!=0){
    var code = (event.keyCode ? event.keyCode : event.which);
    if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
     //Your Code Here
    }
  }
  pressed=0;
}
});
var=0;
$(“input.BoggleGridCell”)
.focus(函数(){
$(this.select();
})
.keydown(功能(事件){
var代码=(event.keyCode?event.keyCode:event.which);

如果((code>=65&&code=97&&code=65&&code=97&&code找到了一个解决办法……我最终使用了jQuery的
keypress
事件加上JavaScript的
setTimeout
函数。下面是最后一段代码,它在IE 8、FF 3和Google Chrome中的工作情况与预期一致

$("input.BoggleGridCell")
    .focus(function () {
        $(this).select();
    })
    .keypress(function (event) {
        var code = (event.keyCode ? event.keyCode : event.which);

        if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
            var currentId = $(this).attr('id');

            var leftDigit = currentId.substring(1, 2);
            var rightDigit = currentId.substring(2, 3);
            if (leftDigit != 3 || rightDigit != 3) {
                if (rightDigit == 3) {
                    rightDigit = 0;
                    leftDigit++;
                }
                else {
                    rightDigit++;
                }

                setTimeout(function () {
                    var moveToId = 'c' + leftDigit + rightDigit;
                    var newCell = document.getElementById(moveToId);
                    if (newCell)
                        newCell.focus();
                }, 1);
            }
            else {
                setTimeout('$("#solve").focus();', 1);
            }
        }
    });
$(“input.BoggleGridCell”)
.focus(函数(){
$(this.select();
})
.按键(功能(事件){
var代码=(event.keyCode?event.keyCode:event.which);

如果((code>=65&&code=97&&code)您的解决方案可以正常工作。如果我快速键入,它不会跳过一个文本框,使其为空,但如果我连续键入两个字符,它会将我锁定在第一个文本框上,直到我键入的速度变慢(如果有意义的话).是的,我明白你的意思。在我的经验中,按键通常会导致界面有点粘。我没有想到按键和超时的组合。顺便说一句,很好的应用程序!我尝试了你的方法,但它导致了同样的问题。我有点接受了你的想法,但改用了按键事件(参见我的答案)而且它似乎像预期的那样工作。