0

The title pretty much explains it, but I am simply wondering if there is a way to use keyup to tell my code to react to @ but not 2...same with # and 3.

Right now it gives me the same keycode for 2 and @ which leads to some undesirable behavior.

Anyone know the magic?

UPDATE - SOLVED

Based on the discussions in the comments below with @RobW and @MonkeyZeus, I have learned that while there are several ways to get what I need, the most straight forward answer is to use keypress rather than keyup. If you must use keyup for some reason, then there are some great solutions to detect the shift key in the other answers below.

Thanks, David

David
  • 2,173
  • 3
  • 25
  • 36
  • 1
    The keycode for 2 and @ will be the same, you need to check for the shift key. – The Blue Dog Jan 21 '14 at 20:00
  • can you show code to see what are you trying? – jcho360 Jan 21 '14 at 20:00
  • http://stackoverflow.com/q/3781142/438992 – Dave Newton Jan 21 '14 at 20:01
  • 1
    As @crnlx pointed out, you can check the shiftKey. You can use the `keydown` event and call `String.fromCharCode` to get the keyCode's value, or you can evaluate what the value is when the keyup event occurs. – Mathachew Jan 21 '14 at 20:02
  • @MonkeyZeus What if the cursor isn't at the end of the input? – Kevin B Jan 21 '14 at 20:03
  • @KevinB Yea I thought of that just before reading your comment... – MonkeyZeus Jan 21 '14 at 20:05
  • @MonkeyZeus `element.selectionStart` and/or `element.selectionEnd` can be used to find the cursor position. – Rob W Jan 21 '14 at 20:11
  • 1
    Of course, this all falls over if someone is using a UK keyboard! – The Blue Dog Jan 21 '14 at 20:12
  • 1
    @RobW I wish I never deleted my comment and you are right. I think for greatest cross-country and cross-keyboard functionality you would need to check the actual character in the `` field to decide what action to take rather than jumping through hoops with keycodes and such – MonkeyZeus Jan 21 '14 at 20:17
  • 2
    @MonkeyZeus Well, if I really want to detect "@" or "#" via the keyboard (not copy-paste), I would not use any of these methods, but the `keypress` event (*not* `keydown` or `keyup`). – Rob W Jan 21 '14 at 20:21
  • 1
    @RobW Is keypress standardized across all browsers? I've experienced varying differences in terms of which key triggers which event before/after the other events, especially for IE8. Before you tell me to give IE8 the single-finger salute I should let you know that 40% of my user-base is still IE8... – MonkeyZeus Jan 21 '14 at 20:26
  • 1
    @MonkeyZeus You can rely on `keypress` to be accurate for "@" and "#". Look at the "Remarks" section on [the MSDN article for keypress](http://msdn.microsoft.com/en-uS/library/ms536939%28v=vs.85%29.aspx) to see which key strokes are supported in IE (4+!). jQuery normalizes the event object, so you can always use `event.which`. – Rob W Jan 21 '14 at 20:53
  • @MonkeyZeus Can you put your advice in a new reply so I can give you credit for the answer? KeyPress was the magic. I had read somewhere that keypress missed some of the key commands so I have stayed away from it. Thanks! – David Jan 21 '14 at 21:14
  • Are you sure I should get the credit? @RobW suggested the `keypress`, I was actually skeptical about it. – MonkeyZeus Jan 21 '14 at 21:32
  • You are right, I would like to give @RobW credit for his answer. There are several ways to skin this cat it seems, but using keypress rather than keyup seems the most straight forward. – David Jan 22 '14 at 00:25

3 Answers3

1

You have to check the Shift press state.

$("#id").on("keyup", function(e){
    var key = String.fromCharCode(e.which).toLowerCase();

    if (key == "3" && e.shiftKey) {
        // #
    } else if(key == "2" && e.shiftKey) {
        // @
    }

});

Likewise, you can also check e.ctrlKey, e.metaKey, and e.altKey.

roydukkey
  • 3,149
  • 2
  • 27
  • 43
0

Based on the discussion from the comments:

Instead of jumping through hoops with keycode detection and other internationalization issues, it is probably best to check the literal character entered by the user as it is shown in the <input> box.

Using a combination of element.selectionStart, element.selectionEnd, and substring() you can check the what is the actual character as rendered by the <input> field.

Recognition goes out to Rob W and PeteR for this post.

MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
0

Just to throw another hat in the ring. Determining characters in keypress events isn't something that JavaScript does very well right now. Due to it's variability, I'd rather not force any method to have to decipher it inline, and defer evaluation to another method that can be subbed in and out.

The ideal would be a method that takes in the KeyUp Event as an argument and returns whatever character was pressed: Let's call it MapKeyPressToActualCharacter.

Then your code could look super clean like this:

$("#id").on("keyup", function(e){
    switch(MapKeyPressToActualCharacter(e)) {
        case "#":
            //handle #
            break;
        case "@":
            //handle @
            break;
    }
});

Now we just have to figure out how to write MapKeyPressToActualCharacter.
Here's an implementation based off the answer to get key char from keycode with shift modifier:

function MapKeyPressToActualCharacter(event) {
    var isShiftKey = event.shiftKey;
    var characterCode = event.keyCode;
    var isAlphabetChar = characterCode >= 65 && characterCode <= 90;
    var specialChars = [8,9,13,16,17,18,20,27,91,92];
    var character = "";

    if (valueInArray(characterCode, specialChars)) {
        return false;
    }

    if (isAlphabetChar) {
        character = String.fromCharCode(characterCode);
    } else if (isShiftKey) {
        character = GetShiftedCharacters()[characterCode];
    } else {
        character = String.fromCharCode(characterCode);
    }
    return character;
}

function valueInArray(value, array) {
    return array.indexOf(value) > -1;
}

Working Demo in Fiddle

You'll also need to get a mapping of each character and it's shifted corollary with the method GetShiftedCharacters:

function GetShiftedCharacters() {
    var characterMap = {32: " ",
                        48: ")",
                        49: "!",
                        50: "@",
                        51: "#",
                        52: "$",
                        53: "%",
                        54: "^",
                        55: "&",
                        56: "*",
                        57: "(",
                        59: ":",
                        107: "+",
                        109: "_",
                        188: "<",
                        190: ">",
                        191: "?",
                        192: "~",
                        219: "{",
                        220: "|",
                        221: "}",
                        222: "\\" };
    return characterMap;
}

Here's a distributable JS file: MapKeyPress.js

*Note, since the MapKeyPress function calls array.indexOf, you should use a polyfill to extend to older browsers. Here's a shiv called indexOfPolyFill.js, and here's an example.

Community
  • 1
  • 1
KyleMit
  • 30,350
  • 66
  • 462
  • 664