Search code examples
javascriptjquerykeypresskeydown

Why does keydown and keypress provide different "which" values?


Edit to clarify -- The linked to question does not answer the question I am asking here as it still describes solutions that do not adequately specify which is more correct to use, which is more reliable, which is more internationally friendly, and which can most readily provide the keys and values from those keys pressed to get both printable and non-printable characters. Most understand when each event fires, but attempting to get actionable data from either/or, especially as stated in that other question that it is bad form to use both in the instance of this particular use case, a better description of these functions would help. Thank you very much for your contribution toward learning and understanding.

I am having to use both keypress and keydown functions to capture keyboard events in a dependable manner for the program I am creating. I fear that when I start diving into international keyboards the solutions necessary will have to be extremely imaginative. Knowing more of how the two functions actually behave will most certainly clarify my further progress as well as many others. Research on the topic have yielded many different approaches and not so clear cut an understanding readily usable. Mainly a bunch of different hacks.

My biggest issue is differentiating the normal chars, "abc" and "123", and the non printable chars such as "enter" or "backspace." And period or decimal is its own animal. My code works, but I'm worried when I have 100+ programmable keyboard shortcuts for several different international keyboard layouts on top of the normal typing of letters and numbers, I might run into trouble.

A good explanation of the difference of keypress and keydown and potentially keyup would be vastly appreciated by many.

Thank you very much for you help!

This code works, but a better understanding might change its form.

keypress catches mainly printable chars

keydown catches non printable keys such as enter and backspace

.keypress(function(key) 
{
/*     $(".temp").append(key.shiftKey + ' -- ' + key.which + ': ' + key.key + '<br>'); */
    console.log(key.shiftKey + ' -- ' + key.which + ': ' + String.fromCharCode(key.which));
    KeyBindHandler(key);
})
.keydown(function(key) 
{
    console.log(key.shiftKey + ' -- ' + key.which + ': ' + String.fromCharCode(key.which));
    if ($.inArray(key.which, [8, 13, 46, 112, 113, 114, 115, 116, 110, 190]) > -1)
        KeyBindHandler(key);
})

function KeyBindHandler(key)
{
    key.preventDefault();

    if (key.which == 8 || key.which == 46)         // backspace delete
        BackSpace();
    else if (key.which == 13)                      // enter keys
        Enter();
    else if (key.which == 110 || key.which == 190) // period or decimal
        ButtonHandler($('#Decimal'));
    else if ($.inArray(key.which, [40, 41, 42, 43, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]) > -1)
    {
        if (key.shiftKey)
        {
            switch (key.which)
            {
                case 40:  // (
                    ButtonHandler($('#Open_peren'));
                    break;
                case 41:  // )
                    ButtonHandler($('#Close_peren'));
                    break;
                case 45: // shift and key minus posneg
                    math_io.PosNegHandler();
                    $(".io_in").html(math_io.Display());
                    break;
            }
        }
        else              // operands and numbers
        {
            switch (key.which)
            {
                case 47:
                    ButtonHandler($('#Division'));
                    break;
                case 42:
                    ButtonHandler($('#Multiplication'));
                    break;
                case 45:
                    ButtonHandler($('#Subtraction'));
                    break;
                case 43:
                    ButtonHandler($('#Addition'));
                    break;
                default:
                    ButtonHandler($('#' + String.fromCharCode(key.which)));
            }

        }
    }
    else                       // F1 to F5
    {
        switch (key.which) 
        {
            case 112:
                NavButtonHandler($('#Standard'));
                break;
            case 113:
                NavButtonHandler($('#Advanced'));
                break;
            case 114:
                NavButtonHandler($('#Scientific'));
                break;
            case 115:
                NavButtonHandler($('#Advanced_Scientific'));
                break;
            case 116:
                NavButtonHandler($('#Graphing'));
                break;
        }
    }
}

Solution

  • key.key is the God send. Two days and probably 50 different browser tabs, and trial and error, and all I needed the whole time was key.key. Anyone that reads this, all you need is to switch key.key via jQuery or KeyboardEvent.key via standard JavaScript to get accurate keyDown values!

    I replaced the above code with the following code using only the keydown event. A definite improvement, I must say, in both aesthetics and functionality. I hope this helps a whole lot of people that were struggling with this very issue. Thank you so much for all that assisted me!

    function KeyBindHandler(key)
    {
        key.preventDefault();
    
        var search_key = '';
    
        if (key.ctrlKey) search_key += 'Control_';
        else if (key.altKey) search_key += 'Alt_';
        else if (key.shiftKey) search_key += 'Shift_';
        else if (key.metaKey) search_key += 'Meta_';
        else search_key += 'NoMod_';
    
        // more to be added, account for symbol keys that are problematic in button or other id's
        search_key += function()
        {
            switch (key.key)
            {
                case '(':
                    return '9';
                case ')':
                    return '0';
                case '/':
                    return 'Divide';
                case '*':
                    return 'Multiply';
                case '-':
                    return key.shiftKey ? 'Posneg' : 'Subtract';
                case '+':
                    return 'Add';
                case '.':
                    return 'Decimal';
                default:
                    return key.key;
            }
        }();
    
        switch (search_key)
        {
            case 'NoMod_F1':
            case 'NoMod_F2':
            case 'NoMod_F3':
            case 'NoMod_F4':
            case 'NoMod_F5':
                NavButtonHandler($('#' + search_key)); // F key handler
                break;
            case 'NoMod_Enter':
                Enter(); // Enter handler
                break;
            case 'NoMod_Backspace':
            case 'NoMod_Delete':
                BackSpace(); // Backspace
                break;
    
            case 'Shift_Posneg': // positive negative handler
            case 'Shift_9': // (
            case 'Shift_0': // )
    
            case 'NoMod_0':
            case 'NoMod_1':
            case 'NoMod_2':
            case 'NoMod_3':
            case 'NoMod_4':
            case 'NoMod_5':
            case 'NoMod_6':
            case 'NoMod_7':
            case 'NoMod_8':
            case 'NoMod_9':
    
            case 'NoMod_Decimal':
            case 'NoMod_Divide': // operands
            case 'NoMod_Multiply':
            case 'NoMod_Subtract':
            case 'NoMod_Add':
                ButtonHandler($('#' + search_key));
                break;
            default:
                //nothing yet
        }
    }