Você está na página 1de 280

www.librosweb.

es

Introduccin a

AJAX

Javier Eguluz Prez


Introduccin a AJAX

Sobre este libro...


Los contenidos de este libro est n bjo un licenci Cretive Commons Reconocimiento -
No Comercil - Sin Obr Derivd 3.0 (http://cretivecommons.org/licenses/by-nc-nd/
3.0/deed.es)

Esta versin impresa se cre el 7 de junio de 2008 y todava est incompleta. L


versio n m s ctulizd de los contenidos de este libro se puede encontrr en
http://www.librosweb.es/jx

Si quieres portr sugerencis, comentrios, crtics o informr sobre errores, puedes


envirnos un mensje contacto@librosweb.es

www.librosweb.es 2
Introduccin a AJAX

Captulo 1. Introduccin a AJAX .................................................................................................................. 5


Captulo 2. JavaScript bsico ...................................................................................................................... 9
2.1. Sintaxis..................................................................................................................................................... 9
2.2. Variables ................................................................................................................................................ 10
2.3. Palabras reservadas ............................................................................................................................... 12
2.4. Tipos de variables .................................................................................................................................. 13
2.5. Operadores ............................................................................................................................................ 21
2.6. Objetos nativos de JavaScript ................................................................................................................ 26
2.7. Funciones............................................................................................................................................... 28
2.8. Funciones y propiedades bsicas de JavaScript..................................................................................... 31
Captulo 3. JavaScript avanzado.................................................................................................................35
3.1. Objetos .................................................................................................................................................. 35
3.2. Clases ..................................................................................................................................................... 44
3.3. Otros conceptos .................................................................................................................................... 52
Captulo 4. DOM (Document Object Model) ..............................................................................................57
4.1. Introduccin a DOM .............................................................................................................................. 57
4.2. Tipos de nodos....................................................................................................................................... 58
4.3. La interfaz Node .................................................................................................................................... 61
4.4. HTML y DOM ......................................................................................................................................... 62
Captulo 5. BOM (Browser Object Model) ..................................................................................................82
5.1. Introduccin a BOM............................................................................................................................... 82
5.2. El objeto window ................................................................................................................................... 83
5.3. El objeto document ............................................................................................................................... 85
5.4. El objeto location ................................................................................................................................... 87
5.5. El objeto navigator ................................................................................................................................ 88
5.6. El objeto screen ..................................................................................................................................... 89
Captulo 6. Eventos ...................................................................................................................................90
6.1. Modelo bsico de eventos..................................................................................................................... 90
6.2. El flujo de eventos ................................................................................................................................. 96
6.3. Handlers y listeners ............................................................................................................................... 99
6.4. El objeto event..................................................................................................................................... 101
6.5. Tipos de eventos .................................................................................................................................. 108
6.6. Solucin cross browser ........................................................................................................................ 111
Captulo 7. Primeros pasos con AJAX .......................................................................................................114
7.1. Breve historia de AJAX ......................................................................................................................... 114
7.2. La primera aplicacin........................................................................................................................... 114
7.3. Mtodos y propiedades del objeto XMLHttpRequest ......................................................................... 119
7.4. Utilidades y objetos para AJAX ............................................................................................................ 121
7.5. Interaccin con el servidor .................................................................................................................. 127
7.6. Aplicaciones complejas........................................................................................................................ 133
7.7. Seguridad ............................................................................................................................................. 138
Captulo 8. Tcnicas bsicas con AJAX......................................................................................................140

www.librosweb.es 3
Introduccin a AJAX

8.1. Listas desplegables encadenadas ........................................................................................................ 140


8.2. Teclado virtual ..................................................................................................................................... 142
8.3. Autocompletar..................................................................................................................................... 146
Captulo 9. Tcnicas avanzadas con AJAX.................................................................................................149
9.1. Monitorizacin de servidores remotos................................................................................................ 149
9.2. Lector RSS ............................................................................................................................................ 152
9.3. Google Maps........................................................................................................................................ 154
Captulo 10. Frameworks y libreras.........................................................................................................164
10.1. El framework Prototype .................................................................................................................... 164
10.2. La librera scriptaculous ..................................................................................................................... 181
10.3. La librera jQuery ............................................................................................................................... 182
10.4. Otros frameworks importantes ......................................................................................................... 194
Captulo 11. Otras utilidades ...................................................................................................................195
11.1. Detener las peticiones HTTP errneas............................................................................................... 195
11.2. Mejorar el rendimiento de las aplicaciones complejas ..................................................................... 198
11.3. Ofuscar el cdigo JavaScript .............................................................................................................. 199
11.4. Evitar el problema de los dominios diferentes .................................................................................. 200
Captulo 12. Recursos tiles.....................................................................................................................203
Captulo 13. Bibliografa ..........................................................................................................................204
Captulo 14. Ejercicios resueltos ..............................................................................................................205

www.librosweb.es 4
Introduccin a AJAX Captulo 1. Introduccin a AJAX

Captulo 1. Introduccin a AJAX


El te rmino AJAX se presento por primer vez en el rtculo "Ajx: A New Approch to Web
Applictions (http://www.dptivepth.com/publictions/essys/rchives/000385.php) "
publicdo por Jesse Jmes Grrett el 18 de Febrero de 2005. Hst ese momento, no exist un
te rmino normlizdo que hicier referenci un nuevo tipo de pliccio n web que estb
preciendo.

En relidd, el te rmino AJAX es un cro nimo de Asynchronous JavaScript + XML, que se puede
trducir como "JvScript sncrono + XML".

El rtculo define AJAX de l siguiente form:

Ajx no es un tecnolog en s mismo. En relidd, se trt de vris tecnologs


independientes que se unen de forms nuevs y sorprendentes.

Ls tecnologs que formn AJAX son:

XHTML y CSS, pr crer un presentcio n bsd en est ndres.


DOM, pr l interccio n y mnipulcio n din mic de l presentcio n.
XML, XSLT y JSON, pr el intercmbio y l mnipulcio n de informcio n.
XMLHttpRequest, pr el intercmbio sncrono de informcio n.
JvScript, pr unir tods ls dem s tecnologs.

Figura 1.1. Tecnologas agrupadas bajo el concepto de AJAX

Desrrollr plicciones AJAX requiere un conocimiento vnzdo de tods y cd un de ls


tecnologs nteriores.

En ls plicciones web trdicionles, ls cciones del usurio en l p gin (pinchr en un boto n,


seleccionr un vlor de un list, etc.) desencdenn llmds l servidor. Un vez procesd l
peticio n del usurio, el servidor devuelve un nuev p gin HTML l nvegdor del usurio.

En el siguiente esquem, l imgen de l izquierd muestr el modelo trdicionl de ls


plicciones web. L imgen de l derech muestr el nuevo modelo propuesto por AJAX:

www.librosweb.es 5
Introduccin a AJAX Captulo 1. Introduccin a AJAX

Figura 1.2. Comparacin grfica del modelo tradicional de aplicacin web y del nuevo modelo
propuesto por AJAX. (Imagen original creada por Adaptive Path y utilizada con su permiso)

Est te cnic trdicionl pr crer plicciones web funcion correctmente, pero no cre un
buen senscio n l usurio. Al relizr peticiones continus l servidor, el usurio debe esperr
que se recrgue l p gin con los cmbios solicitdos. Si l pliccio n debe relizr peticiones
continus, su uso se convierte en lgo molesto

AJAX permite mejorr completmente l interccio n del usurio con l pliccio n, evitndo ls
recrgs constntes de l p gin, y que el intercmbio de informcio n con el servidor se
produce en un segundo plno.

Ls plicciones construids con AJAX eliminn l recrg constnte de p gins medinte l


crecio n de un elemento intermedio entre el usurio y el servidor. L nuev cp intermedi de
AJAX mejor l respuest de l pliccio n, y que el usurio nunc se encuentr con un ventn
del nvegdor vc esperndo l respuest del servidor.

El siguiente esquem muestr l diferenci m s importnte entre un pliccio n web trdicionl


y un pliccio n web cred con AJAX. L imgen superior muestr l intercio n sncron propi
de ls plicciones web trdicionles. L imgen inferior muestr l comuniccio n sncron de
ls plicciones creds con AJAX.

www.librosweb.es 6
Introduccin a AJAX Captulo 1. Introduccin a AJAX

Figura 1.3. Comparacin entre las comunicaciones sncronas de las aplicaciones web tradicionales y
las comunicaciones asncronas de las aplicaciones AJAX (Imagen original creada por Adaptive Path y
utilizada con su permiso)

Ls peticiones HTTP l servidor se sustituyen por peticiones JvScript que se relizn l


elemento encrgdo de AJAX. Ls peticiones m s simples no requieren intervencio n del servidor,
por lo que l respuest es inmedit. Si l interccio n requiere un respuest del servidor, l
peticio n se reliz de form sncron medinte AJAX. En este cso, l interccio n del usurio
tmpoco se ve interrumpid por recrgs de p gin o lrgs espers por l respuest del
servidor.

Desde su pricio n, se hn credo cientos de plicciones web bsds en AJAX. En l myor de


csos, AJAX puede sustituir completmente otrs te cnics como Flsh. Adem s, en el cso de
ls plicciones web m s vnzds, pueden llegr sustituir ls plicciones de escritorio.

A continucio n se muestr un list de lguns de ls plicciones m s conocids bsds en


AJAX:

www.librosweb.es 7
Introduccin a AJAX Captulo 1. Introduccin a AJAX

Gestores de correo electro nico: Gmil (http://www.gmil.com) , Yhoo Mil


(http://mil.yhoo.com) , Windows Live Mil (http://www.hotmil.com) .
Crtogrf: Google Mps (http://mps.google.com) , Yhoo Mps
(http://mps.yhoo.com) , Windows Live Locl (http://mps.live.com) .
Aplicciones web y productividd: Google Docs (http://docs.google.com) , Zimbr
(http://www.zimbr.com/) , Zoho (http://www.zoho.com/) .
Otrs: Netvibes (http://www.netvibes.com) [metp gin], Digg (http://www.digg.com)
[noticis], Meebo (http://www.meebo.com) [mensjer], 30 Boxes
(http://www.30boxes.com) [clendrio], Flickr (http://www.flickr.com) [fotogrf].

www.librosweb.es 8
Introduccin a AJAX Captulo 2. JavaScript bsico

Captulo 2. JavaScript bsico


2.1. Sintaxis
L sintxis de un lenguje de progrmcio n se define como el conjunto de regls que deben
seguirse l escribir el co digo fuente de los progrms pr considerrse como correctos pr ese
lenguje de progrmcio n.

L sintxis de JvScript es muy similr l de otros lengujes como Jv y C. Ls norms b sics


que definen l sintxis de JvScript son ls siguientes:

No se tienen en cuent los espcios en blnco y ls nuevs lnes: como sucede con
XHTML, el inte rprete de JvScript ignor culquier espcio en blnco sobrnte, por lo que
el co digo se puede ordenr de form decud pr su mnejo (tbulndo ls lnes,
n diendo espcios, crendo nuevs lnes, etc.)
Se distinguen ls myu sculs y minu sculs: l igul que sucede con l sintxis de ls
etiquets y elementos XHTML. Sin embrgo, si en un p gin XHTML se utilizn
indistintmente myu sculs y minu sculs, l p gin se visuliz correctmente y el u nico
problem es que l p gin no vlid. Por el contrrio, si en JvScript se intercmbin
myu sculs y minu sculs, ls plicciones no funcionn correctmente.
No se define el tipo de ls vribles: l definir un vrible, no es necesrio indicr el tipo
de dto que lmcenr . De est form, un mism vrible puede lmcenr diferentes
tipos de dtos durnte l ejecucio n del progrm.
No es obligtorio terminr cd sentenci con el cr cter del punto y com ( ;): l
contrrio de l myor de lengujes de progrmcio n, en JvScript no es obligtorio
terminr cd sentenci con el cr cter del punto y com (;). No obstnte, es muy
recomendble seguir l trdicio n de terminr cd sentenci con el cr cter ;

Se pueden incluir comentrios: los comentrios se utilizn pr n dir lgun informcio n


relevnte l co digo fuente del progrm. Aunque no se visulizn por pntll, su
contenido se env l nvegdor del usurio junto con el resto del progrm, por lo que es
necesrio extremr ls precuciones sobre el contenido de los comentrios.

JvScript define dos tipos de comentrios: los de un sol lne y los que ocupn vris lnes.
Los comentrios de un sol lne se definen n diendo dos brrs oblicus (//) l principio de
cd lne que form el comentrio:
// a continuacin se muestra un mensaje
alert("mensaje de prueba");

Tmbie n se pueden incluir vrios comentrios seguidos de un sol lne:


// a continuacin se muestra un mensaje
// y despus se muestra otro mensaje
alert("mensaje de prueba");

www.librosweb.es 9
Introduccin a AJAX Captulo 2. JavaScript bsico

Cundo un comentrio ocup m s de un lne, es m s eficiente utilizr los comentrios


multilne, que se definen encerrndo el texto del comentrio entre los crcteres /* y */
/* Los comentarios de varias lneas son muy tiles
cuando se necesita incluir bastante informacin
en los comentarios */
alert("mensaje de prueba");

Ls norms complets de sintxis y de culquier otro specto relciondo con JvScript se


pueden consultr en el est ndr oficil del lenguje que est disponible en
http://www.ecm-interntionl.org/publictions/stndrds/Ecm-262.htm

2.2. Variables
Ls vribles se definen medinte l plbr reservd var, que permite definir un o vris
vribles simult nemente:
var variable1 = 16;
var variable2 = "hola", variable3 = "mundo";
var variable4 = 16, variable5 = "hola";

El nombre de ls vribles debe cumplir ls dos siguientes condiciones:

El primer cr cter debe ser un letr o un guio n bjo (_) o un do lr ($).

El resto de crcteres pueden ser letrs, nu meros, guiones bjos ( _) y smbolos de do lr


($).

No es obligtorio inicilizr un vrible l declrrl:


var variable6;

Si l vrible no se declr medinte el operdor var, utom ticmente se cre un vrible


globl con ese identificdor y su vlor. Ejemplo:
var variable1 = 16;
variable2 = variable1 + 4;

En el ejemplo nterior, l variable2 no h sido declrd, por lo que l llegr es instruccio n,


JvScript cre utom ticmente un vrible globl llmd variable2 y le sign el vlor
correspondiente.

El mbito de un vrible (llmdo scope en ingle s) es l zon del progrm en l que se define l
vrible. JvScript define dos mbitos pr ls vribles: globl y locl.

El siguiente ejemplo ilustr el comportmiento de los mbitos:


function muestraMensaje() {
var mensaje = "Mensaje de prueba";
}

muestraMensaje();
alert(mensaje);

www.librosweb.es 10
Introduccin a AJAX Captulo 2. JavaScript bsico

Cundo se ejecut el co digo JvScript nterior, su resultdo no es el esperdo, y que no se


muestr por pntll ningu n mensje. L vrible mensaje se h definido dentro de l funcio n
y por tnto es un vrible locl que solmente est definid dentro de l funcio n.

Culquier instruccio n que se encuentre dentro de l funcio n puede hcer uso de l vrible. Sin
embrgo, culquier instruccio n que se encuentre en otrs funciones o fuer de culquier funcio n
no tendr definid l vrible mensje.

Adem s de vribles locles, tmbie n existe el concepto de vrible globl, que est definid en
culquier punto del progrm (incluso dentro de culquier funcio n).
var mensaje = "Mensaje de prueba";

function muestraMensaje() {
alert(mensaje);
}

El co digo JvScript nterior define un vrible fuer de culquier funcio n. Este tipo de
vribles utom ticmente se trnsformn en vribles globles y est n disponibles en
culquier punto del progrm.

De est form, unque en el interior de l funcio n no se h definido ningun vrible llmd


mensaje, l vrible globl cred nteriormente permite que l instruccio n alert() dentro de
l funcio n muestre el mensje correctmente.

Si un vrible se declr fuer de culquier funcio n, utom ticmente se trnsform en


vrible globl independientemente de si se define utilizndo l plbr reservd var o no.
Sin embrgo, en el interior de un funcio n, ls vribles declrds medinte var se
considern locles y el resto se trnsformn tmbie n utom ticmente en vribles globles.

Por lo tnto, el siguiente ejemplo si que funcion como se esper:


function muestraMensaje() {
mensaje = "Mensaje de prueba";
}

muestraMensaje();
alert(mensaje);

En cso de colisio n entre ls vribles globles y locles, dentro de un funcio n prevlecen ls


vribles locles:
var mensaje = "gana la de fuera";

function muestraMensaje() {
var mensaje = "gana la de dentro";
alert(mensaje);
}

alert(mensaje);
muestraMensaje();
alert(mensaje);

El co digo nterior muestr por pntll los siguientes mensjes:

www.librosweb.es 11
Introduccin a AJAX Captulo 2. JavaScript bsico

gana la de fuera
gana la de dentro
gana la de fuera

L vrible locl llmd mensaje dentro de l funcio n tiene m s prioridd que l vrible
globl del mismo nombre, pero solmente dentro de l funcio n.

Si no se define l vrible dentro de l funcio n con l plbr reservd var, en relidd se est
modificndo el vlor de l vrible globl:
var mensaje = "gana la de fuera";

function muestraMensaje() {
mensaje = "gana la de dentro";
alert(mensaje);
}

alert(mensaje);
muestraMensaje();
alert(mensaje);

En este cso, los mensjes mostrdos son:


gana la de fuera
gana la de dentro
gana la de dentro

L recomendcio n generl es definir como vribles locles tods ls vribles que sen de uso
exclusivo pr relizr ls tres encrgds cd funcio n. Ls vribles globles se utilizn
pr comprtir vribles entre funciones de form r pid.

2.3. Palabras reservadas


Como culquier otro lenguje de progrmcio n, JvScript utiliz un serie de plbrs pr
crer ls instrucciones que formn cd progrm. Por este motivo, ests plbrs se considern
reservds y no se pueden utilizr como nombre de un vrible o funcio n.

El est ndr ECMA-262 incluye l list de ls plbrs reservds que utiliz ctulmente
JvScript y l list de ls plbrs reservds pr su uso futuro.

Utilizds ctulmente: break, else, new, var, case, finally, return, void, catch, for, switch,
while, continue, function, this, with, default, if, throw, delete, in, try, do, instanceof,
typeof

Reservds pr su uso futuro:

abstract, enum, int, short, boolean, export, interface, static, byte, extends, long, super,
char, final, native, synchronized, class, float, package, throws, const, goto, private,
transient, debugger, implements, protected, volatile, double, import, public

www.librosweb.es 12
Introduccin a AJAX Captulo 2. JavaScript bsico

2.4. Tipos de variables


JvScript divide los distintos tipos de vribles en dos grupos: tipos primitivos y tipos de
referenci o clses.

2.4.1. Tipos primitivos


JvScript define cinco tipos primitivos: undefined, null, boolean, number y string. Adem s de
estos tipos, JvScript define el operdor typeof pr verigur el tipo de un vrible.

2.4.1.1. El operador typeof

El operdor typeof se emple pr determinr el tipo de dto que lmcen un vrible. Su


uso es muy sencillo, y que so lo es necesrio indicr el nombre de l vrible cuyo tipo se quiere
verigur:
var variable1 = 7;
typeof variable1; // "number"
var variable2 = "hola mundo";
typeof variable2; // "string"

Los posibles vlores de retorno del operdor son: undefined, boolean, number, string pr
cd uno de los tipos primitivos y object pr los vlores de referenci y tmbie n pr los
vlores de tipo null.

2.4.1.2. Variables de tipo undefined

El tipo undefined corresponde ls vribles que hn sido definids y todv no se les h


signdo un vlor:
var variable1;
typeof variable1; // devuelve "undefined"

El operdor typeof no distingue entre ls vribles declrds pero no inicilizds y ls


vribles que ni siquier hn sido declrds:
var variable1;
typeof variable1; // devuelve "undefined", aunque la variable1 ha sido declarada
typeof variable2; // devuelve "undefined", la variable2 no ha sido declarada

2.4.1.3. Variables de tipo null

Se trt de un tipo similr undefined, y de hecho en JvScript se considern igules


(undefined == null). El tipo null se suele utilizr pr representr objetos que en ese
momento no existen.
var nombreUsuario = null;

www.librosweb.es 13
Introduccin a AJAX Captulo 2. JavaScript bsico

2.4.1.4. Variables de tipo boolean

Adem s de vribles de tipo boolean, tmbie n se suelen llmr vribles lo gics y vribles
booleanas. Se trt de un vrible que so lo puede lmcenr uno de los dos vlores especiles
definidos y que representn el vlor "verdadero" y el vlor "falso".
var variable1 = true;
var variable2 = false;

Los vlores true y false son vlores especiles, de form que no son plbrs ni nu meros
ni ningu n otro tipo de vlor. Este tipo de vribles son esenciles pr crer culquier
pliccio n, tl y como se ver m s delnte.

Cundo es necesrio convertir un vrible nume ric un vrible de tipo boolean, JvScript
plic l siguiente conversio n: el nu mero 0 se convierte en false y culquier otro nu mero
distinto de 0 se convierte en true.

Por este motivo, en ocsiones se soci el nu mero 0 con el vlor false y el nu mero 1 con el
vlor true. Sin embrgo, es necesrio insistir en que true y false son vlores especiles que
no se corresponden ni con nu meros ni con ningu n otro tipo de dto.

2.4.1.5. Variables de tipo numrico

Ls vribles nume rics son muy utilizds en ls plicciones hbitules, y que permiten
lmcenr culquier vlor nume rico. Si el nu mero es entero, se indic directmente. Si el
nu mero es deciml, se debe utilizr el punto (.) pr seprr l prte enter de l deciml.
var variable1 = 10;
var variable2 = 3.14159265;

Adem s del sistem nume rico deciml, tmbie n se pueden indicr vlores en el sistem octl (si
se incluye un cero delnte del nu mero) y en sistem hexdeciml (si se incluye un cero y un x
delnte del nu mero).
var variable1 = 10;
var variable_octal = 034;
var variable_hexadecimal = 0xA3;

JvScript define tres vlores especiles muy u tiles cundo se trbj con nu meros. En primer
lugr se definen los vlores Infinity y Infinity pr representr nu meros demsido
grndes (positivos y negtivos) y con los que JvScript no puede trbjr.
var variable1 = 3, variable2 = 0;
alert(variable1/variable2); // muestra "Infinity"

El otro vlor especil definido por JvScript es NaN, que es el cro nimo de "Not a Number". De
est form, si se relizn operciones mtem tics con vribles no nume rics, el resultdo ser
de tipo NaN.

Pr mnejr los vlores NaN, se utiliz l funcio n relciond isNaN(), que devuelve true si el
pr metro que se le ps no es un nu mero:

www.librosweb.es 14
Introduccin a AJAX Captulo 2. JavaScript bsico

var variable1 = 3;
var variable2 = "hola";
isNaN(variable1); // false
isNaN(variable2); // true
isNaN(variable1 + variable2); // true

Por u ltimo, JvScript define lguns constntes mtem tics que representn vlores
nume ricos significtivos:

Constante Valor Significado


Constante de Euler, base de los logaritmos naturales y tambi n
Math.E 2.718281828459045
llamado nmero e
Math.LN2 0.6931471805599453 Logaritmo natural de 2
Math.LN10 2.302585092994046 Logaritmo natural de 10
Math.LOG2E 1.4426950408889634 Logaritmo en base 2 de Math.E
Math.LOG10E 0.4342944819032518 Logaritmo en base 10 de Math.E
Math.PI 3.141592653589793 Pi, relacin entre el radio de una circunferencia y su dimetro
Math.SQRT1_2 0.7071067811865476 Raz cuadrada de 1/2
Math.SQRT2 1.4142135623730951 Raz cuadrada de 2

De est form, pr clculr el re de un crculo de rdio r, se debe utilizr l constnte que


represent l nu mero Pi:
var area = Math.PI * r * r;

2.4.1.6. Variables de tipo cadena de texto

Ls vribles de tipo cden de texto permiten lmcenr cuquier sucesio n de crcteres, por
lo que se utilizn mplimente en l myor de plicciones JvScript. Cd cr cter de l
cden se encuentr en un posicio n l que se puede cceder individulmente, siendo el
primer cr cter el de l posicio n 0.

El vlor de ls cdens de texto se indic encerrdo entre comills simples o dobles:


var variable1 = "hola";
var variable2 = 'mundo';
var variable3 = "hola mundo, esta es una frase ms larga";

Ls cdens de texto pueden lmcenr culquier cr cter, unque lgunos no se pueden incluir
directmente en l declrcio n de l vrible. Si por ejemplo se incluye un ENTER pr mostrr
el resto de crcteres en l lne siguiente, se produce un error en l pliccio n:
var variable = "hola mundo, esta es
una frase ms larga";

L vrible nterior no est correctmente definid y se producir un error en l pliccio n. Por


tnto, result evidente que lgunos crcteres especiales no se pueden incluir directmente. De
l mism form, como ls comills (doble y simple) se utilizn pr encerrr los contenidos,
tmbie n se pueden producir errores:

www.librosweb.es 15
Introduccin a AJAX Captulo 2. JavaScript bsico

var variable1 = "hola 'mundo'";


var variable2 = 'hola "mundo"';
var variable3 = "hola 'mundo', esta es una "frase" ms larga";

Si el contenido de texto tiene en su interior lgun comill simple, se encierrn los contenidos
con comills dobles (como en el cso de l variable1 nterior). Si el contenido de texto tiene
en su interior lgun comill doble, se encierrn sus contenidos con comills simples (como en el
cso de l variable2 nterior). Sin embrgo, en el cso de l variable3 su contenido tiene
tnto comills simples como comills dobles, por lo que su declrcio n provocr un error.

Pr resolver estos problems, JvScript define un mecnismo pr incluir de form sencill


crcteres especiles (ENTER, Tabulador) y problem ticos (comills). Est estrtegi se
denomin "mecanismo de escape", y que se sustituyen los crcteres problem ticos por otros
crcteres seguros que siempre empiezn con l brr \:

Si se quiere incluir... Se debe sustituir por...


Una nueva lnea \n
Un tabulador \t
Una comilla simple \'
Una comilla doble \"
Una barra inclinada \\

Utilizndo el mecnismo de escpe, se pueden corregir los ejemplos nteriores:


var variable = "hola mundo, esta es \n una frase ms larga";
var variable3 = "hola 'mundo', esta es una \"frase\" ms larga";

2.4.1.7. Conversin entre tipos de variables

JvScript es un lenguje de progrmcio n "no tipado", lo que signific que un mism vrible
puede gurdr diferentes tipos de dtos lo lrgo de l ejecucio n de l pliccio n. De est form,
un vrible se podr inicilizr con un vlor nume rico, despue s podr lmcenr un cden
de texto y podr cbr l ejecucio n del progrm en form de vrible boolen.

No obstnte, en ocsiones es necesrio que un vrible lmcene un dto de un determindo


tipo. Pr segurr que s se, se puede convertir un vrible de un tipo otro, lo que se
denomin typecasting:

As, JvScript incluye un me todo llmdo toString() que permite convertir vribles de
culquier tipo vribles de cden de texto, tl y como se muestr en el siguiente ejemplo:
var variable1 = true;
variable1.toString(); // devuelve "true" como cadena de texto
var variable2 = 5;
variable2.toString(); // devuelve "5" como cadena de texto

JvScript tmbie n incluye me todos pr convertir los vlores de ls vribles en vlores


nume ricos. Los me todos definidos son parseInt() y parseFloat(), que convierten l vrible
que se le indic en un nu mero entero o un nu mero deciml respectivmente.

www.librosweb.es 16
Introduccin a AJAX Captulo 2. JavaScript bsico

L conversio n nume ric de un cden se reliz cr cter cr cter empezndo por el de l


primer posicio n. Si ese cr cter no es un nu mero, l funcio n devuelve el vlor NaN. Si el primer
cr cter es un nu mero, se continu con los siguientes crcteres mientrs estos sen nu meros.
var variable1 = "hola";
parseInt(variable1); // devuelve NaN
var variable2 = "34";
parseInt(variable2); // devuelve 34
var variable3 = "34hola23";
parseInt(variable3); // devuelve 34
var variable4 = "34.23";
parseInt(variable4); // devuelve 34

En el cso de parseFloat(), el comportmiento es el mismo slvo que tmbie n se consider


v lido el cr cter . que indic l prte deciml del nu mero:
var variable1 = "hola";
parseFloat(variable1); // devuelve NaN
var variable2 = "34";
parseFloat(variable2); // devuelve 34.0
var variable3 = "34hola23";
parseFloat(variable3); // devuelve 34.0
var variable4 = "34.23";
parseFloat(variable4); // devuelve 34.23

2.4.2. Tipos de referencia


Aunque JvScript no define el concepto de clse, los tipos de referenci se semejn ls clses
de otros lengujes de progrmcio n. Los objetos en JvScript se cren medinte l plbr
reservd new y el nombre de l clase que se v instncir. De est form, pr crer un objeto
de tipo String se indic lo siguiente (los pre ntesis solmente son obligtorios cundo se
utilizn rgumentos, unque se recomiend incluirlos incluso cundo no se utilicen):
var variable1 = new String("hola mundo");

JvScript define un clse pr cd uno de los tipos de dtos primitivos. De est form, existen
objetos de tipo Boolean pr ls vribles boolens, Number pr ls vribles nume rics y
String pr ls vribles de cdens de texto. Ls clses Boolean, Number y String
lmcenn los mismos vlores de los tipos de dtos primitivos y n den propieddes y me todos
pr mnipulr sus vlores.

Aunque m s delnte se explic en detlle, el siguiente ejemplo determin el nu mero de


crcteres de un cden de texto:
var longitud = "hola mundo".length;

L propiedd length so lo est disponible en l clse String, por lo que en principio no


deber poder utilizrse en un dto primitivo de tipo cden de texto. Sin embrgo, JvScript
convierte el tipo de dto primitivo l tipo de referenci String, obtiene el vlor de l propiedd
length y devuelve el resultdo. Este proceso se reliz de form utom tic y trnsprente pr
el progrmdor.

www.librosweb.es 17
Introduccin a AJAX Captulo 2. JavaScript bsico

En relidd, con un vrible de tipo String no se pueden hcer muchs m s coss que con
su correspondiente tipo de dto primitivo. Por este motivo, no existen muchs diferencis
pr ctics entre utilizr el tipo de referenci o el tipo primitivo, slvo en el cso del resultdo del
operdor typeof y en el cso de l funcio n eval(), como se ver m s delnte.

L principl diferenci entre los tipos de dtos es que los dtos primitivos se mnipuln por
vlor y los tipos de referenci se mnipuln, como su propio nombre indic, por referenci. Los
conceptos "por valor" y "por referencia" son igules que en el resto de lengujes de
progrmcio n, unque existen diferencis importntes (no existe por ejemplo el concepto de
puntero).

Cundo un dto se mnipul por vlor, lo u nico que import es el vlor en s. Cundo se sign
un vrible por vlor otr vrible, se copi directmente el vlor de l primer vrible en l
segund. Culquier modificcio n que se relice en l segund vrible es independiente de l
primer vrible.

De l mism form, cundo se ps un vrible por vlor un funcio n (como se explicr m s


delnte) so lo se ps un copi del vlor. As, culquier modificcio n que relice l funcio n
sobre el vlor psdo no se reflej en el vlor de l vrible originl.

En el siguiente ejemplo, un vrible se sign por vlor otr vrible:


var variable1 = 3;
var variable2 = variable1;

variable2 = variable2 + 5;
// Ahora variable2 = 8 y variable1 sigue valiendo 3

L variable1 se sign por vlor en l variable1. Aunque ls dos vribles lmcenn en ese
momento el mismo vlor, son independientes y culquier cmbio en un de ells no fect l
otr. El motivo es que los tipos de dtos primitivos siempre se signn (y se psn) por vlor.

Sin embrgo, en el siguiente ejemplo, se utilizn tipos de dtos de referenci:


var variable1 = new Date(2009, 11, 25); // variable1 = 25 diciembre de 2009
var variable2 = variable1; // variable2 = 25 diciembre de 2009

variable2.setFullYear(2010, 11, 31); // variable2 = 31 diciembre de 2010


// Ahora variable1 tambin es 31 diciembre de 2010

En el ejemplo nterior, se utiliz un tipo de dto primitivo que se ver m s delnte, que se
llm Date y que se utiliz pr mnejr fechs. Se cre un vrible llmd variable1 y
se iniciliz l fech 25 de diciembre de 2009. A continucio n, se sign el vlor de l
variable1 otr vrible llmd variable2.

Como Date es un tipo de referenci, l signcio n se reliz por referenci. Por lo tnto, ls dos
vribles quedn "unids" y hcen referenci l mismo objeto, l mismo dto de tipo Date. De
est form, si se modific el vlor de variable2 (y se cmbi su fech 31 de diciembre de
2010) el vlor de variable1 se ver utom ticmente
modificdo.

www.librosweb.es 18
Introduccin a AJAX Captulo 2. JavaScript bsico

2.4.2.1. Variables de tipo Object

L clse Object por s sol no es muy u til, y que su u nic funcio n es l de servir de bse
prtir de l cul heredn el resto de clses. Los conceptos fundmentles de los objetos son los
constructores y l propiedd prototype, tl y como se explicr n en el siguiente cptulo.

Un utilidd pr ctic de Object es l conversio n entre tipos de dtos primitivos y sus


correspondientes tipos de referenci:
var numero = new Object(5); // numero es de tipo Number
var cadena = new Object("hola mundo"); // cadena es de tipo String
var conectado = new Object(false); // conectado es de tipo Boolean

2.4.2.2. Variables de tipo Boolean

Utilizndo el tipo de referenci Boolean, es posible crer objetos de tipo lo gico o booleano:
var variable1 = new Boolean(false);

Sin embrgo, en generl no se utilizn objetos de tipo Boolean porque su comportmiento no


siempre es ide ntico l de los tipos de dtos primitivos:
var variable1 = true, variable2 = false;
var variable3 = new Boolean(false);
variable2 && variable1; // el resultado es false
variable3 && variable1; // el resultado es true

El resultdo de l u ltim opercio n es relmente sorprendente, y que se esperb un resultdo


false. El problem reside en que los objetos no se comportn igul que los tipos primitivos. En
un opercio n lo gic, culquier objeto que exist se convierte true, independientemente de su
vlor.

Por este motivo, con los vlores boolenos normlmente se utilizn tipos de dtos primitivos en
vez de objetos de tipo Boolean.

2.4.2.3. Variables de tipo Number

L clse Number permite definir vribles de tipo nume rico independientemente de si el vlor
es entero o deciml:
var variable1 = new Number(16);
var variable2 = new Number(3.141592);

Pr obtener el vlor nume rico lmcendo, se puede utilizr el me todo valueOf():


var variable1 = new Number(16);
var variable2 = variable1.valueOf(); // variable2 = 16

Uno de los me todos m s u tiles pr los nu meros es toFixed(), que trunc el nu mero de
decimles de un nu mero l vlor indicdo como pr metro:
var variable1 = new Number(3.141592);
var variable2 = variable1.toFixed(); // variable2 = 3
var variable3 = variable1.toFixed(2); // variable3 = 3.14
var variable4 = variable1.toFixed(10); // variable4 = 3.1415920000

www.librosweb.es 19
Introduccin a AJAX Captulo 2. JavaScript bsico

En ocsiones, el me todo toFixed() no funcion como deber, debido los problems que
sufren l myor de lengujes de progrmcio n con los nu meros decimles (en relidd, se
denominn "nmeros de coma flotante"):
var numero1 = new Number(0.235);
var numero2 = new Number(1.235);

numero3 = numero1.toFixed(2); // numero3 = 0.23


numero3 = numero2.toFixed(2); // numero3 = 1.24

Como se ve en el ejemplo nterior, el redondeo de los decimles no funcion de form


consistente, y que el nu mero 5 veces increment el deciml nterior y otrs veces no. De l
mism form, se pueden producir errores de precisio n en operciones prentemente sencills,
como en l siguiente multipliccio n:
var numero1 = new Number(162.295);
var numero2 = numero1 * new Number(100);

// numero2 no es igual a 16229.5


// numero2 = 16229.499999999998

Los errores de redondeo fectn de l mism form ls vribles nume rics creds con tipos
de dtos primitivos. En culquier cso, l igul que sucede con Boolean, se recomiend utilizr el
tipo de dto primitivo pr los nu meros, y que l clse Number no port mejors significtivs.

2.4.2.4. Variables de tipo String

L clse String represent un cden de texto, de form similr los tipos de dtos
primitivos:
var variable1 = new String("hola mundo");

El objeto de tipo String es el m s complejo de JvScript y contiene decens de me todos y


utiliddes, lgunos de los cules se ver n m s delnte. Como y se h comentdo, siempre que
se necesrio JvScript convierte de form utom tic ls cdens de texto de dto primitivo
dto de referenci. De est form, no es obligtorio crer objetos de tipo String pr cceder
tods ls utiliddes disponibles pr ls cdens de texto.

2.4.2.5. Operador instanceof

El operdor typeof no es suficiente pr trbjr con tipos de referenci, y que devuelve el


vlor object pr culquier objeto independientemente de su tipo. Por este motivo, JvScript
define el operdor instanceof pr determinr l clse concret de un objeto.
var variable1 = new String("hola mundo");
typeof variable1; // devuelve "object"
instanceof String; // devuelve true

El operdor instanceof so lo devuelve como vlor true o false. De est form, instanceof
no devuelve directmente l clse de l que h instncido l vrible, sino que se debe
comprobr cd posible tipo de clse individulmente.

www.librosweb.es 20
Introduccin a AJAX Captulo 2. JavaScript bsico

2.5. Operadores
Ls vribles so lo se pueden utilizr pr lmcenr informcio n. Sin embrgo, es muy hbitul
que los progrms tengn que mnipulr l informcio n originl pr trnsformrl en otr
informcio n. Los operdores son los elementos b sicos que se utilizn pr modificr el vlor de
ls vribles y pr combinr vrios vlores entre s pr obtener otro vlor.

JvScript define numerosos operdores, entre los que se encuentrn los operdores
mtem ticos (sum, rest, multipliccio n, divisio n) y los operdores lo gicos utilizdos pr
relizr comprciones (myor que, igul, menor que).

2.5.1. Operador de asignacin


El operdor de signcio n es el m s utilizdo y el m s sencillo. Simplemente se utiliz pr
signr un vrible un vlor especfico. El smbolo utilizdo es = (no confundir con el
operdor ==):
var numero1 = 3;
var variable1 = "hola mundo";

2.5.2. Operadores de incremento y decremento


Solmente son v lidos pr ls vribles nume rics y son un me todo sencillo de incrementr o
decrementr en 1 unidd el vlor de un vrible, tl y como se muestr en el siguiente ejemplo:
var numero = 5;
++numero;
alert(numero); // numero = 6

El nterior ejemplo es equivlente :


var numero = 5; numero =
numero + 1; alert(numero);
// numero = 6

De l mism form, el operdor -- se utiliz pr decrementr el vlor de l


vrible:
var numero = 5;
--numero;
alert(numero); // numero = 4

Como y se supone, el nterior ejemplo es equivlente :


var numero = 5; numero =
numero - 1; alert(numero);
// numero = 4

Adem s de estos dos operdores, existen otros dos operdores similres pero que se diferencin
en l form en l que se reliz el incremento o decremento. En el siguiente ejemplo:
var numero = 5;
numero++;
alert(numero); // numero = 6

www.librosweb.es 21
Introduccin a AJAX Captulo 2. JavaScript bsico

El resultdo es el mismo que ntes y puede precer que es equivlente n dir el operdor ++
delnte o detr s del identificdor de l vrible. Sin embrgo, el siguiente ejemplo muestr sus
diferencis:
var numero1 = 5;
var numero2 = 2;
numero3 = numero1++ + numero2;
// numero3 = 7, numero1 = 6

var numero1 = 5;
var numero2 = 2;
numero3 = ++numero1 + numero2;
// numero3 = 8, numero1 = 6

Si el operdor ++ se indic como prefijo del identificdor de l vrible, su vlor se


increment ntes de relizr culquier otr opercio n. Si el operdor ++ se indic como
sufijo del identificdor de l vrible, su vlor se increment despue s de ejecutr l sentenci en
l que prece.

2.5.3. Operadores lgicos

2.5.3.1. Negacin

Uno de los operdores lo gicos m s utilizdos es el de l negcio n. Se utiliz pr obtener el vlor


lo gico contrrio l vlor de l vrible:
var visible = true;
alert(!visible); // Muestra 'false' y no 'true'

L negcio n lo gic se obtiene prefijndo el smbolo ! l identificdor de l vrible. Cundo


l vrible es de tipo booleno, obtener su vlor lo gico contrrio es trivil:

variable !variable
true false
false true

Por el contrrio, si l vrible lmcen un nu mero o un cden de texto, no se puede obtener


su vlor lo gico contrrio de form direct. En este cso, JvScript convierte previmente l
vrible un vlor lo gico y despue s obtiene su vlor contrrio.

Si l vrible originl contiene un nu mero, su trnsformcio n en vrible lo gic es false si el


nu mero es 0 y true en culquier otro cso. Si l vrible originl contiene un cden de
texto, su trnsformcio n en vrible lo gic es false si l cden no contiene ningu n cr cter y
true en culquier otro cso:

var cantidad = 0;
vacio = !cantidad; // vacio = true
cantidad = 2;
vacio = !cantidad; // vacio = false

var mensaje = "";

www.librosweb.es 22
Introduccin a AJAX Captulo 2. JavaScript bsico

sinMensaje = !mensaje; // sinMensaje = true


mensaje = "hola mundo";
sinMensaje = !mensaje; // sinMensaje = false

2.5.3.2. AND

L opercio n lo gic AND combin dos vlores boolenos pr obtener como resultrdo otro
vlor de tipo lo gico. El resultdo de l opercio n solmente es true si los dos operndos son
true. El operdor se indic medinte el smbolo &&:

variable1 variable2 variable1 && variable2


true true true
true false false
false true false
false false false

El siguiente ejemplo muestr co mo combinr vlores medinte el operdor &&:


var valor1 = true;
var valor2 = false;
resultado = valor1 && valor2; // resultado = false
valor1 = true;
valor2 = true;
resultado = valor1 && valor2; // resultado = true

2.5.3.3. OR

L opercio n lo gic OR tmbie n combin dos vlores boolenos pr obtener como resultdo
otro vlor de tipo lo gico. El resultdo de l opercio n es true si lguno de los dos operndos
es true. El operdor se indic medinte el smbolo ||:

variable1 variable2 variable1 || variable2


true true true
true false true
false true true
false false false

El siguiente ejemplo muestr co mo combinr vlores medinte el operdor ||:


var valor1 = true;
var valor2 = false;
resultado = valor1 || valor2; // resultado = true
valor1 = false;
valor2 = false;
resultado = valor1 || valor2; // resultado = false

www.librosweb.es 23
Introduccin a AJAX Captulo 2. JavaScript bsico

2.5.4. Operadores matemticos


JvScript permite relizr mnipulciones mtem tics sobre el vlor de ls vribles
nume rics. Los operdores definidos son: sum ( +), rest (-), multipliccio n (*) y divisio n (/).
Ejemplo:
var numero1 = 10;
var numero2 = 5;
resultado = numero1 / numero2; // resultado = 2
resultado = 3 + numero1; // resultado = 13
resultado = numero2 4; // resultado = 1
resultado = numero1 * numero 2; // resultado = 50

Uno de los operdores mtem ticos m s singulres cundo se estudi por primer vez es el
mdulo, que clcul el resto de l divisio n enter. Si se divide 10 entre 5, l divisio n es exct y
d un resultdo de 2. El resto de es divisio n es 0, por lo que "mdulo de 10 y 5" es igul 0.

Sin embrgo, si se divide 9 y 5, l divisio n no es exct, el resultdo es 1 y el resto es 4, por lo


que
"mdulo de 9 y 5" es igul 4.

El mo dulo en JvScript se indic medinte el smbolo %, que no debe confundirse con el


porcentje:
var numero1 = 10;
var numero2 = 5;
resultado = numero1 % numero2; // resultado = 0
numero1 = 9;
numero2 = 5;
resultado = numero1 % numero2; // resultado = 4

Aunque el operdor mo dulo prece demsido extrn o como pr ser u til, en muchs
plicciones web reles se utiliz pr relizr lguns te cnics hbitules, tl y como se ver
m s delnte.

Los operdores mtem ticos se pueden combinr con el operdor de sgincio n pr escribir de
form brevid lguns operciones comunes:
var numero1 = 5;
numero1 += 3; // numero1 = numero1 + 3 = 8
numero1 -= 1; // numero1 = numero1 - 1 = 4
numero1 *=2; // numero1 = numero1 * 2 = 10
numero1 /= 2; // numero1 = numero1 / 2 = 2.5
numero1 %= 3; // numero1 = numero1 % 3 = 2

2.5.5. Operadores relacionales


Los operdores relcionles definidos por JvScript son ide nticos los definidos por ls
mtem tics: myor que (>), menor que (<), myor o igul (>=), menor o igul (<=), igul (==) y
distinto (!=).

El resultdo de tods ests operciones siempre es un vlor booleno:


var numero1 = 3;
var numero2 = 5;
www.librosweb.es 24
Introduccin a AJAX Captulo 2. JavaScript bsico

resultado = numero1 > numero2; // resultado = false


resultado = numero1 < numero2; // resultado = true
numero1 = 5;
numero2 = 5;
resultado = numero1 >= numero2; // resultado = true
resultado = numero1 <= numero2; // resultado = true
resultado = numero1 == numero2; // resultado = true
resultado = numero1 != numero2; // resultado = false

El operdor == es l myor fuente de errores de progrmcio n incluso pr los usurios que y


tienen ciert experienci desrrollndo scripts. Si se quiere comprr el vlor de dos vribles,
no se debe utilizr el operdor =:
var numero1 = 5;
resultado = numero1 = 3; // numero1 = 3 y resultado = 3

Pr comprr vlores, se debe utilizr el operdor == (con dos signos de


igul):
var numero1 = 5;
resultado = numero1 == 3; // numero1 = 5 y resultado = false

Adem s de ls vribles nume rics, tmbie n se pueden utilizr vribles de tipo cden de texto
con los operdores relcionles:
var texto1 = "hola";
var texto2 = "hola";
var texto3 = "adios";
resultado = texto1 == texto3; // resultado = false
resultado = texto1 != texto2; // resultado = false
resultado = texto3 >= texto2; // resultado = false

Cundo se comprn cdens de texto con los operdores > y <, el resultdo obtenido puede
ser poco intuitivo. JvScript compr letr letr comenzndo desde l izquierd hst que se
encuentre un diferenci entre ls dos letrs. Pr determinr si un letr es myor o menor que
otr, se consider que:
A < B < ... < Z < a < b < ... < z

Adem s de los operdores b sicos de iguldd, tmbie n existen los operdores "idntico"
(tmbie n llmdo "exactamente igual") y "no idntico" (tmbie n llmdo "no exactamente
igual"). Cundo se utilizn estos operdores, no so lo se comprn los vlores que lmcenn ls
vribles, sino que tmbie n se compr el tipo de cd vrible.
var variable1 = 10;
var variable2 = "10";
variable1 == variable2; // devuelve true
variable1 === variable2; // devuelve false

El operdor "idntico" se indic medinte tres signos de iguldd (===) y devuelve true
solmente si los dos operndos son exctmente igules sin necesidd de relizr ningun
conversio n. En el ejemplo nterior, l primer vrible es de tipo nume rico y su vlor es 10,
mientrs que l segund vrible es de tipo cden de texto y su vlor es "10".

www.librosweb.es 25
Introduccin a AJAX Captulo 2. JavaScript bsico

Si se utiliz el operdor ==, JvScript convierte utom ticmente el tipo de ls vribles pr


relizr l comprcio n. Al convertir l cden de texto en vrible nume ric, se obtiene el vlor
10, por lo que los dos vlores que se comprn son igules y el resultdo de l opercio n es true.

Sin embrgo, en el cso del operdor "idntico", ls dos vribles tienen que ser dem s del
mismo tipo. Como l primer vrible es de tipo nume rico y l segund es un cden de texto,
unque sus vlores son igules, el resultdo de l opercio n es false.

El operdor "no idntico" tiene un funcionmiento equivlente y se indic medinte los


crcteres !==

2.6. Objetos nativos de JavaScript


JvScript define lgunos objetos de form ntiv, por lo que pueden ser utilizdos directmente
por los plicciones sin tener que declrrlos. Adem s de ls clses de tipo Object, Number,
Boolean y String que y se hn visto, JvScript define otrs clses como Function, Array,
Date y RegExp.

2.6.1. La clase Array


JvScript permite definir los rrys de form brevid (como se ver en el cptulo de
JvScript vnzdo) y tmbie n de form trdicionl medinte l clse Array:
var variable1 = new Array();

Si l instncir l clse Array() se ps un u nico rgumento y es de tipo nume rico, se cre


un rry con el nu mero de elementos indicdo:
var variable1 = new Array(10);

En el primer ejemplo, l variable1 simplemente cre un rry vco, mientrs que el segundo
ejemplo cre un rry de 10 elementos que todv no est n definidos. Los elementos de un
rry no tienen por que ser todos del mismo tipo. Adem s, si l declrr el rry se conocen los
elementos que v contener, es posible incluirlos en l declrcio n del rry:
var variable1 = new Array(2, "hola", true, 45.34);

Otr form hbitul de n dir nuevos elementos l rry es medinte l notcio n con corchetes
que tmbie n se utiliz en otros lengujes de progrmcio n:
var variable1 = new Array();
variable1[0] = 2;
variable1[1] = "hola";
variable1[2] = true;
variable1[3] = 45.34;

El primer elemento del rry siempre ocup l posicio n 0 (cero) y el tmn o del rry
ument de form din mic medid que se n den nuevos elementos.

Los rrys contienen decens de propieddes y me todos muy u tiles pr mnipulr sus
contenidos y relizr operciones complejs, tl y como se ver m s delnte.

www.librosweb.es 26
Introduccin a AJAX Captulo 2. JavaScript bsico

2.6.2. La clase Date


Entre ls utiliddes que proporcion JvScript, se encuentr l clse Date que permite
representr y mnipulr vlores relciondos con fechs. Pr obtener l representcio n de l
fech ctul, so lo es necesrio instncir l clse sin pr metros:
var fecha = new Date();

Adem s de l fech, l instruccio n nterior represent l hor en l que h sido ejecutd l


instruccio n. Internmente, y como sucede en otros lengujes de progrmcio n y otros sistems,
l fech y hor se lmcen como el nu mero de milisegundos que hn trnscurrido desde el 1 de
Enero de 1970 ls 00:00:00. Por este motivo, se puede construir un fech culquier
indicndo el nu mero de milisegundos prtir de es referenci temporl:
var fecha = new Date(0); // "Thu Jan 01 1970 01:00:00 GMT+0100"
var fecha = new Date(10000000000000); // "Sat Nov 20 2286 18:46:40 GMT+0100"

Afortundmente, existen otrs forms m s sencills de estblecer l fech y hor que se vn


utilizr:
var fecha = new Date(2009, 5, 1); // 1 de Junio de 2009 (00:00:00)
var fecha = new Date(2009, 5, 1, 19, 29, 39); // 1 de Junio de 2009 (19:29:39)

El constructor de l clse Date permite estblecer so lo un fech o l fech y hor l vez. El


formto es (ao, mes, dia) o (ao, mes, dia, hora, minuto, segundo). Los meses se
indicn medinte un vlor nume rico que empiez en el 0 (Enero) y termin en el 11
(Diciembre). Los ds del mes se cuentn de form nturl desde el d 1 hst el 28, 29, 30 o
31 dependiendo de cd mes.

A continucio n se muestrn lgunos de los me todos m s u tiles disponibles pr l clse Date:

getTime() devuelve un nu mero que represent l fech como el nu mero de


milisegundos trnscurridos desde l referenci de tiempos (1 de Enero de 1970).
getMonth() devuelve el nu mero del mes de l fech (empezndo por 0 pr Enero
y cbndo en 11 pr Diciembre)

getFullYear() devuelve el n o de l fech como un nu mero de 4 cifrs.

getYear() devuelve el n o de l fech como un nu mero de 2 cifrs.

getDate() devuelve el nu mero del d del mes.

getDay() devuelve el nu mero del d de l semn (0 pr Domingo, 1 pr Lunes, ..., 6


pr S bdo)
getHours(), getMinutes(), getSeconds(), getMilliseconds() devuelve
respectivmente ls hors, minutos, segundos y milisegundos de l hor correspondiente
l fech.

Cd me todo get() mostrdo nteriormente tiene su correspondiente me todo set() que


permite estblecer el vlor de cd un de ls propieddes.

www.librosweb.es 27
Introduccin a AJAX Captulo 2. JavaScript bsico

2.6.3. La clase Function


L clse Function rrmente se utiliz de form explcit pr crer funciones. Utilizd de
est form, se deben indicr todos los pr metros de l funcio n y sus instrucciones como
pr metros l instncir l clse:
var miFuncion = new Function("a", "b", "return a+b;");

El u ltimo rgumento de l llmd se consider como ls instrucciones de l funcio n y todos los


nteriores son los rgumentos de l mism. En cunto se complic un poco el co digo de l
funcio n, este me todo se hce invible.

2.7. Funciones
Ls funciones de JvScript no suelen definirse medinte l clse Function, sino que se cren
medinte l plbr reservd function:
function suma(a, b) {
return a+b;
}

No es obligtorio que ls funciones tengn un instruccio n de tipo return pr devolver vlores.


De hecho, cundo un funcio n no devuelve ningu n vlor o cundo en l instruccio n return no
se indic ningu n vlor, utom ticmente se devuelve el vlor undefined.

Pr llmr l funcio n en culquier instruccio n, se indic su nombre junto con l list de


pr metros esperdos:
var resultado = suma(2, 3);

Los pr metros que se psn pueden estr definidos medinte operciones que se evlu n ntes
de psrlos l funcio n:
var resultado = suma(2+1, 3-4*3+4);

Como JvScript no define tipos de vribles, no es posible segurr que los pr metros que se
psn un funcio n sen los del tipo decudo pr ls operciones que reliz l funcio n.

Si un funcio n se le psn m s pr metros que los que h definido, los pr metros sobrntes
se ignorn. Si se psn menos pr metros que los que h definido l funcio n, l resto de
pr metros hst completr el nu mero correcto se les sign el vlor undefined.

Un funcio n puede contener en su interior otrs funciones nidds:


function sumaCuadrados(a, b) {
function cuadrado(x) { return x*x; }
return cuadrado(a) + cuadrado(b);
}

L funcio n nterior clcul l sum del cudrdo de dos nu meros. Pr ello, define en el interior
de l funcio n otr funcio n que clcul el cudrdo del nu mero que se le ps. Pr obtener el
resultdo finl, l funcio n sumaCuadrados() hce uso de l funcio n nidd cuadrado().

www.librosweb.es 28
Introduccin a AJAX Captulo 2. JavaScript bsico

Ls funciones tmbie n se pueden crer medinte lo que se conoce como "function literals" y que
consiste en definir l funcio n con un expresio n en l que el nombre de l funcio n es opcionl.
Debido est u ltim crcterstic, tmbie n se conocen como funciones annimas. A
continucio n se muestr un mism funcio n definid medinte el me todo trdicionl y medinte
un funcio n no nim:
function suma(a, b) {
return a+b;
}

var miFuncion = function(a, b) { return a+b; }

Ls funciones no nims son ideles pr los csos en los que se necesit definir funciones
sencills que so lmente se utilizn un vez y pr ls que no es necesrio crer un funcio n
trdicionl con nombre. M s delnte en el cptulo de JvScript vnzdo se muestr en
detlle el uso de funciones no nims con objetos.

Como se h comentdo, cundo un funcio n recibe menos pr metros de los que necesit,
iniciliz el vlor del resto de pr metros undefined. De est form, puede ser necesrio
proteger l pliccio n frente posibles vlores incorrectos en sus pr metros. El me todo
hbitul es relizr un comprobcio n sencill:
function suma(a, b) {
if(isNaN(b)) {
b = 0;
}
return a + b;
}

L funcio n del ejemplo nterior comprueb que b se un nu mero pr poder relizr


correctmente l sum. En cso de que no lo se (es decir, que se null, undefined o culquier
vlor v lido distinto de un nu mero) se le sign el vlor 0 pr que l funcio n pued devolver un
resultdo v lido.

JvScript permite prescindir de l comprobcio n nterior y obtener el mismo resultdo


medinte el siguiente truco que hce uso del operdor OR (||):
function suma(a, b) {
b = b || 0;
return a + b;
}

En el ejemplo nterior, si l funcio n no se le ps el pr metro b, utom ticmente se sign el


vlor 0 ese pr metro. El truco funcion porque el comportmiento del operdor lo gico OR
(y tmbie n el del operdor AND) es m s complejo de lo que se h explicdo nteriormente.

En relidd, el operdor lo gico OR funcion de l siguiente


mner:

1. Si el primer operndo es true o culquier otro vlor que se puede trnsformr en


true, se devuelve directmente el vlor de ese operndo.
2. En otro cso, se evlu el segundo operndo y se devuelve directmente su vlor.

www.librosweb.es 29
Introduccin a AJAX Captulo 2. JavaScript bsico

Por lo tnto:
alert(true || false); // muestra true
alert(3 || false); // muestra 3
alert(true || 5); // muestra true
alert(false || true); // muestra true
alert(false || 5); // muestra 5
alert(3 || 5); // muestra 3

De est form, si se utilizn ls siguientes llmds l funcio n:


suma(3);
suma(3, null);
suma(3, false);

En todos los csos nteriores l vrible b vle 0. Si no se indic un pr metro, su vlor es


undefined, que se trnsform en false y por tnto el resultdo de b || 0 es 0. Si se indic
null como vlor del pr metro, tmbie n se trnsform en false, por lo que nuevmente el
resultdo de b || 0 es 0. Por u ltimo, si se indic directmente el vlor false l
pr metro, tmbie n provoc que el resultdo de b || 0 se 0. En culquier otro cso, el
pr metro b vldr lo mismo que se l hy psdo en l llmd l funcio n.

Como el nu mero de rgumentos que se psn un funcio n de JvScript puede ser vrible e
independiente del nu mero de pr metros incluidos en su definicio n, JvScript proporcion un
vrible especil que contiene todos los pr metros con los que se h invocdo l funcio n. Se
trt de un rry que se llm arguments y solmente est definido dentro de culquier funcio n.
function suma(a, b)
{ alert(arguments.length
); alert(arguments[2]);
return a + b;
}

suma(3, 5);

L propiedd arguments.length devuelve el nu mero de pr metros con los que se h llmdo


l funcio n. En el cso del ejemplo nterior, se mostrr el vlor 2. Como arguments es un
rry, se puede cceder directmente culquier pr metro medinte l notcio n trdicionl de
los rrys. En este cso, el vlor arguments[2] devuelve undefined, y que l funcio n se llm
con dos pr metros y por tnto el tercer pr metro no est definido.

El rry arguments permite crer funciones con un nu mero vrible de


rgumentos:
function mayor() {
var elMayor = arguments[0];
for(var i=1; i<arguments.length; i++) {
if(arguments[i] > elMayor) {
elMayor = arguments[i];
}
}
return elMayor;
}

www.librosweb.es 30
Introduccin a AJAX Captulo 2. JavaScript bsico

var variable1 = mayor(1, 3, 5, 8);


var variable2 = mayor(4, 6, 8, 1, 2, 3, 4, 5);

Te cnicmente, arguments no es un rry, sino que es un objeto de tipo Arguments. Sin embrgo,
por sus propieddes y sus me todos de cceso, se puede considerr como si fuer un rry.

Un u ltim propiedd del objeto arguments que no suele utilizrse hbitulmente, pero que
puede ser necesri en ocsiones es l propiedd callee. L propiedd callee hce referenci
l funcio n que se est ejecutndo. En el siguiente ejemplo se utiliz l propiedd callee
pr mostrr el co digo fuente de l funcio n que se est ejecutndo:
function suma(a, b)
{ alert(arguments.callee
); return a + b;
}

suma(3, 5);

L propiedd callee se puede utilizr pr determinr el nu mero de pr metros que esper l


funcio n:
function suma(a, b)
{ alert(arguments.callee.length
); alert(arguments.length);
return a + b;
}

suma(3, 5, 7, 9);

L propiedd arguments.callee.length indic el nu mero de pr metros que se incluyen en l


definicio n de l funcio n, en este cso 2. Como se h visto nteriormente, l propiedd
arguments.length indic el nu mero de pr metros con los que se h llmdo l funcio n, en
este cso 4.

2.8. Funciones y propiedades bsicas de JavaScript


JvScript incluye numeross propieddes y me todos muy u tiles pr cd uno de los tipos de
vribles y clses que define.

2.8.1. Cadenas de texto


A continucio n se muestrn lguns de ls funciones m s u tiles pr el mnejo de cdens de
texto:

length, clcul l longitud de un cden de texto (el nu mero de crcteres que l formn)

var mensaje = "Hola Mundo";


var numeroLetras = mensaje.length; // numeroLetras = 10

+, se emple pr conctenr vris cdens de texto.

www.librosweb.es 31
Introduccin a AJAX Captulo 2. JavaScript bsico

var mensaje1 = "Hola";


var mensaje2 = " Mundo";
var mensaje = mensaje1 + mensaje2; // mensaje = "Hola Mundo"

Adem s del operdor +, tmbie n se puede utilizr l funcio n concat()


var mensaje1 = "Hola";
var mensaje2 = mensaje1.concat(" Mundo"); // mensaje2 = "Hola Mundo"

Ls cdens tmbie n se pueden unir con vribles nume rics:


var variable1 = "Hola ";
var variable2 = 3;
var mensaje = variable1 + variable2; // mensaje = "Hola 3"

Cundo se unen vris cdens de texto es hbitul olvidr n dir un espcio de seprcio n
entre ls plbrs:
var mensaje1 = "Hola";
var mensaje2 = "Mundo";
var mensaje = mensaje1 + mensaje2; // mensaje = "HolaMundo"

Los espcios en blnco se pueden n dir l finl o l principio de ls cdens o indicrlos de


form explcit:
var mensaje1 = "Hola";
var mensaje2 = "Mundo";
var mensaje = mensaje1 + " " + mensaje2; // mensaje = "Hola Mundo"

toUpperCase(), trnsform todos los crcteres de l cden sus correspondientes crcteres


en myu sculs:
var mensaje1 = "Hola";
var mensaje2 = mensaje1.toUpperCase(); // mensaje2 = "HOLA"

toLowerCase(), trnsform todos los crcteres de l cden sus correspondientes crcteres


en minu sculs:
var mensaje1 = "HolA";
var mensaje2 = mensaje1.toLowerCase(); // mensaje2 = "hola"

charAt(posicion), obtiene el cr cter que se encuentr en l posicio n indicd:

var mensaje = "Hola";


var letra = mensaje.charAt(0); // letra = H
letra = mensaje.charAt(2); // letra = l

indexOf(letra), clcul l primer posicio n en l que se encuentr el cr cter indicdo dentro


de l cden de texto. Si l cden no contiene el cr cter, l funcio n devuelve el vlor -1:
var mensaje = "Hola";
var posicion = mensaje.indexOf('a'); // posicion = 3
posicion = mensaje.indexOf('b'); // posicion = -1

L funcio n indexOf() comienz su bu squed desde el principio de l plbr y solo devuelve


l primer posicio n de tods ls existentes. Su funcio n n log es lastIndexOf().

www.librosweb.es 32
Introduccin a AJAX Captulo 2. JavaScript bsico

lastIndexOf(letra), clcul l u ltim posicio n en l que se encuentr el cr cter indicdo


dentro de l cden de texto. Si l cden no contiene el cr cter, l funcio n devuelve el vlor -1:
var mensaje = "Hola";
var posicion = mensaje.lastIndexOf(a); // posicion = 3
posicion = mensaje.lastIndexOf(b); // posicion = -1

L funcio n lastIndexOf() comienz su bu squed desde el finl de l cden hci el


principio, unque l posicio n devuelt es l correct empezndo contr desde el principio de l
plbr.

substring(inicio, final), extre un porcio n de un cden de texto. El segundo pr metro


es opcionl. Si solo se indic el pr metro inicio, l funcio n devuelve l prte de l cden
originl correspondiente desde es posicio n hst el finl:
var mensaje = "Hola Mundo";
var porcion = mensaje.substring(2); // porcion = "la Mundo"
porcion = mensaje.substring(5); // porcion = "Mundo"
porcion = mensaje.substring(7); // porcion = "ndo"

Si se indic un inicio negtivo, se devuelve l mism cden originl:


var mensaje = "Hola Mundo";
var porcion = mensaje.substring(-2); // porcion = "Hola Mundo"

Si se indic el inicio y el finl, se devuelve l prte de l cden originl comprendid entre l


posicio n inicil y l inmeditmente nterior l posicio n finl (es decir, l posicio n inicio est
incluid y l posicio n finl no):
var mensaje = "Hola Mundo";
var porcion = mensaje.substring(1, 8); // porcion = "ola Mun"
porcion = mensaje.substring(3, 4); // porcion = "a"

Si se indic un finl m s pequen o que un inicio, JvScript los consider de form invers, y que
utom ticmente sign el vlor m s pequen o l inicio y el m s grnde l finl:
var mensaje = "Hola Mundo";
var porcion = mensaje.substring(5, 0); // porcion = "Hola "
porcion = mensaje.substring(0, 5); // porcion = "Hola "

split(separador), convierte un cden de texto en un rry de cdens de texto. L funcio n


prte un cden de texto dividiendo sus trozos prtir del cr cter delimitdor indicdo:
var mensaje = "Hola Mundo, soy una cadena de texto!";
var palabras = mensaje.split(" ");
// palabras = ["Hola", "Mundo,", "soy", "una", "cadena", "de", "texto!"];

Con est funcio n se pueden extrer f cilmente ls letrs que formn un plbr:
var palabra = "Hola";
var letras = palabra.split(""); // letras = ["H", "o", "l", "a"]

2.8.2. Arrays
A continucio n se muestrn lguns de ls funciones m s u tiles pr el mnejo de rrys:

length, clcul el nu mero de elementos de un rry:


www.librosweb.es 33
Introduccin a AJAX Captulo 2. JavaScript bsico

var vocales = ["a", "e", "i", "o", "u"];


var numeroVocales = vocales.length; // numeroVocales = 5

concat(), se emple pr conctenr los elementos de vrios rrys:

var array1 = [1, 2, 3];


array2 = array1.concat(4, 5, 6); // array2 = [1, 2, 3, 4, 5, 6]
array3 = array1.concat([4, 5, 6]); // array3 = [1, 2, 3, 4, 5, 6]

join(separador), es l funcio n contrri split(). Une todos los elementos de un rry pr


formr un cden de texto. Pr unir los elementos se utiliz el cr cter separador:
var array = ["hola", "mundo"];
var mensaje = array.join(""); // mensaje = "holamundo"
mensaje = array.join(" "); // mensaje = "hola mundo"

pop(), elimin el u ltimo elemento del rry y lo devuelve. El rry originl se modific y su
longitud disminuye un unidd.
var array = [1, 2, 3];
var ultimo = array.pop();
// ahora array = [1, 2]

push(), n de un elemento l finl del rry. El rry originl se modific y ument su longitud
un unidd. Tmbie n es posible n dir m s de un elemento l vez.
var array = [1, 2, 3];
array.push(4);
// ahora array = [1, 2, 3, 4]

shift(), elimin el primer elemento del rry y lo devuelve. El rry originl se modific y su
longitud disminuye un unidd.
var array = [1, 2, 3];
var primero = array.shift();
// ahora array = [2, 3]

unshift(), n de un elemento l principio del rry. El rry originl se modific y ument su


longitud en un unidd. Tmbie n es posible n dir m s de un elemento l vez.
var array = [1, 2, 3];
array.unshift(0);
// ahora array = [0, 1, 2, 3]

reverse(), modific un rry colocndo sus elementos en el orden inverso su posicio n


originl:
var array = [1, 2, 3];
array.reverse();
// ahora array = [3, 2, 1]

www.librosweb.es 34
Introduccin a AJAX Captulo 3. JavaScript avanzado

Captulo 3. JavaScript avanzado


3.1. Objetos
Al igul que sucede con otros lengujes de progrmcio n, los objetos se emplen en JvScript
pr orgnizr el co digo fuente de un form m s clr y pr encpsulr me todos y funciones
comunes. L form m s sencill de crer un objeto es medinte l plbr reservd new
seguid del nombre de l clse que se quiere instncir:
var elObjeto = new Object();
var laCadena = new String();

El objeto laCadena credo medinte el objeto ntivo String permite lmcenr un cden
de texto y provechr tods ls herrmients y utiliddes que proporcion JvScript pr su
mnejo. Por otr prte, l vrible elObjeto lmcen un objeto gene rico de JvScript, l que
se pueden n dir propieddes y me todos propios pr definir su comportmiento.

3.1.1. Definicin de un objeto


Te cnicmente, un objeto de JvScript es un rry socitivo formdo por ls propieddes y los
me todos del objeto. As, l form m s direct pr definir ls propieddes y me todos de un
objeto es medinte l notacin de puntos de los rrys socitivos.

Un rry socitivo es quel en el que cd elemento no est socido su posicio n nume ric
dentro del rry, sino que est socido otro vlor especfico. Los vlores de los rrys
normales se socin ndices que siempre son nume ricos. Los vlores de los rrys socitivos
se socin clves que siempre son cdens de texto.

L form trdicionl de definir los rrys socitivos es medinte l clse Array:


var elArray = new Array();
elArray['primero'] = 1;
elArray['segundo'] = 2;

alert(elArray['primero']);
alert(elArray[0]);

El primer alert() muestr el vlor 1 correspondiente l vlor socido con l clve primero.
El segundo alert() muestr undefined, y que como no se trt de un rry normal, sus
elementos no se pueden cceder medinte su posicio n nume ric.

Afortundmente, existen me todos lterntivos brevidos pr crer rry socitivos. El


ejemplo nterior se puede rehcer de l siguiente form:
var elArray = new Array();
elArray.primero = 1;
elArray.segundo = 2;

alert(elArray['primero']);

www.librosweb.es 35
Introduccin a AJAX Captulo 3. JavaScript avanzado

alert(elArray.primero);
alert(elArray[0]);

El me todo seguido en el ejemplo nterior pr crer el rry socitivo se denomin "notacin


de puntos". Pr cceder y/o estblecer cd vlor, se indic el nombre del rry seguido de un
punto y seguido del nombre de cd clve. De form gene ric, l notcio n de puntos tiene el
siguiente formto:
nombreArray.nombreClave = valor;

Pr cceder un determindo vlor, tmbie n se puede utilizr l notcio n de puntos en vez de


l trdicionl notcio n de los rrys, de form que ls dos instrucciones siguientes son
equivlentes:
elArray['primero'];
elArray.primero;

M s delnte se muestr otr form u n m s brevid y direct de estblecer el vlor tnto de


los rrys "normales" como de los rrys socitivos.

3.1.1.1. Propiedades

Como los objetos son en relidd rrys socitivos que lmcenn sus propieddes y me todos,
l form m s direct pr definir ess propieddes y me todos es l notcio n de puntos:
elObjeto.id = "10";
elObjeto.nombre = "Objeto de prueba";

Al contrrio de lo que sucede en otros lengujes orientdos objetos, como por ejemplo Jv,
pr signr el vlor de un propiedd no es necesrio que l clse teng definid previmente
es propiedd.

Tmbie n es posible utilizr l notcio n trdicionl de los rrys pr definir el vlor de ls


propieddes:
elObjeto['id'] = "10";
elObjeto['nombre'] = "Objeto de prueba";

3.1.1.2. Mtodos

Adem s de ls propieddes, los me todos de los objetos tmbie n se pueden definir medinte l
notcio n de puntos:
elObjeto.muestraId = function() {
alert("El ID del objeto es " + this.id);
}

Los me todos se definen signndo funciones l objeto. Si l funcio n no est definid


previmente, es posible crer un funcio n no nim pr signrl l nuevo me todo del objeto,
tl y como muestr el ejemplo nterior.

Uno de los spectos m s importntes del ejemplo nterior es el uso de l plbr reservd this.
L plbr this se suele utilizr hbitulmente dentro de los me todos de un objeto y siempre
hce referenci l objeto que est llmdo ese me todo.

www.librosweb.es 36
Introduccin a AJAX Captulo 3. JavaScript avanzado

De est form, en el ejemplo nterior:


var elObjeto = new Object();
elObjeto.id = "10";
elObjeto.muestraId = function() {
alert("El ID del objeto es " + this.id);
}

Dentro del me todo, this punt l objeto que llm ese me todo. En este cso, this hce
referenci elObjeto. Por tnto, l instruccio n del me todo muestraId es equivlente indicr:
alert("El ID del objeto es " + elObjeto.id);

El uso de this es imprescindible pr crer plicciones reles. El motivo es que nunc se


puede suponer el nombre que tendr l vrible (el objeto) que incluye ese me todo. Como los
progrmdores pueden elegir libremente el nombre de cd objeto, no hy form de segurr
que l siguiente instruccio n funcione siempre correctmente:
alert("El ID del objeto es " + elObjeto.id);

Si el objeto se llmr otroObjeto, el co digo nterior no funcionr correctmente. Sin


embrgo, utilizndo l plbr reservd this, el me todo funcion siempre bien
independientemente del nombre del objeto.

Adem s, l plbr this se debe utilizr siempre que se quier cceder un propiedd de
un objeto, y que en otro cso, no se est ccediendo correctmente l propiedd:
var elObjeto = new Object();
elObjeto.id = "10";
elObjeto.muestraId = function() {
alert("El ID del objeto es "+ id);
}

Si se ejecut el ejemplo nterior, se muestr el error "id is not defined" (la variable id no
est definida).

Adem s de ls funciones no nims, tmbie n es posible signr los me todos de un objeto


funciones definids con nterioridd:
function obtieneId() {
return this.id;
}

elObjeto.obtieneId = obtieneId;

Pr signr un funcio n extern l me todo de un objeto, so lo se debe indicr el nombre de l


funcio n extern sin pre ntesis. Si se utilizrn los pre ntesis:
function obtieneId() {
return this.id;
}

elObjeto.obtieneId = obtieneId();

www.librosweb.es 37
Introduccin a AJAX Captulo 3. JavaScript avanzado

En el ejemplo nterior, se ejecut l funcio n obtieneId() y el resultdo de l ejecucio n se


sign l propiedd obtieneId del objeto. As, el objeto no tendr un me todo llmdo
obtieneId, sino un propiedd con ese nombre y con un vlor igul l resultdo devuelto por l
funcio n extern.

Por otr prte, no es obligtorio que el me todo del objeto se llme igul que l funcio n extern,
unque es posible que s se.

A continucio n se muestr un objeto completo formdo por vris propieddes y me todos y


credo con l notcio n de puntos:
var elObjeto = new Object();
elObjeto.id = "10";
elObjeto.nombre = "Objeto de prueba";
elObjeto.muestraId = function() {
alert("El ID del objeto es "+ this.id);
}
elObjeto.muestraNombre = function() {
alert(this.nombre);
}

Siguiendo este mismo procedimiento, es posible crer objetos complejos que contengn otros
objetos:
var Aplicacion = new Object();

Aplicacion.Modulos = new Array();


Aplicacion.Modulos[0] = new Object();
Aplicacion.Modulos[0].titulo = "Lector RSS";

var inicial = new Object();


inicial.estado = 1;
inicial.publico = 0;
inicial.nombre = "Modulo_RSS";
inicial.datos = new Object();

Aplicacion.Modulos[0].objetoInicial = inicial;

En el ejemplo nterior, se define un objeto principl llmdo Aplicacion que su vez contiene
vrios objetos. L propiedd Modulos de l pliccio n es un rry en el que cd elemento es
un objeto que represent un mo dulo. A su vez, cd objeto Modulo tiene un propiedd
llmd titulo y otr llmd objetoInicial que tmbie n es un objeto con ls propieddes
y vlores iniciles del mo dulo.

L notcio n trdicionl de JvScript puede llegr ser tedios cundo se desrrolln


plicciones complejs con objetos que contienen otros muchos objetos y rrys. Por este
motivo, JvScript define un me todo lterntivo de notcio n llmdo JSON (JavaScript Object
Notation) y que se ver m s delnte.

3.1.1.3. Mtodos apply() y call()

JvScript define un pr de me todos denomindos apply() y call() que son muy u tiles pr
ls funciones. Ambos me todos permiten ejecutr un funcio n como si fuer un me todo de

www.librosweb.es 38
Introduccin a AJAX Captulo 3. JavaScript avanzado
otro

www.librosweb.es 39
Introduccin a AJAX Captulo 3. JavaScript avanzado

objeto. L u nic diferenci entre los dos me todos es l form en l que se psn los rgumentos
l funcio n.

El siguiente ejemplo muestr co mo utilizr el me todo call() pr ejecutr un funcio n como


si fuer un me todo del objeto elObjeto:
function miFuncion(x) {
return this.numero + x;
}

var elObjeto = new Object();


elObjeto.numero = 5;

var resultado = miFuncion.call(elObjeto, 4);


alert(resultado);

El primer pr metro del me todo call() es el objeto sobre el que se v ejecutr l funcio n.
Como l funcio n se trt como si fuer un me todo del objeto, l plbr reservd this hce
referenci l objeto indicdo en l llmd call(). De est form, si en l funcio n se utiliz
this.numero, en relidd se est obteniendo el vlor de l propiedd numero del objeto.

El resto de pr metros del me todo call() son los pr metros que se psn l funcio n. En
este cso, solmente es necesrio un pr metro, que es el nu mero que se sumr l propiedd
numero del objeto.

El me todo apply() es ide ntico l me todo call(), slvo que en este cso los pr metros se
psn como un rry:
function miFuncion(x) {
return this.numero + x;
}
var elObjeto = new Object();
elObjeto.numero = 5;

var resultado = miFuncion.apply(elObjeto, [4]);


alert(resultado);

3.1.2. Notacin JSON


JSON (JavaScript Object Notation) es un formto sencillo pr el intercmbio de informcio n. El
formto JSON permite representr estructurs de dtos (rrys) y objetos (rrys socitivos)
en form de texto. L notcio n de objetos medinte JSON es un de ls crcterstics principles
de JvScript y es un mecnismo definido en los fundmentos b sicos del lenguje.

En los u ltimos n os, JSON se h convertido en un lterntiv l formto XML, y que es m s f cil
de leer y escribir, dem s de ser mucho m s conciso. No obstnte, XML es superior te cnicmente
porque es un lenguje de mrcdo, mientrs que JSON es simplemente un formto pr
intercmbir dtos.

L especificcio n complet de JSON se puede consultr en RFC 4627 (http://tools.ietf.org/html/


rfc4627) y su tipo MIME oficil es application/json.

www.librosweb.es 40
Introduccin a AJAX Captulo 3. JavaScript avanzado

Como y se sbe, l notcio n trdicionl de los rrys es tedios cundo existen muchos
elementos:
var modulos = new Array();
modulos[0] = "Lector RSS";
modulos[1] = "Gestor email";
modulos[2] = "Agenda";
modulos[3] = "Buscador";
modulos[4] = "Enlaces";

Pr crer un rry norml medinte JSON, se indicn sus vlores seprdos por coms y
encerrdos entre corchetes. Por lo tnto, el ejemplo nterior se puede reescribir de l siguiente
mner utilizndo l notcio n JSON:
var modulos = ["Lector RSS", "Gestor email", "Agenda", "Buscador", "Enlaces"];

Por su prte, l notcio n trdicionl de los rrys socitivos es igul de tedios que l de los
rrys normles:
var modulos = new Array(); modulos.titulos =
new Array(); modulos.titulos['rss'] = "Lector
RSS"; modulos.titulos['email'] = "Gestor de
email"; modulos.titulos['agenda'] = "Agenda";

En este cso, se puede utilizr l notcio n de puntos pr brevir ligermente su definicio n:


var modulos = new Array(); modulos.titulos
= new Array(); modulos.titulos.rss =
"Lector RSS"; modulos.titulos.email =
"Gestor de email"; modulos.titulos.agenda
= "Agenda";

En culquier cso, l notcio n JSON permite definir los rrys socitivos de un form mucho
m s concis. De hecho, el ejemplo nterior se puede reescribir de l siguiente mner utilizndo
l notcio n JSON:
var modulos = new Array();
modulos.titulos = {rss: "Lector RSS", email: "Gestor de email", agenda: "Agenda"};

L notcio n JSON pr los rrys socitivos se compone de tres prtes:

1. Los contenidos del rry socitivo se encierrn entre llves ( { y })


2. Los elementos del rry se seprn medinte un com (,)
3. L clve y el vlor de cd elemento se seprn medinte dos puntos (:)

Si l clve no contiene espcios en blnco, es posible prescindir de ls comills que encierrn sus
contenidos. Sin embrgo, ls comills son obligtoris cundo ls clves pueden contener
espcios en blnco:
var titulosModulos = {"Lector RSS": "rss", "Gestor de email": "email", "Agenda":
"agenda"};

Como JvScript ignor los espcios en blnco sobrntes, es posible reordenr ls clves y
vlores pr que se muestren m s clrmente en el co digo fuente de l pliccio n. El ejemplo

www.librosweb.es 41
Introduccin a AJAX Captulo 3. JavaScript avanzado

nterior se puede rehcer de l siguiente mner n diendo nuevs lnes pr seprr los
elementos y n diendo espcios en blnco pr tbulr ls clves y pr liner los vlores:
var titulos = {
rss: "Lector RSS",
email: "Gestor de email",
agenda: "Agenda"
};

Combinndo l notcio n de los rrys simples y socitivos, es posible construir objetos muy
complejos de form sencill. Con l notcio n trdicionl, un objeto complejo se puede crer de l
siguiente mner:
var modulo = new Object(); modulo.titulo =
"Lector RSS"; modulo.objetoInicial = new
Object(); modulo.objetoInicial.estado = 1;
modulo.objetoInicial.publico = 0;
modulo.objetoInicial.nombre = "Modulo_RSS";
modulo.objetoInicial.datos = new Object();

Utilizndo JSON, es posible reescribir el ejemplo nterior de form mucho m s concis:


var modulo = {
titulo : "Lector RSS",
objetoInicial : { estado : 1, publico : 0, nombre : "Modulo RSS", datos : {} }
};

Los objetos se pueden definir en form de pres clve/vlor seprdos por coms y encerrdos
entre llves. Pr crer objetos vcos, se utilizn un pr de llves sin contenido en su interior {}.

A continucio n se muestr l notcio n JSON gene ric pr crer rrys y objetos:

Arrays
var array = [valor1, valor2, valor3, ..., valorN];

Objetos
var objeto = { clave1: valor1, clave2: valor2, clave3: valor3, ..., claveN: valorN };

L notcio n brevid se puede combinr pr crer rrys de objetos, objetos con rrys,
objetos con objetos y rrys, etc. A continucio n se muestrn lgunos ejemplos de plicciones
web reles que cren objetos medinte est notcio n.

Ejemplo extrado del cdigo fuente de Blinksale.com


var Invoice = Class.create();
Invoice.prototype = {
initialize: function(line_html, currency_symbol) {
this.line_html = line_html;
this.currency_symbol = currency_symbol;
this.line_index = 1;
this.update();
},

kinds: ['Service','Hours','Days','Product'],

www.librosweb.es 42
Introduccin a AJAX Captulo 3. JavaScript avanzado

change_kind: function(i) {
if($F('lines_'+i+'_kind')=='Hours') {
$('lines_'+i+'_unit_price').value = $F('default_hourly_rate');
this.update();
}
},

focus_num: function() {
$('invoice_number').focus();
},

use_freight: function() {
return $('invoice_use_freight').checked
},

freight: function() {
return this.use_freight() ? Number(noCommas($('invoice_freight').value)) : 0 ;
},
...
}

Ejemplo extrado del cdigo fuente de Gmail.com


pf.prototype =
{ Ed:function(a)
{this.hm=a},
dh:function(){if(this.eb.Th>0) {var a=Math.random()*100; return a<this.eb.Th} return
false },
Sg:function(a,b,c){ this.Vd=2; this.kb=Ic(a,true); this.Pc=b; this.Vl=c; this.Be() },
ne:function(a,b,c){ this.Vd=2; this.kb=Ic(a,true); this.Pc=null; this.Vl=b;
if(c){this.vm=false} this.Be()},
...
}

Ejemplo extrado del cdigo fuente de la librera prototype.js


var Prototype =
{ Version:
'1.6.0.2',

ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

emptyFunction: function() { },
K: function(x) { return x }
};

Ejemplo extrado del cdigo fuente de Netvibes.com


var App = new Object();
App.mode = 'userPage';
App.lang = 'es';
App.Modules = new Object();

App.Modules.RssReaderInfos = {
infos: App.Loc.defaultRssReader_infos,
defaultObj: {status:1, share:0, title:"", moduleName:"RssReader", data:{}}
www.librosweb.es 43
Introduccin
} a AJAX Captulo 3. JavaScript avanzado

www.librosweb.es 44
Introduccin a AJAX Captulo 3. JavaScript avanzado

App.Modules.GmailInfos = {
title: App.Loc.defaultGmail_title,
infos: App.Loc.defaultGmail_infos,
defaultObj:{status:1, share:0, title:App.Loc.defaultGmail_title, moduleName:"Gmail",
data:{}},
path: NV_PATH+"modules/gmail/gmail.js?v=5",
ico: NV_PATH+"img/gmail.gif"
}
App.Modules.WeatherInfos = {
title: App.Loc.defaultWeather_title,
infos: App.Loc.defaultWeather_infos,
defaultObj:{status:1, share:0, title:App.Loc.defaultWeather_title,
moduleName:"Weather", data:{town:"FRXX0076"}},
path: NV_PATH+"modules/weather/weather.js?v=2",
ico: NV_PATH+"img/weather.gif"
}

Ejemplo extrado del cdigo fuente de Writeboard.com


// ===================================================
// EXPORT MANAGER
// ===================================================
var exportManager = {
show: function() {
$('exportButton').src = "/images/b-export-on.gif"
showElement('download_export')
},

hide: function() {
$('exportButton').src = "/images/b-export.gif"
hideElement('download_export')
},

toggle: function() {
Element.visible('download_export') ? this.hide() : this.show()
}
}

Ejemplo extrado del cdigo fuente del framework Dojo


var dojo;
if(dj_undef("dojo")){ dojo = {}; }

dojo.version = {
major: 0, minor: 2, patch: 2, flag: "",
revision: Number("$Rev: 2836 $".match(/[0-9]+/)[0]),
toString: function() {
with (dojo.version) {
return major + "." + minor + "." + patch + flag + " (" + revision + ")";
}
}
};

A prtir de los ejemplos nteriores, se deduce que l form hbitul pr definir los objetos en
JvScript se bs en el siguiente modelo credo con l notcio n JSON:

www.librosweb.es 45
Introduccin a AJAX Captulo 3. JavaScript avanzado

var objeto = {
"propiedad1": valor_simple_1,
"propiedad2": valor_simple_2,
"propiedad3": [array1_valor1, array1_valor2],
"propiedad4": { "propiedad anidada": valor },
"metodo1": nombre_funcion_externa,
"metodo2": function() { ... },
"metodo3": function() { ... },
"metodo4": function() { ... }
};

En un mismo objeto se puede utilizr de form simult ne l notcio n trdicionl de JvScript y


l notcio n JSON:
var libro = new Object();
libro.numeroPaginas = 150;
libro.autores = [ {id: 50}, {id: 67} ];

El ejemplo nterior se puede reescribir utilizndo solmente l notcio n trdicionl:


var libro = { numeroPaginas: 150 };
libro.autores = new Array();
libro.autores[0] = new Object();
libro.autores[0].id = 50;
libro.autores[1] = new Object();
libro.autores[1].id = 67;

El ejemplo nterior tmbie n se puede reescribir utilizndo exclusivmente l notcio n JSON:


var libro = { numeroPaginas: 150, autores: [{id: 50}, {id: 67}] };

Ejercicio 1

Definir la estructura de un objeto que almacena una factura. Las facturas estn formadas por la
informacin de la propia empresa (nombre de la empresa, direccin, telfono, NIF), la informacin
del cliente (similar a la de la empresa), una lista de elementos (cada uno de los cuales dispone de
descripcin, precio, cantidad) y otra informacin bsica de la factura (importe total, tipo de iva,
forma de pago).

Una vez definidas las propiedades del objeto, aadir un mtodo que calcule el importe total de la
factura y actualice el valor de la propiedad correspondiente. Por ltimo, aadir otro mtodo que
muestre por pantalla el importe total de la factura.

3.2. Clases
Los objetos que se hn visto hst hor son un simple coleccio n de propieddes y me todos que
se definen pr cd objeto individul. Sin embrgo, en l progrmcio n orientd objetos, el
concepto fundmentl es el de clse.

L form hbitul de trbjo consiste en definir clses prtir de ls cules se cren los objetos
con los que trbjn ls plicciones. Sin embrgo, JvScript no permite crer clses similres
ls de lengujes como Jv o C++. De hecho, l plbr class so lo est reservd pr su uso
en futurs versiones de JvScript.

www.librosweb.es 46
Introduccin a AJAX Captulo 3. JavaScript avanzado

A pesr de ests limitciones, es posible utilizr en JvScript unos elementos precidos ls


clses y que se denominn pseudoclases. Los conceptos que se utilizn pr simulr ls clses
son ls funciones constructors y el prototype de los objetos.

3.2.1. Funciones constructoras


Al contrrio que en los lengujes orientdos objetos, en JvScript no existe el concepto de
constructor. Por lo tnto, l definir un clse no se incluyen uno o vrios constructores. En
relidd, JvScript emul el funcionmiento de los constructores medinte el uso de funciones.

En el siguiente ejemplo, se cre un objeto gene rico y un objeto de tipo rry:


var elObjeto = new Object();
var elArray = new Array(5);

En los dos csos, se utiliz l plbr reservd new y el nombre del tipo de objeto que se
quiere crer. En relidd, ese nombre es el nombre de un funcio n que se ejecut pr crer el
nuevo objeto. Adem s, como se trt de funciones, es posible incluir pr metros en l crecio n
del objeto.

JvScript utiliz funciones pr simulr los constructores de objetos, por lo que ests funciones
se denominn "funciones constructoras". El siguiente ejemplo cre un funcio n llmd Factura
que se utiliz pr crer objetos que representn un fctur.
function Factura(idFactura, idCliente) {
this.idFactura = idFactura;
this.idCliente = idCliente;
}

Cundo se cre un objeto es hbitul psr l constructor de l clse un serie de vlores pr


inicilizr lguns propieddes. Este concepto tmbie n se utiliz en JvSript, unque su
relizcio n es diferente. En este cso, l funcio n constructor iniciliz ls propieddes de cd
objeto medinte el uso de l plbr reservd this.

L funcio n constructor puede definir todos los pr metros que necesit pr construir los
nuevos objetos y posteriormente utilizr esos pr metros pr l inicilizcio n de ls
propieddes. En el cso nterior, l fctur se iniciliz medinte el identificdor de fctur y el
identificdor de cliente.

Despue s de definir l funcio n nterior, es posible crer un objeto de tipo Factura y simulr el
funcionmiento de un constructor:
var laFactura = new Factura(3, 7);

As, el objeto laFactura es de tipo Factura, con tods sus propieddes y me todos y se puede
cceder ellos utilizndo l notcio n de puntos hbitul:
alert("cliente = " + laFactura.idCliente + ", factura = " + laFactura.idFactura);

Normlmente, ls funciones constructors no devuelven ningu n vlor y se limitn definir ls


propieddes y los me todos del nuevo objeto.

www.librosweb.es 47
Introduccin a AJAX Captulo 3. JavaScript avanzado

3.2.2. Prototype
Ls funciones constructors no solmente pueden estblecer ls propieddes del objeto, sino
que tmbie n pueden definir sus me todos. Siguiendo con el ejemplo nterior, se puede crer un
objeto completo llmdo Factura con sus propieddes y me todos:
function Factura(idFactura, idCliente) {
this.idFactura = idFactura;
this.idCliente = idCliente;

this.muestraCliente = function() {
alert(this.idCliente);
}

this.muestraId = function() {
alert(this.idFactura);
}
}

Un vez definid l pseudoclase medinte l funcio n constructor, y es posible crer objetos de


ese tipo. En el siguiente ejemplo se cren dos objetos diferentes y se emplen sus me todos:
var laFactura = new Factura(3, 7);
laFactura.muestraCliente();
var otraFactura = new Factura(5, 4);
otraFactura.muestraId();

Incluir los me todos de los objetos como funciones dentro de l propi funcio n constructor, es
un te cnic que funcion correctmente pero que tiene un grn inconveniente que l hce poco
consejble.

En el ejemplo nterior, ls funciones muestraCliente() y muestraId() se cren de nuevo


por cd objeto credo. En efecto, con est te cnic, cd vez que se instnci un objeto, se
definen tnts nuevs funciones como me todos incluy l funcio n constructor. L penlizcio n
en el rendimiento y el consumo excesivo de recursos de est te cnic puede suponer un
inconveniente en ls plicciones profesionles relizds con JvScript.

Afortundmente, JvScript incluye un propiedd que no est presente en otros lengujes de


progrmcio n y que solucion este inconveniente. L propiedd se conoce con el nombre de
prototype y es un de ls crcterstics m s podeross de JvScript.

Todos los objetos de JvScript incluyen un referenci intern otro objeto llmdo prototype o
"prototipo". Culquier propiedd o me todo que conteng el objeto prototipo, est presente de
form utom tic en el objeto originl.

Relizndo un smil con los lengujes orientdos objetos, es como si culquier objeto de
JvScript heredr de form utom tic tods ls propieddes y me todos de otro objeto
llmdo prototype. Cd tipo de objeto diferente hered de un objeto prototype diferente.

En cierto modo, se puede decir que el prototype es el molde con el que se fbric cd objeto de
ese tipo. Si se modific el molde o se le n den nuevs crcterstics, todos los objetos
fbricdos con ese molde tendr n ess crcterstics.

www.librosweb.es 48
Introduccin a AJAX Captulo 3. JavaScript avanzado

Normlmente los me todos no vrn de un objeto otro del mismo tipo, por lo que se puede
evitr el problem de rendimiento comentdo nteriormente n diendo los me todos l
prototipo prtir del cul se cren los objetos.

Si se consider de nuevo l clse Factura del ejemplo


nterior:
function Factura(idFactura, idCliente) {
this.idFactura = idFactura;
this.idCliente = idCliente;

this.muestraCliente = function() {
alert(this.idCliente);
}

this.muestraId = function() {
alert(this.idFactura);
}
}

L clse nterior que incluye los me todos en l funcio n constructor, se puede reescribir
utilizndo el objeto prototype:
function Factura(idFactura, idCliente) {
this.idFactura = idFactura;
this.idCliente = idCliente;
}

Factura.prototype.muestraCliente = function() {
alert(this.idCliente);
}

Factura.prototype.muestraId = function() {
alert(this.idFactura);
}

Pr incluir un me todo en el prototipo de un objeto, se utiliz l propiedd prototype del


objeto. En el ejemplo nterior, se hn n dido los dos me todos del objeto en su prototipo. De est
form, todos los objetos credos con est funcio n constructor incluyen por defecto estos dos
me todos. Adem s, no se cren dos nuevs funciones por cd objeto, sino que se definen
u nicmente dos funciones pr todos los objetos credos.

Evidentemente, en el prototype de un objeto so lo se deben n dir quellos elementos


comunes pr todos los objetos. Normlmente se n den los me todos y ls constntes
(propieddes cuyo vlor no vr durnte l ejecucio n de l pliccio n). Ls propieddes del
objeto permnecen en l funcio n constructor pr que cd objeto diferente pued tener un
vlor distinto en ess propieddes.

El myor inconveniente de l propiedd prototype es que se pueden reescribir propieddes y


me todos de form ccidentl. Si se consider el siguiente ejemplo:
Factura.prototype.iva = 16;
var laFactura = new Factura(3, 7); // laFactura.iva = 16

Factura.prototype.iva = 7;
www.librosweb.es 49
Introduccin a AJAX Captulo 3. JavaScript avanzado

var otraFactura = new Factura(5, 4);


// Ahora, laFactura.iva = otraFactura.iva = 7

El primer objeto credo de tipo Factura dispone de un propiedd llmd iva cuyo vlor es
16. M s delnte, se modific el prototipo del objeto Factura durnte l ejecucio n del progrm
y se estblece un nuevo vlor en l propiedd iva.

De est form, l propiedd iva del segundo objeto credo vle 7. Adem s, el vlor de l
propiedd iva del primer objeto h cmbido y hor vle 7 y no 16. Aunque l modificcio n
del prototipo en tiempo de ejecucio n no suele ser un opercio n que se relice hbitulmente, s
que
es posible modificrlo de form ccidentl.

Ejercicio 2

Modificar el ejercicio anterior del objeto Factura para crear una pseudoclase llamada Factura y que
permita crear objetos de ese tipo. Se deben utilizar las funciones constructoras y la propiedad
prototype.

Para instanciar la clase, se debe utilizar la instruccin Factura(cliente, elementos), donde


cliente tambin es una pseudoclase que guarda los datos del cliente y elementos es un array
simple que contiene las pseudoclases de todos los elementos que forman la factura.

Un de ls posibiliddes m s interesntes de l propiedd prototype es que tmbie n permite


n dir y/o modificr ls propieddes y me todos de los objetos predefinidos por JvScript. Por
lo tnto, es posible redefinir el comportmiento hbitul de lgunos me todos de los objetos
ntivos de JvScript. Adem s, se pueden n dir propieddes o me todos completmente nuevos.

Si por ejemplo se consider l clse Array, est no dispone de un me todo que indique l posicio n
de un elemento dentro de un rry (como l funcio n indexOf() de Jv). Modificndo el
prototipo con el que se construyen los objetos de tipo Array, es posible n dir est
funcionlidd:
Array.prototype.indexOf = function(objeto) {
var resultado = -1;
for(var i=0; i<this.length; i++) {
if(this[i] == objeto) {
resultado = i;
break;
}
}
return resultado;
}

El co digo nterior permite que todos los rrys de JvScript dispongn de un me todo llmdo
indexOf que devuelve el ndice de l primer posicio n de un elemento dentro del rry o -1 si
el elemento no se encuentr en el rry, tl y como sucede en otros lengujes de progrmcio n.

El funcionmiento del me todo nterior consiste en recorrer el rry ctul (obteniendo su


nu mero de elementos medinte this.length) y comprr cd elemento del rry con el
elemento que se quiere encontrr. Cundo se encuentr por primer vez el elemento, se
devuelve su posicio n dentro del rry. En otro cso, se devuelve -1.
www.librosweb.es 50
Introduccin a AJAX Captulo 3. JavaScript avanzado

Como se ver m s delnte, existen librers de JvScript formds por un conjunto de


utiliddes que fcilitn l progrmcio n de ls plicciones. Un de ls crcterstics hbitules
de ests librers es el uso de l propiedd prototype pr mejorr ls funcionliddes
b sics de JvScript.

A continucio n se muestr el ejemplo de un librer llmd Prototype que utiliz l propiedd


prototype pr mplir ls funcionliddes de los rrys de
JvScript:
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
iterator(this[i]);
},
clear: function() {
this.length = 0;
return this;
},
first: function() {
return this[0];
},
last: function() {
return this[this.length - 1];
},
compact: function() {
return this.select(function(value) {
return value != undefined || value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
return array.concat(value.constructor == Array ?
value.flatten() : [value]);
});
},
without: function() {
var values = $A(arguments);
return this.select(function(value) {
return !values.include(value);
});
},
indexOf: function(object) {
for (var i = 0; i < this.length; i++)
if (this[i] == object) return i;
return -1;
},
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
shift: function() {
var result = this[0];
for (var i = 0; i < this.length - 1; i++)
this[i] = this[i + 1];
this.length--;
return result;

www.librosweb.es 51
Introduccin a AJAX Captulo 3. JavaScript avanzado

},
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
});

El co digo nterior n de l clse Array de JvScript vris utiliddes que no disponen los
rrys por defecto: obtener (sin extrerlo) el primer o u ltimo elemento del rry, filtrr sus
vlores, determinr l posicio n de un elemento, borrr el rry, etc.

Ejercicio 3

Extender el objeto Array para que permita aadir nuevos elementos al final del array:
var array1 = [0, 1, 2];
array1.anadir(3);
// array1 = [0, 1, 2, 3]

Incluir la opcin de controlar si se permiten elementos duplicados o no:


var array1 = [0, 1, 2];

array1.anadir(2);
// array1 = [0, 1, 2, 2]

array1.anadir(2, false);
// array1 = [0, 1, 2]

Culquier clse ntiv de JvScript puede ser modificd medinte l propiedd prototype,
incluso l clse Object. Se puede modificr por ejemplo l clse String pr n dir un
me todo que conviert un cden en un rry:
String.prototype.toArray = function() {
return this.split('');
}

L funcio n split() divide un cden de texto segu n el seprdor indicdo. Si no se indic


ningu n seprdor, se divide cr cter cr cter. De este modo, l funcio n nterior devuelve un
rry en el que cd elemento es un letr de l cden de texto originl.

Un funcio n muy comu n en otros lengujes de progrmcio n y que no dispone JvScript es l


funcio n trim(), que elimin el espcio en blnco que pued existir l principio y l finl de un
cden de texto:
String.prototype.trim = function() {
return this.replace(/^\s*|\s*$/g, '');
}

var cadena = " prueba de cadena ";


cadena.trim();
// Ahora cadena = "prueba de cadena"

L funcio n trim() n did l prototipo de l clse String hce uso de ls expresiones


regulres pr detectr todos los espcios en blnco que puedn existir tnto l principio como
l finl de l cden y se sustituyen por un cden vc, es decir, se eliminn.

www.librosweb.es 52
Introduccin a AJAX Captulo 3. JavaScript avanzado

Con este me todo, es posible definir ls funciones socids rtrim() y ltrim() que eliminn
los espcios en blnco l derech (finl) de l cden y su izquierd (principio).
String.prototype.rtrim = function() {
return this.replace(/\s*$/g, '');
}
String.prototype.ltrim = function() {
return this.replace(/^\s*/g, '');
}
String.prototype.trim = function() {
return this.ltrim().rtrim();
}

Otr funcio n muy u til pr ls cdens de texto es l de eliminr tods ls etiquets HTML que
pued contener. Culquier pliccio n en l que el usurio pued introducir informcio n, debe
tener especil cuiddo con los dtos introducidos por el usurio. Medinte JvScript se puede
modificr l clse String pr incluir un utilidd que elimine culquier etiquet de co digo
HTML de l cden de texto:
String.prototype.stripTags = function() {
return this.replace(/<\/?[^>]+>/gi, '');
}

var cadena = '<html><head><meta content="text/html; charset=UTF-8"


http-equiv="content-type"></head><body><p>Parrafo de prueba</p></body></html>';
cadena.stripTags();
// Ahora cadena = "Parrafo de prueba"

El ejemplo nterior tmbie n hce uso de expresiones regulres complejs pr eliminr


culquier trozo de texto que se similr un etiquet HTML, por lo que se buscn ptrones
como <...> y </...>.

Ejercicio 4

Extender la clase String para que permita truncar una cadena de texto a un tamao indicado como
parmetro:
var cadena = "hola mundo";
cadena2 = cadena.truncar(6); // cadena2 = "hola m"

Modificar la funcin anterior para que permita definir el texto que indica que la cadena se ha
truncado:
var cadena = "hola mundo";
cadena2 = cadena.truncar(6, '...'); // cadena2 = "hol..."

Ejercicio 5

Aadir a la clase Array un mtodo llamado sin() que permita filtrar los elementos del array original
y obtenga un nuevo array con todos los valores diferentes al indicado:
var array1 = [1, 2, 3, 4, 5];
var filtrado = array1.sin(4); // filtrado = [1, 2, 3, 5]

www.librosweb.es 53
Introduccin a AJAX Captulo 3. JavaScript avanzado

3.2.3. Herencia y mbito (scope)


Los lengujes orientdos objetos disponen, entre otros, de los conceptos de herenci entre
clses y de mbito (scope) de sus me todos y propieddes (public, private, protected).

Sin embrgo, JvScript no dispone de form ntiv ni de herenci ni de mbitos. Si se requieren


mbos mecnismos, l u nic opcio n es simulr su funcionmiento medinte clses, funciones y
me todos desrrolldos medid.

Alguns te cnics simuln el uso de propieddes privds prefijndo su nombre con un guio n
bjo, pr distinguirls del resto de propieddes pu blics. Pr simulr l herenci de clses,
lguns librers como Prototype n den un me todo l clse Object llmdo extend() y
que copi ls propieddes de un clse origen en otr clse destino:
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}

3.3. Otros conceptos


3.3.1. Excepciones
JvScript dispone de un mecnismo de trtmiento de excepciones muy similr l de otros
lengujes de progrmcio n como Jv. Pr ello, define ls plbrs reservds try, catch y
finally.

L plbr reservd try se utiliz pr encerrr el bloque de co digo JvScript en el que se vn


controlr ls excepciones. Normlmente, el bloque definido por try v seguido de otro
bloque de co digo definido por catch.

Cundo se produce un excepcio n en el bloque try, se ejecutn ls instrucciones contenids


dentro del bloque catch socido. Despue s del bloque catch, es posible definir un bloque con
l plbr reservd finally. Todo el co digo contenido en el bloque finally se ejecut
independientemente de l excepcio n ocurrid en el bloque try.

Un bloque try debe ir seguido obligtorimente de un bloque catch o de un bloque


finally. Tmbie n es posible que vy seguido de los dos bloques.

A continucio n se muestr un ejemplo de excepcio n y uso de los bloques try y


catch:

try {
var resultado = 5/a;
} catch(excepcion) {
alert(excepcion);
}

www.librosweb.es 54
Introduccin a AJAX Captulo 3. JavaScript avanzado

El bloque catch permite indicr el nombre del pr metro que se cre utom ticmente l
producirse un excepcio n. Este identificdor de l vrible so lo est definido dentro del bloque
catch y se puede utilizr pr obtener m s informcio n sobre l excepcio n producid.

En este cso, l intentr dividir el nu mero 5 por l vrible a que no est definid, se
produce un excepcio n que muestr el siguiente mensje dentro del bloque catch:

Figura 3.1. Excepcin JavaScript provocada por una variable no definida

El funcionmiento del bloque finally no es tn sencillo como el bloque catch. Si se ejecut


culquier prte del co digo que se encuentr dentro del bloque try, siempre se ejecut el bloque
finally, independientemente del resultdo de l ejecucio n del bloque try.

Si dentro del bloque try se ejecut un instruccio n de tipo return, continue o break, tmbie n
se ejecut el bloque finally ntes de ejecutr culquier de ess instrucciones. Si se produce
un excepcio n en el bloque try y est n definidos los bloques catch y finally, en primer
lugr se ejecut el bloque catch y continucio n el bloque finally.

JvScript tmbie n permite lnzr excepciones mnulmente medinte l plbr reservd


throw:

try {
if(typeof a == "undefined" || isNaN(a)) {
throw new Error('La variable "a" no es un nmero');
}
var resultado = 5/a;
} catch(excepcion) {
alert(excepcion);
} finally {
alert("Se ejecuta");
}

En este cso, l ejecutr el script se muestrn los dos siguientes mensjes de form consecutiv:

Figura 3.2. Manejando las excepciones en JavaScript para mostrar mensajes al usuario

www.librosweb.es 55
Introduccin a AJAX Captulo 3. JavaScript avanzado

Figura 3.3. El bloque "finally" siempre se ejecuta cuando se produce una excepcin en JavaScript

3.3.2. Clausura (closure)


El concepto de clausura (closure en ingle s) es conocido y utilizdo en vrios lengujes de
progrmcio n desde hce de cds. JvScript tmbie n permite utilizr clausuras en el co digo de
ls plicciones. En este cso, ls clausuras se cren de form implcit, y que no existe ningun
form de declrrls explcitmente.

A continucio n se muestr un ejemplo sencillo de clausura en JvScript:


var x = "estoy fuera";

function funcionExterna() {
var x = "estoy dentro";
function funcionAnidada() { alert(x); }
funcionAnidada();
}

funcionExterna();

Al ejecutr el co digo nterior, se muestr el mensje "estoy dentro". Cundo se define un


funcio n dentro de otr, tods ls vribles de l primer funcio n est n disponibles de form
direct en l funcio n nidd.

Te cnicmente, un clausura es un porcio n de co digo (normlmente un funcio n) que se evlu


en un entorno de ejecucio n que contiene vribles de otro entorno de ejecucio n. JvScript cre
clausuras pr tods ls funciones definids dentro de otr funcio n. Sin embrgo, el uso expreso
de clausuras es muy limitdo y se reserv so lo pr ls te cnics m s vnzds y complejs de
JvScript. Utilizndo clausuras es posible por ejemplo simulr el funcionmiento de ls
propieddes privds en los objetos de JvScript.

Existen recursos online con un expliccio n detlld del funcionmiento y plicciones de ls


clausuras en JvScript, como por ejemplo http://www.jibbering.com/fq/fq_notes/
closures.html

3.3.3. Reflexin
Al igul que l myor prte de los lengujes de progrmcio n m s utilizdos, JvScript define
mecnismos que permiten l reflexin sobre los objetos. L reflexio n es un proceso medinte el
cul un progrm es cpz de obtener informcio n sobre si mismo y por tnto es cpz de uto
modificrse en tiempo de ejecucio n.

www.librosweb.es 56
Introduccin a AJAX Captulo 3. JavaScript avanzado

JvScript emple el concepto de reflexio n pr permitir descubrir propieddes y me todos de


objetos externos. El ejemplo m s sencillo es el de verigur si un objeto posee un determindo
me todo y s poder ejecutrlo. Si se dispone de un objeto llmdo elObjeto, el co digo necesrio
pr descubrir si posee un determind propiedd llmd laPropiedad ser el siguiente:
if(elObjeto.laPropiedad) {
// el objeto posee la propiedad buscada
}

Si el objeto no dispone de l propiedd buscd, l respuest ser undefined, que se


trnsformr en un vlor false que hce que no se ejecute el interior del bloque if.

Sin embrgo, el co digo nterior no es del todo correcto, y que si l propiedd buscd tiene un
vlor de false, null o el nu mero 0, el nterior co digo no se ejecutr correctmente. En tl
cso, el co digo necesrio es el siguiente:
if(typeof(elObjeto.laPropiedad) != 'undefined') {
// el objeto posee la propiedad buscada
}

El ejemplo nterior hce uso del operdor typeof, que devuelve el tipo del objeto o vrible que
se le ps como pr metro. Los vlores que devuelve este operdor son: undefined, number,
object, boolean, string o function.

El otro operdor que y se comento nteriormente es instanceof, que comprueb si un objeto


es un instnci de otro objeto:
if(elObjeto instanceof Factura) {
alert("Se trata de un objeto de tipo Factura");
}

Este operdor tmbie n se puede empler con objetos ntivos de JvScript:


var elObjeto = [];
if(elObjeto instanceof Array) {
alert("Es un array");
}
else if(elObjeto instanceof Object) {
alert("Es un objeto");
}

En el ejemplo nterior, el progrm muestr por pntll el mensje "Es un array" y que se
cumple l primer comprobcio n por ser l vrible elObjeto un rry. Sin embrgo, si se
cmbi de orden ls comprobciones:
var elObjeto = [];
if(elObjeto instanceof Object) {
alert("Es un objeto");
}
else if(elObjeto instanceof Array) {
alert("Es un array");
}

www.librosweb.es 57
Introduccin a AJAX Captulo 3. JavaScript avanzado

En este cso, l slid del progrm es el mensje "Es un objeto". El motivo es que, pesr de
que JvScript no soport el concepto de herenci en los objetos definidos medid, los objetos
ntivos Function y Array s que heredn del objeto Object. As, l comprobcio n elObjeto
instanceof Object devuelve un vlor true, por ser Array un clse que hered de
Object.

Ejercicio 6

Sobrescribir el objeto Object para que incluya un mtodo llamado implementa() y que indique si
el objeto posee el mtodo cuyo nombre se le pasa como parmetro.

www.librosweb.es 58
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

Captulo 4. DOM (Document Object


Model)
4.1. Introduccin a DOM
Cundo se definio el lenguje XML, surgio l necesidd de procesr y mnipulr el contenido de
los rchivos XML medinte los lengujes de progrmcio n trdicionles. XML es un lenguje
sencillo de escribir pero complejo pr procesr y mnipulr de form eficiente. Por este motivo,
surgieron lguns te cnics entre ls que se encuentr DOM.

DOM o Document Object Model es un conjunto de utiliddes especficmente disen ds pr


mnipulr documentos XML. Por extensio n, DOM tmbie n se puede utilizr pr mnipulr
documentos XHTML y HTML. Te cnicmente, DOM es un API de funciones que se pueden utilizr
pr mnipulr ls p gins XHTML de form r pid y eficiente.

Antes de poder utilizr sus funciones, DOM trnsform internmente el rchivo XML originl en
un estructur m s f cil de mnejr formd por un jerrqu de nodos. De est form, DOM
trnsform el co digo XML en un serie de nodos interconectdos en form de rbol.

El rbol generdo no so lo represent los contenidos del rchivo originl (medinte los nodos del
rbol) sino que tmbie n represent sus relciones (medinte ls rms del rbol que conectn
los nodos).

Aunque en ocsiones DOM se soci con l progrmcio n web y con JvScript, l API de DOM es
independiente de culquier lenguje de progrmcio n. De hecho, DOM est disponible en l
myor de lengujes de progrmcio n comu nmente empledos.

Si se consider l siguiente p gin HTML sencill:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Pgina sencilla</title>
</head>

<body>
<p>Esta pgina es <strong>muy sencilla</strong></p>
</body>
</html>

Antes de poder utilizr ls funciones de DOM, los nvegdores convierten utom ticmente l
p gin HTML nterior en l siguiente estructur de rbol de nodos:

www.librosweb.es 59
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

Figura 4.1. Representacin en forma de rbol de la pgina HTML de ejemplo

L p gin HTML se h trnsformdo en un jerrqu de nodos, en l que el nodo rz es un nodo


de tipo documento HTML. A prtir de este nodo, existen dos nodos en el mismo nivel formdos
por ls etiquets <head> y <body>. De cd uno de los nteriores surge otro nodo (<title> y
<p> respectivmente). Por u ltimo, de cd nodo nterior surge otro nodo de tipo texto.

Antes de poder utilizr l API de DOM, se construye de form utom tic el rbol pr poder
ejecutr de form eficiente tods ess funciones. De este modo, pr utilizr DOM es
imprescindible que l p gin web se hy crgdo por completo, y que de otro modo no existe
el rbol de nodos y ls funciones DOM no pueden funcionr correctmente.

L ventj de empler DOM es que permite los progrmdores disponer de un control muy
preciso sobre l estructur del documento HTML o XML que est n mnipulndo. Ls funciones
que proporcion DOM permiten n dir, eliminr, modificr y reemplzr culquier nodo de
culquier documento de form sencill.

L primer especificcio n de DOM (DOM Level 1) se definio en 1998 y permitio homogeneizr l


implementcio n del DHTML o HTML dinmico en los diferentes nvegdores, y que permit
modificr el contenido de ls p gins web sin necesidd de recrgr l p gin enter.

4.2. Tipos de nodos


Los documentos XML y HTML trtdos por DOM se convierten en un jerrqu de nodos. Los
nodos que representn los documentos pueden ser de diferentes tipos. A continucio n se
detlln los tipos m s importntes:

Document: es el nodo rz de todos los documentos HTML y XML. Todos los dem s nodos
derivn de e l.

www.librosweb.es 60
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

DocumentType: es el nodo que contiene l representcio n del DTD empledo en l p gin


(indicdo medinte el DOCTYPE).

Element: represent el contenido definido por un pr de etiquets de pertur y cierre


(<etiqueta>...</etiqueta>) o de un etiquet abreviada que se bre y se cierr l vez
(<etiqueta/>). Es el u nico nodo que puede tener tnto nodos hijos como tributos.

Attr: represent el pr nombre-de-tributo/vlor.

Text: lmcen el contenido del texto que se encuentr entre un etiquet de pertur y
un de cierre. Tmbie n lmcen el contenido de un seccio n de tipo CDATA.
CDataSection: es el nodo que represent un seccio n de tipo <![CDATA[ ]]>.

Comment: represent un comentrio de XML.

Se hn definido otros tipos de nodos pero que no son empledos hbitulmente:


DocumentFragment, Entity, EntityReference, ProcessingInstruction y Notation.

El siguiente ejemplo de documento sencillo de XML muestr lgunos de los nodos m s


hbitules:
<?xml version="1.0"?>
<clientes>
<!-- El primer cliente -->
<cliente>
<nombre>Empresa SA</nombre>
<sector>Tecnologia</sector>
<notas><![CDATA[
Llamar la proxima semana
]]></notas>
</cliente>
</clientes>

Su representcio n como rbol de nodos DOM es l siguiente:

www.librosweb.es 61
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

Figura 4.2. Representacin en forma de rbol del archivo XML de ejemplo

El nodo rz siempre es el nodo de tipo Document, del que derivn todos los dem s nodos del
documento. Este nodo es comu n pr tods ls p gins HTML y todos los documentos XML. A
continucio n se incluye l etiquet <clientes>...</clientes>. Como se trt de un etiquet,
DOM l trnsform en un nodo de tipo Element. Adem s, como l etiquet encierr todos los
dem s elementos de l p gin, el nodo Clientes de tipo Element deriv directmente de
Document y todos los dem s nodos del documento derivn de ese nodo.

El comentrio es el primer texto que se incluye dentro de l etiquet <clientes>, por lo que se
trnsform en el primer subnodo del nodo clientes. Al ser un comentrio de XML, se trt de
un nodo de tipo Comment.

Al mismo nivel que el comentrio, se encuentr l etiquet <cliente> que define ls


crcterstics del primer cliente y form el segundo subnodo del nodo clientes. Tods ls
dem s etiquets del documento XML se encuentrn encerrds por l etiquet
<cliente>...</cliente>, por lo que todos los nodos restntes derivr n del nodo cliente.

Cd etiquet simple de tipo <etiqueta>texto</etiqueta> se trnsform en un pr de nodos:


el primero de tipo Element (que contiene l etiquet en s) y el segundo, un nodo hijo de tipo
Text que contiene el contenido definido entre l etiquet de pertur y l de cierre.

www.librosweb.es 62
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

Figura 4.3. Nodos generados por una etiqueta HTML

L etiquet <notas> se trnsform en tres nodos, y que contiene un seccio n de tipo CData,
que su vez se trnsform en un nodo del que deriv el contenido propio de l seccio n CData.

Un buen me todo pr comprobr l trnsformcio n que sufren ls p gins web y visulizr l


jerrqu de nodos cred por DOM es utilizr l utilidd "Inspector DOM" (o "DOM Inspector")
del nvegdor Mozill Firefox.

L utilidd se puede encontrr en el menu Herramientas y dem s de mostrr visulmente l


jerrqu de nodos, permite cceder f cilmente tod l informcio n de cd nodo y muestr en
l p gin web el contenido l que hce referenci el nodo ctul.

4.3. La interfaz Node


Un vez que DOM h credo de form utom tic el rbol completo de nodos de l p gin, y es
posible utilizr sus funciones pr obtener informcio n sobre los nodos o mnipulr su
contenido. JvScript cre el objeto Node pr definir ls propieddes y me todos necesrios
pr procesr y mnipulr los documentos.

En primer lugr, el objeto Node define ls siguientes constntes pr l identificcio n de los


distintos tipos de nodos:

Node.ELEMENT_NODE = 1

Node.ATTRIBUTE_NODE = 2

Node.TEXT_NODE = 3

Node.CDATA_SECTION_NODE = 4

Node.ENTITY_REFERENCE_NODE = 5

Node.ENTITY_NODE = 6

Node.PROCESSING_INSTRUCTION_NODE = 7

Node.COMMENT_NODE = 8

Node.DOCUMENT_NODE = 9

Node.DOCUMENT_TYPE_NODE = 10

Node.DOCUMENT_FRAGMENT_NODE = 11

www.librosweb.es 63
Introduccin a AJAX Captulo 4. DOM (Document Object Model)

Node.NOTATION_NODE = 12

Adem s de ests constntes, Node proporcion ls siguientes propieddes y me todos:

Propiedad/Mtodo Valor devuelto Descripcin

El nombre del nodo (no est definido para algunos tipos de


nodeName String nodo)

El valor del nodo (no est definido para algunos tipo s de


nodeValue String
nodo)
nodeType Number Una de las 12 constantes definidas anteriormente
ownerDocument Document Referencia del documento al que pertenece el nodo
firstChild Node Referencia del primer nodo de la lista childNodes
lastChild Node Referencia del ltimo nodo de la lista childNodes
childNodes NodeList Lista de todos los nodos hijo del nodo actual

Referencia del nodo hermano anterior o null si este nodo


previousSibling Node es el primer hermano

Referencia del nodo hermano siguiente o null si este


nextSibling Node nodo es el ltimo hermano

Devuelve true si el nodo actual tiene uno o ms nodos


hasChildNodes() Bolean hijo

Se emplea con nodos de tipo Element. Contiene objetos


attributes NamedNodeMap de tipo Attr que definen todos los atributos del elemento

appendChild(nodo) Node Aade un nuevo nodo al final de la lista childNodes


removeChild(nodo) Node Elimina un nodo de la lista childNodes

www.librosweb.es 64
Introduccin a AJAX Captulo 4. DOM (Document Object Model)
replaceChild(nuevoNodo, Node Reemplaza el nodo anteriorNodo por el nodo
anteriorNodo) nuevoNodo
insertBefore(nuevoNodo, Node Inserta el nodo nuevoNodo antes que la posicin del nodo
anteriorNodo)
anteriorNodo dentro de la lista childNodes

Los me todos y propieddes incluids en l tbl nterior son especficos de XML, unque pueden
plicrse todos los lengujes bsdos en XML, como por ejemplo XHTML. Pr ls p gins
creds con HTML, los nvegdores hacen como si HTML estuvier bsdo en XML y lo trtn de
l mism form. No obstnte, se hn definido lguns extensiones y prticulriddes especfics
pr XHTML y HTML.

4.4. HTML y DOM


Desfortundmente, ls posibiliddes teo rics de DOM son mucho m s vnzds de ls que se
pueden utilizr en l pr ctic pr desrrollr plicciones web. El motivo es que el uso de DOM
siempre est limitdo por ls posibiliddes que ofrece cd nvegdor. Mientrs que lgunos
nvegdores como Firefox y Sfri implementn DOM de nivel 1 y 2 (y prte del 3), otros
nvegdores como Internet Explorer (versio n 7 y nteriores) ni siquier son cpces de ofrecer
un implementcio n complet de DOM nivel 1.

www.librosweb.es 65
Cundo se utiliz DOM en p gins HTML, el nodo rz de todos los dem s se define en el objeto
HTMLDocument. Adem s, se cren objetos de tipo HTMLElement por cd nodo de tipo Element
del rbol DOM. Como se ver en el siguiente cptulo, el objeto document es prte del BOM
(Browser Object Model), unque tmbie n se consider que es equivlente del objeto Document
del DOM de los documentos XML. Por este motivo, el objeto document tmbie n hce referenci
l nodo rz de tods ls p gins HTML.

4.4.1. Acceso relativo a los nodos


A continucio n se muestr l p gin HTML b sic que se v empler en todos los siguientes
ejemplos:
<html>
<head>
<title>Aprendiendo DOM</title>
</head>
<body>
<p>Aprendiendo DOM</p>
<p>DOM es sencillo de aprender</p>
<p>Ademas, DOM es muy potente</p>
</body>
</html>

L opercio n b sic consiste en obtener el objeto que represent el elemento rz de l p gin:


var objeto_html = document.documentElement;

Despue s de ejecutr l instruccio n nterior, l vrible objeto_html contiene un objeto de tipo


HTMLElement y que represent el elemento <html> de l p gin web. Segu n el rbol de
nodos DOM, desde el nodo <html> derivn dos nodos del mismo nivel jer rquico: <head> y
<body>.

Utilizndo los me todos proporciondos por DOM, es sencillo obtener los elementos <head> y
<body>. En primer lugr, los dos nodos se pueden obtener como el primer y el u ltimo nodo hijo
del elemento <html>:
var objeto_head = objeto_html.firstChild;
var objeto_body = objeto_html.lastChild;

Otr form direct de obtener los dos nodos consiste en utilizr l propiedd childNodes del
elemento <html>:
var objeto_head = objeto_html.childNodes[0];
var objeto_body = objeto_html.childNodes[1];

Si se desconoce el nu mero de nodos hijo que dispone un nodo, se puede empler l propiedd
length de
childNodes:

var numeroDescendientes = objeto_html.childNodes.length;

Adem s, el DOM de HTML permite cceder directmente l elemento <body> utilizndo el


tjo
document.body:

var objeto_body = document.body;


Adem s de ls propieddes nteriores, existen otrs propieddes como previousSibling y
parentNode que se pueden utilizr pr cceder un nodo prtir de otro. Utilizndo ests
propieddes, se pueden comprobr ls siguientes igulddes:
objeto_head.parentNode == objeto_html
objeto_body.parentNode == objeto_html
objeto_body.previousSibling == objeto_head
objeto_head.nextSibling == objeto_body
objeto_head.ownerDocument == document

4.4.2. Tipos de nodos


Un opercio n comu n en muchs plicciones consiste en comprobr el tipo de nodo, que se
obtiene de form direct medinte l propiedd nodeType:
alert(document.nodeType); // 9
alert(document.documentElement.nodeType); // 1

En el primer cso, el vlor 9 es igul l definido en l constnte Node.DOCUMENT_NODE. En el


segundo ejemplo, el vlor 1 coincide con l constnte Node.ELEMENT_NODE. Afortundmente,
no es necesrio memorizr los vlores nume ricos de los tipos de nodos, y que se pueden
empler ls constntes predefinids:
alert(document.nodeType == Node.DOCUMENT_NODE); // true
alert(document.documentElement.nodeType == Node.ELEMENT_NODE); // true

El u nico nvegdor que no soport ls constntes predefinids es Internet Explorer 7 y sus


versiones nteriores, por lo que si se quieren utilizr es necesrio definirls de form explcit:
if(typeof Node == "undefined") {
var Node = { ELEMENT_NODE:
1, ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
};
}

El co digo nterior comprueb si el nvegdor en el que se est ejecutndo tiene definido el


objeto Node. Si este objeto no est definido, se trt del nvegdor Internet Explorer 7 o lgun
versio n nterior, por lo que se cre un nuevo objeto llmdo Node y se le incluyen como
propieddes tods ls constntes definids por DOM.
4.4.3. Atributos
Adem s del tipo de etiquet HTML y su contenido de texto, DOM permite el cceso directo
todos los tributos de cd etiquet. Pr ello, los nodos de tipo Element contienen l
propiedd attributes, que permite cceder todos los tributos de cd elemento. Aunque
te cnicmente l propiedd attributes es de tipo NamedNodeMap, sus elementos se pueden
cceder como si fuer un rry. DOM proporcion diversos me todos pr trtr con los
tributos:

getNamedItem(nombre), devuelve el nodo cuy propiedd nodeName conteng el vlor


nombre.

removeNamedItem(nombre), elimin el nodo cuy propiedd nodeName coincid con el vlor


nombre.

setNamedItem(nodo), n de el nodo l list attributes, index ndolo segu n su propiedd


nodeName.

item(posicion), devuelve el nodo que se encuentr en l posicio n indicd por el vlor


nume rico posicion.

Los me todos nteriores devuelven un nodo de tipo Attr, por lo que no devuelven directmente
el vlor del tributo. Utilizndo estos me todos, es posible procesr y modificr f cilmente los
tributos de los elementos HTML:
<p id="introduccion" style="color: blue">Prrafo de prueba</p>

var p = document.getElementById("introduccion");
var elId = p.attributes.getNamedItem("id").nodeValue; // elId = "introduccion"
var elId = p.attributes.item(0).nodeValue; // elId = "introduccion"
p.attributes.getNamedItem("id").nodeValue = "preintroduccion";

var atributo = document.createAttribute("lang");


atributo.nodeValue = "es";
p.attributes.setNamedItem(atributo);

Afortundmente, DOM proporcion otros me todos que permiten el cceso y l modificcio n de


los tributos de form m s direct:

getAttribute(nombre), es equivlente attributes.getNamedItem(nombre).

setAttribute(nombre, valor) equivlente attributes.getNamedItem(nombre).value


= valor.

removeAttribute(nombre), equivlente attributes.removeNamedItem(nombre) .

De est form, el ejemplo nterior se puede reescribir utilizndo los nuevos me todos:
<p id="introduccion" style="color: blue">Prrafo de prueba</p>

var p = document.getElementById("introduccion");
var elId = p.getAttribute("id"); // elId = "introduccion"
p.setAttribute("id", "preintroduccion");
4.4.4. Acceso directo a los nodos
Los me todos presentdos hst el momento permiten cceder culquier nodo del rbol de
nodos DOM y todos sus tributos. Sin embrgo, ls funciones que proporcion DOM pr
cceder un nodo trve s de sus pdres oblign cceder l nodo rz de l p gin y despue s
sus nodos hijos y los nodos hijos de esos hijos y s sucesivmente hst el u ltimo nodo de l
rm termind por el nodo buscdo.

Cundo se trbj con un p gin web rel, el rbol DOM tiene miles de nodos de todos los tipos.
Por este motivo, no es eficiente cceder un nodo descendiendo trve s de todos los
scendentes de ese nodo.

Pr solucionr este problem, DOM proporcion un serie de me todos pr cceder de form


direct los nodos desedos. Los me todos disponibles son getElementsByTagName(),
getElementsByName() y getElementById().

4.4.4.1. Funcin getElementsByTagName()

L funcio n getElementsByTagName() obtiene todos los elementos de l p gin XHTML cuy


etiquet se igul que el pr metro que se le ps l funcio n.

El siguiente ejemplo muestr co mo obtener todos los p rrfos de un p gin XHTML:


var parrafos = document.getElementsByTagName("p");

El vlor que devuelve l funcio n es un rry con todos los nodos que cumplen l condicio n de
que su etiquet coincide con el pr metro proporciondo. En relidd, el vlor devuelto no es de
tipo rry normal, sino que es un objeto de tipo NodeList. De este modo, el primer p rrfo de l
p gin se puede obtener de l siguiente mner:
var parrafos = document.getElementsByTagName("p");
var primerParrafo = parrafos[0];

De l mism form, se pueden recorrer todos los p rrfos de l p gin recorriendo el rry de
nodos devuelto por l funcio n:
var parrafos = document.getElementsByTagName("p");
for(var i=0; i<parrafos.length; i++) {
var parrafo = parrafos[i];
}

L funcio n getElementsByTagName() se puede plicr de form recursiv sobre cd uno de


los nodos devueltos por l funcio n. En el siguiente ejemplo, se obtienen todos los enlces del
primer p rrfo de l p gin:
var parrafos = document.getElementsByTagName("p");
var primerParrafo = parrafos[0];
var enlaces = primerParrafo.getElementsByTagName("a");

4.4.4.2. Funcin getElementsByName()

L funcio n getElementsByName() obtiene todos los elementos de l p gin XHTML cuyo


tributo
name coincid con el pr metro que se le ps l
funcio n.
En el siguiente ejemplo, se obtiene directmente el u nico p rrfo de l p gin que tiene el
nombre indicdo:
var parrafoEspecial = document.getElementsByName("especial");

<p name="prueba">...</p>
<p name="especial">...</p>
<p>...</p>

Normlmente el tributo name es u nico pr los elementos HTML que lo incluyen, por lo que
es un me todo muy pr ctico pr cceder directmente l nodo desedo. En el cso de los
elementos HTML radiobutton, el tributo name es comu n todos los radiobutton que est n
relciondos, por lo que l funcio n devuelve un coleccio n de elementos.

Internet Explorer 7 y sus versiones nteriores no implementn de form correct est funcio n,
y que tmbie n devuelven los elementos cuyo tributo id se igul l pr metro de l funcio n.

4.4.4.3. Funcin getElementById()

L funcio n getElementById() es l funcio n m s utilizd cundo se desrrolln plicciones


web din mics. Se trt de l funcio n preferid pr cceder directmente un nodo y pr leer
o modificr sus propieddes.

L funcio n getElementById() devuelve el elemento XHTML cuyo tributo id coincide con el


pr metro indicdo en l funcio n. Como el tributo id debe ser u nico pr cd elemento de
un mism p gin, l funcio n devuelve u nicmente el nodo desedo.
var cabecera = document.getElementById("cabecera");

<div id="cabecera">
<a href="/" id="logo">...</a>
</div>

Ejercicio 7

A partir de la pgina web proporcionada y utilizando las funciones DOM, mostrar por pantalla la
siguiente informacin:

1. Nmero de enlaces de la pgina


2. Direccin a la que enlaza el penltimo enlace
3. Numero de enlaces que enlazan a http://prueba
4. Nmero de enlaces del tercer prrafo

Ejercicio 8

A partir de la pgina web proporcionada y utilizando las funciones DOM:

1. Se debe modificar el protocolo de todas las direcciones de los enlaces. De esta forma, si un
enlace apuntaba a http://prueba, ahora debe apuntar a https://prueba
2. Los prrafos de la pgina cuyo atributo class es igual a "importante" deben
modificarlo por "resaltado". El resto de prrafos deben incluir un atributo class igual a
"normal".
3. A los enlaces de la pgina cuyo atributo class sea igual a "importante", se les aade
un atributo "name" con un valor generado automticamente y que sea igual a
"importante"+i, donde i es un valor numrico cuyo valor inicial es 0 para el primer enlace.

4.4.5. Crear, modificar y eliminar nodos


Hst hor, todos los me todos DOM presentdos se limitn cceder los nodos y sus
propieddes. A continucio n, se muestrn los me todos necesrios pr l crecio n, modificcio n
y elimincio n de nodos dentro del rbol de nodos DOM.

Los me todos DOM disponibles pr l crecio n de nuevos nodos son los siguientes:

Mtodo Descripcin
createAttribute(nombre) Crea un nodo de tipo atributo con el nombre indicado

Crea una seccin CDATA con un nodo hijo de tipo texto


createCDataSection(texto) que contiene el valor indicado

Crea un nodo de tipo comentario que contiene el valor


createComment(texto) indicado

createDocumentFragment() Crea un nodo de tipo DocumentFragment


Crea un elemento del tipo indicado en el parmetro
createElement(nombre_etiqueta)
nombre_etiqueta
createEntityReference(nombre) Crea un nodo de tipo EntityReference
createProcessingInstruction(objetivo, Crea un nodo de tipo
ProcessingInstruction
datos)

Crea un nodo de tipo texto con el valor indicado como


createTextNode(texto) parmetro

Internet Explorer no soport los me todos createCDataSection, createEntityReference y


createProcessingInstruction. Los me todos m s empledos son createElement,
createTextNode y createAttribute.

A continucio n se muestr un ejemplo sencillo en el que se cre un nuevo nodo (un nuev
etiquet HTML) y se n de din micmente l siguiente p gin HTML:
<html>
<head><title>Ejemplo de creacin de nodos</title></head>
<body></body>
</html>

L p gin HTML originl no tiene contenidos, pero medinte DOM se n de din micmente el
siguiente p rrfo de texto:
<p>Este prrafo no exista en la pgina HTML original</p>

An dir el p rrfo nterior l p gin requiere los siguientes psos:

1. Crer un nodo de tipo elemento


2. Crer un nodo de tipo texto
3. Asocir el nodo de texto l elemento
4. An dir el nuevo nodo de tipo elemento l p gin originl

En primer lugr, se cre un nuevo nodo de tipo elemento:


var p = document.createElement("p");

A continucio n se cre un nodo de texto que lmcen el contenido de texto del p rrfo:
var texto = document.createTextNode("Este prrafo no exista en la pgina HTML
original");

En tercer lugr, se soci el elemento credo y su contenido de texto (los nodos de tipo Text son
hijos de los nodos de tipo Element):
p.appendChild(texto);

El me todo appendChild() est definido pr todos los diferentes tipos de nodos y se encrg
de n dir un nodo l finl de l list childNodes de otro nodo.

Por u ltimo, se n de el nodo credo l rbol de nodos DOM que represent l p gin.
Utilizndo el me todo appendChild(), se n de el nodo como hijo del nodo que represent l
elemento <body> de l p gin:
document.body.appendChild(p);

L p gin HTML que result despue s de l ejecucio n del co digo JvScript se muestr
continucio n:
<html>
<head><title>Ejemplo de creacin de nodos</title></head>
<body>
<p>Este prrafo no exista en la pgina HTML original</p>
</body>
</html>

Un vez m s, es importnte recordr que ls modificciones en el rbol de nodos DOM so lo se


pueden relizr cundo toda l p gin web se h crgdo en el nvegdor. El motivo es que los
nvegdores construyen el rbol de nodos DOM un vez que se h crgdo completmente l
p gin web. Cundo un p gin no h termindo de crgrse, su rbol no est construido y por
tnto no se pueden utilizr ls funciones DOM.

Si un p gin reliz modificciones utom tics (sin intervencio n del usurio) es importnte
utilizr el evento onload() pr llmr ls funciones de JvScript, tl y como se ver m s
delnte en el cptulo de los eventos.

Por otr prte, tmbie n se pueden utilizr funciones DOM pr eliminr culquier nodo
existente originlmente en l p gin y culquier nodo credo medinte los me todos DOM:

Si se consider l siguiente p gin HTML con un p rrfo de texto:


<html>
<head><title>Ejemplo de eliminacin de nodos</title></head>
<body>
<p>Este parrafo va a ser eliminado dinamicamente</p>
</body>
</html>

En primer lugr, se obtiene l referenci l nodo que se v eliminr:


var p = document.getElementsByTagName("p")[0];

Pr eliminr culquier nodo, se emple l funcio n removeChild(), que tom como rgumento l
referenci l nodo que se quiere eliminr. L funcio n removeChild() se debe invocr sobre el
nodo pdre del nodo que se v eliminr. En este cso, el padre del primer p rrfo de l p gin
es el nodo <body>:
var p = document.getElementsByTagName("p")[0];
document.body.removeChild(p);

L p gin HTML que result despue s de l ejecucio n del co digo JvScript nterior se muestr
continucio n:
<html>
<head><title>Ejemplo de eliminacin de nodos</title></head>
<body></body>
</html>

Cundo l p gin est formd por miles de nodos, puede ser costoso cceder hst el nodo
pdre del nodo que se quiere eliminr. En estos csos, se puede utilizr l propiedd
parentNode, que siempre hce referenci l nodo pdre de un nodo.

De est form, el ejemplo nterior se puede rehcer pr eliminr el nodo hciendo uso de l
propiedd parentNode:
var p = document.getElementsByTagName("p")[0];
p.parentNode.removeChild(p);

Adem s de crer y eliminr nodos, ls funciones DOM tmbie n permiten reemplzr un nodo
por otro. Utilizndo l mism p gin HTML de ejemplo, se v sustituir el p rrfo originl por
otro p rrfo con un contenido diferente. L p gin originl contiene el siguiente p rrfo:
<html>
<head><title>Ejemplo de sustitucin de nodos</title></head>
<body>
<p>Este parrafo va a ser sustituido dinamicamente</p>
</body>
</html>

Utilizndo ls funciones DOM de JvScript, se cre el nuevo p rrfo que se v mostrr en l


p gin, se obtiene l referenci l nodo originl y se emple l funcio n replaceChild() pr
intercmbir un nodo por otro:
var nuevoP = document.createElement("p");
var texto = document.createTextNode("Este parrafo se ha creado dinmicamente y
sustituye al parrafo original");
nuevoP.appendChild(texto);

var anteriorP = document.body.getElementsByTagName("p")[0];


anteriorP.parentNode.replaceChild(nuevoP, anteriorP);
Despue s de ejecutr ls instrucciones nteriores, l p gin HTML resultnte es:
<html>
<head><title>Ejemplo de sustitucin de nodos</title></head>
<body>
<p>Este parrafo se ha creado dinmicamente y sustituye al parrafo original</p>
</body>
</html>

Adem s de crer, eliminr y sustituir nodos, ls funciones DOM permiten insertr nuevos nodos
ntes o despue s de otros nodos y existentes. Si se quiere insertr un nodo despue s de otro, se
emple l funcio n appendChild(). P gin HTML originl:
<html>
<head><title>Ejemplo de insercin de nodos</title></head>
<body>
<p>Primer parrafo</p>
</body>
</html>

El siguiente co digo JvScript cre un nuevo p rrfo y lo insert despue s de culquier otro nodo
de l p gin HTML:
var nuevoP = document.createElement("p");
var texto = document.createTextNode("Segundo parrafo");
nuevoP.appendChild(texto);

document.body.appendChild(nuevoP);

Despue s de ejecutr el co digo JvScript nterior, el co digo HTML resultnte es:


<html>
<head><title>Ejemplo de insercin de nodos</title></head>
<body>
<p>Primer parrafo</p>
<p>Segundo parrafo</p>
</body>
</html>

Si se quiere insetr el nuevo p rrfo delnte del p rrfo existente, se puede utilizr l funcio n
insertBefore(). P gin HTML originl:

<html>
<head><title>Ejemplo de insercin de nodos</title></head>
<body>
<p>Primer parrafo</p>
</body>
</html>

Co digo JvScript necesrio pr insertr un nuevo p rrfo delnte del p rrfo existente:
var nuevoP = document.createElement("p");
var texto = document.createTextNode("Segundo parrafo, antes del primero");
nuevoP.appendChild(texto);

var anteriorP = document.getElementsByTagName("p")[0];


document.body.insertBefore(nuevoP, anteriorP);
Despue s de ejecutr el co digo JvScript nterior, el co digo HTML resultnte es:
<html>
<head><title>Ejemplo de insercin de nodos</title></head>
<body>
<p>Segundo parrafo, antes del primero</p>
<p>Primer parrafo</p>
</body>
</html>

Ejercicio 9

A partir de la pgina HTML que se proporciona, completar el cdigo JavaScript definido para realizar
la siguiente aplicacin sencilla:

Figura 4.4. Inicio de la aplicacin


Figura 4.5. Generacin de nmeros aleatorios

Figura 4.6. Resultado de la comparacin

Inicialmente, la aplicacin cuenta con tres cajas vacas y dos botones. Al presionar el botn de
"Genera", se crean dos nmeros aleatorios. Cada nmero aleatorio se guarda en un elemento <p>,
que a su vez se guarda en una de las dos cajas superiores.

Una vez generados los nmeros, se presiona el botn "Comparar", que compara el valor de los dos
prrafos anteriores y determina cual es el mayor. El prrafo con el nmero ms grande, se mueve a
la ltima caja que se utiliza para almacenar el resultado de la operacin.
La pgina que se proporciona contiene todo el cdigo HTML y CSS necesario. Adems, incluye todo el
cdigo JavaScript relativo a la pulsacin de los botones y que se estudiar con detalle en el siguiente
captulo.

En el ejercicio se deben utilizar entre otras, las funciones getElementById(), createElement(),


createTextNode(), appendChild() y
replaceChild().

4.4.6. Atributos HTML y propiedades CSS en DOM


Los me todos presentdos nteriormente pr el cceso los tributos de los elementos, son
gene ricos de XML. L versio n de DOM especfic pr HTML incluye lguns propieddes y
me todos u n m s directos y sencillos pr el cceso los tributos de los elementos HTML y
sus propieddes CSS.

L principl ventj del DOM pr HTML es que todos los tributos de todos los elementos
HTML se trnsformn en propieddes de los nodos. De est form, es posible cceder de form
direct culquier tributo de HTML. Si se consider el siguiente elemento <img> de HTML
con sus tres tributos:
<img id="logo" src="logo.gif" border="0" />

Emplendo los me todos trdicionles de DOM, se puede cceder y mnipulr cd tributo:


var laImagen = document.getElementById("logo");

// acceder a los atributos


var archivo = laImagen.getAttribute("src");
var borde = laImagen.getAttribute("border");

// modificar los atributos


laImagen.setAttribute("src", "nuevo_logo.gif");
laImagen.setAttribute("border", "1");

L ventj de l especificcio n de DOM pr HTML es que permite cceder y modificr todos los
tributos de los elementos de form direct:
var laImagen = document.getElementById("logo");

// acceder a los atributos


var archivo = laImagen.src;
var borde = laImagen.border;

// modificar los atributos


laImagen.src = "nuevo_logo.gif";
laImagen.border = "1";

Ls ventjs de utilizr est form de cceder y modificr los tributos de los elementos es que
el co digo resultnte es m s sencillo y conciso. Por otr prte, lguns versiones de Internet
Explorer no implementn correctmente el me todo setAttribute(), lo que provoc que, en
ocsiones, los cmbios relizdos no se reflejn en l p gin HTML.

L u nic excepcio n que existe en est form de obtener el vlor de los tributos HTML es el
tributo class. Como l plbr class est reservd por JvScript pr su uso futuro, no es
posible utilizrl pr cceder l vlor del tributo class de HTML. L solucio n consiste en
cceder ese tributo medinte el nombre lterntivo className:
<p id="parrafo" class="normal">...</p>

var parrafo = document.getElementById("parrafo");


alert(parrafo.class); // muestra "undefined"
alert(parrafo.className); // muestra "normal"

El cceso ls propieddes CSS no es tn directo y sencillo como el cceso los tributos HTML.
En primer lugr, los estilos CSS se pueden plicr de vris forms diferentes sobre un mismo
elemento HTML. Si se estblecen ls propieddes CSS medinte el tributo style de HTML:
<p id="parrafo" style="color: #C00">...</p>

El cceso ls propieddes CSS estblecids medinte el tributo style se reliz trve s de


l propiedd style del nodo que represent ese elemento:
var parrafo = document.getElementById("parrafo");
var color = parrafo.style.color;

Pr cceder l vlor de un propiedd CSS, se obtiene l referenci del nodo, se ccede su


propiedd style y continucio n se indic el nombre de l propiedd CSS cuyo vlor se quiere
obtener. Aunque prece lo gico que en el ejemplo nterior el vlor obtenido se #C00, en relidd
cd nvegdor obtiene el mismo vlor de forms diferentes:

Firefox y Sfri muestrn el vlor rgb(204, 0, 0)

Internet Explorer muestr el vlor #c00

Oper muestr el vlor #cc0000

En el cso de ls propieddes CSS con nombre compuesto (font-weight, border-top-style,


list-style-type, etc.), pr cceder su vlor es necesrio modificr su nombre originl
eliminndo los guiones medios y escribiendo en myu sculs l primer letr de cd plbr que
no se l primer:
var parrafo = document.getElementById("parrafo");
var negrita = parrafo.style.fontWeight;

El nombre originl de l propiedd CSS es font-weight. Pr obtener su vlor medinte


JvScript, se elimin el guio n medio (fontweight) y se ps myu sculs l primer letr de
cd plbr que no se l primer (fontWeight).

Si el nombre de l propiedd CSS est formdo por tres plbrs, se reliz l mism
trnsformcio n. De est form, l propiedd border-top-style se ccede en DOM medinte el
nombre borderTopStyle.

Adem s de obtener el vlor de ls propieddes CSS, tmbie n es posible modificr su vlor


medinte JvScript. Un vez obtenid l referenci del nodo, se puede modificr el vlor de
culquier propiedd CSS ccediendo ell medinte l propiedd style:
<p id="parrafo">...</p>
var parrafo = document.getElementById("parrafo");
parrafo.style.margin = "10px"; // aade un margen de 10px al prrafo
parrafo.style.color = "#CCC"; // modifica el color de la letra del prrafo

Todos los ejemplos nteriores hcen uso de l propiedd style pr cceder o estblecer el
vlor de ls propieddes CSS de los elementos. Sin embrgo, est propiedd so lo permite
cceder l vlor de ls propieddes CSS estblecids directmente sobre el elemento HTML. En
otrs plbrs, l propiedd style del nodo so lo contiene el vlor de ls propieddes CSS
estblecids medinte el tributo style de HTML.

Por otr prte, los estilos CSS normlmente se plicn medinte regls CSS incluids en rchivos
externos. Si se utiliz l propiedd style de DOM pr cceder l vlor de un propiedd CSS
estblecid medinte un regl extern, el nvegdor no obtiene el vlor correcto:
// Cdigo HTML
<p id="parrafo">...</p>

// Regla CSS
#parrafo { color: #008000; }

// Cdigo JavaScript
var parrafo = document.getElementById("parrafo");
var color = parrafo.style.color; // color no almacena ningn valor

Pr obtener el vlor de ls propieddes CSS independientemente de co mo se hyn plicdo, es


necesrio utilizr otrs propieddes de JvScript. Si se utiliz un nvegdor de l fmili
Internet Explorer, se hce uso de l propiedd currentStyle. Si se utiliz culquier otro
nvegdor, se puede empler l funcio n getComputedStyle().
// Cdigo HTML
<p id="parrafo">...</p>

// Regla CSS
#parrafo { color: #008000; }

// Cdigo JavaScript para Internet Explorer


var parrafo = document.getElementById("parrafo");
var color = parrafo.currentStyle['color'];

// Cdigo JavaScript para otros navegadores


var parrafo = document.getElementById("parrafo");
var color = document.defaultView.getComputedStyle(parrafo,
'').getPropertyValue('color');

L propiedd currentStyle requiere el nombre de ls propieddes CSS segu n el formto de


JvScript (sin guiones medios), mientrs que l funcio n getPropertyValue() exige el uso del
nombre originl de l propiedd CSS. Por este motivo, l crecio n de plicciones comptibles
con todos los nvegdores se puede complicr en exceso.

A continucio n se muestr un funcio n comptible con todos los nvegdores, cred por el
progrmdor Robert Nymn y publicd en su blog personl (http://www.robertnymn.com/
2006/04/24/get-the-rendered-style-of-n-element/) :
function getStyle(elemento, propiedadCss) {
var valor = "";
if(document.defaultView && document.defaultView.getComputedStyle){
valor = document.defaultView.getComputedStyle(elemento,
'').getPropertyValue(propiedadCss);
}
else if(elemento.currentStyle) {
propiedadCss = propiedadCss.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
valor = elemento.currentStyle[propiedadCss];
}
return valor;
}

Utilizndo l funcio n nterior, es posible rehcer el ejemplo pr que funcione correctmente en


culquier nvegdor:
// Cdigo HTML
<p id="parrafo">...</p>

// Regla CSS
#parrafo { color: #008000; }

// Cdigo JavaScript para cualquier navegador


var parrafo = document.getElementById("parrafo");
var color = getStyle(parrafo, 'color');

4.4.7. Tablas HTML en DOM


Ls tbls son elementos muy comunes en ls p gins HTML, por lo que DOM proporcion
me todos especficos pr trbjr con ells. Si se utilizn los me todos trdicionles, crer un
tbl es un tre tedios, por l grn cntidd de nodos de tipo elemento y de tipo texto que se
deben crer.

Afortundmente, l versio n de DOM pr HTML incluye vris propieddes y me todos pr


crer tbls, fils y columns de form sencill.

Propieddes y me todos de <table>:

Propiedad/Mtodo Descripcin
rows Devuelve un array con las filas de la tabla
tBodies Devuelve un array con todos los <tbody> de la
tabla
insertRow(posicion) Inserta una nueva fila en la posicin indicada dentro del array de filas de la tabla
deleteRow(posicion) Elimina la fila de la posicin indicada

Propieddes y me todos de <tbody>:

Propiedad/Mtodo Descripcin
rows Devuelve un array con las filas del <tbody>
seleccionado
Inserta una nueva fila en la posicin indicada dentro del array de filas del
insertRow(posicion)
<tbody>

deleteRow(posicion) Elimina la fila de la posicin indicada

Propieddes y me todos de <tr>:

Propiedad/Mtodo Descripcin
cells Devuelve un array con las columnas de la fila seleccionada

Inserta una nueva columna en la posicin indicada dentro del array de columnas
insertCell(posicion) de la fila

deleteCell(posicion) Elimina la columna de la posicin indicada

Si se consider l siguiente tbl XHTML:


<table summary="Descripcin de la tabla y su contenido">
<caption>Ttulo de la tabla</caption>
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Cabecera columna 1</th>
<th scope="col">Cabecera columna 2</th>
</tr>
</thead>

<tfoot>
<tr>
<th scope="col"></th>
<th scope="col">Cabecera columna 1</th>
<th scope="col">Cabecera columna 2</th>
</tr>
</tfoot>

<tbody>
<tr>
<th scope="row">Cabecera fila 1</th>
<td>Celda 1 - 1</td>
<td>Celda 1 - 2</td>
</tr>
<tr>
<th scope="row">Cabecera fila 2</th>
<td>Celda 2 - 1</td>
<td>Celda 2 - 2</td>
</tr>
</tbody>

</table>

A continucio n se muestrn lgunos ejemplos de mnipulcio n de tbls XHTML medinte ls


propieddes y funciones especfics de DOM.

Obtener el nu mero totl de fils de l tbl:


var tabla = document.getElementById('miTabla');
var numFilas = tabla.rows.length;

Obtener el nu mero totl de cuerpos de l tbl (secciones <tbody>):


var tabla = document.getElementById('miTabla');
var numCuerpos = tabla.tBodies.length;

Obtener el nu mero de fils del primer cuerpo (seccio n <tbody>) de l tbl:


var tabla = document.getElementById('miTabla');
var numFilasCuerpo = tabla.tBodies[0].rows.length;

Borrr l primer fil de l tbl y l primer fil del cuerpo (seccio n <tbody>):
var tabla = document.getElementById('miTabla');
tabla.deleteRow(0);
tabla.tBodies[0].deleteRow(0);

Borrr l primer column de l primer fil del cuerpo (seccio n <tbody>):


var tabla = document.getElementById('miTabla');
tabla.tBodies[0].rows[0].deleteCell(0);

Obtener el nu mero de columns de l primer prte del cuerpo (seccio n <tbody>):


var tabla = document.getElementById('miTabla');
var numColumnas = tabla.rows[0].cells.length;

Obtener el texto de l primer column de l primer fil del cuerpo (seccio n <tbody>):
var tabla = document.getElementById('miTabla');
var texto = tabla.tBodies[0].rows[0].cells[0].innerHTML;

Recorrer tods ls fils y tods ls columns de l tbl:


var tabla = document.getElementById('miTabla');
var filas = tabla.rows;
for(var i=0; i<filas.length; i++) {
var fila = filas[i];
var columnas = fila.cells;
for(var j=0; j<columnas.length; j++) {
var columna = columnas[j];
// ...
}
}

Insertr un tercer fil l cuerpo (seccio n <tbody>) de l tbl:


var tabla = document.getElementById('miTabla');

// Insertar la tercera fila


tabla.tBodies[0].insertRow(2);

// Crear la columna de tipo <th> que hace de cabecera de fila


var cabecera = document.createElement("th");
cabecera.setAttribute('scope', 'row');
cabecera.innerHTML = 'Cabecera fila 3'
tabla.tBodies[0].rows[2].appendChild(cabecera);
// Crear las dos columnas de datos y aadirlas a la nueva fila
tabla.tBodies[0].rows[2].insertCell(1);
tabla.tBodies[0].rows[2].cells[1].innerHTML = 'Celda 3 - 1';
tabla.tBodies[0].rows[2].insertCell(2);
tabla.tBodies[0].rows[2].cells[2].innerHTML = 'Celda 3 - 2';

Por u ltimo, se muestr de form resumid el co digo JvScript necesrio pr crer l tbl
XHTML del ejemplo nterior:
// Crear <table> y sus dos atributos
var tabla = document.createElement('table');
tabla.setAttribute('id', 'otraTabla');
tabla.setAttribute('summary', 'Descripcin de la tabla y su contenido');

// Crear <caption> y aadirlo a la <table>


var caption = document.createElement('caption');
var titulo = document.createTextNode('Ttulo de la tabla');
caption.appendChild(titulo);
tabla.appendChild(caption);

// Crear seccin <thead>


var thead = document.createElement('thead');
tabla.appendChild(thead);

// Aadir una fila a la seccin <thead>


thead.insertRow(0);

// Aadir las tres columnas de la fila de <thead>


var cabecera = document.createElement('th');
cabecera.innerHTML = '';
thead.rows[0].appendChild(cabecera);

cabecera = document.createElement('th');
cabecera.setAttribute('scope', 'col');
cabecera.innerHTML = 'Cabecera columna 1';
tabla.rows[0].appendChild(cabecera);

cabecera = document.createElement('th');
cabecera.setAttribute('scope', 'col');
cabecera.innerHTML = 'Cabecera columna 2';
tabla.rows[0].appendChild(cabecera);

// La seccin <tfoot> se creara de forma similar a <thead>

// Crear seccin <tbody>


var tbody = document.createElement('tbody');
tabla.appendChild(tbody);

// Aadir una fila a la seccin <tbody>


tbody.insertRow(0);

cabecera = document.createElement("th");
cabecera.setAttribute('scope', 'row');
cabecera.innerHTML = 'Cabecera fila 1'
tabla.tBodies[0].rows[0].appendChild(cabecera);

tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].innerHTML = 'Celda 1 - 1';
// Tambin se podra hacer:
// tbody.rows[0].cells[0].appendChild(document.createTextNode('Celda 1 - 1'));

tbody.rows[0].insertCell(2);
tbody.rows[0].cells[2].innerHTML = 'Celda 1 - 2';

// El resto de filas del <tbody> se creara de la misma forma

// Aadir la tabla creada al final de la pgina


document.body.appendChild(tabla);
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

Captulo 5. BOM (Browser Object Model)


5.1. Introduccin a BOM
Ls versiones 3.0 de los nvegdores Internet Explorer y Netscpe Nvigtor introdujeron el
concepto de Browser Object Model o BOM, que permite cceder y modificr ls propieddes de
ls ventns del propio nvegdor.

Medinte BOM, es posible redimensionr y mover l ventn del nvegdor, modificr el texto
que se muestr en l brr de estdo y relizr muchs otrs mnipulciones no relcionds
con el contenido de l p gin HTML.

El myor inconveniente de BOM es que, l contrrio de lo que sucede con DOM, ningun entidd
se encrg de estndrizrlo o definir unos mnimos de interoperbilidd entre nvegdores.

Algunos de los elementos que formn el BOM son los siguientes:

Crer, mover, redimensionr y cerrr ventns de nvegdor.


Obtener informcio n sobre el propio nvegdor.
Propieddes de l p gin ctul y de l pntll del usurio.
Gestio n de cookies.
Objetos ActiveX en Internet Explorer.

El BOM est compuesto por vrios objetos relciondos entre s. El siguiente esquem muestr
los objetos de BOM y su relcio n:

Figura 5.1. Jerarqua de objetos que forman el BOM

En el esquem nterior, los objetos mostrdos con vrios recudros superpuestos son rrys. El
resto de objetos, representdos por un rect ngulo individul, son objetos simples. En culquier
cso, todos los objetos derivn del objeto window.
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

5.2. El objeto window


El objeto window represent l ventn complet del nvegdor. Medinte este objeto, es posible
mover, redimensionr y mnipulr l ventn ctul del nvegdor. Incluso es posible brir y
cerrr nuevs ventns de nvegdor.

Si un p gin emple frmes, cd uno de ellos se lmcen en el rry frames, que puede ser
ccedido nume ricmente (window.frames[0]) o, si se h indicdo un nombre l frme, medinte
su nombre (window.frames["nombre del frame"]).

Como todos los dem s objetos heredn direct o indirectmente del objeto window, no es
necesrio indicrlo de form explcit en el co digo JvScript. En otrs plbrs:
window.frames[0] == frames[0]
window.document == document

BOM define cutro me todos pr mnipulr el tmn o y l posicio n de l ventn:

moveBy(x, y) desplz l posicio n de l ventn x pxel hci l derech y y pxel hci


bjo. Se permiten desplzmientos negtivos pr mover l ventn hci l izquierd o
hci rrib.
moveTo(x, y) desplz l ventn del nvegdor hst que l esquin superior
izquierd se encuentre en l posicio n (x, y) de l pntll del usurio. Se permiten
desplzmientos negtivos, unque ello supong que prte de l ventn no se visuliz en
l pntll.
resizeBy(x, y) redimension l ventn del nvegdor de form que su nuev nchur
se igul (anchura_anterior + x) y su nuev ltur se igul (altura_anterior +
y). Se pueden empler vlores negtivos pr reducir l nchur y/o ltur de l ventn.

resizeTo(x, y) redimension l ventn del nvegdor hst que su nchur se igul x


y su ltur se igul y. No se permiten vlores negtivos.

Los nvegdores son cd vez menos permisivos con l modificcio n medinte JvScript de ls
propieddes de sus ventns. De hecho, l myor de nvegdores permite los usurios
bloquer el uso de JvScript pr relizr cmbios de este tipo. De est form, un pliccio n
nunc debe suponer que este tipo de funciones est n disponibles y funcionn de form corret.

A continucio n se muestrn lgunos ejemplos de uso de ests funciones:


// Mover la ventana 20 pxel hacia la derecha y 30 pxel hacia abajo
window.moveBy(20, 30);

// Redimensionar la ventana hasta un tamao de 250 x 250


window.resizeTo(250, 250);

// Agrandar la altura de la ventana en 50 pxel


window.resizeBy(0, 50);

// Colocar la ventana en la esquina izquierda superior de la ventana


window.moveTo(0, 0);
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

Adem s de desplzr y redimensionr l ventn del nvegdor, es posible verigur l posicio n


y tmn o ctul de l ventn. Sin embrgo, l usenci de un est ndr pr BOM provoc que
cd nvegdor implemente su propio me todo:

Internet Explorer proporcion ls propieddes window.screenLeft y window.screenTop


pr obtener ls coordends de l posicio n de l ventn. No es posible obtener el
tmn o de l ventn complet, sino solmente del re visible de l p gin (es decir, sin
brr de estdo ni menu s). Ls propieddes que proporcionn ests dimensiones son
document.body.offsetWidth y document.body.offsetHeight.

Los nvegdores de l fmili Mozill, Sfri y Oper proporcionn ls propieddes


window.screenX y window.screenY pr obtener l posicio n de l ventn. El tmn o de
l zon visible de l ventn se obtiene medinte window.innerWidth y
window.innerHeight, mientrs que el tmn o totl de l ventn se obtiene medinte
window.outerWidth y window.outerHeight.

Al contrrio que otros lengujes de progrmcio n, JvScript no incorpor un me todo wait()


que deteng l ejecucio n del progrm durnte un tiempo determindo. Sin embrgo, JvScript
proporcion los me todos setTimeout() y setInterval() que se pueden empler pr
relizr tres similres.

El me todo setTimeout() permite ejecutr un funcio n l trnscurrir un determindo periodo


de tiempo:
setTimeout("alert('Han transcurrido 3 segundos desde que me programaron')", 3000);

El me todo setTimeout() requiere dos rgumentos. El primero es el co digo que se v ejecutr


o un referenci l funcio n que se debe ejecutr. El segundo rgumento es el tiempo, en
milisegundos, que se esper hst que comienz l ejecucio n del co digo. El ejemplo nterior se
puede rehcer utilizndo un funcio n:
function muestraMensaje() {
alert("Han transcurrido 3 segundos desde que me programaron");
}

setTimeout(muestraMensaje, 3000);

Como es hbitul, cundo se indic l referenci l funcio n no se incluyen los pre ntesis, y que
de otro modo, se ejecut l funcio n en el mismo instnte en que se estblece el intervlo de
ejecucio n.

Cundo se estblece un cuent tr s, l funcio n setTimeout() devuelve el identificdor de


es nuev cuent tr s. Emplendo ese identificdor y l funcio n clearTimeout() es posible
impedir que se ejecute el co digo pendiente:
function muestraMensaje() {
alert("Han transcurrido 3 segundos desde que me programaron");
}
var id = setTimeout(muestraMensaje, 3000);

// Antes de que transcurran 3 segundos, se decide eliminar la ejecucin pendiente


clearTimeout(id);
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

Ls funciones de timeout son imprescindibles pr crer plicciones profesionles, y que


permiten, por ejemplo, que un script no espere infinito tiempo pr obtener el resultdo de un
funcio n.

En este cso, l estrtegi consiste en estblecer un cuent tr s ntes de llmr l funcio n. Si


l funcio n se ejecut correctmente, en cunto finlice su ejecucio n se elimin l cuent tr s y
continu l ejecucio n norml del script. Si por culquier motivo l funcio n no se ejecut
correctmente, l cuent tr s se cumple y l pliccio n puede informr l usurio o reintentr
l ejecucio n de l funcio n.

Adem s de progrmr l ejecucio n futur de un funcio n, JvScript tmbie n permite estblecer


l ejecucio n perio dic y repetitiv de un funcio n. El me todo necesrio es setInterval() y su
funcionmiento es ide ntico l mostrdo pr setTimeout():
function muestraMensaje() {
alert("Este mensaje se muestra cada segundo");
}

setInterval(muestraMensaje, 1000);

De form n log clearTimeout(), tmbie n existe un me todo que permite eliminr un


repeticio n perio dic y que en este cso se denomin clearInterval():
function muestraMensaje() {
alert("Este mensaje se muestra cada segundo");
}

var id = setInterval(muestraMensaje, 1000);

// Despues de ejecutarse un determinado nmero de veces, se elimina el intervalo


clearInterval(id);

5.3. El objeto document


El objeto document es el u nico que pertenece tnto l DOM (como se vio en el cptulo
nterior) como l BOM. Desde el punto de vist del BOM, el objeto document proporcion
informcio n sobre l propi p gin HTML.

Alguns de ls propieddes m s importntes definids por el objeto document


son:

Propiedad Descripcin
lastModified La fecha de la ltima modificacin de la pgina
La URL desde la que se accedi a la pgina (es decir, la pgina anterior en el array
referrer
history)

title El texto de la etiqueta <title>


URL La URL de la pgina actual del navegador

Ls propieddes title y URL son de lectur y escritur, por lo que dem s de obtener su
vlor, se puede estblecer de form direct:
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

// modificar el ttulo de la pgina


document.title = "Nuevo titulo";

// llevar al usuario a otra pgina diferente


document.URL = "http://nueva_pagina";

Adem s de propieddes, el objeto document contiene vrios rrys con informcio n sobre
lgunos elementos de l p gin:

Array Descripcin
anchors Contiene todas las "anclas" de la pgina (los enlaces de tipo <a name="nombre_ancla"></a>)
applets Contiene todos los applets de la pgina
embeds Contiene todos los objetos embebidos en la pgina mediante la etiqueta <embed>
forms Contiene todos los formularios de la pgina
images Contiene todas las imgenes de la pgina

Contiene todos los enlaces de la pgina (los elementos de tipo <a


links href="enlace.html"></a>)

Los elementos de cd rry del objeto document se pueden cceder medinte su ndice
nume rico o medinte el nombre del elemento en l p gin HTML. Si se consider por ejemplo l
siguiente p gin HTML:
<html>
<head><title>Pagina de ejemplo</title></head>
<body>
<p>Primer parrafo de la pagina</p>
<a href="otra_pagina.html">Un enlace</a>
<img src="logo.jpg" name="logotipo"/>
<form method="post" name="consultas">
<input type="text" name="id" />
<input type="submit" value="Enviar">
</form>
</body>
</html>

Pr cceder los elementos de l p gin se pueden empler ls funciones DOM o los objetos de
BOM:

P rrfo: document.getElementsByTagName("p")

Enlce: document.links[0]

Imgen: document.images[0] o document.images["logotipo"]

Formulrio: document.forms[0] o document.forms["consultas"]

Un vez obtenid l referenci l elemento, se puede cceder l vlor de sus tributos HTML
utilizndo ls propieddes de DOM. De est form, el me todo del formulrio se obtiene medinte
document.forms["consultas"].method y l rut de l imgen es document.images[0].src.
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)

5.4. El objeto location


El objeto location es uno de los objetos m s u tiles del BOM. Debido l flt de estndrizcio n,
location es un propiedd tnto del objeto window como del objeto document.

El objeto location represent l URL de l p gin HTML que se muestr en l ventn del
nvegdor y proporcion vris propieddes u tiles pr el mnejo de l URL:

Propiedad Descripcin
El contenido de la URL que se encuentra despus del signo # (para los enlaces de las anclas)
Introduccin a AJAX Captulo 5. BOM (Browser Object Model)
hash http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
hash = #seccion
host
El nombre del servidor
http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
hostname
host = www.ejemplo.com
La mayora de las veces coincide con host, aunque en ocasiones, se eliminan las www
del principio
href http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
hostname = www.ejemplo.com
pathname
La URL completa de la pgina actual
http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
URL = http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
port
Todo el contenido que se encuentra despus del host
http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
pathname = /ruta1/ruta2/pagina.html
Si se especifica en la URL, el puerto accedido
protocol http://www.ejemplo.com:8080/ruta1/ruta2/pagina.html#seccion
port = 8080
La mayora de URL no proporcionan un puerto, por lo que su contenido es vaco
http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
search port = (vaco)
El protocolo empleado por la URL, es decir, todo lo que se encuentra antes de las dos barras
inclinadas //
http://www.ejemplo.com/ruta1/ruta2/pagina.html#seccion
protocol = http:
Todo el contenido que se encuentra tras el smbolo ?, es decir, la consulta o "query string"
http://www.ejemplo.com/pagina.php?variable1=valor1&variable2=valor2
search = ?variable1=valor1&variable2=valor2

De tods ls propieddes, l m s utilizd es location.href, que permite obtener o estblecer l


direccio n de l p gin que se muestr en l ventn del nvegdor.

Adem s de ls propieddes de l tbl nterior, el objeto location contiene numerosos me todos


y funciones. Algunos de los me todos m s u tiles son los siguientes:
// Mtodo assign()
location.assign("http://www.ejemplo.com");
// Equivalente a location.href = "http://www.ejemplo.com"
// Mtodo replace()
location.replace("http://www.ejemplo.com");
// Similar a assign(), salvo que se borra la pgina actual del array history del
navegador

// Mtodo reload()
location.reload(true);
/* Recarga la pgina. Si el argumento es true, se carga la pgina desde el servidor.
Si es false, se carga desde la cache del navegador */

5.5. El objeto navigator


El objeto navigator es uno de los primeros objetos que incluyo el BOM y permite obtener
informcio n sobre el propio nvegdor. En Internet Explorer, el objeto navigator tmbie n se
puede cceder trve s del objeto clientInformation.

Aunque es uno de los objetos menos estndrizdos, lguns de sus propieddes son comunes
en csi todos los nvegdores. A continucio n se muestrn lguns de ess propieddes:

Propiedad Descripcin
appCodeName Cadena que representa el nombre del navegador (normalmente es Mozilla)
appName Cadena que representa el nombre oficial del navegador

(Slo Internet Explorer) Cadena que representa informacin extra sobre la versin del
appMinorVersion navegador

appVersion Cadena que representa la versin del navegador


browserLanguage Cadena que representa el idioma del navegador
cookieEnabled Boolean que indica si las cookies estn habilitadas

(Slo Internet Explorer) Cadena que representa el tipo de CPU del usuario ("x86",
cpuClass "68K", "PPC", "Alpha", "Other")

javaEnabled Boolean que indica si Java est habilitado language


Cadena que representa el idioma del navegador mimeTypes Array
de los tipos MIME registrados por el navegador
onLine (Slo Internet Explorer) Boolean que indica si el navegador est conectado a Internet
oscpu (Slo Firefox) Cadena que representa el sistema operativo o la CPU
platform Cadena que representa la plataforma sobre la que se ejecuta el navegador
plugins Array con la lista de plugins instalados en el navegador
preference() (Slo Firefox) Mtodo empleado para establecer preferencias en el navegador
product Cadena que representa el nombre del producto (normalmente, es Gecko)

Cadena que representa informacin adicional sobre el producto (normalmente, la


productSub versin del motor Gecko)

securityPolicy Slo Firefox


systemLanguage (Slo Internet Explorer) Cadena que representa el idioma del sistema operativo

Cadena que representa la cadena que el navegador emplea para identificarse en los
userAgent servidores

userLanguage (Slo Explorer) Cadena que representa el idioma del sistema operativo
userProfile (Slo Explorer) Objeto que permite acceder al perfil del usuario

El objeto navigator se emple hbitulmente pr detectr el tipo y/o versio n del nvegdor
en ls plicciones cuyo co digo difiere pr cd nvegdor. Adem s, se emple pr detectr si
el nvegdor tiene hbilitds ls cookies y Jv y tmbie n pr comprobr los plugins
disponibles en el nvegdor.

5.6. El objeto screen


El objeto screen se utiliz pr obtener informcio n sobre l pntll del usurio. Uno de los
dtos m s importntes que proporcion el objeto screen es l resolucio n del monitor en el
que se est n visulizndo ls p gins. Los disen dores de p gins web necesitn conocer ls
resoluciones m s utilizds por los usurios pr dptr sus disen os ess resoluciones.

Ls siguientes propieddes est n disponibles en el objeto screen:

Propiedad Descripcin
availHeight Altura de pantalla disponible para las ventanas
availWidth Anchura de pantalla disponible para las ventanas
colorDepth Profundidad de color de la pantalla (32 bits normalmente)
height Altura total de la pantalla en pxel
width Anchura total de la pantalla en pxel

L ltur/nchur de pntll disponible pr ls ventns es menor que l ltur/nchur totl


de l pntll, y que se tiene en cuent el tmn o de los elementos del sistem opertivo como
por ejemplo l brr de tres y los bordes de ls ventns del nvegdor.

Adem s de l elborcio n de estdstics de los equipos de los usurios, ls propieddes del


objeto screen se utilizn por ejemplo pr determinr co mo y cunto se puede
redimensionr un ventn y pr colocr un ventn centrd en l pntll del usurio.

El siguiente ejemplo redimension un nuev ventn l tmn o m ximo posible segu n l


pntll del usurio:
window.moveTo(0, 0);
window.resizeTo(screen.availWidth, screen.availHeight);
Introduccin a AJAX Captulo 6. Eventos

Captulo 6. Eventos
En l progrmcio n trdicionl, ls plicciones se ejecutn secuencilmente de principio fin
pr producir sus resultdos. Sin embrgo, en l ctulidd el modelo predominnte es el de l
progrmcio n bsd en eventos. Los scripts y progrms espern sin relizr ningun tre
hst que se produzc un evento. Un vez producido, ejecutn lgun tre socid l
pricio n de ese evento y cundo concluye, el script o progrm vuelve l estdo de esper.

JvScript permite relizr scripts con mbos me todos de progrmcio n: secuencil y bsd en
eventos. Los eventos de JvScript permiten l interccio n entre ls plicciones JvScript y los
usurios. Cd vez que se puls un boto n, se produce un evento. Cd vez que se puls un tecl,
tmbie n se produce un evento. No obstnte, pr que se produzc un evento no es obligtorio
que interveng el usurio, y que por ejemplo, cd vez que se crg un p gin, tmbie n se
produce un evento.

El nivel 1 de DOM no incluye especificciones reltivs los eventos JvScript. El nivel 2 de


DOM incluye ciertos spectos relciondos con los eventos y el nivel 3 de DOM incluye l
especificcio n complet de los eventos de JvScript. Desfortundmente, l especificcio n de
nivel 3 de DOM se publico en el n o 2004, m s de diez n os despue s de que los primeros
nvegdores incluyern los eventos.

Por este motivo, muchs de ls propieddes y me todos ctules relciondos con los eventos son
incomptibles con los de DOM. De hecho, nvegdores como Internet Explorer trtn los eventos
siguiendo su propio modelo incomptible con el est ndr.

6.1. Modelo bsico de eventos


El modelo simple de eventos se introdujo en l versio n 4 del est ndr HTML y se consider prte
del nivel m s b sico de DOM. Aunque sus crcterstics son limitds, es el u nico modelo que es
comptible con todos los nvegdores y por tnto, el u nico que permite crer plicciones que
funcionn de l mism mner en todos los nvegdores.

6.1.1. Tipos de eventos


Cd elemento XHTML tiene definid su propi list de posibles eventos que se le pueden
signr. Un mismo tipo de evento (por ejemplo, pinchr el boto n izquierdo del rto n) puede
estr definido pr vrios elementos XHTML y un mismo elemento XHTML puede tener
socidos diferentes eventos.

El nombre de los eventos se construye medinte el prefijo on, seguido del nombre en ingle s de l
ccio n socid l evento. As, el evento de pinchr un elemento con el rto n se denomin
onclick y el evento socido l ccio n de mover el rto n se denomin onmousemove.

L siguiente tbl resume los eventos m s importntes definidos por JvScript:

Evento Descripcin Elementos para los que est definido


Introduccin a AJAX Captulo 6. Eventos

<button>, <input>, <label>, <select>,


onblur Deseleccionar el elemento
<textarea>, <body>
Deseleccionar un elemento que se ha
onchange <input>, <select>, <textarea>
modificado
onclick Pinchar y soltar el ratn Todos los elementos
ondblclick Pinchar dos veces seguidas con el ratn Todos los elementos
<button>, <input>, <label>, elect>,
onfocus Seleccionar un elemento <s
<textarea>, <body>
onkeydown Pulsar una tecla y no soltarla
Elementos de formulario y <body>
onkeypress Pulsar una tecla Elementos de formulario y <body>
onkeyup Soltar una tecla pulsada Elementos de formulario y <body>
onload Pgina cargada completamente <body>
onmousedown Pulsar un botn del ratn y no soltarlo Todos los elementos
onmousemove Mover el ratn Todos los elementos
onmouseout El ratn "sale" del elemento Todos los elementos
onmouseover El ratn "entra" en el elemento Todos los elementos
onmouseup Soltar el botn del ratn Todos los elementos
onreset Inicializar el formulario <form>
onresize Modificar el tamao de la ventana <body>
onselect Seleccionar un texto <input>, <textarea>
onsubmit Enviar el formulario

Se abandona la pgina, por ejemplo al <body>


onunload cerrar el navegador

Algunos de los eventos nteriores (onclick, onkeydown, onkeypress, onreset y onsubmit)


permiten evitr el comportmiento por defecto del evento si se devuelve el vlor false, tl y
como se ver m s delnte.

Por otr prte, ls cciones tpics que reliz un usurio en un p gin web pueden dr lugr
un sucesio n de eventos. Si se puls por ejemplo sobre un boto n de tipo submit se
desencdenn los eventos onmousedown, onmouseup, onclick y onsubmit.

6.1.2. Manejadores de eventos


En l progrmcio n orientd eventos, ls plicciones espern que se produzcn los
eventos. Un vez que se produce un evento, l pliccio n responde ejecutndo cierto co digo
especilmente preprdo. Este tipo de co digo se denomin "manejadores de eventos" (del ingle s
"event handlers") y ls funciones externs que se definen pr responder los eventos se suelen
denominr "funciones manejadoras".

En ls siguientes secciones se presentn ls tres forms m s utilizds pr indicr el co digo que


se ejecut cundo se produce un evento.
Introduccin a AJAX Captulo 6. Eventos

6.1.2.1. Manejadores como atributos XHTML

L form m s sencill de incluir un mnejdor de evento es medinte un tributo de XHTML. El


siguiente ejemplo muestr un mensje cundo el usurio pinch en el boto n:
<input type="button" value="Pinchame y vers" onclick="alert('Gracias por pinchar');" />

Figura 6.1. Pgina HTML

Figura 6.2. El usuario pincha con el ratn sobre el botn que se muestra

Figura 6.3. Despus de pinchar con el ratn, se muestra un mensaje en una nueva ventana

El me todo consiste en incluir un tributo XHTML con el mismo nombre del evento que se quiere
procesr. En este cso, como se quiere mostrr un mensje cundo se pinch con el rto n sobre
un boto n, el evento es onclick.

El contenido del tributo es un cden de texto que contiene tods ls instrucciones JvScript
que se ejecutn cundo se produce el evento. En este cso, el co digo JvScript es muy sencillo,
y que solmente se trt de mostrr un mensje medinte l funcio n alert().

En este otro ejemplo, se muestr un mensje cundo l p gin se h crgdo completmente:


Introduccin a AJAX Captulo 6. Eventos

<body onload="alert('La pgina se ha cargado completamente');">


...
</body>

El evento onload es uno de los m s utilizdos porque, como se vio en el cptulo de DOM, ls
funciones de cceso y mnipulcio n de los nodos del rbol DOM solmente est n disponibles
cundo l p gin se crg por completo.

6.1.2.2. Manejadores de eventos y variable this

En los eventos de JvScript, se puede utilizr l plbr reservd this pr referirse l


elemento XHTML sobre el que se est ejecutndo el evento. Est te cnic es u til pr ejemplos
como el siguiente, en el que se modificn ls propieddes del elemento que provoc el evento.

En el siguiente ejemplo, se muestr un borde destcdo en el elemento <div> cundo el


usurio ps el rto n por encim. Cundo el rto n sle del <div>, se vuelve mostrr el borde
originl:
<div id="elemento" style="padding: .2em; width: 150px; height: 60px; border: thin solid
silver" onmouseover = "document.getElementById('elemento').style.borderColor = 'black'"
onmouseout = "document.getElementById('elemento').style.borderColor = 'silver'">
Seccin de contenidos...
</div>

El evento onmouseover se ctiv cundo el rto n ps por encim del elemento, en este cso el
<div>. Pr cmbir el color del borde, se utiliz l propiedd border-color de CSS. Por lo
tnto, en primer lugr se obtiene l referenci del elemento medinte
document.getElementById('elemento') . A continucio n, se utiliz l propiedd style pr
cceder ls propieddes CSS y se modific el nombre de border-color por el de
borderColor. Pr volver l color originl cundo el rto n sle del elemento, se reliz l mism
opercio n sobre el evento onmouseout.

El uso de l vrible this puede simplificr todos estos psos, y que dentro de un mnejdor
de eventos, l vrible this equivle l elemento que h provocdo el evento. As, l vrible
this es igul l <div> de l p gin y por tnto this.style.borderColor permite cmbir de
form direct el color del borde del <div>:
<div style="padding: .2em; width: 150px; height: 60px; border: thin solid silver"
onmouseover="this.style.borderColor='black'"
onmouseout="this.style.borderColor='silver'">
Seccin de contenidos...
</div>

Hciendo uso de l vrible this, el co digo es mucho m s sencillo de escribir, leer y mntener.

6.1.2.3. Manejadores de eventos como funciones externas

L definicio n de mnejdores de eventos en los tributos XHTML es un me todo sencillo pero


poco consejble pr trtr con los eventos en JvScript. El principl inconveniente es que se
complic en exceso en cunto se n den lguns pocs instrucciones, por lo que solmente es
recomendble pr los csos m s sencillos.
Introduccin a AJAX Captulo 6. Eventos

Cundo el co digo de l funcio n mnejdor es m s complejo, como por ejemplo l vlidcio n de


un formulrio, es consejble grupr todo el co digo JvScript en un funcio n extern que se
invoc desde el co digo XHTML cundo se produce el evento.

De est form, el siguiente ejemplo:


<input type="button" value="Pinchame y vers" onclick="alert('Gracias por pinchar');" />

Se puede trnsformr en:


function muestraMensaje() {
alert('Gracias por pinchar');
}

<input type="button" value="Pinchame y vers" onclick="muestraMensaje()" />

En ls funciones externs no es posible utilizr l vrible this de l mism form que en los
mnejdores insertdos en los tributos XHTML. Por tnto, es necesrio psr l vrible this
como pr metro l funcio n mnejdor:
function resalta(elemento) {
switch(elemento.style.borderColor) {
case 'silver':
case 'silver silver silver silver':
case '#c0c0c0':
elemento.style.borderColor = 'black';
break;
case 'black':
case 'black black black black':
case '#000000':
elemento.style.borderColor = 'silver';
break;
}
}

<div style="padding: .2em; width: 150px; height: 60px; border: thin solid silver"
onmouseover="resalta(this)" onmouseout="resalta(this)">
Seccin de contenidos...
</div>

En el ejemplo nterior, l funcio n extern se le ps el pr metro this, que dentro de l


funcio n se denomin elemento. Al psr this como pr metro, es posible cceder de form
direct desde l funcio n extern ls propieddes del elemento que h provocdo el evento.

Por otr prte, el ejemplo nterior se complic por l form en l que los distintos nvegdores
lmcenn el vlor de l propiedd borderColor. Mientrs que Firefox lmcen (en cso de que
los cutro bordes coincidn en color) el vlor simple black, Internet Explorer lo lmcen como
black black black black y Oper lmcen su representcio n hexdeciml #000000.

6.1.2.4. Manejadores de eventos semnticos

Utilizr los tributos XHTML o ls funciones externs pr n dir mnejdores de eventos tiene
un grve inconveniente: "ensucian" el co digo XHTML de l p gin.
Introduccin a AJAX Captulo 6. Eventos

Como es conocido, l crer p gins web se recomiend seprr los contenidos (XHTML) de l
presentcio n (CSS). En lo posible, tmbie n se recomiend seprr los contenidos (XHTML) de l
progrmcio n (JvScript). Mezclr JvScript y XHTML complic excesivmente el co digo
fuente de l p gin, dificult su mntenimiento y reduce l sem ntic del documento finl
producido.

Afortundmente, existe un me todo lterntivo pr definir los mnejdores de eventos de


JvScript. Est te cnic consiste en signr ls funciones externs medinte ls propieddes
DOM de los elementos XHTML. As, el siguiente ejemplo:
<input id="pinchable" type="button" value="Pinchame y vers" onclick="alert('Gracias
por pinchar');" />

Se puede trnsformr en:


function muestraMensaje() {
alert('Gracias por pinchar');
}
document.getElementById("pinchable").onclick = muestraMensaje;

<input id="pinchable" type="button" value="Pinchame y vers" />

El co digo XHTML resultnte es muy "limpio", y que no se mezcl con el co digo JvScript. L
te cnic de los mnejdores sem nticos consiste en:

1. Asignr un identificdor u nico l elemento XHTML medinte el tributo id.


2. Crer un funcio n de JvScript encrgd de mnejr el evento.
3. Asignr l funcio n un evento concreto del elemento XHTML medinte DOM.

Otr ventj dicionl de est te cnic es que ls funciones externs pueden utilizr l vrible
this referid l elemento que originl el
evento.

Asignr l funcio n mnejdor medinte DOM es un proceso que requiere un expliccio n


detlld. En primer lugr, se obtiene l referenci del elemento l que se v signr el
mnejdor:
document.getElementById("pinchable");

A continucio n, se sign l funcio n extern l evento desedo medinte un propiedd del


elemento con el mismo nombre del evento:
document.getElementById("pinchable").onclick = ...

Por u ltimo, se sign l funcio n extern. Como y se h comentdo en cptulos nteriores, lo


m s importnte (y l cus m s comu n de errores) es indicr solmente el nombre de l funcio n,
es decir, prescindir de los pre ntesis l signr l funcio n:
document.getElementById("pinchable").onclick = muestraMensaje;

Si se n den los pre ntesis l finl, en relidd se est invocndo l funcio n y signndo el vlor
devuelto por l funcio n l evento onclick de elemento.

El u nico inconveniente de este me todo es que los mnejdores se signn medinte ls


funciones DOM, que solmente se pueden utilizr despue s de que l p gin se h crgdo
Introduccin a AJAX Captulo 6. Eventos

completmente. De est form, pr que l signcio n de los mnejdores no resulte erro ne, es
necesrio segurrse de que l p gin y se h crgdo.

Un de ls forms m s sencills de segurr que cierto co digo se v ejecutr despue s de que l


p gin se crgue por completo es utilizr el evento onload:
window.onload = function() {
document.getElementById("pinchable").onclick = muestraMensaje;
}

L te cnic nterior utiliz un funcio n no nim pr signr lguns instrucciones l evento


onload de l p gin (en este cso se h estblecido medinte el objeto window). De est
form, pr segurr que cierto co digo se v ejecutr despue s de que l p gin se hy
crgdo, so lo es necesrio incluirlo en el interior de l siguiente construccio n:
window.onload = function() {
...
}

Ejercicio 10

A partir de la pgina web proporcionada y utilizando manejadores de eventos semnticos, completar


el cdigo JavaScript para que:

1. Cuando se pinche sobre el primer enlace, se oculte su seccin relacionada


2. Cuando se vuelva a pinchar sobre el mismo enlace, se muestre otra vez esa seccin de
contenidos
3. Completar el resto de enlaces de la pgina para que su comportamiento sea idntico al del
primer enlace

Cuando la seccin se oculte, debe cambiar el mensaje del enlace asociado (pista: propiedad
innerHTML).

6.2. El flujo de eventos


Adem s de los eventos b sicos que se hn visto, los nvegdores incluyen un mecnismo
relciondo llmdo flujo de eventos o "event flow". El flujo de eventos permite que vrios
elementos diferentes puedn responder un mismo evento.

Si en un p gin HTML se define un elemento <div> con un boto n en su interior, cundo el


usurio puls sobre el boto n, el nvegdor permite signr un funcio n de respuest l boto n,
otr funcio n de respuest l <div> que lo contiene y otr funcio n de respuest l p gin
complet. De est form, un solo evento (l pulscio n de un boto n) provoc l respuest de tres
elementos de l p gin (incluyendo l propi p gin).

El orden en el que se ejecutn los eventos signdos cd elemento de l p gin es lo que


constituye el flujo de eventos. Adem s, existen muchs diferencis en el flujo de eventos de cd
nvegdor.
Introduccin a AJAX Captulo 6. Eventos

6.2.1. Event bubbling


En este modelo de flujo de eventos, el orden que se sigue es desde el elemento m s especfico
hst el elemento menos especfico.

En los pro ximos ejemplos se emple l siguiente p gin HTML:


<html onclick="procesaEvento()">
<head><title>Ejemplo de flujo de eventos</title></head>
<body onclick="procesaEvento()">
<div onclick="procesaEvento()">Pincha aqui</div>
</body>
</html>

Cundo se puls sobre el texto "Pinch qu" que se encuentr dentro del <div>, se ejecutn los
siguientes eventos en el orden que muestr el siguiente esquem:

Figura 6.4. Esquema del funcionamiento del "event bubbling"

El primer evento que se tiene en cuent es el generdo por el <div> que contiene el mensje.
A continucio n el nvegdor recorre los scendentes del elemento hst que lcnz el nivel
superior, que es el elemento document.

Este modelo de flujo de eventos es el que incluye el nvegdor Internet Explorer. Los nvegdores
de l fmili Mozill (por ejemplo Firefox) tmbie n soportn este modelo, pero ligermente
modificdo. El nterior ejemplo en un nvegdor de l fmili Mozill present el siguiente flujo
de eventos:
Introduccin a AJAX Captulo 6. Eventos

Figura 6.5. Esquema del funcionamiento del "event bubbling" en los navegadores de Mozilla (por
ejemplo, Firefox)

Aunque el objeto window no es prte del DOM, el flujo de eventos implementdo por Mozill
recorre los scendentes del elemento hst el mismo objeto window, n diendo por tnto un
evento m s l modelo de Internet Explorer.

6.2.2. Event capturing


En ese otro modelo, el flujo de eventos se define desde el elemento menos especfico hst el
elemento m s especfico. En otrs plbrs, el mecnismo definido es justmente el contrrio l
"event bubbling". Este modelo lo utilizb el desprecido nvegdor Netscpe Nvigtor 4.0.

6.2.3. Eventos DOM


El flujo de eventos definido en l especificcio n DOM soport tnto el bubbling como el
capturing, pero el "event capturing" se ejecut en primer lugr. Los dos flujos de eventos
recorren todos los objetos DOM desde el objeto document hst el elemento m s especfico y
vicevers. Adem s, l myor de nvegdores que implementn los est ndres, continu n el
flujo hst el objeto window.

El flujo de eventos DOM del ejemplo nterior se muestr continucio n:

Figura 6.6. Esquema del flujo de eventos del modelo DOM

El elemento m s especfico del flujo de eventos no es el <div> que desencden l ejecucio n


de los eventos, sino el nodo de tipo TextNode que contiene el <div>. El hecho de combinr los
dos flujos de eventos, provoc que el nodo m s especfico pued ejecutr dos eventos de form
consecutiv.
Introduccin a AJAX Captulo 6. Eventos

6.3. Handlers y listeners


En ls secciones nteriores se introdujo el concepto de "event handler" o mnejdor de eventos,
que son ls funciones que responden los eventos que se producen. Adem s, se vieron tres
forms de definir los mnejdores de eventos pr el modelo b sico de eventos:

1. Co digo JvScript dentro de un tributo del propio elemento HTML


2. Definicio n del evento en el propio elemento HTML pero el mnejdor es un funcio n
extern
3. Mnejdores sem nticos signdos medinte DOM sin necesidd de modificr el co digo
HTML de l p gin

Culquier de estos tres modelos funcion correctmente en todos los nvegdores disponibles
en l ctulidd. Ls diferencis entre nvegdores surgen cundo se define m s de un
mnejdor de eventos pr un mismo evento de un elemento. L form de signr y "desasignar"
mnejdores mu ltiples depende completmente del nvegdor utilizdo.

6.3.1. Manejadores de eventos de Internet Explorer


L fmili de nvegdores de Internet Explorer emplen los me todos attachEvent() y
detachEvent() pr socir y dessocir mnejdores de eventos. Todos los elementos y el
objeto window disponen de estos me todos.

Los me todos requieren dos pr metros: el nombre del evento que se quiere mnejr y un
referenci l funcio n encrgd de procesr el evento. El nombre del evento se debe indicr
con el prefijo on incluido, como muestr el siguiente ejemplo:
function muestraMensaje() {
alert("Has pulsado el ratn");
}
var elDiv = document.getElementById("div_principal");
elDiv.attachEvent("onclick", muestraMensaje);

// Ms adelante se decide desasociar la funcin del evento


elDiv.detachEvent("onclick", muestraMensaje);

Asocir m s de un funcio n l mismo evento es igul de sencillo:


function muestraMensaje() {
alert("Has pulsado el ratn");
}

function muestraOtroMensaje() {
alert("Has pulsado el ratn y por eso se muestran estos mensajes");
}

var elDiv = document.getElementById("div_principal");


elDiv.attachEvent("onclick", muestraMensaje);
elDiv.attachEvent("onclick", muestraOtroMensaje);

Si el usurio pinch sobre el <div>, se muestrn los dos mensjes de viso que se hn signdo l
evento.
Introduccin a AJAX Captulo 6. Eventos

Se pueden mezclr incluso diferentes te cnics pr socir mu ltiples mnejdores de eventos


un mismo evento de un elemento. El siguiente ejemplo utiliz l signcio n sem ntic de
mnejdores pr signr el primer mnejdor y l funcio n attachEvent() pr signr el
segundo mnejdor. El resultdo finl es igul l del ejemplo nterior:
var elDiv = document.getElementById("div_principal");
elDiv.onclick = muestraMensaje;
elDiv.attachEvent("onclick", muestraOtroMensaje);

Sin embrgo, no es posible signr mu ltiples eventos medinte ls propieddes de DOM:


var elDiv = document.getElementById("div_principal");
elDiv.onclick = muestraMensaje;
elDiv.onclick = muestraOtroMensaje;

6.3.2. Manejadores de eventos de DOM


L especificcio n DOM define otros dos me todos similres los disponibles pr Internet
Explorer y denomindos addEventListener() y removeEventListener() pr socir y
dessocir mnejdores de eventos.

L principl diferenci entre estos me todos y los nteriores es que en este cso se requieren tres
pr metros: el nombre del "event listener", un referenci l funcio n encrgd de procesr el
evento y el tipo de flujo de eventos l que se plic.

El primer rgumento no es el nombre completo del evento como sucede en el modelo de


Internet Explorer, sino que se debe eliminr el prefijo on. En otrs plbrs, si en Internet
Explorer se utilizb el nombre onclick, hor se debe utilizr click.

Si el tercer pr metro es true, el mnejdor se emple en l fse de capture. Si el tercer


pr metro es false, el mnejdor se soci l fse de bubbling.

A continucio n, se muestrn los ejemplos nteriores emplendo los me todos definidos por DOM:
function muestraMensaje() {
alert("Has pulsado el ratn");
}
var elDiv = document.getElementById("div_principal");
elDiv.addEventListener("click", muestraMensaje, false);

// Ms adelante se decide desasociar la funcin al evento


elDiv.removeEventListener("click", muestraMensaje, false);

Asocindo mu ltiples funciones un u nico evento:


function muestraMensaje() {
alert("Has pulsado el ratn");
}

function muestraOtroMensaje() {
alert("Has pulsado el ratn y por eso se muestran estos mensajes");
}

var elDiv = document.getElementById("div_principal");


Introduccin a AJAX Captulo 6. Eventos

elDiv.addEventListener("click", muestraMensaje, true);


elDiv.addEventListener("click", muestraOtroMensaje, true);

Si se soci un funcio n un flujo de eventos determindo, es funcio n so lo se puede dessocir


en el mismo tipo de flujo de eventos. Si se consider el siguiente ejemplo:
function muestraMensaje() {
alert("Has pulsado el ratn");
}
var elDiv = document.getElementById("div_principal");
elDiv.addEventListener("click", muestraMensaje, false);

// Ms adelante se decide desasociar la funcin al evento


elDiv.removeEventListener("click", muestraMensaje, true);

L u ltim instruccio n intent dessocir l funcio n muestraMensaje en el flujo de eventos de


capture, mientrs que l socirl, se indico el flujo de eventos de bubbling. Aunque l ejecucio n
de l pliccio n no se detiene y no se produce ningu n error, l u ltim instruccio n no tiene ningu n
efecto.

6.4. El objeto event


Cundo se produce un evento, no es suficiente con signrle un funcio n responsble de
procesr ese evento. Normlmente, l funcio n que proces el evento necesit informcio n
reltiv l evento producido: l tecl que se h pulsdo, l posicio n del rto n, el elemento que h
producido el evento, etc.

El objeto event es el mecnismo definido por los nvegdores pr proporcionr tod es


informcio n. Se trt de un objeto que se cre utom ticmente cundo se produce un evento y
que se destruye de form utom tic cundo se hn ejecutdo tods ls funciones signds l
evento.

Internet Explorer permite el cceso l objeto event trve s del objeto


window:

elDiv.onclick = function() {
var elEvento = window.event;
}

El est ndr DOM especific que el objeto event es el u nico pr metro que se debe psr
ls funciones encrgds de procesr los eventos. Por tnto, en los nvegdores que siguen los
est ndres, se puede cceder l objeto event trve s del rry de los rgumentos de l funcio n:
elDiv.onclick = function() {
var elEvento = arguments[0];
}

Tmbie n es posible indicr el nombre rgumento de form explcit:


elDiv.onclick = function(elEvento) {
...
}

El funcionmiento de los nvegdores que siguen los est ndres puede precer "mgico", y que
Introduccin a AJAX Captulo 6. Eventos
en l declrcio n de l funcio n se indic que tiene un pr metro, pero en l pliccio n no se ps
Introduccin a AJAX Captulo 6. Eventos

ningu n pr metro es funcio n. En relidd, los nvegdores que siguen los est ndres cren
utom ticmente ese pr metro y lo psn siempre l funcio n encrgd de mnejr el evento.

6.4.1. Propiedades y mtodos


A pesr de que el mecnismo definido por los nvegdores pr el objeto event es similr,
existen numeross diferencis en cunto ls propieddes y me todos del objeto.

6.4.1.1. Propiedades definidas por Internet Explorer

L siguiente tbl recoge ls propieddes definids pr el objeto event en los nvegdores de


l fmili Internet Explorer:

Propiedad/
Devuelve Descripcin
Mtodo
altKey Boolean Devuelve true si se ha pulsado la tecla ALT y false en otro caso
El botn del ratn que ha sido pulsado. Posibles valores:
0 Ningn botn pulsado
1 Se ha pulsado el botn izquierdo
2 Se ha pulsado el botn derecho
Introduccin a AJAX Captulo 6. Eventos
Nmero 3 Se pulsan a la vez el botn izquierdo y el derecho
button entero
4 Se ha pulsado el botn central
5 Se pulsan a la vez el botn izquierdo y el central
6 Se pulsan a la vez el botn derecho y el central
7 Se pulsan a la vez los 3 botones
cancelBubble Boolean Si se establece un valor true, se detiene el flujo de eventos de tipo bubbling
Nmero
clientX Coordenada X de la posicin del ratn respecto del rea visible de la ventana
entero
Nmero
clientY Coordenada Y de la posicin del ratn respecto del rea visible de la ventana
entero

ctrlKey Boolean Devuelve true si se ha pulsado la tecla CTRL y false en otro caso
fromElement Element El elemento del que sale el ratn (para ciertos eventos de ratn)
Nmero En el evento keypress, indica el carcter de la tecla pulsada. En los eventos
keyCode
entero keydown y keyup indica el cdigo numrico de la tecla pulsada

Nmero Coordenada X de la posicin del ratn respecto del elemento que origina el
offsetX evento
entero
Nmero Coordenada Y de la posicin del ratn respecto del elemento que origina el
offsetY evento
entero

Devuelve true si se est produciendo el evento keydown de forma


repeat Boolean continuada y false en otro caso

returnValue Boolean Se emplea para cancelar la accin predefinida del evento


Nmero
screenX Coordenada X de la posicin del ratn respecto de la pantalla completa
entero
Nmero
screenY Coordenada Y de la posicin del ratn respecto de la pantalla completa
entero
shiftKey Boolean Devuelve true si se ha pulsado la tecla SHIFT y false en otro caso
srcElement Element El elemento que origina el evento
toElement Element El elemento al que entra el ratn (para ciertos eventos de ratn)
Cadena El nombre del evento
type
de texto
Nmero Coordenada X de la posicin del ratn respecto del elemento padre del
x entero elemento que origina el evento

Nmero Coordenada Y de la posicin del ratn respecto del elemento padre del
y entero elemento que origina el evento

Tods ls propieddes slvo repeat son de lectur/escritur y por tnto, su vlor se puede leer
y/o estblecer.

6.4.1.2. Propiedades definidas por DOM

L siguiente tbl recoge ls propieddes definids pr el objeto event en los nvegdores que
siguen los est ndres:

Propiedad/Mtodo Devuelve Descripcin


altKey Boolean Devuelve true si se ha pulsado la tecla ALT y false en otro caso
bubbles Boolean Indica si el evento pertenece al flujo de eventos de bubbling
El botn del ratn que ha sido pulsado. Posibles valores:
0 Ningn botn pulsado
1 Se ha pulsado el botn izquierdo
2 Se ha pulsado el botn derecho
Nmero 3 Se pulsan a la vez el botn izquierdo y el derecho
button entero
4 Se ha pulsado el botn central
5 Se pulsan a la vez el botn izquierdo y el central
6 Se pulsan a la vez el botn derecho y el central
7 Se pulsan a la vez los 3 botones
cancelable Boolean Indica si el evento se puede cancelar
cancelBubble Boolean Indica si se ha detenido el flujo de eventos de tipo bubbling
Nmero
charCode El cdigo unicode del carcter correspondiente a la tecla pulsada
entero
Nmero Coordenada X de la posicin del ratn respecto del rea visible de la
clientX ventana
entero
Nmero Coordenada Y de la posicin del ratn respecto del rea visible de la
clientY ventana
entero
ctrlKey Boolean Devuelve true si se ha pulsado la tecla CTRL y false en otro caso
currentTarget Element El elemento que es el objetivo del evento
Nmero
detail El nmero de veces que se han pulsado los botones del ratn
entero
La fase a la que pertenece el evento:
Nmero 0 Fase capturing
eventPhase
entero 1 En el elemento destino
2 Fase bubbling
isChar Boolean Indica si la tecla pulsada corresponde a un carcter
Nmero
keyCode Indica el cdigo numrico de la tecla pulsada
entero
Nmero
metaKey Devuelve true si se ha pulsado la tecla META y false en otro caso
entero
Nmero
pageX Coordenada X de la posicin del ratn respecto de la pgina
entero
Nmero
pageY Coordenada Y de la posicin del ratn respecto de la pgina
entero
preventDefault() Funcin Se emplea para cancelar la accin predefinida del evento

El elemento que es el objetivo secundario del evento (relacionado con


relatedTarget Element los eventos de ratn)
Nmero Coordenada X de la posicin del ratn respecto de la pantalla
screenX
entero completa

Nmero Coordenada Y de la posicin del ratn respecto de la pantalla


screenY completa
entero
shiftKey Boolean Devuelve true si se ha pulsado la tecla SHIFT y false en otro
caso
stopPropagation() Funcin Se emplea para detener el flujo de eventos de tipo bubbling
target Element El elemento que origina el evento
timeStamp Nmero La fecha y hora en la que se ha producido el evento
Cadena de
type El nombre del evento
texto

Al contrrio de lo que sucede con Internet Explorer, l myor de propieddes del objeto event
de DOM son de so lo lectur. En concreto, solmente ls siguientes propieddes son de lectur y
escritur: altKey, button y keyCode.

L tecl META es un tecl especil que se encuentr en lgunos tecldos de ordendores muy
ntiguos. Actulmente, en los ordendores tipo PC se simil l tecl Alt o l tecla de
Windows, mientrs que en los ordendores tipo Mc se simil l tecl Command.

6.4.2. Similitudes y diferencias entre navegadores

6.4.2.1. Similitudes

En mbos csos se utiliz l propiedd type pr obtener el tipo de evento que se


trt:
function procesaEvento(elEvento) {
if(elEvento.type == "click") {
alert("Has pulsado el raton");
}
else if(elEvento.type == "mouseover") {
alert("Has movido el raton");
}
}

elDiv.onclick = procesaEvento;
elDiv.onmouseover = procesaEvento;

Mientrs que el mnejdor del evento incluye el prefijo on en su nombre, el tipo de evento
devuelto por l propiedd type prescinde de ese prefijo. Por eso en el ejemplo nterior se
compr su vlor con click y mouseover y no con onclick y onmouseover.

Otr similitud es el uso de l propiedd keyCode pr obtener el co digo correspondiente l


cr cter de l tecl que se h pulsdo. L tecl pulsd no siempre represent un cr cter
lfnume rico. Cundo se puls l tecl ENTER por ejemplo, se obtiene el co digo 13. L brr
espcidor se corresponde con el co digo 32 y l tecl de borrdo tiene un co digo igul 8.

Un form m s inmedit de comprobr si se hn pulsdo lguns tecls especiles, es utilizr


ls propieddes shiftKey, altKey y ctrlKey.

Pr obtener l posicio n del rto n respecto de l prte visible de l ventn, se emplen ls


propieddes clientX y clientY. De l mism form, pr obtener l posicio n del puntero del
rto n respecto de l pntll complet, se emplen ls propieddes screenX y screenY.

6.4.2.2. Diferencias

Un de ls principles diferencis es l form en l que se obtiene el elemento que origin el


evento. Si un elemento <div> tiene signdo un evento onclick, l pulsr con el rto n el
interior del <div> se origin un evento cuyo objetivo es el elemento <div>.
// Internet Explorer
var objetivo = elEvento.srcElement;

// Navegadores que siguen los estandares


var objetivo = elEvento.target;

Otr diferenci importnte es l reltiv l obtencio n del cr cter correspondiente l tecl


pulsd. Cd tecl pulsd tiene socidos dos co digos diferentes: el primero es el co digo de l
tecl que h sido presiond y el otro co digo es el que se refiere l cr cter pulsdo.

El primer co digo es un co digo de tecl interno pr JvScript. El segundo co digo coincide con el
co digo ASCII del cr cter. De est form, l letr a tiene un co digo interno igul 65 y un
co digo ASCII de 97. Por otro ldo, l letr A tiene un co digo interno tmbie n de 65 y un co digo
ASCII de
95.

En Internet Explorer, el contenido de l propiedd keyCode depende de cd evento. En los


eventos de "pulscio n de tecls" (onkeyup y onkeydown) su vlor es igul l co digo interno. En
los eventos de "escribir con tecls" (onkeypress) su vlor es igul l co digo ASCII del
cr cter pulsdo.
Por el contrrio, en los nvegdores que siguen los est ndres l propiedd keyCode es igul l
co digo interno en los eventos de "pulscio n de tecls" (onkeyup y onkeydown) y es igul 0 en
los eventos de "escribir con tecls" (onkeypress).

En l pr ctic, esto supone que en los eventos onkeyup y onkeydown se puede utilizr l
mism propiedd en todos los nvegdores:
function manejador(elEvento) {
var evento = elEvento || window.event;
alert("["+evento.type+"] El cdigo de la tecla pulsada es " + evento.keyCode);
}
document.onkeyup = manejador;
document.onkeydown = manejador;

En este cso, si se crg l p gin en culquier nvegdor y se puls por ejemplo l tecl a, se
muestr el siguiente mensje:

Figura 6.7. Mensaje mostrado en el navegador Firefox

Figura 6.8. Mensaje mostrado en el navegador Internet Explorer

L grn diferenci se produce l intentr obtener el cr cter que se h pulsdo, en este cso l
letr a. Pr obtener l letr, en primer lugr se debe obtener su co digo ASCII. Como se h
comentdo, en Internet Explorer el vlor de l propiedd keyCode en el evento onkeypress
es igul l cr cter ASCII:
function manejador() {
var evento = window.event;

// Internet Explorer
var codigo = evento.keyCode;
}

document.onkeypress = manejador;

Sin embrgo, en los nvegdores que no son Internet Explorer, el co digo nterior es igul 0
pr culquier tecl pulsd. En estos nvegdores que siguen los est ndres, se debe utilizr l
propiedd charCode, que devuelve el co digo de l tecl pulsd, pero solo pr el evento
onkeypress:

function manejador(elEvento) {
var evento = elEvento;

// Navegadores que siguen los estndares


var codigo = evento.charCode;
}

document.onkeypress = manejador;

Un vez obtenido el co digo en cd nvegdor, se debe utilizr l funcio n


String.fromCharCode() pr obtener el cr cter cuyo co digo ASCII se ps como pr metro.
Por tnto, l solucio n complet pr obtener l tecl pulsd en culquier nvegdor es l
siguiente:
function manejador(elEvento) {
var evento = elEvento || window.event;
var codigo = evento.charCode || evento.keyCode;
var caracter = String.fromCharCode(codigo);
}

document.onkeypress = manejador;

Un de ls propieddes m s interesntes es l posibilidd de impedir que se complete el


comportmiento norml de un evento. En otrs plbrs, con JvScript es posible no mostrr
ningu n cr cter cundo se puls un tecl, no envir un formulrio despue s de pulsr el boto n
de envo, no crgr ningun p gin l pulsr un enlce, etc. El me todo vnzdo de impedir que
un evento ejecute su ccio n socid depende de cd nvegdor:
// Internet Explorer
elEvento.returnValue = false;

// Navegadores que siguen los estandares


elEvento.preventDefault();

En el modelo b sico de eventos tmbie n es posible impedir el comportmiento por defecto de


lgunos eventos. Si por ejemplo en un elemento <textarea> se indic el siguiente mnejdor
de eventos:
<textarea onkeypress="return false;"></textarea>

En el <textarea> nterior no ser posible escribir ningu n cr cter, y que el mnejdor de


eventos devuelve false y ese es el vlor necesrio pr impedir que se termine de ejecutr el
evento y por tnto pr evitr que l letr se escrib.

As, es posible definir mnejdores de eventos que devuelvn true o false en funcio n de
lgunos pr metros. Por ejemplo se puede disen r un limitdor del nu mero de crcteres que se
pueden escribir en un <textarea>:
function limita(maximoCaracteres) {
var elemento = document.getElementById("texto");
if(elemento.value.length >= maximoCaracteres ) {
return false;
}
else {
return true;
}
}

<textarea id="texto" onkeypress="return limita(100);"></textarea>

El funcionmiento del ejemplo nterior se detll continucio n:

1. Se utiliz el evento onkeypress pr controlr si l tecl se escribe o no.


2. En el mnejdor del evento se devuelve el vlor devuelto por l funcio n extern
limita() l que se ps como pr metro el vlor 100.
3. Si el vlor devuelto por limita() es true, el evento se produce de form norml y
el cr cter se escribe en el <textarea>. Si el vlor devuelto por limita() es false,
el evento no se produce y por tnto el cr cter no se escribe en el <textarea>.
4. L funcio n limita() devuelve true o false despue s de comprobr si el nu mero de
crcteres del <textarea> es superior o inferior l m ximo nu mero de crcteres que
se le h psdo como pr metro.

El objeto event tmbie n permite detener completmente l ejecucio n del flujo norml de
eventos:
// Internet Explorer
elEvento.cancelBubble = true;

// Navegadores que siguen los estandares


elEvento.stopPropagation();

Al detener el flujo de eventos pendientes, se invlidn y no se ejecutn los eventos que restn
desde ese momento hst que se recorren todos los elementos pendientes hst el elemento
window.

6.5. Tipos de eventos


L list complet de eventos que se pueden generr en un nvegdor se puede dividir en cutro
grndes grupos. L especificcio n de DOM define los siguientes grupos:

Eventos de rto n: se originn cundo el usurio emple el rto n pr relizr lguns


cciones.
Eventos de tecldo: se originn cundo el usurio puls sobre culquier tecl de su
tecldo.
Eventos HTML: se originn cundo se producen cmbios en l ventn del nvegdor o
cundo se producen cierts intercciones entre el cliente y el servidor.
Eventos DOM: se originn cundo se produce un cmbio en l estructur DOM de l
p gin. Tmbie n se denominn "eventos de mutcio n".
6.5.1. Eventos de ratn
Los eventos de rto n son, con much diferenci, los m s empledos en ls plicciones web. Los
eventos que se incluyen en est clsificcio n son los siguientes:

Evento Descripcin

Se produce cuando se pulsa el botn izquierdo del ratn. Tambin se produce cuando el foco
click de la aplicacin est situado en un botn y se pulsa la tecla ENTER

dblclick Se produce cuando se pulsa dos veces el botn izquierdo del ratn
mousedown Se produce cuando se pulsa cualquier botn del ratn

Se produce cuando el puntero del ratn se encuentra en el interior de un elemento y el usuario


mouseout mueve el puntero a un lugar fuera de ese elemento

Se produce cuando el puntero del ratn se encuentra fuera de un elemento y el usuario mueve
mouseover el puntero hacia un lugar en el interior del elemento

mouseup Se produce cuando se suelta cualquier botn del ratn que haya sido pulsado
mousemove Se produce (de forma continua) cuando el puntero del ratn se encuentra sobre un elemento

Todos los elementos de ls p gins soportn los eventos de l tbl nterior.

6.5.1.1. Propiedades

El objeto event contiene ls siguientes propieddes pr los eventos de


rto n:

Ls coordends del rto n (tods ls coordends diferentes reltivs los distintos


elementos)
L propiedd type

L propiedd srcElement (Internet Explorer) o target (DOM)

Ls propieddes shiftKey, ctrlKey, altKey y metaKey (so lo DOM)

L propiedd button (so lo en los eventos mousedown, mousemove, mouseout, mouseover y


mouseup)

Los eventos mouseover y mouseout tienen propieddes dicionles. Internet Explorer define
l propiedd fromElement, que hce referenci l elemento desde el que el puntero del rto n se
h movido y toElement que es el elemento l que el puntero del rto n se h movido. De est
form, en el evento mouseover, l propiedd toElement es ide ntic srcElement y en el
evento mouseout, l propiedd fromElement es ide ntic srcElement.

En los nvegdores que soportn el est ndr DOM, solmente existe un propiedd denomind
relatedTarget. En el evento mouseout, relatedTarget punt l elemento l que se h movido
el rto n. En el evento mouseover, relatedTarget punt l elemento desde el que se h
movido el puntero del rto n.

Cundo se puls un boto n del rto n, l secuenci de eventos que se produce es l siguiente:
mousedown, mouseup, click. Por tnto, l secuenci de eventos necesri pr llegr l doble click
lleg ser tn complej como l siguiente: mousedown, mouseup, click, mousedown, mouseup,
click, dblclick.

6.5.2. Eventos de teclado


Los eventos que se incluyen en est clsificcio n son los siguientes:

Evento Descripcin

Se produce cuando se pulsa cualquier tecla del teclado. Tambin se produce de forma continua si
keydown se mantiene pulsada la tecla

Se produce cuando se pulsa una tecla correspondiente a un carcter alfanumrico (no se tienen
keypress en cuenta telas como SHIFT, ALT, etc.). Tambin se produce de forma continua si se mantiene
pulsada la tecla
keyup Se produce cuando se suelta cualquier tecla pulsada

6.5.2.1. Propiedades

El objeto event contiene ls siguientes propieddes pr los eventos de tecldo:

L propiedd keyCode

L propiedd charCode (so lo DOM)

L propiedd srcElement (Internet Explorer) o target (DOM)

Ls propieddes shiftKey, ctrlKey, altKey y metaKey (so lo DOM)

Cundo se puls un tecl correspondiente un cr cter lfnume rico, se produce l siguiente


secuenci de eventos: keydown, keypress, keyup. Cundo se puls otro tipo de tecl, se produce l
siguiente secuenci de eventos: keydown, keyup. Si se mntiene pulsd l tecl, en el primer cso
se repiten de form continu los eventos keydown y keypress y en el segundo cso, se repite
el evento keydown de form continu.

6.5.3. Eventos HTML


Los eventos HTML definidos se recogen en l siguiente tbl:

Evento Descripcin
Se produce en el objeto window cuando la pgina se carga por completo. En el elemento <img>
load
cuando se carga por completo la imagen. En el elemento <object> cuando se carga el objeto

Se produce en el objeto window cuando la pgina desaparece por completo (al cerrar la ventana
unload del navegador por ejemplo). En el elemento <object> cuando desaparece el objeto.

Se produce en un elemento <object> cuando el usuario detiene la descarga del elemento antes
abort de que haya terminado

Se produce en el objeto window cuando se produce un error de JavaScript. En el elemento <img>


error cuando la imagen no se ha podido cargar por completo y en el elemento <object> cuando
el elemento no se carga correctamente
Se produce cuando se seleccionan varios caracteres de un cuadro de texto (<input> y
select
<textarea>)

Se produce cuando un cuadro de texto (<input> y <textarea>) pierde el foco y su contenido ha


change variado. Tambin se produce cuando vara el valor de un elemento <select>

submit Se produce cuando se pulsa sobre un botn de tipo submit (<input type="submit">)
reset Se produce cuando se pulsa sobre un botn de tipo reset (<input type="reset">)
resize Se produce en el objeto window cuando se redimensiona la ventana del navegador

Se produce en cualquier elemento que tenga una barra de scroll, cuando el usuario la utiliza. El
scroll elemento <body> contiene la barra de scroll de la pgina completa

focus Se produce en cualquier elemento (incluido el objeto window) cuando el elemento obtiene el foco
blur Se produce en cualquier elemento (incluido el objeto window) cuando el elemento pierde el foco

Uno de los eventos m s utilizdos es el evento load, y que tods ls mnipulciones que se
relizn medinte DOM requieren que l p gin este crgd por completo y por tnto, el rbol
DOM se hy construido completmente.

El elemento <body> define ls propieddes scrollLeft y scrollTop que se pueden


empler junto con el evento scroll.

6.5.4. Eventos DOM


Aunque los eventos de este tipo son prte de l especificcio n oficil de DOM, u n no hn sido
implementdos en todos los nvegdores. L siguiente tbl recoge los eventos m s importntes
de este tipo:

Evento Descripcin

Se produce cuando se aaden o eliminan nodos en el subrbol de un


DOMSubtreeModified documento o elemento

DOMNodeInserted Se produce cuando se aade un nodo como hijo de otro nodo


DOMNodeRemoved Se produce cuando se elimina un nodo que es hijo de otro nodo
DOMNodeRemovedFromDocument Se produce cuando se elimina un nodo del documento
DOMNodeInsertedIntoDocument Se produce cuando se aade un nodo al documento

6.6. Solucin cross browser


Ls diferencis existentes entre los nvegdores disponibles en l ctulidd complicn en
exceso el desrrollo de plicciones comptibles con todos los nvegdores, llmds
plicciones "cross browser" en ingle s.

Por ese motivo, se v disen r un utilidd que permit unificr l socicio n/dessocicio n de
mnejdores de eventos, l obtencio n del objeto event y tods sus propieddes. L utilidd que
se muestr se h obtenido del excelente libro "Professional JavaScript for Web Developers",
escrito por Nichols C. Zks y publicdo por l editoril Wrox.
6.6.1. Asignacin de manejadores de eventos
En primer lugr, se cre el objeto que v englobr tods ls propieddes y me todos
relciondos con los eventos:
var EventUtil = new Object();

El primer me todo relciondo con los eventos que es necesrio estndrizr es el de l


signcio n y elimincio n de mnejdores de eventos:
EventUtil.addEventHandler = function(elemento, tipoEvento, funcion) {
if(elemento.addEventListener) { // navegadores DOM
elemento.addEventListener(tipoEvento, funcion, false);
}
else if(elemento.attachEvent) { // Internet Explorer
elemento.attachEvent("on"+tipoEvento, funcion);
}
else { // resto de navegadores
elemento["on"+tipoEvento] = funcion;
}
};

EventUtil.removeEventHandler = function(elemento, tipoEvento, funcion) {


if(elemento.removeEventListener) { // navegadores DOM
elemento.removeEventListener(tipoEvento, funcion, false);
}
else if(elemento.detachEvent) { // Internet Explorer
elemento.detachEvent("on"+tipoEvento, funcion);
}
else { // resto de navegadores
elemento["on"+tipoEvento] = null;
}
};

6.6.2. Obtencin del objeto Event


Pr obtener el objeto event, se cre un nuevo me todo en l utilidd llmdo getEvent():
EventUtil.getEvent = function() {
if(window.event) { // Internet Explorer
return this.formatEvent(window.event);
}
else { // navegadores DOM
return EventUtil.getEvent.caller.arguments[0];
}
};

El me todo getEvent() es un me todo que no cept pr metros y que devuelve el objeto event
convenientemente dptdo pr permitir un comportmiento homoge neo entre diferentes
nvegdores.

En el cso de Internet Explorer, el objeto event se obtiene directmente prtir del objeto
window. Sin embrgo, ntes de devolver el objeto, se modific n diendo ls propieddes que no
dispone en comprcio n con el objeto event de los nvegdores DOM.
En el cso de los nvegdores DOM, el objeto event se obtiene como el primer rgumento de
l funcio n que ctu como mnejdor del evento. Como y se vio en el cptulo de JvScript
b sico, l propiedd caller de un funcio n siempre lmcen un referenci l funcio n que l
invoco .

As, si en el interior de un mnejdor de eventos se hce l llmd l me todo


EventUtil.getEvent(), l propiedd caller ser el propio mnejdor de eventos y su primer
rgumento ser el objeto event. Prece muy bstrcto, pero si se piens detenidmente se
comprende f cilmente l solucio n tn concis y elegnte que se h utilizdo.

6.6.3. Estandarizacin del objeto Event


El objeto event present uns propieddes y me todos muy diferentes en funcio n del tipo de
nvegdor en el que se ejecut l pliccio n JvScript. Pr estndrizr el objeto event, se cre
un me todo que n de l objeto event de Internet Explorer tods ls propieddes que le fltn.

El co digo completo de este me todo se muestr continucio n:


EventUtil.formatEvent = function(elEvento) {
// Detectar si el navegador actual es Internet Explorer
var esIE = navigator.userAgent.toLowerCase().indexOf('msie')!=-1;
if(esIE) {
elEvento.charCode = (elEvento.type=="keypress") ? elEvento.keyCode : 0;
elEvento.eventPhase = 2;
elEvento.isChar = (elEvento.charCode > 0);
elEvento.pageX = elEvento.clientX + document.body.scrollLeft;
elEvento.pageY = elEvento.clientY + document.body.scrollTop;
elEvento.preventDefault = function() {
this.returnValue = false;
};
if(elEvento.type == "mouseout") {
elEvento.relatedTarget = elEvento.toElement;
}
else if(elEvento.type == "mouseover") {
elEvento.relatedTarget = elEvento.fromElement
}
elEvento.stopPropagation = function() {
this.cancelBuble = true;
};
elEvento.target = elEvento.srcElement;
elEvento.time = (new Date).getTime();
}
return elEvento;
}
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

Captulo 7. Primeros pasos con AJAX


7.1. Breve historia de AJAX
L histori de AJAX est ntimmente relciond con un objeto de progrmcio n llmdo
XMLHttpRequest. El origen de este objeto se remont l n o 2000, con productos como Exchnge
2000, Internet Explorer 5 y Outlook Web Access.

Todo comenzo en 1998, cundo Alex Hopmann y su equipo se encontrbn desrrollndo l


entonces futur versio n de Exchnge 2000. El punto de bil del servidor de correo electro nico er
su cliente v web, llmdo OWA (Outlook Web Access).

Durnte el desrrollo de OWA, se evluron dos opciones: un cliente formdo so lo por p gins
HTML est tics que se recrgbn constntemente y un cliente relizdo completmente con
HTML din mico o DHTML. Alex Hopmnn pudo ver ls dos opciones y se decnto por l bsd
en DHTML. Sin embrgo, pr ser relmente u til est u ltim le fltb un componente esencil:
"lgo" que evitr tener que envir continumente los formulrios con dtos l servidor.

Motivdo por ls posibiliddes futurs de OWA, Alex creo en un solo fin de semn l primer
versio n de lo que denomino XMLHTTP. L primer demostrcio n de ls posibiliddes de l
nuev tecnolog fue un e xito, pero fltb lo m s difcil: incluir es tecnolog en el nvegdor
Internet Explorer.

Si el nvegdor no inclu XMLHTTP de form ntiv, el e xito del OWA se hbr reducido
enormemente. El myor problem es que fltbn pocs semns pr que se lnzr l u ltim
bet de Internet Explorer 5 previ su lnzmiento finl. Grcis sus contctos en l empres,
Alex consiguio que su tecnolog se incluyer en l librer MSXML que incluye Internet
Explorer.

De hecho, el nombre del objeto (XMLHTTP) se eligio pr tener un buen excus que justificr
su inclusio n en l librer XML de Internet Explorer, y que este objeto est mucho m s
relciondo con HTTP que con XML.

7.2. La primera aplicacin


7.2.1. Cdigo fuente
L pliccio n AJAX complet m s sencill consiste en un dptcio n del cl sico "Hola Mundo".
En este cso, un pliccio n JvScript descrg un rchivo del servidor y muestr su contenido
sin necesidd de recrgr l p gin.

Co digo fuente completo:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

<title>Hola Mundo con AJAX</title>

<script type="text/javascript">
function descargaArchivo() {
// Obtener la instancia del objeto XMLHttpRequest
if(window.XMLHttpRequest) {
peticion_http = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
peticion_http = new ActiveXObject("Microsoft.XMLHTTP");
}

// Preparar la funcion de respuesta


peticion_http.onreadystatechange = muestraContenido;

// Realizar peticion HTTP


peticion_http.open('GET', 'http://localhost/holamundo.txt', true);
peticion_http.send(null);

function muestraContenido() {
if(peticion_http.readyState == 4) {
if(peticion_http.status == 200) {
alert(peticion_http.responseText);
}
}
}
}

window.onload = descargaArchivo;
</script>

</head>
<body></body>
</html>

En el ejemplo nterior, cundo se crg l p gin se ejecut el me todo JvScript que muestr el
contenido de un rchivo llmdo holamundo.txt que se encuentr en el servidor. L clve del
co digo nterior es que l peticio n HTTP y l descrg de los contenidos del rchivo se relizn
sin necesidd de recrgr l p gin.

7.2.2. Anlisis detallado


L pliccio n AJAX del ejemplo nterior se compone de cutro grndes bloques: instncir el
objeto XMLHttpRequest, preprr l funcio n de respuest, relizr l peticio n l servidor y
ejecutr l funcio n de respuest.

Tods ls plicciones relizds con te cnics de AJAX deben instncir en primer lugr el
objeto XMLHttpRequest, que es el objeto clve que permite relizr comunicciones con el
servidor en segundo plno, sin necesidd de recrgr ls p gins.

L implementcio n del objeto XMLHttpRequest depende de cd nvegdor, por lo que es


necesrio empler un discrimincio n sencill en funcio n del nvegdor en el que se est
ejecutndo el co digo:
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

if(window.XMLHttpRequest) { // Navegadores que siguen los estndares


peticion_http = new XMLHttpRequest();
}
else if(window.ActiveXObject) { // Navegadores obsoletos
peticion_http = new ActiveXObject("Microsoft.XMLHTTP");
}

Los nvegdores que siguen los est ndres (Firefox, Sfri, Oper, Internet Explorer 7 y 8)
implementn el objeto XMLHttpRequest de form ntiv, por lo que se puede obtener trve s
del objeto window. Los nvegdores obsoletos (Internet Explorer 6 y nteriores) implementn el
objeto XMLHttpRequest como un objeto de tipo ActiveX.

Un vez obtenid l instnci del objeto XMLHttpRequest, se prepr l funcio n que se encrg
de procesr l respuest del servidor. L propiedd onreadystatechange del objeto
XMLHttpRequest permite indicr est funcio n directmente incluyendo su co digo medinte un
funcio n no nim o indicndo un referenci un funcio n independiente. En el ejemplo nterior
se indic directmente el nombre de l funcio n:
peticion_http.onreadystatechange = muestraContenido;

El co digo nterior indic que cundo l pliccio n recib l respuest del servidor, se debe
ejecutr l funcio n muestraContenido(). Como es hbitul, l referenci l funcio n se indic
medinte su nombre sin pre ntesis, y que de otro modo se estr ejecutndo l funcio n y
lmcenndo el vlor devuelto en l propiedd onreadystatechange.

Despue s de preprr l pliccio n pr l respuest del servidor, se reliz l peticio n HTTP l


servidor:
peticion_http.open('GET', 'http://localhost/prueba.txt', true);
peticion_http.send(null);

Ls instrucciones nteriores relizn el tipo de peticio n m s sencillo que se puede envir l


servidor. En concreto, se trt de un peticio n de tipo GET simple que no env ningu n pr metro
l servidor. L peticio n HTTP se cre medinte el me todo open(), en el que se incluye el tipo de
peticio n (GET), l URL solicitd (http://localhost/prueba.txt) y un tercer pr metro que
vle true.

Un vez cred l peticio n HTTP, se env l servidor medinte el me todo send(). Este me todo
incluye un pr metro que en el ejemplo nterior vle null. M s delnte se ven en detlle todos
los me todos y propieddes que permiten hcer ls peticiones l servidor.

Por u ltimo, cundo se recibe l respuest del servidor, l pliccio n ejecut de form utom tic
l funcio n estblecid nteriormente.
function muestraContenido() {
if(peticion_http.readyState == 4) {
if(peticion_http.status == 200) {
alert(peticion_http.responseText);
}
}
}
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

L funcio n muestraContenido() comprueb en primer lugr que se h recibido l respuest


del servidor (medinte el vlor de l propiedd readyState). Si se h recibido lgun respuest,
se comprueb que se v lid y correct (comprobndo si el co digo de estdo HTTP devuelto
es igul 200). Un vez relizds ls comprobciones, simplemente se muestr por pntll el
contenido de l respuest del servidor (en este cso, el contenido del rchivo solicitdo)
medinte l propiedd responseText.

7.2.3. Refactorizando la primera aplicacin


L primer pliccio n AJAX mostrd nteriormente present lguns crencis importntes. A
continucio n, se refctoriz su co digo mpli ndolo y mejor ndolo pr que se dpte mejor
otrs situciones. En primer lugr, se definen uns vribles que se utilizn en l funcio n que
proces l respuest del servidor:
var READY_STATE_UNINITIALIZED = 0;
var READY_STATE_LOADING = 1;
var READY_STATE_LOADED = 2;
var READY_STATE_INTERACTIVE = 3;
var READY_STATE_COMPLETE = 4;

Como se ver m s delnte, l respuest del servidor so lo puede corresponder lguno de los
cinco estdos definidos por ls vribles nteriores. De est form, el co digo puede utilizr el
nombre de cd estdo en vez de su vlor nume rico, por lo que se fcilit l lectur y el
mntenimiento de ls plicciones.

Adem s, l vrible que lmcen l instnci del objeto XMLHttpRequest se v trnsformr


en un vrible globl, de form que tods ls funciones que hcen uso de ese objeto tengn
cceso directo l mismo:
var peticion_http;

A continucio n, se cre un funcio n gene ric de crg de contenidos medinte AJAX:


function cargaContenido(url, metodo, funcion) {
peticion_http = inicializa_xhr();

if(peticion_http)
{ peticion_http.onreadystatechange =
funcion; peticion_http.open(metodo, url,
true); peticion_http.send(null);
}
}

L funcio n definid dmite tres pr metros: l URL del contenido que se v crgr, el me todo
utilizdo pr relizr l peticio n HTTP y un referenci l funcio n que proces l respuest
del servidor.

En primer lugr, l funcio n cargaContenido() iniciliz el objeto XMLHttpRequest (llmdo


xhr de form brevid). Un vez inicilizdo, se emple el objeto peticion_http pr
estblecer l funcio n que proces l respuest del servidor. Por u ltimo, l funcio n
cargaContenido() reliz l peticio n l servidor emplendo l URL y el me todo HTTP indicdos
como pr metros.
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

L funcio n inicializa_xhr() se emple pr encpsulr l crecio n del objeto XMLHttpRequest:


function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

L funcio n muestraContenido() tmbie n se refctoriz pr empler ls vribles globles


definids:
function muestraContenido() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
alert(peticion_http.responseText);
}
}
}

Por u ltimo, l funcio n descargaArchivo() simplemente reliz un llmd l funcio n


cargaContenido() con los pr metros decudos:

function descargaArchivo() {
cargaContenido("http://localhost/holamundo.txt", "GET", muestraContenido);
}

A continucio n se muestr el co digo completo de l refctorizcio n de l primer pliccio n:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Hola Mundo con AJAX, version 2</title>

<script type="text/javascript" language="javascript">

var READY_STATE_UNINITIALIZED=0;
var READY_STATE_LOADING=1;
var READY_STATE_LOADED=2;
var READY_STATE_INTERACTIVE=3;
var READY_STATE_COMPLETE=4;

var peticion_http;

function cargaContenido(url, metodo, funcion) {


peticion_http = inicializa_xhr();

if(peticion_http)
{ peticion_http.onreadystatechange =
funcion; peticion_http.open(metodo, url,
true); peticion_http.send(null);
}
}
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function muestraContenido() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
alert(peticion_http.responseText);
}
}
}

function descargaArchivo() {
cargaContenido("http://localhost/holamundo.txt", "GET", muestraContenido);
}

window.onload = descargaArchivo;

</script>

</head>
<body></body>
</html>

Ejercicio 11

A partir de la pgina web proporcionada, aadir el cdigo JavaScript necesario para que:

1. Al cargar la pgina, el cuadro de texto debe mostrar por defecto la URL de la propia pgina.
2. Al pulsar el botn "Mostrar Contenidos", se debe descargar mediante peticiones AJAX el
contenido correspondiente a la URL introducida por el usuario. El contenido de la respuesta
recibida del servidor se debe mostrar en la zona de "Contenidos del archivo".
3. En la zona "Estados de la peticin" se debe mostrar en todo momento el estado en el que se
encuentra la peticin (No inicializada, cargando, completada, etc.)
4. Mostrar el contenido de todas las cabeceras de la respuesta del servidor en la zona
"Cabeceras HTTP de la respuesta del servidor".
5. Mostrar el cdigo y texto de estado de la respuesta del servidor en la zona "Cdigo de
estado".

7.3. Mtodos y propiedades del objeto XMLHttpRequest


El objeto XMLHttpRequest posee muchs otrs propieddes y me todos diferentes ls
mnejds por l primer pliccio n de AJAX. A continucio n se incluye l list complet de
tods ls propieddes y me todos del objeto y todos los vlores nume ricos de sus propieddes.

Ls propieddes definids pr el objeto XMLHttpRequest


son:
Introduccin a AJAX Captulo 7. Primeros pasos con AJAX

Propiedad Descripcin
readyState Valor numrico (entero) que almacena el estado de la peticin
responseText El contenido de la respuesta del servidor en forma de cadena de texto

El contenido de la respuesta del servidor en formato XML. El objeto devuelto se puede


responseXML procesar como un objeto DOM
El cdigo de estado HTTP devuelto por el servidor (200 para una respuesta correcta, 404
status
para "No encontrado", 500 para un error de servidor, etc.)
El cdigo de estado HTTP devuelto por el servidor en forma de cadena de texto: "OK", "Not
statusText
Found", "Internal Server Error", etc.

Los vlores definidos pr l propiedd readyState son los siguientes:

Valor Descripcin
0 No inicializado (objeto creado, pero no se ha invocado el mtodo open)
1 Cargando (objeto creado, pero no se ha invocado el mtodo send)
2 Cargado (se ha invocado el mtodo send, pero el servidor an no ha respondido)
Interactivo (se han recibido algunos datos, aunque no se puede emplear la propiedad
3
responseText)

4 Completo (se han recibido todos los datos de la respuesta del servidor)

Los me todos disponibles pr el objeto XMLHttpRequest son los siguientes:

Mtodo Descripcin
abort() Detiene la peticin actual

Devuelve una cadena de texto con todas las cabeceras de la


getAllResponseHeaders() respuesta del servidor

Devuelve una cadena de texto con el contenido de la cabecera


getResponseHeader("cabecera") solicitada

Responsable de manejar los eventos que se producen. Se invoca


Introduccin a AJAX Captulo 7. Primeros pasos con AJAX
onreadystatechange cada vez que se produce un cambio en el estado de la peticin HTTP.
Normalmente es una referencia a una funcin JavaScript
Establece los parmetros de la peticin que se realiza al servidor. Los
open("metodo", "url") parmetros necesarios son el mtodo HTTP empleado y la URL
destino (puede indicarse de forma absoluta o relativa)
send(contenido) Realiza la peticin HTTP al servidor
setRequestHeader("cabecera", Permite establecer cabeceras personalizadas en la peticin HTTP. Se
"valor") debe invocar el mtodo open() antes que setRequestHeader()

El me todo open() requiere dos pr metros (me todo HTTP y URL) y cept de form opcionl
otros tres pr metros. Definicio n forml del me todo open():
open(string metodo, string URL [,boolean asincrono, string usuario, string password]);
Por defecto, ls peticiones relizds son sncrons. Si se indic un vlor false l tercer
pr metro, l peticio n se reliz de form sncron, esto es, se detiene l ejecucio n de l
pliccio n hst que se recibe de form complet l respuest del servidor.

No obstnte, ls peticiones sncrons son justmente contrris l filosof de AJAX. El motivo


es que un peticio n sncron congela el nvegdor y no permite l usurio relizr ningun
ccio n hst que no se hy recibido l respuest complet del servidor. L senscio n que
provoc es que el nvegdor se h colgado por lo que no se recomiend el uso de peticiones
sncrons slvo que se imprescindible.

Los u ltimos dos pr metros opcionles permiten indicr un nombre de usurio y un contrsen
v lidos pr cceder l recurso solicitdo.

Por otr prte, el me todo send() requiere de un pr metro que indic l informcio n que se v
envir l servidor junto con l peticio n HTTP. Si no se envn dtos, se debe indicr un
vlor igul null. En otro cso, se puede indicr como pr metro un cden de texto, un rry
de bytes o un objeto XML DOM.

7.4. Utilidades y objetos para AJAX


Un de ls operciones m s hbitules en ls plicciones AJAX es l de obtener el contenido de
un rchivo o recurso del servidor. Por tnto, se v construir un objeto que permit relizr l
crg de dtos del servidor simplemente indicndo el recurso solicitdo y l funcio n encrgd
de procesr l respuest:
var cargador = new net.CargadorContenidos("pagina.html", procesaRespuesta);

L lo gic comu n de AJAX se encpsul en un objeto de form que se f cilmente reutilizble.


Aplicndo los conceptos de objetos de JvScript, funciones constructors y el uso de prototype,
es posible relizr de form sencill el objeto crgdor de contenidos.

El siguiente co digo h sido dptdo del excelente libro "Ajx in Action", escrito por Dve Crne,
Eric Pscrello y Drren Jmes y publicdo por l editoril Mnning.
var net = new Object();

net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;

// Constructor
net.CargadorContenidos = function(url, funcion, funcionError) {
this.url = url;
this.req = null;
this.onload = funcion;
this.onerror = (funcionError) ? funcionError : this.defaultError;
this.cargaContenidoXML(url);
}

net.CargadorContenidos.prototype = {
cargaContenidoXML: function(url) {
if(window.XMLHttpRequest) {
this.req = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
this.req = new ActiveXObject("Microsoft.XMLHTTP");
}

if(this.req) {
try {
var loader = this;
this.req.onreadystatechange = function() {
loader.onReadyState.call(loader);
}
this.req.open('GET', url, true);
this.req.send(null);
} catch(err) {
this.onerror.call(this);
}
}
},

onReadyState: function() {
var req = this.req;
var ready = req.readyState;
if(ready == net.READY_STATE_COMPLETE) {
var httpStatus = req.status;
if(httpStatus == 200 || httpStatus == 0) {
this.onload.call(this);
}
else {
this.onerror.call(this);
}
}
},

defaultError: function() {
alert("Se ha producido un error al obtener los datos"
+ "\n\nreadyState:" + this.req.readyState
+ "\nstatus: " + this.req.status
+ "\nheaders: " + this.req.getAllResponseHeaders());
}
}

Un vez definido el objeto net con su me todo CargadorContenidos(), y es posible utilizrlo


en ls funciones que se encrgn de mostrr el contenido del rchivo del servidor:
function muestraContenido() {
alert(this.req.responseText);
}

function cargaContenidos() {
var cargador = new net.CargadorContenidos("http://localhost/holamundo.txt",
muestraContenido);
}
window.onload = cargaContenidos;

En el ejemplo nterior, l pliccio n muestr un mensje con los contenidos de l URL indicd:

Figura 7.1. Mensaje mostrado cuando el resultado es exitoso

Por otr prte, si l URL que se quiere crgr no es v lid o el servidor no responde, l pliccio n
muestr el siguiente mensje de error:

Figura 7.2. Mensaje mostrado cuando el resultado es errneo

El co digo del crgdor de contenidos hce un uso intensivo de objetos, JSON, funciones no nims
y uso del objeto this. Seguidmente, se detll el funcionmiento de cd un de sus prtes.

El primer elemento importnte del co digo fuente es l definicio n del objeto net.
var net = new Object();

Se trt de un vrible globl que encpsul tods ls propieddes y me todos reltivos ls


operciones relcionds con ls comunicciones por red. De cierto modo, est vrible globl
simul el funcionmiento de los namespaces y que evit l colisio n entre nombres de
propieddes y me todos diferentes.

Despue s de definir ls constntes empleds por el objeto XMLHttpRequest, se define el


constructor del objeto CargadorContenidos:
net.CargadorContenidos = function(url, funcion, funcionError) {
this.url = url;
this.req = null;
this.onload = funcion;
this.onerror = (funcionError) ? funcionError : this.defaultError;
this.cargaContenidoXML(url);
}
Aunque el constructor define tres pr metros diferentes, en relidd solmente los dos
primeros son obligtorios. De est form, se iniciliz el vlor de lguns vribles del objeto, se
comprueb si se h definido l funcio n que se emple en cso de error (si no se h definido, se
emple un funcio n gene ric definid m s delnte) y se invoc el me todo responsble de crgr
el recurso solicitdo (cargaContenidoXML).
net.CargadorContenidos.prototype = {
cargaContenidoXML:function(url) {
...
},
onReadyState:function() {
...
},
defaultError:function() {
...
}
}

Los me todos empledos por el objeto net.cargaContenidos se definen medinte su


prototipo. En este cso, se definen tres me todos diferentes: cargaContenidoXML() pr crgr
recursos de servidor, onReadyState() que es l funcio n que se invoc cundo se recibe l
respuest del servidor y defaultError() que es l funcio n que se emple cundo no se h
definido de form explcit un funcio n responsble de mnejr los posibles errores que se
produzcn en l peticio n HTTP.

L funcio n defaultError() muestr un mensje de viso del error producido y dem s


muestr el vlor de lguns de ls propieddes de l peticio n HTTP:
defaultError:function() {
alert("Se ha producido un error al obtener los datos"
+ "\n\nreadyState:" + this.req.readyState
+ "\nstatus: " + this.req.status
+ "\nheaders: " + this.req.getAllResponseHeaders());
}

En este cso, el objeto this se resuelve l objeto net.cargaContenidos, y que es el objeto que
contiene l funcio n no nim que se est ejecutndo.

Por otr prte, l funcio n onReadyState es l encrgd de gestionr l respuest del servidor:
onReadyState: function() {
var req = this.req;
var ready = req.readyState;
if(ready == net.READY_STATE_COMPLETE) {
var httpStatus = req.status;
if(httpStatus == 200 || httpStatus == 0) {
this.onload.call(this);
} else {
this.onerror.call(this);
}
}
}
Trs comprobr que l respuest del servidor est disponible y es correct, se reliz l llmd
l funcio n que relmente proces l respuest del servidor de cuerdo ls necesiddes de l
pliccio n.
this.onload.call(this);

El objeto this se resuelve como net.CargadorContenidos, y que es el objeto que contiene l


funcio n que se est ejecutndo. Por tnto, this.onload es l referenci l funcio n que se h
definido como responsble de procesr l respuest del servidor (se trt de un referenci
un funcio n extern).

Normlmente, l funcio n extern encrgd de procesr l respuest del servidor, requerir


cceder l objeto XMLHttpRequest que lmcen l peticio n relizd l servidor. En otro cso, l
funcio n extern no ser cpz de cceder l contenido devuelto por el servidor.

Como y se vio en los cptulos nteriores, el me todo call() es uno de los me todos
definidos pr el objeto Function(), y por tnto disponible pr tods ls funciones de
JvScript. Emplendo el me todo call() es posible obligr un funcio n ejecutrse sobre
un objeto concreto. En otrs plbrs, emplendo el me todo call() sobre un funcio n, es
posible que dentro de es funcio n el objeto this se resuelv como el objeto psdo como
pr metro en el me todo call().

As, l instruccio n this.onload.call(this); se interpret de l siguiente


form:

El objeto this que se ps como pr metro de call() se resuelve como el objeto


net.CargadorContenidos.

El objeto this.onload lmcen un referenci l funcio n extern que se v


empler pr procesr l respuest.
El me todo this.onload.call() ejecut l funcio n cuy referenci se lmcen en
this.onload.

L instruccio n this.onload.call(this); permite ejecutr l funcio n extern con el objeto


net.CargadorContenidos ccesible en el interior de l funcio n medinte el objeto this.

Por u ltimo, el me todo cargaContenidoXML se encrg de envir l peticio n HTTP y relizr l


llmd l funcio n que proces l respuest:
cargaContenidoXML:function(url) {
if(window.XMLHttpRequest) {
this.req = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
this.req = new ActiveXObject("Microsoft.XMLHTTP");
}
if(this.req) {
try {
var loader=this;
this.req.onreadystatechange = function() {
loader.onReadyState.call(loader);
}
this.req.open('GET', url, true);
this.req.send(null);
} catch(err) {
this.onerror.call(this);
}
}
}

En primer lugr, se obtiene un instnci del objeto XMLHttpRequest en funcio n del tipo de
nvegdor. Si se h obtenido correctmente l instnci, se ejecutn ls instrucciones m s
importntes del me todo cargaContenidoXML:
var loader = this;
this.req.onreadystatechange = function() {
loader.onReadyState.call(loader);
}
this.req.open('GET', url, true);
this.req.send(null);

A continucio n, se lmcen l instnci del objeto ctul (this) en l nuev vrible loader.
Un vez lmcend l instnci del objeto net.cargadorContenidos, se define l funcio n
encrgd de procesr l respuest del servidor. En l siguiente funcio n no nim:
this.req.onreadystatechange = function() { ... }

En el interior de
es funcio n, el objeto this no se resuelve en el objeto
net.CargadorContenidos, por lo que no se puede empler l siguiente instruccio n:

this.req.onreadystatechange = function() {
this.onReadyState.call(loader);
}

Sin embrgo, desde el interior de es funcio n no nim si es posible cceder ls vribles


definids en l funcio n exterior que l englob. As, desde el interior de l funcio n no nim s que
es posible cceder l instnci del objeto net.CargadorContenidos que se lmceno
nteriormente.

En el co digo nterior, no es obligtorio empler l llmd l me todo call(). Se podr hber


definido de l siguiente form:
var loader=this;
this.req.onreadystatechange = function() {
// loader.onReadyState.call(loader);
loader.onReadyState();
}

En el interior de l funcio n onReadyState, el objeto this se resuelve como


net.ContentLoader, y que se trt de un me todo definido en el prototipo del propio objeto.

Ejercicio 12

La pgina HTML proporcionada incluye una zona llamada ticker en la que se deben mostrar noticias
generadas por el servidor. Aadir el cdigo JavaScript necesario para:
1. De forma peridica cada cierto tiempo (por ejemplo cada segundo) se realiza una peticin al
servidor mediante AJAX y se muestra el contenido de la respuesta en la zona reservada para
las noticias.
2. Adems del contenido enviado por el servidor, se debe mostrar la hora en la que se ha
recibido la respuesta.
3. Cuando se pulse el botn "Detener", la aplicacin detiene las peticiones peridicas al
servidor. Si se vuelve a pulsar sobre ese botn, se reanudan las peticiones peridicas.
4. Aadir la lgica de los botones "Anterior" y "Siguiente", que detienen las peticiones al
servidor y permiten mostrar los contenidos anteriores o posteriores al que se muestra en
ese momento.
5. Cuando se recibe una respuesta del servidor, se resalta visualmente la zona llamada ticker.
6. Modificar la aplicacin para que se reutilice continuamente el mismo objeto
XMLHttpRequest para hacer las diferentes peticiones.

7.5. Interaccin con el servidor


7.5.1. Envo de parmetros con la peticin HTTP
Hst hor, el objeto XMLHttpRequest se h empledo pr relizr peticiones HTTP
sencills. Sin embrgo, ls posibiliddes que ofrece el objeto XMLHttpRequest son muy
superiores, y que tmbie n permite el envo de pr metros junto con l peticio n HTTP.

El objeto XMLHttpRequest puede envir pr metros tnto con el me todo GET como con el
me todo POST de HTTP. En mbos csos, los pr metros se envn como un serie de pres
clve/vlor conctendos por smbolos &. El siguiente ejemplo muestr un URL que env
pr metros l servidor medinte el me todo GET:
http://localhost/aplicacion?parametro1=valor1&parametro2=valor2&parametro3=valor3

L principl diferenci entre mbos me todos es que medinte el me todo POST los pr metros se
envn en el cuerpo de l peticio n y medinte el me todo GET los pr metros se conctenn l
URL ccedid. El me todo GET se utiliz cundo se ccede un recurso que depende de l
informcio n proporciond por el usurio. El me todo POST se utiliz en operciones que cren,
borrn o ctulizn informcio n.

Te cnicmente, el me todo GET tiene un lmite en l cntidd de dtos que se pueden envir. Si se
intentn envir m s de 512 bytes medinte el me todo GET, el servidor devuelve un error con
co digo 414 y mensje Request-URI Too Long ("La URI de la peticin es demasiado larga").

Cundo se utiliz un elemento <form> de HTML, l pulsr sobre el boto n de envo del
formulrio, se cre utom ticmente l cden de texto que contiene todos los pr metros que se
envn l servidor. Sin embrgo, el objeto XMLHttpRequest no dispone de es posibilidd y l
cden que contiene los pr metros se debe construir mnulmente.

A continucio n se incluye un ejemplo del funcionmiento del envo de pr metros l servidor. Se


trt de un formulrio con tres cmpos de texto que se vlidn en el servidor medinte AJAX. El
co digo HTML tmbie n incluye un elemento <div> vco que se utiliz pr mostrr l respuest
del servidor:
<form>
<label for="fecha_nacimiento">Fecha de nacimiento:</label>
<input type="text" id="fecha_nacimiento" name="fecha_nacimiento" /><br/>

<label for="codigo_postal">Codigo postal:</label>


<input type="text" id="codigo_postal" name="codigo_postal" /><br/>

<label for="telefono">Telefono:</label>
<input type="text" id="telefono" name="telefono" /><br/>

<input type="button" value="Validar datos" />


</form>

<div id="respuesta"></div>

El co digo nterior produce l siguiente p gin:

Figura 7.3. Formulario de ejemplo

El co digo JvScript necesrio pr relizr l vlidcio n de los dtos en el servidor se muestr


continucio n:
var READY_STATE_COMPLETE=4;
var peticion_http = null;

function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function crea_query_string() {
var fecha = document.getElementById("fecha_nacimiento");
var cp = document.getElementById("codigo_postal");
var telefono = document.getElementById("telefono");

return "fecha_nacimiento=" + encodeURIComponent(fecha.value) +


"&codigo_postal=" + encodeURIComponent(cp.value) +
"&telefono=" + encodeURIComponent(telefono.value) +
"&nocache=" + Math.random();
}

function valida() {
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/validaDatos.php", true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var query_string = crea_query_string();
peticion_http.send(query_string);
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
document.getElementById("respuesta").innerHTML = peticion_http.responseText;
}
}
}

L clve del ejemplo nterior se encuentr en ests dos lnes de co digo:


peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send(query_string);

En primer lugr, si no se estblece l cbecer Content-Type correct, el servidor descrt todos


los dtos envidos medinte el me todo POST. De est form, l progrm que se ejecut en el
servidor no le lleg ningu n pr metro. As, pr envir pr metros medinte el me todo POST, es
obligtorio incluir l cbecer Content-Type medinte l siguiente instruccio n:
peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

Por otr prte, el me todo send() es el que se encrg de envir los pr metros l servidor. En
todos los ejemplos nteriores se utilizb l instruccio n send(null) pr indicr que no se
envn pr metros l servidor. Sin embrgo, en este cso l peticio n si que v envir los
pr metros.

Como y se h comentdo, los pr metros se envn en form de cden de texto con ls


vribles y sus vlores conctendos medinte el smbolo & (est cden normlmente se
conoce como "query string"). L cden con los pr metros se construye mnulmente, pr lo
cul se utiliz l funcio n crea_query_string():
function crea_query_string() {
var fecha = document.getElementById("fecha_nacimiento");
var cp = document.getElementById("codigo_postal");
var telefono = document.getElementById("telefono");

return "fecha_nacimiento=" + encodeURIComponent(fecha.value) +


"&codigo_postal=" + encodeURIComponent(cp.value) +
"&telefono=" + encodeURIComponent(telefono.value) +
"&nocache=" + Math.random();
}

L funcio n nterior obtiene el vlor de todos los cmpos del formulrio y los concten junto con
el nombre de cd pr metro pr formr l cden de texto que se env l servidor. El uso de
l funcio n encodeURIComponent() es imprescindible pr evitr problems con lgunos
crcteres especiles.
L funcio n encodeURIComponent() reemplz todos los crcteres que no se pueden utilizr
de form direct en ls URL por su representcio n hexdeciml. Ls letrs, nu meros y los
crcteres - _ . ! ~ * ' ( ) no se modificn, pero todos los dem s crcteres se sustituyen
por su equivlente hexdeciml.

Ls sustituciones m s conocids son ls de los espcios en blnco por %20, y l del smbolo &
por
%26. Sin embrgo, como se muestr en el siguiente ejemplo, tmbie n se sustituyen todos los
centos y culquier otro cr cter que no se puede incluir directmente en un URL:
var cadena = "cadena de texto";
var cadena_segura = encodeURIComponent(cadena);
// cadena_segura = "cadena%20de%20texto";

var cadena = "otra cadena & caracteres problemticos / : =";


var cadena_segura = encodeURIComponent(cadena);
// cadena_segura = "otra%20cadena%20%26%20caracteres%20problem%C3%A1ticos
%20%2F%20%3A%20%3D";

JvScript incluye un funcio n contrri llmd decodeURIComponent() y que reliz l


trnsformcio n invers. Adem s, tmbie n existen ls funciones encodeURI() y decodeURI()
que codificn/decodificn un URL complet. L principl diferenci entre
encodeURIComponent() y encodeURI() es que est u ltim no codific los crcteres ; / ? : @
& = + $ , #:

var cadena = "http://www.ejemplo.com/ruta1/index.php?parametro=valor con y &";


var cadena_segura = encodeURIComponent(cadena);
// cadena_segura = "http%3A%2F%2Fwww.ejemplo.com%2Fruta1%2Findex.php%3Fparametro%3Dvalor%20con
%20%C3%B1%20y%20%26";

var cadena_segura = encodeURI(cadena);


// cadena_segura = "http://www.ejemplo.com/ruta1/
index.php?parametro=valor%20con%20%C3%B1%20y%20";

Por u ltimo, l funcio n crea_query_string() n de l finl de l cden un pr metro


llmdo nocache y que contiene un nu mero letorio (credo medinte el me todo
Math.random()). An dir un pr metro letorio dicionl ls peticiones GET y POST es un
de ls estrtegis m s utilizds pr evitr problems con l cche de los nvegdores. Como
cd peticio n vr l menos en el vlor de uno de los pr metros, el nvegdor est obligdo
siempre relizr l peticio n directmente l servidor y no utilizr su cche. A continucio n se
muestr un ejemplo de l query string cred por l funcio n definid:

Figura 7.4. Query String creada para el formulario de ejemplo

En este ejemplo sencillo, el servidor simplemente devuelve el resultdo de un supuest


vlidcio n de los dtos envidos medinte AJAX:
Figura 7.5. Mostrando el resultado devuelto por el servidor

En ls plicciones reles, ls vlidciones de dtos medinte AJAX so lo se utilizn en el cso de


vlidciones complejs que no se pueden relizr medinte el uso de co digo JvScript b sico.
En generl, ls vlidciones complejs requieren el uso de bses de dtos: comprobr que un
nombre de usurio no este previmente registrdo, comprobr que l loclidd se corresponde
con el co digo postl indicdo, etc.

Ejercicio 13

Un ejemplo de validacin compleja es la que consiste en comprobar si un nombre de usuario


escogido est libre o ya lo utiliza otro usuario. Como es una validacin que requiere el uso de una
base de datos muy grande, no se puede realizar en el navegador del cliente. Utilizando las tcnicas
mostradas anteriormente y la pgina web que se proporciona:

1. Crear un script que compruebe con AJAX y la ayuda del servidor si el nombre escogido por el
usuario est libre o no.
2. El script del servidor se llama compruebaDisponibilidad.php y el parmetro que
contiene el nombre se llama login.
3. La respuesta del servidor es "si" o "no", en funcin de si el nombre de usuario est libre
y se puede utilizar o ya ha sido ocupado por otro usuario.
4. A partir de la respuesta del servidor, mostrar un mensaje al usuario indicando el resultado
de la comprobacin.

7.5.2. Refactorizando la utilidad net.CargadorContenidos


L utilidd disen d nteriormente pr l crg de contenidos y recursos lmcendos en el
servidor, solmente est preprd pr relizr peticiones HTTP sencills medinte GET. A
continucio n se refctoriz es utilidd pr que permit ls peticiones POST y el envo de
pr metros l servidor.

El primer cmbio necesrio es el de dptr el constructor pr que se puedn especificr los


nuevos pr metros:
net.CargadorContenidos = function(url, funcion, funcionError, metodo, parametros,
contentType) {

Se hn n dido tres nuevos pr metros: el me todo HTTP empledo, los pr metros que se
envn l servidor junto con l peticio n y el vlor de l cbecer content-type.
A continucio n, se sustituye l instruccio n this.req.open('GET', url, true); por est otr:
this.req.open(metodo, url, true);

El siguiente pso es n dir (si s se indic) l cbecer Content-Type de l peticio n:


if(contentType) {
this.req.setRequestHeader("Content-Type", contentType);
}

Por u ltimo, se sustituye l instruccio n this.req.send(null); por est otr:


this.req.send(parametros);

As, el co digo completo de l solucio n refctorizd es el siguiente:


var net = new Object();

net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;

// Constructor
net.CargadorContenidos = function(url, funcion, funcionError, metodo, parametros,
contentType) {
this.url = url;
this.req = null;
this.onload = funcion;
this.onerror = (funcionError) ? funcionError : this.defaultError;
this.cargaContenidoXML(url, metodo, parametros, contentType);
}

net.CargadorContenidos.prototype = {
cargaContenidoXML: function(url, metodo, parametros, contentType) {
if(window.XMLHttpRequest) {
this.req = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
this.req = new ActiveXObject("Microsoft.XMLHTTP");
}

if(this.req) {
try {
var loader = this;
this.req.onreadystatechange = function() {
loader.onReadyState.call(loader);
}
this.req.open(metodo, url, true);
if(contentType) {
this.req.setRequestHeader("Content-Type", contentType);
}
this.req.send(parametros);
} catch(err) {
this.onerror.call(this);
}
}
},

onReadyState: function() {
var req = this.req;
var ready = req.readyState;
if(ready == net.READY_STATE_COMPLETE) {
var httpStatus = req.status;
if(httpStatus == 200 || httpStatus == 0) {
this.onload.call(this);
}
else {
this.onerror.call(this);
}
}
},

defaultError: function() {
alert("Se ha producido un error al obtener los datos"
+ "\n\nreadyState:" + this.req.readyState
+ "\nstatus: " + this.req.status
+ "\nheaders: " + this.req.getAllResponseHeaders());
}
}

7.6. Aplicaciones complejas


7.6.1. Envo de parmetros mediante XML
L flexibilidd del objeto XMLHttpRequest permite el envo de los pr metros por otros medios
lterntivos l trdicionl query string. De est form, si l pliccio n del servidor s lo
requeire, es posible relizr un peticio n l servidor envindo los pr metros en formto XML.

A continucio n se modific el ejemplo nterior pr envir los dtos del usurio en form de
documento XML. En primer lugr, se modific l llmd l funcio n que construye l query
string:
function valida() {
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/validaDatos.php", true);
var parametros_xml = crea_xml();
peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send(parametros_xml);
}
}

Seguidmente, se cre l funcio n crea_xml() que se encrg de construir el documento XML


que contiene los pr metros envidos l servidor:
function crea_xml() {
var fecha = document.getElementById("fecha_nacimiento");
var cp = document.getElementById("codigo_postal");
var telefono = document.getElementById("telefono");

var xml = "<parametros>";


xml = xml + "<fecha_nacimiento>" + fecha.value + "<\/fecha_nacimiento>";
xml = xml + "<codigo_postal>" + cp.value + "<\/codigo_postal>";
xml = xml + "<telefono>" + telefono.value + "<\/telefono>";
xml = xml + "<\/parametros>";
return xml;
}

El co digo de l funcio n nterior emple el cr cter \ en el cierre de tods ls etiquets XML.


El motivo es que ls etiquets de cierre XML y HTML (l contrrio que ls etiquets de pertur)
se interpretn en el mismo lugr en el que se encuentrn, por lo que si no se incluyen esos
crcteres \ el co digo no vlidr siguiendo el est ndr XHTML de form estrict.

El me todo send() del objeto XMLHttpRequest permite el envo de un cden de texto y de


un documento XML. Sin embrgo, en el ejemplo nterior se h optdo por un solucio n
intermedi: un cden de texto que represent un documento XML. El motivo es que no existe
d de hoy un me todo robusto y que se pued empler en l myor de nvegdores pr l
crecio n de documentos XML completos.

7.6.2. Procesando respuestas XML


Adem s del envo de pr metros en formto XML, el objeto XMLHttpRequest tmbie n permite
l recepcio n de respuests de servidor en formto XML. Un vez obtenid l respuest del
servidor medinte l propiedd peticin_http.responseXML, es posible procesrl emplendo
los me todos DOM de mnejo de documentos XML/HTML.

En este cso, se modific l respuest del servidor pr que no se un texto sencillo, sino que l
respuest este definid medinte un documento XML:
<respuesta>
<mensaje>...</mensaje>
<parametros>
<telefono>...</telefono>
<codigo_postal>...</codigo_postal>
<fecha_nacimiento>...</fecha_nacimiento>
</parametros>
</respuesta>

L respuest del servidor incluye un mensje sobre el e xito o frcso de l opercio n de


vlidcio n de los pr metros y dem s incluye l list complet de pr metros envidos l
servidor.

L funcio n encrgd de procesr l respuest del servidor se debe modificr por completo pr
trtr el nuevo tipo de respuest recibid:
function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
var documento_xml = peticion_http.responseXML;
var root = documento_xml.getElementsByTagName("respuesta")[0];
var mensajes = root.getElementsByTagName("mensaje")[0];
var mensaje = mensajes.firstChild.nodeValue;

var parametros = root.getElementsByTagName("parametros")[0];

var telefono =
parametros.getElementsByTagName("telefono")[0].firstChild.nodeValue;
var fecha_nacimiento =
parametros.getElementsByTagName("fecha_nacimiento")[0].firstChild.nodeValue;
var codigo_postal =
parametros.getElementsByTagName("codigo_postal")[0].firstChild.nodeValue;

document.getElementById("respuesta").innerHTML = mensaje + "<br/>" + "Fecha


nacimiento = " + fecha_nacimiento + "<br/>" + "Codigo postal = " + codigo_postal +
"<br/>" + "Telefono = " + telefono;
}
}
}

El primer cmbio importnte es el de obtener el contenido de l respuest del servidor. Hst


hor, siempre se utilizb l propiedd responseText, que devuelve el texto simple que incluye
l respuest del servidor. Cundo se procesn respuests en formto XML, se debe utilizr l
propiedd responseXML.

El vlor devuelto por responseXML es un documento XML que contiene l respuest del servidor.
Como se trt de un documento XML, es posible utilizr con sus contenidos tods ls funciones
DOM que se vieron en el cptulo correspondiente DOM.

Aunque el mnejo de repuests XML es mucho m s pesdo y requiere el uso de numeross


funciones DOM, su utilizcio n se hce imprescindible pr procesr respuests muy complejs o
respuests recibids por otros sistems que exportn sus respuests interns un formto
est ndr XML.

El mecnismo pr obtener los dtos vr mucho segu n cd documento XML, pero en generl,
se trt de obtener el vlor lmcendo en lgunos elementos XML que su vez pueden ser
descendientes de otros elementos. Pr obtener el primer elemento que se corresponde con un
etiquet XML, se utiliz l siguiente instruccio n:
var elemento = root.getElementsByTagName("nombre_etiqueta")[0];

En este cso, se busc l primer etiquet <nombre_etiqueta> que se encuentr dentro del
elemento root (en este cso se trt de l rz del documento XML). Pr ello, se buscn tods
ls etiquets <nombre_etiqueta> del documento y se obtiene l primer medinte [0], que
corresponde l primer elemento del rry de elementos.

Un vez obtenido el elemento, pr obtener su vlor se debe cceder su primer nodo hijo (que
es el nodo de tipo texto que lmcen el vlor) y obtener l propiedd nodeValue, que es l
propiedd que gurd el texto correspondiente l vlor de l etiquet:
var valor = elemento.firstChild.nodeValue;

Normlmente, ls dos instrucciones nteriores se unen en un sol instruccio n:


var tfno = parametros.getElementsByTagName("telefono")[0].firstChild.nodeValue;

Ejercicio 14

Normalmente, cuando se valida la disponibilidad de un nombre de usuario, se muestra una lista de


valores alternativos en el caso de que el nombre elegido no est disponible. Modificar el ejercicio de
comprobacin de disponibilidad de los nombres para que permita mostrar una serie de valores
alternativos devueltos por el servidor.

El script del servidor se llama compruebaDisponibilidadXML.php y el parmetro que contiene el


nombre se llama login. La respuesta del servidor es un documento XML con la siguiente estructura:

Si el nombre de usuario est libre:


<respuesta>
<disponible>si</disponible>
</respuesta>

Si el nombre de usuario est ocupado:


<respuesta>
<disponible>no</disponible>
<alternativas>
<login>...</login>
<login>...</login>
...
<login>...</login>
</alternativas>
</respuesta>

Los nombres de usuario alternativos se deben mostrar en forma de lista de elementos ( <ul></ul>).

Modificar la lista anterior para que muestre enlaces para cada uno de los nombres alternativos. Al
pinchar sobre el enlace de un nombre alternativo, se copia en el cuadro de texto del login del
usuario.

7.6.3. Parmetros y respuestas JSON


Aunque el formto XML est soportdo por csi todos los lengujes de progrmcio n, por
muchs plicciones y es un tecnolog mdur y probd, en lguns ocsiones es m s u til
intercmbir informcio n con el servidor en formto JSON.

JSON es un formto mucho m s compcto y ligero que XML. Adem s, es mucho m s f cil de
procesr en el nvegdor del usurio. Afortundmente, cd vez existen m s utiliddes pr
procesr y generr el formto JSON en los diferentes lengujes de progrmcio n del servidor
(PHP, Jv, C#, etc.)

El ejemplo mostrdo nteriormente pr procesr ls respuests XML del servidor se puede


reescribir utilizndo respuests JSON. En este cso, l respuest que gener el servidor es mucho
m s concis:
{
mensaje: "...",
parametros: {telefono: "...", codigo_postal: "...", fecha_nacimiento: "..." }
}

Considerndo el nuevo formto de l respuest, es necesrio modificr l funcio n que se encrg


de procesr l respuest del servidor:
function procesaRespuesta() {
if(http_request.readyState == READY_STATE_COMPLETE) {
if(http_request.status == 200) {
var respuesta_json = http_request.responseText;
var objeto_json = eval("("+respuesta_json+")");

var mensaje = objeto_json.mensaje;

var telefono = objeto_json.parametros.telefono;


var fecha_nacimiento = objeto_json.parametros.fecha_nacimiento;
var codigo_postal = objeto_json.parametros.codigo_postal;

document.getElementById("respuesta").innerHTML = mensaje + "<br>" + "Fecha


nacimiento = " + fecha_nacimiento + "<br>" + "Codigo postal = " + codigo_postal +
"<br>" + "Telefono = " + telefono;
}
}
}

L respuest JSON del servidor se obtiene medinte l propiedd responseText:


var respuesta_json = http_request.responseText;

Sin embrgo, est propiedd solmente devuelve l respuest del servidor en form de cden
de texto. Pr trbjr con el co digo JSON devuelto, se debe trnsformr es cden de texto en
un objeto JSON. L form m s sencill de relizr es conversio n es medinte l funcio n eval(),
en l que deben n dirse pre ntesis l principio y l finl pr relizr l evlucio n de form
correct:
var objeto_json = eval("("+respuesta_json+")");

Un vez relizd l trnsformcio n, el objeto JSON y permite cceder sus me todos y


propieddes medinte l notcio n de puntos trdicionl. Comprdo con ls respuests XML,
este procedimiento permite cceder l informcio n devuelt por el servidor de form mucho
m s simple:
// Con JSON
var fecha_nacimiento = objeto_json.parametros.fecha_nacimiento;

// Con XML
var parametros = root.getElementsByTagName("parametros")[0]; var
fecha_nacimiento = parametros.getElementsByTagName("fecha_nacimiento")
[0].firstChild.nodeValue;

Tmbie n es posible el envo de los pr metros en formto JSON. Sin embrgo, no es un tre
tn sencill como l crecio n de un documento XML. As, se hn disen do utiliddes especfics
pr l trnsformcio n de objetos JvScript cdens de texto que representn el objeto en
formto JSON. Est librer se puede descrgr desde el sitio web www.json.org.
Pr emplerl, se n de l referenci en el co digo de l p gin:
<script type="text/javascript" src="json.js"></script>

Un vez referencid l librer, se emple el me todo stringify pr relizr l


trnsformcio n:
var objeto_json = JSON.stringify(objeto);

Adem s de ls librers pr JvScript, est n disponibles otrs librers pr muchos otros


lengujes de progrmcio n hbitules. Emplendo l librer desrrolld pr Jv, es posible
procesr l peticio n JSON relizd por un cliente:
import org.json.JSONObject;
...
String cadena_json = "{propiedad: valor, codigo_postal: otro_valor}";
JSONObject objeto_json = new JSONObject(cadena_json);
String codigo_postal = objeto_json.getString("codigo_postal");

Ejercicio 15

Rehacer el ejercicio 14 para procesar respuestas del servidor en formato JSON. Los cambios
producidos son:

1) El script del servidor se llama compruebaDisponibilidadJSON.php y el parmetro que contiene


el nombre se llama login.

2) La respuesta del servidor es un objeto JSON con la siguiente estructura:

El nombre de usuario est libre:


{ disponible: "si" }

El nombre de usuario est ocupado:


{ disponible: "no", alternativas: ["...", "...", ..., "..."] }

7.7. Seguridad
L ejecucio n de plicciones JvScript puede suponer un riesgo pr el usurio que permite su
ejecucio n. Por este motivo, los nvegdores restringen l ejecucio n de todo co digo JvScript
un entorno de ejecucio n limitdo y pr cticmente sin recursos ni permisos pr relizr tres
b sics.

Ls plicciones JvScript no pueden leer ni escribir ningu n rchivo del sistem en el que se
ejecutn. Tmpoco pueden estblecer conexiones de red con dominios distintos l dominio en el
que se loj l pliccio n JvScript. Adem s, un script so lo puede cerrr quells ventns de
nvegdor que h bierto ese script.

L restriccio n del cceso diferentes dominios es m s restrictiv de lo que en principio puede


precer. El problem es que los nvegdores emplen un me todo demsido simple pr
diferencir entre dos dominios y que no permiten ni subdominios ni otros protocolos ni otros
puertos.
Por ejemplo, si el co digo JvScript se descrg desde l siguiente URL:
http://www.ejemplo.com/scripts/codigo.js, ls funciones y me todos incluidos en ese co digo no
pueden cceder los recursos contenidos en los siguientes rchivos:

http://www.ejemplo.com:8080/scripts/codigo2.js
https://www.ejemplo.com/scripts/codigo2.js
http://192.168.0.1/scripts/codigo2.js
http://scripts.ejemplo.com/codigo2.js

Afortundmente, existe un form de solucionr prcilmente el problem del cceso


recursos no origindos exctmente en el mismo dominio. L solucio n se bs en estblecer el
vlor de l propiedd document.domain

As, si el co digo lojdo en http://www.ejemplo.com/scritps/codigo1.js estblece l vrible


document.domain = "ejemplo.com"; y por otr prte, el co digo lojdo en
http://scripts.ejemplo.com/codigo2.js estblece l vrible document.domain =
"ejemplo.com"; los recursos de mbos co digos pueden interctur entre s.

L propiedd document.domain se emple pr permitir el cceso entre subdominios del


dominio principl de l pliccio n. Evidentemente, los nvegdores no permiten estblecer
culquier vlor en es propiedd, por lo que so lo se puede indicr un vlor que correspond
un prte del subdominio completo donde se encuentr el script.
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

Captulo 8. Tcnicas bsicas con AJAX


8.1. Listas desplegables encadenadas
8.1.1. Contexto
Alguns plicciones web disponen de vris lists desplegbles encdends. En este tipo de
lists, cundo se seleccion un elemento de l primer list desplegble, se crgn en l segund
list unos vlores que dependen del vlor selecciondo en l primer list.

El myor inconveniente de este tipo de lists se produce cundo existen un grn nu mero de
opciones posibles. Si se consider por ejemplo el cso de un tiend, en l primer list
desplegble se pueden mostrr decens de productos y en l segund list se muestrn los
diferentes modelos de cd producto y sus precios.

Si todos los elementos de ls lists desplegbles se lmcenn medinte rrys de JvScript en


l propi p gin, los tiempos de crg se pueden disprr y hcerlo completmente invible.

Por otr prte, se puede optr por recrgr completmente l p gin cd vez que se seleccion
un vlor diferente en l primer list desplegble. Sin embrgo, recrgr l p gin enter cd
vez que se seleccion un vlor, ument l crg en el servidor y el tiempo de esper del usurio.

Un posible solucio n intermedi consiste en ctulizr ls lists desplegbles medinte AJAX.


Los vlores de l primer list se incluyen en l p gin web y cundo se seleccion un vlor de
est list, se reliz un consult l servidor que devuelve los vlores que se deben mostrr en l
otr list desplegble.

8.1.2. Solucin propuesta


A continucio n se muestr el esquem gr fico del funcionmiento de l solucio n propuest:
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

Figura 8.1. Solucin propuesta para las listas encadenadas con AJAX

Ejercicio 16

Crear un script que cargue de forma dinmica mediante AJAX la lista de provincias de un pas y la lista
de los municipios de cada provincia seleccionada.

1) Definir el cdigo HTML de las dos listas desplegables vacas.

2) Cuando se cargue la pgina, cargar la lista de provincias en la primera lista desplegable. El script
del servidor se llama cargaProvinciasXML.php. El formato de la respuesta es XML, con la siguiente
estructura:
<provincias>
<provincia>
<codigo>01</codigo>
<nombre>lava</nombre>
</provincia>
...
</provincias>

Para insertar las opciones en la lista desplegable, se pueden utilizar dos tcnicas:

1. Propiedad innerHTML de la lista y cdigo HTML de cada etiqueta <option>.


2. Crear elementos de tipo opcin (new Option(nombre, valor)) y aadirlo al array
options[] de la lista desplegable.

3) Aadir de forma semntica el evento adecuado a la lista de provincias para que cuando se
seleccione una provincia, se carguen automticamente todos sus municipios en la otra lista.
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

4) Cuando se seleccione una determinada provincia, se carga mediante AJAX la lista completa de
municipios en la otra lista desplegable. El script del servidor se llama cargaMunicipiosXML.php. El
parmetro que se debe enviar al servidor es el cdigo de la provincia y el parmetro se llama
provincia. El mtodo que espera el servidor es POST. El formato de la respuesta es XML, con la
siguiente estructura:
<municipios>
<municipio>
<codigo>0014</codigo>
<nombre>Alegra-Dulantzi</nombre>
</municipio>
...
</municipios>

Ejercicio 17

Modificar el ejercicio anterior para soportar las respuestas del servidor en formato JSON. Los
cambios introducidos son los siguientes:

1) El script del servidor utilizado para cargar las provincias se llama cargaProvinciasJSON.php y la
respuesta del servidor tiene el siguiente formato:
{ "01": "lava/Araba", "02": "Albacete", "03": "Alicante/Alacant", ... }

2) El script del servidor utilizado para cargar los municipios se llama cargaMunicipiosJSON.php y la
respuesta del servidor tiene el siguiente formato:
{ "0014": "Alegra-Dulantzi", "0029": "Amurrio", ... }

8.2. Teclado virtual


8.2.1. Contexto
Alguns plicciones web multi-idiom disponen de l posibilidd de introducir informcio n en
muchos idioms diferentes. El principl problem de ests plicciones es que el tecldo fsico
que utiliz el usurio no siempre corresponde l idiom en el que se quieren introducir los
contenidos.

L solucio n hbitul de este problem consiste en mostrr un tecldo virtul en l pntll que
muestre el vlor correcto pr cd tecl del idiom selecciondo por el usurio.

8.2.2. Solucin propuesta


A continucio n se muestr el specto gr fico del tecldo virtul que se v construir medinte
AJAX:
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

Figura 8.2. Aspecto final del teclado virtual construido con AJAX

Ejercicio 18

Se propone la construccin de un teclado virtual que permita escribir los contenidos en diversos
idiomas y alfabetos. El script hace un uso intensivo de elementos de AJAX como los eventos, DOM,
javascript avanzado, JSON y el objeto XMLHttpRequest.

Cada uno de los teclados correspondientes a un idioma se carga desde el servidor, para no
sobrecargar la aplicacin. El teclado de un idioma concreto est formado por varios teclados
alternativos o variantes. As, se encuentra el teclado normal para las teclas que se muestran
inicialmente, el teclado caps con las teclas que se escriben al pulsar sobre la tecla Bloq.
Maysculas, el teclado shift que contiene los smbolos que se escriben al pulsar sobre la tecla
Shift y el teclado altgr que contiene los smbolos que se pueden escribir despus de pulsar la
tecla Alt Gr.

Por tanto, cada idioma tiene cuatro teclados diferentes: normal, caps, shift y altgr. Inicialmente,
el script proporciona el objeto teclados con un elemento llamado es que contiene los cuatro
teclados correspondientes al idioma espaol.

Figura 8.3. Detalle del teclado para el idioma espaol y la variante "normal"
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

Figura 8.4. Detalle del teclado para el idioma espaol y la variante "caps"

Figura 8.5. Detalle del teclado para el idioma espaol y la variante "shift"

Figura 8.6. Detalle del teclado para el idioma espaol y la variante "altgr"

1) Crear una funcin llamada cargaTeclado() que muestre en cada tecla virtual el valor de la
tecla correspondiente al teclado de un idioma y una variante determinados.

2) Al cargar la pgina, se debe ejecutar la funcin cargaTeclado(). Previamente, se debe establecer


el valor inicial de dos variables globales llamadas tecladoIdioma y tecladoVariante.

En la misma funcin cargaTeclado(), se debe asignar un evento a cada tecla activa para que al
pulsar con el ratn sobre ella, se ejecute la funcin pulsaTecla().

3) En la funcin pulsaTecla() se obtiene el carcter de la tecla que se ha pulsado correspondiente


al teclado activo en ese momento. La tecla se aade a un array global llamado teclasPulsadas.

Por ltimo, desde la funcin pulsaTecla() se llama a una funcin mostrarContenidos() que
actualiza el texto mostrado en el rea reservada para mostrar las teclas pulsadas.

4) Aadir la lgica para tratar las "teclas especiales". Para ello, aadir un evento adecuado que llame
a la funcin pulsaTeclaEspecial() cuando el usuario pulse sobre Enter, Tabulador, Barra
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

Espaciadora y Borrado (BackSpace). En cada caso, se debe aadir al array de teclas pulsadas
el carcter correspondiente: \n, \t, espacio en blanco y el borrado de la ltima tecla pulsada.

5) Modificar la funcin mostrarContenidos() para que antes de mostrar las teclas que se han
pulsado, convierta los caracteres especiales en caracteres correctos para mostrarlos en un elemento
HTML: las nuevas lneas (\n) se transforman en <br/>, los espacios en blanco se transforman en
&nbsp; y el tabulador (\t) se transforma en
&nbsp;&nbsp;&nbsp;&nbsp;.

6) Cuando se pulsa la tecla Bloq. Mays. o Shift o Alt Gr, se debe cambiar la variante del
teclado actual. Para ello, existen las variantes caps para las maysculas, shift para los smbolos
de la tecla Shift y altgr para los smbolos que aparecen cuando se pulsa la tecla AltGr. Aadir a
estas teclas especiales el evento adecuado para que se ejecute la funcin pulsaTeclaEspecial()
en la que se deben realizar las tareas que correspondan a cada tecla. Adems, debera crearse una
variable global llamada estado que almacene en todo momento el estado de pulsacin de estas
teclas especiales, ya que el resultado no es el mismo si se pulsa la tecla de maysculas estando o no
estando pulsada anteriormente.

7) Una vez configurado el script bsico del teclado virtual, se van a aadir los elementos relativos a la
comunicacin con el servidor. En primer lugar, al cargar la pgina se muestran en una lista
desplegable todos los idiomas disponibles. El script del servidor se llama tecladoVirtual.php y
el envo de parmetros se realiza mediante POST. Para cargar los idiomas disponibles, el parmetro
que se debe utilizar es accion y su valor es listaIdiomas. La respuesta del servidor es un objeto
JSON con los cdigos y nombres de cada idioma, adems del cdigo del idioma que se carga al
principio:
{ idiomas: {es: "Espaol", de: "Alemn", ru: "Ruso", el: "Griego", ...},
defecto: "es" }

Figura 8.7. Lista desplegable con los idiomas disponibles para el teclado virtual

8) Cuando se cambie el idioma en la lista desplegable, se debe cargar automticamente el teclado


correspondiente a ese idioma. El primer teclado que se muestra al cargar la pgina es el
correspondiente al idioma por defecto indicado por el servidor.

Los teclados de cada idioma con todas sus variantes tambin se descargan desde el servidor. El script
es tecladoVirtual.php, en este caso la accin es cargaTeclado y se debe pasar otro parmetro
llamado idioma con el cdigo del idioma cuyo teclado se quiere cargar desde el servidor.

La respuesta del servidor es la siguiente:


{ normal: ["&#x00BA;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;",
"&#x0036;", ..., "&#x002E;", "&#x002D;"],
caps: ["&#x00BA;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;",
"&#x0036;", ..., "&#x002E;", "&#x002D;"],
shift: ["&#x00AA;", "&#x0021;", "&#x0022;", "&#x0027;", "&#x0024;", "&#x0025;",
Introduccin a AJAX..., "&#x003A;", "&#x005F;"],
"&#x0026;", Captulo 8. Tcnicas bsicas con AJAX
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

altgr: ["&#x005C;", "&#x007C;", "&#x0040;", "&#x0023;",,, "&#x00AC;",,,,,,,,


,,,,,,,,, "&#x005B;","&#x005D;",,,,,,,,,,, "&#x007B;", "&#x007D;",,,,,,,,,,""] }

Figura 8.8. Detalle del teclado para el idioma ruso y la variante "normal"

Figura 8.9. Detalle del teclado para el idioma griego y la variante "normal"

Si se utiliza net.CargadorContenidoscompleto, puede ser til emplear el ltimo parmetro que


indica si la peticin al servidor es sncrona o asncrona. En este caso, debera ser sncrona, ya que el
resto del programa no puede seguir trabajando hasta que se haya cargado completamente el teclado
solicitado.

9) Por ltimo, se va a aadir la caracterstica de autoguardado. Para ello, cada 30 segundos se enva
el contenido del usuario al servidor para almacenarlo de forma segura. El servidor devuelve el texto
que ha guardado y se muestra en la pgina para comprar el texto del usuario y el texto guardado. El
script del servidor se llama tecladoVirtual.php, la accin es guardar y el parmetro contenido
es el que indica el contenido creado por el usuario.

10) Se puede aadir una pequea mejora visual al teclado virtual: existe una clase de CSS llamada
pulsada y que se puede utilizar para resaltar de forma clara la tecla que se ha pulsado. Utilizar esa
clase para iluminar durante un breve espacio de tiempo la tecla pulsada en cada momento.

11) Otras posibles mejoras: funcionamiento del teclado numrico, funcionamiento de los acentos,
manejo de los LED del teclado, etc.

8.3. Autocompletar
8.3.1. Contexto
Alguns veces, se present l usurio un cudro de texto en el que tiene que introducir un vlor
que pertenece un grupo muy grnde de dtos. Algunos csos hbitules son: un direccio n de
correo electro nico que pertenezc l libret de direcciones del usurio, el nombre v lido de un
municipio de un ps, el nombre de un empledo de un empres grnde, etc.

En l myor de csos, utilizr un list desplegble que muestre todos los vlores es
completmente invible, y que pueden existir miles de posibles vlores. Por otr prte, un
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

cudro de texto simple result de poc utilidd pr el usurio. L solucio n consiste en combinr
un cudro de texto y un list desplegble medinte AJAX.

Al usurio se le present un cudro de texto simple en el que puede introducir l informcio n. A


medid que el usurio escribe en el cudro de texto, l pliccio n solicit l servidor quellos
te rminos que este n relciondos con lo escrito por el usurio. Cundo l pliccio n recibe l
respuest del servidor, l muestr l usurio modo de yud pr utocompletr l
informcio n.

8.3.2. Solucin propuesta


A continucio n se muestr l interccio n del sistem de utocompletdo propuesto:

Figura 8.10. Interaccin completa del usuario con el sistema de autocompletado

Ejercicio 19

A partir del formulario proporcionado, aadir la opcin de autocompletar el nombre del municipio
que est escribiendo el usuario. El esquema del funcionamiento propuesto es el siguiente:

1) Al cargar la pgina, se debe crear un elemento HTML de tipo <div> en el que se van a mostrar las
sugerencias enviadas por el servidor.

Adems, se debe establecer el evento de teclado adecuado en el cuadro de texto y tambin se debe
posicionar el cursor en ese cuadro de texto para poder escribir en el directamente (Pista: focus()).

2) Cuando se pulse una tecla sobre el cuadro de texto, se debe ejecutar la funcin autocompleta().
Desde esta funcin, se debe llamar a la funcin responsable de obtener la lista de municipios del
servidor. El script se llama autocompletaMunicipios.php, el parmetro que se enva mediante
POST, se llama municipio y debe contener la cadena de texto escrita por el usuario.
Introduccin a AJAX Captulo 8. Tcnicas bsicas con AJAX

El servidor responde con un array en formato JSON con la lista de municipios cuyo nombre comienza
por el texto enviado. Ejemplo de respuesta del servidor:
[ "Alegra-Dulantzi", "Amurrio", "Aana", "Aramaio", "Armin", ... ]

3) Una vez obtenido el array de sugerencias, se debe mostrar en forma de lista de elementos
(etiqueta <ul> de HTML). Para transformar el array en la lista <ul>, modificar el prototype del
objeto Array y aadir una funcin especfica que realice la transformacin.

4) Modificar la funcin autocompleta() para tener en consideracin 3 teclas especiales: las flechas
superior e inferior y la tecla Enter. (Pista: propiedad keyCode). Cuando se utilizan las flechas del
teclado hacia arriba y hacia abajo, se van seleccionando los elementos de la lista. Cuando se pulsa el
Enter, se selecciona el elemento copiando su valor al cuadro de texto y ocultando la lista de
sugerencias. (Pista: variable global elementoSeleccionado)

5) Para mejorar el rendimiento de la aplicacin, aadir una cache para las sugerencias. Cada vez que
se recibe una lista de sugerencias del servidor, se almacena en un objeto que relaciona el texto que
ha introducido el usuario y la respuesta del servidor. Ejemplo:
{
"a": ["Ababuj", "Abades", "Abada", "Abadn", "Abadio", "Abigar", "Abajas",
"Abaltzisketa", "Abnades", "Abanilla", "Abanto y Cirvana-Abanto Zierbena", "Abanto",
"Abarn", "Abarca de Campos", "Abrzuza", "Abaurregaina/Abaurrea Alta", "Abaurrepea/
Abaurrea Baja", "Abegondo", "Abejar", "Abejuela", "Abella de la Conca"],

"al": ["Alacn", "Aladrn", "Alaejos", "Alagn", "Alaior", "Aljar", "Alajer",


"Alameda de Gardn (La)", "Alameda de la Sagra", "Alameda del Valle", "Alameda",
"Alamedilla (La)", "Alamedilla", "Alamillo", "Alaminos", "Alams (Els)", "Alange",
"Alans", "Alaqus", "Alar del Rey", "Alaraz"],
...
}

De esta forma, antes de realizar una peticin al servidor, se comprueba si ya est disponible una lista
de sugerencias para ese texto. Adems, cuando se realiza una consulta al servidor, la respuesta se
almacena en la cache para su posible reutilizacin futura.

6) Mostrar un mensaje adecuado cuando el servidor devuelva un array vaco por no haber
sugerencias para el texto introducido por el usuario.
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Captulo 9. Tcnicas avanzadas con AJAX


9.1. Monitorizacin de servidores remotos
9.1.1. Contexto
Ls plicciones JvScript ejecutds en los nvegdores tienen uns restricciones muy
estricts en cunto su seguridd. Adem s de no poder cceder recursos locles como
rchivos y directorios, los scripts solmente pueden relizr conexiones de red con el mismo
dominio l que pertenece l pliccio n JvScript.

9.1.2. Solucin propuesta


Ejercicio 20

Se propone la realizacin de una consola bsica de monitorizacin de equipos de red. Los servidores
que se van a monitorizar pertenecen a dominios conocidos de Internet y por tanto, externos a la
aplicacin JavaScript.

En otras palabras, se trata de "hacer un ping" a travs de la red mediante AJAX para comprobar los
equipos que se quieren monitorizar.

1) Cuando se cargue la pgina, se debe construir "el mapa de red" que muestra todos los servidores
que se van a monitorizar. Para construir este mapa, se proporciona la pgina web bsica y un objeto
llamado nodos, que contiene los datos correspondientes a los equipos que se quieren monitorizar.

Para mostrar cada nodo que se van a monitorizar, se crean dinmicamente elementos de tipo <div>
que muestran el nombre de cada nodo, su URL y una zona de datos en la que se mostrar ms
adelante cierta informacin del nodo. A continuacin se muestra un ejemplo del posible cdigo
XHTML que se puede utilizar:
<div id="nodo0" class="normal">
<strong>Nombre</strong>
<br/>
URL
<span id="datos0"></span>
</div>
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.1. Aspecto inicial de la consola de monitorizacin mostrando todos los servidores remotos
que se van a monitorizar

2) La consola de monitorizacin se controla mediante dos botones. De esta forma, se deben


establecer los eventos adecuados en los botones Monitorizar y Detener.

3) Al pulsar sobre el botn Monitorizar debe comenzar la ejecucin peridica (por ejemplo cada
10 segundos) de la funcin que realiza las conexiones con los servidores y procesa su respuesta.
Al pulsar sobre el botn Detener, se debe impedir la ejecucin peridica de esa funcin.

4) La funcin que se ejecuta de forma peridica (por ejemplo cada 10 segundos) debe realizar un
"ping" a cada uno de los equipos. Hacer un ping consiste en intentar establecer una conexin con el
servidor utilizando el mtodo HEAD de HTTP (en vez de los tradicionales mtodos GET o POST).

Si se intenta acceder a la pgina principal de un sitio web utilizando el mtodo HEAD y la peticin es
correcta, el servidor devuelve las cabeceras HTTP. De esta forma, para comprobar si el servidor ha
respondido de forma correcta, se puede intentar obtener el valor de alguna cabecera enviada por el
servidor, como por ejemplo Date.

Para realizar las peticiones, se puede utilizar la utilidad net.CargadorContenidosCompleto y


establecer de forma adecuada las funciones que se encargan de procesar las respuestas correctas y
las respuestas errneas.
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

5) La funcin que procesa las respuestas correctamente recibidas, debe obtener el valor de alguna
cabecera HTTP como por ejemplo Date. Si la respuesta es correcta, mostrar en la zona <span
id="datos"></span> de cada nodo el valor de la cabecera Server, que indica el tipo de servidor
web que utiliza el nodo remoto.

6) Tambin es importante mostrar visualmente la monitorizacin que se est realizando, por lo que
se van a modificar las propiedades CSS de cada nodo para indicar el estado en el que se encuentra:

Cuando se est realizando una consulta al servidor, la propiedad border de CSS debe ser igual
a 3px solid #000000.
Cuando la respuesta recibida es correcta, la clase CSS del <div> es "on" y el valor de
la propiedad border es 3px solid #00FF00.
Cuando la respuesta es errnea, la clase CSS del <div> es "off" y el valor de la
propiedad
border es 3px solid #FF0000.

Figura 9.2. La consola de monitorizacin muestra visualmente el estado de cada nodo y tambin
muestra parte de la informacin devuelta por el servidor

Al ejecutr l pliccio n en Internet Explorer, se muestr un viso l usurio sobre si dese dr


permiso l pliccio n pr relizr conexiones externs:
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.3. Mensaje de aviso que muestra Internet Explorer al intentar establecer conexiones de red
con servidores remotos

Pr poder ejecutr correctmente l pliccio n en los nvegdores de tipo Firefox, se debe


firmr digitlmente el script y solicitr permiso de form expres l usurio. Pr m s
informcio n, se puede consultr el siguiente recurso: http://www.mozill.org/projects/
security/components/signed-scripts.html

9.2. Lector RSS


9.2.1. Contexto
L sindiccio n de contenidos medinte protocolos como RSS y Atom h permitido que los sitios
web puedn comprtir f cilmente sus noticis, rtculos, entrds de blogs y muchos otros
contenidos digitles. Aunque RSS es un conjunto de formtos y protocolos, en su form u ltim es
un rchivo XML que incluye los contenidos que quiere comprtir el servidor web. L sencillez del
formto y l posibilidd de procesr rchivos XML con JvScript hcen que RSS se idel pr
desrrollr plicciones AJAX que trten con sus contenidos.

9.2.2. Solucin propuesta


Ejercicio 21

A partir de la pgina web que se proporciona, completar el script para realizar un lector avanzado de
canales RSS.

1) Al cargar la pgina, se debe aadir un evento en el botn Mostrar RSS.

2) El script debe mostrar informacin sobre las operaciones que realiza. Para ello, cada accin que se
ejecute debe mostrar un mensaje en el elemento <div id="info"></div> de la pgina.

3) Al pulsar sobre el botn Mostrar RSS, se ejecuta la funcin cargarRSS() y se informa al


usuario de que se est buscando el canal RSS.

4) La primera tarea que se ejecuta en la funcin cargarRSS() es la de obtener la URL especfica del
canal RSS a partir de la URL original de la pgina HTML. Esta tarea no es sencilla, por lo que es
recomendable utilizar el script del servidor llamado descubreRss.php(), que acepta un parmetro
llamado url pasado mediante el mtodo GET y devuelve la URL correspondiente al canal RSS.

5) Una vez obtenida la URL del canal RSS, se descarga su contenido. Para obtener los contenidos del
canal RSS, es conveniente utilizar un proxy que permita saltarse la restriccin de JavaScript para
realizar conexiones de red remotas. El script se llama proxy.php y admite dos parmetros GET
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

llamados url (que es la URL que se quiere descargar) y ct (Content-Type del contenido que se
est descargando, que es muy importante cuando se quieren recibir contenidos de tipo XML).

6) Despus de descargar el contenido del canal RSS, se debe procesar su contenido para obtener
cada uno de sus elementos y almacenarlos en un array global llamado canal.

El formato XML resumido de RSS es el siguiente:


<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Ejemplo de canal 2.0</title>
<link>http://www.ejemplo_no_real.com</link>
<description>Se trata de un ejemplo de canal RSS 2.0, sencillo pero
completo</description>
<item>
<title>El primer elemento</title>
<link>http://www.ejemplo_no_real.com/elementos/001.html</link>
<description>Esta es la descripcin del primer elemento.</description>
<pubDate>Sun, 18 Feb 2007 15:04:27 GMT</pubDate>
</item>
<item>
<title>El segundo elemento</title>
<link> http://www.ejemplo_no_real.com/elementos/002.html </link>
<description> Esta es la descripcin del primer elemento.</description>
<pubDate>Sun, 18 Feb 2007 15:04:27 GMT</pubDate>
</item>
...
<item>
<title>El elemento N</title>
<link> http://www.ejemplo_no_real.com/elementos/00n.html </link>
<description> Esta es la descripcin del elemento N.</description>
<pubDate>Sun, 18 Feb 2007 15:04:27 GMT</pubDate>
</item>
</channel>
</rss>

El formato del array elementos puede ser cualquiera que permita almacenar para cada elemento su
titular, descripcin, enlace y fecha de publicacin.

7) Una vez descargado y procesado el canal RSS, mostrar sus elementos tal y como se indica en la
siguiente imagen:
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.4. Aspecto final del lector RSS construido con AJAX

Al pinchar en cada titular de los que se muestran en la parte izquierda, se carga su contenido
completo en la zona central.

9.3. Google Maps


9.3.1. Contexto
Google Mps fue un de ls primers plicciones bsds en AJAX de uso msivo por prte de
los usurios. Su grn e xito h provocdo que todos sus rivles hyn copido el funcionmiento
de sus mps.

Adem s, Google ofrece de form grtuit un API con l que poder desrrollr plicciones
medid bsds en los mps de Google, integrr los mps en otrs plicciones e incluso hcer
"mash-up" o mezcls de Google Mps y otrs plicciones web que tmbie n disponen de un API
pu blic.

9.3.2. Solucin propuesta


Antes de utilizr l API de los mps de Google, es necesrio obtener un clve personl y u nic
pr cd sitio web donde se quiere utilizr. El uso de l API es grtuito pr culquier
pliccio n que pued ser ccedid libremente por los usurios. L clve de l API se puede
obtener desde: http://www.google.com/pis/mps/

Pr usos comerciles de l API tmbie n existen servicios de pgo que requieren el uso de otrs
clves.

Ls clves se solicitn por cd rut del servidor. De est form, si se solicit un clve pr
http://www.misitio.com/rut1, culquier pliccio n o p gin que se encuentre bjo es rut del
servidor podr hcer uso de l API de los mps con es clve.
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Si no se dispone de un sitio web pu blico, es posible indicr como servidor el vlor


http://localhost pr poder hcer pruebs en un servidor locl. Pr solicitr l clve, es
necesrio disponer de un cuent de usurio de Google (se puede utilizr por ejemplo l cuent
de Gmil). L clve generd depende por tnto del dominio de l pliccio n y de l cuent de
usurio.

Ls clves de l API de Google Mps consisten en un cden de texto muy lrg con un specto
similr l siguiente:
ABQIAAAA30JtKUU8se-7KKPRGSfCMBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRZNdns2BwZvEY-V68DvlyUYwi1-Q .

Un vez obtenid l clve, culquier p gin que quier hcer uso de l API debe enlzr el
siguiente rchivo de JvScript:
<script src="http://maps.google.com/
maps?file=api&amp;v=2&amp;hl=es&amp;key=ABQIAAAA30JtKUU8se-7KKPRGSfCMBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxR
type="text/javascript"></script>

Los pr metros necesrios son file, que indic el tipo de rchivo que se quiere crgr (en este
cso l API), v, que indic l versio n de l API (en este cso 2), hl, que permite indicr el idiom
en el que se muestrn los mps (si no se indic este pr metro, los mps se muestrn en
ingle s) y el pr metro key, que contiene l clve que se cb de obtener.

Un vez obtenid l clve, es muy sencillo crer el primer mp de Google:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejemplo de uso de Google Maps</title>
<script src="http://maps.google.com/
maps?file=api&amp;v=2&amp;hl=es&amp;key=ABQIAAAA30JtKUU8se-7KKPRGSfCMBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxR
type="text/javascript"></script>
<script type="text/javascript">
function load() {
if (GBrowserIsCompatible()) {
var latitud = 48.858729;
var longitud = 2.352448;
var zoom = 15;
var mapa = new GMap2(document.getElementById("mapa"));
mapa.setCenter(new GLatLng(latitud, longitud), zoom);
}
}
</script>
</head>

<body onload="load()" onunload="GUnload()">


<div id="mapa" style="width: 500px; height: 400px"></div>
</body>
</html>

El nterior co digo HTML y JvScript gener el siguiente mp:


Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.5. Mapa sencillo creado con la API de Google Maps y las coordenadas de longitud y latitud
indicadas

En primer lugr, se define un elemento (normlmente un <div>) en el que se mostrr el mp.


El tmn o del mp ser igul l tmn o de su elemento contenedor, no ser que se indique
explcitmente otro tmn o:
<div id="mapa" style="width: 500px; height: 400px"></div>

Un vez definido el contenedor del mp, se estblecen los eventos necesrios en l p gin que
lo contiene:
<body onload="load()" onunload="GUnload()">

Los ejemplos que se pueden consultr en l documentcio n de Google utilizn es signcio n


direct de eventos en l etiquet <body>. Evidentemente, los eventos tmbie n se podrn signr
de form semntica medinte el siguiente co digo:
window.onload = load;
window.onunload = GUnload;

L funcio n load() es l que se ejecut l crgr l p gin y l que estblece ls opciones con
ls que se cre el mp. En primer lugr, se ejecut l funcio n GBrowserIsCompatible(), que
indic si el nvegdor ctul del usurio es comptible con el uso de los mps de Google. En
cso contrrio, no se ejecutn ls instrucciones y no se muestr el mp:
if (GBrowserIsCompatible()) {
...
}
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Pr crer un nuevo mp, se utiliz l clse GMap2, que represent un mp en un p gin. Ls


p gins pueden contener m s de un mp, pero cd uno de ellos hce referenci un instnci
diferente de l clse GMap2. El u nico rgumento obligtorio pr crer el mp es l referenci l
elemento que contendr el mp (obtenid medinte su id):
var mapa = new GMap2(document.getElementById("mapa"));

Un vez instncid l clse GMap2, el mp y h sido credo. Sin embrgo, el mp no se


muestr correctmente hst que se indique en que punto geogr fico est centrdo. El me todo
setCenter() permite centrr un mp y opcionlmente, indicr el nivel de zoom y el tipo de
mp que se muestr:
var latitud = 42.845007;
var longitud = -2.673;
var zoom = 15;
mapa.setCenter(new GLatLng(latitud, longitud), zoom);

El punto geogr fico en el que est centrdo el mp se indic medinte un objeto de tipo
GLatLng() que tom dos pr metros: el primero es el vlor de l ltitud del punto geogr fico y
el otro pr metro indic l longitud de es posicio n geogr fic. De form opcionl se puede
indicr el nivel de zoom del mp.

L ltitud puede tomr un vlor entre +90 (90 grdos l norte del ecudor) y -90 (90 grdos
l sur del ecudor), l longitud puede tomr un vlor entre +180 (180 grdos l este de
Greenwitch) y -180 (180 grdos l oeste de Greenwitch). El nivel de zoom puede vrir entre 1
(en el que se ve l Tierr enter) y 18 (en el que se ven los detlles de cd clle). No obstnte,
se debe tener en cuent que no todos los puntos geogr ficos disponen de todos los niveles de
zoom.

Despue s de crer un mp b sico, es muy sencillo n dir los controles pr umentr o


disminuir el nivel de zoom y el control que indic el tipo de mp que se muestr:
mapa.addControl(new GSmallMapControl());
mapa.addControl(new GMapTypeControl());

Ahor, el mp permite vrir el nivel de zoom y mostrr otro tipo de mp, como se muestr en
l siguiente imgen:
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.6. Mapa sencillo creado con la API de Google Maps y que permite variar su nivel de zoom y
el tipo de mapa que se muestra

Google Mps incluye un documentcio n muy extens sobre el uso de l API y todos los me todos
disponibles. L documentcio n inicil con ejemplos b sicos se puede consultr en:
http://www.google.com/pis/mps/documenttion/

L referenci complet de clses, propieddes y me todos de l API est disponible en:


http://www.google.com/pis/mps/documenttion/reference.html

Los mps de Google permiten controlr un grn nu mero de eventos, pudiendo socir
funciones o ejecutr directmente co digo JvScript cd vez que se produce un evento. El
siguiente ejemplo muestr un mensje de tipo alert() con ls coordends del centro del
mp cd vez que el usurio suelt el mp despue s de hberlo movido:
GEvent.addListener(mapa, "moveend", function() {
var centro = mapa.getCenter();
alert(centro.toString());
});

Adem s del evento moveend existen muchos otros, como por ejemplo move que permite
ejecutr culquier funcio n de form repetid medid que el usurio mueve el mp. Los mps
tmbie n permiten colocr mrcdores pr mostrr un posicio n. El siguiente ejemplo hce uso
del evento click sobre los mps pr mostrr mrcdores:
GEvent.addListener(mapa, "click", function(marcador, punto) {
mapa.addOverlay(new GMarker(punto));
});
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Ahor, cd vez que se puls sobre un punto del mp, se n de un nuevo mrcdor en ese
punto:

Figura 9.7. Los eventos de la API de los mapas de Google permiten aadir marcadores de posicin
cada vez que se pincha en un punto del mapa

Modificndo ligermente el ejemplo nterior, es posible borrr un mrcdor si se puls sobre el:
GEvent.addListener(mapa, "click", function(marcador, punto) {
if(marcador) {
mapa.removeOverlay(marcador);
} else {
mapa.addOverlay(new GMarker(punto));
}
});

Modificndo de nuevo el co digo nterior, es posible n dir eventos los mrcdores pr que
cd vez que se pinche en uno de ellos se muestre un mensje con sus coordends geogr fics:
GEvent.addListener(mapa, "click", function(marcador, punto) {
var nuevoMarcador = new GMarker(punto);
GEvent.addListener(nuevoMarcador, "click", function() {
this.openInfoWindowHtml("Lat: " + this.getPoint().lat() + "<br/>Lon: " +
this.getPoint().lng());
});
mapa.addOverlay(nuevoMarcador);
});
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.8. Al pulsar sobre cada marcador de posicin en el mapa, se muestra un mensaje
informando sobre la longitud y latitud de la posicin del marcador

A continucio n se muestr l expliccio n detlld del co digo nterior. En primer lugr se


estblece un nuevo evento cd vez que se pinch sobre el mp:
GEvent.addListener(mapa, "click", function(marcador, punto) {

Cd vez que se pinch, se cre un nuevo mrcdor con ls coordends de l posicio n en l que
se h pinchdo:
var nuevoMarcador = new GMarker(punto);

Antes de mostrr el mrcdor en el mp, se n de un evento l propio mrcdor, que se


ejecutr cd vez que se pinche sobre el:
GEvent.addListener(nuevoMarcador, "click", function() {

El me todo openInfoWindowHtml() permite mostrr un pequen ventn con un mensje que


puede contener co digo HTML. Dentro de l funcio n mnejdor del evento, l vrible this se
resuelve en el propio mrcdor, por lo que se puede hcer uso de ell pr obtener sus
coordends y pr mostrr el mensje:
this.openInfoWindowHtml("Lat: " + this.getPoint().lat() + "<br/>Lon: " +
this.getPoint().lng());

Por u ltimo, se n de el mrcdor l mp:


mapa.addOverlay(nuevoMarcador);

Ejercicio 22
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Partiendo del mapa bsico que se acaba de crear, se pide:

1) En la misma pgina se debe incluir otro mapa que muestre las antpodas del punto geogrfico
inicial del primer mapa. Este segundo mapa no debe mostrar ningn control de zoom ni de tipo de
mapa.

Figura 9.9. Aspecto del mapa principal y del mapa secundario que muestra el lugar geogrfico
definido como "antpodas" del lugar mostrado en el mapa principal

2) Al mover el primer mapa, el segundo mapa debe mostrar en todo momento las antpodas de ese
lugar. Adems, el zoom y el tipo de mapa tambin debe estar sincronizado, de forma que el segundo
mapa muestre en todo momento el mismo nivel de zoom y el mismo tipo de mapa que el primero.

3) Cuando se pinche en el primer mapa, se muestra un marcador con su longitud y su latitud.


Adems, automticamente se crea un marcador en el segundo mapa indicando el lugar exacto que
corresponde a su antpoda.

Figura 9.10. Cuando se crea un marcador en el mapa principal, automticamente debe crearse otro
marcador de posicin en el lugar geogrfico correspondiente a su antpoda

Ejercicio 23

La disponibilidad de una API pblica, sencilla, gratuita y muy potente permite integrar los mapas de
Google con cualquier otra aplicacin abierta que genere informacin geoespacial.

Un ejemplo tpico de esta mezcla de aplicaciones es la informacin metereolgica. Con la ayuda de


los mapas de Google, es posible mostrar en cada punto del mapa la previsin metereolgica en
forma de marcador de posicin con un icono personalizado, tal y como se muestra en la siguiente
imagen:
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

Figura 9.11. Mapa de previsin metereolgica construido con los mapas de Google y que utiliza
iconos personalizados para mostrar cada marcador de posicin

1) Mostrar un mapa de Google de tamao 600x600 pxel, centrado en [40.41558722527384,


-3.6968994140625], que muestre por defecto el mapa de tipo satlite y que no incluya ningn tipo
de control.

2) Cada cierto tiempo se debe mostrar la previsin meteorolgica descargada desde el servidor. El
script del servidor se denomina previsionMeteorologica.php y no es necesario pasar ningn
parmetro. El servidor devuelve un array en formato JSON con la lista de puntos geogrficos junto
con su previsin meteorolgica:
[
{ latlon: [42.779275360242, -2.63671875], prediccion: "tormentas" },
{ latlon: [43.245202722034, -8.32763671875], prediccion: "nieve" },
{ latlon: [42.228517356209, -7.36083984375], prediccion: "lluvia" },
...
{ latlon: [41.54147766679, -3.75732421875], prediccion: "nublado" },
]

3) La informacin meteorolgica de cada punto se muestra mediante un marcador personalizado.


Pistas: la clase GMarkerManager permite gestionar conjuntos grandes de marcadores. La clase
GMarker permite definir un icono personalizado para el marcador. La clase GIcon permite crear
nuevos iconos listos para los marcadores. En la carpeta imagenes se proporcionan iconos para cada
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX

una de las condiciones meteorolgicas: lluvia.png, nieve.png, nublado.png, etc. Las imgenes
utilizadas en este ejemplo, pertenecen al excelente conjunto de iconos del proyecto Tango
(http://tango.freedesktop.org/Tango_Desktop_Project) .
Introduccin a AJAX Captulo 10. Frameworks y libreras

Captulo 10. Frameworks y libreras


Ls plicciones web son cd vez m s complejs, y que incluyen efectos e intercciones que
hst hce poco tiempo ern exclusivs de ls plicciones de escritorio. Al mismo tiempo, l
progrmcio n de ests plicciones vnzds se complic por vrios motivos.

En primer lugr, ls plicciones comerciles deben funcionr correctmente e igul de bien en


l menos cinco nvegdores diferentes: Internet Explorer 6 y 7, Firefox, Oper y Sfri. En
segundo lugr, el tiempo disponible pr el desrrollo de cd nuev crcterstic se reduce
cd vez m s por l necesidd continu de incluir noveddes en ls plicciones ntes de que ls
incluy l competenci.

Por todo lo nterior, hn surgido librers y frameworks especficos pr el desrrollo de


plicciones con JvScript. Utilizndo ests librers, se reduce el tiempo de desrrollo y se
tiene l seguridd de que ls plicciones funcionn igul de bien en culquier de los
nvegdores m s populres.

Aunque se hn publicdo decens de librers y frmeworks, continucio n se vn mostrr ls


dos m s populres: Prototype (junto con script.culo.us) y jQuery.

10.1. El framework Prototype


Prototype (http://www.prototypejs.org/) es un frmework que fcilit el desrrollo de
plicciones web con JvScript y AJAX. Su utor originl es Sam Stephenson, unque ls
u ltims versiones incorporn co digo e ides de muchos otros progrmdores. A pesr de que
incluye decens de utiliddes, l librer es compct y est progrmd de form muy eficiente.

Prototype se h convertido en poco tiempo en un referenci b sic de AJAX y es l bse de


muchos otros frmeworks y librers relcionds como script.culo.us (http://script.culo.us/)
. Ls primers versiones de Prototype no inclun ningu n tipo de documentcio n, lo que
dificultb su uso y provocb que l myor de usurios desconociern su verddero
potencil.

Afortundmente, ls versiones m s recientes del frmework disponen de un complet


documentcio n de tods ls funciones y me todos que componen su API. L documentcio n
incluye l definicio n complet de cd me todo, sus tributos y vrios ejemplos de uso:
http://www.prototypejs.org/pi

10.1.1. Funciones y mtodos bsicos


L primer funcio n que se estudi cundo se est prendiendo Prototype es tn u til como
impronuncible: $(). L "funcin dlar" es un tjo mejordo de l funcio n
document.getElementById().

Si se le ps un cden de texto con el identificdor de un elemento, obtiene ese elemento. L


funcio n dmite uno o m s pr metros: si se le ps un pr metro, devuelve un objeto; si se le
psn vrios pr metros, devuelve un rry simple con todos los objetos.
Introduccin a AJAX Captulo 10. Frameworks y libreras

// Con JavaScript
var elemento = document.getElementById('primero');

// Con Prototype
var elemento = $('primero');

// Con JavaScript
var elemento1 = document.getElementById('primero');
var elemento2 = document.getElementById('segundo');

// Con Prototype
var elementos = $('primero', 'segundo');

Otr de ls funciones m s u tiles de Prototype es $F(), que es similr l nterior funcio n, pero
se utiliz pr obtener directmente el vlor de los cmpos de formulrio:
<input id="municipio" />

// Con JavaScript
document.getElementById("municipio").value

// Con Prototype
$F("municipio")

<select id="municipio">
<option>...</option>
</select>

// Con JavaScript
document.getElementById("municipio").options[document.getElementById("municipio").selectedIndex].va

// Con Prototype
$F("municipio")

Un de ls funciones m s espectculres de Prototype y que no tiene equivlente en JvScript


es $$(), que permite seleccionr elementos de l p gin utilizndo selectores de CSS.
<div id="principal">
<p>Primer prrafo</p>
<p>Segundo prrafo</p>
</div>
<p>Tercer prrafo</p>

var todosParrafos = $$('p');


var parrafosInteriores = $$('#principal p');

Prototype incluye un funcio n muy u til llmd $A(), pr convertir en rry "cualquier cosa que
se parezca a un array". Alguns funciones de JvScript, como por ejemplo
getElementsByTagName() devuelven objetos de tipo NodeList o HTMLCollection, que no son
rrys, unque pueden recorrerse como tles.
<select id="lista">
<option value="1">Primer valor</option>
<option value="2">Segundo valor</option>
Introduccin a AJAX Captulo 10. Frameworks y libreras

<option value="3">Tercer valor</option>


</select>

// 'lista_nodos' es una variable de tipo NodeList


var lista_nodos = $('lista').getElementsByTagName('option');

// 'nodos' es una variable de tipo array


var nodos = $A(lista_nodos);
// nodos = [objeto_html_opcion1, objeto_html_opcion2, objeto_html_opcion3]

Un funcio n similr $A() es $H(), que cre arrays asociativos (tmbie n llmdos "hash")
prtir del rgumento que se le ps:
var usuarios = { usuario1: "password1",
usuario2: "password2",
usuario3: "password3" };

var hash_usuarios = $H(usuarios);

var logins = hash_usuarios.keys();


// logins = ["usuario1", "usuario2", "usuario3"]

var passwords = hash_usuarios.values();


// passwords = ["password1", "password2", "password3"]

var queryString = hash_usuarios.toQueryString();


// queryString = "usuario1=password1&usuario2=password2&usuario3=password3"

var debug = hash_usuarios.inspect();


// #<Hash:{'usuario1':'password1', 'usuario2':'password2,'usuario3':'password3'}>

Por u ltimo, Prototype incluye l funcio n $R() pr crer rngos de vlores. El rngo de vlores
se cre desde el vlor del primer rgumento hst el vlor del segundo rgumento. El tercer
rgumento de l funcio n indic si se excluye o no el u ltimo vlor (por defecto, el tercer
rgumento vle false, que indic que s se incluye el u ltimo vlor).
var rango = $R(0, 100, false);
// rango = [0, 1, 2, 3, ..., 100]

var rango = $R(0, 100);


// rango = [0, 1, 2, 3, ..., 100]

var rango = $R(0, 100, true);


// rango = [0, 1, 2, 3, ..., 99]

var rango2 = $R(100, 0);


// rango2 = [100]

var rango = $R(0, 100);


var incluido = rango.include(4);
// incluido = true

var rango = $R(0, 100);


var incluido = rango.include(400);
// incluido = false
Introduccin a AJAX Captulo 10. Frameworks y libreras

Los rngos que se pueden crer vn mucho m s ll de simples sucesiones nume rics. L
"inteligencia" de l funcio n $R() permite crer rngos tn vnzdos como los
siguientes:
var rango = $R('a', 'k');
// rango = ['a', 'b', 'c', ..., 'k']

var rango = $R('aa', 'ak');


// rango = ['aa', 'ab', 'ac', ..., 'ak']

var rango = $R('a_a', 'a_k');


// rango = ['a_a', 'a_b', 'a_c', ..., 'a_k']

Por u ltimo, un funcio n muy u til que se puede utilizr con cdens de texto, objetos y rrys de
culquier tipo es inspect(). Est funcio n devuelve un cden de texto que es un
representcio n de los contenidos del objeto. Se trt de un utilidd imprescindible cundo se
est n depurndo ls plicciones, y que permite visulizr el contenido de vribles complejs.

10.1.2. Funciones para cadenas de texto


El frmework Prototype extiende ls cdens de texto de JvScript n die ndoles un serie de
funciones que pueden resultr muy u tiles:

stripTags(): Elimin tods ls etiquets HTML y XML de l cden de texto

stripScripts(): Elimin todos los bloques de tipo <script></script> de l cden de


texto

escapeHTML(): trnsform todos los crcteres problemticos en HTML su respectiv entidd


HTML (< se trnsform en &lt;, & se trnsform en &amp;,
etc.)
var cadena = "<p>Prueba de texto & caracteres HTML</p>".escapeHTML();
// cadena = "&lt;p&gt;Prueba de texto &amp; caracteres HTML&lt;/p&gt;"

unescapeHTML(): funcio n invers de escapeHTML()

var cadena = "<p>Prueba de texto & caracteres HTML</p>".unescapeHTML();


// cadena = "Prueba de texto & caracteres HTML"

var cadena = "<p>&ntilde; &aacute; &iquest; &amp;</p>".unescapeHTML();


// cadena = " &"

extractScripts(): devuelve un rry con todos los bloques <script></script> de l cden


de texto

evalScripts(): ejecut cd uno de los bloques <script></script> de l cden de


texto

toQueryParams(): convierte un cden de texto de tipo query string en un rry socitivo


(hash) de pres pr metro/vlor
var cadena = "parametro1=valor1&parametro2=valor2&parametro3=valor3";

var parametros = cadena.toQueryParams();


Introduccin a AJAX
// $H(parametros).inspect() = #<Hash:{'parametro1':'valor1',Captulo 10. Frameworks y libreras
'parametro2':'valor2','
parametro3':'valor3'}>

toArray(): convierte l cden de texto en un rry que contiene sus letrs


Introduccin a AJAX Captulo 10. Frameworks y libreras

camelize(): convierte un cden de texto seprd por guiones en un cden con notcio n de
tipo CamelCase
var cadena = "el-nombre-de-la-variable".camelize();
// cadena = "elNombreDeLaVariable"

underscore(): funcio n invers de camelize(), y que convierte un cden de texto escrit con
notcio n CamelCase en un cden de texto con ls plbrs seprds por guiones bjos
var cadena = "elNombreDeLaVariable".underscore();
// cadena = "el_nombre_de_la_variable"

dasherize(): modific los guiones bjos (_) de un cden de texto por guiones medios ( -)

var cadena = "el_nombre_de_la_variable".dasherize();


// cadena = "el-nombre-de-la-variable"

Combinndo camelize(), underscore() y dasherize(), se puede obtener el nombre DOM de


cd propiedd CSS y vicevers:
var cadena = 'borderTopStyle'.underscore().dasherize();
// cadena = 'border-top-style'

var cadena = 'border-top-style'.camelize();


// cadena = 'borderTopStyle'

10.1.3. Funciones para elementos


Prototype define funciones muy u tiles pr mnipulr los elementos incluidos en ls p gins
HTML. Culquier elemento obtenido medinte l funcio n $() puede hcer uso de ls
siguientes funciones:

Element.visible(): devuelve true/false si el elemento es visible/oculto (devuelve true


pr los cmpos tipo hidden)

Element.show() y Element.hide(): muestr y ocult el elemento indicdo

Element.toggle(): si el elemento es visible, lo ocult. Si es elemento est oculto, lo muestr

Element.scrollTo(): bj o sube el scroll de l p gin hst l posicio n del elemento indicdo

Element.getStyle() y Element.setStyle(): obtiene/estblece el vlor del estilo CSS del


elemento (el estilo completo, no l propiedd className)

Element.classNames(), Element.hasClassName(), Element.addClassName(),


Element.removeClassName(): obtiene los class del elemento, devuelve true/false si incluye
un determindo class, n de un class l elemento y elimin el class l elemento
respectivmente

Tods ls funciones nteriores se pueden invocr de dos forms diferentes:


// Las dos instrucciones son equivalentes
Element.toggle('principal');
$('principal').toggle()
Introduccin a AJAX Captulo 10. Frameworks y libreras

10.1.4. Funciones para formularios


Prototype incluye muchs utiliddes relcionds con los formulrios y sus elementos. A
continucio n se muestrn ls m s u tiles pr los cmpos de un formulrio:

Field.clear(): borr el vlor de cd cmpo que se le ps (dmite uno o m s pr metros)

Field.present(): devuelve true si los cmpos que se le indicn hn sido rellendos por
prte del usurio, es decir, si contienen vlores no vcos (dmite uno o m s pr metros)

Field.focus(): estblece el foco del formulrio en el cmpo que se le indic

Field.select(): seleccion el vlor del cmpo (solo pr los cmpos en los que se pued
seleccionr su texto)

Field.activate(): combin en un u nic funcio n los me todos focus() y


select()

A ls funciones nteriores se les debe psr como pr metro un cden de texto con el
identificdor del elemento o el propio elemento (obtenido por ejemplo con $()). Ls funciones
mostrds se pueden invocr de tres forms diferentes:
// Las 3 instrucciones son equivalentes
Form.Element.focus('id_elemento');
Field.focus('id_elemento')
$('id_elemento').focus()

Adem s de ls funciones especfics pr los cmpos de los formulrios, Prototype tmbie n


define utiliddes pr los propios formulrios completos. Tods ls funciones requieren un solo
pr metro: el identificdor o el objeto del formulrio.

Form.serialize(): devuelve un cden de texto de tipo "query string" con el vlor de todos los
cmpos del formulrio ("campo1=valor1&campo2=valor2&campo3=valor3" )

Form.findFirstElement(): devuelve el primer cmpo ctivo del formulrio

Form.getElements(): devuelve un rry con todos los cmpos del formulrio (incluyendo los
elementos ocultos)

Form.getInputs(): devuelve un rry con todos los elementos de tipo <input> del formulrio.
Admite otros dos pr metros pr filtrr los resultdos. El segundo pr metro indic el tipo de
<input> que se quiere obtener y el tercer pr metro indic el nombre del elemento
<input>.

Form.disable(): deshbilit todo el formulrio deshbilitndo todos sus cmpos

Form.enable(): hbilit el formulrio completo hbilitndo todos sus cmpos

Form.focusFirstElement(): pone el foco del formulrio en el primer cmpo que se visible y


este hbilitdo

Form.reset(): resete el formulrio completo, y que es equivlente l me todo reset() de


JvScript
Introduccin a AJAX Captulo 10. Frameworks y libreras

10.1.5. Funciones para arrays


Ls utiliddes n dids los rrys de JvScript es otro de los puntos fuertes de Prototype:

clear(): vc de contenidos el rry y lo devuelve

compact(): devuelve el rry sin elementos null o

undefined first(): devuelve el primer elemento del rry

flatten(): convierte culquier rry que se le pse en un rry unidimensionl. Se reliz un


proceso recursivo que v "aplanando" el rry:
var array_original = ["1", "2", 3,
["a", "b", "c",
["A", "B", "C"]
]
];

var array_plano = array_original.flatten();


// array_plano = ["1", "2", 3, "a", "b", "c", "A", "B", "C"]

indexOf(value): devuelve el vlor de l posicio n del elemento en el rry o -1 si no lo


encuentr
var array = ["1", "2", 3, ["a", "b", "c", ["A", "B", "C"] ] ];
array.indexOf(3); // 2
array.indexOf("C"); // -1

last(): devuelve el u ltimo elemento del rry

reverse(): devuelve el rry originl en sentido inverso:

var array = ["1", "2", 3, ["a", "b", "c", ["A", "B", "C"] ] ];
array.reverse();
// array = [["a", "b", "c", ["A", "B", "C"]], 3, "2", "1"]

shift(): devuelve el primer elemento del rry y lo extre del rry (el rry se modific y su
longitud disminuye en 1 elemento)

without(): devuelve el rry del que se hn elimindo todos los elementos que coinciden con los
rgumentos que se psn l funcio n. Permite filtrr los contenidos de un rry
var array = [12, 15, 16, 3, 40].without(16, 12)
// array = [15, 3, 40]

10.1.6. Funciones para objetos enumerables


Algunos tipos de objetos en JvScript se comportn como colecciones de vlores, tmbie n
llmds "enumeraciones" de vlores. Prototype define vris utiliddes pr este tipo de
objetos trve s de Enumerable, que es uno de los pilres b sicos del frmework y un de ls
forms m s sencills de mejorr l productividd cundo se desrrolln plicciones JvScript.

Algunos de los objetos obtenidos medinte ls funciones de Prototype, y incorporn todos los
me todos de Enumerable. Sin embrgo, si se quieren n dir estos me todos un objeto propio, se
Introduccin a AJAX Captulo 10. Frameworks y libreras
pueden utilizr ls utiliddes de Prototype pr crer objetos y extenderlos:
Introduccin a AJAX Captulo 10. Frameworks y libreras

var miObjeto = Class.create();


Object.extend(miObjeto.prototype, Enumerable);

Grcis Enumerable, se pueden recorrer los rrys de form mucho m s eficiente:


// Array original
var vocales = ["a", "e", "i", "o", "u"];

// Recorrer el array con JavaScript


for(var i=0; i<vocales.length; i++) {
alert("Vocal " + vocales[i] + " est en la posicin " + i);
}

// Recorrer el array con Prototype:


vocales.each(function(elemento, indice) {
alert("Vocal " + elemento + " est en la posicin " + indice);
});

El me todo select(), que es un lis del me todo findAll(), permite filtrr los contenidos de un
rry:
var numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
resultado = numeros.findAll(function(elemento) { return elemento > 5; });
// resultado = [6, 7, 8, 9, 10]

Otro me todo u til es pluck(), que permite obtener el vlor de un mism propiedd pr todos
los elementos de l coleccio n:
var numLetras = ['hola', 'mundo', 'que', 'bien', 'funciona',
'Prototype'].pluck('length');
// numLetras = [4, 5, 3, 4, 8, 9]

Enumerable incluye decens de utiliddes y me todos, lgunos tn curiosos como partition()


que permite dividir un coleccio n en dos grupos: el de los elementos de tipo true y el de los
elementos de tipo false (vlores como null, undefined, etc.)
var valores = ['nombreElemento', 12, null, 2, true, , false].partition();
// valores = [['nombreElemento', 12, 2, true], [null, undefined, false]]

El me todo partition() permite signr un funcio n propi pr decidir si un elemento se


consider true o false. En el siguiente ejemplo, se divide un rry con letrs en dos grupos, el
de ls vocles y el de ls consonntes:
var letras = $R('a', 'k').partition(function(n) {
return ['a', 'e', 'i', 'o', 'u'].include(n);
})
// letras = [['a', 'e', 'i'], ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k']]

El me todo invoke() permite ejecutr un funcio n pr todos los elementos de l


coleccio n:
var palabras = ['hola', 'mundo', 'con', 'Prototype'].invoke('toUpperCase');
// palabras = ['HOLA', 'MUNDO', 'CON', 'PROTOTYPE']

L documentcio n de Enumerble (http://www.prototypejs.org/pi/enumerble) incluye l


definicio n y ejemplos de muchos otros me todos u tiles como inGroupsOf() (grup elementos
en subconjuntos del mismo tmn o), sortBy() (permite definir l ordencio n de los
Introduccin a AJAX Captulo 10. Frameworks y libreras
elementos
Introduccin a AJAX Captulo 10. Frameworks y libreras

medinte un funcio n propi), zip() (soci uno uno los elementos de dos colecciones),
collect() (permite trnsformr los elementos de l coleccio n con un funcio n propi),
etc.

10.1.7. Otras funciones tiles


Try.these(): permite probr vris funciones de form consecutiv hst que un de ells
funcione. Es muy u til pr ls plicciones que deben funcionr correctmente en vrios
nvegdores diferentes.

El propio co digo fuente de Prototype utiliz Try.these() pr obtener el objeto encrgdo de


relizr ls peticiones AJAX:
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},

activeRequestCount: 0
}

Class.create(): permite crer clses de un form elegnte y sencill:

MiClase = Class.create();
MiClase.prototype = {
initialize: function(a, b) {
this.a = a;
this.b = b;
}
}

var miClase = new MiClase("primer_valor", "segundo_valor");

Object.extend(): se emple pr n dir o sobrescribir ls propieddes de un objeto en otro


objeto. Se puede considerr como un form primitiv y muy b sic de herenci entre clses. En
l llmd l funcio n, el primer objeto es el destino en el que se copin ls propieddes del
segundo objeto psdo como pr metro:
Object.extend(objetoDestino, objetoOrigen);

Est funcio n es muy u til pr que ls plicciones definn un serie de opciones por defecto y
puedn tener en cuent ls opciones estblecids por cd usurio:
// El array "opciones" guarda las opciones por defecto de la aplicacin
var opciones = {campo: "usuario", orden: "ASC"};

// El usuario establece sus propias opciones


var opciones_usuario = {orden: "DESC", tipoBusqueda: "libre"};

// Se mezclan los dos arrays de opciones, dando prioridad


// a las opciones establecidas por los usuarios
Introduccin a AJAX Captulo 10. Frameworks y libreras

Object.extend(opciones, opciones_usuario);

// Ahora, opciones.orden = "DESC"

El co digo fuente de Prototype utiliz Object.extend() continumente pr n dir


propieddes y me todos u tiles los objetos de JvScript. El co digo que se muestr continucio n
n de cinco me todos l objeto Number originl de JvScript:
Object.extend(Number.prototype, {
toColorPart: function() {
return this.toPaddedString(2, 16);
},

succ: function() {
return this + 1;
},

times: function(iterator) {
$R(0, this, true).each(iterator);
return this;
},

toPaddedString: function(length, radix) {


var string = this.toString(radix || 10);
return '0'.times(length - string.length) + string;
},

toJSON: function() {
return isFinite(this) ? this.toString() : 'null';
}
});

10.1.8. Funciones para AJAX


Adem s de tods ls funciones y utiliddes pr l progrmcio n tradicional de JvScript,
Prototype incluye numeross funciones relcionds con el desrrollo de plicciones AJAX. Los
me todos que componen este mo dulo son Ajax.Request(), Ajax.Updater(),
Ajax.PeriodicalUpdater() y Ajax.Responders().

Ajax.Request() es el me todo principl de este mo dulo. Se utiliz pr relizr peticiones AJAX


y procesr sus resultdos. Su sintxis es:
new Ajax.Request(url, opciones);

El primer pr metro (url) es l URL que solicit l peticio n AJAX y el segundo pr metro
(opciones) es opcionl y se emple pr especificr vlores diferentes ls opciones por
defecto. Ls opciones se indicn en form de rry socitivo:
new Ajax.Request('/ruta/hasta/pagina.php', {
method: 'post',
asynchronous: true,
postBody: 'parametro1=valor1&parametro2=valor2',
onSuccess: procesaRespuesta,
Introduccin a AJAX Captulo 10. Frameworks y libreras

onFailure: muestraError
});

Como es hbitul, pr estblecer l funcio n que proces l respuest del servidor, se indic el
nombre de l funcio n sin pre ntesis. Ls funciones externs signds pr procesr l
respuest, reciben como primer pr metro el objeto que represent l respuest del servidor.
Hciendo uso de este objeto, ls funciones pueden cceder tods ls propieddes hbitules:
function procesaRespuesta(respuesta) {
alert(respuesta.responseText);
}

A continucio n se incluye un tbl con tods ls opciones que se pueden definir pr el me todo
Ajax.Request():

Opcin Descripcin
method El mtodo de la peticin HTTP. Por defecto es POST
Lista de valores que se envan junto con la peticin. Deben estar formateados como una
parameters
query string: parametro1=valor1&parametro2=valor2

encoding Indica la codificacin de los datos enviados en la peticin. Su valor por defecto es UTF-8
Controla el tipo de peticin que se realiza. Por defecto es true, lo que indica que la
Introduccin a AJAX Captulo 10. Frameworks y libreras
asynchronous peticin realizada al servidor es asncrona, el tipo de peticin habitual en las aplicaciones
AJAX
postBody Contenido que se enva en el cuerpo de la peticin de tipo POST

Indica el valor de la cabecera Content-Type utilizada para realizar la peticin. Su valor


contentType por defecto es application/x-www-form-urlencoded

requestHeaders Array con todas las cabeceras propias que se quieren enviar junto con la peticin
onComplete
onLoaded Permiten asignar funciones para el manejo de las distintas fases de la peticin. Se
on404 pueden indicar funciones para todos los cdigos de estado vlidos de HTTP
on500

Permite indicar la funcin que se encarga de procesar las respuestas correctas de


onSuccess servidor

onFailure Se emplea para indicar la funcin que se ejecuta cuando la respuesta ha sido incorrecta
Permite indicar la funcin encargada de manejar las peticiones errneas en las que la
onException respuesta del servidor no es vlida, los argumentos que se incluyen en la peticin no son
vlidos, etc.

L funcio n Ajax.Updater() es un versin especial de Ajax.Request() que se emple pr


ctulizr el contenido HTML de un elemento de l p gin con l respuest del servidor.
<div id="info"></div>

new Ajax.Updater('info', '/ruta/hasta/pagina.php');

Si l respuest del servidor es


<ul>
<li>Lorem ipsum dolor sit amet</li>
<li>Consectetuer adipiscing elit</li>
<li>Curabitur risus magna, lobortis</li>
</ul>

Despue s de relizr l peticio n de tipo Ajax.Updater(), el contenido HTML de l respuest del


servidor se muestr dentro del <div>:
<div id="info">
<ul>
<li>Lorem ipsum dolor sit amet</li>
<li>Consectetuer adipiscing elit</li>
<li>Curabitur risus magna, lobortis</li>
</ul>
</div>

L sintxis de Ajax.Updater() se muestr


continucio n:
new Ajax.Updater(elemento, url, opciones);

Adem s de tods ls opciones de Ajax.Request(), l funcio n Ajax.Updater() permite


estblecer ls siguientes opciones:

Opcin Descripcin
Indica cmo se inserta el contenido HTML en el elemento indicado. Puede ser
insertion
Insertion.Before, Insertion.Top, Insertion.Bottom o Insertion.After

Si la respuesta del servidor incluye scripts en su contenido, esta opcin permite indicar si se
evalScripts ejecutan o no. Su valor por defecto es false, por lo que no se ejecuta ningn script

L funcio n Ajax.PeriodicalUpdater() es un versio n especilizd de Ajax.Updater(), que


se emple cundo se quiere ejecutr de form repetitiv un llmd Ajax.Updater(). Est
funcio n puede ser u til pr ofercer informcio n en tiempo real como noticis:
<div id="titulares"></div>

new Ajax.PeriodicalUpdater('titulares', '/ruta/hasta/pagina.php', { frequency:30 });

El co digo nterior ctuliz, cd 30 segundos, el contenido del <div> con l respuest


recibid desde el servidor.

Adem s de tods ls opciones nteriores, Ajax.PeriodicalUpdater() dispone de ls


siguientes opciones propis:

Opcin Descripcin
frequency Nmero de segundos que se espera entre las peticiones. El valor por defecto es de 2 segundos
Indica el factor que se aplica a la frecuencia de actualizacin cuando la ltima respuesta del
s es
d e 10
e r seg
v un
i do
d sy
o el
r de
ca
e y
s val
e
3,
i
cu
g
an
u
do
a
un
l
a
q
res
u
pu
e
est
a
l
del
a
ser
vid
a or
n sea
t igu
e al a
r la
i ant
o eri
r or,
. la
E sig
j uie
e nte
m pe
p tici
l n
o se
: har
s 3
i *
l 10
a = 30
segund
f os
r despu
e s de la
c ltima
u petici
e n
n
c
i
a
Por u ltimo, Ajax.Responders permite signr de form globl ls funciones que se encrgn
de responder los eventos AJAX. Un de ls principles utiliddes de Ajax.Responders es l
de indicr l usurio en todo momento si se est relizndo lgun peticio n AJAX.

Los dos me todos principles de Ajax.Responders son register() y unregister() los que
se ps como rgumento un objeto de tipo rry socitivo que incluye ls funciones que
responden cd evento:
Ajax.Responders.register({
onCreate: function() {
if($('info') && Ajax.activeRequestCount> 0) {
$('info').innerHTML = Ajax.activeRequestCount + "peticiones pendientes";
}
},
onComplete: function() {
if($('info') && Ajax.activeRequestCount> 0) {
$('info').innerHTML = Ajax.activeRequestCount + "peticiones pendientes";
}
}
});

10.1.9. Funciones para eventos


El mo dulo de eventos de Prototype es uno de los menos desrrolldos, por lo que v ser
completmente redisen do en ls pro xims versiones del frmework. Au n s, Prototype ofrece
un solucio n sencill y comptible con todos los nvegdores pr mnejr los eventos de l
pliccio n. Event.observe() registr los eventos, Event lmcen el objeto con l
informcio n del evento producido y Event.stopObserving() permite eliminr los eventos
registrdos.
<div id="pinchable">Si se pulsa en este DIV, se muestra un mensaje</div>

// Registrar el evento
Event.observe('pinchable', 'click', procesaEvento, false);

// Eliminar el evento registrado


// Event.stopObserving('pinchable', 'click', procesaEvento, false);

function procesaEvento(e) {
// Obtener el elemento que ha originado el evento (el DIV)
var elemento = Event.element(e);

// Determinar la posicion del puntero del ratn


var coordenadas = [Event.pointerX(e), Event.pointerY(e)];

// Mostrar mensaje con los datos obtenidos


alert("Has pinchado el DIV '"+elemento.id+"' con el raton en la posicion
("+coordenadas[0]+","+coordenadas[1]+")");

// Evitar la propagacion del evento


Event.stop(e);
}

L sintxis complet del me todo Event.observe() se muestr continucio n:


Event.observe(elemento, nombreEvento, funcionManejadora, [usarCapture]);

El primer rgumento (elemento) indic el identificdor del elemento o el propio elemento que
puede originr el evento. El segundo rgumento (nombreEvento) indic el nombre del evento
que se quiere mnejr, sin incluir el prefijo on (load, click, mouseover, etc.). El tercer rgumento
(funcionManejadora) es el nombre de l funcio n que proces el evento cundo se produce. El
u ltimo pr metro (usarCapture) no se suele empler, pero indic si se debe utilizr l fse de
capture o l fse de bubbling.

El objeto Event incluye l informcio n disponible sobre el evento producido. A continucio n se


muestr un tbl con sus me todos y propieddes principles:

Mtodo/Propiedad Descripcin
element() Devuelve el elemento que ha originado el evento (un div, un botn, etc.)
isLeftClick() Indica si se ha pulsado el botn izquierdo del ratn
pointerX()
Posicin x e y del puntero del
pointerY()
ratn

stop() Detiene la propagacin del evento


observers() Devuelve un array con todos los eventos registrados en la pgina

Adem s, Event define un serie de constntes pr referirse ls tecls m s hbitules que


se mnejn en ls plicciones (tbuldor, ENTER, flechs de direccio n, etc.) Ls constntes
definids son KEY_BACKSPACE, KEY_TAB, KEY_RETURN, KEY_ESC, KEY_LEFT, KEY_UP, KEY_RIGHT,
KEY_DOWN, KEY_DELETE.

Prototype tmbie n incluye otros me todos u tiles pr l gestio n de eventos con formulrios:
Form.Observer(formulario, frecuencia, funcionManejadora);

Form.Observer() permite monitorizar el formulrio indicdo cd cierto tiempo (el tiempo se


indic en segundos medinte el pr metro frecuencia). Si se produce culquier cmbio en el
formulrio, se ejecut l funcio n cuyo nombre se indic en el pr metro funcionManejadora.
Form.Observer() se emple pr los formulrios que contienen elementos sin eventos
registrdos que procesen sus cmbios.

Otr funcio n similr es Form.EventObserver() cuy definicio n forml


es:
Form.EventObserver(formulario, funcionManejadora);

L principl diferenci de Form.EventObserver() respecto Form.Observer() es que, en


este cso, se utilizn los eventos registrdos por los elementos del formulrio pr detectr si se
h producido lgu n cmbio en el formulrio.

10.1.10. Mtodos para funciones


Cundo se psn referencis funciones en el co digo de JvScript, es posible que se pierd el
contexto originl de l funcio n. El contexto de ls funciones es fundmentl pr el correcto
funcionmiento de l plbr reservd this.
Prototype incluye l posibilidd de segurr que un funcio n se v ejecutr en un determindo
contexto. Pr ello, extiende l clse Function() pr n dir el me todo bind(). Considerndo el
siguiente ejemplo:
nombre = 'Estoy fuera';
var objeto = {
nombre: 'Estoy dentro',
funcion: function() {
alert(this.nombre);
}
};

function ejecutaFuncion(f) {
f();
}

var funcion2 = objeto.funcion.bind(objeto);

ejecutaFuncion(objeto.funcion);
ejecutaFuncion(funcion2);

El co digo nterior define en primer lugr l vrible globl nombre y le sign el vlor Estoy
fuera. A continucio n, se define un objeto con un tributo llmdo tmbie n nombre y con un
me todo sencillo que muestr el vlor del tributo utilizndo l plbr reservd this.

Si se ejecut l funcio n del objeto trve s de un referenci suy (medinte l funcio n


ejecutaFuncion()), l plbr reservd this se resuelve en el objeto window y por tnto el
mensje que se muestr es Estoy fuera. Sin embrgo, si se utiliz el me todo bind(objeto)
sobre l funcio n, siempre se ejecut considerndo su contexto igul l objeto que se ps como
pr metro l me todo bind().

Prototype incluye dem s el me todo bindAsEventListener() que es equivlente bind()


pero que se puede empler pr evitr lgunos de los problems comunes de los eventos que se
producen en lgunos nvegdores como Internet Explorer.

10.1.11. Rehaciendo ejemplos con Prototype


Ls plicciones relizds con el frmework Prototype suelen ser muy conciss en comprcio n
con ls plicciones JvScript trdicionles, pero siguen mnteniendo un grn fcilidd pr
leer su co digo y entenderlo.

Por ejemplo, el ejercicio que mostrb y ocultb diferentes secciones de contenidos se relizo
de l siguiente mner:
function muestraOculta() {
// Obtener el ID del elemento
var id = this.id;
id = id.split('_');
id = id[1];

var elemento = document.getElementById('contenidos_'+id);


var enlace = document.getElementById('enlace_'+id);
if(elemento.style.display == "" || elemento.style.display == "block") {
elemento.style.display = "none";
enlace.innerHTML = 'Mostrar contenidos';
}
else {
elemento.style.display = "block";
enlace.innerHTML = 'Ocultar contenidos';
}
}

window.onload = function()
{ document.getElementById('enlace_1').onclick =
muestraOculta; document.getElementById('enlace_2').onclick =
muestraOculta;
document.getElementById('enlace_3').onclick = muestraOculta;
}

Con Prototype, su co digo se puede reducir ls siguientes instrucciones:


function muestraOculta() {
var id = (this.id).split('_')[1];

$('contenidos_'+id).toggle();
$('enlace_'+id).innerHTML = (!$('contenidos_'+id).visible()) ? 'Ocultar contenidos' :
'Mostrar contenidos';
}

window.onload = function() {
$R(1, 3).each(function(n) {
Event.observe('enlace_'+n, 'click', muestraOculta);
});
}

Los me todos $R(), toggle() y visible() permiten simplificr el co digo originl un


mnim prte de su longitud, pero conservndo el mismo funcionmiento, dem s de ser un
co digo sencillo de entender.

Otro de los ejercicios nteriores relizb peticiones AJAX l servidor pr comprobr si un


determindo nombre de usurio estb libre. El co digo originl de JvScript er:
var READY_STATE_COMPLETE = 4;
var peticion_http = null;

function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function comprobar() {
var login = document.getElementById("login").value;
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/compruebaDisponibilidad.php", true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send("login="+login+"&nocache="+Math.random());
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
var login = document.getElementById("login").value;
if(peticion_http.responseText == "si") {
document.getElementById("disponibilidad").innerHTML = "El nombre elegido
["+login+"] est disponible";
}
else {
document.getElementById("disponibilidad").innerHTML = "NO est disponible el
nombre elegido ["+login+"]";
}
}
}
}

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

Con Prototype se puede conseguir el mismo comportmiento con tres veces menos de lnes de
co digo:
function comprobar() {
var login = $F('login');
var url = 'http://localhost/compruebaDisponibilidad.php?nocache=' + Math.random();
var peticion = new Ajax.Request(url, {
method: 'post',
postBody: 'login='+login,
onSuccess: function(respuesta) {
$('disponibilidad').innerHTML = (respuesta.responseText == 'si') ?
'El nombre elegido ['+login+'] est disponible' : 'NO est disponible el nombre
elegido ['+login+']';
},
onFailure: function() { alert('Se ha producido un error'); }
});
}

window.onload = function()
{ Event.observe('comprobar', 'click',
comprobar);
}
10.2. La librera scriptaculous
Script.culo.us (http://script.culo.us/) es un de ls muchs librers que hn surgido pr
fcilitr el desrrollo de plicciones JvScript y que est n bsds en Prototype. El utor
originl de l librer es Thomas Fuchs, unque ctulmente recibe contribuciones de
numerosos progrmdores, y que l librer se distribuye de form completmente grtuit y
dispone de un buen documentcio n: http://wiki.script.culo.us/scriptculous/

L librer est dividid en vrios mo dulos:

Efectos: permite n dir de form muy sencill efectos especiles culquier elemento de
l p gin. L librer incluye un serie de efectos b sicos y otros efectos complejos
construidos con l combincio n de esos efectos b sicos. Entre los efectos predisen dos se
encuentrn el prpdeo, movimiento r pido, precer/desprecer, umentr/disminuir
de tmn o, desplegrse, etc.
Controles: define vrios controles que se pueden n dir directmente culquier
pliccio n web. Los tres controles que formn este mo dulo son: "rrstrr y soltr", que
permite definir los elementos que se pueden rrstrr y ls zons en ls que se pueden
soltr elementos; "utocompletr", que permite definir un cudro de texto en el que los
vlores que se escriben se utocompletn con yud del servidor; editor de contenidos,
que permite modificr los contenidos de culquier p gin web n diendo un sencillo
editor AJAX en cd elemento.
Utiliddes: l utilidd principl que incluye se llm builder, que se utiliz pr crer
f cilmente nodos y frgmentos complejos de DOM.

L documentcio n de script.culo.us es muy complet e incluye muchos ejemplos, por lo que


continucio n so lo se muestr el uso de uno de sus componentes m s populres. En uno de los
ejercicios nteriores, se relizb un ejemplo de utocompletr el texto introducido por el
usurio. El co digo completo del ejercicio ocup m s de 140 lnes.

El siguiente co digo hce uso de script.culo.us pr conseguir el mismo resultdo con un 90%
menos de lnes de co digo:
window.onload = function() {
// Crear elemento de tipo <div> para mostrar las sugerencias del servidor
var elDiv = Builder.node('div', {id:'sugerencias'});
document.body.appendChild(elDiv);

new Ajax.Autocompleter('municipio', 'sugerencias',


'http://localhost/autocompletaMunicipios.php?modo=ul',
{paramName: 'municipio'}
);
}

L sintxis del control Ajax.Autocompleter() es l siguiente:


new Ajax.Autocompleter(idCuadroTexto, idDivResultados, url, opciones);

El primer pr metro (idCuadroTexto) es el identificdor del cudro de texto en el que el usurio


escribe ls letrs que se vn utocompletr. El segundo pr metro (idDivResultados) indic el
identificdor del elemento <div> en el que se v mostrr l respuest del servidor. En el
ejemplo nterior, este <div> se cre din micmente cundo se crg l p gin. El tercer
pr metro (url) indic l URL del script de servidor que recibe ls letrs escrits por el usurio
y devuelve l list de sugerencis que se muestrn. El u ltimo pr metro (opciones) permite
modificr lguns de ls opciones por defecto de este control.

A continucio n se muestrn ls opciones m s importntes disponibles pr el control de


utocompletr:

Opcin Descripcin
El nombre del parmetro que se enva al servidor con el texto escrito por el
paramName usuario. Por defecto es igual que el atributo name del cuadro de texto utilizado
para autocompletar

Permite autocompletar ms de un valor en un mismo cuadro de texto. Ms


tokens adelante se explica con un ejemplo.

Nmero mnimo de caracteres que el usuario debe escribir antes de que se realice
minChars la peticin al servidor. Por defecto es igual a 1 carcter.

Elemento que se muestra mientras se realiza la peticin al servidor y que se vuelve


a ocultar al recibir la respuesta del servidor. Normalmente es una imagen animada
indicator
que se utiliza para indicar al usuario que en ese momento se est realizando una
peticin al servidor
Funcin que se ejecuta despus de que el usuario seleccione un elemento de la
lista de sugerencias. Por defecto el comportamiento consiste en seleccionar el
updateElement
elemento, mostrarlo en el cuadro de texto y ocultar la lista de sugerencias. Si se
indica una funcin propia, no se ejecuta este comportamiento por defecto.

Similar a la opcin updateElement. En este caso, la funcin indicada se ejecuta


afterUpdateElement despus de la funcin por defecto y no en sustitucin de esa funcin por defecto.

L opcio n tokens permite indicr los crcteres que seprn los diferentes elementos de un
cudro de texto. En el siguiente ejemplo:
new Ajax.Autocompleter('municipio', 'sugerencias',
'http://localhost/autocompletaMunicipios.php?modo=ul',
{ paramName: 'municipio', tokens: ',' }
);

L opcio n tokens indic que el cr cter "," sepr los diferentes elementos dentro de un
mismo cudro de texto. De est form, si despue s de utocompletr un plbr se escribe un
cr cter "," el script utocompletr l siguiente plbr.

10.3. La librera jQuery


jQuery (http://jquery.com/) es l librer JvScript que h irrumpido con m s fuerz como
lterntiv Prototype. Su utor originl es John Resig, unque como sucede con tods ls
librers exitoss, ctulmente recibe contribuciones de decens de progrmdores. jQuery
tmbie n h sido progrmd de form muy eficiente y su versio n comprimid pens ocup 20
KB.
jQuery comprte con Prototype muchs ides e incluso dispone de funciones con el mismo
nombre. Sin embrgo, su disen o interno tiene lguns diferencis dr stics respecto Prototype,
sobre todo el "encadenamiento" de llmds me todos.

L documentcio n de jQuery es muy complet en ingle s e incluye muchos ejemplos. Adem s,


tmbie n existen lgunos recursos u tiles en espn ol pr prender su funcionmiento b sico:
http://docs.jquery.com/

10.3.1. Funciones y mtodos bsicos


L funcio n b sic de jQuery y un de ls m s u tiles tiene el mismo nombre que en Prototype, y
que se trt de l "funcin dolar": $(). A diferenci de l funcio n de Prototype, l de jQuery es
mucho m s que un simple tjo mejordo de l funcio n document.getElementById().

L cden de texto que se ps como pr metro puede hcer uso de Xpth o de CSS pr
seleccionr los elementos. Adem s, seprndo expresiones con un cr cter "," se puede
seleccionr un nu mero ilimitdo de elementos.
// Selecciona todos los enlaces de la pgina
$('a')

// Selecciona el elemento cuyo id sea "primero"


$('#primero')

// Selecciona todos los h1 con class "titular"


$('h1.titular')

// Selecciona todo lo anterior


$('a, #primero, h1.titular')

Ls posibiliddes de l funcio n $() vn mucho m s ll de estos ejemplos sencillos, y que


soport csi todos los selectores definidos por CSS 3 (lgo que dispondr n los nvegdores
dentro de vrios n os) y tmbie n permite utilizr XPth:
// Selecciona todos los prrafos de la pgina que tengan al menos un enlace
$('p[a]')

// Selecciona todos los radiobutton de los formularios de la pgina


$('input:radio')

// Selecciona todos los enlaces que contengan la palabra "Imprimir"


$('a:contains("Imprimir")');

// Selecciona los div que no estn ocultos


$('div:visible')

// Selecciona todos los elementos pares de una lista


$("ul#menuPrincipal li:even")

// Selecciona todos los elementos impares de una lista


$("ul#menuPrincipal li:odd")
// Selecciona los 5 primeros prrafos de la pgina
$("p:lt(5)")

Como se puede comprobr, ls posibiliddes de l funcio n $() son pr cticmente ilimitds, por
lo que l documentcio n de jQuery sobre los selectores (http://docs.jquery.com/Selectors)
disponibles es l mejor form de descubrir tods sus posibiliddes.

10.3.2. Funciones para eventos


Un de ls utiliddes m s interesntes de jQuery est relciond con el evento onload de l
p gin. Ls plicciones web m s complejs suelen utilizr un co digo similr l siguiente pr
inicir l pliccio n:
window.onload = function() {
...
};

Hst que no se crg l p gin, el nvegdor no construye el rbol DOM, lo que signific que no
se pueden utilizr funciones que seleccionen elementos de l p gin, ni se pueden n dir o
eliminr elementos. El problem de window.onload es que el nvegdor esper que l p gin
se crgue completmente, incluyendo tods ls im genes y rchivos externos que se hyn
enlzdo.

jQuery propone el siguiente co digo pr ejecutr ls instrucciones un vez que se h crgdo l


p gin:
$(document).ready(function() {
...
});

L grn ventj del me todo propuesto por jQuery es que l pliccio n no esper que se crguen
todos los elementos de l p gin, sino que so lo esper que se hy descrgdo el contenido
HTML de l p gin, con lo que el rbol DOM y est disponible pr ser mnipuldo. De est
form, ls plicciones JvScript desrrollds con jQuery pueden inicirse m s r pidmente
que ls plicciones JvScript trdicionles.

En relidd, ready() no es m s que un de ls muchs funciones que componen el mo dulo de


los eventos. Todos los eventos comunes de JvScript (click, mousemove, keypress, etc.)
disponen de un funcio n con el mismo nombre que el evento. Si se utiliz l funcio n sin
rgumentos, se ejecut el evento:
// Ejecuta el evento 'onclick' en todos los prrafos de la pgina
$('p').click();

// Ejecuta el evento 'mouseover' sobre un 'div' con id 'menu'


$('div#menu').mouseover();

No obstnte, el uso m s hbitul de ls funciones de cd evento es el de estblecer l funcio n


mnejdor que se v ejecutr cundo se produzc el evento:
// Establece la funcin manejadora del evento 'onclick'
// a todos los prrafos de la pgina
$('p').click(function() {
alert($(this).text());
});

// Establece la funcin manejadora del evento 'onblur'


// a los elementos de un formulario
$('#elFormulario :input').blur(function() {
valida($(this));
});

Entre ls utiliddes definids por jQuery pr los eventos se encuentr l funcio n toggle(), que
permite ejecutr dos funciones de form ltern cd vez que se pinch sobre un elemento:
$("p").toggle(function(){
alert("Me acabas de activar");
},function(){
alert("Me acabas de desactivar");
});

En el ejemplo nterior, l primer vez que se pinch sobre el elemento (y tods ls veces
impres), se ejecut l primer funcio n y l segund vez que se pinch el elemento (y tods ls
veces pres) se ejecut l segund funcio n.

10.3.3. Funciones para efectos visuales


Ls plicciones web m s vnzds incluyen efectos visules complejos pr construir
intercciones similres ls de ls plicciones de escritorio. jQuery incluye en l propi librer
vrios de los efectos m s comunes:
// Oculta todos los enlaces de la pgina
$('a').hide();

// Muestra todos los 'div' que estaban ocultos


$('div:hidden').show();

// Muestra los 'div' que estaba ocultos y oculta


// los 'div' que eran visibles
$('div').toggle();

Tods ls funciones relcionds con los efectos visules permiten indicr dos pr metros
opcionles: el primero es l durcio n del efecto y el segundo pr metro es l funcio n que se
ejecut l finlizr el efecto visul.

Otros efectos visules incluidos son los relciondos con el fundido o "fading" (fadeIn()
muestr los elementos con un fundido suve, fadeOut() ocult los elementos con un fundido
suve y fadeTo() estblece l opcidd del elemento en el nivel indicdo) y el despliegue de
elementos (slideDown() hce precer un elemento despleg ndolo en sentido descendente,
slideUp() hce desprecer un elemento despleg ndolo en sentido scendente,
slideToggle() hce desprecer el elemento si er visible y lo hce precer si no er visible).
10.3.4. Funciones para AJAX
Como sucede con Prototype, ls funciones y utiliddes relcionds con AJAX son prte
fundmentl de jQuery. El me todo principl pr relizr peticiones AJAX es $.ajax()
(importnte no olvidr el punto entre $ y ajax). A prtir de est funcio n b sic, se hn
definido otrs funciones relcionds, de m s lto nivel y especilizds en tres concrets:
$.get(),
$.post(), $.load(), etc.

L sintxis de $.ajax() es muy


sencill:
$.ajax(opciones);

Al contrrio de lo que sucede con Prototype, l URL que se solicit tmbie n se incluye dentro del
rry socitivo de opciones. A continucio n se muestr el mismo ejemplo b sico que se utilizo
en Prototype relizdo con $.ajax():
$.ajax({
url: '/ruta/hasta/pagina.php',
type: 'POST',
async: true,
data: 'parametro1=valor1&parametro2=valor2',
success: procesaRespuesta,
error: muestraError
});

L siguiente tbl muestr tods ls opciones que se pueden definir pr el me todo $.ajax():

Opcin Descripcin
Indica si la peticin es asncrona. Su valor por defecto es true, el habitual para las peticiones
async
AJAX

Permite indicar una funcin que modifique el objeto XMLHttpRequest antes de realizar la
beforeSend peticin. El propio objeto XMLHttpRequest se pasa como nico argumento de la funcin

Permite establecer la funcin que se ejecuta cuando una peticin se ha completado (y


despus de ejecutar, si se han establecido, las funciones de success o error). La funcin
complete
recibe el objeto XMLHttpRequest como primer parmetro y el resultado de la peticin
como segundo argumento

Indica el valor de la cabecera Content-Type utilizada para realizar la peticin. Su valor por
contentType defecto es application/x-www-form-urlencoded

Informacin que se incluye en la peticin. Se utiliza para enviar parmetros al servidor. Si es


una cadena de texto, se enva tal cual, por lo que su formato debera ser
data parametro1=valor1&parametro2=valor2. Tambin se puede indicar un array
asociativo de pares clave/valor que se convierten automticamente en una cadena tipo
query string
El tipo de dato que se espera como respuesta. Si no se indica ningn valor, jQuery lo deduce
a partir de las cabeceras de la respuesta. Los posibles valores son: xml (se devuelve un
documento XML correspondiente al valor responseXML), html (devuelve directamente la
dataType
respuesta del servidor mediante el valor responseText), script (se evala la respuesta
como si fuera JavaScript y se devuelve el resultado) y json (se evala la respuesta como si
fuera JSON y se devuelve el objeto JavaScript generado)
Indica la funcin que se ejecuta cuando se produce un error durante la peticin. Esta funcin
recibe el objeto XMLHttpRequest como primer parmetro, una cadena de texto indicando
error
el error como segundo parmetro y un objeto con la excepcin producida como tercer
parmetro

Permite considerar como correcta la peticin solamente si la respuesta recibida es diferente


ifModified de la anterior respuesta. Por defecto su valor es false

Indica si se transforman los datos de la opcin data para convertirlos en una cadena de
processData texto. Si se indica un valor de false, no se realiza esta transformacin automtica

Permite establecer la funcin que se ejecuta cuando una peticin se ha completado de


success forma correcta. La funcin recibe como primer parmetro los datos recibidos del servidor,
previamente formateados segn se especifique en la opcin dataType

Indica el tiempo mximo, en milisegundos, que la peticin espera la respuesta del servidor
timeout antes de anular la peticin

El tipo de peticin que se realiza. Su valor por defecto es GET, aunque tambin se puede
type utilizar el mtodo POST

url La URL del servidor a la que se realiza la peticin

Adem s de l funcio n $.ajax() gene ric, existen vris funciones relcionds que son
versiones simplificds y especilizds de es funcio n. As, ls funciones $.get() y $.post()
se utilizn pr relizr de form sencill peticiones GET y POST:
// Peticin GET simple
$.get('/ruta/hasta/pagina.php');

// Peticin GET con envo de parmetros y funcin que


// procesa la respuesta
$.get('/ruta/hasta/pagina.php',
{ articulo: '34' },
function(datos) {
alert('Respuesta = '+datos);
});

Ls peticiones POST se relizn exctmente de l mism form, por lo que so lo hy que


cmbir
$.get() por $.post(). L sintxis de ests funciones
son:
$.get(url, datos, funcionManejadora);

El primer pr merto (url) es el u nico obligtorio e indic l URL solicitd por l peticio n. Los
otros dos pr metros son opcionles, siendo el segundo (datos) los pr metros que se envn
junto con l peticio n y el tercero (funcionManejadora) el nombre o el co digo JvScript de l
funcio n que se encrg de procesr l respuest del servidor.

L funcio n $.get() dispone su vez de un versio n especilizd denomind


$.getIfModified(), que tmbie n obtiene un respuest del servidor medinte un peticio n GET,
pero l respuest so lo est disponible si es diferente de l u ltim respuest recibid.

jQuery tmbie n dispone de l funcio n $.load(), que es ide ntic l funcio n Ajax.Updater()
de
Prototype. L funcio n $.load() insert el contenido de l respuest del servidor en el
elemento
de l p gin que se indic. L form de indicr ese elemento es lo que diferenci jQuery de
Prototype:
<div id="info"></div>

// Con Prototype
new Ajax.Updater('info', '/ruta/hasta/pagina.php');

// Con jQuery
$('#info').load('/ruta/hasta/pagina.php');

Al igul que suced con l funcio n $.get(), l funcio n $.load() tmbie n dispone de un
versio n especfic denomind $.loadIfModified() que crg l respuest del servidor en el
elemento so lo si es respuest es diferente l u ltim recibid.

Por u ltimo, jQuery tmbie n dispone de ls funciones $.getJSON() y $.getScript() que crgn
y evlu n/ejecutn respectivmente un respuest de tipo JSON y un respuest con co digo
JvScript.

10.3.5. Funciones para CSS


jQuery dispone de vris funciones pr l mnipulcio n de ls propieddes CSS de los
elementos. Tods ls funciones se emplen junto con un seleccio n de elementos relizd con l
funcio n $().

Si l funcio n obtiene el vlor de ls propieddes CSS, so lo se obtiene el vlor de l propiedd CSS


del primer elemento de l seleccio n relizd. Sin embrgo, si l funcio n estblece el vlor de ls
propieddes CSS, se estblecen pr todos los elementos selecciondos.
// Obtiene el valor de una propiedad CSS
// En este caso, solo para el primer 'div' de la pgina
$('div').css('background');

// Establece el valor de una propiedad CSS


// En este caso, para todos los 'div' de la pgina
$('div').css('color', '#000000');

// Establece varias propiedades CSS


// En este caso, para todos los 'div' de la pgina
$('div').css({ padding: '3px', color: '#CC0000' });

Adem s de ls funciones nteriores, CSS dispone de funciones especfics pr obtener/


estblecer l ltur y nchur de los elementos de l p gin:
// Obtiene la altura en pxel del primer 'div' de la pgina
$('div').height();

// Establece la altura en pxel de todos los 'div' de la pgina


$('div').height('150px');

// Obtiene la anchura en pxel del primer 'div' de la pgina


$('div').width();
// Establece la anchura en pxel de todos los 'div' de la pgina
$('div').width('300px');

10.3.6. Funciones para nodos DOM


L funcio n $() permite seleccionr elementos (nodos DOM) de l p gin de form muy
sencill. jQuery permite, dem s, seleccionr nodos relciondos con l seleccio n relizd. Pr
seleccionr nodos relciondos, se utilizn funciones de filtrdo y funciones de bu squed.

Los filtros son funciones que modificn un seleccio n relizd con l funcio n $() y permiten
limitr el nu mero de nodos devueltos.

L funcio n contains() limit los elementos selecciondos quellos que contengn en su


interior el texto indicdo como pr metro:
// Slo obtiene los prrafos que contengan la palabra 'importante'
$('p').contains('importante');

L funcio n not() elimin de l seleccio n de elementos quellos que cumpln con el selector
indicdo:
// Selecciona todos los enlaces de la pgina, salvo el que
// tiene una 'class' igual a 'especial'
$('a').not('.especial');
// La siguiente instruccin es equivalente a la anterior
$('a').not($('.especial'));

L funcio n filter() es l invers de not(), y que elimin de l seleccio n de elementos


quellos que no cumpln con l expresio n indicd. Adem s de un expresio n, tmbie n se puede
indicr un funcio n pr filtrr l seleccio n:
// Selecciona todas las listas de elementos de la pgina y quedate
// slo con las que tengan una 'class' igual a 'menu'
$('ul').filter('.menu');

Un funcio n especil relciond con los filtros y buscdores es end(), que permite volver l
seleccio n originl de elementos despue s de relizr un filtrdo de elementos. L documentcio n
de jQuery incluye el siguiente ejemplo:
$('a')
.filter('.pinchame')
.click(function(){
alert('Ests abandonando este sitio web');
})
.end()
.filter('ocultame')
.click(function(){
$(this).hide();
return false;
})
.end();

El co digo nterior obtiene todos los enlces de l p gin $('a') y plic diferentes funciones
mnejdors del evento click en funcio n del tipo de enlce. Aunque se podrn incluir dos
instrucciones diferentes pr relizr cd filtrdo, l funcio n end() permite encdenr vris
selecciones.

El primer filtrdo ($('a').filter('.pinchame'))) seleccion todos los elementos de l p gin


cuyo tributo class se igul pinchame. Despue s, se sign l funcio n mnejdor pr el
evento de pinchr con el rto n medinte l funcio n click().

A continucio n, el co digo nterior reliz otro filtrdo prtir de l seleccio n originl de enlces.
Pr volver l seleccio n originl, se utiliz l funcio n end() ntes de relizr un nuevo filtrdo.
De est form, l instruccio n .end().filter('ocultame') es equivlente relizr el filtrdo
directmente sobre l seleccio n originl $('a').filter('.ocultame')).

El segundo grupo de funciones pr l mnipulcio n de nodos DOM est formdo por los
buscdores, funciones que buscn/seleccionn nodos relciondos con l seleccio n relizd. De
est form, jQuery define l funcio n children() pr obtener todos los nodos hijo o
descendientes del nodo ctul, parent() pr obtener el nodo padre o nodo scendente del
nodo ctul (parents() obtiene todos los scendentes del nodo hst l rz del rbol) y
siblings() que obtiene todos los nodos hermano del nodo ctul, es decir, todos los nodos que
tienen el mismo nodo padre que el nodo ctul.

L nvegcio n entre nodos hermano se puede relizr con ls funciones next() y pev() que
vnzn o retroceden trve s de l list de nodos hermano del nodo ctul.

Por u ltimo, jQuery tmbie n dispone de funciones pr mnipulr f cilmente el contenido de los
nodos DOM (http://docs.jquery.com/Mnipultion) . Ls funciones append() y prepend()
n den el contenido indicdo como pr metro l principio o l finl respectivmente del
contenido originl del nodo.

Ls funciones after() y before() n den el contenido indicdo como pr metro ntes de


cd uno de los elementos selecciondos. L funcio n wrap() permite "envolver" un elemento
con el contenido indicdo (se n de prte del contenido por delnte y el resto por detr s).

L funcio n empty() vc de contenido un elemento, remove() elimin los elementos


selecciondos del rbol DOM y clone() copi de form exct los nodos selecciondos.

10.3.7. Otras funciones tiles


jQuery detect utom ticmente el tipo de nvegdor en el que se est ejecutndo y permite
cceder est informcio n trve s del objeto $.browser:
$.browser.msie; // 'true' para navegadores de la familia Internet Explorer
$.browser.mozilla; // 'true' para navegadores de la familia Firefox
$.browser.opera; // 'true' para navegadores de la familia Opera
$.browser.safari; // 'true' para navegadores de la familia Safari

Recorrer rrys y objetos tmbie n es muy sencillo con jQuery, grcis l funcio n $.each(). El
primer pr metro de l funcio n es el objeto que se quiere recorrer y el segundo pr metro es el
co digo de l funcio n que lo recorre ( su vez, est funcio n se le ps como primer pr metro el
ndice del elemento y como segundo pr metro el vlor del elemento):
// Recorrer arrays
var vocales = ['a', 'e', 'i', 'o', 'u'];

$.each( vocales, function(i, n){


alert('Vocal nmero ' + i + " = " + n);
});

// Recorrer objetos
var producto = { id: '12DW2', precio: 12.34, cantidad: 5 };

$.each( producto, function(i, n){


alert(i + ' : ' + n);
});

10.3.8. Rehaciendo ejemplos con jQuery


Como suced con Prototype, cundo se rehce un pliccio n JvScript con jQuery, el resultdo
es un co digo muy conciso pero que mntiene su fcilidd de lectur y comprensio n.

Por ejemplo, el ejercicio que mostrb y ocultb diferentes secciones de contenidos se relizo
con JvScript de l siguiente mner:
function muestraOculta() {
// Obtener el ID del elemento
var id = this.id;
id = id.split('_');
id = id[1];

var elemento = document.getElementById('contenidos_'+id);


var enlace = document.getElementById('enlace_'+id);

if(elemento.style.display == "" || elemento.style.display == "block") {


elemento.style.display = "none";
enlace.innerHTML = 'Mostrar contenidos';
}
else {
elemento.style.display = "block";
enlace.innerHTML = 'Ocultar contenidos';
}
}

window.onload = function()
{ document.getElementById('enlace_1').onclick =
muestraOculta; document.getElementById('enlace_2').onclick =
muestraOculta;
document.getElementById('enlace_3').onclick = muestraOculta;
}

Con Prototype, su co digo se redujo ls siguientes instrucciones:


function muestraOculta() {
var id = (this.id).split('_')[1];

$('contenidos_'+id).toggle();
$('enlace_'+id).innerHTML = (!$('contenidos_'+id).visible()) ? 'Ocultar contenidos' :
'Mostrar contenidos';
}

window.onload = function() {
$R(1, 3).each(function(n) {
Event.observe('enlace_'+n, 'click', muestraOculta);
});
}

Con jQuery, el mismo co digo se puede escribir de l siguiente form:


$(document).ready(function(){
$.each([1, 2, 3], function(i, n){
$('#enlace_'+n).toggle(
function() { $('#contenidos_'+n).toggle(); $(this).html('Mostrar contenidos'); },
function() { $('#contenidos_'+n).toggle(); $(this).html('Ocultar contenidos'); }
);
})
});

El co digo nterior utiliz l funcio n toggle() como evento que permite lternr l ejecucio n
de dos funciones y como funcio n que ocult un elemento visible y muestr un elemento oculto.

Otro de los ejercicios nteriores relizb peticiones AJAX l servidor pr comprobr si un


determindo nombre de usurio estb libre. El co digo originl de JvScript er:
var READY_STATE_COMPLETE=4;
var peticion_http = null;

function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function comprobar() {
var login = document.getElementById("login").value;
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/compruebaDisponibilidad.php", true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send("login="+login+"&nocache="+Math.random());
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
var login = document.getElementById("login").value;
if(peticion_http.responseText == "si") {
document.getElementById("disponibilidad").innerHTML = "El nombre elegido
["+login+"] est disponible";
}
else {
document.getElementById("disponibilidad").innerHTML = "NO est disponible el
nombre elegido ["+login+"]";
}
}
}
}

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

Con Prototype se puede conseguir el mismo comportmiento con tres veces menos de lnes de
co digo:
function comprobar() {
var login = $F('login');
var url = 'http://localhost/compruebaDisponibilidad.php?nocache=' + Math.random();
var peticion = new Ajax.Request(url, {
method:'post',
postBody:'login='+login,
onSuccess: function(respuesta) {
$('disponibilidad').innerHTML = (respuesta.responseText == 'si') ?
'El nombre elegido ['+login+'] est disponible' : 'NO est disponible el nombre
elegido ['+login+']';
},
onFailure: function() { alert('Se ha producido un error'); }
});
}

window.onload = function()
{ Event.observe('comprobar', 'click',
comprobar);
}

jQuery tmbie n permite simplificr notblemente el co digo de l pliccio n originl:


function comprobar() {
var login = $('#login').value;
var peticion = $.ajax({
url: 'http://localhost/compruebaDisponibilidad.php?nocache=' + Math.random(),
method: 'POST',
data: { login: login },
success: function(respuesta) {
$('#disponibilidad').html((respuesta.responseText == 'si') ?
'El nombre elegido ['+login+'] est disponible' :
'NO est disponible el nombre elegido ['+login+']');
},
error: function() { alert('Se ha producido un error'); }
});
}

$(document).ready(function(){
$('#comprobar').click(comprobar);
});
10.4. Otros frameworks importantes
El boom de ls plicciones web con interfces din mics complejs y que incluyen mu ltiples
intercciones AJAX h provocdo l irrupcio n de un grn nu mero de frmeworks especilizdos
pr el desrrollo de plicciones con JvScript. Adem s de Prototype y jQuery, existen otros
frmeworks destcbles:

Dojo (http://dojotoolkit.org/) es mucho m s que un frmework, y que sus propios


credores lo denominn "el conjunto de herramientas ("toolkit") de JavaScript que permite
desarrollar aplicaciones web profesionales de forma sencilla y ms rpida". Adem s, Dojo
dispone de un licenci de tipo softwre libre.
Mootools (http://mootools.net/) es un frmework que destc por su reducido tmn o y
por lo modulr de su desrrollo. De hecho, l descrgr el frmework, se pueden elegir los
componentes que se vn utilizr, pr descrgr un versio n comprimid que so lo
conteng los componentes escogidos. De est form, se puede reducir l mnimo el tmn o
de los rchivos descrgdos por los usurios.
Ext JS (http://extjs.com/) es otro de los frmeworks m s populres de JvScript. Aunque
comenzo siendo un n dido de l librer YUI de Yhoo (http://developer.yhoo.com/
yui/) ,pronto dquirio entidd propi. Adem s de ls utiliddes comunes, incluye un
serie de componentes listos pr usr y tiene un licenci de tipo softwre libre y otr
licenci de tipo comercil si se dese obtener soporte te cnico.
Introduccin a AJAX Captulo 11. Otras utilidades

Captulo 11. Otras utilidades


11.1. Detener las peticiones HTTP errneas
L crecio n de plicciones AJAX implic l pricio n de nuevos tipos de errores y excepciones.
Probblemente, el problem m s importnte se el de relizr un peticio n l servidor y que
este no respond en un periodo de tiempo rzonble.

Aunque ls peticiones se relizn de form sncron y el usurio puede continur utilizndo l


pliccio n mientrs se reliz l peticio n l servidor en un segundo plno, normlmente es
necesrio disponer de un respuest r pid del servidor.

L funcio n setTimeout() se puede empler pr estblecer un cuent tr s l inicir un


nuev peticio n. Si el servidor responde ntes de que expire l cuent tr s, se elimin es
cuent tr s y se continu con l ejecucio n norml de l pliccio n. Si el servidor no
responde y l cuent tr s finliz, se ejecut un funcio n encrgd de detener l peticio n,
reintentrl, mostrr un mensje l usurio, etc.
// Variable global que almacena el identificador de la cuenta atrs
var cuentaAtras = null;
var tiempoMaximo = 5000; // 5000 = 5 segundos

function cargaContenido(url, metodo, funcion) {


peticion_http = inicializa_xhr();
if(peticion_http) {
// Establecer la cuenta atrs al realizar la peticin HTTP
cuentraAtras = setTimeout(expirada, tiempoMaximo);
peticion_http.onreadystatechange = funcion;
peticion_http.open(metodo, url, true);
peticion_http.send(null);
}
}

function muestraMensaje() {
...
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if(peticion_http.status == 200) {
// Si se ha recibido la respuesta del servidor, eliminar la cuenta atrs
clearTimeout(cuentaAtras);
...
}
}
}

function expirada() {
// La cuentra atrs se ha cumplido, detener la peticin HTTP pendiente
peticion_http.abort();
alert("Se ha producido un error en la comunicacin con el servidor. Intntalo un poco
ms adelante.");
}
Introduccin a AJAX Captulo 11. Otras utilidades

Adem s de l flt de respuest del servidor, ls plicciones AJAX deben estr preprds pr
otros tipos de respuests que pueden generr los servidores. El tipo de respuest se comprueb
medinte el vlor del tributo status del objeto XMLHTTPRequest.

A continucio n se muestrn ls tbls de los co digos de estdo m s comunes que pueden


devolver los servidores:

Cdigos de informacin

status statusText Explicacin

Una parte de la peticin (normalmente la primera) se ha recibido sin problemas y se


100 Continue puede enviar el resto de la peticin
Introduccin a AJAX Captulo 11. Otras utilidades
Switching El servidor va a cambiar el protocolo con el que se enva la informacin de la respuesta.
101 protocols En la cabecera Upgrade indica el nuevo protocolo

Cdigos de peticin y respuesta correctas

status statusText Explicacin

La peticin se ha recibido correctamente y se est enviando la respuesta. Este


200 OK cdigo es con mucha diferencia el que mas devuelven los servidores

Se ha creado un nuevo recurso (por ejemplo una pgina web o un archivo) como
201 Created parte de la respuesta

La peticin se ha recibido correctamente y se va a responder, pero no de forma


202 Accepted inmediata
Non-Authoritative La respuesta que se enva la ha generado un servidor externo. A efectos prcticos,
203
Information es muy parecido al cdigo 200
204 No Content La peticin se ha recibido de forma correcta pero no es necesaria una respuesta

El servidor solicita al navegador que inicialice el documento desde el que se


205 Reset Content realiz la peticin, como por ejemplo un formulario

La respuesta contiene slo la parte concreta del documento que se ha solicitado


206 Partial Content en la peticin

Cdigos de redireccin

status statusText Explicacin


Multiple El contenido original ha cambiado de sitio y se devuelve una lista con varias direcciones
300
Choices alternativas en las que se puede encontrar el contenido
Moved El contenido original ha cambiado de sitio y el servidor devuelve la nueva URL del
301
Permanently contenido. La prxima vez que solicite el contenido, el navegador utiliza la nueva URL
El contenido original ha cambiado de sitio de forma temporal. El servidor devuelve la
302 Found nueva URL, pero el navegador debe seguir utilizando la URL original en las prximas
peticiones
El contenido solicitado se puede obtener en la URL alternativa devuelta por el servidor.
303 See Other
Este cdigo no implica que el contenido original ha cambiado de sitio
Normalmente, el navegador guarda en su cach los contenidos accedidos
frecuentemente. Cuando el navegador solicita esos contenidos, incluye la condicin de
Not
304 que no hayan cambiado desde la ltima vez que los recibi. Si el contenido no ha
Modified
cambiado, el servidor devuelve este cdigo para indicar que la respuesta sera la misma
que la ltima vez

El recurso solicitado slo se puede obtener a travs de un proxy, cuyos datos se


305 Use Proxy incluyen en la respuesta
Temporary Se trata de un cdigo muy similar al 302, ya que indica que el recurso solicitado se
307
Redirect encuentra de forma temporal en otra URL

Cdigos de error del navegador

status statusText Explicacin


400 Bad Request El servidor no entiende la peticin porque no ha sido creada de forma correcta
401 Unauthorized El recurso solicitado requiere autorizacin previa
Payment
402 Cdigo reservado para su uso futuro
Required

No se puede acceder al recurso solicitado por falta de permisos o porque el usuario y


403 Forbidden contrasea indicados no son correctos

El recurso solicitado no se encuentra en la URL indicada. Se trata de uno de los


404 Not Found cdigos ms utilizados y responsable de los tpicos errores de Pgina no encontrada
Method Not El servidor no permite el uso del mtodo utilizado por la peticin, por ejemplo por
405
Allowed utilizar el mtodo GET cuando el servidor slo permite el mtodo POST
Not El tipo de contenido solicitado por el navegador no se encuentra entre la lista de
406
Acceptable tipos de contenidos que admite, por lo que no se enva en la respuesta
Proxy
Similar al cdigo 401, indica que el navegador debe obtener autorizacin del proxy
407 Authentication
antes de que se le pueda enviar el contenido solicitado
Required
Request El navegador ha tardado demasiado tiempo en realizar la peticin, por lo que el
408
Timeout servidor la descarta

El navegador no puede procesar la peticin, ya que implica realizar una operacin no


409 Conflict permitida (como por ejemplo crear, modificar o borrar un archivo)

Similar al cdigo 404. Indica que el recurso solicitado ha cambiado para siempre su
410 Gone localizacin, pero no se proporciona su nueva URL
Length El servidor no procesa la peticin porque no se ha indicado de forma explcita el
411
Required tamao del contenido de la peticin
Precondition
412 No se cumple una de las condiciones bajo las que se realiz la peticin
Failed

Request Entity La peticin incluye ms datos de los que el servidor es capaz de procesar.
413 Normalmente este error se produce cuando se adjunta en la peticin un archivo con
Too Large
un tamao demasiado grande

Request-URI La URL de la peticin es demasiado grande, como cuando se incluyen ms de 512


414 Too Long bytes en una peticin realizada con el mtodo GET
Unsupported Al menos una parte de la peticin incluye un formato que el servidor no es capaz
415
Media Type procesar
Requested
El trozo de documento solicitado no est disponible, como por ejemplo cuando se
416 Range Not
solicitan bytes que estn por encima del tamao total del contenido
Suitable
Expectation El servidor no puede procesar la peticin porque al menos uno de los valores
417
Failed incluidos en la cabecera Expect no se pueden cumplir

Cdigos de error del servidor

status statusText Explicacin


Internal Server
500 Se ha producido algn error en el servidor que impide procesar la peticin
Error
Not
501 Procesar la respuesta requiere ciertas caractersticas no soportadas por el servidor
Implemented

El servidor est actuando de proxy entre el navegador y un servidor externo del


502 Bad Gateway que ha obtenido una respuesta no vlida
Service El servidor est sobrecargado de peticiones y no puede procesar la peticin
503
Unavailable realizada
Gateway El servidor est actuando de proxy entre el navegador y un servidor externo que ha
504
Timeout tardado demasiado tiempo en responder
HTTP Version El servidor no es capaz de procesar la versin HTTP utilizada en la peticin. La
505
Not Supported respuesta indica las versiones de HTTP que soporta el servidor

11.2. Mejorar el rendimiento de las aplicaciones complejas


Cundo se desrrolln plicciones complejs, es hbitul encontrrse con decens de rchivos
JvScript de miles de lnes de co digo. Estructurr ls plicciones de est form es correcto y
fcilit el desrrollo de l pliccio n, pero penliz en exceso el rendimiento de l pliccio n.

L primer recomendcio n pr mejorr el rendimiento de l pliccio n consiste en unir en un


u nico rchivo JvScript el contenido de todos los diferentes rchivos JvScript. En Windows, se
puede crer un pequen o progrm ejecutble que copi el contenido de vrios rchivos
JvScript en uno solo:
more archivo1.js > archivoUnico.js
more archivo2.js >> archivoUnico.js
more archivo3.js >> archivoUnico.js
...

L primer instruccio n tiene un solo smbolo > pr borrr el contenido del archivoUnico.js
cd vez que se ejecut el comndo. El resto de instrucciones tienen un smbolo >> pr n dir
el contenido de los dem s rchivos l finl del archivoUnico.js

En sistems opertivos de tipo Linux es todv m s sencillo unir vrios rchivos en uno solo:
cat archivo1.js archivo2.js archivo3.js > archivoUnico.js
L u nic considercio n que se debe tener en cuent con este me todo es el de ls dependencis
entre rchivos. Si por ejemplo el archivo1.js contiene funciones que dependen de otrs
funciones definids en el archivo3.js, los rchivos debern unirse en este otro orden:
cat archivo3.js archivo1.js archivo2.js > archivoUnico.js

Otr recomendcio n muy u til pr mejorr el rendimiento de l pliccio n es l de comprimir el


co digo de JvScript. Este tipo de herrmients compresors de co digo no modificn el
comportmiento de l pliccio n, pero pueden reducir mucho su tmn o.

El proceso de compresio n consiste en eliminr todos los espcios en blnco sobrntes, eliminr
todos los comentrios del co digo y convertir tod l pliccio n en un u nic lne de co digo
JvScript muy lrg. Algunos compresores vn m s ll y sustituyen el nombre de ls vribles
y funciones por nombres m s cortos.

ShrinkSfe (http://dojotoolkit.org/shrinksfe/) es un de ls herrmients que proporcion el


frmeworkDojo(http://dojotoolkit.org/) y que puede ser utilizd incluso de form online. Los
credores de l pliccio n segurn de que es l herrmient m s segur pr reducir el tmn o
del co digo, y que no modific ningu n elemento que pued provocr errores en l pliccio n.

11.3. Ofuscar el cdigo JavaScript


El co digo de ls plicciones JvScript, l igul que el resto de contenidos de ls p gins web,
est disponible pr ser ccedido y visulizdo por culquier usurio. Con l pricio n de ls
plicciones bsds en AJAX, muchs empress hn desrrolldo complejs plicciones cuyo
co digo fuente est disposicio n de culquier usurio.

Aunque se trt de un problem csi imposible de solucionr, existen te cnics que minimizn el
problem de que se pued cceder libremente l co digo fuente de l pliccio n. L principl
te cnic es l de ofuscr el co digo fuente de l pliccio n.

Los ofuscadores utilizn diversos mecnismos pr hcer csi imposible de entender el co digo
fuente de un pliccio n. Mnteniendo el comportmiento de l pliccio n, consiguen ensuciar y
dificultr tnto el co digo que no es myor problem que lguien pued cceder ese co digo.

El progrm ofuscdor Jsob (http://www.jsob.com/) ofrece un ejemplo del resultdo de


ofuscr cierto co digo JvScript. Este es el co digo originl ntes de ofuscrlo:
//------------------------------------------------------
// Calculate salary for each employee in "aEmployees".
// "aEmployees" is array of "Employee" objects.
//------------------------------------------------------
function CalculateSalary(aEmployees)
{
var nEmpIndex = 0;
while (nEmpIndex < aEmployees.length)
{
var oEmployee = aEmployees[nEmpIndex];
oEmployee.fSalary = CalculateBaseSalary(oEmployee.nType,
oEmployee.nWorkingHo
if urs);
(oEmployee.
bBonusAllow
ed == true)
{
oEmployee.fBonus = CalculateBonusSalary(oEmployee.nType,
oEmployee.nWorkingHours,
oEmployee.fSalary);
}
else
{
oEmployee.fBonus = 0;
}
oEmployee.sSalaryColor = GetSalaryColor(oEmployee.fSalary +
oEmployee.fBonus);
nEmpIndex++;
}
}

Despue s de psr el co digo nterior por el ofuscdor el resultdo es:


function c(g){var m=0;while(m<g.length){var r=g[m];r.l=d(r.n,r.o);if(r.j==true){
r.k=e(r.n,r.o,r.l);}else{r.k=0;}r.t=f(r.l+r.k);m++;}}

Al sustituir todos los nombres de ls vribles y de ls funciones por nombres de un sol letr,
es pr cticmente imposible comprender el co digo del progrm. En ocsiones, tmbie n se
utilizn ofuscdores de este tipo con el propo sito de reducir el tmn o del co digo fuente.

Adem s de plicciones comerciles especficmente disen ds pr ofuscr co digo JvScript,


tmbie n se pueden utilizr ls herrmients que minimizn el tmn o de los scripts. Eliminndo
los comentrios y reduciendo el nombre de tods ls vribles, los progrms que minimizn el
tmn o de los scripts tmbie n consiguen ofuscr su co digo.

L pliccio n pcker(http://den.edwrds.nme/pcker/) es grtuit, se puede cceder vi web


y consigue un excelente compresio n del co digo originl. Tmbie n se puede utilizr jsjuicer
(http://drin3.googlepges.com/jsjuicer.html) , que est disponible como pliccio n
descrgble y tmbie n se puede utilizr v web (http://gueschl.com/lbs/jsjuicer/) .

11.4. Evitar el problema de los dominios diferentes


Como y se h explicdo y se h podido comprobr en lgunos de los ejercicios, los nvegdores
imponen restricciones muy severs ls conexiones de red que se pueden relizr medinte
AJAX. Est crcterstic se conoce como "el problema de los dominios diferentes" (en ingle s,
"cross-domain problem").

El co digo JvScript lojdo en un servidor, no puede relizr conexiones con otros dominios
externos. Tmbie n existen problems entre subdominios de un mismo sitio web, que se pueden
evitr con el uso de l propiedd document.domain.

Afortundmente, existen opciones pr poder relizr conexiones con culquier dominio


externo l servidor que loj el co digo JvScript. Tods ls soluciones que son vibles
te cnicmente y que funcionn de l mism form en culquier nvegdor hcen uso de recursos
en el servidor que loj el co digo JvScript originl.
L solucio n m s sencill es l de hbilitr el mo dulo mod_rewrite en los servidores web de
tipo Apche. Con este mo dulo ctivdo, Apche se puede convertir en un proxy trnsprente que
relice ls peticiones externs en nombre del script y le devuelv los resultdos.

En el siguiente ejemplo, el nvegdor descrg el script desde el servidor1. Por este motivo, el
co digo del script puede solicitr recursos del servidor1, pero no puede estblecer conexiones
con el servidor2:

Figura 11.1. El script descargado desde el servidor1 no puede establecer conexiones de red con el
servidor2

L solucio n m s sencill pr resolver este problem consiste en configurr el servidor web del
servidor1. Si se utiliz el servidor web Apche, pr configurr el proxy trnsprente, se
hbilit el mo dulo mod_rewrite y se n den ls siguientes directivs l configurcio n de
Apche:
RewriteEngine on
RewriteRule ^/ruta/al/recurso$ http://www.servidor2.com/ruta/al/recurso [P]

Ahor, el co digo de l pliccio n puede cceder culquier recurso del servidor2 y


que:

El script reliz peticiones : http://www.servidor1.com/rut/l/recurso


En el servidor1 se trnsform utom ticmente : http://www.servidor2.com/rut/l/
recurso
El servidor1 obtiene l respuest del servidor2 y l env de nuevo l script
Figura 11.2. Utilizando un proxy transparente, los scripts pueden acceder a los recursos que se
encuentren en cualquier servidor

Adem s de utilizr el servidor web como proxy trnsprente, tmbie n es posible disen r un
proxy medid medinte softwre. Yhoo por ejemplo ofrece un extens documentcio n pr
los desrrolldores de plicciones web. Entre est documentcio n, se encuentr un rtculo
sobre el uso de proxys pr evitr el problem de ls peticiones externs de AJAX:
http://developer.yhoo.com/jvscript/howto-proxy.html

Adem s, Yhoo ofrece un proxy de ejemplo relizdo con PHP y que puede ser utilizdo pr
conectr plicciones JvScript con sus servicios web.
Introduccin a AJAX Captulo 12. Recursos tiles

Captulo 12. Recursos tiles


Documentcio n y referencis:

Ajx: A New Approch to Web Applictions (http://www.dptivepth.com/publictions/


essys/rchives/000385.php) : el rtculo en el que se cun o por primer vez el te rmino
AJAX y en el que se explic su funcionmiento b sico.
Documentcio n de referenci sobre el objeto XMLHttpRequest: W3C (borrdor)
(http://www.w3.org/TR/XMLHttpRequest/) , Microsoft (Internet Explorer)
(http://msdn2.microsoft.com/en-us/librry/ms535874.spx) , Mozill (Firefox)
(http://developer.mozill.org/en/docs/XMLHttpRequest) , Apple (Sfri)
(http://developer.pple.com/internet/webcontent/xmlhttpreq.html) .

Noticis y ctulidd:

Ajxin (http://www.jxin.com) : el blog m s populr dedicdo l mundo AJAX.

Librers y frmeworks:

Prototype (http://www.prototypejs.org/) : el primer frmework de JvScript/AJAX de


uso msivo.
script.culo.us (http://script.culo.us/) : l librer bsd en Prototype m s utilizd.
jQuery (http://jquery.com/) : l librer de JvScript que h surgido como lterntiv
Prototype.

Otrs utiliddes:

Ajxlod (http://www.jxlod.info/) : utilidd pr construir los pequen os iconos


nimdos que ls plicciones AJAX suelen utilizr pr indicr l usurio que se est
relizndo un peticio n.
MiniAjx (http://minijx.com/) : decens de ejemplos reles de plicciones AJAX lists
pr descrgr (glers de im genes, reflejos pr im genes, formulrios, tbls
reordenbles, etc.)
Introduccin a AJAX Captulo 13. Bibliografa

Captulo 13. Bibliografa


Bibliogrf sobre JvScript:

Professional JavaScript for Web Developers, Nichols C. Zks (ISBN: 978-0-7645-7908-0).


A pesr de ser un libro antiguo, sigue siendo un buen referenci de prendizje de
JvScript pr los progrmdores de plicciones web. Ver m s informcio n sobre el
libro (http://www.wrox.com/WileyCDA/WroxTitle/productCd-0764579088.html) .
JavaScript: The Definitive Guide (Fifth Edition), Dvid Flngn (ISBN-13:
9780596101992). Referenci complet de JvScript en m s de 1.000 p gins que
explicn con detlle culquier specto de este lenguje de progrmcio n. Ver m s
informcio n sobre el libro (http://www.oreilly.com/ctlog/jscript5/index.html)

Bibliogrf sobre AJAX:

Pragmatic Ajax: A Web 2.0 Primer, Justin Gehtlnd, Ben Glbrith, Dion Almer (ISBN13:
978-0976694083). Se trt de un libro muy pr ctico que incluye muchos ejemplos reles
f ciles de entender pesr de su complejidd. Ver m s informcio n sobre el libro
(http://www.prgmticprogrmmer.com/title/jx/) .
Ajax in Action, Dve Crne, Eric Pscrello, Drren Jmes (ISBN-13: 978-1932394610).
Aunque no es tn pr ctico como el nterior, el co digo de los ejemplos incluidos est muy
bien progrmdo, lo que yud crer plicciones muy profesionles. Ver m s
informcio n sobre el libro (http://www.mnning.com/crne/) .
Ajax Hacks, Bruce Perry (ISBN-13: 978-0596101695). Coleccio n de trucos y pequen s
utiliddes lists pr copir+pegr en ls plicciones reles. Ver m s informcio n sobre
el libro (http://www.oreilly.com/ctlog/jxhks/) .
Introduccin a AJAX Captulo 14. Ejercicios resueltos

Captulo 14. Ejercicios resueltos


14.1. Ejercicio 1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 1 - Objetos</title>
<script type="text/javascript">
// Estructura bsica del objeto Factura
var factura = {
empresa: {
nombre: "Nombre de la empresa",
direccion: "Direccin de la empresa",
telefono: "900900900",
nif: ""
},
cliente: {
nombre: "Nombre del cliente",
direccion: "Direccin del cliente",
telefono: "600600600",
nif: "XXXXXXXXX"
},
elementos: [
{ descripcion: "Producto 1", cantidad: 0, precio: 0 },
{ descripcion: "Producto 2", cantidad: 0, precio: 0 },
{ descripcion: "Producto 3", cantidad: 0, precio: 0 }
],
informacion:
{ baseImponible:
0, iva: 16,
total: 0,
formaPago: "contado"
}
};

// Mtodos de clculo del total y de visualizacin del total


factura.calculaTotal = function() {
for(var i=0; i<this.elementos.length; i++) {
this.informacion.baseImponible += this.elementos[i].cantidad *
this.elementos[i].precio;
}
this.informacion.total = this.informacion.baseImponible * this.informacion.iva;
}

factura.muestraTotal = function() {
this.calculaTotal();
alert("TOTAL = " + this.informacion.total + " euros");
}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

factura.muestraTotal();
</script>
</head>

<body>
</body>
</html>

14.2. Ejercicio 2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 2 - Clases</title>
<script type="text/javascript">
// Definicin de la clase Cliente
function Cliente(nombre, direccion, telefono, nif) {
this.nombre = nombre;
this.direccion = direccion;
this.telefono = telefono;
this.nif = nif;
}

// Definicin de la clase Elemento


function Elemento(descripcion, cantidad, precio) {
this.descripcion = descripcion;
this.cantidad = cantidad;
this.precio = precio;
}

// Definicin de la clase Factura


function Factura(cliente, elementos) {
this.cliente = cliente;
this.elementos = elementos;
this.informacion = {
baseImponible: 0,
iva: 16,
total: 0,
formaPago: "contado"
};
};

// La informacin de la empresa que emite la factura se


// aade al prototype porque se supone que no cambia
Factura.prototype.empresa = {
nombre: "Nombre de la empresa",
direccion: "Direccion de la empresa",
telefono: "900900900",
nif: "XXXXXXXX"
};

// Mtodos aadidos al prototype de la Factura


Factura.prototype.calculaTotal = function() {
Introduccin a AJAX Captulo 14. Ejercicios resueltos

for(var i=0; i<this.elementos.length; i++) {


this.informacion.baseImponible += this.elementos[i].cantidad *
this.elementos[i].precio;
}
this.informacion.total = this.informacion.baseImponible * this.informacion.iva;
}

Factura.prototype.muestraTotal = function() {
this.calculaTotal();
alert("TOTAL = " + this.informacion.total + " euros");
}

// Creacin de una factura


var elCliente = new Cliente("Cliente 1", "", "", "");
var losElementos = [new Elemento("elemento1", "1", "5"),
new Elemento("elemento2", "2", "12"),
new Elemento("elemento3", "3", "42")
];
var laFactura = new Factura(elCliente, losElementos);
laFactura.muestraTotal();
</script>
</head>

<body>
</body>
</html>

14.3. Ejercicio 3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 3 - Prototype</title>
<script type="text/javascript">
// Funcion que aade elementos al final del array
Array.prototype.anadir = function(elemento) {
this[this.length] = elemento;
}

var array1 = [0, 1, 2];


array1.anadir(2);
alert(array1);

// Funcion que aade elementos al final del array y


// permite evitar aadir elementos duplicados
Array.prototype.contiene = function(elemento) {
for(var i=0; i<this.length; i++) {
// Es importante utilizar el operador === para comprobar
// que los elementos sean exactamente iguales
if(this[i] === elemento) {
return true;
}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

}
return false;
}

Array.prototype.anadir = function(elemento, permitirDuplicados) {


var permitir = (permitirDuplicados == null) ? true : permitirDuplicados;

if (!permitir) {
if(!(this.contiene(elemento))) {
this[this.length] = elemento;
}
}
else {
this[this.length] = elemento;
}
}

var array2 = [0, 1, 2];


array2.anadir(2);
alert(array2);

var array3 = [0, 1, 2];


array3.anadir(2, false);
alert(array3);
</script>
</head>

<body>
</body>
</html>

14.4. Ejercicio 4
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 4 - Prototype</title>
<script type="text/javascript">
// Funcion que trunca la longitud de una cadena
String.prototype.truncar = function(longitud) {
longitud = longitud || 10;
if(this.length > longitud) {
return this.substring(0, longitud);
}
else {
return this;
}
}

var cadena = "hola mundo";


alert(cadena.truncar(6));

// Funcion que trunca la longitud de una cadena y aade


Introduccin a AJAX Captulo 14. Ejercicios resueltos

// un indicador de cadena truncada


String.prototype.truncar = function(longitud, indicador) {
longitud = longitud || 10;
indicador = indicador || '...';

if(this.length > longitud) {


return this.substring(0, longitud-indicador.length) + indicador;
}
else {
return this;
}
}

var cadena = "En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho
tiempo que viva un hidalgo de los de lanza en astillero, adarga antigua, rocn flaco y
galgo corredor.";
alert(cadena.truncar(50, '... (sigue)'));
alert(cadena.truncar(50));
</script>
</head>

<body>
</body>
</html>

14.5. Ejercicio 5
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 5 - Prototype</title>
<script type="text/javascript">
// Devuelve un array sin los elementos que coinciden con
// el elemento que se pasa como parmetro
Array.prototype.sin = function(elemento) {
var filtrado = [];
for(var i=0; i<this.length; i++) {
// Es importante utilizar el operador !== para comprobar
// que los elementos no sean exactamente iguales
if(this[i] !== elemento) {
filtrado.push(this[i]);
}
}
return filtrado;
}

var array1 = [1, 2, 3, 4, 5];


var filtrado = array1.sin(1);
alert(filtrado);
</script>
</head>

<body>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

</body>
</html>

14.6. Ejercicio 6
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 6 - Reflexin y Prototype</title>
<script type="text/javascript">
// Determina si un objeto implementa un mtodo cuyo nombre
// se pasa como parmetro
Object.prototype.implementa = function (nombreMetodo){
return this[nombreMetodo] && this[nombreMetodo] instanceof Function;
}

var objeto1 = {
muestraMensaje: function(){
alert("hola mundo");
}
};

var objeto2 = {
a: 0,
b: 0,
suma: function() {
return this.a + this.b;
}
};

alert(objeto1.implementa("muestraMensaje"));
alert(objeto1.implementa("suma"));
alert(objeto2.implementa("muestraMensaje"));
alert(objeto2.implementa("suma"));
alert(objeto1.implementa("implementa"));
// Un objeto vaco tambin debera incluir el mtodo "implementa"
alert({}.implementa('implementa'));
</script>
</head>

<body>
</body>
</html>

14.7. Ejercicio 7
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 7 - DOM</title>
<script type="text/javascript">
Introduccin a AJAX Captulo 14. Ejercicios resueltos

window.onload = function() {
// Numero de enlaces de la pagina
var enlaces = document.getElementsByTagName("a");
alert("Numero de enlaces = "+enlaces.length);

// Direccion del penultimo enlace


var penultimo = enlaces[enlaces.length-2];
alert("El penultimo enlace apunta a: "+penultimo.getAttribute('href'));

// Numero de enlaces que apuntan a http://prueba


var contador = 0;
for(var i=0; i<enlaces.length; i++) {
if(enlaces[i].getAttribute('href') == "http://prueba") {
contador++;
}
}
alert(contador + " enlaces apuntan a http://prueba");

// Numero de enlaces del tercer prrafo


var parrafos = document.getElementsByTagName("p");
enlaces = parrafos[2].getElementsByTagName("a");
alert("Numero de enlaces del tercer prrafo = "+enlaces.length);
}
</script>
</head>

<body>
<p>Lorem ipsum dolor sit amet, <a href="http://prueba">consectetuer adipiscing
elit</a>. 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. <a href="http://prueba2">Fusce
porta</a>. 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. Donec lacus neque, vehicula in, eleifend vitae,
venenatis ac, felis. Donec arcu. Nam sed tortor nec ipsum aliquam ullamcorper. Duis
accumsan metus eu urna. Aenean vitae enim. Integer lacus. Vestibulum venenatis erat eu
odio. Praesent id metus.</p>

<p>Aenean at nisl. Maecenas egestas dapibus odio. Vestibulum ante ipsum primis in
faucibus orci luctus et ultrices posuere cubilia Curae; Proin consequat auctor diam. <a
href="http://prueba">Ut bibendum blandit est</a>. Curabitur vestibulum. Nunc malesuada
porttitor sapien. Aenean a lacus et metus venenatis porta. Suspendisse cursus, sem non
dapibus tincidunt, lorem magna porttitor felis, id sodales dolor dolor sed urna. Sed
rutrum nulla vitae tellus. Sed quis eros nec lectus tempor lacinia. Aliquam nec lectus
nec neque aliquet dictum. Etiam <a href="http://prueba3">consequat sem quis massa</a>.
Donec aliquam euismod diam. In magna massa, mattis id, pellentesque sit amet, porta sit
amet, lectus. Curabitur posuere. Aliquam in elit. Fusce condimentum, arcu in
scelerisque lobortis, ante arcu scelerisque mi, at cursus mi risus sed tellus.</p>

<p>Donec sagittis, nibh nec ullamcorper tristique, pede velit feugiat massa, at
sollicitudin justo tellus vitae justo. Vestibulum aliquet, nulla sit amet imperdiet
suscipit, nunc erat laoreet est, a <a href="http://prueba">aliquam leo odio sed
sem</a>. Quisque eget eros vehicula diam euismod tristique. Ut dui. Donec in metus sed
Introduccin a AJAX Captulo 14. Ejercicios resueltos

risus laoreet sollicitudin. Proin et nisi non arcu sodales hendrerit. In sem. Cras id
augue eu lorem dictum interdum. Donec pretium. Proin <a
href="http://prueba4">egestas</a> adipiscing ligula. Duis iaculis laoreet turpis.
Mauris mollis est sit amet diam. Curabitur hendrerit, eros quis malesuada tristique,
ipsum odio euismod tortor, a vestibulum nisl mi at odio. <a href="http://prueba5">Sed
non lectus non est pellentesque</a> auctor.</p>
</body>
</html>

14.8. Ejercicio 8
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 8 - DOM</title>

<script type="text/javascript">
window.onload = function() {
// Todos los enlaces deben cambiarse por un protocolo ms seguro: "https://"
var enlaces = document.getElementsByTagName("a");
for(var i=0; i<enlaces.length; i++) {
var href_anterior = enlaces[i].getAttribute('href');
var nuevo_href = href_anterior.replace('http://', "https://");
// Tambin se puede utilizar la funcin split()
// var trozos = href_anterior.split('://');
// var nuevo_href = 'https://' + trozos[1];
enlaces[i].setAttribute('href', nuevo_href);
}

// Los parrafos cuyo class="importante" se modifica por class="resaltado"


// y el resto de parrafos se les aade class="normal"
// Solucin al problema de setAttribute() en Internet Explorer extrada de
// http://www.digitalmediaminute.com/article/1394/
the-browser-dom-and-the-class-attribute
var nombreAtributoClass = document.all ? 'className' : 'class';

var parrafos = document.getElementsByTagName("p");


for(var i=0; i<parrafos.length; i++) {
if(parrafos[i].getAttribute(nombreAtributoClass) == 'importante') {
parrafos[i].setAttribute(nombreAtributoClass, "resaltado");
}
else {
parrafos[i].setAttribute(nombreAtributoClass, "normal");
}
}

// Enlaces cuyo class="importante", se les aade el atributo "name" con un valor


// autogenerado que sea igual a importante+i, donde i empieza en 0
var enlaces = document.getElementsByTagName("a");
var j=0;
for(var i=0; i<enlaces.length; i++) {
if(enlaces[i].getAttribute(nombreAtributoClass) == 'importante') {
enlaces[i].setAttribute('name', 'importante'+j);
Introduccin a AJAX Captulo 14. Ejercicios resueltos

j++;
}
}
}
</script>
</head>

<body>
<p>Lorem ipsum dolor sit amet, <a class="importante"
href="http://www.prueba.com">consectetuer adipiscing elit</a>. 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. <a class="importante" href="http://prueba2">Fusce
porta</a>. 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. Donec lacus neque, vehicula in, eleifend vitae,
venenatis ac, felis. Donec arcu. Nam sed tortor nec ipsum aliquam ullamcorper. Duis
accumsan metus eu urna. Aenean vitae enim. Integer lacus. Vestibulum venenatis erat eu
odio. Praesent id metus.</p>

<p class="importante">Aenean at nisl. Maecenas egestas dapibus odio. Vestibulum ante


ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin consequat
auctor diam. <a href="http://prueba">Ut bibendum blandit est</a>. Curabitur vestibulum.
Nunc malesuada porttitor sapien. Aenean a lacus et metus venenatis porta. Suspendisse
cursus, sem non dapibus tincidunt, lorem magna porttitor felis, id sodales dolor dolor
sed urna. Sed rutrum nulla vitae tellus. Sed quis eros nec lectus tempor lacinia.
Aliquam nec lectus nec neque aliquet dictum. Etiam <a href="http://prueba3">consequat
sem quis massa</a>. Donec aliquam euismod diam. In magna massa, mattis id, pellentesque
sit amet, porta sit amet, lectus. Curabitur posuere. Aliquam in elit. Fusce
condimentum, arcu in scelerisque lobortis, ante arcu scelerisque mi, at cursus mi risus
sed tellus.</p>

<p>Donec sagittis, nibh nec ullamcorper tristique, <span class="importante">pede velit


feugiat massa</span>, at sollicitudin justo tellus vitae justo. Vestibulum aliquet,
nulla sit amet imperdiet suscipit, nunc erat laoreet est, a <a
href="http://prueba">aliquam leo odio sed sem</a>. Quisque eget eros vehicula diam
euismod tristique. Ut dui. Donec in metus sed risus laoreet sollicitudin. Proin et nisi
non arcu sodales hendrerit. In sem. Cras id augue eu lorem dictum interdum. Donec
pretium. Proin <a href="http://prueba4">egestas</a> adipiscing ligula. Duis iaculis
laoreet turpis. Mauris mollis est sit amet diam. Curabitur hendrerit, eros quis
malesuada tristique, ipsum odio euismod tortor, a vestibulum nisl mi at odio. <a
class="importante" href="http://prueba5">Sed non lectus non est pellentesque</a>
auctor.</p>
</body>
</html>

14.9. Ejercicio 9
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<title>Ejercicio 9 - Crear, eliminar y modidicar nodos DOM</title>


<script type="text/javascript">
function genera() {
// Generar nmeros aleatorios entre 0 y 10
var numero1 = (Math.random()*10).toFixed();
var numero2 = (Math.random()*10).toFixed();

// Obtener los nodos padre de los prrafos


var primero = document.getElementById("primero");
var segundo = document.getElementById("segundo");

// Obtener el cada uno de los prrafos


var parrafoAnterior1 = primero.firstChild;
var parrafoAnterior2 = segundo.firstChild;

// Crear el nuevo prrafo


var parrafo1 = document.createElement("p");
var texto1 = document.createTextNode(numero1);
parrafo1.appendChild(texto1);
// Si ya exista un prrafo, sustituirlo. Si no, aadirlo
if(parrafoAnterior1 != null) {
primero.replaceChild(parrafo1, parrafoAnterior1);
}
else {
primero.appendChild(parrafo1);
}

// Crear el otro nuevo prrafo


var parrafo2 = document.createElement("p");
var texto2 = document.createTextNode(numero2);
parrafo2.appendChild(texto2);
// Si ya exista un prrafo, sustituirlo. Si no, aadirlo
if(parrafoAnterior2 != null) {
segundo.replaceChild(parrafo2, parrafoAnterior2);
}
else {
segundo.appendChild(parrafo2);
}
}

function compara() {
// Obtener los nodos padre de los prrafos
var primero = document.getElementById("primero");
var segundo = document.getElementById("segundo");

// Obtener los prrafos (existen varios mtodos...)


var parrafo1 = primero.getElementsByTagName("p")[0];
var parrafo2 = segundo.firstChild;

// Obtener los nmeros a travs del nodo Text de cada


// nodo de tipo Element de los parrafos
var numero1 = parseInt(parrafo1.firstChild.nodeValue);
var numero2 = parseInt(parrafo2.firstChild.nodeValue);

// Determinar el nodo del prrafo cuyo nodo es mayor


Introduccin a AJAX Captulo 14. Ejercicios resueltos

var parrafoMayor = (numero1 > numero2)? parrafo1 : parrafo2;

// Obtener el nodo padre del prrafo resultado


var resultado = document.getElementById("resultado");

var parrafoAnterior = resultado.firstChild;


// Si ya exista un prrafo de resultado anterior, sustituirlo. Si no, aadirlo
if(parrafoAnterior != null) {
resultado.replaceChild(parrafoMayor, parrafoAnterior);
}
else {
resultado.appendChild(parrafoMayor);
}
}
</script>

<style type="text/css">
#primero, #segundo, #resultado {width: 150px; height: 150px; border: thin solid silver;
background: #F5F5F5; float: left; margin:20px; font-size: 6em; color: #333; text-align:
center; padding: 5px; font-family:Arial, Helvetica, sans-serif;}
#primero p, #segundo p, #resultado p {margin:.2em 0;}
#resultado {margin-left:1.3em; border-color: black;}
.clear {clear:both;}
#compara {margin-left:11em;}
#genera {font-size:1.2em; margin-left:8em;}
</style>
</head>

<body>

<input id="genera" type="button" value=" Genera !!" onclick="genera()" />

<div id="primero"></div>

<div id="segundo"></div>

<div class="clear"></div>

<input id="compara" type="button" value="<< Comparar >>" onclick="compara()" />

<div id="resultado"></div>

</body>
</html>

14.10. Ejercicio 10
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 10 - DOM bsico y atributos XHTML</title>

<script type="text/javascript">
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function muestraOculta() {
// Obtener el ID del elemento
var id = this.id;
id = id.split('_');
id = id[1];

var elemento = document.getElementById('contenidos_'+id);


var enlace = document.getElementById('enlace_'+id);

if(elemento.style.display == "" || elemento.style.display == "block") {


elemento.style.display = "none";
enlace.innerHTML = 'Mostrar contenidos';
}
else {
elemento.style.display = "block";
enlace.innerHTML = 'Ocultar contenidos';
}
}

window.onload = function()
{ document.getElementById('enlace_1').onclick =
muestraOculta; document.getElementById('enlace_2').onclick =
muestraOculta;
document.getElementById('enlace_3').onclick = muestraOculta;
}
</script>
</head>

<body>

<p id="contenidos_1">[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">[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">[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
Introduccin a AJAX Captulo 14. Ejercicios resueltos

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>
</html>

14.11. Ejercicio 11
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ejercicio 11 - Estados de la peticin AJAX</title>
<style type="text/css">
body { font: 13px Arial, Helvetica, sans-serif; }
h2 { margin-bottom: 0; font-size: 1.2em; }
#recurso, #enviar { padding: .3em; font-size: 1.2em; }
#principal { float: left; width: 70%; }
#secundario { float: right; width: 25%; }
#contenidos, #estados, #cabeceras, #codigo {
border: 2px solid #CCC;
background: #FAFAFA;
padding: 1em;
white-space: pre;
}
#contenidos {
min-height: 400px;
max-height: 600px;
overflow: scroll;
}
#estados { min-height: 200px; }
#cabeceras { min-height: 200px; }
#codigo { min-height: 100px; font-size: 1.5em; }
</style>
<script type="text/javascript">
String.prototype.transformaCaracteresEspeciales = function() {
return unescape(escape(this). replace(/
%0A/g, '<br/>').
replace(/%3C/g, '&lt;').
replace(/%3E/g, '&gt;'));
}

var estadosPosibles = ['No inicializado', 'Cargando', 'Cargado', 'Interactivo',


'Completado'];
var tiempoInicial = 0;

window.onload = function() {
// Cargar en el input text la URL de la pgina
var recurso = document.getElementById('recurso');
recurso.value = location.href;
Introduccin a AJAX Captulo 14. Ejercicios resueltos

// Cargar el recurso solicitado cuando se pulse el botn MOSTRAR CONTENIDOS


document.getElementById('enviar').onclick = cargaContenido;
}

function cargaContenido() {
// Borrar datos anteriores
document.getElementById('contenidos').innerHTML = "";
document.getElementById('estados').innerHTML = "";

// Instanciar objeto XMLHttpRequest


if(window.XMLHttpRequest) {
peticion = new XMLHttpRequest();
}
else {
peticion = new ActiveXObject("Microsoft.XMLHTTP");
}

// Preparar funcin de respuesta


peticion.onreadystatechange = muestraContenido;

// Realizar peticin
tiempoInicial = new Date();
var recurso = document.getElementById('recurso').value;
peticion.open('GET', recurso+'?nocache='+Math.random(), true);
peticion.send(null);
}

// Funcin de respuesta
function muestraContenido() {
var tiempoFinal = new Date();
var milisegundos = tiempoFinal - tiempoInicial;

var estados = document.getElementById('estados');


estados.innerHTML += "[" + milisegundos + " mseg.] " +
estadosPosibles[peticion.readyState] + "<br/>";

if(peticion.readyState == 4) {
if(peticion.status == 200) {
var contenidos = document.getElementById('contenidos');
contenidos.innerHTML = peticion.responseText.transformaCaracteresEspeciales();
} muestraCabeceras();
muestraCodigoEstado();
}
}

function muestraCabeceras() {
var cabeceras = document.getElementById('cabeceras');
cabeceras.innerHTML =
peticion.getAllResponseHeaders().transformaCaracteresEspeciales();
}

function muestraCodigoEstado() {
var codigo = document.getElementById('codigo');
Introduccin a AJAX Captulo 14. Ejercicios resueltos

codigo.innerHTML = peticion.status + "<br/>" + peticion.statusText;


}
</script>
</head>
<body>
<form action="#">
URL: <input type="text" id="recurso" size="70" />
<input type="button" id="enviar" value="Mostrar contenidos" />
</form>

<div id="principal">
<h2>Contenidos del archivo:</h2>
<div id="contenidos"></div>

<h2>Cabeceras HTTP de la respuesta del servidor:</h2>


<div id="cabeceras"></div>
</div>

<div id="secundario">
<h2>Estados de la peticin:</h2>
<div id="estados"></div>

<h2>Cdigo de estado:</h2>
<div id="codigo"></div>
</div>
</body>
</html>

14.12. Ejercicio 12
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/
strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ejercicio 12 - Actualizacin peridica de contenidos</title>
<style type="text/css">
body { margin: 0; }
#contenidos { padding: 1em; }
#ticker
{ height:
20px; padding:
.3em;
border-bottom: 1px solid #CCC;
background: #FAFAFA;
font-family: Arial, Helvetica, sans-serif;
}
#ticker strong { margin-right: 1em; }
#acciones {
position: absolute;
top: 3px;
right: 3px;
}
</style>
<script type="text/javascript">
Number.prototype.toString = function(){
Introduccin a AJAX Captulo 14. Ejercicios resueltos

if (this < 10) {


return '0' + this;
}
else {
return this;
}
}

var peticion = null;


var intervalo = null;
var noticias = [];
var numeroElemento = null;

window.onload = function(){
intervalo = setInterval(descargaNoticia, 1000);
document.getElementById('detener').onclick = detener;
document.getElementById('anterior').onclick = anterior;
document.getElementById('siguiente').onclick = siguiente;
}

function descargaNoticia(){
if (peticion == null) {
if (window.XMLHttpRequest) {
peticion = new XMLHttpRequest();
}
else {
peticion = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else {
peticion.abort();
}

peticion.onreadystatechange = procesaNoticia;

peticion.open('GET', 'http://localhost/RUTA_HASTA_ARCHIVO/
generaContenidos.php'+'?nocache='+Math.random(), true);
peticion.send(null);
}

function procesaNoticia(){
if (peticion.readyState == 4) {
if (peticion.status == 200) {
var fechaHora = new Date();
var hora = fechaHora.getHours().toString() + ":" +
fechaHora.getMinutes().toString() + ":" + fechaHora.getSeconds().toString();
noticias.push({
hora: hora,
titular: peticion.responseText
});
muestraNoticia(noticias[noticias.length - 1]);
}
}
}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function detener()
{ clearInterval(intervalo
); this.value =
'Iniciar';
this.onclick = iniciar;
}

function iniciar(){
intervalo = setInterval(descargaNoticia, 1000);
this.value = 'Detener';
this.onclick = detener;

numeroElemento = null;
}

function anterior(){
var detener = document.getElementById('detener');
clearInterval(intervalo);
detener.value = 'Iniciar';
detener.onclick = iniciar;

if (numeroElemento == null) {
numeroElemento = noticias.length - 1;
}

if (numeroElemento > 0) {
numeroElemento--;
}

var noticia = noticias[numeroElemento];


muestraNoticia(noticia);
}

function siguiente(){
var detener = document.getElementById('detener');
clearInterval(intervalo);
detener.value = 'Iniciar';
detener.onclick = iniciar;

if (numeroElemento == null) {
numeroElemento = noticias.length - 1;
}

if (numeroElemento < noticias.length - 1) {


numeroElemento++;
}

var noticia = noticias[numeroElemento];


muestraNoticia(noticia);
}

function muestraNoticia(noticia){
var ticker = document.getElementById('ticker');
ticker.innerHTML = "<strong>" + noticia.hora + "</strong> " + noticia.titular;
ticker.style.backgroundColor = '#FFFF99';
setTimeout(limpiaTicker, 300);
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function limpiaTicker(){
var ticker = document.getElementById('ticker');
ticker.style.backgroundColor = '#FAFAFA';
}
</script>
</head>
<body>
<div id="ticker"></div>

<div id="acciones">
<input type="button" id="detener" value="Detener"/>
<input type="button" id="anterior" value="&laquo; Anterior" />
<input type="button" id="siguiente" value="Siguiente &raquo;" />
</div>

<div id="contenidos">
<h1>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</h1>
<p>Proin tristique condimentum sem. Fusce lorem sem, laoreet nec, laoreet et, venenatis
nec, ligula.
Nunc dictum sodales lorem. Fusce turpis. Nullam semper, ipsum ut ultrices mattis, nulla
magna luctus
purus, sit amet vehicula magna magna vel velit.</p>

<h2>Morbi a lacus. Proin pharetra nisi id est.</h2>

<p>Maecenas mollis suscipit sapien. Pellentesque blandit dui eu mauris. Etiam elit
urna, iaculis non,
dignissim in, fermentum nec, ipsum. Nulla commodo aliquam lectus. Sed vulputate diam ac
sapien accumsan
consequat. Aliquam id urna sed dolor tincidunt tempor.</p>

<h2>Quisque consequat. Nullam vel justo.</h2>

<p>Cras sit amet elit a mauris ultricies viverra. Phasellus placerat quam et magna.
Nunc sed tellus.
Pellentesque hendrerit pellentesque nunc. Aenean turpis. Sed justo tellus, mollis at,
euismod at,
pellentesque eu, tellus. Nam vulputate. Nunc porttitor sapien tristique velit.
Vestibulum tempus,
quam non dapibus pellentesque, sem nulla sagittis ligula, et volutpat turpis felis
vitae nunc.</p>

<p>Ut eros magna, congue in, sodales ac, facilisis ac, dolor. Aenean faucibus
pellentesque est. Proin
cursus. Vivamus mollis enim in magna. Donec urna risus, convallis eget, aliquet non,
auctor sit amet, leo.
Duis tellus purus, pharetra in, cursus sed, posuere semper, lorem. Fusce eget velit nec
felis tempus
gravida. Donec et augue vitae nulla posuere hendrerit. Nulla vehicula scelerisque
massa. Phasellus eget
lorem id quam molestie ultrices. Integer ac ligula sit amet lectus condimentum euismod.
Sed malesuada
orci eu neque.</p>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

</div>
</body>
</html>

14.13. Ejercicio 13
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 13 - Comprobar disponibilidad del login</title>

<script type="text/javascript">
var READY_STATE_COMPLETE=4;
var peticion_http = null;

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function comprobar() {
var login = document.getElementById("login").value;
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/ajax/compruebaDisponibilidad.php",
true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send("login="+login+"&nocache="+Math.random());
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if (peticion_http.status == 200) {
var login = document.getElementById("login").value;
if(peticion_http.responseText == "si") {
document.getElementById("disponibilidad").innerHTML = "El nombre elegido
["+login+"] est disponible";
}
else {
document.getElementById("disponibilidad").innerHTML = "NO est disponible el
nombre elegido ["+login+"]";
}
}
}
}

window.onload = function() {
Introduccin a AJAX Captulo 14. Ejercicios resueltos

document.getElementById("comprobar").onclick = comprobar;
}

</script>
</head>

<body>
<h1>Comprobar disponibilidad del login</h1>
<form>
<label for="login">Nombre de usuario:</label>
<input type="text" name="login" id="login" />
<a id="comprobar" href="#">Comprobar disponibilidad...</a>
</form>

<div id="disponibilidad"></div>

</body>
</html>

14.14. Ejercicio 14
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 14 - Comprobar disponibilidad del login y mostrar alternativas</title>
<script type="text/javascript">
var READY_STATE_COMPLETE=4;
var peticion_http = null;

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function comprobar() {
var login = document.getElementById("login").value;
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/ajax/compruebaDisponibilidadXML.php",
true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send("login="+login+"&nocache="+Math.random());
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if (peticion_http.status == 200) {
Introduccin a AJAX Captulo 14. Ejercicios resueltos

var login = document.getElementById("login").value;


var documento_xml = peticion_http.responseXML;
var raiz = documento_xml.getElementsByTagName("respuesta")[0];

var disponible = raiz.getElementsByTagName("disponible")[0].firstChild.nodeValue;

if(disponible == "si") {
document.getElementById("disponibilidad").innerHTML = "El nombre elegido
["+login+"] est disponible";
}
else {
var mensaje = "NO est disponible el nombre elegido ["+login+"]. Puedes probar
con las siguientes alternativas.";
var alternativas = raiz.getElementsByTagName("alternativas")[0];
var logins = alternativas.getElementsByTagName("login");
mensaje += "<ul>";
for(var i=0; i<logins.length; i++) {
mensaje += "<li><a href=\"#\"
onclick=\"selecciona('"+logins[i].firstChild.nodeValue+"'); return
false\">"+logins[i].firstChild.nodeValue+"<\/a><\/li>";
}
mensaje += "<\/ul>";
document.getElementById("disponibilidad").innerHTML = mensaje;
}
}
}
}

function selecciona(login) {
var cuadroLogin = document.getElementById("login");
cuadroLogin.value = login;
}

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

</script>
</head>

<body>
<h1>Comprobar disponibilidad del login y mostrar alternativas</h1>
<form>
<label for="login">Nombre de usuario:</label>
<input type="text" name="login" id="login" />
<a id="comprobar" href="#">Comprobar disponibilidad...</a>
</form>
<div id="disponibilidad"></div>
</body>
</html>

14.15. Ejercicio 15
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 15 - Comprobar disponibilidad del login y mostrar alternativas</title>
<script type="text/javascript">
var READY_STATE_COMPLETE=4;
var peticion_http = null;

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function comprobar() {
var login = document.getElementById("login").value;
peticion_http = inicializa_xhr();
if(peticion_http) {
peticion_http.onreadystatechange = procesaRespuesta;
peticion_http.open("POST", "http://localhost/ajax/compruebaDisponibilidadJSON.php",
true);

peticion_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion_http.send("login="+login+"&nocache="+Math.random());
}
}

function procesaRespuesta() {
if(peticion_http.readyState == READY_STATE_COMPLETE) {
if (peticion_http.status == 200) {
var login = document.getElementById("login").value;
var respuesta_json = peticion_http.responseText;
var respuesta = eval("("+respuesta_json+")");

if(respuesta.disponible == "si") {
document.getElementById("disponibilidad").innerHTML = "El nombre elegido
["+login+"] est disponible";
}
else {
var mensaje = "NO est disponible el nombre elegido ["+login+"]. Puedes probar
con las siguientes alternativas.";
mensaje += "<ul>";
for(var i in respuesta.alternativas) {
mensaje += "<li><a href=\"#\"
onclick=\"selecciona('"+respuesta.alternativas[i]+"'); return
false\">"+respuesta.alternativas[i]+"<\/a><\/li>";
}
mensaje += "<\/ul>";
document.getElementById("disponibilidad").innerHTML = mensaje;
}
}
}
}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function selecciona(login) {
var cuadroLogin = document.getElementById("login");
cuadroLogin.value = login;
}

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

</script>
</head>

<body>
<h1>Comprobar disponibilidad del login y mostrar alternativas</h1>
<form>
<label for="login">Nombre de usuario:</label>
<input type="text" name="login" id="login" />
<a id="comprobar" href="#">Comprobar disponibilidad...</a>
</form>
<div id="disponibilidad"></div>
</body>
</html>

14.16. Ejercicio 16
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 16 - Listas desplegables encadenadas</title>

<script type="text/javascript">
var peticion = null;

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function muestraProvincias() {
if (peticion.readyState == 4) {
if (peticion.status == 200) {
var lista = document.getElementById("provincia");
var documento_xml = peticion.responseXML;

var provincias = documento_xml.getElementsByTagName("provincias")[0];


var lasProvincias = provincias.getElementsByTagName("provincia");
lista.options[0] = new Option("- selecciona -");

// Mtodo 1: Crear elementos Option() y aadirlos a la lista


Introduccin a AJAX Captulo 14. Ejercicios resueltos

for(i=0; i<lasProvincias.length; i++) {


var codigo =
lasProvincias[i].getElementsByTagName("codigo")[0].firstChild.nodeValue;
var nombre =
lasProvincias[i].getElementsByTagName("nombre")[0].firstChild.nodeValue;
lista.options[i+1] = new Option(nombre, codigo);
}

// Mtodo 2: crear el cdigo HTML de <option value="">...</option> y utilizar el


innerHTML de la lista

/*
var codigo_html = "";
codigo_html += "<option>- selecciona -<\/option>";
for(var i=0; i<lasProvincias.length; i++) {
var codigo =
lasProvincias[i].getElementsByTagName("codigo")[0].firstChild.nodeValue;
var nombre =
lasProvincias[i].getElementsByTagName("nombre")[0].firstChild.nodeValue;
codigo_html += "<option value=\""+codigo+"\">"+nombre+"<\/option>";
}

// La separacion siguiente se tiene que hacer por este bug de microsoft:


// http://support.microsoft.com/default.aspx?scid=kb;en-us;276228
var esIE = navigator.userAgent.toLowerCase().indexOf('msie')!=-1;
if(esIE) {
document.getElementById("provincia").outerHTML = "<select
id=\"provincia\">"+codigo_html+"</select>";
}
else {
document.getElementById("provincia").innerHTML = codigo_html;
}
*/
}
}
}

function cargaMunicipios() {
var lista = document.getElementById("provincia");
var provincia = lista.options[lista.selectedIndex].value;
if(!isNaN(provincia))
{ peticion =
inicializa_xhr(); if
(peticion) {
peticion.onreadystatechange = muestraMunicipios;
peticion.open("POST", "http://localhost/RUTA_HASTA_ARCHIVO/
cargaMunicipiosXML.php?nocache=" + Math.random(), true);
peticion.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion.send("provincia=" + provincia);
}
}
}

function muestraMunicipios() {
if (peticion.readyState == 4) {
if (peticion.status == 200) {
Introduccin a AJAX Captulo 14. Ejercicios resueltos

var lista = document.getElementById("municipio");


var documento_xml = peticion.responseXML;

var municipios = documento_xml.getElementsByTagName("municipios")[0];


var losMunicipios = municipios.getElementsByTagName("municipio");

// Borrar elementos anteriores


lista.options.length = 0;

// Se utiliza el mtodo de crear elementos Option() y aadirlos a la lista


for(i=0; i<losMunicipios.length; i++) {
var codigo =
losMunicipios[i].getElementsByTagName("codigo")[0].firstChild.nodeValue;
var nombre =
losMunicipios[i].getElementsByTagName("nombre")[0].firstChild.nodeValue;
lista.options[i] = new Option(nombre, codigo);
}
}
}
}

window.onload = function()
{ peticion =
inicializa_xhr();
if(peticion) {
peticion.onreadystatechange = muestraProvincias;
peticion.open("GET", "http://localhost/RUTA_HASTA_ARCHIVO/
cargaProvinciasXML.php?nocache="+Math.random(), true);
peticion.send(null);
}

document.getElementById("provincia").onchange = cargaMunicipios;
}

</script>
</head>

<body>
<h1>Listas desplegables encadenadas</h1>

<form>
<label for="provincia">Provincia</label>
<select id="provincia">
<option>Cargando...</option>
</select>
<br/><br/>
<label for="municipio">Municipio</label>
<select id="municipio">
<option>- selecciona una provincia -</option>
</select>
</form>

</body>
</html>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

14.17. Ejercicio 17
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 17 - Listas desplegables encadenadas</title>

<script type="text/javascript">
var peticion = null;

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function muestraProvincias() {
if (peticion.readyState == 4) {
if (peticion.status == 200) {
var lista = document.getElementById("provincia");
var provincias = eval('(' + peticion.responseText + ')');

lista.options[0] = new Option("- selecciona -");


var i=1;
for(var codigo in provincias) {
lista.options[i] = new Option(provincias[codigo], codigo);
i++;
}
}
}
}

function cargaMunicipios() {
var lista = document.getElementById("provincia");
var provincia = lista.options[lista.selectedIndex].value;
if(!isNaN(provincia))
{ peticion =
inicializa_xhr(); if
(peticion) {
peticion.onreadystatechange = muestraMunicipios;
peticion.open("POST", "http://localhost/RUTA_HASTA_ARCHIVO/
cargaMunicipiosJSON.php?nocache=" + Math.random(), true);
peticion.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion.send("provincia=" + provincia);
}
}
}

function muestraMunicipios() {
if (peticion.readyState == 4) {
if (peticion.status == 200) {
var lista = document.getElementById("municipio");
Introduccin a AJAX Captulo 14. Ejercicios resueltos

var municipios = eval('(' + peticion.responseText + ')');

lista.options.length = 0;
var i=0;
for(var codigo in municipios) {
lista.options[i] = new Option(municipios[codigo], codigo);
i++;
}
}
}
}

window.onload = function()
{ peticion =
inicializa_xhr();
if(peticion) {
peticion.onreadystatechange = muestraProvincias;
peticion.open("GET", "http://localhost/RUTA_HASTA_ARCHIVO/
cargaProvinciasJSON.php?nocache="+Math.random(), true);
peticion.send(null);
}

document.getElementById("provincia").onchange = cargaMunicipios;
}

</script>
</head>

<body>
<h1>Listas desplegables encadenadas</h1>

<form>
<label for="provincia">Provincia</label>
<select id="provincia">
<option>Cargando...</option>
</select>
<br/><br/>
<label for="municipio">Municipio</label>
<select id="municipio">
<option>- selecciona una provincia -</option>
</select>
</form>

</body>
</html>

14.18. Ejercicio 18
El rchivo util.js que utiliz el ejercicio se incluye en el rchivo ZIP de l solucio n complet.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">

<head>
Introduccin a AJAX
<meta http-equiv="Content-Type" Captulo 14. Ejercicios resueltos
content="text/html; charset=ISO-8859-1">
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<title>Ejercicio 18 - Teclado virtual</title>

<style type="text/css" media="screen">


body, html { padding:0; margin:0; }
p { font-family:verdana,tahoma,arial,helvetica,sans-serif; font-size:13px;
margin-left:10px; }
#keyboard {
padding:30px 8px 8px 8px;
margin:5px 0 0 0;
height:300px;
width:1000px;
background-color:#eee;
border-top:3px solid #ccc;
border-right:3px solid #aaa;
border-bottom:5px solid #888;
border-left:3px solid #bbb;
}
kbd, .tecla {
font-family:verdana,tahoma,arial,helvetica,sans-serif;
font-size:13px;
border-top:2px solid #ccc;
border-right:5px solid #aaa;
border-bottom:9px solid #888;
border-left:5px solid #bbb;
padding:3px 6px 3px 6px;
white-space:nowrap;
color:#000;
background:#eee;
width:22px;
height:30px;
float:left;
overflow:hidden;
cursor: pointer; cursor: hand;
}
.delete { padding:3px 8px 3px 4px; }
img { margin-top:2px; }
.narrow, .lock { font-family:arial,helvetica,sans-serif; font-size:9px; }
#keyboard div, .clear { clear:both; margin:0; }
.fontgap { margin-left:10px; }
.rightgap { margin-right:12px; }
#esc, #f4, #f8 { margin-right:30px; }
#row1 { margin-bottom:12px; width:990px; height:50px; }
.tab { width:48px; }
.capslock { width:62px; }
.shift-right { width:98px; margin-right:56px; }
.backspace { width:68px; }
.spacebar { width:234px; }
.numpad-0 { width:66px; }
.shift-left, #ctrl-left, #ctrl-right, #windows-left, #windows-right, #alt-left,
.alt-right, #application { width:36px; }
.enter-top { border-bottom:0; height:39px; width:42px; }
#enter-bottom { border-top:0; height:32px; width:28px; margin-right:156px; }
.numpad-top { border-bottom:0; height:10px; padding-top:32px;}
.numpad-bottom { border-top:0; height:32px; }
#arrow-up {margin-right:56px;}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

#sysreq, #break { font-family:'arial narrow'; font-size:10px; position:absolute;


top:72px; left:696px; z-index:2; }
#break {left:785px;}
.lock { margin-left:30px; margin-top:25px; float:left;}
#enter-edge { position:absolute; top:183px; left:609px; z-index:2; }
#led-active, #led2, #led3 {
position:absolute;
top:40px;
left:850px;
width:6px;
height:6px;
margin-left:5px;
border-top:2px solid #888;
border-right:2px solid #bbb;
border-bottom:2px solid #ccc;
border-left:2px solid #aaa;
background-color:#6f0;
}
#led2 {left:900px; background-color:#060;}
#led3 {left:950px; background-color:#060;}
.pulsada { background: #FFFF99; border-top-width:5px; border-bottom-width: 6px;}
.enter-top.pulsada {border-bottom: none; border-top-width:2px;}
#contenido, #contenidoGuardado { margin: 10px; background-color: #ededed; border: 2px
solid #a0a0a0; padding: 1em;}
</style>
<script src="util.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
var teclados = {};
var tecladoActivo = null;
var teclasPulsadas = [];
var teclasEspeciales = ["borrado", "tabulador", "enter", "espaciadora", "mayusculas",
"shift_izquierdo", "shift_derecho", "altgr"];
var tecladoIdioma = null;
var tecladoVariante = null;
var estado = {mayusculas: false, shift: false, altgr: false};

function descargaTeclado(idioma) {
var cargador = new net.CargadorContenidosCompleto("http://localhost/
RUTA_HASTA_EL_ARCHIVO/tecladoVirtual.php?nocache="+Math.random(),
function() { teclados[idioma] =
eval('('+this.req.responseText+')'); },
null,
"POST",
"accion=cargaTeclado&idioma="+idioma,
"application/x-www-form-urlencoded",
false);
}

function cargaTeclado() {
// Obtener o descargar el teclado requerido
if(teclados[tecladoIdioma] == null) {
descargaTeclado(tecladoIdioma);
}
var teclado = teclados[tecladoIdioma][tecladoVariante];
Introduccin a AJAX Captulo 14. Ejercicios resueltos

// Cargar teclas normales y aadir el evento a cada una


for(var i=0; i<teclado.length; i++) {
if(teclado[i] != undefined)
{ document.getElementById('tecla_'+i).innerHTML =
teclado[i]; document.getElementById('tecla_'+i).onclick =
pulsaTecla;
}
else {
document.getElementById('tecla_'+i).innerHTML = '';
}
}

// Aadir eventos a las teclas especiales


for(var i=0; i<teclasEspeciales.length; i++) {
document.getElementById('tecla_especial_'+teclasEspeciales[i]).onclick =
pulsaTeclaEspecial;
}

tecladoActivo = teclado;
}

function pulsaTecla() {
var teclaPulsada = this.id.replace(/tecla_/gi, "");
var caracter = tecladoActivo[teclaPulsada];

teclasPulsadas.push(caracter);

// Iluminar la tecla pulsada


this.className+=" pulsada";
setTimeout(apagaTecla, 100);

mostrarContenidos();
}

function apagaTecla() {
for(var i in tecladoActivo) {
if(tecladoActivo[i]) {
document.getElementById('tecla_'+i).className =
document.getElementById('tecla_'+i).className.replace(/pulsada/ig, "");
}
}
for(var i in teclasEspeciales) {
if(teclasEspeciales[i]) {
document.getElementById('tecla_especial_'+teclasEspeciales[i]).className =
document.getElementById('tecla_especial_'+teclasEspeciales[i]).className.replace(/pulsada/
ig, "");
}
}
}

function pulsaTeclaEspecial() {
var teclaPulsada = this.id.replace(/tecla_especial_/gi, "");

// Iluminar la tecla pulsada


this.className+=" pulsada";
setTimeout(apagaTecla, 100);
Introduccin a AJAX Captulo 14. Ejercicios resueltos

switch(teclaPulsada) {
case 'borrado':
teclasPulsadas.pop();
break;
case 'tabulador':
teclasPulsadas.push('\t');
break;
case 'enter':
teclasPulsadas.push('\n');
break;
case 'espaciadora':
teclasPulsadas.push(' ');
break;
case 'mayusculas':
cargaVarianteTeclado('mayusculas');
break;
case 'shift_izquierdo':
cargaVarianteTeclado('shift_izquierdo');
break;
case 'shift_derecho':
cargaVarianteTeclado('shift_derecho');
break;
case 'altgr':
cargaVarianteTeclado('altgr');
break;
}

mostrarContenidos();
}

function cargaVarianteTeclado(variante) {
var nombreVariante = {mayusculas: 'caps', shift_izquierdo: 'shift', shift_derecho:
'shift', altgr: 'altgr'};

if(estado[variante] == true) {
estado[variante] = false;
tecladoVariante = 'normal';
}
else {
estado[variante] = true;
tecladoVariante = nombreVariante[variante];
}
cargaTeclado();
}

function mostrarContenidos(texto, zona) {


var elemento = zona || "contenido";
var contenido = texto || teclasPulsadas.join("");

contenido = contenido.replace(/\n/gi, '<br/>');


contenido = contenido.replace(/\t/gi, '&nbsp;&nbsp;&nbsp;&nbsp;');
contenido = contenido.replace(/ /gi, '&nbsp;');

document.getElementById(elemento).innerHTML = contenido;
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function muestraIdiomas() {
var respuesta = eval('('+this.req.responseText+')');
var lista = document.getElementById("idiomas");

var i=0;
for(var codigo in respuesta.idiomas) {
// Aadir idiomas a la lista desplegable
lista.options[i] = new Option(respuesta.idiomas[codigo], codigo);
i++;
// Crear los objetos que almacenan los teclados de cada idioma
teclados[codigo] = null;
}

// Cargar el teclado del idioma por defecto (la variante normal)


tecladoIdioma = respuesta.defecto;
tecladoVariante = 'normal';
cargaTeclado();
}

function cambiaIdioma() {
var lista = document.getElementById("idiomas");
tecladoIdioma = lista.options[lista.selectedIndex].value;
cargaTeclado();
}

function guarda() {
var cargador = new net.CargadorContenidosCompleto("http://localhost/
RUTA_HASTA_EL_ARCHIVO/tecladoVirtual.php?nocache="+Math.random(),
function() {
mostrarContenidos(unescape(this.req.responseText), "contenidoGuardado"); },
null,
"POST",

"accion=guardar&contenido="+escape(teclasPulsadas.join("")),
"application/x-www-form-urlencoded");
}

window.onload = function() {
var cargador = new net.CargadorContenidosCompleto("http://localhost/
RUTA_HASTA_EL_ARCHIVO/tecladoVirtual.php?nocache="+Math.random(),
muestraIdiomas,
null,
"POST",
"accion=listaIdiomas",
"application/x-www-form-urlencoded");

// Evento necesario para cambiar el idioma del teclado


document.getElementById("idiomas").onchange = cambiaIdioma;

setInterval(guarda, 30 * 1000);
}

/*
Introduccin a AJAX Captulo 14. Ejercicios resueltos

Los teclados de cada idioma y algunas ideas de implementacin son originales del
JavaScript Virtual Keyboard, cuya nota de copyright
se incluye a continuacin:
*/
/*
* JavaScript Virtual Keyboard, version 2.2
*
* Copyright (C) 2006-2007 Dmitriy Khudorozhkov
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the author be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* - Dmitriy Khudorozhkov, kh_dmitry2001@mail.ru
*/

/*
El diseo del teclado es obra de Chris Hester y se puede descargar desde
http://www.designdetector.com/archives/05/03/KeyboardDemo.php
*/

</script>

</head>

<body>

<div id="led-active">&nbsp;</div>
<div id="led2">&nbsp;</div>
<div id="led3">&nbsp;</div>

<div id="keyboard">

<div id="row1">
<kbd id="esc">Esc</kbd><kbd>F1</kbd><kbd>F2</kbd><kbd>F3</kbd><kbd id="f4">F4</kbd>
<kbd>F5</kbd><kbd>F6</kbd><kbd>F7</kbd><kbd
id="f8">F8</kbd><kbd>F9</kbd><kbd>F10</kbd>
<kbd>F11</kbd><kbd class="rightgap">F12</kbd><kbd class="narrow">Impr<br>Pant</kbd>
<kbd class="narrow">Bloq<br>Des</kbd><kbd class="narrow">Pausa</kbd>
<span class="lock">Bloq<br>Num</span><span class="lock">Bloq<br>Mayus</span>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<span class="lock">Bloq<br>Des</span>
</div>

<div id="row2">
<kbd id="tecla_0"></kbd><kbd id="tecla_1"></kbd><kbd id="tecla_2"></kbd>
<kbd id="tecla_3"></kbd><kbd id="tecla_4"></kbd><kbd id="tecla_5"></kbd>
<kbd id="tecla_6"></kbd><kbd id="tecla_7"></kbd><kbd id="tecla_8"></kbd>
<kbd id="tecla_9"></kbd><kbd id="tecla_10"></kbd><kbd id="tecla_11"></kbd>
<kbd id="tecla_12"></kbd>
<kbd id="tecla_especial_borrado" class="rightgap backspace"><img src="imagenes/
backspace.gif" alt="" height="19" width="52"></kbd>
<kbd class="narrow">Insert</kbd><kbd class="narrow">Inicio</kbd><kbd class="narrow
rightgap">Re<br>Pag</kbd>
<kbd class="narrow">Bloq<br>Num</kbd><kbd>/</kbd><kbd>*</kbd><kbd>-</kbd>
</div>

<div>
<kbd id="tecla_especial_tabulador" class="tab"><img src="imagenes/tab.gif" alt=""
height="27" width="23"></kbd>
<kbd id="tecla_13"></kbd><kbd id="tecla_14"></kbd><kbd id="tecla_15"></kbd><kbd
id="tecla_16"></kbd>
<kbd id="tecla_17"></kbd><kbd id="tecla_18"></kbd><kbd id="tecla_19"></kbd><kbd
id="tecla_20"></kbd>
<kbd id="tecla_21"></kbd><kbd id="tecla_22"></kbd><kbd id="tecla_23"></kbd><kbd
id="tecla_24"></kbd>
<kbd id="tecla_especial_enter" class="rightgap enter-top"><img src="imagenes/
enter.gif" alt="" height="24" width="24"></kbd>
<kbd class="narrow delete">Supr</kbd><kbd class="narrow">Fin</kbd><kbd class="narrow
rightgap">Av<br>Pag</kbd>
<kbd>7<br><span class="narrow">Inicio</span></kbd><kbd>8<br><img src="imagenes/
arrow-up-small.gif" alt="" height="13" width="21"></kbd>
<kbd>9<br><span class="narrow">RePag</span></kbd><kbd class="numpad-top">+</kbd>
</div>

<div>
<kbd id="tecla_especial_mayusculas" class="narrow capslock">Bloq Mayus</kbd>
<kbd id="tecla_25"></kbd><kbd id="tecla_26"></kbd><kbd id="tecla_27"></kbd><kbd
id="tecla_28"></kbd>
<kbd id="tecla_29"></kbd><kbd id="tecla_30"></kbd><kbd id="tecla_31"></kbd><kbd
id="tecla_32"></kbd>
<kbd id="tecla_33"></kbd><kbd id="tecla_34"></kbd><kbd id="tecla_35"></kbd><kbd
id="tecla_36"></kbd>
<kbd id="enter-bottom">&nbsp;</kbd><kbd>4<br><img src="imagenes/arrow-left-small.gif"
alt="" height="7" width="13"></kbd>
<kbd>5</kbd><kbd>6<br><img src="imagenes/arrow-right-small.gif" alt="" height="7"
width="13"></kbd>
<kbd class="numpad-bottom">&nbsp;</kbd>
</div>

<div>
<kbd id="tecla_especial_shift_izquierdo" class="narrow shift-left"><img src="imagenes/
shift.gif" alt="" height="20" width="17"></kbd>
<kbd>&gt;<br>&lt;</kbd><kbd id="tecla_37"></kbd><kbd id="tecla_38"></kbd><kbd
id="tecla_39"></kbd>
<kbd id="tecla_40"></kbd><kbd id="tecla_41"></kbd><kbd id="tecla_42"></kbd><kbd
Introduccin a AJAX Captulo 14. Ejercicios resueltos

id="tecla_43"></kbd>
<kbd id="tecla_44"></kbd><kbd id="tecla_45"></kbd><kbd id="tecla_46"></kbd>
<kbd id="tecla_especial_shift_derecho" class="shift-right"><img src="imagenes/
shift.gif" alt="" height="20" width="17"></kbd>
<kbd id="arrow-up"><img src="imagenes/arrow-up.gif" alt="" height="22"
width="21"></kbd>
<kbd>1<br><span class="narrow">Fin</span></kbd>
<kbd>2<br><img src="imagenes/arrow-down-small.gif" alt="" height="13"
width="21"></kbd>
<kbd>3<br><span class="narrow">AvPag</span></kbd>
<kbd class="numpad-top narrow">Enter</kbd>
</div>

<div>
<kbd id="ctrl-left" class="narrow">Ctrl</kbd>
<kbd id="windows-left"><img src="imagenes/windows-key.gif" alt="Windows Key"
height="13" width="16"></kbd>
<kbd id="alt-left" class="narrow">Alt</kbd>
<kbd id="tecla_especial_espaciadora" class="spacebar">&nbsp;</kbd>
<kbd id="tecla_especial_altgr" class="narrow alt-right">Alt Gr</kbd>
<kbd id="windows-right"><img src="imagenes/windows-key.gif" alt="" height="13"
width="16"></kbd>
<kbd id="application"><img src="imagenes/windows-application-key.gif" alt=""
height="13" width="12"></kbd>
<kbd id="ctrl-right" class="narrow rightgap">Ctrl</kbd>
<kbd><img src="imagenes/arrow-left.gif" alt="" height="19" width="21"></kbd>
<kbd><img src="imagenes/arrow-down.gif" alt="" height="22" width="21"></kbd>
<kbd class="rightgap"><img src="imagenes/arrow-right.gif" alt="" height="19"
width="21"></kbd>
<kbd class="numpad-0" id="_0">0<br><span class="narrow">Ins</span></kbd>
<kbd>.<br><span class="narrow">Supr</span></kbd>
<kbd class="numpad-bottom">&nbsp;</kbd>
</div>

</div>

<select id="idiomas"><option>Cargando...</option></select>

<div id="contenido"></div>

<p>Contenido en el servidor [se actualiza automticamente]</p>


<div id="contenidoGuardado"></div>

<p style="font-size:.9em;color:#888;margin-top:2em;">&copy; El diseo del teclado es


obra de Chris Hester y se puede descargar desde http: //www.designdetector.com/archives/
05/03/KeyboardDemo.php</p>
</body>

</html>

14.19. Ejercicio 19
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 19 - Autocompletar</title>
<script type="text/javascript">
var peticion = null;
var elementoSeleccionado = -1;
var sugerencias = null;
var cacheSugerencias = {};

function inicializa_xhr() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

Array.prototype.formateaLista = function() {
var codigoHtml = "";

codigoHtml = "<ul>";
for(var i=0; i<this.length; i++) {
if(i == elementoSeleccionado) {
codigoHtml += "<li class=\"seleccionado\">"+this[i]+"</li>";
}
else {
codigoHtml += "<li>"+this[i]+"</li>";
}
}
codigoHtml += "</ul>";

return codigoHtml;
};

function autocompleta() {
var elEvento = arguments[0] || window.event;
var tecla = elEvento.keyCode;

if(tecla == 40) { // Flecha Abajo


if(elementoSeleccionado+1 < sugerencias.length) {
elementoSeleccionado++;
}
muestraSugerencias();
}
else if(tecla == 38) { // Flecha Arriba
if(elementoSeleccionado > 0) {
elementoSeleccionado--;
}
muestraSugerencias();
}
else if(tecla == 13) { // ENTER o Intro
seleccionaElemento();
}
else {
var texto = document.getElementById("municipio").value;
Introduccin a AJAX Captulo 14. Ejercicios resueltos

// Si es la tecla de borrado y el texto es vaco, ocultar la lista


if(tecla == 8 && texto == "") {
borraLista();
return;
}

if(cacheSugerencias[texto] == null) {
peticion = inicializa_xhr();

peticion.onreadystatechange = function() {
if(peticion.readyState == 4) {
if(peticion.status == 200) {
sugerencias = eval('('+peticion.responseText+')');
if(sugerencias.length == 0) {
sinResultados();
}
else {
cacheSugerencias[texto] = sugerencias;
actualizaSugerencias();
}
}
}
};

peticion.open('POST', 'http://localhost/RUTA_HASTA_ARCHIVO/
autocompletaMunicipios.php?nocache='+Math.random(), true);
peticion.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
peticion.send('municipio='+encodeURIComponent(texto));
}
else {
sugerencias = cacheSugerencias[texto];
actualizaSugerencias();
}
}
}

function sinResultados() {
document.getElementById("sugerencias").innerHTML = "No existen municipios que
empiecen con ese texto";
document.getElementById("sugerencias").style.display = "block";
}

function actualizaSugerencias() {
elementoSeleccionado = -1;
muestraSugerencias();
}

function seleccionaElemento() {
if(sugerencias[elementoSeleccionado]) {
document.getElementById("municipio").value = sugerencias[elementoSeleccionado];
borraLista();
}
}
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function muestraSugerencias() {
var zonaSugerencias = document.getElementById("sugerencias");

zonaSugerencias.innerHTML = sugerencias.formateaLista();
zonaSugerencias.style.display = 'block';
}

function borraLista() {
document.getElementById("sugerencias").innerHTML = "";
document.getElementById("sugerencias").style.display = "none";
}

window.onload = function() {
// Crear elemento de tipo <div> para mostrar las sugerencias del servidor
var elDiv = document.createElement("div");
elDiv.id = "sugerencias";
document.body.appendChild(elDiv);

document.getElementById("municipio").onkeyup = autocompleta;
document.getElementById("municipio").focus();
}
</script>

<style type="text/css">
body {font-family: Arial, Helvetica, sans-serif;}
#sugerencias {width:200px; border:1px solid black; display:none; margin-left: 83px;}
#sugerencias ul {list-style: none; margin: 0; padding: 0; font-size:.85em;}
#sugerencias ul li {padding: .2em; border-bottom: 1px solid silver;}
.seleccionado {font-weight:bold; background-color: #FFFF00;}
</style>

</head>

<body>
<h1>Autocompletar texto</h1>

<form>
<label for="municipio">Municipio</label> &nbsp;&nbsp;
<input type="text" id="municipio" name="municipio" size="30" />
<input type="text" id="oculto" name="oculto" style="display:none;" />
</form>

</body>
</html>

14.20. Ejercicio 20
El rchivo util.js que utiliz el ejercicio se incluye en el rchivo ZIP de l solucio n complet.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 20 - Monitorizar</title>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

<script type="text/javascript" src="util.js"></script>


<script type="text/javascript">
var nodos = [{"nombre": "Google", "url": "http://www.google.com"}, {"nombre": "Yahoo",
"url": "http://www.yahoo.com"},
{"nombre": "MSN", "url": "http://www.msn.com"}, {"nombre": "eBay", "url":
"http://www.ebay.com"},
{"nombre": "YouTube", "url": "http://www.youtube.com"}, {"nombre":
"Flickr", "url": "http://www.flickr.com"}];
var intervalo;

function monitoriza() {
intervalo = setInterval(monitorizaNodos, 1000);
}

function detiene() {
clearInterval(intervalo);
}

function monitorizaNodos() {
for(var i=0; i<nodos.length; i++) {
document.getElementById("nodo"+i).style.border = "3px solid #000000";
var ping = new net.CargadorContenidosCompleto(nodos[i].url, procesaPing,
noDisponible, "HEAD");
}
}

function procesaPing() {
if(new Date(this.req.getResponseHeader("Date"))) { var numeroNodo =
calculaNumeroNodo(this.url);
document.getElementById("nodo"+numeroNodo).style.border = "3px solid #00FF00";
document.getElementById("nodo"+numeroNodo).className = "on";
document.getElementById("datos"+numeroNodo).innerHTML =
this.req.getResponseHeader("Server");
}
}

function noDisponible() {
var numeroNodo = calculaNumeroNodo(this.url);
document.getElementById("nodo"+numeroNodo).style.border = "3px solid #FF0000";
document.getElementById("nodo"+numeroNodo).className = "off";
}

function calculaNumeroNodo(url) {
for(var i=0; i<nodos.length; i++) {
if(nodos[i].url == url) {
return i;
}
}
}

window.onload = function() {
// Crear elemento de tipo <div> para mostrar cada uno de los nodos
for(i=0; i<nodos.length; i++) {
var nodo = document.createElement("div");
Introduccin a AJAX Captulo 14. Ejercicios resueltos

nodo.id = "nodo"+i;
nodo.innerHTML = "<strong>" + nodos[i].nombre + "</strong><br>" + nodos[i].url +
"<span id=\"datos"+i+"\"></span>";
document.getElementById("mapa_red").appendChild(nodo);
document.getElementById("nodo"+i).className = "normal";
}

// Establecer los eventos en los botones


document.getElementById("monitoriza").onclick = monitoriza;
document.getElementById("detiene").onclick = detiene;
}

</script>

<style type="text/css">
body {font-size:14px; font-family:Arial, Helvetica, sans-serif;}
.normal, .consulta, .on, .off {width: 140px; text-align: center; margin: .5em; padding:
.5em; }
form {display: inline; }
.normal {background-color: #FFFFFF; border: 3px solid #C0C0C0;}
.consulta {border:3px solid #000000;}
.on {background-color: #00CC00; border: 3px solid #00FF00;}
.off {background-color: #CC0000; border: 3px solid #FF0000;}
#mapa_red {border:5px solid #D0D0D0; float: left; padding: 1em 0; margin: 1em 0; width:
50%;}
#mapa_red div { float: left; margin: 1em; height: 5em; width: 35%;}
div span {display:block; padding:.3em;}
</style>

</head>

<body>
<h1>Consola de monitorizacin</h1>

<form>
<input type="button" id="monitoriza" value="Monitorizar"></input>
<input type="button" id="detiene" value="Detener"></input>
</form>

<div id="mapa_red"></div>

</body>
</html>

14.21. Ejercicio 21
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 21 - RSS</title>
<script type="text/javascript">
Object.prototype.get = function(etiqueta) {
return this.getElementsByTagName(etiqueta)[0].textContent;
Introduccin a AJAX Captulo 14. Ejercicios resueltos

var rss =
{ canal:
{}, items:
[]
};

window.onload = function(){
document.getElementById('mostrar').onclick = cargaRss;
}

function cargaRss(){
// Obtener URL de RSS
borrarLog();
log('Averiguar la URL del canal RSS');

var url_original = document.getElementById('url').value;


log('URL original es ' + url_original);

var url_rss = descubreRss(url_original);


log('La URL descubierta es ' + url_rss);

// Descargar canal RSS


log('Descargando canal RSS');
descargaRss(url_rss);
}

function descubreRss(url){
var peticion = new XMLHttpRequest();
peticion.onreadystatechange = function(){};
peticion.open('GET', 'http://localhost/RUTA_HASTA_ARCHIVO/descubreRss.php?url=' +
encodeURIComponent(url), false);
peticion.send(null);

return peticion.responseText;
}

function descargaRss(url){
var peticion = new XMLHttpRequest();
peticion.onreadystatechange = procesaRss;
peticion.open('GET', 'http://localhost/RUTA_HASTA_ARCHIVO/proxy.php?url=' +
encodeURIComponent(url) + '&ct=text/xml', true);
peticion.send(null);

function procesaRss(){
if (peticion.readyState == 4) {
if (peticion.status == 200) {
var xml = peticion.responseXML;

var canal = xml.getElementsByTagName('channel')[0];


var titulo = canal.getElementsByTagName('title')[0].textContent;
rss.canal.titulo = titulo;

if(canal.getElementsByTagName('image').length > 0) {
var url_imagen =
Introduccin a AJAX Captulo 14. Ejercicios resueltos

canal.getElementsByTagName('image')[0].getElementsByTagName('url')[0].textContent;
rss.canal.titulo = '<img src="'+url_imagen+'" />'+rss.canal.titulo;
}

var enlace = canal.getElementsByTagName('link')[0].textContent;


rss.canal.enlace = enlace;

var items = xml.getElementsByTagName('item');


for (var i = 0; i < items.length; i++) {
var item = items[i];
var titulo = item.get('title');
var enlace = item.getElementsByTagName('link')[0].textContent;
var descripcion = item.getElementsByTagName('description')[0].textContent;
var fecha = item.getElementsByTagName('pubDate')[0].textContent;

rss.items[i] =
{ titulo:
titulo, enlace:
enlace,
descripcion: descripcion,
fecha: fecha
};
}

muestraRss();
}
}
}
}

function muestraRss()
{ document.getElementById('noticias').style.display =
'block'; document.getElementById('titulares').innerHTML =
''; document.getElementById('contenidos').innerHTML = '';

document.getElementById('titulo').innerHTML = '<a href="' + rss.canal.enlace + '">' +


rss.canal.titulo + '</a>';

var titulares = document.getElementById('titulares');

for (var i = 0; i < rss.items.length; i++) {


titulares.innerHTML += '<a href="#" onclick="muestraElemento(' + i + ')">' +
rss.items[i].titulo + '</a> <br/>';
}
}

function muestraElemento(indice){
var item = rss.items[indice];
var html = "";
html += "<h1><a href=\"" + item.enlace + "\">" + item.titulo + "</a></h1>";
if (item.fecha != undefined) {
html += "<h2>" + item.fecha + "</h2>";
}
html += "<p>" + item.descripcion + "</p>";

document.getElementById("contenidos").innerHTML = html;
Introduccin a AJAX Captulo 14. Ejercicios resueltos

function log(mensaje){
document.getElementById('info').innerHTML += mensaje + "<br/>";
}

function borrarLog(){
document.getElementById('info').innerHTML = "";
}
</script>
<style type="text/css">
body { font-family: Arial, Helvetica, sans-serif; }
form { margin: 0; }
#info { margin: 0; font-size: .7em; color: #777; }
#noticias {
position: absolute;
width: 80%;
margin-top: 1em;
border: 2px solid #369;
padding: 0;
display: none;
}
#titulo { background-color: #DDE8F3; padding: .3em; border-bottom: 1px solid #369; }
#titulares { width: 20%; float: left; border: none; border-right: 1px solid #D9E5F2; }
#contenidos { margin-left: 22%; padding: 0px 20px; vertical-align: top; }
#titulo h2 { font-weight: bold; color: #00368F; font-size: 1.4em; margin: 0; }
#titulares ul { list-style: none; margin: 0; padding: 0; }
#titulares ul li { border-bottom: 1px solid #EDEDED; padding: 6px; line-height: 1.4em; }
#titulares a { display: block; font-size: 12px; color: #369; }
#titulares a:hover { text-decoration: none; color: #C00; }
#contenidos h1 { font-weight: bold; color: #00368F; font-size: 1.4em; padding: .2em;
margin: .3em 0 0 0; }
#contenidos h2 { font-weight: bold; color: #888; font-size: .9em; padding: .2em;
margin: .3em 0 0 0; }
#contenidos p { color: #222; font-size: 1.1em; padding: 4px; line-height: 1.5em; }
</style>
</head>
<body>
<form action="#">
<input type="text" size="40" id="url" value="http://www.microsiervos.com" />
<input type="button" value="Mostrar RSS" id="mostrar" />
<div id="info"></div>
</form>

<div id="noticias">
<div id="titulo"></div>
<div id="titulares"></div>
<div id="contenidos"></div>
</div>
</body>
</html>
Introduccin a AJAX Captulo 14. Ejercicios resueltos

14.22. Ejercicio 22
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/
strict.dtd">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 22 - Google Maps</title>
<script src="http://maps.google.com/
maps?file=api&amp;v=2&amp;hl=es&amp;key=ABQIAAAA30JtKUU8se-7KKPRGSfCMBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxR
type="text/javascript"></script>
<script type="text/javascript">
function load() {
if (GBrowserIsCompatible()) {
// Variables para el mapa
var lat = 42.845007;
var lon = -2.673;
var zoom = 5;

// Crear un nuevo mapa


var map = new GMap2(document.getElementById("map"));

// Centrarlo en un punto geogrfico y con un nivel de zoom


map.setCenter(new GLatLng(lat, lon), zoom);

// Aadir los controles de zoom y de tipo de mapa


map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());

// Crear el segundo mapa


var map2 = new GMap2(document.getElementById("map2"));
// Calcular las antipodas del punto geogrfico
var antipodas = calculaAntipodas(lat, lon);
// Centrarlo en el punto geogrfico de las antpodas y con el mismo nivel de zoom
map2.setCenter(new GLatLng(antipodas.lat, antipodas.lon), zoom);

// Cuando se mueve el primer mapa, se sincroniza la posicin y aspecto del segundo


GEvent.addListener(map, "move", function() {
var centro = map.getCenter();
var antipodas = calculaAntipodas(centro.lat(), centro.lng());
map2.setCenter(new GLatLng(antipodas.lat, antipodas.lon), map.getZoom());
map2.setMapType(map.getCurrentMapType());
});

GEvent.addListener(map, "click", function(marcador, punto) {


// Crear el nuevo marcador y mostrar sus coordenadas
var nuevoMarcador = new GMarker(punto);
GEvent.addListener(nuevoMarcador, "click", function() {
this.openInfoWindowHtml("Lat: " + this.getPoint().lat() + "<br/>Lon: " +
this.getPoint().lng());
});
map.addOverlay(nuevoMarcador);

// Crear el marcador correspondiente a las antpodas


Introduccin a AJAX Captulo 14. Ejercicios resueltos

var antipodas = calculaAntipodas(punto.lat(), punto.lng());


var marcador2 = new GMarker(new GPoint(antipodas.lon, antipodas.lat));
GEvent.addListener(marcador2, "click", function() {
this.openInfoWindowHtml("Lat: " + this.getPoint().lat() + "<br/>Lon: " +
this.getPoint().lng());
});
map2.addOverlay(marcador2);
});
}

function calculaAntipodas(lat, lon) {


var antiLat = -lat;
var antiLon = 180 - Math.abs(lon);
return {lat: antiLat, lon: antiLon};
}
}

window.onload = load;
window.onunload = GUnload;

</script>
<style type="text/css">
#map, #map2 {border:1px solid black; float: left;}
</style>
</head>

<body>
<div id="map" style="width: 500px; height: 300px"></div>
<div id="map2" style="width: 500px; height: 300px"></div>
</body>
</html>

14.23. Ejercicio 23
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejercicio 23 - Google Maps</title>
<script src="http://maps.google.com/
maps?file=api&amp;v=2&amp;hl=es&amp;key=ABQIAAAA30JtKUU8se-7KKPRGSfCMBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxR
type="text/javascript"></script>
<script type="text/javascript">
var map = null;
var mgr = null;
var lat = 40.41558722527384;
var lon = -3.6968994140625;
var zoom = 6;
var puntos = {};
var peticion = null;

function inicializa_xhr() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
Introduccin a AJAX Captulo 14. Ejercicios resueltos

} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function load() {
if(GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(lat, lon), zoom);
map.setMapType(G_SATELLITE_MAP);
setInterval(cargaPrediccion, 3000);
}
}

function cargaPrediccion() { peticion =


inicializa_xhr(); peticion.onreadystatechange =
muestraPrediccion;
peticion.open('GET', 'http://localhost/RUTA_HASTA_ARCHIVO/
previsionMeteorologica.php?nocache='+Math.random(), true);
peticion.send(null);
}

function muestraPrediccion() {
if(peticion.readyState == 4) {
if(peticion.status == 200) {
puntos = eval("("+peticion.responseText+")");
map.clearOverlays();
mgr = new GMarkerManager(map);
mgr.addMarkers(getMarcadores(), 3);
mgr.refresh();
}
}
}

function getMarcadores() {
var marcadores = [];
for (var i=0; i<puntos.length; ++i) {
var marcador = new GMarker(getPunto(i), { icon: getIcono(i) });
marcadores.push(marcador);
}
return marcadores;
}

function getPunto(i) {
var punto = puntos[i];
var lat = punto.latlon[0];
var lon = punto.latlon[1];
return new GLatLng(lat, lon);
}

function getIcono(i) { var


punto = puntos[i]; var
icono = new GIcon();
icono.image = "imagenes/" + punto.prediccion + ".png";
icono.iconAnchor = new GPoint(16, 16);
Introduccin a AJAX Captulo 14. Ejercicios resueltos

icono.iconSize = new GSize(32, 32);

return icono;
}
</script>
</head>

<body onload="load()" onunload="GUnload()">


<div id="map" style="width: 600px; height: 600px"></div>
</body>
</html>

Você também pode gostar