0

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;
        }
    }
}
Joel
  • 85
  • 8
  • The short answer is, `keypress` is about typed characters, as in, what you end up seeing in a program like Word. `keydown` is about keyboard keys, detecting a physical interaction with the keyboard. Pressing the Shift key for instance will not trigger a `keypress` event, since Shift is a modifier key. –  Mar 02 '18 at 00:36
  • 3
    Possible duplicate of [keypress and keyup - why is the keyCode different?](https://stackoverflow.com/questions/11030532/keypress-and-keyup-why-is-the-keycode-different) – Heretic Monkey Mar 02 '18 at 00:36
  • @Chris G - while your comment is spot on, it doesn't answer the question. – Randy Casburn Mar 02 '18 at 00:40
  • Two questions: 1. Are these keyboard events coming from an input element? 2. Is there a distinct reason you've chosen to use `.which` rather than `.key`? Your code simply decodes the output of `.which` and that value is provided by `.key` without the extra step. – Randy Casburn Mar 02 '18 at 00:50
  • 1
    You're never going to get a description of "which is more correct to use, which is more reliable, which is more internationally friendly" on Stack Overflow, as those are opinions, which are not on topic. As far as descriptions of the events and their arguments, I find [MDN to have outstanding documentation](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names_and_Char_values). – Heretic Monkey Mar 02 '18 at 00:54
  • Consider this analogy: Two types of shoes: business shoes vs. running shoes :: Would you wear business shoes to run a sprint race? Probably not, but this really comes down to "why would you ask? - that's silly". Right - understanding the tools and which to use at the right time is pretty important. Consider keypress vs. keydown precisely the same way - they have different purposes because they are different tools. – Randy Casburn Mar 02 '18 at 00:55
  • Answer 1. Its a document event for controlling the on screen buttons with keybindings. Answer 2. I have spent around 20 hours researching and writing this bit of code to accurately depict user input, and with this research, I found that the only reliable cross browser, normalized, differentiation, is "which." None of the others are stated to be "All Major Browser" compatible. Keypress is even stated to behave differently across browsers. Thats why I'd rather use "keydown." – Joel Mar 02 '18 at 00:55
  • @RandyCasburn My comment was supposed to suggest that OP might want to change their approach. Given the above comment, my next suggestion would be to focus on `keydown`. –  Mar 02 '18 at 00:59
  • @Joel - ref use of `which` - then consider Mike McCaughan's comment and read the docs that you must have missed or glossed over. `which` has been removed from the spec and is deprecated. Use keyCode. – Randy Casburn Mar 02 '18 at 01:00
  • @RandyCasburn https://stackoverflow.com/questions/4471582/keycode-vs-which – Joel Mar 02 '18 at 01:02
  • @Joel - hooey : https://caniuse.com/#search=keyboardEvent.keyCode -- that was true **SEVEN years ago** – Randy Casburn Mar 02 '18 at 01:05
  • If it helps, I am using jquery-3.3.1. "Which" through jquery should be the best of whichever browser the application is being run on as it normalizes the property. If someone can confirm that it also normalizes keyCode and charCode, that would help tons as then all I'd need is a simple switch on keydown. – Joel Mar 02 '18 at 01:12
  • To address the clarification edit: If your use case is to implement keyboard shortcuts, it seems your intent is to expect meta keys. If you are going to expect meta keys then you should choose the correct tool to use. This is an absolute answer directly from the spec and documentation. "The keydown event is fired when a key is pressed down. Unlike the keypress event, the keydown event is fired for keys that produce a character value and for keys that do not produce a character value." – Randy Casburn Mar 02 '18 at 01:14
  • "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 key accurate Keydown values! Thank you all that helped reach this conclusion! :) – Joel Mar 02 '18 at 01:30

1 Answers1

0

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
    }
}
Joel
  • 85
  • 8