Search code examples
javascripthtml

Does preventDefault() in keydown event prevent a following keypress event?


I have a simple html page with a webgl canvas and javascript attached. In the script i listen to 'keydown', 'keypress' and 'keyup' events of the canvas. Inside the eventhandlers i log to debug when the events are triggered. If i call preventDefault() on the event object in the 'keydown' handler i don't get 'keypress' events anymore and wonder if this is intended behavior? So if i press for example a character key like 'a', the keydown and keyup events are fired, but keypress is only called if i preventDefault() is not called in the keydown event handler.

I tested this on windows, firefox and chrome so far.

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Main</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="mobile-web-app-capable" content="yes" />
    <style>
        body,html { margin:0; padding:0; background-color:black; width:100%; height:100%; }
        canvas#webgl { width:100%; height:100%; }
    </style>
</head>
<body>
    <canvas id="webgl" tabindex="0"></canvas>
    <script type="text/javascript" src="test_canvaskeypress.js"></script>
</body>
</html>

test_canvaskeypress.js:


var canvas = document.getElementById("webgl"); 
canvas.addEventListener('keydown',this.onKeyDown,false);
canvas.addEventListener('keyup',this.onKeyUp,false);
canvas.addEventListener('keypress',this.onKeyPress,false);


function onKeyDown(e) {
    console.log('keyup: '+e.keyCode); 
    e.preventDefault();//prevents the keypress event, is this intended behavior?
    e.stopPropagation();

}
function onKeyUp(e) {
    console.log('keydown: '+e.keyCode); 
    e.preventDefault();
    e.stopPropagation();
}
function onKeyPress(e) {
    console.log('keypress: '+e.key); 
    e.preventDefault();
    e.stopPropagation();
}

I don't know what to expect, because the docs for preventDefault are not very informative, but i think a keypress event should appear nonetheless preventDefault is called in onKeyDown(), because the key up event also is fired.


Solution

  • From the most recent W3C Working Draft (https://www.w3.org/TR/uievents/#keydown) we can see that one of the keydown default actions is the keypress event (among others)! So, when you do a preventDefault on the keydown event, you are actually preventing the event default actions, and in this case, one of those actions is the keypress event.