Les pàgines estàtiques, amb una orientació purament informativa, van deixant lloc a d'altres, més intel·ligents, que es mouen seguint els interessos dels seus autors i dels usuaris. De l'aparador es passa a l'intercanvi d'informació.

Sota el títol "La pàgina respon" agrupem dos aspectes més relacionats amb aquest intercanvi que no pas amb el disseny: veurem com podem saber més del que els usuaris ens volen dir; aprendrem a protegir les pàgines de manera que només hi pugui entrar qui conegui la clau d'accés, desactivarem el botó dret, ...

En definitiva, no es tracta d'efectes espectaculars,sinó més aviat de conèixer unes tècniques que ens aportaran més control sobre el que passa amb les nostres pàgines.

  Conceptes JavaScript en aquest capítol
Comportament oncontextmenu : acció quan s'activa el menú de context amb el botó dret.
Mètode history.go() : salta a la pàgina de l'historial especificada i al lloc on l'havia deixada.

  1.- Camps ocults
En un formulari hi pot haver dades que s'enviaran i/o serviran per processar la resposta i que l'usuari no veu. Es tracta de camps que l'autor introdueix amb el modificador "hidden", ocult.

Aquest tipus de camps ens poden resultar molt útils en algunes ocasions. Per exemple, podem donar a un mateix formulari diverses utilitats depenent del valor d'un camp ocult: podem enviar un mateix formulari a llocs diferents, filtrar els missatges, obtenir informació sobre el client, ...

Els camps ocults s'utilitzen com qualsevol altre camp d'un formulari:

  <input type="hidden" name="noEsVeu" value="ocult">

En aquest exemple prepararem un formulari que, a més del nom i el missatge de l'usuari, tindrà altres dades que ens poden ser útils: títol i adreça de la pàgina, navegador, versió, sistema, pantalla i el temps que ha trigat a carregar-se la pàgina.

Al cos farem un formulari amb 8 camps, sis d'ocults i dos de visibles. També hi posarem un botó per esborrar i un altre per enviar. S'enviarà pel mètode POST, sense encriptar (enctype="text/plain"), com a acció tindrà un "mailto:" a la nostra adreça i definirem onSubmit="return noDupli(this)", és a dir, que en el moment d'enviar-lo es passi a si mateix com a paràmetre d'una funció.

Assignarem l'event onLoad del cos a una altra funció que s'executarà quan s'acabi de carregar la pàgina. Aquesta funció, Fet(), posarà a la variable fi el temps actual.

A la capçalera declararem tres variables:
  - inici: li assignem el temps actual quan comença la càrrega de la pàgina.
  - fi: ja esmentada, servirà per calcular el temps de càrrega. No la inicialitzem.
  - trameses: de moment a 0, evitarà que s'enviï el formulari dues vegades.

A continuació, la funció noDupli() rep com a paràmetre una referència al formulari. Comprova que el formulari existeix i, si és així, assigna als camps ocults les dades que volíem obtenir, entre elles, la resta ( fi - inici ) que ens diu quant ha trigat la pàgina a carregar-se. Després incrementa les trameses i, si encara són menys de 2 (és a dir, la primera) retorna a "true" i permet que s'enviï el formulari. En tots els altres casos retorna a "false".

Bé, ja tenim un formulari que ens informa més del que sembla i, de passada, hem vist com evitar trameses duplicades. Això només és el principi. Més endavant, quan tractarem les Cookies, caldrà recordar que els seus valors, que poden haver estat dies guardats a l'ordinador del client, també es poden assignar a camps ocults. Això ens permetria, per exemple, fer un seguiment detallat de les visites de cada usuari.

A l'exemple, en lloc d'enviar el missatge per correu, hem posat un camp de text on es mostren els valors dels camps ocults que s'envien.

<script language="javascript">
var inici = new Date()
inici = inici.getTime()
var fi
var trameses = 0
function noDupli(f1) {
  if (f1) {
    f1.pag.value = document.title
    f1.tmp.value = (fi - inici) + ' mil·lisegons'
    f1.url.value = location.href
    f1.sis.value = navigator.appName
    f1.ver.value = navigator.appVersion
    f1.pan.value = screen.width + 'x' + screen.height + ', ' + screen.colorDepth + ' bits'
    trameses++
    if (trameses<2) return true
  }
  return false
}
function Fet() {
  fi = new Date()
  fi = fi.getTime()
}
</script>
</head>

<body onLoad="
Fet()">
<form name="form1" method="POST" enctype="text/plain"
  action="mailto:unnom@pie.xtec.net?Subject=Info" onSubmit="
return noDupli(this)">
<input type="hidden" name="pag" value="">
<input type="hidden" name="tmp" value="">
<input type="hidden" name="url" value="">
<input type="hidden" name="sis" value="">
<input type="hidden" name="ver" value="">
<input type="hidden" name="pan" value="">
Nom: &nbsp <input type="text" name="nom" size="40" maxlength="60"><br>
<textarea name="missatge" rows="7" cols="48"></textarea><br>
<input type="reset" name="Reset" value="Esborrar les dades"> &nbsp;
<input type="submit" name="Enviar" value="Enviar el missatge">
...
 
2.- Afegir informació al formulari
L'exemple anterior va una mica carregat de camps. La veritat és que no cal. Podem fer el mateix, fins i tot de forma més elegant, sense utilitzar camps ocults. Un formulari amb el nom, el missatge i els botons és suficient.

La funció que comprovava els duplicats - i omplia els camps ocults -, s'haurà d'encarregar d'afegir aquesta informació a continuació del missatge. Hem preparat un exemple que ho fa, però ens hem oblidat d'escriure la solució.

No té massa gràcia afegir unes dades al cos del missatge, perquè l'usuari el podrà veure i, potser, no li agradarà. Si el nostre objectiu és recollir el màxim d'informació sobre els usuaris d'una pàgina, la millor opció és posar-hi alguna cosa senzilla i gormanda, com ara una votació o una enquesta. Podem recollir les dades en un camp ocult.

El que es planteja - som en un mòdul avançat - és descobrir la forma de fer-ho. Un parell de pistes: es basa en l'exemple anterior i es fa un bon ús de l'operador "+=".

 
3.- Accés restringit
JavaScript, com a llenguatge que pot executar el client, no disposa d'opcions de seguretat ni d'autentificació d'usuaris. Qualsevol pàgina que es carregui es podrà investigar, si més no, a partir de la còpia que queda a la memòria cau.

Podem intentar que no es guardi amb un parell de directives <meta>: una que li diu que la pàgina expira a l'instant i l'altra que demana que no es guardi. Però la pàgina ja és al navegador, i hi ha moltes maneres d'interceptar-la. Si volem una autentificació segura hem d'utilitzar llenguatges que s'executin al servidor.

Si la pàgina que volem protegir no conté informació vital, o el nostre servidor no permet tenir executables, podem usar trucs que amaguin la contrasenya. En aquest cas farem una pàgina que demana la clau i no deixa accedir a la seva codificació.

Per això, hem de fer que l'arxiu s'obri en una finestra nova, sense botons ni menús, i que vagi directament a demanar la clau. Si l'usuari l'encerta, carrega la pàgina protegida a la finestra base (opener) i tanca la nova. Si no, presenta un missatge - que esborra el contingut de la pàgina - i prepara un temporitzador per tancar la finestra al cap de dos segons.

Amb aquest mètode, la versió que queda a la memòria cau si han fallat els 'metas' dels usuaris que no han encertat la clau i només conté el missatge "Clau incorrecta". Mirem el codi, perquè la funció és prou senzilla i s'explica tota sola. La clau és "dhtml".

<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<script language="javascript">

function clau() {
  var pwd = prompt('Clau d\'accés', '')
  if (pwd == 'dhtml') {
    opener.location.href = 'd108m7p4.htm'
    window.close()
  }
  else {
    document.write( '<h2>Clau incorrecta</h2>' )
    setTimeout( 'window.close()', 2000 )
  }
}
</script>
</head>

<body onload="
clau()">
<font face="Arial" size="3"><br><br><br><br><br><br><br>
Escriviu la clau per accedir a la pràctica següent</font>

...
 
4.- Desactivar el botó dret
Amb el botó dret del ratolí els navegadors activen un menú de context. Hi ha opcions com ara "veure el codi de la pàgina", "Guardar imatge", "Copiar fons", "Crea una drecera", ... De vegades, no ens interessa gens que els usuaris tinguin aquestes possibilitats.

Per exemple, tenim una imatge original que no volem que es pugui guardar o no volem que es pugui veure el codi. Doncs, obrim una finestra sense menús i desactivem el botó dret. En aquest últim cas, els usuaris espavilats obriran una nova finestra (amb Control + N o, en navegadors moderns, + U) i el visualitzaran amb el menú. Més difícil ho tindran, en canvi, si posem la pàgina que volem protegir en un marc.

Hi ha diverses maneres de desactivar el botó dret del ratolí. Al segon exemple d'aquesta pàgina n'hem utilitzat un. Ara provarem un model diferent. Es tracta, en tots dos casos, d'interceptar l'event onmousedown, enviar-ho a una funció que comprovi, segons el navegador, amb quin botó s'ha fet clic, i que bloquegi la resposta.

L'exemple anterior es fa enviant una alerta. En aquest, més sofisticat, senzillament retornem fals. Això sí, interceptem també l'event oncontextmenu, assignem un valor fals al retorn (en lloc del menú de context) i, altre cop, retornem fals. Amb aquesta estratègia, ni funciona el botó dret, ni passa res, senzillament, la seva funcionalitat ha desaparegut.

<script language="javascript">
function bDret(e){
  if (document.all) if (event.button == 2) return false
  if (document.layers) if (e.which == 3) return false
}
function cMenu(){
  event.returnValue=false
  return false
}
if (document.layers) document.captureEvents(Event.MOUSEDOWN)
document.onmousedown=bDret
document.oncontextmenu=cMenu
</script>
 
5.- Diferències subtils
En diverses ocasions, al llarg del curs, hem utilitzat l'expressió location.reload() per tornar a carregar una pàgina. L'objecte history té el mètode go() que permet anar a la pàgina de l'historial que li especifiquem: history.go(-1) va a la pàgina anterior, history.go(+1) va a la següent, ... Aleshores, history.go(0) torna a carregar la pàgina actual.

Pel que sembla, tenim dues maneres de fer el mateix: history.go(0) i location.reload(). Doncs no. La diferència està en l'objecte que utilitzem: mentre location guarda les adreces, history recorda el punt des d'on hem deixat una pàgina, com els botons del navegador.

La conseqüència és evident: si volem tornar a carregar la pàgina amb el cursor al principi, utilitzem location.reload(). Si, al contrari, volem anar a parar a un lloc precís de la pàgina, hem d'utilitzar history.go(0). Per exemple, si una pàgina té elements actius - vincles, formulari - que no es visualitzen a la primera pantalla (s'han d'usar les barres de desplaçament), i volem recarregar la pàgina a la mateixa posició, hem d'usar history.go(0).

Això és el que passa a l'índex d'aquest curs: com que és un llistat d'enllaços llarg, la majoria d'usuaris necessiten desplaçar la barra per accedir a les últimes posicions. Quan es fa clic en un vincle, l'índex es torna a carregar, destacant la pàgina actual. Si s'utilitzés location.reload() també funcionaria però, en aquests casos, el vincle actual quedaria per sota de l'àrea visible.