NF1 - Esdeveniments i Validacio de formularis

De wikiserver
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:

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í]

Gestor 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".

Gestor 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');">Ratolí</div>

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.

Gestor 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 >.

Gestor 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.

Gestor 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;
}

Gestor d'esdeveniments amb DOM

El mètode addEventListener ens permet incloure un gestor d'esdeveniment. La sintaxi de addEventListener és la següent:

element_que_escolta.addEventListener('event',funció_a_llançar, booleà);

element_que_escolta - és qualsevol element present en un document al qual es vol associar l'esdeveniment.

esdeveniment - és el succés ocorregut sobre l'element (clic, load, ...).

funció_a_llançar - és qualsevol funció definida que vulguem que s'executi quan passi l'esdeveniment.

booleà - és un valor que defineix l'ordre del flux d'esdeveniments.


Si es vol escoltar un esdeveniment només una vegada i després eliminar-ho s'ha d'utilitzar el mètode removeEventListener:

element_que_escolta.removeEventListener ('esdeveniment',funció_a_llançar, booleà);


NOTA 1: Explicació del paràmetre booleà del mètode addEventListener amb un exemple. Suposem que tenim això:

<html onclick="processaEvent()">
  <head><title>Exemple de fluix events</title></head>
  <body onclick="processaEvent()">
    <div onclick="processaEvent()">Clica aqui</div>
  </body>
</html>


Quan fem clic al div no només ho estem fent sobre ell, sinó sobre els elements que el contenen en l'arbre del DOM, és a dir, hem fet clic a més sobre l'element html i sobre l'element body. Sí només hi ha una funció assignada a una escolta per al div no hi ha major problema, però si a més hi ha una per al html i una altra per al body, quin és l'ordre en què s'han de llançar les tres funcions?


Per contestar a aquesta pregunta hi ha un model de comportament, el flux d'esdeveniments (anglès). Segons aquest, quan es fa clic sobre un element, l'esdeveniment es propaga en dues fases, una que és la captura -el esdeveniment comença en el nivell superior del document i recorre els elements de pares a fills- i l'altra la bombolla -el ordre invers, ascendint de fills a pares-.


Un cop vist això, podem comprendre el tercer paràmetre de addEventListener, que el que fa és permetre'ns escollir l'ordre de propagació:

true: El flux d'esdeveniments és com el representat, i la fase de captura passa en llançar l'esdeveniment. L'ordre de propagació per l'exemple seria, per tant, l'indicat, html-body-div.

false: Permet saltar la fase de captura, i la propagació seguiria només la bombolla. Així, l'ordre seria div-body-html.


NOTA 2: A internet explorer no funciona en les versions anteriors a la 7 (inclosa).


<script type="text/javascript">
        function alerta(){
            alert(this);
        }

        window.onload = function (){
            var elBody = document.getElementsByTagName('body')[0];
            var elDiv = document.getElementById('elDiv');
            var elButton = document.getElementById('elButton');
         
            elBody.addEventListener('click',alerta,false);
            elDiv.addEventListener('click',alerta,false);
            elButton.addEventListener('click',alerta,false);
        }


//event.stopPropagation();   //evita propagarse el evento en forma de burbuja
    </script>
<body id="body">
    <div id="elDiv">Clica aqui
          <button id="elButton">boton</button>
     </div>
</body>


Exemple d'utilització manejadores d'esdeveniments amb DOM:

function muestraMensaje() {
  				console.log("Has pulsado el ratón");
  				elDiv.removeEventListener("click", muestraMensaje, false);  // borra el evento asociado de tipo click a ese elemento.
			}
 
			var elDiv = document.getElementById("div_principal");
			elDiv.addEventListener("click", muestraMensaje, false);



En el caso que no queramos que se aplique el evento de tipo de Submit o Hipervínculo "<a></a>" al ser botón usaremos "e.preventDefault()" y realizará las acciones que tengamos establecidas

window.addEventListener("load",ejemplo); // window.onload= ejemplo;

	function ejemplo(){
			function muestraMensaje(e) {
  				console.log("Has pulsado el ratón");
                                e.preventDefault();  //evita que se ejecute el submit y recargue la página
			}
         document.getElementById("boton").addEventListener("click", muestraMensaje, false);
	}      

</script>

<form action="./index.html" method="post">
	<input type="submit" id="boton" name="boton" value="boton">
</form>


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

<form id="formulario" action="">
    <input type="text" placeholder="hola">
    <input type="text" placeholder="holaa">
</form>
<script type="text/javascript">
    function resalta() {
        console.log("holaa")
    }

    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;
            }
        }
    }
    
</script>

Exercicis

Mostrar / Ocultar text

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)
Exercici 4 Events

Obtenint informació de l'esdeveniment (objecte event)

Normalment, els manegadors d'esdeveniments requereixen informació addicional per processar les seves tasques. Si una funció per exemple s'encarrega de processar l'esdeveniment onclick, potser necessiti saber que posició estava el ratolí en el moment de punxar el botó.

No obstant això, el cas més habitual en el qual és necessari conèixer informació addicional sobre l'esdeveniment és el dels esdeveniments associats al teclat. Normalment, és molt important conèixer la tecla que s'ha premut, per exemple per diferenciar les tecles normals de les tecles especials (ENTER, tabulador, Alt, Ctrl., etc.).

Javascript permet obtenir informació sobre el ratolí i el teclat mitjançant un objecte especial anomenat event. Desafortunadament, els diferents navegadors presenten diferències molt notables en el tractament de la informació sobre els esdeveniments.

La principal diferència resideix en la forma en la qual s'obté l'objecte event. Internet Explorer considera que aquest objecte forma part de l'objecte window i la resta de navegadors ho consideren com l'únic argument que tenen les funcions manejadoras d'esdeveniments.

Encara que és un comportament que resulta molt estrany al principi, tots els navegadors moderns excepte Internet Explorer creen màgicament i de forma automàtica un argument que es passa a la funció manegadora, per la qual cosa no és necessari incloure-ho en la trucada a la funció manegadora. D'aquesta forma, per utilitzar aquest "argument màgic", només és necessari assignar-li un nom, ja que els navegadors ho creen automàticament.

En resum, en els navegadors tipus Internet Explorer, l'objecte event s'obté directament mitjançant:

var esdeveniment = window.event;
D'altra banda, en la resta de navegadors, l'objecte event s'obté màgicament a partir de l'argument que el navegador crea automàticament:

function manejadorEventos(elEvento) {
var esdeveniment = elEvento;
}

Si es vol programar una aplicació que funcioni correctament en tots els navegadors, és necessari obtenir l'objecte event de forma correcta segons cada navegador. El següent codi mostra la forma correcta d'obtenir l'objecte event en qualsevol navegador:

function manejadorEventos(elEvento) {
var esdeveniment = elEvento || window.event;
}

Una vegada obtingut l'objecte event, ja es pot accedir a tota la informació relacionada amb l'esdeveniment, que depèn del tipus d'esdeveniment produït.

Informació sobre l'esdeveniment

La propietat type indica el tipus d'esdeveniment produït, la qual cosa és útil quan una mateixa funció s'utilitza per manejar diversos esdeveniments:

var tipus = esdeveniment.type;

La propietat type retorna el tipus d'esdeveniment produït, que és igual al nom de l'esdeveniment però sense el prefix on.

Mitjançant aquesta propietat, es pot refer de forma més senzilla l'exemple anterior en el qual es ressaltava una secció de continguts en passar el ratolí per damunt:

function ressalta(elEvento) {
    var esdeveniment = elEvento || window.event;
    switch(esdeveniment.type) {
         case 'mouseover':
               this.style.borderColor = 'black';
               break;
         case 'mouseout':
               this.style.borderColor = 'silver';
               break;
    }
}

window.onload = function() {
       document.getElementById("seccion").onmouseover = ressalta;
       document.getElementById("seccion").onmouseout = ressalta;
}
<div id="seccion" style="width:150px; height:60px; border:thin solid silver">
  Secció de continguts...
</div>

Informació sobre els esdeveniments de teclat

De tots els esdeveniments disponibles en Javascript, els esdeveniments relacionats amb el teclat són els més incompatibles entre diferents navegadors i per tant, els més difícils de manegar. En primer lloc, existeixen moltes diferències entre els navegadors, els teclats i els sistemes operatius dels usuaris, principalment a causa de les diferències entre idiomes.

A més, existeixen tres esdeveniments diferents per a les pulsacions de les tecles (onkeyup, onkeypress i onkeydown). Finalment, existeixen dos tipus de tecles: les tecles normals (com a lletres, nombres i símbols normals) i les tecles especials (com ENTER, Alt, Shift, etc.)

Quan un usuari prem una tecla normal, es produeixen tres esdeveniments seguits i en aquest ordre:

  • onkeydown,
  • onkeypress i
  • onkeyup.

L'esdeveniment onkeydown es correspon amb el fet de prémer una tecla i no deixar-la anar; l'esdeveniment onkeypress és la pròpia pulsació de la tecla i l'esdeveniment onkeyup fa referència al fet de deixar anar una tecla que estava premuda.

La forma més senzilla d'obtenir la informació sobre la tecla que s'ha premut és mitjançant l'esdeveniment onkeypress. La informació que proporcionen els esdeveniments onkeydown i onkeyup es pot considerar com més tècnica, ja que retornen el codi intern de cada tecla i no el caràcter que s'ha premut.

A continuació s'inclou una llista amb totes les propietats diferents de tots els esdeveniments de teclat tant en Internet Explorer com en la resta de navegadors:

  • Esdeveniment keydown:
    • Mateix comportament en tots els navegadors:
      • Propietat keyCode: codi intern de la tecla
      • Propietat charCode: no definit
  • Esdeveniment keypress:
    • Internet Explorer:
      • Propietat keyCode: el codi del caràcter de la tecla que s'ha premut
      • Propietat charCode: no definit
    • Resta de navegadors:
    • Propietat keyCode: per a les tecles normals, no definit. Per a les tecles especials, el codi intern de la tecla.
    • Propietat charCode: per a les tecles normals, el codi del caràcter de la tecla que s'ha premut. Per a les tecles especials, 0.
  • Esdeveniment keyup:
    • Mateix comportament en tots els navegadors:
      • Propietat keyCode: codi intern de la tecla
      • Propietat charCode: no definit

Per convertir el codi d'un caràcter (no confondre amb el codi intern) al caràcter que representa la tecla que s'ha premut, s'utilitza la funció String.fromCharCode().

<script type="text/javascript">

    window.onkeydown = teclado;
    window.onkeypress = teclado;
    window.onkeyup = teclado;

    function teclado(magica) {
        var e = magica || window.event; // para salvar las deficiencias de IE=window.event
        mostrar(e.type, e.keyCode, e.which, e.charCode, e.key);
        
    }

    function mostrar(evento, keyCode, which, charCode, key) {
      
        let cadena =  "<b> Evento: </b>" + evento 
                     + " ==> <b> keyCode: </b>" + keyCode 
                     + "<b> which: </b>" + which 
                     + "<b> charCode: </b>"+ charCode 
                     + "<b> key: </b>"+ key 
                     + "<b> FromCharCode: </b>"+String.fromCharCode(charCode)+"<br>"

         let info = document.getElementById("info"); //display
         info.innerHTML += cadena
   }

</script>
</head>
<body>
<div id="info"></div>
</body>
</html>


https://sospedia.net/pinchar-el-teclado-en-javascript/

https://www.w3.org/2002/09/tests/keys-cancel2.html

Exercici Teclat

Crea un script que mostri per pantalla la següent informació cada vedada que es premi una tecla:

  • Caràcter permut (amb key i StringCharCode)
  • Tipus event (keydown, keypress, keyup)
  • Propietat keycode
  • Propietat charcode


informació sobre els esdeveniments de ratolí

La informació més rellevant sobre els esdeveniments relacionats amb el ratolí és la de les coordenades de la posició del punter del ratolí. Encara que l'origen de les coordenades sempre es troba en la cantonada superior esquerra, el punt que es pren com a referència de les coordenades pot variar.

D'aquesta forma, és possible obtenir la posició del ratolí respecte de la pantalla de l'ordinador, respecte de la finestra del navegador i respecte de la pròpia pàgina HTML (que s'utilitza quan l'usuari ha fet scroll sobre la pàgina). Les coordenades més senzilles són les que es refereixen a la posició del punter respecte de la finestra del navegador, que s'obtenen mitjançant les propietats clientX i clientY:

function muestraInformacion(elEvento) {
   var esdeveniment = elEvento || window.event;
   var coordenadaX = esdeveniment.clientX;
   var coordenadaY = esdeveniment.clientY;
   alert("Has premut el ratolí en la posició: " + coordenadaX + ", " + coordenadaY);
}

document.onclick = muestraInformacion;
//document.addeventlistener(click,"muestraInformacion",false);

Les coordenades de la posició del punter del ratolí respecte de la pantalla completa de l'ordinador de l'usuari s'obtenen de la mateixa forma, mitjançant les propietats screenX i screenY:

var coordenadaX = esdeveniment.screenX;
var coordenadaY = esdeveniment.screenY;

En moltes ocasions, és necessari obtenir un altre parell de coordenades diferents: les que corresponen a la posició del ratolí respecte de l'origen de la pàgina. Aquestes coordenades no sempre coincideixen amb les coordenades respecte de l'origen de la finestra del navegador, ja que l'usuari pot fer scroll sobre la pàgina web. Internet Explorer no proporciona aquestes coordenades de forma directa, mentre que la resta de navegadors sí que ho fan. D'aquesta forma, és necessari detectar si el navegador és de tipus Internet Explorer i en cas afirmatiu realitzar un càlcul senzill:

// Detectar si el navegador és Internet Explorer
var ie = navigator.userAgent.toLowerCase().indexOf('msie')!=-1;

if(ie) {
     coordenadaX = esdeveniment.clientX + document.body.scrollLeft;
     coordenadaY = esdeveniment.clientY + document.body.scrollTop;
}
else {
     coordenadaX = esdeveniment.pageX;
     coordenadaY = esdeveniment.pageY;
}

alert("Has premut el ratolí en la posició: " + coordenadaX + ", " + coordenadaY + " respecte de la pàgina web");

La variable ie val true si el navegador en el qual s'executa el script és de tipus Internet Explorer (qualsevol versió) i val false en un altre cas. Per a la resta de navegadors, les coordenades respecte de l'origen de la pàgina s'obtenen mitjançant les propietats pageX i pageY. En el cas d'Internet Explorer, s'obtenen sumant la posició respecte de la finestra del navegador (clientX, clientY) i el desplaçament que ha sofert la pàgina (document.bodi.scrollLeft, document.bodi.scrollTop).


Client page screen.jpg


Gràfics senzills amb canvas

Amb els esdeveniments de teclat i ratolí podrem programar jocs senzills. Només ens caldrà saber com situar i moure gràfics per la pantalla. Amb aquesta finalitat ens serà d'ajuda l'ús de l'element canvas de HTML.

Al següent exemple definim un canvas (llenç) de 800x600 píxels i hi situem la imatge d'un cotxe a la coordenada (400,300).

<canvas id="myCanvas" width="800" height="600" style="background-color: lightskyblue;"></canvas>

<img id="cotxe" src="cotxe.jpg" style="display: none;" >

<script type="text/javascript">

var canvas;
var ctx;
var imatge;

window.onload = function() {
         canvas= document.getElementById("myCanvas");
         ctx = canvas.getContext("2d");
         imatge=document.getElementById("cotxe");

        ctx.drawImage(imatge,400,300);
}
</script>

Si volem simular el moviment de la imatge haurem l'haurem d'esborrar de la posició antiga i tornar-la a dibuixar a la nova posició. Per borrar la imatge podem dibuixar un rectangle del color de fons del canvas sobre la imatge amb les instruccions:

ctx.fillStyle = "lightskyblue"
ctx.fillRect(0,300,100,66);

A l'exemple dibuixem al canvas un triangle de color lightskyblue a la coordenada (0,300) i de dimensions 100x66.

Exercicis

Estrella Michelin

Un restaurant té 4 tapes principals on cadascuna té un preu 1 €, 2 €, 3 € i 4 € (esquerra a dreta).

Com el local és petit, es disposa de dos cambrers, cadascun d'ells té un botó que l'executarà en el cas de servir una tapa. Quan un cambrer serveixi una tapa haurà:

  • 1. Primer seleccionar-se amb el botó
  • 2. Clicar a la tapa o tapes servides.

Cada vegada que el cambrer faci click a una tapa el seu preu s'incrementarà en la recaudació del cambrer.


Michelin.png

Expressions Regulars

Les expressions regulars son una necessitat a l'hora de validar formularis. Alguns problemes de validació no es podrien solucionar de una manera elegant sense elles. Les expressions regulars son senzillament una manera d'expresar un patró per a cadenes coincidents de text. La expressions contenen termes i operadors que ens pemeten definir els patrons.

Creació d'expresions regulars

A Javascript, com succeeix amb la majoria d'objectes, existeixen dos formes de crear expresions regulars:

  • mitjançant un literal
  • creant una instància d'un objecte de tipus RegExp

La creació d'una expressió regular amb un literal és molt sezill. Veïem un exemple. Volem crear una expressió regular que coincideixi exactament amb el string "test":

var pattern = /test/;

Les expresions regulars van envoltades del caràctes /. Igual que els String van envoltades del caràcter ".

També podíem haver creat una instància del objecte RegExp de la següent manera:

var pattern = new RegExp("test");

Modificadors a utilitzar a l'hora de crear expressions regulars

A més a més de la pròpia expressió regular, podem introduïr els següents modificadors:

Exemple d'ús:

var pattern = /test/ig
var pattern2 = new RegExp("test","ig");
//exemple d'us de la expressió regular
alert(pattern.test("test"));
alert(pattern2.test("test"));

Termes i Operadors

  • Coincidència exacta: Tot lo que no sigui un caràcter especial o un operador haurà d'apareixer de forma literal en la expressió. Ex: /test/ la paraula 'test ha d'aparèixer exactament.
  • Combinacions de caràcters: Moltes vegades no volem combinar un caràcter literal específic, sino un grup finit de caràcters. Podem especificar-ho col·locant el grup de caràcters que volem combinar entre claudàtors. Ex: [abc]
  • Combinacions de caràcters excloents: Altres vegades volem combinar tots els caràcters trets d'uns quants. Per fer-ho podem utilitzar el símbol ^ seguit dels caràcters que no volem en la expresió. Ex: [^abc].
  • Rang de valors: També tenim la habilitat d'especificar un rang de valors. Ex: volem qualsevol caràcter entre a i m minmúscula --> [a-m] (ambdós incloses).

Caràcters especials

Existeixen caràcters especials en les expresions regulars, de fet, ja hem vist uns quants: [, ], - i ^. Però encara hi ha uns quants més com serien el $, {, }, ?, ,, + i el . Com podem fer per utilitzar-los de forma literal en comptes d'utilitzar-los com a operadors de les expressions regulars? Escapant-los. Però com? Utilitzant un caràcter especial: \. Ex: La expressió regular /\[/ significa el caràcter [ i no l'inici d'un grup de caràcters. Així mateix, per poder utilitzar el caràcter \ dintre de la expressió regular l'haurem d'escapar. Ex: \\ correspon al literal \.

Principis i finals

A vegades volem que un patró coincideixi amb el principi d'una cadena o amb el final.

  • Principi: Utilitzarem el caràcter ^. Ex: /^test/ : només coincideix si la cadena test coincideix amb el principi.
  • Final: Utilitzarem el caràcter $. Ex: /test$/ : només coincideix si la cadena test coincideix amb el final.
  • Principi i final: Ex: /^test$/ : Indica que el patró especificat ha d'incluir tota la cadena candidata.

Repetició de caràcters

Si volem combinar una serie de quatre caràcters 'a' podem expressar-ho amb /aaa/ però que succeeix si volem utilitzar un número qualsevol de repeticions del mateix caràcter? Tenim diferents opcions:

  • Podem especificar que un caràcter és opcional, es a dir, pot aparèixer alguna vegada o cap (0 ó 1), Es fa afegint el caràcter ? al final. Exemple: /t?est/. Aquest patró combina dues opcions: test i est.
  • Si volem que un caràcter apareixi moltes vegades (1 o més) utilitzarem +. Ex: /t+est/. Aquest patró combina test, ttest i tttest però no est.
  • Si volem que un caràcter apareixi zero o més vegades (0 o més) utilitzem el caràcter *. Ex: /t*est/. Aquest patró combina test, ttest, tttest i també est.
  • Podem especificar una quantitat concreta amb el número de repeticions permeses entre claudàtors {}Text en negreta. Per exemple, /a{4}/ indica una coincidència de quatre caràcters 'a' consecutius.
  • També podem especificar un intérval per al compte de repeticions. Per exemple, /a{4,10}/ indica una combinació de 4 a 10 caracters 'a' consecutius.
  • Si en aquest interval no s'indica el segon valor de l'intèrval indiquem que el número final és infinit. Ex: /a{4,}/. Aquest patró combina qualsevol cadena de cuatre o més caràcters 'a' consecutius. Fixat que és important posar la coma després del 4.

Caràcters predefinits

La sintaxis de les expressions regulars ens proporcionen un nombre de termes predefinits que representen caràcters o clases de caràcters que s'utilitzen amb freqüència. Taula:

Terme Predefinit Equivalència
\t Tabulació horitzontal
\b Retrocés
\v Tabulació Vertical
\f Salt de página
\r Retorn de carro.
\n Nova linia
\cA : \cZ Caràcters de control
\x0000 : \xFFFF Unicode Hexadecimal
\x00 : \xFF ASCII Hexadecimal
. Qualsevol caràcter, excepte nova linia
\d Qualsevol dígit decimal. Equivalent a [0-9]
\D Qualsevol caràcter menys un dígit decimal. Equivalent a [^0-9]
\w Qualsevol caràcter alfanuméric incloent el subratllat. [A-Za-z0-9_]
\W Qualsevol caràcter menys els alfanumèric i el subratllat. [^A-Za-z0-9_]
\s Qualsevol espai en blanc (espai, tabulador, salt de pàgina,etc.)
\S Qualsevol caràcter menys un espai en blanc.

Per veure el llistat complert fes click aquí.

Agrupació de caràcters

De moment, hem observat que els operadors + i * només afecten al terme que els precedeix. Si volem aplicar-los a un grup de termes, podem utilitzar parèntesis, igual que si es tractés d'una formula matemàtica. Per exemple: /(ab)+/. Aquest patró combina una o més aparicions de la cadena ab.

Alternància de caràcters

La alternància pot expressar-se utilitzant el caràcter |. Per exemple: /a|b/ combina el caràcter a o b, i /(ab)+|(cd)+/ combina només una o més repeticions de ab o cd.

Mètodes de les Expressions Regulars

  • pattern.test(cadena) : Executa la expressió regular e indica si la cadena passada per paràmetre coincideix o no. (retorna True o False)
  • pattern.exec(cadena) : Executa la expressió regular i retorna la primera coincidència.

Resum Expressions Regulars

Expresiones.jpg Resum Expressions Regulars

Exercicis

Comprovar expressions regulars

Comprovar expressions regulars II

Crea un patró per a cadascuna de les diferents cadenes que es mostren a continuació:

  • Codi postal. Ex: 46700
  • Numero de telèfon amb prefix i guións, el primer nombre pot ser un 8 ó 9. Ex: 93-123-11-33
  • Numero de telèfon amb prefix i punts. Ex: 93-1.231.1339
  • Numero de telèfon internacional. Ex: (+34)952356817
  • Nom d'usuari amb un mínim de 4 i un màxim de 15. Ex: julio_30
  • Nombre Real. Ex: -122.33 ó 7,3 ó 8
  • Numero ISBN de 13 dígits: 978-3-16-148410-0
  • Numero de la seguretat social: 01-123456789
  • Adreça Postal amb les següent condicions: Carrer (C\), Plaza(Pz.), Avinguda(Av.). Direcció. Numero - Porta.

Ex: C\ Mare de Deu de montserrat. 233 - 2

  • Numero IP d'un ordinador de la versió 4.
  • Numero Mac d'un ordinador separats per ':'
  • URL (amb http, https, www, etc)
  • Data: Ex: DD/MM/AAAA
  • Hora: 23:55:55
  • Email
  • Comprobar un nombre propio
  • Targeta de crèdit



Formularis

JavaScript disposa de nombroses propietats i funcions que faciliten la programació d'aplicacions que manegen formularis. En primer lloc, quan es carrega una pàgina web, el navegador crea automàticament una matriu anomenat forms i que conté la referència a tots els formularis de la pàgina.

Per accedir al array forms , s'utilitza l'objecte document , de manera que document.forms és la matriu que conté tots els formularis de la pàgina. Com es tracta d'un array, l'accés a cada formulari es realitza amb la mateixa sintaxi dels arrays. La següent instrucció accedeix al primer formulari de la pàgina:

document. forms [0];

A més de l'array de formularis, el navegador crea automàticament una matriu anomenat elements per cadascun dels formularis de la pàgina. Cada array elements conté la referència a tots els elements (quadres de text, botons, llistes desplegables, etc.) d'aquest formulari. Utilitzant la sintaxi dels arrays, la següent instrucció obté el primer element del primer formulari de la pàgina:

document. forms [0]. elements [0];

La sintaxi dels arrays no sempre és tan concisa. El següent exemple mostra com obtenir directament l'últim element del primer formulari de la pàgina:

document. forms [0]. elements [document. forms [0]. elements. length - 1];

Encara que aquesta forma d'accedir als formularis és ràpida i senzilla, té un inconvenient molt greu. Què passa si canvia el disseny de la pàgina i en el codi HTML es canvia l'ordre dels formularis originals o s'afegeixen nous formularis? El problema és que "el primer formulari de la pàgina" ara podria ser un altre formulari diferent al que espera l'aplicació.

En un entorn tan canviant com el disseny web, és molt difícil confiar que l'ordre dels formularis es mantingui estable en una pàgina web. Per aquest motiu, sempre s'hauria d'evitar l'accés als formularis d'una pàgina mitjançant l'array document.forms.

Una forma d'evitar els problemes del mètode anterior consisteix a accedir als formularis d'una pàgina a través del seu nom (atribut name) o a través del seu atribut id . L'objecte document permet accedir directament a qualsevol formulari mitjançant la seva atribut name:

var formularioPrincipal = document. formulari;
 var formularioSecundario = document. otro_formulario;

 <Form name = "formulari">
   ...
 </ Form>

 <Form name = "otro_formulario">
   ...
 </ Form>

Accedint d'aquesta forma als formularis de la pàgina, l'script funciona correctament encara que es reordenin els formularis o s'afegeixin nous formularis a la pàgina. Els elements dels formularis també es poden accedir directament mitjançant el seu atribut name:

var formularioPrincipal = document. formulari;
 var primerElemento = document. formulari. element;

 <Form name = "formulari">
   <Input type = "text" name = "element" />
 </ Form>

Òbviament, també es pot accedir als formularis i als seus elements utilitzant les funcions DOM d'accés directe als nodes. El següent exemple utilitza l'habitual funció document.getElementById() per accedir de forma directa a un formulari i un dels seus elements:

var formularioPrincipal = document. getElementById ("formulari");
 var primerElemento = document. getElementById ("element");

 <Form name = "formulari" id = "formulari">
   <Input type = "text" name = "element" id = "element" />
 </ Form>

Independentment del mètode utilitzat per obtenir la referència a un element de formulari, cada element disposa de les següents propietats útils per al desenvolupament de les aplicacions:

  • type : indica el tipus d'element que es tracta. Per als elements de tipus <input> ( text , button , checkbox , etc.) coincideix amb el valor del seu atribut type . Per a les llistes desplegables normals (element <select> ) el seu valor és select-one , el que permet diferenciar-les de les llistes que permeten seleccionar diversos elements alhora i el tipus és select-multiple. Finalment, en els elements de tipus <textarea> , el valor de type és textarea .
  • form : és una referència directa al formulari al qual pertany l'element. Així, per accedir al formulari d'un element, es pot utilitzar document.getElementById("id_del_elemento").form
  • name : obté el valor de l'atribut name de XHTML. Només es pot llegir el seu valor, per la qual cosa no es pot modificar.
  • value : permet llegir i modificar el valor de l'atribut value de XHTML. Per als camps de text ( <input type="text"> i <textarea> ) obté el text que ha escrit l'usuari. Per als botons obté el text que es mostra al botó. Per als elements checkbox i radiobutton no és molt útil, com es veurà més endavant

Validació

La principal utilitat de JavaScript en el maneig dels formularis és la validació de les dades introduïdes pels usuaris. Abans d'enviar un formulari al servidor, es recomana validar mitjançant JavaScript les dades inserides per l'usuari. D'aquesta manera, si l'usuari ha comès algun error en omplir el formulari, se li pot notificar de forma instantània, sense necessitat d'esperar la resposta del servidor.

Notificar els errors de forma immediata mitjançant JavaScript millora la satisfacció de l'usuari amb l'aplicació (el que tècnicament es coneix com "millorar l'experiència d'usuari") i ajuda a reduir la càrrega de processament al servidor.

Normalment, la validació d'un formulari consisteix en cridar a una funció de validació quan l'usuari prem sobre el botó d'enviament del formulari. En aquesta funció, es comproven si els valors que ha introduït l'usuari compleixen les restriccions imposades per l'aplicació.

Encara que hi ha tantes possibles comprovacions com a elements de formulari diferents, algunes comprovacions són molt habituals: que ompli un camp obligatori, que se seleccioni el valor d'una llista desplegable, que l'adreça d'email indicada sigui correcta, que la data introduïda sigui lògica, que s'hagi introduït un nombre on així es requereix, etc.

A continuació es mostra el codi JavaScript bàsic necessari per incorporar la validació a un formulari:

<form name="formulario"  onSubmit="return ValidaCampos()">
 Teléfono: <input type="text" name="telefono" size="15" maxlength="15"><br>
           <input type="submit" value="Enviar" name="enviar">
</form>

I l'esquema de la funció validacio() és el següent:

function ValidaCampos() {
   var expresion_regular_telefono = /^[89](\d-\d.)\d{3}\.\d{3}$/;  
// 9 cifras numéricas.
// Usaremos el método "test" de las expresiones regulares:
      if (expresion_regular_telefono.test(formulario.telefono.value) == false) {
                alert('Campo TELEFONO no válido.');
                return false; // sale de la función y NO envía el formulario
                }
                
                alert('Gracias por rellenar nuestro formulario correctamente.');
                return true; // sale de la función y SÍ envía el formulario
            }

El funcionament d'aquesta tècnica de validació es basa en el comportament de l'esdeveniment onsubmit de JavaScript. Igual que altres esdeveniments com onclick i onkeypress , l'esdeveniment onsubmit varia el seu comportament en funció del valor que retorna.

Així, si l'esdeveniment onsubmit torna el valor true , el formulari s'envia com ho faria normalment. No obstant això, si l'esdeveniment onsubmit torna el valor false , el formulari no s'envia. La clau d'aquesta tècnica consisteix a comprovar tots i cadascun dels elements del formulari. En tant es troba un element incorrecte, es torna el valor false . Si no es troba cap error, es torna el valor true.

Per tant, en primer lloc es defineix l'esdeveniment onsubmit del formulari com:

onsubmit = "return validacio()"

Com el codi JavaScript retorna el valor resultant de la funció validacio() , el formulari només s'enviarà al servidor si aquesta funció retorna true . En el cas que la funció validacio() retorni false , el formulari romandrà sense enviar.

Dins de la funció validacio() es comproven totes les condicions imposades per l'aplicació. Quan no es compleix una condició, es retorna false i per tant el formulari no s'envia. Si s'arriba al final de la funció, totes les condicions s'han complert correctament, de manera que es retorna true i el formulari s'envia.

La notificació dels errors comesos depèn del disseny de cada aplicació. En el codi de l'exemple anterior simplement es mostren missatges mitjançant la funció alert() indicant l'error produït. Les aplicacions web ben dissenyades mostren cada missatge d'error al costat de l'element de formulari corresponent i també solen mostrar un missatge principal indicant que el formulari conté errors.

Un cop definit l'esquema de la funció validacio() , s'ha d'afegir a aquesta funció el codi corresponent a totes les comprovacions que es realitzen sobre els elements del formulari.

Validació formularis HTML5

Validació formularis HTML5 I

Validació formularis HTML5 II

Client-side form validation

Exercicis de Validació

Formulari de validació 1

Crea un formulari que demani 4 camps en un textbox: nom, cognoms, email i telèfon. El formulari tindrà un botó "Enviar" que validarà el contingut dels textbox i en cas de passar les validacions s'obrirà una nova pàgina (que no cal que existeixi) amb els valors introduïts passats amb el mètode GET:

  • tots els camps seran obligatoris
  • el format serà el típic de cada camp
  • mostra els missatges d'error d'un en un, per ordre i posant el focus al camp que produeix cada error
  • usa els elements que coneixes de HTML, CSS, etc per a marcar l'error. Sigues creatiu

Formulari de validació 2

Al formulari anterior afegeix els camps data de naixement, adreça, codi postal i municipi (per aquest ordre) tenint en compte:

  • la data de naixement ha de ser vàlida, en format dd/mm/aaaa i anterior a la data actual.
  • l'adreça estarà formada per caràcters alfanumèrics i també admetrà espais,comes i guions.
  • el codi postal i municipi tindran el format típic d'aquests camps.

solució

<html>

<style>
.input_ok {background-color: lightcyan}
.input_error {background-color: rgb(255, 255, 119)}
.label_error {color: darkred}
</style>

<body >
	<h1>Exercici 1 de Validacions</h1>

	<form name="formulari" onSubmit="return valida()" action="ex_validacions.html" method="get">
		<label for="nom">Nom:</label><br>
		<input type="text" id="nom" name="nom" class="input_ok">
		<label id="er_nom" class="label_error"></label><br>	

		<label for="cognoms">Cognoms:</label><br>
		<input type="text" id="cognoms" name="cognoms" class="input_ok">
		<label id="er_cognoms" class="label_error"></label><br>

		<label for="email">Email:</label><br>
		<input type="text" id="email" name="email" class="input_ok">
		<label id="er_email" class="label_error"></label><br>

		<label for="telefon">Telefon:</label><br>
		<input type="text" id="telefon" name="telefon" class="input_ok">
		<label id="er_telefon" class="label_error"></label><br>

		<label for="data">Data de naixement:</label><br>
		<input type="text" id="data" name="data" class="input_ok">
		<label id="er_data" class="label_error"></label><br>

		<label for="adreca">Adreça:</label><br>
		<input type="text" id="adreca" name="adreca" class="input_ok">
		<label id="er_adreca" class="label_error"></label><br>

		<label for="cp">Codi postal:</label><br>
		<input type="text" id="cp" name="cp" class="input_ok">
		<label id="er_cp" class="label_error"></label><br>

		<label for="municipi">Municipi:</label><br>
		<input type="text" id="municipi" name="municipi" class="input_ok">
		<label id="er_municipi" class="label_error"></label><br><br>
		
		<input type="submit" value="Submit">
	
	</form>
</body >
<script type="text/javascript">


function valida(){

var nom=document.getElementById("nom").value;
var cognoms=document.getElementById("cognoms").value;
var email=document.getElementById("email").value;
var telefon=document.getElementById("telefon").value;
var data=document.getElementById("data").value;
var adreca=document.getElementById("adreca").value;
var cp=document.getElementById("cp").value;
var municipi=document.getElementById("municipi").value;
var patt_alfanumeric = /^[\wñÑçÇàáèéíòóúÀÁÈÉÍÒÓÚ]+(\s[\wñÑçÇàáèéíòóúÀÁÈÉÍÒÓÚ]+)*$/;
var patt_email = /^\w+@\w+\.\w+$/;
var patt_telefon =/^\d{9}$/;
var patt_data = /^\d{2}\/\d{2}\/\d{4}$/;
var patt_adreca = /^[\wñÑçÇàáèéíòóúÀÁÈÉÍÒÓÚ\,\.\-]+(\s[\wñÑçÇàáèéíòóúÀÁÈÉÍÒÓÚ\,\.\-]+)*$/;
var patt_cp=/^\d{5}$/;

// reset format dels textbox i missatges d'error
document.getElementById("nom").className="input_ok";
document.getElementById("er_nom").innerHTML="";
document.getElementById("cognoms").className="input_ok";
document.getElementById("er_cognoms").innerHTML="";
document.getElementById("email").className="input_ok";
document.getElementById("er_email").innerHTML="";
document.getElementById("telefon").className="input_ok";
document.getElementById("er_telefon").innerHTML="";
document.getElementById("data").className="input_ok";
document.getElementById("er_data").innerHTML="";
document.getElementById("adreca").className="input_ok";
document.getElementById("er_adreca").innerHTML="";
document.getElementById("cp").className="input_ok";
document.getElementById("er_cp").innerHTML="";
document.getElementById("municipi").className="input_ok";
document.getElementById("er_municipi").innerHTML="";

//validació del nom
if(nom=="") {
	document.getElementById("nom").className="input_error";
	document.getElementById("nom").focus();
	document.getElementById("er_nom").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_alfanumeric.test(nom)) {
	document.getElementById("nom").className="input_error";
	document.getElementById("nom").focus();
	document.getElementById("er_nom").innerHTML="&nbsp;format incorrecte";
	return false;
}

//validació dels cognoms
if(cognoms=="") {
	document.getElementById("cognoms").className="input_error";
	document.getElementById("cognoms").focus();
	document.getElementById("er_cognoms").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_alfanumeric.test(cognoms)) {
	document.getElementById("cognoms").className="input_error";
	document.getElementById("cognoms").focus();
	document.getElementById("er_cognoms").innerHTML="&nbsp;format incorrecte";
	return false;
}

//validació del email
if(email=="") {
	document.getElementById("email").className="input_error";
	document.getElementById("email").focus();
	document.getElementById("er_email").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_email.test(email)) {
	document.getElementById("email").className="input_error";
	document.getElementById("email").focus();
	document.getElementById("er_email").innerHTML="&nbsp;format incorrecte (ex. usuari@servidor.xx)";
	return false;
}

//validació del telefon
if(telefon=="") {
	document.getElementById("telefon").className="input_error";
	document.getElementById("telefon").focus();
	document.getElementById("er_telefon").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_telefon.test(telefon)) {
	document.getElementById("telefon").className="input_error";
	document.getElementById("telefon").focus();
	document.getElementById("er_telefon").innerHTML="&nbsp;format incorrecte (6 digits)";
	return false;
}

//validació de la data
if(data=="") {
	document.getElementById("data").className="input_error";
	document.getElementById("data").focus();
	document.getElementById("er_data").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_data.test(data)) {
	document.getElementById("data").className="input_error";
	document.getElementById("data").focus();
	document.getElementById("er_data").innerHTML="&nbsp;format incorrecte (dd/mm/aaaa)";
	return false;
}

var components_data = data.split("/");
var val_data=Date.parse(components_data[2]+"/"+components_data[1]+"/"+components_data[0]);

if(isNaN(val_data)) {
	document.getElementById("data").className="input_error";
	document.getElementById("data").focus();
	document.getElementById("er_data").innerHTML="&nbsp;data no vàlida";
	return false;	
}

var today=new Date();
if(val_data>=today) {
	document.getElementById("data").className="input_error";
	document.getElementById("data").focus();
	document.getElementById("er_data").innerHTML="&nbsp;la data ha de ser anterior a la data acutal";
	return false;	
}




//validació de l'adreça
if(adreca=="") {
	document.getElementById("adreca").className="input_error";
	document.getElementById("adreca").focus();
	document.getElementById("er_adreca").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_adreca.test(adreca)) {
	document.getElementById("adreca").className="input_error";
	document.getElementById("adreca").focus();
	document.getElementById("er_adreca").innerHTML="&nbsp;format incorrecte";
	return false;
}

//validació del codi postal
if(cp=="") {
	document.getElementById("cp").className="input_error";
	document.getElementById("cp").focus();
	document.getElementById("er_cp").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_cp.test(cp)) {
	document.getElementById("cp").className="input_error";
	document.getElementById("cp").focus();
	document.getElementById("er_cp").innerHTML="&nbsp;format incorrecte (5 digits)";
	return false;
}

//validació del municipi
if(municipi=="") {
	document.getElementById("municipi").className="input_error";
	document.getElementById("municipi").focus();
	document.getElementById("er_municipi").innerHTML="&nbsp;camp obligatori";
	return false;
}

if(!patt_adreca.test(municipi)) {
	document.getElementById("municipi").className="input_error";
	document.getElementById("municipi").focus();
	document.getElementById("er_municipi").innerHTML="&nbsp;format incorrecte";
	return false;
}

return true;


}
	</script>

		
</html>


Bibliografia

JavaScript RegExp Reference: https://www.w3schools.com/jsref/jsref_obj_regexp.asp

Experiments amb Expresions Regulars: http://www.regexplanet.com/advanced/javascript/index.html

John Resig, Bear Bibeault, "Secrets of the Javascript Ninja", Manning Publications, 2012. ISBN 193398869X

Introducció a Javascript

Expressions Regulars a Mozilla