JavaScript y el DOM: keyDown vs keyPress
Tags: javascript, webdev, spanish
Published: 2019-11-19 19:03:44

Formularios. Qué sería de nuestro software web sin formularios. La majestuosa forma de permitir a los usuarios de un sistema ingresar información.

**En realidad los formularios son un dolor de cabeza**. Entre menos campos tengan mejor pero hay situaciones donde el mínimo de campos es muchos campos. Un ejemplo de eso es aplicaciones del sector salud donde hay que tomar muchos datos de un paciente.

Para disminuir el impacto de digitar un formulario tan extenso se busca ayuda de expertos en UX y aún así, por debajo de cuerda, hay muchos campos en un solo formulario.

## Solo ingresar números

Un caso común de formularios es que determinados campos solo permitan ingresar valores numéricos y no letras del alfabeto. En primera instancia se pensaría que el campo tipo número que trajo consigo HTML5 bastaría, pero no.

Dicho tipo de campo permite que se escriban letras. Su funcionalidad es más orientada al mundo móvil donde en un celular, un campo de tipo número, abre el teclado numérico y no el alfanumérico.

También está el atributo `pattern` para indicar una expresión regular, sin embargo, hasta donde recuerdo(no lo he vuelto a probar) esta solución se queda corta.

Finalmente, las soluciones más óptimas están dadas por controlar que se ingresa en el campo(s) y prevenir que se ingrese usando un `event listener`.

Aquí es donde el asunto se pone interesante.

## keyDown, keyUp, keyPress

Los anteriores son eventos que se disparan cuando pasa algo en el teclado del usuario. Estos mismos sirven cuando se quiere prevenir que se ingrese texto en el campo del formulario.

Hace un par de años implementé una solución de este tipo usando [jQuery](https://otroespacioblog.wordpress.com/2018/09/01/cosas-de-javascript-seleccionando-id-numerico-con-queryselector/) y capturando el evento `keydown` y evitando que se ingresara texto sino era número o alguna de las teclas especiales como _CTRL_ o _SHIFT_.

La semana pasada, en un proyecto más recién, me tocó implementar algo similar. Lo que hice fue buscar la implementación en el proyecto viejo, sin embargo solo me fijé en la parte interna del manejador de eventos y no en el evento que estaba capturando. En esta nueva implementación usé `keypress` y ahí vino una complicación.

Pasa que `keydown` y `keypress` varian en un atributo.

Cada tecla tiene un código único que la diferencia de las demás. En el caso de `keypress` este valor viene el atributo `charCode` y en `keydown` viene en `keyCode`. Y resulta que no todas las teclas devuelven un valor para `charCode` y la implementación fallaba.

Cuando [analicé, busqué y probé](https://stackoverflow.com/a/4285697/1407371), me di cuenta la diferencia entre los dos tipos de evento. En la primera implementación estaba usando `keydown` y en la más reciente `keypress`. Cuando cambié, todo funcionó como se esperaba.

## Y entonces, ¿qué uso?

Hoy en día, [el uso de `keypress` es desaconsejado por MDN ya que está depreciado](https://developer.mozilla.org/en-US/docs/Web/Events/keypress) y debería cambiarse [por `keydown`](https://developer.mozilla.org/en-US/docs/Web/Events/keydown).

## Bonus Track


Resulta que mientras redactaba este artículo y leía la documentación de los dos eventos, encontré una forma aún más sencilla de impedir el ingreso de texto en campos dispuestos para solo números. Es así según MDN:

```javascript
function numbersOnly(event) {
  return event.charCode === 0 || /\d/.test(String.fromCharCode(event.charCode));
}

const input = document.querySelector('input');

input.onkeypress = numbersOnly;
```

Bastante sencilla si se compara con mi implementación la cual usa jQuery:

```javascript
$('form').on('keydown', '.only-numbers', function(e) {
  if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
    (e.keyCode == 65 && e.ctrlKey === true) ||
    (e.keyCode == 67 && e.ctrlKey === true) ||
    (e.keyCode == 88 && e.ctrlKey === true) ||
    (e.keyCode >= 35 && e.keyCode <= 39)) { 
   return;
  } 

  if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
    e.preventDefault();
  }
});

```

Vaya diferencia para lograr lo mismo 😀

***

_Este artículo fue [publicado primero en mi blog personal](https://otroespacioblog.wordpress.com/2019/02/13/javascript-y-el-dom-keydown-vs-keypress/), Otro Espacio Blog. Ahí escribo sobre todo lo que aprendo al programar y también sobre temas no relacionados a tecnología._