En la programació tradicional, les aplicacions s’executen seqüencialment de principi a fi per produir els seus resultats. No obstant això, en l’actualitat el model predominant és el de la programació basada en esdeveniments. Els scripts i programes esperen sense realitzar cap tasca fins que es produeixi un esdeveniment. Un cop produït, executen alguna tasca associada a l’aparició d’aquest esdeveniment i quan conclou, l’script o programa torna a l’estat d’espera.
JavaScript permet realitzar scripts amb tots dos mètodes de programació: seqüencial i basada en esdeveniments . Els esdeveniments de JavaScript permeten la interacció entre les aplicacions JavaScript i els usuaris. Cada vegada que es prem un botó, es produeix un esdeveniment. Cada vegada que es prem una tecla, també es produeix un esdeveniment. No obstant això, perquè es produeixi un esdeveniment no és obligatori que intervingui l’usuari, ja que per exemple, cada vegada que es carrega una pàgina, també es produeix un esdeveniment.
El nivell 1 de DOM no inclou especificacions relatives als esdeveniments JavaScript. El nivell 2 de DOM inclou certs aspectes relacionats amb els esdeveniments i el nivell 3 de DOM inclou l’especificació completa dels esdeveniments de JavaScript. Desafortunadament, l’especificació de nivell 3 de DOM es va publicar l’any 2004, més de deu anys després que els primers navegadors incloguessin els esdeveniments.
Per aquest motiu, moltes de les propietats i mètodes actuals relacionats amb els esdeveniments són incompatibles amb els de DOM. De fet, navegadors com Internet Explorer tracten els esdeveniments seguint el seu propi model incompatible amb l’estàndard.
El model simple d’esdeveniments es va introduir a la versió 4 de l’estàndard HTML i es considera part de el nivell més bàsic de DOM . Encara que les seves característiques són limitades, és l’únic model que és compatible amb tots els navegadors i per tant, l’únic que permet crear aplicacions que funcionen de la mateixa manera en tots els navegadors.
15.1 Tipus d’esdeveniments
Cada element XHTML té definida la seva pròpia llista de possibles esdeveniments que se li poden assignar. Un mateix tipus d’esdeveniment (per exemple, punxar el botó esquerre de l’ratolí) pot estar definit per a diversos elements XHTML i un mateix element XHTML pot tenir associats diferents esdeveniments.
El nom dels esdeveniments es construeix mitjançant el prefix on
, seguit del nom en anglès de l’acció associada a l’esdeveniment. Així, l’esdeveniment de punxar un element amb el ratolí s’anomena onclick
i l’esdeveniment associat a l’acció de moure el ratolí es denomina onmousemove
.
La següent taula resumeix els esdeveniments més importants definits per JavaScript:
Esdeveniment | Descripció | Elements per als quals està definit |
---|---|---|
onblur |
Un element perd el focus | <button> , <input> , <label> , <select> , <textarea> , <body> |
onchange |
Un element ha estat modificat | <input> , <select> , <textarea> |
onclick |
Prémer i deixar anar el ratolí | Tots els elements |
ondblclick |
Prémer dues vegades seguides amb el ratolí | Tots els elements |
onfocus |
Un element obté el focus | <button> , <input> , <label> , <select> , <textarea> , <body> |
onkeydown |
Prémer una tecla i no deixar-la anar | Elements de formulari i <body> |
onkeypress |
Prémer una tecla | Elements de formulari i <body> |
onkeyup |
Deixar anar una tecla premuda | Elements de formulari i <body> |
onload |
Pàgina carregada completament | <body> |
onmousedown |
Prémer un botó de l’ratolí i no deixar-lo anar | Tots els elements |
onmousemove |
Moure el ratolí | Tots els elements |
onmouseout |
El ratolí “surt” de l’ element | Tots els elements |
onmouseover |
El ratolí “entra” en l’element | Tots els elements |
onmouseup |
Deixar anar el botó de l’ratolí | Tots els elements |
onreset |
Inicialitzar el formulari | <form> |
onresize |
Modificar l’ mida de la finestra | <body> |
onselect |
Seleccionar un text | <input> , <textarea> |
onsubmit |
Enviar el formulari | <form> |
onunload |
s’abandona la pàgina, per exemple a l’tancar el navega dor | <body> |
els esdeveniments més utilitzats en les aplicacions web tradicionals són onload
per esperar que es carregui la pàgina per complet, els esdeveniments onclick
, onmouseover
, onmouseout
per controlar el ratolí i onsubmit
per controlar l’enviament dels formularis.
Alguns esdeveniments de la taula anterior (onclick
, onkeydown
, onkeypress
, onreset
, onsubmit
) permeten evitar l ‘ “acció per defecte” d’aquest esdeveniment. Més endavant es mostra en detall aquest comportament, que pot resultar molt útil en algunes tècniques de programació.
Les accions típiques que realitza un usuari en una pàgina web poden donar lloc a una successió d’esdeveniments. A l’prémer per exemple sobre un botó de tipus <input type="submit">
es desencadenen els esdeveniments onmousedown
, onclick
, onmouseup
i onsubmit
de forma consecutiva.
15.1.1 Manejadors d’esdeveniments
un esdeveniment de JavaScript per si mateix no té utilitat. Perquè els esdeveniments resultin útils, s’han d’associar funcions o codi JavaScript a cada esdeveniment. D’aquesta manera, quan es produeix un esdeveniment s’executa el codi indicat, de manera que l’aplicació pot respondre davant qualsevol esdeveniment que es produeixi durant la seva execució.
Les funcions o codi JavaScript que es defineixen per a cada esdeveniment s’anomenen gestor d’esdeveniments (event handlers en anglès) i com JavaScript és un llenguatge molt flexible, hi ha diverses formes diferents d’indicar els controladors:
- manejadors com atributs dels elements XHTML.
- Manejadors com a funcions JavaScript externes.
- Manejadors “semàntics”.
15.1.1.1 Manejadors com atributs XHTML
Es tracta de el mètode més senzill i alhora menys professional d’indicar el codi JavaScript que s’ha d’executar quan es produeixi un esdeveniment. En aquest cas, el codi s’inclou en un atribut de el propi element XHTML. En el següent exemple, es vol mostrar un missatge quan l’usuari faci clic amb el ratolí sobre un botó:
<input type="button" value="Pinchame y verás" onclick="console.log('Gracias por pinchar');" />
En aquest mètode , es defineixen atributs XHTML amb el mateix nom que els esdeveniments que es volen utilitzar. L’exemple anterior només vol controlar l’esdeveniment de punxar amb el ratolí, el nom és onclick
. Així, l’element XHTML per al qual es vol definir aquest esdeveniment, ha d’incloure un atribut anomenat onclick
.
El contingut de l’atribut és una cadena de text que conté totes les instruccions JavaScript que s’executen quan es produeix l’esdeveniment. En aquest cas, el codi JavaScript és molt senzill (console.log('Gracias por pinchar');
), ja que només es tracta de mostrar un missatge.
En aquest altre exemple, quan l’usuari punxa sobre l’element <div>
es mostra un missatge i quan l’usuari passa el ratolí per sobre de l’element, es mostra un altre missatge:
<div onclick="console.log('Has pinchado con el ratón');" onmouseover="console.log('Acabas de pasar el ratón por encima');"> Puedes pinchar sobre este elemento o simplemente pasar el ratón por encima</div>
Aquest altre exemple inclou una de les instruccions més utilitzades en les aplicacions JavaScript més antigues:
<body onload="console.log('La página se ha cargado completamente');"> ...</body>
El missatge anterior es mostra després que la pàgina s’hagi carregat completament, és a dir, després que s’hagi descarregat el seu codi HTML, les seves imatges i qualsevol altre objecte inclòs a la pàgina.
l’esdeveniment onload
és un dels més utilitzats ja que, com es va veure en el capítol de DOM, les funcions que permeten accedir i manipular els nodes de l’arbre DOM només estan disponibles quan la pàgina s’ha carregat comple tament.
15.1.1.2 Manejadors d’esdeveniments i variable this
estigui habilitat defineix una variable especial anomenada this
que es crea automàticament i que es empra en algunes tècniques avançades de programació. En els esdeveniments, es pot utilitzar la variable this
per referir-se a l’element XHTML que ha provocat l’esdeveniment. Aquesta variable és molt útil per exemples com el següent:
Quan l’usuari passa el ratolí per sobre de l ‘<div>
, el color de la vora es mostra de color negre. Quan el ratolí surt de l’<div>
, es torna a mostrar la vora amb el color gris clar original.
<div style="width:150px; height:60px; border:thin solid silver"> Sección de contenidos...</div>
Si no s’utilitza la variable this
, el codi necessari per modificar el color de les vores, seria el següent:
<div style="width:150px; height:60px; border:thin solid silver" onmouseover="document.getElementById('contenidos').style.borderColor='black';" onmouseout="document.getElementById('contenidos').style.borderColor='silver';"> Sección de contenidos...</div>
El codi anterior és massa llarg i massa propens a cometre errors. Dins el codi d’un esdeveniment, JavaScript crea automàticament la variable this
, que fa referència a l’element XHTML que ha provocat l’esdeveniment. Així, l’exemple anterior es pot reescriure de la següent manera:
<div style="width:150px; height:60px; border:thin solid silver" onmouseover="this.style.borderColor='black';" onmouseout="this.style.borderColor='silver';"> Sección de contenidos...</div>
El codi anterior és molt més compacte, més fàcil de llegir i d’escriure i segueix funcionant correctament encara que es modifiqui el valor de l’atribut id de l’<div>
.
15.1.1.3 Manejadors d’esdeveniments com a funcions externes
La definició de controladors d’esdeveniments en els atributs XHTML és un mètode senzill però poc aconsellable per tractar amb els esdeveniments en JavaScript. El principal inconvenient és que es complica en excés pel que fa s’afegeixen algunes poques instruccions, de manera que només és recomanable per als casos més senzills.
Quan el codi de la funció manejadora és més complex, com ara la validació d’un formulari, és aconsellable agrupar tot el codi JavaScript en una funció externa que s’invoca des del codi XHTML quan es produeix l’esdeveniment.
d’aquesta manera, el següent exemple:
<input type="button" value="Pinchame y verás" onclick="console.log('Gracias por pinchar');" />
Es pot transformar en:
function muestraMensaje() { console.log('Gracias por pinchar');}
<input type="button" value="Pinchame y verás" onclick="muestraMensaje()" />
en les funcions externes no és possible utilitzar la variable this
de la mateixa manera que en els manejadors inserits en els atributs XHTML. Per tant, cal passar la variable this
com a paràmetre a la funció manejadora:
function resalta(elemento) { switch(elemento.style.borderColor) { case 'silver': case 'silver silver silver silver': case '#c0c0c0': elemento.style.borderColor = 'black'; break; case 'black': case 'black black black black': case '#000000': elemento.style.borderColor = 'silver'; break; }}
<div style="padding: .2em; width: 150px; height: 60px; border: thin solid silver" onmouseover="resalta(this)" onmouseout="resalta(this)"> Sección de contenidos...</div>
En l’exemple anterior, a la funció externa se li passa el paràmetre this
, que dins de la funció s’anomena elemento
. A el passar this
com a paràmetre, és possible accedir de forma directa des de la funció externa a les propietats de l’element que ha provocat l’esdeveniment.
D’altra banda, l’exemple anterior es complica per la forma en la qual els diferents navegadors emmagatzemen el valor de la propietat borderColor
. Mentre que el Firefox emmagatzema (en cas que les quatre vores coincideixin en color) el valor simple black
, Internet Explorer l’emmagatzema com black black black black
i opera emmagatzema la seva representació hexadecimal #000000
.
15.1.1.4 manejadors d’esdeveniments semàntics
Utilitzar els atributs XHTML o les funcions externes per afegir controladors d’esdeveniments té un greu inconvenient: “embruten” el codi XHTML de la pàgina.
Com és conegut, a l’crear pàgines web es recomana separar els continguts (XHTML) de la presentació (CSS). Sempre que sigui possible, també es recomana separar els continguts (XHTML) de la programació (JavaScript). Barrejar JavaScript i XHTML complica excessivament el codi font de la pàgina, dificulta el seu manteniment i redueix la semàntica de el document final produït.
Afortunadament, hi ha un mètode alternatiu per definir els controladors d’esdeveniments de JavaScript. Aquesta tècnica consisteix a assignar les funcions externes mitjançant les propietats DOM dels elements XHTML. Així, el següent exemple:
<input type="button" value="Pinchame y verás" onclick="console.log('Gracias por pinchar');" />Se puede transformar en:
function muestraMensaje() { console.log('Gracias por pinchar');}document.getElementById("pinchable").onclick = muestraMensaje;
<input type="button" value="Pinchame y verás" />
el codi XHTML resultant és molt “net”, ja que no es barreja amb el codi JavaScript. La tècnica dels manejadors semàntics consisteix en:
- Assignar un identificador únic a l’element XHTML mitjançant l’atribut id.
- Crear una funció de JavaScript encarregada de gestionar l’esdeveniment.
- Assignar la funció a un esdeveniment concret de l’element XHTML mitjançant DOM.
un altre avantatge addicional d’aquesta tècnica és que les funcions externes poden utilitzar la variable this
referida a l’element que original l’esdeveniment.
Assignar la funció manejadora mitjançant DOM és un procés que requereix una explicació detallada. En primer lloc, s’obté la referència de l’element a què es va a assignar el gestor:
document.getElementById("pinchable");
A continuació, s’assigna la funció externa a l’esdeveniment desitjat mitjançant una propietat de l’element amb el mateix nom de l’esdeveniment:
document.getElementById("pinchable").onclick = ...
Finalment, s’assigna la funció externa. Com ja s’ha comentat en capítols anteriors, el més important (i la causa més comuna d’errors) és indicar només el nom de la funció, és a dir, prescindir dels parèntesis a l’assignar la funció:
document.getElementById("pinchable").onclick = muestraMensaje;
Si s’afegeixen els parèntesis a la fin, en realitat s’està invocant la funció i assignant el valor retornat per la funció a l’esdeveniment onclick
d’element.
l’únic inconvenient d’aquest mètode és que els gestors s’assignen mitjançant les funcions DOM, que només es poden utilitzar després que la pàgina s’ha carregat completament. D’aquesta manera, perquè l’assignació dels controladors no resulti errònia, cal assegurar-se que la pàgina ja s’ha carregat.
Una de les formes més senzilles d’assegurar que cert codi es va a executar després que la pàgina es carregui completament és utilitzar l’esdeveniment onload
:
window.onload = function() { document.getElementById("pinchable").onclick = muestraMensaje;}
la tècnica anterior utilitza una funció anònima per assignar algunes instruccions a l’esdeveniment onload
de la pàgina (en aquest cas s’ha establert mitjançant l’objecte window
). D’aquesta manera, per assegurar que cert codi es va a executar després que la pàgina s’hagi carregat, només cal incloure-ho en l’interior de la següent construcció:
window.onload = function() { ...}
15.2 El flux d’esdeveniments
A més dels esdeveniments bàsics que s’han vist, els navegadors inclouen un mecanisme relacionat anomenat flux d’esdeveniments o “event flow”. El flux d’esdeveniments permet que diversos elements diferents puguin respondre a un mateix esdeveniment.
Si en una pàgina HTML es defineix un element <div>
amb un botó al seu interior , quan l’usuari prem sobre el botó, el navegador permet assignar una funció de resposta a el botó, una altra funció de resposta a l’<div>
que el conté i altra funció de resposta a la pàgina completa. D’aquesta manera, un sol esdeveniment (la pulsació d’un botó) provoca la resposta de tres elements de la pàgina (incloent-hi la pròpia pàgina).
L’ordre en què s’executen els esdeveniments assignats a cada element de la pàgina és el que constitueix el flux d’esdeveniments. A més, hi ha moltes diferències en el flux d’esdeveniments de cada navegador.
15.2.1 Event bubbling
En aquest model de flux d’esdeveniments, l’ordre que se segueix és des de l’element més específic fins a l’element menys específic.
En els propers exemples s’empra la següent pàgina HTML:
<html onclick="procesaEvento()"> <head><title>Ejemplo de flujo de eventos</title></head> <body onclick="procesaEvento()"> <div onclick="procesaEvento()">Pincha aqui</div> </body></html>
Quan es prem sobre el text “Fes clic aquí” que es troba dins de l’<div>
, s’executen els següents esdeveniments en l’ordre que mostra el següent esquema:
Figura 15.1 Esquema de l’funcionament del “event bubbling”
el primer esdeveniment que es té en compte és el generat pel <div>
que conté el missatge. A continuació el navegador recorre els ascendents de l’element fins que arriba al nivell superior, que és l’element document
.
Aquest model de flux d’esdeveniments és el que inclou el navegador Internet Explorer. Els navegadors de la família Mozilla (per exemple Firefox) també suporten aquest model, però lleugerament modificat. L’anterior exemple en un navegador de la família Mozilla presenta el següent flux d’esdeveniments:
Figura 15.2 Esquema de l’funcionament del “event bubbling” en els navegadors de Mozilla
Encara que l’objecte window
no és part de DOM, el flux d’esdeveniments implementat per Mozilla recorre els ascendents de l’element fins al mateix objecte window
, afegint per tant un esdeveniment més a el model d’Internet Explorer.
15.2.2 Event capturing
En aquest altre model, el flux d’esdeveniments es defineix des de l’element menys específic fins a l’element més específic. En altres paraules, el mecanisme definit és justament el contrari a l ‘ “event bubbling”. Aquest model l’utilitzava el desaparegut navegador Netscape Navigator 4.0.
15.2.3 Esdeveniments DOM
El flux d’esdeveniments definit en l’especificació DOM suporta tant el bubbling com el capturing, però el ” event capturing “s’executa en primer lloc. Els dos fluxos d’esdeveniments recorren tots els objectes DOM des de l’objecte document
fins l’element més específic i viceversa. A més, la majoria de navegadors que implementen els estàndards, continuen el flux a l’objecte window
.
El flux d’esdeveniments DOM de l’exemple anterior es mostra a continuació:
Figura 15.3 Esquema de l’flux d’esdeveniments de el model DOM
l’element més específic de l’flux d’esdeveniments no és el <div>
que desencadena l’execució dels esdeveniments, sinó el node de tipus TextNode
que conté el <div>
. El fet de combinar els dos fluxos d’esdeveniments, provoca que el node més específic pugui executar dos esdeveniments de forma consecutiva.
15.3 Handlers i listeners
A les seccions anteriors es va introduir el concepte de “event handler” o gestor d’esdeveniments, que són les funcions que responen als esdeveniments que es produeixen. A més, es van veure tres formes de definir els controladors d’esdeveniments per al model bàsic d’esdeveniments:
- JavaScript dins d’un atribut de l’propi element HTML
- Definició de l’esdeveniment en el propi element HTML però el gestor és una funció externa
- Manejadors semàntics assignats mitjançant DOM sense necessitat de modificar el codi HTML de la pàgina
Qualsevol d’aquests tres models funciona correctament en tots els navegadors disponibles en l’actualitat. Les diferències entre navegadors sorgeixen quan es defineix més d’un gestor d’esdeveniments per a un mateix esdeveniment d’un element. La forma d’assignar i “desassignar” controladors múltiples depèn completament de el navegador utilitzat.
15.3.1 Manejadors d’esdeveniments de DOM
L’especificació DOM defineix dos mètodes similars als disponibles per Internet Explorer i denominats addEventListener()
i removeEventListener()
per associar i desassociar controladors d’esdeveniments.
La principal diferència entre aquests mètodes i els anteriors és que en aquest cas es requereixen tres paràmetres: el nom del “event listener”, una referència a la funció encarregada de processar l’esdeveniment i el tipus de flux d’esdeveniments a què s’aplica.
el primer argument no és el nom complet de l’esdeveniment com succeeix en el model d’Internet Explorer, sinó que s’ha d’eliminar el prefix on
. En altres paraules, si a Internet Explorer s’utilitzava el nom onclick
, ara s’ha d’utilitzar click
.
Si el tercer paràmetre és true
, el gestor s’empra en la fase d’capturi. Si el tercer paràmetre és false
, el gestor s’associa a la fase d’bubbling.
A continuació, es mostren els exemples anteriors emprant els mètodes definits per DOM:
function muestraMensaje() { console.log("Has pulsado el ratón");}var elDiv = document.getElementById("div_principal");elDiv.addEventListener("click", muestraMensaje, false); // Más adelante se decide desasociar la función al eventoelDiv.removeEventListener("click", muestraMensaje, false);
Associant múltiples funcions a un únic esdeveniment:
function muestraMensaje() { console.log("Has pulsado el ratón");} function muestraOtroMensaje() { console.log("Has pulsado el ratón y por eso se muestran estos mensajes");} var elDiv = document.getElementById("div_principal");elDiv.addEventListener("click", muestraMensaje, true);elDiv.addEventListener("click", muestraOtroMensaje, true);
Si s’associa una funció a un flux d’esdeveniments determinat, aquesta funció només es pot desassociar en el mateix tipus de flux d’esdeveniments. Si es considera el següent exemple:
function muestraMensaje() { console.log("Has pulsado el ratón");} var elDiv = document.getElementById("div_principal");elDiv.addEventListener("click", muestraMensaje, false); // Más adelante se decide desasociar la función al eventoelDiv.removeEventListener("click", muestraMensaje, true);
L’última instrucció intenta desassociar la funció muestraMensaje
en el flux d’esdeveniments de capturi, mentre que a l’associar-la, es va indicar el flux d’esdeveniments de bubbling. Encara que l’execució de l’aplicació no s’atura i no es produeix cap error, l’última instrucció no té cap efecte.
15.4 L’objecte event
Quan es produeix un esdeveniment, no és suficient amb assignar-li una funció responsable de processar aquest esdeveniment. Normalment, la funció que processa l’esdeveniment necessita informació relativa a l’esdeveniment produït: la tecla que s’ha premut, la posició de l’ratolí, l’element que s’ha produït l’esdeveniment, etc..
L’objecte event
és el mecanisme definit pels navegadors per proporcionar tota aquesta informació. Es tracta d’un objecte que es crea automàticament quan es produeix un esdeveniment i que es destrueix de forma automàtica quan s’han executat totes les funcions assignades a l’esdeveniment.
L’estàndard DOM especifica que l’objecte event
és l’únic paràmetre que s’ha de passar a les funcions encarregades de processar els esdeveniments. Per tant, en els navegadors que segueixen els estàndards, es pot accedir a l’objecte event
mitjançant l’array dels arguments de la funció:
elDiv.onclick = function() { var elEvento = arguments;}
També és possible indicar el nom argument de manera explícita:
elDiv.onclick = function(event) { ...}
El funcionament dels navegadors que segueixen els estàndards pot semblar “màgic”, ja que en la declaració de la funció s’indica que té un paràmetre, però en l’aplicació no es passa cap paràmetre a aquesta funció. En realitat, els navegadors que segueixen els estàndards creen automàticament aquest paràmetre i ho passen sempre a la funció encarregada de gestionar l’esdeveniment.
15.4.1 Propietats i mètodes
Tot i que el mecanisme definit pels navegadors per a l’objecte event
és similar, existeixen nombroses diferències quant les propietats i mètodes de l’objecte.
15.4.1.1 propietats definides per DOM
La següent taula recull les propietats definides per a l’objecte event
en els navegadors que segueixen els estàndards:
Propietat / Mètode | Retorna | Descripció |
---|---|---|
altKey |
boolean | Retorna true si s’ha premut la tecla ALT i false en un altre cas |
bubbles |
Boolean | Indica si l’esdeveniment pertany a el flux d’esdeveniments de bubbling |
button |
Nombre sencer | el botó de l’ratolí que ha estat premut.Possibles valors: 0 – Cap botó premut 1 – S’ha premut el botó izquierdo 2 – Se ha pulsado el botón derecho 3 – Se pulsan a la vez el botón izquierdo y el derecho 4 – Se ha pulsado el botón central 5 – Se pulsan a la vez el botón izquierdo y el central 6 – Se pulsan a la vez el botón derecho y el central 7` – Es premen alhora els 3 botons |
cancelable |
Boolean | Indica si l’esdeveniment es pot cancel·lar |
cancelBubble |
Boolean | Indica si s’ha aturat el flux d’esdeveniments de tipus bubbling |
charCode |
Nombre sencer | el codi unicode de l’caràcter corresponent a la tecla premuda |
clientX |
Nombre sencer | Coordenada X de la posició de l’ratolí respecte de l’àrea visible de la finestra |
clientY |
Nombre sencer | Coordenada I de la posició de l’ratolí re specto de l’àrea visible de la finestra |
ctrlKey |
Boolean | Retorna true si s’ha premut la tecla CTRL i false en un altre cas |
currentTarget |
element | l’element que és l’objectiu de l’esdeveniment |
detail |
nombre sencer | el nombre de vegades que s’han premut els botons de l’ratolí |
eventPhase |
Nombre sencer | la fase a la qual pertany l’esdeveniment: 0 – Fase capturing 1 – En l’element destí 2 – Fase bubbling |
isChar |
Boolean | Indica si la tecla polsada correspon a un caràcter |
keyCode |
Nombre sencer | Indica el codi numèric de l’ tecla premuda |
metaKey |
Nombre sencer | Retorna true si s’ha premut la tecla META i false en un altre cas |
pageX |
Nombre sencer | Coordenada X de la posició de l’ratolí respecte de la pàgina |
pageY |
Nombre sencer | Coordenada I de la posició de l’ratolí respecte de la pàgina |
preventDefault() |
Funció | Es fa servir per cancel·lar l’acció per omissió de l’esdeveniment |
relatedTarget |
element | l’element que és l’objectiu secundari de l’esdeveniment (relacionat amb els esdeveniments de ratolí) |
screenX |
Nombre sencer | Coordenada X de la posició de l’ratolí respecte de la pantalla completa |
Nombre sencer | Coordenada I de la posició de l’ratolí respecte de la pantalla completa | |
shiftKey |
Boolean | Retorna true si s’ha premut la tecla SHIFT i false en un altre cas |
stopPropagation() |
Funció | Es fa servir per aturar el flux d’esdeveniments de tipus bubbling |
target |
element | l’element que origina l’esdeveniment |
timeStamp |
nombre | la data i hora en què s’ha produït l’esdeveniment |
type |
Cadena de text | el nom de l’esdeveniment |
A l’contrari del que passa amb Internet Explorer, la majoria de propietats de l’objecte event
de DOM són de només lectura. En concret, només les següents propietats són de lectura i escriptura: altKey
, button
i keyCode
.
La tecla META
és una tecla especial que es troba en alguns teclats d’ordinadors molt antics. Actualment, en els ordinadors tipus PC s’assimila a la tecla Alt
oa la tecla de Windows, mentre que en els ordinadors tipus Mac s’assimila a la tecla Command
.
15.4.2 Similituds i diferències entre navegadors
15.4.2.1 Similituds
En ambdós casos s’utilitza la propietat type per obtenir el tipus d’esdeveniment que es tracta:
function procesaEvento(elEvento) { if(elEvento.type == "click") { console.log("Has pulsado el raton"); } else if(elEvento.type == "mouseover") { console.log("Has movido el raton"); }} elDiv.onclick = procesaEvento;elDiv.onmouseover = procesaEvento;
Mentre que el gestor de l’esdeveniment inclou el prefix on
en el seu nom, el tipus d’esdeveniment retornat per la propietat type
prescindeix d’aquest prefix.Per això en l’exemple anterior es compara el seu valor amb click
i mouseover
i no amb onclick
i onmouseover
.
Una altra similitud és l’ús de la propietat keyCode
per obtenir el codi corresponent a l’caràcter de la tecla que s’ha premut. La tecla polsada no sempre representa un caràcter alfanumèric. Quan es prem la tecla ENTER
per exemple, s’obté el codi 13
. La barra d’espai es correspon amb el codi 32
i la tecla d’esborrat té un codi igual a 8
.
una forma més immediata de comprovar si s’han premut algunes tecles especials, és utilitzar les propietats shiftKey
, altKey
i ctrlKey
.
Per obtenir la posició de l’ratolí respecte de la part visible de la finestra, s’empren les propietats clientX
i clientY
. De la mateixa manera, per obtenir la posició de l’punter de l’ratolí respecte de la pantalla completa, s’empren les propietats screenX
i .
15.4.2.2 diferències
Una de les principals diferències és la forma en la qual s’obté l’element que origina l’esdeveniment. Si un element <div>
té assignat un esdeveniment onclick
, a l’prémer amb el ratolí l’interior de l’<div>
s’origina un esdeveniment l’objectiu és l’element <div>
.
// Internet Explorervar objetivo = elEvento.srcElement; // Navegadores que siguen los estandaresvar objetivo = elEvento.target;
Una altra diferència important és la relativa a l’obtenció de l’caràcter corresponent a la tecla premuda. Cada tecla polsada té associats dos codis diferents: el primer és el codi de la tecla que ha estat pressionada i l’altre codi és el que es refereix a l’caràcter premut.
El primer codi és un codi de tecla intern per a JavaScript. El segon codi coincideix amb el codi ASCII de l’caràcter. D’aquesta manera, la lletra a
té un codi intern igual a 65
i un codi ASCII de 97
. D’altra banda, la lletra A
té un codi intern també de 65
i un codi ASCII de 95
.
A Internet Explorer, el contingut de la propietat keyCode
depèn de cada esdeveniment. En els esdeveniments de “pulsació de tecles” (onkeyup
i onkeydown
) el seu valor és igual a el codi intern. En els esdeveniments de “escriure amb tecles” (onkeypress
) el seu valor és igual a el codi ASCII de l’caràcter premut.
Per contra, en els navegadors que segueixen els estàndards la propietat keyCode
és igual a el codi intern en els esdeveniments de “pulsació de tecles” (onkeyup
i onkeydown
) i és igual a 0
en els esdeveniments de” escriure amb tecles “(onkeypress
).
a la pràctica, això suposa que en els esdeveniments onkeyup
i onkeydown
es pot utilitzar la mateixa propietat en tots els navegadors:
function manejador(elEvento) { var evento = elEvento || window.event; console.log(" El código de la tecla pulsada es " + evento.keyCode);}document.onkeyup = manejador;document.onkeydown = manejador;
en aquest cas, si es carrega la pàgina en qualsevol navegador i es prem per exemple la tecla a, es mostra el següent missatge:
Figura 15.4 missatge mostrat en el navegador Firefox
la gran diferència es produc i a l’intentar obtenir el caràcter que s’ha premut, en aquest cas la lletra a
. Per obtenir la lletra, en primer lloc s’ha d’obtenir el seu codi ASCII. Com s’ha comentat, a Internet Explorer el valor de la propietat keyCode
en l’esdeveniment onkeypress
és igual a el caràcter ASCII:
function manejador() { var evento = window.event;
// Internet Explorer var codigo = evento.keyCode;} document.onkeypress = manejador;
no obstant això, en els navegadors que no són Internet Explorer, el codi anterior és igual a 0
per a qualsevol tecla premuda. En aquests navegadors que segueixen els estàndards, s’ha d’utilitzar la propietat charCode
, que retorna el codi de la tecla polsada, però només per a l’esdeveniment onkeypress
:
function manejador(elEvento) { var evento = elEvento;
// Navegadores que siguen los estándares var codigo = evento.charCode;} document.onkeypress = manejador;
Un cop obtingut el codi a cada navegador, s’ha d’utilitzar la funció String.fromCharCode()
per obtenir el caràcter el codi ASCII es passa com a paràmetre. Per tant, la solució completa per obtenir la tecla premuda en qualsevol navegador és la següent:
function manejador(elEvento) { var evento = elEvento || window.event; var codigo = evento.charCode || evento.keyCode; var caracter = String.fromCharCode(codigo);} document.onkeypress = manejador;
Una de les propietats més interessants és la possibilitat d’impedir que es completi el comportament normal d’un esdeveniment.En altres paraules, amb JavaScript és possible no mostrar cap caràcter quan es prem una tecla, no enviar un formulari després de prémer el botó d’enviament, no carregar cap pàgina a l’prémer un enllaç, etc. El mètode avançat d’impedir que un esdeveniment executi la seva acció associada depèn de cada navegador:
// Navegadores que siguen los estandareselEvento.preventDefault();
En el model bàsic d’esdeveniments també és possible impedir el comportament per defecte d’alguns esdeveniments. Si per exemple en un element <textarea>
s’indica el següent gestor d’esdeveniments:
<textarea onkeypress="return false;"></textarea>
al <textarea>
anterior no és possible escriure cap caràcter, ja que el gestor d’esdeveniments retorna false
i aquest és el valor necessari per a impedir que s’acabi d’executar l’esdeveniment i per tant per evitar que la lletra s’escrigui.
Així, és possible definir controladors d’esdeveniments que tornin true
o false
en funció d’alguns paràmetres. Per exemple es pot dissenyar un limitador de el nombre de caràcters que es poden escriure en un <textarea>
:
function limita(maximoCaracteres) { var elemento = document.getElementById("texto"); if(elemento.value.length >= maximoCaracteres ) { return false; } else { return true; }}
<textarea onkeypress="return limita(100);"></textarea>
el funcionament de l’exemple anterior es detalla a continuació:
- s’utilitza l’esdeveniment
onkeypress
per controlar si la tecla s’escriu o no. - En el gestor de l’esdeveniment es torna el valor retornat per la funció externa
limita()
a la qual es passa com a paràmetre el valor100
. - Si el valor retornat per
limita()
éstrue
, l’esdeveniment es produeix de forma normal i el caràcter s’escriu al<textarea>
. Si el valor retornat perlimita()
ésfalse
, l’esdeveniment no es produeix i per tant el caràcter no s’escriu al<textarea>
. - La funció
limita()
retornatrue
ofalse
després de comprovar si el nombre de caràcters de l ‘<textarea>
és superior o inferior a l’màxim nombre de caràcters que se li ha passat com a paràmetre.
l’objecte event
també permet aturar completament l’execució de l’flux normal d’esdeveniments:
// Navegadores que siguen los estandareselEvento.stopPropagation();
A l’aturar el flux d’esdeveniments pendents, es invaliden i no s’executen els esdeveniments que resten des d’aquest moment fins que es recorren tots els elements pendents fins l’element window
.
15.5 Tipus d’esdeveniments
La llista completa d’esdeveniments que es poden generar en un navegador es pot dividir en quatre grans g rups. L’especificació de DOM defineix els següents grups:
- Esdeveniments de ratolí: s’originen quan l’usuari fa servir el ratolí per realitzar algunes accions.
- Esdeveniments de teclat: s’originen quan l’usuari prem sobre qualsevol tecla del teclat.
- Esdeveniments HTML: s’originen quan es produeixen canvis en la finestra de el navegador o quan es produeixen certes interaccions entre el client i el servidor.
- Esdeveniments DOM: s’originen quan es produeix un canvi en l’estructura DOM de la pàgina. També es denominen “esdeveniments de mutació”.
15.5.1 Esdeveniments de ratolí
Els esdeveniments de ratolí són, amb molta diferència, els més emprats en les aplicacions web . Els esdeveniments que s’inclouen en aquesta classificació són els següents:
Esdeveniment | Descripció |
---|---|
click |
es produeix quan es prem el botó esquerre de l’ratolí.També es produeix quan el focus de l’aplicació està situat en un botó i es prem la tecla ENTER |
dblclick |
es produeix quan es prem dues vegades el botó esquerre de l’ratolí |
mousedown |
es produeix quan es prem qualsevol botó de l’ratolí |
mouseout |
es produeix quan el punter de l’ratolí es troba a l’interior d’un element i l’usuari mou el punter a un lloc fora d’aquest element |
mouseover |
es produeix quan el punter de l’ratolí es troba fora d’un element i l’usuari mou el punter cap a un lloc a l’interior de l’element |
mouseup |
es produeix quan es deixa anar qualsevol botó de l’ratolí que hagi estat premut |
mousemove |
Es produeix (de forma contínua) quan el punter o de l’ratolí es troba sobre un element |
Tots els elements de les pàgines suporten els esdeveniments de la taula anterior.
15.5.1.1 propietats
l’objecte event conté les següents propietats per als esdeveniments de ratolí:
- les coordenades de l’ratolí (totes les coordenades diferents relatives als diferents elements)
- La propietat
type
- La propietat
srcElement
(Internet Explorer) otarget
(DOM) - Les propietats
shiftKey
,ctrlKey
,altKey
imetaKey
(només DOM) - la propietat
button
(només en els esdevenimentsmousedown
,mousemove
,mouseout
,mouseover
imouseup
)
Els esdeveniments mouseover
i mouseout
tenen propietats addicionals. Internet Explorer defineix la propietat fromElement
, que fa referència a l’element des del qual el punter de l’ratolí s’ha mogut i toElement
que és l’element a què el punter de l’ratolí s’ha mogut. D’aquesta manera, en l’esdeveniment mouseover
, la propietat toElement
és idèntica a srcElement
i en l’esdeveniment mouseout
, la propietat fromElement
és idèntica a srcElement
.
En els navegadors que suporten l’estàndard DOM, només hi ha una propietat denominada relatedTarget
. En l’esdeveniment mouseout
, relatedTarget
apunta l’element a què s’ha mogut el ratolí. En l’esdeveniment mouseover
, relatedTarget
apunta l’element des del qual s’ha mogut el punter de l’ratolí.
Quan es prem un botó de l’ratolí, la seqüència d’esdeveniments que es produeix és la següent: mousedown
, mouseup
, click
. Per tant, la seqüència d’esdeveniments necessària per arribar a l’doble clic arriba a ser tan complexa com la següent: mousedown
, mouseup
, click
, mousedown
, mouseup
, click
, dblclick
.
15.5.2 esdeveniments de teclat
els esdeveniments que s’inclouen en aquesta classificació són els següents:
Esdeveniment | Descripció |
---|---|
keydown |
Es produeix quan es prem qualsevol tecla del teclat. També es produeix de forma contínua si es manté premuda la tecla |
keypress |
Es produeix quan es prem una tecla corresponent a un caràcter alfanumèric (no es tenen en compte teles com SHIFT , ALT , etc.). També es produeix de forma contínua si es manté premuda la tecla |
keyup |
Es produeix quan es deixa anar qualsevol tecla premuda |
15.5.2.1 Propietats
L’objecte event conté les següents propietats per als esdeveniments de teclat:
- La propietat
keyCode
- La propietat
charCode
(només DOM) - La propietat
srcElement
(Internet Explorer) otarget
(DOM) - Les propietats
shiftKey
,ctrlKey
,altKey
imetaKey
(només DOM)
Quan es prem una tecla corresponent a un caràcter alfanumèric, es produeix la següent seqüència d’esdeveniments: keydown
, keypress
, keyup
. Quan es prem un altre tipus de tecla, es produeix la següent seqüència d’esdeveniments: keydown
, keyup
. Si es manté premuda la tecla, en el primer cas es repeteixen de forma contínua els esdeveniments keydown
i keypress
i en el segon cas, es repeteix l’esdeveniment keydown
de forma contínua.
15.5.3 esdeveniments HTML
Els esdeveniments HTML definits es recullen en la següent taula:
Esdeveniment | Descripció |
---|---|
load |
es produeix en l’objecte window quan la pàgina es carrega del tot. En l’element <img> cuando se carga por completo la imagen. En el elemento `quan es carrega l’objecte |
unload |
Es produeix en l’objecte window quan la pàgina desapareix per complet (a l’tancar la finestra de el navegador per exemple). En l’element <object> quan desapareix l’objecte. |
abort |
Es produeix en un element <object> quan l’usuari deté la descàrrega de l’element abans que hagi acabat |
error |
es produeix en l’objecte window quan es produeix un error de JavaScript. En l’element <img> quan la imatge no s’ha pogut carregar per complet i en l’element <object> quan l’element no es carrega correctament |
select |
es produeix quan es seleccionen diversos caràcters d’un quadre de text (<input> i <textarea> ) |
change |
Es produeix quan un quadre de text (<input> i <textarea> ) perd el focus i el seu contingut ha variat. També es produeix quan varia el valor d’un element <select> |
submit |
es produeix quan es prem sobre un botó de tipus submit (<input type="submit"> ) |
reset |
es produeix quan es prem sobre un botó de tipus reset (<input type="reset"> ) |
resize |
es produeix en l’objecte window quan es redimensiona la finestra de el navegador |
scroll |
Es produeix en qualsevol element que tingui una barra de desplaçament, quan l’usuari la fa servir. L’element <body> conté la barra de desplaçament de la pàgina completa |
focus |
Es produeix en qualsevol element (inclòs l’objecte finestra) quan l’element obté el focus |
blur |
Es produeix en qualsevol element (inclòs l’objecte finestra) quan l’element perd el focus |
Un dels esdeveniments més utilitzats és l’esdeveniment load
, ja que totes les manipulacions que es realitzen mitjançant DOM requereixen que la pàgina estigui carregada per complet i per tant, l’arbre DOM s’hagi construït completament.
l’element <body>
defineix les propietats scrollLeft
i scrollTop
que es poden emprar juntament amb l’esdeveniment scroll
.
15.5.4 Esdeveniments DOM
Tot i que els esdeveniments d’aquest tipus són part de la especificació oficial de DOM, encara no han estat implementats en tots els navegadors.La següent taula recull els esdeveniments més importants d’aquest tipus:
Esdeveniment | Descripció |
---|---|
DOMSubtreeModified |
es produeix quan s’afegeixen o eliminen nodes en el subarbre d’un document o element |
DOMNodeInserted |
es produeix quan s’afegeix un node com a fill d’un altre node |
DOMNodeRemoved |
es produeix quan s’elimina un node que és fill d’un altre node |
DOMNodeRemovedFromDocument |
es produeix quan s’elimina un node de el document |
DOMNodeInsertedIntoDocument |
es produeix quan s’afegeix un node a el document |
Exercici 17
Veure enunciat
Exercici 18
Veure enunciat
Exercici 19
Veure enunciat