Módulo 01 // Unidad 03

Eventos

Cómo reacciona una página a lo que hace el usuario sin quedarse esperando

Unidad para alumnos del curso

Comprobando tu sesión…

Inicia sesión con la cuenta de Google con la que estás matriculado para ver esta unidad.

Esa cuenta no tiene acceso a este curso. Prueba con otra.

No se ha podido cargar el inicio de sesión de Google. Comprueba la conexión o si algún bloqueador lo impide, y recarga la página.

Una aplicación de consola sigue un guion: pide un dato, espera, lo procesa. En el navegador el orden lo marca el usuario, que puede pulsar, escribir o hacer scroll en cualquier momento. JavaScript no se queda esperando: registra funciones que el navegador llamará cuando ocurra algo. Ese «algo» es un evento.

1 // Escuchar un evento

Para reaccionar a un evento necesitas tres cosas: el elemento, el tipo de evento y la función que se ejecutará. Se unen con addEventListener:

const boton = document.querySelector('#guardar');

function manejarClic() {
  console.log('Has pulsado guardar');
}

boton.addEventListener('click', manejarClic);

Aquí aparecen juntas dos ideas del módulo anterior. La función se pasa sin paréntesis, porque no quieres ejecutarla ahora sino entregarla. Y como es un callback, puede usar las variables del lugar donde se escribió gracias a los closures.

Un mismo elemento puede tener varios listeners para el mismo evento, y se ejecutarán en el orden en que se registraron.

DE UN CLIC A TU FUNCIÓN al cargar · tu código boton.addEventListener('click', manejarClic) se guarda, no se ejecuta más tarde... 1 · usuario hace clic 2 · navegador crea el evento 3 · busca los listeners 4 · llama a manejarClic(e) e.type → 'click' e.target → el botón pulsado
Distingue los dos momentos: la franja superior ocurre una vez, al cargar el script; la cadena de abajo ocurre cada vez que el usuario pulsa, y termina llamando a la función que se registró.

Verás código antiguo con atributos en el HTML, como <button onclick="guardar()">, o con la propiedad boton.onclick = guardar. El atributo mezcla JavaScript con el marcado, y la propiedad sólo admite una función: asignar otra borra la anterior. Usa siempre addEventListener.

2 // El objeto evento

Cuando el navegador llama a tu función, le pasa como argumento un objeto evento con la información de lo que ha ocurrido. Por convención se llama e, ev o event:

boton.addEventListener('click', (e) => {
  console.log(e.type);      // 'click'
  console.log(e.target);    // el elemento sobre el que se hizo clic
});

document.addEventListener('keydown', (e) => {
  console.log(e.key);       // 'Enter', 'a', 'Escape'...
  if (e.key === 'Escape') cerrarModal();
});

campo.addEventListener('input', (e) => {
  console.log(e.target.value); // el texto actual del campo
});

Además de las propiedades comunes, cada tipo de evento añade las suyas: los de ratón traen la posición (clientX, clientY), los de teclado la tecla (key) y los modificadores (ctrlKey, shiftKey).

3 // Los eventos que más vas a usar

Evento Cuándo se dispara Uso típico
click Al pulsar un elemento (también con teclado en botones) Botones, enlaces, tarjetas
input Cada vez que cambia el valor de un campo Buscadores en vivo, contadores
change Al confirmar un cambio (salir del campo, elegir opción) select, casillas, ficheros
submit Al enviar un formulario Validar y enviar datos
keydown Al pulsar una tecla Atajos de teclado
focus / blur Al entrar o salir de un campo Mostrar ayudas o errores
DOMContentLoaded Cuando el HTML está analizado Arrancar la aplicación

Para botones, usa click aunque pienses en teclado: el navegador lo dispara también al pulsar Enter o la barra espaciadora sobre un <button>. Si en su lugar pones un click sobre un <div>, la acción no será accesible desde el teclado.

4 // Comportamiento por defecto y limpieza

Muchos elementos ya hacen algo por sí mismos: un enlace navega, un formulario se envía y recarga la página, un clic derecho abre el menú contextual. El método preventDefault() cancela esa acción del navegador, pero no detiene tu código:

formulario.addEventListener('submit', (e) => {
  e.preventDefault();       // el formulario no recarga la página
  // aquí validas y envías los datos con JavaScript
});

Para dejar de escuchar un evento se usa removeEventListener con exactamente la misma función que se registró. Por eso, si piensas quitar un listener, no puedes usar una flecha anónima al registrarlo. Si sólo necesitas que se ejecute una vez, hay una opción más cómoda:

boton.addEventListener('click', mostrarBienvenida, { once: true });

Un campo de búsqueda debe mostrar debajo cuántos caracteres llevas escritos y avisar en rojo si pasas de 30.

<input id="buscar" type="search">
<p id="contador">0 / 30</p>
  1. Elegir el evento: change sólo se dispara al salir del campo; para reaccionar en cada pulsación se necesita input.
  2. Leer el valor desde el evento: e.target.value.length da la longitud actual, sin tener que volver a seleccionar el campo.
  3. Actualizar el texto: contador.textContent = `${longitud} / 30`;.
  4. Reflejar el estado con una clase: contador.classList.toggle('excedido', longitud > 30); y el CSS pinta .excedido en rojo.
const buscar = document.querySelector('#buscar');
const contador = document.querySelector('#contador');

buscar.addEventListener('input', (e) => {
  const longitud = e.target.value.length;
  contador.textContent = `${longitud} / 30`;
  contador.classList.toggle('excedido', longitud > 30);
});
El contador se actualiza con cada carácter y el aviso aparece y desaparece solo. El código no comprueba nada en un bucle: se limita a describir qué hacer cuando el navegador avise de que el valor ha cambiado.

5 // Para practicar

Botones que muestran y ocultan contenido, un contador en vivo y un atajo de teclado. Cada ejercicio trae el enunciado en los comentarios del código.

Ocultar contenidos y contar caracterestraining-daw-sv/modulo-01/03-eventos/01_hide_contents

Autoevaluación

Tu programa Java de consola lee una opción con Scanner y se queda esperando. En el navegador no escribes nada parecido para esperar un clic. ¿Cómo se consigue reaccionar a él?
Registrando una función que el navegador llamará cuando ocurra el evento. El script termina de ejecutarse y la página queda libre; cuando el usuario hace clic, el navegador busca las funciones registradas para ese elemento y ese tipo de evento y las ejecuta. Tu código no espera: es avisado.
Un removeEventListener('click', () => guardar()) no elimina el listener que se añadió con la misma línea. ¿Por qué?
Porque son dos funciones distintas, aunque tengan el mismo código. Cada flecha escrita crea un objeto función nuevo, y removeEventListener busca exactamente la misma referencia que se registró. Para poder quitarlo hay que guardar la función en una constante y usar esa constante en las dos llamadas.
Un formulario recarga la página al pulsar «Enviar» y el mensaje de confirmación que pintas desaparece al instante. ¿Qué falta?
Falta event.preventDefault() en el listener de submit. Enviar un formulario es un comportamiento por defecto del navegador: navega a la URL del atributo action, o recarga la misma página. Tu código se ejecuta, pero la navegación posterior borra el resultado.