Documentos de Académico
Documentos de Profesional
Documentos de Cultura
es
Introduccin a
AJAX
www.librosweb.es 2
Introduccin a AJAX
www.librosweb.es 3
Introduccin a AJAX
www.librosweb.es 4
Introduccin a AJAX Captulo 1. Introduccin a AJAX
En relidd, el te rmino AJAX es un cro nimo de Asynchronous JavaScript + XML, que se puede
trducir como "JvScript sncrono + XML".
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.
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)
www.librosweb.es 7
Introduccin a AJAX Captulo 1. Introduccin a AJAX
www.librosweb.es 8
Introduccin a AJAX Captulo 2. JavaScript bsico
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 ;
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");
www.librosweb.es 9
Introduccin a AJAX Captulo 2. JavaScript bsico
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 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.
muestraMensaje();
alert(mensaje);
www.librosweb.es 10
Introduccin a AJAX Captulo 2. JavaScript bsico
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.
muestraMensaje();
alert(mensaje);
function muestraMensaje() {
var mensaje = "gana la de dentro";
alert(mensaje);
}
alert(mensaje);
muestraMensaje();
alert(mensaje);
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);
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.
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
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
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.
www.librosweb.es 13
Introduccin a AJAX Captulo 2. JavaScript bsico
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.
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:
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.
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";
www.librosweb.es 15
Introduccin a AJAX Captulo 2. JavaScript bsico
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.
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.
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
www.librosweb.es 16
Introduccin a AJAX Captulo 2. JavaScript bsico
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.
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.
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.
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
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.
Utilizndo el tipo de referenci Boolean, es posible crer objetos de tipo lo gico o booleano:
var variable1 = new Boolean(false);
Por este motivo, con los vlores boolenos normlmente se utilizn tipos de dtos primitivos en
vez de objetos de tipo Boolean.
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);
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);
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.
L clse String represent un cden de texto, de form similr los tipos de dtos
primitivos:
var variable1 = new String("hola mundo");
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).
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
2.5.3.1. Negacin
variable !variable
true false
false true
var cantidad = 0;
vacio = !cantidad; // vacio = true
cantidad = 2;
vacio = !cantidad; // vacio = false
www.librosweb.es 22
Introduccin a AJAX Captulo 2. JavaScript bsico
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 &&:
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 ||:
www.librosweb.es 23
Introduccin a AJAX Captulo 2. JavaScript bsico
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.
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
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
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.
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
www.librosweb.es 27
Introduccin a AJAX Captulo 2. JavaScript bsico
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;
}
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.
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;
}
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;
}
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
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);
www.librosweb.es 30
Introduccin a AJAX Captulo 2. JavaScript bsico
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);
suma(3, 5, 7, 9);
length, clcul l longitud de un cden de texto (el nu mero de crcteres que l formn)
www.librosweb.es 31
Introduccin a AJAX Captulo 2. JavaScript bsico
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"
www.librosweb.es 32
Introduccin a AJAX Captulo 2. JavaScript bsico
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 "
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:
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]
www.librosweb.es 34
Introduccin a AJAX Captulo 3. JavaScript avanzado
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.
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.
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.
alert(elArray['primero']);
www.librosweb.es 35
Introduccin a AJAX Captulo 3. JavaScript avanzado
alert(elArray.primero);
alert(elArray[0]);
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.
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);
}
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
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);
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).
elObjeto.obtieneId = obtieneId;
elObjeto.obtieneId = obtieneId();
www.librosweb.es 37
Introduccin a AJAX Captulo 3. JavaScript avanzado
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.
Siguiendo este mismo procedimiento, es posible crer objetos complejos que contengn otros
objetos:
var Aplicacion = 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.
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 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;
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.
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 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"};
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();
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 {}.
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.
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 ;
},
...
}
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
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"
}
hide: function() {
$('exportButton').src = "/images/b-export.gif"
hideElement('download_export')
},
toggle: function() {
Element.visible('download_export') ? this.hide() : this.show()
}
}
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() { ... }
};
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
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;
}
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);
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);
}
}
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.
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.
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);
}
Factura.prototype.iva = 7;
www.librosweb.es 49
Introduccin a AJAX Captulo 3. JavaScript avanzado
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.
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.
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]
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('');
}
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, '');
}
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
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;
}
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:
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.
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
function funcionExterna() {
var x = "estoy dentro";
function funcionAnidada() { alert(x); }
funcionAnidada();
}
funcionExterna();
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
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.
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)
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.
<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)
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.
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)
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[ ]]>.
www.librosweb.es 61
Introduccin a AJAX Captulo 4. DOM (Document Object Model)
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.
www.librosweb.es 62
Introduccin a AJAX Captulo 4. DOM (Document Object Model)
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.
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
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.
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.
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:
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";
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.
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];
}
<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.
<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:
Ejercicio 8
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.
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
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>
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>
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:
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>
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);
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);
Ejercicio 9
A partir de la pgina HTML que se proporciona, completar el cdigo JavaScript definido para realizar
la siguiente aplicacin sencilla:
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.
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" />
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");
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>
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>
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.
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
// Regla CSS
#parrafo { color: #008000; }
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;
}
// Regla CSS
#parrafo { color: #008000; }
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
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>
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
<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>
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);
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;
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');
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);
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';
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.
El BOM est compuesto por vrios objetos relciondos entre s. El siguiente esquem muestr
los objetos de BOM y su relcio n:
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)
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
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.
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.
setInterval(muestraMensaje, 1000);
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)
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)
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
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]
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)
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
// 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 */
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
(Slo Internet Explorer) Cadena que representa el tipo de CPU del usuario ("x86",
cpuClass "68K", "PPC", "Alpha", "Other")
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.
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
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.
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.
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.
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.
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().
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.
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.
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>
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.
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.
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:
Otr ventj dicionl de est te cnic es que ls funciones externs pueden utilizr l vrible
this referid l elemento que originl el
evento.
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.
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.
Ejercicio 10
Cuando la seccin se oculte, debe cambiar el mensaje del enlace asociado (pista: propiedad
innerHTML).
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:
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.
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.
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);
function muestraOtroMensaje() {
alert("Has pulsado el ratn y por eso se muestran estos mensajes");
}
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
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.
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);
function muestraOtroMensaje() {
alert("Has pulsado el ratn y por eso se muestran estos mensajes");
}
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];
}
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.
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
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.
L siguiente tbl recoge ls propieddes definids pr el objeto event en los nvegdores que
siguen los est ndres:
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.1. Similitudes
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.
6.4.2.2. Diferencias
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 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:
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;
document.onkeypress = manejador;
document.onkeypress = manejador;
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;
}
}
El objeto event tmbie n permite detener completmente l ejecucio n del flujo norml de
eventos:
// Internet Explorer
elEvento.cancelBubble = true;
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.
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 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
6.5.1.1. Propiedades
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.
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
L propiedd keyCode
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
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.
Evento Descripcin
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 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 .
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.
<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");
}
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.
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.
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.
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
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.
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.
function descargaArchivo() {
cargaContenido("http://localhost/holamundo.txt", "GET", muestraContenido);
}
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;
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".
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
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)
Mtodo Descripcin
abort() Detiene la peticin actual
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.
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.
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());
}
}
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:
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:
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();
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);
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().
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);
}
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.
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¶metro2=valor2¶metro3=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.
<label for="telefono">Telefono:</label>
<input type="text" id="telefono" name="telefono" /><br/>
<div id="respuesta"></div>
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");
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;
}
}
}
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.
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";
Ejercicio 13
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.
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);
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());
}
}
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);
}
}
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 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 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;
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.
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;
Ejercicio 14
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.
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.)
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+")");
// 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>
Ejercicio 15
Rehacer el ejercicio 14 para procesar respuestas del servidor en formato JSON. Los cambios
producidos son:
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.
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
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.
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.
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.
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:
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", ... }
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.
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.
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().
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
y el tabulador (\t) se transforma en
.
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
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.
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"
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.
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"],
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
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
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.
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
Figura 9.3. Mensaje de aviso que muestra Internet Explorer al intentar establecer conexiones de red
con servidores remotos
A partir de la pgina web que se proporciona, completar el script para realizar un lector avanzado de
canales 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.
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 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.
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.
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
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&v=2&hl=es&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.
<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&v=2&hl=es&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>
Figura 9.5. Mapa sencillo creado con la API de Google Maps y las coordenadas de longitud y latitud
indicadas
Un vez definido el contenedor del mp, se estblecen los eventos necesrios en l p gin que
lo contiene:
<body onload="load()" 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
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.
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/
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
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);
Ejercicio 22
Introduccin a AJAX Captulo 9. Tcnicas avanzadas con AJAX
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.
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.
Figura 9.11. Mapa de previsin metereolgica construido con los mapas de Google y que utiliza
iconos personalizados para mostrar cada marcador de posicin
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" },
]
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
// 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")
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
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" };
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]
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']
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.
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 ( -)
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.select(): seleccion el vlor del cmpo (solo pr los cmpos en los que se pued
seleccionr su texto)
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()
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.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>.
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]
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
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]
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.
activeRequestCount: 0
}
MiClase = Class.create();
MiClase.prototype = {
initialize: function(a, b) {
this.a = a;
this.b = b;
}
}
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"};
Object.extend(opciones, opciones_usuario);
succ: function() {
return this + 1;
},
times: function(iterator) {
$R(0, this, true).each(iterator);
return this;
},
toJSON: function() {
return isFinite(this) ? this.toString() : 'null';
}
});
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¶metro2=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¶metro2=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
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
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.
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
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";
}
}
});
// Registrar el evento
Event.observe('pinchable', 'click', procesaEvento, false);
function procesaEvento(e) {
// Obtener el elemento que ha originado el evento (el DIV)
var elemento = Event.element(e);
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.
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
Prototype tmbie n incluye otros me todos u tiles pr l gestio n de eventos con formulrios:
Form.Observer(formulario, frecuencia, funcionManejadora);
function ejecutaFuncion(f) {
f();
}
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.
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];
window.onload = function()
{ document.getElementById('enlace_1').onclick =
muestraOculta; document.getElementById('enlace_2').onclick =
muestraOculta;
document.getElementById('enlace_3').onclick = muestraOculta;
}
$('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);
});
}
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/
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.
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);
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
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.
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.
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')
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.
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.
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.
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.
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.
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¶metro2=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
Indica el valor de la cabecera Content-Type utilizada para realizar la peticin. Su valor por
contentType defecto es application/x-www-form-urlencoded
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
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
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');
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.
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.
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 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'));
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.
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.
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'];
// Recorrer objetos
var producto = { id: '12DW2', precio: 12.34, cantidad: 5 };
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];
window.onload = function()
{ document.getElementById('enlace_1').onclick =
muestraOculta; document.getElementById('enlace_2').onclick =
muestraOculta;
document.getElementById('enlace_3').onclick = muestraOculta;
}
$('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);
});
}
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.
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);
}
$(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:
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.
Cdigos de informacin
Se ha creado un nuevo recurso (por ejemplo una pgina web o un archivo) como
201 Created parte de la respuesta
Cdigos de redireccin
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
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
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.
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.
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.
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.
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]
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
Noticis y ctulidd:
Librers y frmeworks:
Otrs utiliddes:
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
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;
}
Factura.prototype.muestraTotal = function() {
this.calculaTotal();
alert("TOTAL = " + this.informacion.total + " euros");
}
<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;
}
}
return false;
}
if (!permitir) {
if(!(this.contiene(elemento))) {
this[this.length] = elemento;
}
}
else {
this[this.length] = elemento;
}
}
<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 = "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;
}
<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);
<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);
}
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>
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
function compara() {
// Obtener los nodos padre de los prrafos
var primero = document.getElementById("primero");
var segundo = document.getElementById("segundo");
<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>
<div id="primero"></div>
<div id="segundo"></div>
<div class="clear"></div>
<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];
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, '<').
replace(/%3E/g, '>'));
}
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
function cargaContenido() {
// Borrar datos anteriores
document.getElementById('contenidos').innerHTML = "";
document.getElementById('estados').innerHTML = "";
// 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;
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
<div id="principal">
<h2>Contenidos del archivo:</h2>
<div id="contenidos"></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
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--;
}
function siguiente(){
var detener = document.getElementById('detener');
clearInterval(intervalo);
detener.value = 'Iniciar';
detener.onclick = iniciar;
if (numeroElemento == null) {
numeroElemento = noticias.length - 1;
}
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="« Anterior" />
<input type="button" id="siguiente" value="Siguiente »" />
</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>
<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>
<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
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 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>";
}
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
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 + ')');
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
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
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
tecladoActivo = teclado;
}
function pulsaTecla() {
var teclaPulsada = this.id.replace(/tecla_/gi, "");
var caracter = tecladoActivo[teclaPulsada];
teclasPulsadas.push(caracter);
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, "");
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();
}
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;
}
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");
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"> </div>
<div id="led2"> </div>
<div id="led3"> </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"> </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"> </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>><br><</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"> </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"> </kbd>
</div>
</div>
<select id="idiomas"><option>Cargando...</option></select>
<div id="contenido"></div>
</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(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>
<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
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";
}
</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');
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;
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;
}
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 = '';
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&v=2&hl=es&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;
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&v=2&hl=es&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 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);
}
return icono;
}
</script>
</head>