NF1 - Esdeveniments i Validacio de formularis

De wikiserver
La revisió el 13:48, 8 des 2013 per Asalinas (Discussió | contribucions) (Es crea la pàgina amb «= Esdeveniments = Fins ara, totes les aplicacions i scripts que s'han creat tenen alguna cosa en comú: s'executen des de la primera instrucció fins a l'última de forma…».)
(dif) ← Versió més antiga | Versió actual (dif) | Versió més nova → (dif)
Dreceres ràpides: navegació, cerca

Esdeveniments

Fins ara, totes les aplicacions i scripts que s'han creat tenen alguna cosa en comú: s'executen des de la primera instrucció fins a l'última de forma seqüencial. Gràcies a les estructures de control de flux (if, for, while) és possible modificar lleugerament aquest comportament i repetir alguns trossos del script i saltar-se altres trossos en funció d'algunes condicions.

Aquest tipus d'aplicacions són poc útils, ja que no interactuen amb els usuaris i no poden respondre als diferents esdeveniments que es produeixen durant l'execució d'una aplicació. Afortunadament, les aplicacions web creades amb el llenguatge Javascript poden utilitzar el model de programació basada en esdeveniments.

En aquest tipus de programació, els scripts es dediquen a esperar al fet que l'usuari "faci alguna cosa" (que premi una tecla, que mogui el ratolí, que tanqui la finestra del navegador). A continuació, el script respon a l'acció de l'usuari normalment processant aquesta informació i generant un resultat.

Els esdeveniments fan possible que els usuaris transmetin informació als programes. Javascript defineix nombrosos esdeveniments que permeten una interacció completa entre l'usuari i les pàgines/aplicacions web. La pulsació d'una tecla constitueix un esdeveniment, així com punxar o moure el ratolí, seleccionar un element d'un formulari, redimensionar la finestra del navegador, etc.

Javascript permet assignar una funció a cadascun dels esdeveniments. D'aquesta forma, quan es produeix qualsevol esdeveniment, Javascript executa la seva funció associada. Aquest tipus de funcions es denominen "event handlers" en anglès i solen traduir-se per "manegadors d'esdeveniments".

Model bàsic d'esdeveniments

Tipus d'esdeveniments

En aquest model, cada element o etiqueta XHTML defineix la seva pròpia llista de possibles esdeveniments que se li poden assignar. Un mateix tipus d'esdeveniment (per exemple, clicar el botó esquerre del ratolí) pot estar definit per a diversos elements XHTML diferents i un mateix element XHTML pot tenir associats varis esdeveniments diferents.

El nom de cada esdeveniment 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í es denomina 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:

<thead> </thead> <tbody> </tbody>
Event Descripció Elements per els que está definit
onblur Deseleccionar l'element (el contrari de onfocus) <button>, <input>, <label>, <select>, <textarea>, <body>
onchange Succeeix quan el valor del element ha canviat <input>, <select>, <textarea>
onclick clicar i deixar anar el ratolí Tots els elements
ondblclick clicar dos vegades seguides amb el ratolí Tots els elements
onfocus Seleccionar un element <button>, <input>, <label>, <select>, <textarea>, <body>
onkeydown Prémer una tecla (sense 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 La pàgina s'ha carregat completament <body>
onmousedown Prémer (sense deixar anar) un botn del ratolí Tots els elements
onmousemove Moure el ratolí Tots els elements
onmouseout El ratolí "surt" de l'element (passa sobre un altre element) Tots els elements
onmouseover El ratoli "entra" dintre de l'elemento (passa per sobre de l'element) Tots els elements
onmouseup Deixar anar el botó que estava premut en el ratolí Tots els elements
onreset Inicialitzar el formulari (esborrar totes les dades) <form>
onresize S'ha modificat la mida de la finestra del navegador <body>
onselect Seleccionar un text <input>, <textarea>
onsubmit Enviar el formulari <form>
onunload S'abandona la pàgina (per exemple al tancar el navegador) <body>

Podeu veure tots el esdeveniments [aquí]

Manegadors d'esdeveniments

Un esdeveniment de Javascript per si mateix manca d'utilitat. Perquè els esdeveniments resultin útils, s'han d'associar funcions o codi Javascript a cada esdeveniment. D'aquesta forma, quan es produeix un esdeveniment s'executa el codi indicat, per la qual cosa 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 es denominen "manegador d'esdeveniments" i com Javascript és un llenguatge molt flexible, existeixen diverses formes diferents d'indicar els manegadors:

  • Manejadores com a atributs dels elements XHTML.
  • Manejadores com a funcions Javascript externes.
  • Manejadores "semàntics".

Manejadores d'esdeveniments com a atributs XHTML

Es tracta del 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 del propi element XHTML. En el següent exemple, es vol mostrar un missatge quan l'usuari cliqui amb el ratolí sobre un botó:

<input type="button" value="clica i veuràs" onclick="alert('Gràcies per clicar');" />

En aquest mètode, es defineixen atributs XHTML amb el mateix nom que els esdeveniments que es volen manejar. L'exemple anterior només vol controlar l'esdeveniment de clicar amb el ratolí, el nom del qual és onclick. Així, l'element XHTML pel 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 (alert('Gràcies per clicar');), ja que solament es tracta de mostrar un missatge.

En aquest altre exemple, quan l'usuari punxa sobre l'element
es mostra un missatge i quan l'usuari passa el ratolí per sobre de l'element, es mostra un altre missatge:
<div onclick="alert('Has clicat amb el ratolí');" onmouseover="alert('Acabes de passar el ratolí per damunt');">

Pots clicar sobre aquest element o simplement passar el ratolí per damunt. Aquest altre exemple inclou una de les instruccions més utilitzades en les aplicacions Javascript més antigues:

<body onload="alert("La pàgina s'ha carregat completament ");">
   ...
</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 veurem en el capítol de DOM, les funcions que permeten accedir i manipular els nodes de l'arbre DOM solament estan disponibles quan la pàgina s'ha carregat completament.

Manejadors d'esdeveniments i variable this

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 a exemples com el següent:

Quan l'usuari passa el ratolí per sobre de el
, el color de la vora es mostra de color negre. Quan el ratolí surt de el
, es torna a mostrar la vora amb el color gris clar original.
Element <div> original:

<div id="continguts" style="width:150px; height:60px; border:thin solid silver">
Secció de continguts...

Si no s'utilitza la variable this, el codi necessari per modificar el color de les vores, seria el següent:

<div id="continguts" style="width:150px; height:60px; border:thin solid silver" onmouseover="document.getElementById('continguts').style.borderColor='black';" onmouseout="document.getElementById('continguts').style.borderColor='silver';">
Secció de continguts...

El codi anterior és massa llarg i massa propens a cometre errors. Dins del 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 id="continguts" style="width:150px; height:60px; border:thin solid silver" onmouseover="this.style.borderColor='black';" onmouseout="this.style.borderColor='silver';">
Secció de continguts...

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 el < div >.

Manegadors d'esdeveniments com a funcions externes

La definició dels manegadores d'esdeveniments en els atributs XHTML és el mètode més senzill però menys aconsellable de tractar amb els esdeveniments en Javascript. El principal inconvenient és que es complica a l'excés quan s'afegeixen algunes poques instruccions, per la qual cosa solament és recomanable per als casos més senzills.

Si es realitzen aplicacions complexes, com per exemple la validació d'un formulari, és aconsellable agrupar tot el codi Javascript en una funció externa i cridar a aquesta funció des de l'element XHTML.

Seguint amb l'exemple anterior que mostra un missatge en clicar sobre un botó:

<input type="button" value="Clica i veuràs" onclick="alert('Gràcies per clicar');" />

Utilitzant funcions externes es pot transformar en:

function mostraMissatge() {
  alert('Gràcies per clicar');
}

<input type="button" value="Clica i veuràs" onclick="mostraMissatge()" />

Aquesta tècnica consisteix a extreure totes les instruccions de Javascript i agrupar-les en una funció externa. Una vegada definida la funció, en l'atribut de l'element XHTML s'inclou el nom de la funció, per indicar que és la funció que s'executa quan es produeix l'esdeveniment.

La crida a la funció es realitza de la forma habitual, indicant el seu nom seguit dels parèntesis i de forma opcional, incloent tots els arguments i paràmetres que es necessitin.

El principal inconvenient d'aquest mètode és que en les funcions externes no es pot seguir utilitzant la variable this i per tant, és necessari passar aquesta variable com a paràmetre a la funció:

function ressalta(element) {
	switch(element.style.borderColor) {
		case 'silver':
		case 'silver silver silver silver':
		case '#c0c0c0':
			element.style.borderColor = 'black';
			break;
		case 'black':
		case 'black black black black':
		case '#000000':
			element.style.borderColor = 'silver';
			break;
	}
}

<div style="width:150px; height:60px; border:thin solid silver" onmouseover="ressalta(this)" onmouseout="ressalta(this)">
Secció de continguts...

En l'exemple anterior, la funció externa és cridada amb el paràmetre this, que dins de la funció es denomina element. La complexitat de l'exemple es produeix sobretot per la forma en la qual els diferents navegadors emmagatzemen el valor de la propietat * borderColor.

Mentre que Firefox emmagatzema (en cas que les quatre vores coincideixin en color) el valor black, Internet Explorer ho emmagatzema com black black black black i Opera emmagatzema la seva representació hexadecimal #000000.

Manejadores d'esdeveniments semàntics

Els mètodes que s'han vist per afegir manejadores d'esdeveniments (com a atributs XHTML i com a funcions externes) tenen un greu inconvenient: "embruten" el codi XHTML de la pàgina.

Com és conegut, una de les bones pràctiques bàsiques en el disseny de pàgines i aplicacions web és la separació dels continguts (XHTML) i el seu aspecte o presentació (CSS). Sempre que sigui possible, també es recomana separar els continguts (XHTML) i el seu comportament o programació (Javascript).

Barrejar el codi Javascript amb els elements XHTML solament contribueix a complicar el codi font de la pàgina, a dificultar la modificació i manteniment de la pàgina i a reduir la semàntica del document final produït.

Afortunadament, existeix un mètode alternatiu per definir els manegadores d'esdeveniments de Javascript. Aquesta tècnica és una evolució del mètode de les funcions externes, ja que es basa a utilitzar les propietats DOM dels elements XHTML per assignar totes les funcions externes que actuen de manejadores d'esdeveniments. Així, el següent exemple:

<input id="clica" type="button" value="Clica i veuràs" onclick="alert('Gràcies per clicar');" />

Es pot transformar en:

// Funció externa
function mostraMissatge() {
alert('Gràcies per clicar');
}

// Assignar la funció externa a l'element
document.getElementById("clica").onclick = mostraMissatge;

// Element XHTML
<input id="clica" type="button" value="Clica i veuràs" />

La tècnica dels manegadores semàntics consisteix en:

  • Assignar un identificador únic a l'element XHTML mitjançant l'atribut id.
  • Crear una funció de Javascript encarregada de manejar l'esdeveniment.
  • Assignar la funció externa a l'esdeveniment corresponent en l'element desitjat.
  • L'últim pas és la clau d'aquesta tècnica. En primer lloc, s'obté l'element al que es desitja associar la funció externa:
document.getElementById("clica");

A continuació, s'utilitza una propietat de l'element amb el mateix nom que l'esdeveniment que es vol manejar. En aquest cas, la propietat és onclick:

document.getElementById("clica").onclick = ...

Finalment, s'assigna la funció externa mitjançant el seu nom sense parèntesi. El més important (i la causa més comuna d'errors) és indicar solament el nom de la funció, és a dir, prescindir dels parèntesis en assignar la funció:

document.getElementById("clica").onclick = mostraMissatge;

Si s'afegeixen els parèntesis després del nom de la funció, en realitat s'està executant la funció i guardant el valor retornat per la funció en la propietat onclick d'element.

// Assignar una funció externa a un esdeveniment d'un element
document.getElementById("clica").onclick = mostraMissatge;

// Executar una funció i guardar el seu resultat en una propietat d'un element
document.getElementById("clica").onclick = mostraMissatge();

El gran avantatge d'aquest mètode és que el codi XHTML resultant és molt "net", ja que no es barreja amb el codi Javascript. A més, dins de les funcions externes assignades sí que es pot utilitzar la variable this per referir-se a l'element que provoca l'esdeveniment.

L'únic inconvenient d'aquest mètode és que la pàgina s'ha de carregar completament abans que es puguin utilitzar les funcions DOM que assignen els manegadors als elements XHTML. Una de les formes més senzilles d'assegurar que cert codi es va a executar després que la pàgina es carregui per complet és utilitzar l'esdeveniment onload:

window.onload = function() {
document.getElementById("clica").onclick = muestraMensaje;
}

En el següent exemple, s'afegeixen esdeveniments als elements de tipus input=text d'un formulari complex:

function ressalta() {
	// Codi Javascript
}

window.onload = function() {
  var formulario = document.getElementById("formulario");
  var camposInput = formulario.getElementsByTagName("input");
 
  for(var i=0; i<camposInput.length; i++) {
    if(camposInput[i].type == "text") {
      camposInput[i].onclick = resalta;
    }
  }
}

Exercicis

Donada la següent pàgina

<script type="text/javascript">
	function muestraOculta() {
	}
</script>
</head>

<body>

<p id="contenidos_1">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed mattis enim vitae orci. Phasellus libero. Maecenas nisl arcu, consequat congue, commodo nec, commodo ultricies, turpis. Quisque sapien nunc, posuere vitae, rutrum et, luctus at, pede. Pellentesque massa ante, ornare id, aliquam vitae, ultrices porttitor, pede. Nullam sit amet nisl elementum elit convallis malesuada. Phasellus magna sem, semper quis, faucibus ut, rhoncus non, mi. Duis pellentesque, felis eu adipiscing ullamcorper, odio urna consequat arcu, at posuere ante quam non dolor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis scelerisque.</p>
<a id="enlace_1" href="#">Ocultar contenidos</a>

<br/>

<p id="contenidos_2">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed mattis enim vitae orci. Phasellus libero. Maecenas nisl arcu, consequat congue, commodo nec, commodo ultricies, turpis. Quisque sapien nunc, posuere vitae, rutrum et, luctus at, pede. Pellentesque massa ante, ornare id, aliquam vitae, ultrices porttitor, pede. Nullam sit amet nisl elementum elit convallis malesuada. Phasellus magna sem, semper quis, faucibus ut, rhoncus non, mi. Duis pellentesque, felis eu adipiscing ullamcorper, odio urna consequat arcu, at posuere ante quam non dolor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis scelerisque.</p>
<a id="enlace_2" href="#">Ocultar contenidos</a>

<br/>

<p id="contenidos_3">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed mattis enim vitae orci. Phasellus libero. Maecenas nisl arcu, consequat congue, commodo nec, commodo ultricies, turpis. Quisque sapien nunc, posuere vitae, rutrum et, luctus at, pede. Pellentesque massa ante, ornare id, aliquam vitae, ultrices porttitor, pede. Nullam sit amet nisl elementum elit convallis malesuada. Phasellus magna sem, semper quis, faucibus ut, rhoncus non, mi. Duis pellentesque, felis eu adipiscing ullamcorper, odio urna consequat arcu, at posuere ante quam non dolor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis scelerisque.</p>
<a id="enlace_3" href="#">Ocultar contenidos</a>

</body>

Realitza els següents apartats:

  • Quan es cliqui sobre el primer enllaç, s'oculti la seva secció relacionada
  • Quan es torni a clicar sobre el mateix enllaç, es mostri una altra vegada aquesta secció de continguts
  • Completar la resta d'enllaços de la pàgina perquè el seu comportament sigui idèntic al del primer enllaç
  • Quan una secció s'oculti, ha de canviar el missatge de l'enllaç associat (pista: propietat innerHTML)