按住键时,跨浏览器方式可自动重复键控事件

时间:2012-12-25 04:59:53

标签: javascript jquery events keydown

使用Javascript / jQuery,当有人按下某个键时,如何自动重复keydown事件或同等事件?

我真正想要的是能够检查一个键是否关闭,但从其他问题来看,这似乎是不可能的。建议的解决方法似乎是记录keydown和keyup事件,然后假设密钥已关闭,如果已记录keydown事件并且没有后续的keyup。

在我的案例中,该解决方案遇到了问题。我正在设计一个在线实验。用户应该按住“T”键进行整个实验,从不放松。该实验包括多个试验,每个试验都无法获得先前试验记录的信息。因此,试验1可记录T的keydown,但试验2无法访问该记录,因此不知道T是否已关闭。

现在,如果按住T键会自动为T生成重复的keydown事件,我就没有问题,因为试验2只会捕获T的下一个keydown事件。但看起来我从按住键自动重复keydown事件,至少在Firefox中。从我所看到的情况来看,似乎不同浏览器处理按键的方式存在差异。什么是解决我的问题的良好的跨浏览器方式?

顺便说一句,如果重要的话,我还需要能够检测其他键的keyup和keydown事件,而这一切都在继续。

编辑:在阅读了一些评论之后,我回过头来验证我确实在一般情况下会重复keydown事件。但我真的不能在需要它们的特定情况下得到它们。我有一些简单的代码,我认为可以隔离这个问题:

<!DOCTYPE html>
<html>

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
</head>

<body>
<div id="target"></div>
</body>

<script type="text/javascript">

var i;
function foo() {
    i++;
    $('#target').html(i);
}

function doTrial() { // do trial
    i=0;
    $(document).keydown(foo);
    $(document).keyup(endTrial);
}

function endTrial() { // end trial
    $('#target').html('');
    $(document).unbind('keydown',foo);
    $(document).unbind('keyup',endTrial);
    doTrial();
}

doTrial();

</script>

</html>

如果按一个键并按住它,然后松开,然后再次按下,行为就像预期的那样,即有一个计数器在按住键时递增,在释放时消失,然后再次开始递增什么时候再次按下。

但是如果按下两个键,然后释放一个,我会认为另一个(未发布)键会继续发送keydown事件,以便计数器(重置后)继续递增。事实上,这不会发生。知道为什么以及如何实现它?

2 个答案:

答案 0 :(得分:6)

在我尝试过的浏览器中,当按下可键入的键时,我得到了重复的keydown事件。我不知道这是否是您实际需要解决的问题。

但是,如果你认为你需要解决它,或者如果你想自己控制重复率,你可以这样做:

  1. 捕获keydown和keyup的事件。
  2. 在keydown上,设置一个间隔计时器,但是通常会想要知道该键仍处于关闭状态。
  3. 在该键的键盘上,停止间隔计时器。
  4. 只要按住键,您就会以跨浏览器的方式重复通知。
  5. 此处的演示演示:http://jsfiddle.net/jfriend00/XbZYs/

    var downTimer;
    var lastKey;
    $(document.body).keydown(function(e) {
        // if not still the same key, stop the timer
        if (e.which !== lastKey) {
            if (downTimer) {
                clearInterval(downTimer);
                downTimer = null;
            }
        }
        // remember previous key
        lastKey = e.which;
        if (!downTimer) {
            // start timer
            downTimer = setInterval(function() {
                $("#result").append("+");
            }, 125);
        }
    }).keyup(function(e) {
        // stop timer
        if (downTimer) {
            clearInterval(downTimer);
            downTimer = null;
            lastKey = 0;
        }
    });
    

    如果你想要一个键永远自动重复,直到它被引发,即使在此期间按下并释放了其他键并且你希望那些其他键自己重复执行,那么操作系统也不会ipmlement行为所以你必须自己实现它。您可以执行类似这样的操作,为每个键重复事件调用回调函数:

    工作演示:http://jsfiddle.net/jfriend00/aD3Eg/

    // this is called for every manufactured repeat event
    // the frequency of the repeat event is determined by the time value set
    // on setInterval() below
    function repeatCallback(key) {
        $("#result").append(key + " ");
    }
    
    var repeatState = {};
    $(document.body).keydown(function(e) {
        var key = e.which;
        // if no time yet for this key, then start one
        if (!repeatState[key]) {
            // make copy of key code because `e` gets reused
            // by other events in IE so it won't be preserved
            repeatState[key] = setInterval(function() {
                repeatCallback(key);
            }, 125);
        } else {
            // nothing really to do here
            // The key was pressed, but there is already a timer
            // firing for it
        }
    }).keyup(function(e) {
        // if we have a timer for this key, then stop it 
        // and delete it from the repeatState object
        var key = e.which;
        var timer = repeatState[key];
        if (timer) {
            clearInterval(timer);
            delete repeatState[key];
        }
    });
    ​
    

    对所有这些制造的自动重复事件调用repeatCallback函数,并传递自动重复的键。

答案 1 :(得分:0)

看看这个jQuery插件:fastKeys我认为,这是你想要/需要的......