KeyboardEvent.keyCode deprecated. What does this mean in practice?

JavascriptKeyDeprecatedKeycode

Javascript Problem Overview


According to MDN, we should most definitely not be using the .keyCode property. It is deprecated:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

On W3 school, this fact is played down and there is only a side note saying that .keyCode is provided for compatibility only and that the latest version of the DOM Events Specification recommend using the .key property instead.

The problem is that .key is not supported by browsers, so what should we using? Is there something I'm missing?

Javascript Solutions


Solution 1 - Javascript

For instance if you want to detect whether the "Enter"-key was clicked or not:

Instead of

event.keyCode === 13

Do it like

event.key === 'Enter'

Solution 2 - Javascript

You have three ways to handle it, as it's written on the link you shared.

if (event.key !== undefined) {
  
} else if (event.keyIdentifier !== undefined) {
  
} else if (event.keyCode !== undefined) {
  
}

you should contemplate them, that's the right way if you want cross browser support.

It could be easier if you implement something like this.

var dispatchForCode = function(event, callback) {
  var code;
  
  if (event.key !== undefined) {
    code = event.key;
  } else if (event.keyIdentifier !== undefined) {
    code = event.keyIdentifier;
  } else if (event.keyCode !== undefined) {
    code = event.keyCode;
  }
  
  callback(code);
};

Solution 3 - Javascript

TLDR: I'd suggest that you should use the new event.key and event.code properties instead of the legacy ones. IE and Edge have support for these properties, but don't support the new key names yet. For them, there is a small polyfill which makes them output the standard key/code names:

https://github.com/shvaikalesh/shim-keyboard-event-key


I came to this question searching for the reason of the same MDN warning as OP. After searching some more, the issue with keyCode becomes more clear:

The problem with using keyCode is that non-English keyboards can produce different outputs and even keyboards with different layouts can produce inconsistent results. Plus, there was the case of

If you read the W3C spec: https://www.w3.org/TR/uievents/#interface-keyboardevent

> In practice, keyCode and charCode are inconsistent across platforms and even the same implementation on different operating systems or using different localizations.

It goes into some depth describing what was wrong with keyCode: https://www.w3.org/TR/uievents/#legacy-key-attributes

> These features were never formally specified and the current browser implementations vary in significant ways. The large amount of legacy content, including script libraries, that relies upon detecting the user agent and acting accordingly means that any attempt to formalize these legacy attributes and events would risk breaking as much content as it would fix or enable. Additionally, these attributes are not suitable for international usage, nor do they address accessibility concerns.

So, after establishing the reason why the legacy keyCode was replaced, let's look at what you need to do today:

  1. All modern browsers support the new properties (key and code).
  2. IE and Edge support an older version of the spec, which has different names for some keys. You can use a shim for it: https://github.com/shvaikalesh/shim-keyboard-event-key (or roll your own - it's rather small anyways)
  3. Edge has fixed this bug in the latest release (probably will be released in Apr 2018) - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
  4. Refer to the list of event keys you can use: https://www.w3.org/TR/uievents-key/

Solution 4 - Javascript

In addition that all of keyCode, which, charCode and keyIdentifier are deprecated :
charCode and keyIdentifier are non-standard features.
keyIdentifier is removed as of Chrome 54 and Opera 41.0
keyCode returns 0, on keypress event with normal characters on FF.

The key property :

 readonly attribute DOMString key

> Holds a key attribute value corresponding to the key pressed

As of the time of this writing, the key property is supported by all major browsers as of : Firefox 52, Chrome 55, Safari 10.1, Opera 46. Except Internet Explorer 11 which has : non-standard key identifiers and incorrect behavior with AltGraph. More info
If that is important and/or backward compatibility is, then you can use feature detection as in the following code :

Notice that the keyvalue is different from keyCode or which properties in that : it contains the name of the key not its code. If your program needs characters' codes then you can make use of charCodeAt(). For single printable characters you can use charCodeAt(), if you're dealing with keys whose values contains multiple characters like ArrowUp chances are : you are testing for special keys and take actions accordingly. So try implementing a table of keys' values and their corresponding codes charCodeArr["ArrowUp"]=38, charCodeArr["Enter"]=13,charCodeArr[Escape]=27... and so on, please take a look at Key Values and their corresponding codes

if(e.key!=undefined){
    	var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        /* As @Leonid suggeted   */
    	var characterCode = e.which || e.charCode || e.keyCode || 0;
    }
    	/* ... code making use of characterCode variable  */  

May be you want to consider forward compatibility i.e use the legacy properties while they're available, and only when dropped switch to the new ones :

if(e.which || e.charCode || e.keyCode ){
    	var characterCode = e.which || e.charCode || e.keyCode;
    }else if (e.key!=undefined){
        var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        var characterCode = 0;
    }
    	

See also : the KeyboardEvent.code property docs and some more details in this answer.

Solution 5 - Javascript

MDN has already provided a solution:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return; // Should do nothing if the default action has been cancelled
  }

  var handled = false;
  if (event.key !== undefined) {
    // Handle the event with KeyboardEvent.key and set handled true.
  } else if (event.keyIdentifier !== undefined) {
    // Handle the event with KeyboardEvent.keyIdentifier and set handled true.
  } else if (event.keyCode !== undefined) {
    // Handle the event with KeyboardEvent.keyCode and set handled true.
  }

  if (handled) {
    // Suppress "double action" if event handled
    event.preventDefault();
  }
}, true);

Solution 6 - Javascript

e.charCode has been deprecated:

<input
  onChange={(e) => setToken(e.target.value)}
  type="text"
  value={token}
  onKeyPress={(e) => {
    if (e.charCode === 13) {
      verifyLoginF()
    }
  }}
/>

enter image description here

you should use now:e.key === 'Enter'

enter image description here

Solution 7 - Javascript

Here was proposed to use key value instead of keyCode and if it fails then use keyCode. Though this is not enough, because values in this attributes are not compatible. Thing is new key contains the string for control keys, like: ArrowUp, but keyCode will contain just code which with trivial

String.fromCharCode(event.keyCode)

will result in a non-printable char. Here the solution for printable chars:

element.keydown((event) => {
	var symbolPressed;
	//cross browser
	if (event.key !== undefined) {
		symbolPressed = event.key; //Here control characters represented as String like: ArrowUp
		if (symbolPressed.length > 1) return; //filter out control characters
	} else if (event.keyCode !== undefined) {
		symbolPressed = String.fromCharCode(event.keyCode); //Here control chars represented as one char string
	}
	//Update this regex if you need other characters
	if (!symbolPressed.match(/[A-z0-9\s]/)) return;
	console.log(symbolPressed);
});

And in case of you need non-printable control characters, you have to update conditions and regex accordingly.

Solution 8 - Javascript

(e)=>{
  e.key === 'Escape';
}

is the same as

(e)=>{
  e.keyCode === 27;
}

It's better to use the second one.

Solution 9 - Javascript

You can use

parseInt(event.key, radix: 10)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJason210View Question on Stackoverflow
Solution 1 - JavascriptThomas GotwigView Answer on Stackoverflow
Solution 2 - JavascriptMiguel LattuadaView Answer on Stackoverflow
Solution 3 - JavascriptkumarharshView Answer on Stackoverflow
Solution 4 - Javascriptuser10089632View Answer on Stackoverflow
Solution 5 - JavascriptVicky GonsalvesView Answer on Stackoverflow
Solution 6 - JavascriptAlanView Answer on Stackoverflow
Solution 7 - JavascriptPavlo MorozovView Answer on Stackoverflow
Solution 8 - JavascriptAyush BaliView Answer on Stackoverflow
Solution 9 - JavascriptmhdizmnView Answer on Stackoverflow