How to decode character pressed from jQuery's keydown()'s event handler
Asked Answered
G

6

70

I need to figure out which character was typed into a text field from within the handler that is called by jQuery's keydown function. key.which gives me only the keycode, but I need to figure out which ASCII character key represents. How do I do this?

Giltzow answered 8/2, 2010 at 7:57 Comment(0)
O
97

For character input, it is suggested you use keypress(), which will report the actual ASCII code for the character pressed. It automatically takes care of letter case, and ignores non-character presses. In either case, you can use fromCharCode() to convert to a string representation. E.g.

var c = String.fromCharCode(e.which) // or e.keyCode

Just remember that for keydown() and keyup(), you'll have to keep track of the case using the e.shiftKey state.

Obstetrics answered 8/2, 2010 at 8:9 Comment(6)
haha.. for some reason, browsers are returning 188 when comma is pressed, but when we convert 188 to char, it is coming as ¼. Interestingly, when we convert 44 to char, browsers are understanding it as comma!!Piggy
I believe it return 1/4 in old version of jQuery. In 1.4.2 it's fixed. It return comma for meSachs
hmm this does not account for e.shiftKeyGharry
I vote for keypress - it receives correct characters for international keyboard layouts, unlike keydown which converts everything to single byte characters.Metal
Oh, so String is not a var... :((Lamoreaux
e.which returns the Id of the key, not the character.Trotyl
C
110

The keyPress event is what you need to get which character was entered. (See below workaround for keydown event).

keydown and keyup provide a code indicating which key is pressed, while keypress indicates which character was entered.

Using jQuery e.which you can get the key code and using String.fromCharCode you can get the specific character that was pressed (including shiftKey).

DEMO: http://jsfiddle.net/9TyzP/3

Code:

element.on ('keypress', function (e) {
    console.log(String.fromCharCode(e.which));
})

Note I said jQuery's e.which because different browsers use differing properties to store this information. jQuery normalizes the .which property so you can reliably use it to retrieve the key code.

Workaround for keydown

However you can write a simple workaround to get the pressed character working on keydown.. The workaround is to create an object with key as the charCode without shift keypress and the value is with shift key.

Note: As @Sajjan Sarkar pointed out there are some differences in e.which keycode value returned from different browser. Read more here

Updated the DEMO code to normalize the cross browser keyCode value. Tested and verified in IE 8, FF and Chrome.

Full Code below and updated DEMO: http://jsfiddle.net/S2dyB/17/

$(function() {

    var _to_ascii = {
        '188': '44',
        '109': '45',
        '190': '46',
        '191': '47',
        '192': '96',
        '220': '92',
        '222': '39',
        '221': '93',
        '219': '91',
        '173': '45',
        '187': '61', //IE Key codes
        '186': '59', //IE Key codes
        '189': '45'  //IE Key codes
    }

    var shiftUps = {
        "96": "~",
        "49": "!",
        "50": "@",
        "51": "#",
        "52": "$",
        "53": "%",
        "54": "^",
        "55": "&",
        "56": "*",
        "57": "(",
        "48": ")",
        "45": "_",
        "61": "+",
        "91": "{",
        "93": "}",
        "92": "|",
        "59": ":",
        "39": "\"",
        "44": "<",
        "46": ">",
        "47": "?"
    };

    $(element).on('keydown', function(e) {
        var c = e.which;

        //normalize keyCode 
        if (_to_ascii.hasOwnProperty(c)) {
            c = _to_ascii[c];
        }

        if (!e.shiftKey && (c >= 65 && c <= 90)) {
            c = String.fromCharCode(c + 32);
        } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) {
            //get shifted keyCode value
            c = shiftUps[c];
        } else {
            c = String.fromCharCode(c);
        }

        //$(element).val(c);
    }).on('keypress', function(e) {
        //$(element).val(String.fromCharCode(e.which));
    });    
});

More about keyboard events --

The keydown, keypress and keyup events fire when the user presses a key.

keydown Fires when the user depresses a key. It repeats while the user keeps the key depressed.

keypress Fires when an actual character is being inserted in, for instance, a text input. It repeats while the user keeps the key depressed.

keyup Fires when the user releases a key, after the default action of that key has been performed.

When a key is first depressed, the keydown event is sent. If the key is not a modifier key, the keypress event is sent. When the user releases the key, the keyup event is sent.

When a key is pressed and held down, it begins to auto-repeat. This results in a sequence of events similar to the following being dispatched:

keydown
keypress
keydown
keypress
<<repeating until the user releases the key>>
keyup

DEMO: http://jsfiddle.net/9TyzP/1/

keyup, keydown vs keypress

The keydown and keyup events represent keys being pressed or released, while the keypress event represents a character being typed.

DEMO: http://jsfiddle.net/9TyzP/

References:

  1. https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent

  2. http://www.quirksmode.org/dom/events/keys.html

  3. http://unixpapa.com/js/key.html

Crossbow answered 29/10, 2012 at 18:29 Comment(10)
this looks like a great canonical answer, will wait a few days so this gets a bit more exposure before awardingGharry
Yes, but as "the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms." src:api.jquery.com/keypress AFAIK, you cannot get the ASCII value in keydown, you can only get it in keyup or keypress as the above person pointed out.Upcoming
@SajjanSarkar Not true.. You get the keyCode (e.which) on keydown/keyup/keypress. If you want the ASCII character then you can use String.fromCharCode function. You don't get the character in keyup/keypress.Crossbow
@Vega Yes and no, try saying Console.log(String.fromCharCode(e.which)) and see what u get for semi-colon and colon.Upcoming
@SajjanSarkar That is because control keys are passed as e.shiftKey on keydown and the value is returned as without shift. That was the original issue in this bounty question to begin with. Also I have mentioned that clearly in my alternate solution with a demo jsfiddle.net/S2dyB/4Crossbow
@Vega its a nice approach, but the truth is, when I press colon (shift+;) i expect the code to give me ":" not "º:" But ur answer is still the best one around..Upcoming
@SajjanSarkar Which browser are you getting that result º:?Crossbow
@SajjanSarkar Thanks and that was a good catch.. I did some readings and based on which I have normalized the keycode so that it works across browser. Updated DEMO: jsfiddle.net/S2dyB/14Crossbow
@Vega except now it gives "::" when I type ":".. same with semi-colonsUpcoming
@SajjanSarkar The DEMO was to demonstrate the keydown keyCode handler and as per the demo you are supposed to keydown outside the textbox. Updated demo: jsfiddle.net/S2dyB/17Crossbow
O
97

For character input, it is suggested you use keypress(), which will report the actual ASCII code for the character pressed. It automatically takes care of letter case, and ignores non-character presses. In either case, you can use fromCharCode() to convert to a string representation. E.g.

var c = String.fromCharCode(e.which) // or e.keyCode

Just remember that for keydown() and keyup(), you'll have to keep track of the case using the e.shiftKey state.

Obstetrics answered 8/2, 2010 at 8:9 Comment(6)
haha.. for some reason, browsers are returning 188 when comma is pressed, but when we convert 188 to char, it is coming as ¼. Interestingly, when we convert 44 to char, browsers are understanding it as comma!!Piggy
I believe it return 1/4 in old version of jQuery. In 1.4.2 it's fixed. It return comma for meSachs
hmm this does not account for e.shiftKeyGharry
I vote for keypress - it receives correct characters for international keyboard layouts, unlike keydown which converts everything to single byte characters.Metal
Oh, so String is not a var... :((Lamoreaux
e.which returns the Id of the key, not the character.Trotyl
M
1

I do this. It will just ignore the keypress if the value is not a number. Seems to work without any problems...

    $("input").on("keypress", function(e) {
        if(!jQuery.isNumeric(String.fromCharCode(e.which)))
            return false;
    });
Milurd answered 20/11, 2013 at 23:44 Comment(0)
O
1

Selvakumar Arumugam's answer works like a charm for me...until I test numpad. So a minor update here:

 $(document).on('keydown', function(e) {
    var c = e.which;

    if (_to_ascii.hasOwnProperty(c)) {
        c = _to_ascii[c];
    }

    if (!e.shiftKey && (c >= 65 && c <= 90)) {
        c = String.fromCharCode(c + 32);
    } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) {
        c = shiftUps[c];
    } else if (96 <= c && c <= 105) {
        c = String.fromCharCode(c - 48);
    }else {
        c = String.fromCharCode(c);
    }

    $kd.val(c);
})

http://jsfiddle.net/S2dyB/78/

Odometer answered 18/8, 2016 at 7:39 Comment(0)
A
0

I created and use the above javascript class for converting gr to en characters. It is able to be used for more languages. It uses JQuery for changing the value pressed from user.

var CharMapper = function (selector) {
    this.getLanguageMapper = function (languageSource, languageTarget) {
        // Check if the map is already defined.
        if (typeof langugageCharMap === "undefined") {
            langugageCharMap = {};
        }
        if (typeof langugageCharMap[languageSource] === "undefined") {
            langugageCharMap[languageSource] = {};
        }

        // Initialize or get the language mapper.
        if (typeof langugageCharMap[languageSource][languageTarget] === "undefined") {
            switch (languageSource) {
                case "GR":
                    switch (languageTarget) {
                        case "EN":
                            langugageCharMap[languageSource][languageTarget] = {
                                "α": "a", "ά": "a", "β": "b", "γ": "g", "δ": "d", "ε": "e", "έ": "e", "ζ": "z", "η": "h", "ή": "h", "θ": "th", "ι": "i", "ί": "i", "ϊ": "i", "ΐ": "i", "κ": "k", "λ": "l", "μ": "m", "ν": "n", "ξ": "ks", "ο": "o", "ό": "o", "π": "p", "ρ": "r", "σ": "s", "ς": "s", "τ": "t", "υ": "y", "ύ": "y", "ϋ": "y", "ΰ": "y", "φ": "f", "χ": "x", "ψ": "ps", "ω": "o", "ώ": "o", "Α": "A", "Ά": "A", "Β": "B", "Γ": "G", "Δ": "D", "Ε": "E", "Έ": "E", "Ζ": "Z", "Η": "H", "Ή": "H", "Θ": "TH", "Ι": "I", "Ί": "I", "Ϊ": "I", "Κ": "K", "Λ": "L", "Μ": "M", "Ν": "N", "Ξ": "KS", "Ο": "O", "Ό": "O", "Π": "P", "Ρ": "R", "Σ": "S", "Τ": "T", "Υ": "Y", "Ύ": "Y", "Ϋ": "Y", "Φ": "F", "Χ": "X", "Ψ": "PS", "Ω": "O", "Ώ": "O"
                            };
                            break;
                        case "GR":
                        default:
                            throw "Language(" + languageTarget + ") is not supported as target for Language(" + languageSource + ").";
                    }
                    break;
                case "EN":
                default:
                    throw "Language(" + languageSource + ") is not supported as source.";
            }
        }

        return langugageCharMap[languageSource][languageTarget];
    };
    // Check the existance of the attribute.
    var items = $(selector).find("*[data-mapkey]");
    if (items.length === 0) {
        return;
    }

    // For each item.
    for (var i = 0; i < items.length; i++) {
        var item = items[i];

        // Get the source and target language.
        var languages = $(item).attr("data-mapkey");
        var languageSource = languages.split("_")[0];
        var languageTarget = languages.split("_")[1];

        // Add the event listener.
        var self = this;
        $(item).keypress(function (event) {
            event.stopPropagation();
            // Get the mapper to use.
            var mapper = self.getLanguageMapper(languageSource, languageTarget);
            // Get the key pressed.
            var keyPressed = String.fromCharCode(event.which);
            // Get the key to set. In case it doesn't exist in the mapper, get the key pressed.
            var keyToSet = mapper[keyPressed] || keyPressed;
            // Set the key to the dom.
            this.value = this.value + keyToSet;

            // Do not propagate.
            return false;
        });
    }
};

Example,

<input type="text" data-mapkey="GR_EN" />
<script type="text/javascript">
    new CharMapper("body");
</script>
Ankerite answered 24/5, 2017 at 13:17 Comment(0)
R
0

keypress is deprecated, you should use keydown instead

Use .key - to get the keypress

The syntax is:

$(selector).keydown(function(event) {
  console.log(event.key)
})

Example:

$(document).keydown(function(event) {
  // print out each keypress
  console.log(event.key)
})
Roeder answered 12/8, 2023 at 22:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.