Alguna vegada heu estat visitant una pàgina web que us ha reconegut i s'ha recordat de les vostres preferències, manifestades en alguna visita anterior? Per Internet es troben pàgines que tenen aquesta habilitat.

Però, com s'ho fan per recordar aquesta informació? La resposta està en les cookies, altrament dit, galetes.

Quin nom més curiós! Igual que altres conceptes d'Internet, aquest nom no té cap relació amb el que representa, però, ha estat acceptat per tothom.

  Elements del llenguatge en aquest capítol
Propietat document.cookie : Facilita el treball amb les cookies.
Objecte Date : Objecte JavaScript per treballar amb dates.
Mètode toGMTString() : Retorna una cadena amb forma de data
Mètode setTime() : Estableix la data i hora d'un objecte Date.
Mètode getTime() : Retorna la data i hora d'un objecte Date.
Funcions escape() i unescape() : Codifiquen i descodifiquen els caràcters no ASCII.
Funció replace() : Substitueix un tros de cadena de text per un altre.
Funció split() : Descompon una cadena en un vector separant-la pel caràcter separador.
 
1.-
Concepte i creació de cookies.
Les cookies ens serveixen per memoritzar dades d'una pàgina web entre diferents sessions de treball amb el navegador.

Es poden definir de dues maneres diferents: Mitjançant una crida al servidor HTTP i mitjançant JavaScript. En el primer cas, es fa utilitzant la directiva Set-cookie: situada a la capçalera de resposta HTTP originada per un programa CGI que s'executa al servidor. L'altre mètode consisteix en la definició local de la cookie mitjançant JavaScript.

En aquesta descripció no es tractarà del cas de cookies definides en el servidor HTTP, ja que la seva implementació requereix la creació de programes CGI situats en el servidor, i això, no és l'objectiu d'aquest curs. En canvi, tot el que tractarem a partir d'ara correspondrà al treball amb cookies mitjançant JavaScript.

Una cookie consisteix en un parell nom=valor que es pot desar en l'ordinador client.
IE desa aquests valors dins la carpeta "cookies" i NN ho fa dins el fitxer "cookies.txt".

La forma de fer-ho és mitjançant la propietat document.cookie. La seva sintaxi general és la següent:

        document.cookie = "nom=valor;expires=data;path=cami;domain=domini;secure";

nom : Aquest és el nom de la cookie. A aquest paràmetre se li assigna el valor de la cookie. És l'única dada imprescindible per crear la cookie.

expires : Aquest valor estableix la data en format GMT (Greenwich Mean Time) a partir de la qual la cookie deixarà de tenir validesa. Si no s'especifica, es pren el valor de la data i hora actual, per tant la cookie caducarà en tancar el navegador. Habitualment s'acostuma a expressar la data corresponent a un nombre de dies especificat en crear la cookie.

path : Aquest valor estableix una expressió patró que representa el camí on tindrà validesa la cookie. Si no s'especifica, agafarà per defecte el camí de la pàgina web que ha creat la cookie.

domain : Aquest valor estableix una expressió patró que representa el domini en què tindrà validesa la cookie. Si no s'especifica agafarà per defecte el domini de la pàgina web que crea la cookie.

secure : L'existència d'aquest paràmetre estableix que només es pot enviar la cookie si s'ha accedit a un servidor segur per mitja del protocol HTTPS.

Exemples de creació de cookies:

      - document.cookie = "Usuari=Joan Costa";
Es crea una cookie de nom "Usuari" i valor "Joan Costa". Com que no s'ha especificat cap altre valor, aquesta tindrà validesa mentre no es tanqui el navegador i dins el domini i path propis de la pàgina web que l'ha creat.

      - document.cookie= "Color = blue; expires=' Thu, 11-Aug-2002 12:30:00 GMT ' ";
Cookie de nom Color i valor blue, que tindrà validesa pel domini i path de la pàgina web que l'ha creat, mentre no s'hagi superat la data del 11-8-2002 a l'hora especificada.

Les cookies també tenen en consideració l'usuari identificat en la sessió de Windows actual. Si aquest usuari no coincideix amb el que ha creat la cookie, aquesta no tindrà cap efecte, encara que coincideixin els altres paràmetres.

S'ha de tenir en compte que la cookie desa per defecte el camí i domini de la pàgina web que l'ha creat, això vol dir que qualsevol altra pàgina que s'hagi descarregat des del mateix camí i domini també podrà tenir accés al contingut de la cookie i, per tant, llegir i escriure el seu contingut. Això pot ser molt útil per passar dades d'una pàgina web a una altra. Si es desitja ampliar l'àmbit de pàgines on la cookie serà accessible, s'haurà d'introduir el contingut corresponent als valors domain i path.

Sempre que desitgem llegir el valor d'una cookie, s'haurà d'utilitzar la propietat document.cookie, sense indicar cap assignació. Aquesta ens retornarà una cadena formada pel conjunt de parelles nom=valor separades amb un ; de totes les cookies que compleixen la condició de domini, path i data d'expiració del document que la sol·licita. La cadena retornada s'haurà de tractar per obtenir els valors individuals.

Si es desitja esborrar una cookie s'ha de fer posant-li una data de caducitat anterior a la data actual.

Tal com s'ha dit, és necessari treballar amb dates per establir la data de caducitat. Per això hem de conèixer bé el treball amb l'objecte Date. Si teniu algun dubte podeu consultar la pràctica 1 del mòdul 5. La data de caducitat s'ha d'establir en format GMT, això és fàcil d'implementar mitjançant el mètode toGMTString() de l'objecte Date que retorna una cadena de text amb aquest format.

Per exemple, si desitgem obtenir la data en format GMT, corresponent a 3 dies, a partir d'avui ho podem fer seguint els tres passos següents:

1 - Obtenim la data actual. data conté la data del sistema:
      data = new Date();

2 - Establim la data al valor de la data actual més tres dies. Recordem que l'objecte Date emmagatzema la data en forma de mil·lisegons, per tant tres dies són: 3 dies * 24 hores/dia * 60 minuts/hora * 60 segons/minut * 1000 ms/s .
      data.setDate( data.getDate + 3 *24*60*60*1000);

3.- Obtenim la data en format GMT:
      data.toGMTString();

Amb això obtindrem la cadena de text amb el format GMT següent:
      DiaSem, DD-Mes-YY HH:MM:SS GMT.

El següent exemple ens mostra la creació i eliminació de les cookie's. S'ha implementat mitjançant la creació de la funció crearCookie() perquè és el mètode més habitual i ens servirà per a exemples posteriors.

S'ha eliminat la utilització dels paràmetres domain, path i secure, per simplificar l'exemple i perquè són d'ús més específic i poc habitual, encara que la funció és fàcilment modificable per afegir aquests paràmetres si és necessari.

Si introduïm uns Dies de vida negatius, la cookie serà esborrada. Si no s'indica cap Dia de vida, la cookie solament existirà fins que es tanquni totes les finestres del navegador.

Si s'indica un determinat nombre de Dies de vida positius, la cookie tindrà vida durant aquests dies fins la seva caducitat. En aquest cas la cookie queda desada dins la carpeta "cookies" en el IE o dins el fitxer "cookies.txt" en el NN. Si no s'indica cap data, la cookie queda emmagatzemada a la memòria i desapareix en tancar totes les finestres del navegador.

Observeu també, com s'utilitza la funció escape() per codificar aquells caràcters que no són ASCII, com per exemple, espais en blanc, accents, caràcters especials, etc. Aquesta funció és necessària per codificar els caràcters especials dins el valor de la cookie. Posteriorment, en llegir la cookie, haurem de fer el procés invers amb unescape().

La funció crearCookie() també la utilitzarem en els següents apartats.


Dins el bloc <head>:

<script language='JavaScript'>

  function crearCookie(pNom, pValor, pDiesCaducitat)
  {
    if (pNom != ' ') {
      var txt = pNom + '=' + escape(pValor);
      if (pDiesCaducitat != ' ') {
        var dataCad = new Date();
        dataCad.setTime(dataCad.getTime() + pDiesCaducitat*24*60*60*1000);
        txt += '; expires=' + dataCad.toGMTString();
      }
      document.cookie = txt;
    }
  }
</script>

Dins el bloc <body>:

...
<form name="form1">
  Nom cookie: <input type="text" name="nom"><br>
  Valor: <input type="text" name="valor"><br>
  Dies de vida: <input type="text" name="dies">
  <input type="button" value="Crear Cookie" onClick="
crearCookie(form1.nom.value,
                                                              form1.valor.value, form1.dies.value);"><p>
  <input type="button" value="Veure les Cookie per aquest document"
                                                                      onClick="alert(
document.cookie);">
</form>
...

 
2.- Recollir les dades de les cookies.
Si una pàgina carregada en el navegador té cookies a la seva disposició, les pot obtenir mitjançant la propietat document.cookie. Aquesta ens retorna una cadena de text amb els parells nom=valor de les cookies.

A l'exemple anterior, fent clic sobre el botó "Veure les cookies ....", hem vist quina forma té la cadena que ens retorna. Aquesta està formada per un conjunt de parells nom=valor units per un punt i coma més un espai, de forma similar a la següent:

                  nom1=valor1; nom2=valor2; nom3=valor3; .......

Si desitgem obtenir el valor d'una sola d'aquestes cookies haurem de tractar la cadena, és a dir, descompondre-la en els diferents parells nom=valor i posteriorment verificar si existeix el nom que busquem i obtenir el seu valor.

En aquest apartat veurem com analitzem aquesta cadena per obtenir el valor desitjat d'una sola cookie.

Crearem una funció de nom llegirCookie(). Passant-li com a paràmetre el nom de la cookie, ens ha de retornar el seu valor, en el cas que la cookie existeixi, o bé, null en el cas que no existeixi.

També aprofitarem aquest apartat per crear una altra funció més senzilla, però que també serà útil posteriorment: és la funció esborraCookie(). Passant-li el nom de la cookie, ens l'esborrarà assignant-li la data corresponent al 1-1-1970.

La funció llegirCookie() rep com a paràmetre el nom de la cookie a llegir. Si el nom del paràmetre pNom té un valor, s'assigna a la variable dc el contingut de document.cookie. Si dc té una longitud superior a 0, es descompon aquesta variable en un vector mitjançant split(). Aquesta descomposició crea un vector, que també s'assigna a dc, on cada element conté un parell nom=valor, ja que s'ha escollit com a element separador el ;.

Posteriorment, dins el bloc while(...), s'analitza cadascun dels elements del vector dc. Cada element del vector dc es torna a descompondre mitjançant split(), assignant el vector resultant a la variable parell, el caràcter separador, en aquest cas és "=".

El vector parell constarà de dos elements, el nom i el valor, referits amb l'índex del vector 0 i 1 respectivament. Els noms corresponents a un índex i superior a zero, tindran afegit un espai en blanc al davant, que prové de la cadena retornada per document.cookie. Aquest espai en blanc afegit s'elimina amb la funció de cadena replace().

La funció replace() cerca un patró dins la cadena i si el troba el substitueix per una cadena nul·la amb ''. El patró és: /^ / . Aquest indica que cerqui un sol espai en blanc a partir del principi de la cadena. Si el troba, serà substituït per la cadena nul·la.

Quan parell[0] ja conté correctament el nom de la cookie, aquest es compara amb el paràmetre pNom. Si coincideixen s'assigna a la variable valor el contingut de parell[1],prèviament es fa el unescape() per desfer la substitució de caràcters que no són ASCII.

Finalment, en acabar el recorregut pel vector dc dins el bloc while(...)... es retorna al contingut de la variable valor. Aquesta valdrà null si no s'ha trobat la cookie o valdrà el valor de la cookie si ha estat trobada.

La funció esborraCookie() fa el mateix que fèiem en l'apartat anterior quan volíem esborrar una cookie. A la cookie indicada pel paràmetre pNom, li assigna un valor de data, al paràmetre expires de la cookie, inferior a la data actual. En aquest cas li assigna la data 1-1-1970 determinat per dataCad=new Date(0), on s'ha utilitzat el constructor de Date amb un valor inicial de 0 mil·lisegons.

Funcions a afegir dins el paràmetre <script> del bloc <head>:

<script language="javascript">

function llegirCookie(pNom)
{
  var valor=null;
  var parell;
  if (pNom!='') {
    var dc=document.cookie;
    if (dc.length > 0) {
      dc=dc.split(';');
      var i=0;
      while (i<dc.length) {
        parell=dc[i].split('=');
        if (i!=0) parell[0]=parell[0].replace(/^ /,'');//elimina l'espai en blanc del principi.
        ++i;
        if (parell[0]==pNom) valor=unescape(parell[1]);
      }
    }
  }
  return valor;
}

function esborraCookie(pNom)
{
  var txt= pNom + '= null';
  var dataCad = new Date(0);
  txt += '; expires=' + dataCad.toGMTString();
  document.cookie = txt;
}
</script>


Afegir dins el paràmetre <form> del bloc <body>:

<input type='button' value='Llegir Cookie' onClick='llegirCookie(Nom de la cookie)'>
<input type='button' value='Esborrar Cookie' onClick='esborraCookie(Nom de la cookie)'>


 
3.- Exemple d'aplicació de cookies.

En aquest apartat farem una aplicació d'ús de les cookies. Consistirà en crear una pàgina web, que inicialment, sol·liciti a l'usuari el seu nom i l'idioma preferit. Posteriorment mostrarà un missatge personalitzat en aquest idioma. A més, també mostrarà el nombre de vegades que hem visualitzat la pàgina i la data de l'últim accés. La caducitat de les cookies serà de 30 dies.

Disposarem, també, d'un botó auxiliar per esborrar totes les cookies i reiniciar l'exemple sense haver d'esperar que caduquin les cookies.

Utilitzarem dos blocs amb codi JavaScript, dins la secció <body> i dins la secció <head>. El codi del bloc <head> conté les tres funcions descrites als apartats anteriors més una nova funció de nom inicialitza(). Aquestes funcions seran invocades des del codi JavaScript del bloc <body>.

La funció inicialitza() (línies 5-12) serveix per inicialitzar les cookies en el cas que en carregar la pàgina, aquestes no existeixin. Les cookies a inicialitzar són 4: nom, idioma, comptador i dataUltimAcces. Les dues primers agafen el valor dels camps nom i idioma del formulari form1 que es crea des d'el bloc <body>. Un cop inicialitzades les cookies, es recarrega la pàgina amb la funció reload() de la línia 11.

Dins el bloc <body> tenim el codi JavaScript entre les línies 14-60, aquest codi s'executa immediatament després de carregar la pàgina. El primer que fa és obtenir el valor de cadascuna de les quatre cookies (línies 15-18). Si alguna d'elles no existeix, retornarà null a la variable nomUsuari, idioma, comptador o dataUltimAcces corresponent. En cas contrari, aquestes variables contindran el valor de la cookie.

A la línia 19 es verifica si cookie nom ha retornat null. Si és així, s'executarà el codi d'inicialització entre les línies 20-27. En cas contrari, s'executa el codi de representació (línies 29-52) del missatge personalitzat de la pàgina i el codi d'actualització de les cookies (línies 53-58).

El codi d'inicialització (línies 20-27) s'encarrega de treure per la finestra un text informatiu més un formulari que conviden a introduir el nom i les preferències respecte l'idioma. Un cop introduïdes aquestes dues dades, en prémer sobre el botó "OK!" s'invoca la funció inicialitzacio() i es creen les cookies amb els valors inicials.

El codi de representació del missatge (línies 29-52) és el que es mostra de forma habitual en la majoria dels casos. En funció del valor de la variable idioma s'executa un sol dels tres blocs que el composen, línies 29 -36 per al català, línies 37-44 per a l'anglès, i línies 45-52 per al francès. Conjuntament amb el text, es mostra el nom de l'usuari, el nombre de visites personalitzades i la data i hora de l'última visita, valors obtinguts de les variables nomUsuari, comptador i dataUltimaVisita.

Un cop s'ha mostrat el text informatiu personalitzat, les línies 53-58 s'encarreguen d'actualitzar les cookies. És necessari actualitzar aquests valors perquè com a mínim s'actualitzi la data de caducitat de les cookies. Aquest procés es fa rescrivint el valor de les cookies amb crearCookie().

Per a les cookies nom i idioma (línies 53 i 54) es rescriu el mateix valor, amb el qual solament s'ha actualitzat la data de caducitat. En el cas de la cookie comptador (línia 55), s'hi rescriu el valor de la variable comptador incrementat en una unitat, així, la propera visita es veurà el comptador incrementat.

Per a la cookie dataUltimAcces és necessari determinar prèviament el valor de la data actual i obtenir la cadena de data i hora en el format apropiat (línies 56 i 57), el resultat es desa a la variable dataHora. Per entendre les funcions de tractament de dates i hores podeu consultar la pràctica 1 del mòdul 5 on es detallen específicament .

Un cop dataHora ja conté el valor apropiat, es rescriu la cookie dataUltimAcces a la línia 58.

Dins el bloc <body> i fora del bloc de codi JavaScript, s'introdueix la resta de codi HTML. En aquest cas solament hi ha definit un formulari que conté un botó per esborrar les cookies. Aquest és un botó d'ús auxiliar, serveix per esborrar totes les cookies amb la funció esborraCookie() invocada per a cada cookie. D'aquesta forma, en tornar a obrir la pàgina d'exemple, ens apareixerà el formulari d'inicialització i podrem fer proves sense haver d'esperar que caduquin les cookies.

Per observar el correcte funcionament de l'exemple, s'ha d'obrir i tancar l'exemple múltiples vegades, observant com s'incrementa el comptador, es mantenen la data, les preferències d'idioma i nom d'usuari. Les proves s'han de fer tenint la finestra del navegador oberta o tancant totes les finestres del navegador, o tancant i tornant a obrir l'ordinador. S'ha de tornar a comprovar si funcionen al cap d'uns quants dies.

El botó "Esborrar totes les....." solament s'ha de polsar quan es desitgin reiniciar manualment totes les cookies sense esperar la seva caducitat. Això és per facilitar la realització de proves de funcionament.


Dins el bloc <head>:

  1 <script language='JavaScript'>
  2  ... Introduïu la funció crearCookie() ...
  3  ... Introduïu la funció llegirCookie() ...
  4  ... Introduïu la funció esborraCookie() ...

  5  function inicialitzacio()
  6  {
  7    crearCookie('nom', document.form1.nom.value, '30');
  8    crearCookie('idioma',
          document.form1.idioma.options[document.form1.idioma.selectedIndex].
                                                                                                              value, '30');
  9    crearCookie('comptador','1','30');
10    crearCookie('dataUltimAcces',' ' ,'30');
11    location.reload();
12  }
13 </script>


Dins el bloc <body> :

     ...

14 <script language="JavaScript">
15   var nomUsuari=llegirCookie('nom');
16   var idioma=llegirCookie('idioma');
17   var comptador=llegirCookie('comptador');
18   var dataUltimAcces=llegirCookie('dataUltimAcces');

19   if (nomUsuari==null || nomUsuari=='null') {
20     document.writeln('Hola, sembla ser que és el primer cop que accedeixes a aquesta
                                                                                                        pàgina<br>');
21     document.writeln('Has d'omplir les següents dades per personalitzar-la.<p>');
22     document.writeln('<form name=\'form1\'>');
23     document.writeln('Introdueix el teu nom: <input type=\'text\' name=\'nom\'>
                                                                                                                    <p>');
24     document.writeln('Selecciona idioma:&nbsp; &nbsp; &nbsp;
                    <select name=\'idioma\'>
                    <option selected value=\'ca\'>Català<option value=\'an\'>Anglès
                    <option value=\'fr\'>Francés</select>');
25     document.writeln('<input type=\'button\' value=\'&nbsp; OK! &nbsp;\'
                     onClick=\'inicialitzacio();\'>');
26     document.writeln('</form>');
27   }
28   else {
29     if (idioma=='ca') {
30       document.writeln('Hola, ' + nomUsuari + '. ');
31       if (comptador==1) document.writeln('És el primer accés que fas a
                                                                                                    aquesta pàgina. ');
32       else {
33         document.writeln('És l\'accés número ' + comptador + ' que fas a
                                                                                                    aquesta pàgina. ');
34         document.writeln('L\'últim acces va esser el ' + dataUltimAcces + '.');
35       }
36     }
37     if (idioma=='an') {
38       document.writeln('Hello, ' + nomUsuari + '. ');
39       if (comptador==1) document.writeln('This is the first access that you do to
                                                                                                            this web. ');
40       else {
41         document.writeln('This is the access number ' + comptador + ' that you do to
                                                                                                            this web. ');
42         document.writeln('The last access was on ' + dataUltimAcces + '.');
43       }
44     }
45     if (idioma=='fr') {
46       document.writeln('Salut, ' + nomUsuari + '. ');
47       if (comptador==1) document.writeln('C\'est la première visite que vous faites
                                                                                                         à ce site. ');
48       else {
49         document.writeln('C\'est la visite numéro ' + comptador + ' que vous faites
                                                                                                         à ce site. ');
50         document.writeln('La dernière visite était le ' + dataUltimAcces + '.');
51       }
52     }
53     crearCookie('nom', nomUsuari, '30');
54     crearCookie('idioma', idioma, '30');
55     crearCookie('comptador', ++comptador, '30');
56     var ara=new Date();
57     var dataHora = ara.getDate() + '/' + (ara.getMonth()+1) + '/' + ara.getFullYear()
              + ' -- ' + ((ara.getHours()<10)?('0'+ara.getHours()):(ara.getHours())) + ':' +
              ((ara.getMinutes()<10)?('0'+ara.getMinutes()):(ara.getMinutes())) + ':' +
              ((ara.getSeconds()<10)?('0'+ara.getSeconds()):(ara.getSeconds()));
58     crearCookie('dataUltimAcces',dataHora, '30');
59   }
60 </script>

61 <form name='form2'>
62   <center>
63     <input type='button' value='Esborrar totes les cookies' onClick=
                        'esborraCookie("nom"); esborraCookie("idioma");
                        esborraCookie("comptador"); esborraCookie("dataUltimAcces");'>
64   </center>
65 </form>
     ...