15

I'm trying to set up a menu that can be navigated via the arrow keys. I have this working fin in Firefox.

Trying to get it to work in IE8 and after a bit of struggle, found that it was because IE8 wouldn't register a keypress on the arrows. To test:

$(document).keypress(function (eh){ 
    alert(eh.keyCode);
};

In Firefox, pressing any of the arrow keys would trigger an alert of 37, 38, 39 or 40.

In IE8, nothing. Any other key on the standard QWERTY keyboard would register, but not the arrow keys.

Is this an issue with my Javascript? A browser setting? A Windows setting?

Tim Down
  • 318,141
  • 75
  • 454
  • 536
DA.
  • 39,848
  • 49
  • 150
  • 213
  • 1
    Please don't forget to test if a user presses the Alt-key, too. It is really bad behaviour when you use and for navigation while preventing the default behaviour for browsing back and forth using and . – Marcel Korpel Feb 08 '10 at 03:00
  • @Marcel What does alt-arrow navigation do? I've never used it nor does it seem to do anything in the browsers I'm using. – DA. Feb 08 '10 at 15:37
  • At least in Firefox, Chrome and IE (just a quick test) is the same as pressing the back button, is like pressing the forward button (I very frequently use these hotkeys). – Marcel Korpel Feb 08 '10 at 16:58

4 Answers4

38

From the jQuery keypress documentation (the last paragraph of the introductory text):

Note that keydown and keyup provide a code indicating which key is pressed, while keypress indicates which character was entered. For example, a lowercase "a" will be reported as 65 by keydown and keyup, but as 97 by keypress. An uppercase "A" is reported as 97 by all events. Because of this distinction, when catching special keystrokes such as arrow keys, .keydown() or .keyup() is a better choice.

It even literally mentions about the arrow keys ;) Thus, you really need to hook on either the keydown or keyup events. Here's an SSCCE with keydown, just copy'n'paste'n'run it. No, you don't need to do a browser-compatible check on the event, this works in all browsers from IE6 up to with Firefox.

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2217553</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script>
            $(document).keydown(function(event) {
                switch (event.keyCode) {
                    case 37: alert('left'); break;
                    case 38: alert('up'); break;
                    case 39: alert('right'); break;
                    case 40: alert('down'); break;
                }
            });
        </script>
    </head>
    <body>
       <p>Press one of the arrow keys.</p> 
    </body>
</html>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    +1 for you giving a thorough answer. -1 for me for not RTFMing. ;o) – DA. Feb 08 '10 at 15:36
  • For future folks having this problem, note that you should use the `keydown` event for `$(document)`, not `$(window)` (this was a problem I ran into). – Jonah Bishop May 30 '12 at 13:25
7

Try this:

$(document).keydown(function (e) {
    if(!e) {
        e = window.event;
    }
    switch(e.keyCode) {
    case 37:
        goLeft();
        break;
    case 39:
        goRight();
        break;
    }
});
Skilldrick
  • 69,215
  • 34
  • 177
  • 229
  • Is the check for `window.event` necessary with jQuery? I understood that it removed the need to do that. – Tim Down Feb 07 '10 at 23:36
2

Use the 'keydown' event

psychotik
  • 38,153
  • 34
  • 100
  • 135
1

Because I sometimes do not want events to bubble for some keys, I use something like: Customize the codes/keys as you see fit.

/* handle special key press */
function checkCptKey(e)
{
    var shouldBubble = true;
    switch (e.keyCode)
    {
        // user pressed the Tab                                                                                                                                        
        case 9:
            {
                $(".someSelect").toggleClass("classSelectVisible");
                shouldBubble = false;
                break;
            };
            // user pressed the Enter    
        case 13:
            {
                $(".someSelect").toggleClass("classSelectVisible");
                break;
            };
            // user pressed the ESC
        case 27:
            {
                $(".someSelect").toggleClass("classSelectVisible");
                break;
            };
    };
    /* this propogates the jQuery event if true */
    return shouldBubble;
};

/* user pressed special keys while in Selector */
$(".mySelect").keydown(function(e)
{
    return checkCptKey(e);
});
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100