Esdeveniments
Al capítol anterior, el codi feia coses a la pàgina una sola vegada, en executar-se. Aquí aprendrem a fer que el codi reaccioni quan l'usuari fa alguna cosa: un clic, escriure en un camp, prémer una tecla… Això és el que converteix una pàgina HTML en una aplicació.
Què és un esdeveniment?
Un esdeveniment (en anglès, event) és una cosa que passa a la pàgina: un clic del ratolí, una tecla premuda, un dit que toca la pantalla, una imatge que acaba de carregar-se… Sempre que passa una d'aquestes coses, el navegador "llança" un esdeveniment.
El que farem és escoltar determinats esdeveniments en determinats elements i dir-li al navegador «quan passi això, executa aquesta funció». Aquest patró s'anomena event listener.
El primer clic: addEventListener
La funció clau és addEventListener, que es crida sobre l'element que vols escoltar. Rep dos arguments: el tipus d'esdeveniment (un string) i la funció a executar quan passi:
Després d'executar, clica el botó a la pàgina viva i fixa't en la consola. Cada clic dispara la funció i imprimeix una nova línia.
Mira la sintaxi amb cura. Aquest és el primer cop que passem una funció com a argument d'una altra funció. No la cridem (no posem parèntesis), només la donem perquè addEventListener la cridi més endavant. El nom tècnic és callback: una funció que tornem a cridar quan passa alguna cosa.
Modificar la pàgina des de la funció
Combinant esdeveniments amb el que vam aprendre al capítol 9, ja pots fer interfícies de veritat. Per exemple, un botó que canvia un text:
Cada vegada que cliques, la funció s'executa i modifica el títol. La primera vegada veuràs el canvi; els clics següents repeteixen la mateixa acció (que ja no fa res visible, perquè el títol ja diu "He canviat!").
Recordar coses: variables fora de la funció
Què passa si volem comptar quantes vegades s'ha clicat el botó? Necessitem una variable que recordi el valor entre clics. La clau és declarar-la fora de la funció (al codi principal), i modificar-la des de dins:
Clica el botó diverses vegades. La variable n es declara una sola vegada (val 0 al començar) i la funció la incrementa a cada clic. Així, el codi té memòria.
Compte: si haguéssim declarat let n = 0 dins de la funció, cada clic la tornaria a posar a 0. Per això la posem fora.
L'objecte event
Quan el navegador crida la nostra funció, li passa un argument: un objecte event amb informació sobre què ha passat. Conté coses com la posició del clic, l'element clicat, quina tecla s'ha premut, etc.
Mou el ratolí dins de la zona i clica en diferents punts. Veuràs com canvien les coordenades a la consola. event.clientX i event.clientY et donen on s'ha produït el clic.
Pots posar el paràmetre amb el nom que vulguis (event, e, ev…), però per convenció s'acostuma a escriure event o, abreujat, e.
Llegir el que escriu l'usuari: <input>
Una pàgina pot tenir un quadre de text on l'usuari escriu coses (un <input>). Per llegir el que hi ha escrit, accedeixes a la propietat .value de l'element:
Escriu un nom al quadre de text i clica "Saluda". El text del <p> resultat es modifica amb el que has escrit.
Hi ha un altre esdeveniment útil amb <input>: "input". Es dispara cada vegada que l'usuari escriu o esborra un caràcter. Així pots fer coses en temps real, sense necessitat de cap botó:
Escriu al quadre i mira com el paràgraf de sota es va actualitzant en majúscules en temps real. Aquesta interactivitat és el que fa que les aplicacions web modernes se sentin "vives".
Altres esdeveniments útils
Hi ha dotzenes d'esdeveniments diferents. Els més habituals:
"click"— clic del ratolí (ja l'has vist)."input"— l'usuari escriu en un<input>o<textarea>."change"— l'usuari acaba d'editar i marxa de l'element."mousemove"— el ratolí es mou per damunt d'un element."mouseover"/"mouseout"— el ratolí entra o surt de l'element."keydown"/"keyup"— l'usuari prem o deixa anar una tecla."submit"— un formulari s'envia.
Tots funcionen amb el mateix patró: element.addEventListener("nom", callback). L'objecte event que rep la funció té propietats específiques per a cada tipus (per exemple, event.key per a tecles).
Aquí en tens un que respon a tecles. Cliquem primer al quadre per donar-li el focus, i després premem qualsevol tecla:
Errors típics
1. Cridar la funció enlloc de passar-la — l'error més comú dels principiants:
// ✗ INCORRECTE — la funció es crida immediatament,
// i passem el resultat (undefined) a addEventListener
boto.addEventListener("click", funcio());
// ✓ CORRECTE — passem la funció sense cridar-la
boto.addEventListener("click", funcio);
Recorda: amb parèntesis, crides la funció ara mateix. Sense parèntesis, referencies la funció perquè algú altre la cridi després. Aquí volem el segon.
2. Declarar la variable d'estat dins la funció:
Clica el botó moltes vegades. El número sempre passa de 0 a 1, mai més. La variable n es declara cada vegada que la funció s'executa, així que sempre torna a començar.
3. Buscar l'element abans que existeixi — si el codi s'executa abans que la pàgina hagi creat l'element, querySelector retorna null. En aquest curs no patirem aquest problema perquè el simulador injecta el codi després de carregar la pàgina, però en un projecte teu propi pot passar.
Exercici
La pàgina ja té els elements preparats: un <h1 id="num"> que mostra el número, un botó #sumar i un botó #restar. Has d'escriure les dues funcions de clic.
Resum
- Un esdeveniment és una cosa que passa a la pàgina: clic, tecla, moviment del ratolí…
element.addEventListener("tipus", funcio)diu al navegador de cridarfunciocada vegada que passi l'esdeveniment.- La funció és un callback: la passem sense cridar (sense parèntesis); algú altre la cridarà més endavant.
- Per recordar dades entre crides al callback, declara la variable fora de la funció.
- La funció rep un objecte
eventamb informació de l'esdeveniment: posició, tecla, element, etc. - El valor d'un
<input>es llegeix amb la propietat.value. - Esdeveniments útils:
click,input,change,mousemove,keydown.