views:

1326

answers:

4

In my web app, I use the onkeydown event to capture key strokes.

For example, I capture the 'j' key to animate a scroll down the page (and do some other stuff meanwhile).

My problem is the user might keep the 'j' key down to scroll further down the page (this is equivalent to fast multiple key strokes).

In my app, this result in a series of animations that doesn't look that good.

How can I know when the key has been released, and know the amount of key stokes I should have captured? This way I could run one long animation instead of multiple short ones.

+1  A: 

Rather than trying to stack up the animations, you could start an animation on keyDown, and if at the end of the animation you haven't yet received keyUp then start another animation. As soon as you reach the end of an animation and you do have keyUp then you're done.

JMD
Thanks. How can I know if keyUp has been fierd while in my keyDown function? Can you give me a syntax example?
yoavf
+1  A: 

you can try using my repsonsiveness plugin see: http://notetodogself.blogspot.com/2008/12/jquery-responsiveness-plugin-for-fast.html

see the demo here: http://doesthatevencompile.com/current-projects/jquery.responsiveness/

the one where you type stuff fast. you can adapt that to your needs. like so: the animation event will be bound with the plugin, and execute when the user stops doing something fast. you can count how many times he does the fast thing by normal binding of the event.

mkoryak
+1  A: 

setTimeout returns a timer ID. So what I would do is after you receive a keyDown event, I would start a timer with a very short wait period, like so:

var globalTimerId = -1;
var keyDownCount = 0;

function handleKeyDown(e) {
    if (globalTimerId != -1) {
        clearTimeout(globalTimerId);
        keyDownCount++;
    }

    /* 500 means 1/2 a second, adjust for your needs */
    globalTimerId = setTimeout(handleKeyDownAfterWait, 500);
    keyDownCount = 1;
}

function handleKeyDownAfterWait() {
    globalTimerId = -1;
    /* keyDownCount will have the number of times handleKeyDown was called */
}

So the idea is that each time a keyDown event is received, the timer is cleared (assuming it hasn't elapsed yet) and restarted. If the timer expires, the user has let go of the key and you can handle that in handleKeyDownAfterWait.

There may be other more elegant solutions with jQuery or another JS library however. This is just something quick and dirty (and possibly buggy ;))

Sean Bright
+2  A: 

Building on @JMD:

var animate = false;

function startanimation()
{
  animate = true;
  runanimation();
}

function stopanimation()
{
  animate = false;
}

function runanimation()
{
  if ( animation_over )
  {
    if ( !animate )
    {
      return;
    }

    return startanimation();
  }

  // animation code

  var timeout = 25;
  setTimeout(function(){runanimation();},timeout);
}

document.onkeydown = startanimation;
document.onkeyup   = stopanimation;

You'll need to add some checks for starting/ending animations, however.

Edit: added a return to the JS; would've recursed endlessly.

kyle
Thanks @kyle -- I'm no javascript expert, so I'm glad you stepped in. +1
JMD