Binding arrow keys in JS/jQuery
Asked Answered
A

16

442

How do I go about binding a function to left and right arrow keys in Javascript and/or jQuery? I looked at the js-hotkey plugin for jQuery (wraps the built-in bind function to add an argument to recognize specific keys), but it doesn't seem to support arrow keys.

Atonic answered 9/9, 2009 at 23:37 Comment(2)
Possible duplicate of How to detect escape key press with pure JS or jQuery?Tempa
@Tempa That question was posted way after this one...Murage
L
569
document.onkeydown = function(e) {
    switch(e.which) {
        case 37: // left
        break;

        case 38: // up
        break;

        case 39: // right
        break;

        case 40: // down
        break;

        default: return; // exit this handler for other keys
    }
    e.preventDefault(); // prevent the default action (scroll / move caret)
};

If you need to support IE8, start the function body as e = e || window.event; switch(e.which || e.keyCode) {.


(edit 2020)
Note that KeyboardEvent.which is now deprecated. See this example using KeyboardEvent.key for a more modern solution to detect arrow keys.

Lyrebird answered 15/5, 2011 at 20:43 Comment(8)
By far best answer. Uses e.which like jQuery recommends for cross-browser, uses e.preventDefault() instead of return false (return false on a jQuery event handler triggers both e.preventDefault() and e.stopPropagation(), the second of which is going to cause any later added events to fail since the event won't propagate to them), and at the end of the switch, will return without calling e.preventDefault() if it's any other key than the ones being looked for to not hinder other key usage, and instead of $.ui.keyCode.DOWN it compares to the numbers (MUCH faster).Macronucleus
Nathan: it seems that not all keycodes are consistent among browsers, but the arrow keys are some of those that are. See here: #5603695Lyrebird
@JimboJonny: Can you explain why comparing with magic numbers is so much faster than comparing with constants, which, as far as I can tell, are just numbers? I ask this in all sincerity, even though I strongly doubt dereferencing pointers has a significant enough performance penalty in any browser, for users to notice when they release a key.Chiromancy
@MichaelScheper - 1) variables != constants, regardless of whether or not they are intended to be changed...the engine still has to treat them like vars until ES6 constants are ubiquituous enough that jQuery can use constants 2) numbers aren't really magic numbers when there is comment right beside them telling exactly what they are, and 3) ...continuedMacronucleus
... 3) when accessing $.ui.keyCode.DOWN you look for $ in your lexical scope, not finding it, going up a level...looking for $, repeat until in global scope, find it on the global window, access $ on window, access ui on window.$, access keyCode on window.$.ui, access DOWN on window.$.ui.keyCode to get to the primitive value you want to compare, then do your actual comparing. Whether or not that speed matters to you is a personal decision, I just have a tendency to avoid 4 levels of accessing when there's a situation where I can just as easily write/comment the primitive.Macronucleus
Note that arrow keys are not captured in keypressDunedin
@NathanArthur Here I found two good online tools to test the keyboard keycodes: keycode.info asquare.net/javascript/tests/KeyCode.html unixpapa.com/js/key.htmlNebulize
e.preventDefault() did NOT work for me. The page is still scrolling. I also tried event.stopImmediatePropagation(); event.stopPropagation(); event.preventDefault(); and returning false. Nothing worked so far. I am using a knockout event binding (keyup) though, so probably related.Cuttlebone
Z
467
$(document).keydown(function(e){
    if (e.which == 37) { 
       alert("left pressed");
       return false;
    }
});

Character codes:

37 - left

38 - up

39 - right

40 - down

Zicarelli answered 9/9, 2009 at 23:48 Comment(11)
Is there any purpose for the return?Atonic
It stops any further keydown events being hit.Dictograph
Shadow: no, he means it stops the keydown event from firing on other DOM elementsLassiter
Except 39 is also apostrophe, isn’t it?Eminent
@PaulD.Waite - 39 is the ASCII for apostrophe, these are keycodes.Talion
When using jQuery, use e.which rather than e.keyCode for more browser support. See my comment below.Lyrebird
The keydown function isn't called for my arrows keys on the MBP13 but characters work out fine. Any ideas on how to get the event?Horsewhip
What about the number keys on the numpad?Elkeelkhound
@Josh.. if you want to move in 8 directions (up-left) etc, how would you implement it?Spun
@Spun look for a keydown for two arrow keys at once and move diagonally. measure keydown and keyup separately, i'd imagine.Zicarelli
And use $("selector").focus().keydown([...]); to focus directly and start using the arrows without additional interaction. :)Avilla
S
109

You can use the keyCode of the arrow keys (37, 38, 39 and 40 for left, up, right and down):

$('.selector').keydown(function (e) {
  var arrow = { left: 37, up: 38, right: 39, down: 40 };

  switch (e.which) {
    case arrow.left:
      //..
      break;
    case arrow.up:
      //..
      break;
    case arrow.right:
      //..
      break;
    case arrow.down:
      //..
      break;
  }
});

Check the above example here.

Salaidh answered 9/9, 2009 at 23:49 Comment(3)
I'm not sure about your use of the || operator in line 2. Isn't a value other than zero or nonzero implementation specific and not guaranteed? I would use something more like: var keyCode = (e.keyCode?e.keyCode:e.which); +1 for the use of the arrow object to give the cases readable names.Sedition
If you are using jQuery, you dont need to test for e.which: The event.which property normalizes event.keyCode and event.charCode - api.jquery.com/event.whichUnitive
I'm trying to put a key event listener on a table, but it wouldn't work. Is there a limited amount of selector types that support key event listeners?Torrent
S
23

This is a bit late, but HotKeys has a very major bug which causes events to get executed multiple times if you attach more than one hotkey to an element. Just use plain jQuery.

$(element).keydown(function(ev) {
    if(ev.which == $.ui.keyCode.DOWN) {
        // your code
        ev.preventDefault();
    }
});
Supercargo answered 25/7, 2010 at 6:28 Comment(2)
+1 for using the ui keycode object. Much easier to understand than 37, 38, 39, or 40. Not sure why the top answer is using e.keyCode when the jQuery documentation explicitly states to use e.which to account for browser differences. Hopefully this answer gets more recognition for doing it right.Pentylenetetrazol
Using $.ui.keyCode.DOWN on every key press is a LOT slower than using the number. Just add a comment if concerned about clarity, especially since it has to be run every time any key is pressed.Macronucleus
S
16

I've simply combined the best bits from the other answers:

$(document).keydown(function(e){
    switch(e.which) {
        case $.ui.keyCode.LEFT:
        // your code here
        break;

        case $.ui.keyCode.UP:
        // your code here
        break;

        case $.ui.keyCode.RIGHT:
        // your code here
        break;

        case $.ui.keyCode.DOWN:
        // your code here
        break;

        default: return; // allow other keys to be handled
    }

    // prevent default action (eg. page moving up/down)
    // but consider accessibility (eg. user may want to use keys to choose a radio button)
    e.preventDefault();
});
Silvery answered 15/10, 2012 at 21:12 Comment(2)
Where is "ui" coming from? Getting " TypeError: $.ui is undefined " EDIT - I was missing JQuery UI. Got that loaded - no more error.Counterpoint
He's apparently also using jQuery UI which must have that enum. I wouldn't include jQuery UI just for that, btw.Borchert
S
14

You can use KeyboardJS. I wrote the library for tasks just like this.

KeyboardJS.on('up', function() { console.log('up'); });
KeyboardJS.on('down', function() { console.log('down'); });
KeyboardJS.on('left', function() { console.log('right'); });
KeyboardJS.on('right', function() { console.log('left'); });

Checkout the library here => http://robertwhurst.github.com/KeyboardJS/

Scarface answered 2/11, 2012 at 20:1 Comment(0)
S
14

A terse solution using plain Javascript (thanks to Sygmoral for suggested improvements):

document.onkeydown = function(e) {
    switch (e.keyCode) {
        case 37:
            alert('left');
            break;
        case 39:
            alert('right');
            break;
    }
};

Also see https://mcmap.net/q/64079/-detecting-arrow-key-presses-in-javascript.

Setscrew answered 29/7, 2013 at 16:17 Comment(1)
Probably also worth binding via document.addEventListener('keydown', myFunction);Cuccuckold
S
9

Are you sure jQuery.HotKeys doesn't support the arrow keys? I've messed around with their demo before and observed left, right, up, and down working when I tested it in IE7, Firefox 3.5.2, and Google Chrome 2.0.172...

EDIT: It appears jquery.hotkeys has been relocated to Github: https://github.com/jeresig/jquery.hotkeys

Streamlined answered 9/9, 2009 at 23:51 Comment(1)
I was reading where it said it was based on another library, and assumed that list of supported keys still applied.Atonic
I
5

Instead of using return false; as in the examples above, you can use e.preventDefault(); which does the same but is easier to understand and read.

Isaisaac answered 16/2, 2011 at 16:1 Comment(1)
return false; and e.preventDefault(); are not exactly the same. See https://mcmap.net/q/40403/-event-preventdefault-vs-return-falseTavarez
O
4

You can use jQuery bind:

$(window).bind('keydown', function(e){
    if (e.keyCode == 37) {
        console.log('left');
    } else if (e.keyCode == 38) {
        console.log('up');
    } else if (e.keyCode == 39) {
        console.log('right');
    } else if (e.keyCode == 40) {
        console.log('down');
    }
});
Owain answered 18/11, 2013 at 16:57 Comment(0)
T
4

Example of pure js with going right or left

        window.addEventListener('keydown', function (e) {
            // go to the right
            if (e.keyCode == 39) {

            }
            // go to the left
            if (e.keyCode == 37) {

            }
        });
Tub answered 18/8, 2017 at 11:57 Comment(0)
C
2

You can check wether an arrow key is pressed by:

$(document).keydown(function(e){
    if (e.keyCode > 36 && e.keyCode < 41) { 
       alert( "arrowkey pressed" );
       return false;
    }
});
Connivance answered 18/12, 2014 at 3:3 Comment(0)
L
1

A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies.

http://jaywcjlove.github.io/hotkeys/

hotkeys('right,left,up,down', function(e, handler){
    switch(handler.key){
        case "right":console.log('right');break
        case "left":console.log('left');break
        case "up":console.log('up');break
        case "down":console.log('down');break
    }
});
Leroylerwick answered 9/9, 2009 at 23:37 Comment(0)
N
0

prevent arrow only available for any object else SELECT, well actually i haven't tes on another object LOL. but it can stop arrow event on page and input type.

i already try to block arrow left and right to change the value of SELECT object using "e.preventDefault()" or "return false" on "kepress" "keydown" and "keyup" event but it still change the object value. but the event still tell you that arrow was pressed.

Notch answered 16/4, 2015 at 3:45 Comment(0)
P
0

I came here looking for a simple way to let the user, when focused on an input, use the arrow keys to +1 or -1 a numeric input. I never found a good answer but made the following code that seems to work great - making this site-wide now.

$("input").bind('keydown', function (e) {
    if(e.keyCode == 40 && $.isNumeric($(this).val()) ) {
        $(this).val(parseFloat($(this).val())-1.0);
    } else if(e.keyCode == 38  && $.isNumeric($(this).val()) ) { 
        $(this).val(parseFloat($(this).val())+1.0);
    }
}); 
Precambrian answered 4/1, 2016 at 15:11 Comment(0)
F
-1

With coffee & Jquery

  $(document).on 'keydown', (e) ->
    switch e.which
      when 37 then console.log('left key')
      when 38 then console.log('up key')
      when 39 then console.log('right key')
      when 40 then console.log('down key')
    e.preventDefault()
Fill answered 31/10, 2014 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.