Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell that keydown will cause keypress event and in that case ignore it?

I'm not very satisfied with the key events in javascript. I need to capture both letters for writing (I'm writing text on <canvas>) and functional keys (escape) for other commands.

In Firefox it works, because Firefox fires keypress event for any key. It's very comfortable but specification directly permits it:

If supported by a user agent, this event MUST be dispatched when a key is pressed down, if and only if that key normally produces a character value.

I disagree with that specification as I see no reason for it. But as it is now, I can't do anything about it.

Problem is that Google Chrome follows that specification and doesn't fire keypress for functional keys. It does, however, notmally fire keydown for all keys.

My program has only one key event handler. It expects event containing keyCode (the ID of the physical key and optionally charCode, the equivalent character value (for keys where it makes sense).

keydown event does not contain any character values in neither browser! It only contains the keyCode. So if you define a Ctrl+Z combination and listen for keydown event, your program will be broken for users that have QWERTZ layout - because the physical location of the key (keyCode) is still the same.

If you listen for both keydown and keypress, character events will fire twice (beacuse character first fires keydown and then keypress with proper charCode property)

What I need?

Based on the above, I need to ignore keydown event for keys that will cause keypress. Doing so, I'll be able to capture Esc in keydown and characters in keypress.

How could I possibly do it?

Relevant code:

  //Keypress for character codes
  div.addEventListener("keypress", function(event) {
    console.log(event);      
    if(_this.editor.event(event)) {
      console.log("Event canceled.");
      event.preventDefault();
      event.cancelBubble = true;
      return false;  
    }
    return true;  
  });
  //Keydown for Esc and the likes
  div.addEventListener("keydown", function(event) {
    //Character events are handled by keypress
    if(event.charCode!=0)  //Does NOT work - in keydown, charCode is ALLWAYS 0
      return true;    

    console.log(event);      
    if(_this.editor.event(event)) {
      console.log("Event canceled.");
      event.preventDefault();
      event.cancelBubble = true;
      return false;  
    }
    return true;
  });   

Interactive example

I figured I spend a lot of time making JSFiddles and it doesn't really increase the odds of getting an answer, so I instead uploaded the actual project.

Click into the white square in Firefox, press T, type text, press Esc, press Esc. After seconds Esc, cursor should get back to normal. Try to draw and press Ctrl+Z.

Repeat the process in Google Chrome. The Escape will not work because it doesn't fire keypress. For some reason, the Ctrl+Z fires event with keyCode 26.

From chat and comments:

@someDoge has created a fiddle which I have expanded and which now nicely shows the situation. As you can see, you can know that a key isn't character and ignore it in keypress. But you can't know that tab isn't character and cancel it in keydown (unless you have fixed array of keycode values as @someDoge sugests in comments).

like image 278
Tomáš Zato - Reinstate Monica Avatar asked Dec 02 '14 16:12

Tomáš Zato - Reinstate Monica


People also ask

Is keypress event raise before Keydown event?

The KeyDown event occurs prior to the KeyPress event. Raised when a character generating key is pressed. The KeyPress event occurs after the KeyDown event and before the KeyUp event. Raised when a key is released.

What is the difference between Keydown and keypress events?

The keydown event is fired when a key is pressed. Unlike the keypress event, the keydown event is fired for all keys, regardless of whether they produce a character value. The keydown and keyup events provide a code indicating which key is pressed, while keypress indicates which character was entered.

Should I use Keyup or Keydown?

Both are used as per the need of your program and as per the convenience of the user. keyup Fires when the user releases a key, after the default action of that key has been performed. keydown Fires when the user depresses a key.

What is the difference between Keyup and Keydown and keypress?

keypress – fires when a key that produces a character value is pressed down, fires after keydown , and before the browser processes the key. keyup – fires when any key is released, fires last, and the browser processes the key.


1 Answers

You need to listen for keyup events instead of keydown, this way you won't get two separate events generated.

Then you can handle the 2 event types with the same handler function which will either get a charCode or not, depending on if the particular key generated a 'keypress' event. As long as you prevent bubbling your handler will only be called once.

Regarding the Chrome CTRL+Z problem: I don't see how you can get a charCode if the control key is being pressed, since it seems only to generate a keyup event.

like image 190
Si Kelly Avatar answered Oct 03 '22 01:10

Si Kelly