Instruction manuals, swedberg, y karl swedberg">
Aprende Jquery 1.3
Aprende Jquery 1.3
Aprende Jquery 1.3
PROGRAMACIN
TTULO DE LA OBRA ORIGINAL:
.3
.'
:".-
Ionathan Chaffer
Karl Swedberg
.s
,"-
..:~~
h\Nh\Yh\
.-MULTIMEDIA_
_~,
_._c. _ ~
\,.
Edicin espaola:
EDICIONES ANAYA MULTIMEDIA (GRUPO ANAYA, S.A.), 2010
"
;:;"';,
~,':.
Quiero dar las gracias a mi mujer Sara, por su constante amor y apoyo.
Gracias tambin a mis dos encantadores hijos, Benjamin y Lucia. Jonathan Chaffer
cuenta con mi ms profundo respeto por su experiencia en programacin y mi gratitud por su
deseo de escribir este libro conmigo.
Muchas gracias a [ohn Resig por crear la librera JavaScript ms grande del mundo y por
fomentar una sorprendente comunidad a su alrededor.
Gracias tambin a las personas de Packt Publishing, los revisores tcnicos de este libro, y a
todos aquellos que han proporcionado ayuda e inspiracin en el camino.
Karl Swedberg
Agradecimientos
"
.,
Indice
d c nt id
i:':.,,~
Prlogo
18
Introduccin
22
24
25
25
25
26
1. Empezar a trabajar
28
Qu hace jQuery
Por qu jQuery funciona bien
Historia del proyecto jQuery
Nuestra primera pgina Web con jQuery
Descargar jQuery
Configurar el documento HTML
Aadir jQuery
Encontrar el texto del poema
Aplicar la nueva clase
Ejecutar el cdigo
El producto terminado
Resumen
29
31
32
33
33
33
36
36
37
37
38
39
2. Selectores
40
UUM
41
$0
42
ndice de contenidos
ndice de contenidos
Selectores CSS
Aplicar estilo a niveles de elementos de lista
Selectores de atributo
Aplicar estilo a vnculos
Selectores personalizados
Aplicar estilo a filas alternas
Selectores de formulario
Mtodos transversales DOM
Aplicar estilo a celdas especficas
Encadenar
Acceder a elementos DOM
Resumen
43
44
46
46
3. Eventos
56
57
57
58
60 ' . 60
61
48
48
51
51
52
53
54
55
"61
63'"
65
67
68
70
70
71
72
74
75
76
76
77
78
80
80
81
83
84
86
4. Efectos
88
93
89
Efectos y velocidad
Aplicar velocidad
Aparecer y desaparecer de forma paulatina
Efectos compuestos
>.................................................................................
Crear animaciones personalizadas
Alternar el aparecer y desaparecer paulatino
Animar mltiples propiedades
Posicionar con CSS
Efectos simultneos frente a "en cola"
Trabajar con un solo conjunto de elementos
Trabajar con mltiples conjuntos de elementos
Rellamadas
,
En pocas palabras
Resumen
99 .
100
101
102
102
105
107
109
109
5. Manipulacin
110
DOM
95
96
96
97
98
Manipular atributos
Atributos que no son clase
La funcin factory $0 revisada
Insertar nuevos elementos
Mover elementos
Marcar, numerar y vincular el contexto
Anexar pies de pgina
Situar elementos alrededor de otros
Copiar elementos
Clonar con eventos
Clonar citas
Una desviacin CSS
De vuelta al cdigo
Embellecer las citas
Mtodos de manipulacin DOM
Resumen
111
112
114
115
118
121
122
124
125
126
126
127
127
129
131
132
6. AJAX
134
i~~
Ca~:~~t~::1~
~~.~~.~~:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Trabajar con objetos JavaScript
140
Recuperar un objeto JavaScript.
140
Funciones jQuery globales
141
Ejecutar un script
144
Cargar un documento XML
146
Elegir un formato de datos
150
Pasar datos al servidor
151
Llevar a cabo una peticin GET
151
lIfJI
ndice de contenidos
ndice de contenidos
Manipulacin
de tabla
154
,' , ,
,
' "
, , 156
,
,
,, ,
,.".,
158
160
, 161
162
163
164
, 164
165
, 167
17O
Ordenar y paginar
172
Ordenacin del lado del servidor
172
Impedir que la pgina se refresque
173
Ordenacin JavaScript
:
173 .
Etiquetas de agrupacin de filas
175
Ordenacin alfabtica bsica
175
El poder de los plug-ins
1z,'
Problemas de rendimiento
180.,
Manipular las teclas de ordenar
182
Ordenar otros tipos de datos
183
Resaltar columna
186
Alternar la direccin de la ordenacin
186
Paginacin del lado del servidor
188
Ordenar y paginar van juntos
189
Paginacin JavaScript
190
Mostrar el paginador
191
Habilitar los botones del paginador
192
Marcar la pgina actual..
: ~' ,
',
, 193
Paginacin con ordenacin
,
,
,.194
El cdigo terminado,
", ,
,.., ,
195
Modificar la apariencia de la tabla
197
Resaltar filas
,
,
,
197
Alternar color de filas
,..,
,..,
198
Alternar colores de fila avanzado
200
Resaltar filas basado en interaccin del usuario
202
Descripciones emergentes
,
,..,,
,
, ,.204
Contraer y expandir secciones
,
,
,
.,
209
Filtrado
,
,.., , ,
,
" , , ,
, ,..,.., ,..,
211
Opciones de filtro.,
,.".,
,
,
,
, ,
, 212
Invertir los filtros
,..,
,
,
,..,
,
, ,
, , , 213
Interactuar con otro cdigo
214
El cdigo terminado
Resumen
, : ,
, ,
,..,
,
,.,
,
,
, , ;.. 216
, 219
220
~~
'
,
,
'
,
,
,
' ,
,
,
, ,
,
, ,
,
, ,
,
,
,.,
9. Rotativos
Titular rotativo
Configurar la pgina
221
222 '
,
, 224
225
228
,..,., ,
" 231
'
,
231
, ,..".., 234
,.. 236
238
241
243
243
, 246
"
247
'..,..,
, ,.., 247
249
249
, , ,
"".251
252
253
253
254
256
256
" 259
,
260
261
,
262
264
,
, 265
,
265
",
266
'
, , 270
,
, 273
,..,..,
,.. 275
276
,
,
,
,..,
, '
, ,
"
,
277
278
fndice de contenidos
ndice de contenidos
Recuperar el feed
Configurar el rotativo
La funcin rotar titular
Detenerse al pasar por encima
Recuperar un feed de un dominio diferente
Aadir un indicador de carga
Efecto degradado
El cdigo terminado
Un carrusel de imgenes
Configurar la pgina
Revisar los estilos con JavaScript..
Mover las imgenes cuando se hace clic
Aadir animacin deslizable
Mostrar iconos de accin
Ampliar imagen
Ocultar la portada ampliada
Mostrar un botn cerrar .........................................................................:
Ms diversin con el etiquetado
Animar la ampliacin de la portada
Aplazar las animaciones hasta que la imagen se carga
Aadir un indicador de carga
El cdigo terminado
Resumen
279
282
283
286
288
289
290
292
294
294
296
297
299
301
304
305
307
308
309
313
320
321
322
323
324
325
325
325
326
326
327
327
330
332
332
333
333
334
334
335
:'
3r4, '
316
318
Tablas
;.. 335
Tablesorter
336
jqGrid
......................................................................................................................... 336
Flexigrid
,,~
337
Imgenes
337
Jcrop
337
Magnify
337
jQuery Lightbox y cuadros de dilogo modales
338
FancyBox
338
r
Thickbox
339
BlockUI
340
jqModal
340
Grficas
:
340
Flot
341
Sparklines
341
Eventos
341
hoverIntent
342
Live query
342
Resumen
343
11. Desarrollar plug-ins
344
345
346
347
347
349
349
352
353
356
359
360
361
362
363
364
366
368
369
369
369
370
370
ndice de contenidos
ndice de contenidos
372
Documentacin jQuery
Wiki jQuery
API jQuery
Navegador de la API jQuery
jQuery visual
Visor jQueryAPI Adobe AIR
Referencia JavaScript
Centro de desarrollo Mozilla
Dev.opera
Referencia JScript MSDN
Quirksmode
JavaScript Toolbox
Compresores de cdigo JavaScript
Compresor YUI
373
373
373
374
374
374
374
374
374
375
375
375
375
375
~~~
~~~~~~:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::~::::::::::::::::::::::
~;~
Referencia (X)HTML.
,
Pgina principal de W3c..
Referencia CSS
Pgina principal CSS de W3C.
La chuleta CSS de Mezzoblue
Position is everything
Blogs de utilidad
El blog jQuery
Learning jQuery
Ajaxian
[ohn Resig
JavaScript ant
Roberts talk
Estndares Web con imaginacin
Snook
Recurso JavaScript de Matt Snider
I cant
DOM scripting
As days pass by
A list apart
Marcos de trabajo de desarrollo Web utilizando jQuery
Apndice B. Herramientas
de desarrollo
::
376
376
376, '
376
377
377
377
377
377
377
378
378
378
378
378
378
378
379
379
379
379
382
383
383
384
Venkman
Comprobador' de expresiones regulares
Herramientas para Internet Explorer
Microsoft Intlrnet Explorer Developej Toolbar
Microsoft Visual Web Developer
DebugBar
Drip
Herramientas para Safari
Men Develop
Inspector Web
Herramientas para Opera
Dragonfly
Otras herramientas
,
- Firebug Lite
NitobiBug
Paquete TextMate jQuery
Charles
Fiddler
:
Aptana
384
:.. 384
384
384
385
385 .
385
385
385
386
386
386
386
386
386
387
387
387
387
388
Funciones internas
,
El gran escape
mbito de aplicacin de variables
Interacciones entre closures
Closures en jQuery
Argumentos para $(document).readyO
Manejadores de evento
Peligros de prdidas de memoria
Bucles de referencia accidentales
El problema de prdidas de memoria de Internet Explorer
La buena noticia
Resumen
389
390
392
394
395
395
396
397
398
399
400
400
402
Expresiones de selector
Mtodos transversales DOM
Mtodos de evento
Mtodos de efecto
Mtodos de manipulacin DOM
Mtodos AJAX
Mtodos variados
403
405
407
409
410
413
414
ndice alfabtico
415
,
(
'..
.
'
.-.~
Prlogo
Me siento honrado de saber que Karl Swedberg y [onathan Chaffer han emprendido
la tarea de escribir este libro. Como el primer libro sobre jQuery, establece el estndar
que otros libros jQuery, y realmente, otros libros JavaScript en general, han intentado
igualar. Constantemente ha sido uno de los libros JavaScript ms vendidos desde su
aparicin, debido a su calidad y atencin al detalle.
Estoy especialmente contento de que Karl y Jonathan hayan escrito el libro ya que
los conoca muy bien y saba que seran perfectos para el trabajo. Al ser parte del equipo jQuery, he tenido la oportunidad de llegar a conocer a Karl bastante bien en los ltimos dos aos, y especialmente dentro del contexto de su esfuerzo por escribir este
libro. Viendo el resultado final, queda claro que sus conocimientos como desarrollador
y profesor de ingls estaban perfectamente diseados para esta tarea.
Tambin he tenido la oportunidad de conocer a ambos en persona, una ocurrencia
extraa en el mundo de los proyectos de cdigo abierto distribuidos, y continan siendo
miembros ntegros de la comunidad jQuery.
La librera jQuery se utiliza por muchas personas diferentes en la comunidad jQuery.
La comunidad est llena de diseadores, desarrolladores, personas que tienen experiencia programando y otros que no la tienen. Incluso dentro del equipo jQuery, tenemos personas de todos los perfiles que proporcionan su conocimiento en la direccin
del proyecto. Hay una cosa que es comn a todos los usuarios de jQuery, sin embargo:
somos una comunidad de desarrolladores y diseadores que quieren que el desarrollo
JavaScript sea sencillo.
Es casi un clich, en este punto, decir que un proyecto de cdigo abierto est orientado
a la comunidad, o que un proyecto quiere centrarse en ayudar a los nuevos usuarios a
empezar. Pero no slo es un gesto vaco para jQuery; es el combustible para el proyecto.
E!II
Prlogo
""
.",
.::~
lntrodu cion
Todo empez como un mero trabajo desinteresado, por amor al arte, all por el ao
2005, por [ohn Resig, un nio prodigio en JavaScript que ahora trabaja para Mozilla.
Inspirado por los pioneros en este terreno como Dean Edwards y Simon Willison, Resig
reuni una serie de funciones para que por medio de programacin fuera sencillo encontrar elementos en una pgina Web y asignarles comportamientos. Cuando hizo pblico su proyecto por primera vez en enero de 2006, haba aadido modificacin DOM
y animaciones bsicas. Le asign el nombre jQuery para enfatizar el papel decisivo de
encontrar o "consultar" partes de una pgina Web y actuar sobre ellas con JavaScript.
Pasados pocos aos desde entonces, jQuery ha crecido en su conjunto de caractersticas,
mejorado en su rendimiento, y adquirido una amplia aprobacin por algunos de los sitios ms populares en Internet. Aunque Resig sigue siendo el desarrollador principal del
proyecto, jQuery ha prosperado, al estilo de cdigo abierto, hasta el punto donde ahora
cuenta con un equipo de excelentes desarrolladores JavaScript, as como una comunidad
dinmica de miles de desarrolladores. La biblioteca JavaScript jQuery puede mejorar sus
sitios Web con independencia de su formacin previa. Proporciona una amplia variedad de caractersticas, una sintaxis fcil de aprender, y compatibilidad multiplataforma
robusta en un solo archivo compacto. Adems, se han desarrollado cientos de plug-ins
para ampliar la funcionalidad de jQuery, convirtindolo en una herramienta esencial
para casi cualquier ocasin de programacin del lado del cliente.
Este libro proporciona una introduccin a los conceptos jQuery, permitindole aadir interacciones y animaciones a sus pginas, incluso si los intentos previos de escribir
JavaScript le han dejado frustrado. Este libro le ayudar a superar los escollos asociados
con AJAX,eventos, efectos y caractersticas avanzadas del lenguaje JavaScript, y le proporciona una breve referencia a la librera jQuery para regresar una y otra vez.
Introduccin
lEa
En el apndice B descubrir un nmero de programas de terceros de utilidad y utilidades para editat y depurar cdigo jQuery dentro de su entorno de desarrollo personal.
En el apndice C adquirir un conocimiento profundo de los closures, qu son y cmo
los puede utilizar en su propio beneficio.
En el apndice D tendr una visin de conjunto de toda la librera jQuery, incluido
cada uno de sus mtodos y expresiones de selector. Su formato es perfecto para esos
momentos cuando sabe qu quiere hacer, pero no est seguro del nombre de mtodo o
selector correcto.
Adems, para ejecutar los ejemplos AJAX del captulo 6, necesitar un servidor compatible con PHP.
Convenciones
Para ayudarle a sacar el mayor partido al texto y saber dnde se encuentra en cada
momento, a lo largo del libro utilizamos distintas convenciones:
ElJI
Introduccin
ttulo</title>
<body>
<div>
<p>Esto
<p>Esto
<p>Esto
</div>
</body>
</html>
es un prrafo.</p>
es otro prrafo.</p>
es otro prrafo.</p>
.ready(function()
$ (/a [href'=mailto,
1/) .addClass (fmailto/)
$(/a[href$=.pdfl/)
.addClass(/pdflink/);
$ (fa [hrefA=http] [href*=henry] /)
.addClass(/henrylink/),
})
':;'"'-,
Cdigo fuente
Para desarrollar los ejemplos, puede optar por introducir manualmente el cdigo o
utilizar los archivos de cdigo fuente que acompaan al libro. Tambin puede descargar
el cdigo fuente utilizado en el sitio Web de Anaya (http://www .AnayaMultimedia .
es, seccin Soporte tcnico, opcin Complementos).
,
1[
"t;
r
r
...
1
m ez
a trabajar
Qu hace jQuery
La librera jQuery proporciona una capa de abstraccin de aplicacin general para
programacin Web comn, y por lo tanto es de utilidad en casi cualquier situacin de
programacin. Su naturaleza extensible significa que casi nunca podemos tratar todos
ElII
1. Empezar a trabajar
los posibles usos y funciones en un nico libro, ya que constantemente se estn desarrollando plug-ins para aadir nuevas posibilidades de uso. Las caractersticas principales,
sin embargo, abordan las siguientes necesidades:
EII
Aprovechar el conocimiento de CSS: Al basar el mecanismo para localizar elementos de pgina en selectores CSS,jQuery hereda una forma concisa y legible
de expresar la estructura de un documento. La librera jQuery se convierte en un
punto de entrada para diseadores que desean aadir comportamientos a sus
pginas porque
requisito previo para realizar desarrollo Web profesional es
conocimiento de sintaxis CSS.
un
Abstraer los fallos de navegador: Una triste realidad del desarrollo Web es
que cada navegador tiene su propio conjunto de desviaciones de los estndares
publicados. Una parte significativa de cualquier aplicacin Web se puede relegar
a gestionar caractersticas de forma diferente en cada plataforma. Aunque el escenario de los navegadores en continuo cambio hace que un cdigo base neutro
para el navegador sea imposible para otras caractersticas avanzadas, jQuery
aade una capa de abstraccin que normaliza las tareas comunes, reduciendo el
tamao del cdigo, y simplificndolo tremendamente.
Siempre trabajar con conjuntos: Cuando le decimos a jQuery, Encontrar todos los
elementos con la clase collapsible y ocultarlos, no hay necesidad de pasar en bucle
por cada elemento devuelto. En su lugar, mtodos como. hide () se disean para
trabajar automticamente sobre conjuntos de objetos en lugar de individuales.
Esta tcnica, denominada iteracin implcita, significa que muchas construcciones
de bucle dejar).de ser necesarias, acortando el cdigo considerablemente.
Permitir mltiples acciones en una lnea: Para evitar uso excesivo de variables
temporales o repeticin malgastada, jQuery emplea un patrn de programacin
denominado encadenamiento para la mayora de sus mtodos. Esto significa que
el resultado de la mayora de operaciones en un objeto es el objeto en s mismo,
listo para la siguiente accin que se le va a aplicar.
Estas estrategias han mantenido el paquete jQuery reducido, por debajo de 20 KB
comprimido, mientras que al mismo tiempo proporciona tcnicas para mantener nuestro cdigo personalizado que utiliza la librera compacta, tambin.
1. Empezar a trabajar
jQuery}.3
(enero 2009): Una importante revisin del motor selector (Sizzle) proporcion un gran impulso al rerimiento de la librera. La delegacin de evento
pas a soportarse formalmente.
plug-in
Dimensions
de
Fase de desarrollo pblico: [ohn Resig mencion por primera vez una mejora en
la biblioteca "Behaviour" del prototipo en agosto de 2005. Este nuevo marco de
trabajo se lanz formalmente
como jQuery el 14 de enero, 2006.
jQuery 1.0 (agosto 2006): sta, la primera versin estable de la biblioteca, ya dispona de soporte robusto para selectores CSS, manejadores de evento e interaccin
AJAX.
jQuery UI (septiembre 2007): Esta nueva suite de plug-in se anunci para sustituir
el plug-in popular, aunque antiguo, Interface. Se incluy una rica coleccin de
widgets prefabricados, as como un conjunto de herramientas para crear elementos
sofisticados como interfaces de arrastrar y soltar.
que tenemos
disponibles
con
Descargar jQuery
El sitio Web jQuery oficial (http://j
query. corn/) es siempre el recurso ms ac ..
tualizado para cdigo y noticias relacionadas con la librera. Para empezar, necesitamos
una copia de jQuery, que se puede descargar desde la pgina principal del sitio. Varias
versiones de jQuery pueden estar disponibles
en cualquier momento dado; lo ms
apropiado para nosotros como desarrolladores
de sitios ser la versin no comprimida
ms actualizada de la librera. sta se puede reemplazar con una versin comprimida
en entornos de produccin. No necesita instalacin. Para utilizar jQuery, simplemente
necesitamos situarlo en nuestro sitio en una ubicacin pblica. Puesto que JavaScript es
un lenguaje interpretado,
no hay fase de compilacin o creacin por la que preocuparse.
Siempre que necesitemos una pgina para tener jQuery disponible, simplemente
haremos referencia a la ubicacin del archivo desde el documento HTML.
lmI
1. Empezar a trabajar
xml:lang:=lIenll
lang=lIen">
chead>
<meta
http-equiv="Content-Typell
content:="textjhtml; charset=utf-8 '/>
1
ctitle>Through
the Looking-Glassc/title>
<link rel="stylesheet"
href="alice.css"
type=lItext/cssll media=l!screenll />
cscript
cscript
src=lIjquery.jsll
sre= alice. j s
11
11
type=lItext/javascriptH></script>
type= text/j avascript ></ s c r pt s
I!
11
</head>
ebody>
<hl>Through the Looking-Glass</hl>
cdiv class="author">by
Lewis Carrollc/div>
cdiv class="chapter
id="chapter-l">
ch2 class=/(chapter-title">l.
Looking-Glass House</h2>
<p>There was a book lying near Alice on the table,
and while she sat watching the White King (for she
was still a little anxious about him, and had the
ink a11 ready te threw over him, in case he fainted
again), she turned over the leaves, to find some
part that she could read, <span c1ass="spoken">
"&mdashfor it1s all in some language I don't know,lI
</span> she said to herself.</p>
<p>It was like this.</p>
cdiv class="poem'1>
ch3 class=lpoem-title">YKCOWREBBAJc/h3>
cdiv class="poem-stanza">
cdiv>sevot yhtils eht dna ,gillirb sawT'c/div>
cdiv>;ebaw eht ni elbrnig dna eryg diDc/div>
cdiv>,sevogorob
eht erew ysmim l1Ac/div>
cdiv>.ebargtuo
shtar ernom eht dnAc/div>
c/div>
c/div>
<p>She puzzled over this for sorne time, but at last
a bright thought struck her. cspan class=l1spoken">
"Why, it's a Looking-glass
book, of course! And if
1 hold it up to a glass, the words will all go the
right way again."</span>c/p>
cp>This was the poem that Alice read.</p>
cdiv class="poem">
ch3 class="poem-title >JAEBERWOCKYc/h3>
cdiv class=l'poem-stanza11>
cdiv>'Twas brillig, and the slithy tovesc/div>
cdiv>Did gyre and gimble in the wabec/div>
cdiv>All mimsy were the borogoves,c/div>
cdiv>And the mame raths outgrabe.c/div>
11
tl
</div>
</div>
c/div>
</body>
</html>
sans-serif
En el resto de este libro, solamente se imprimirn las partes relevantes de los archivos
HTMLy CSS. Los archivos completos se encuentran disponibles en la pgina Web de
Anaya Multimedia (http://www.AnayaMultimedia.es.
seccin Soporte tcnico,
opcin Complementos).
AprendejQuery
1. Empezar a trabajar
1. Looking.Glass House
There ...
as a book Iyill( ne.at AliOR on 11'1. tabla, anel whlle
throw ovar htm. in case he 'ante<!
aoaln),
she tumed OVIK
teeves.
lo find
(for $he
she
in
1.3
del libro. Pasaremos por las diferentes formas de localizar partes de un documento en
el captulo siguiente.
La funcin, $ () es en realidad una funcin factory para el objeto jQuery, que es el
componente bsico con el que trabaj~emos a partir de ahora. El objeto jQuery encapsula cero o ms elementos DOM, y nos permite interactuar con ellos de formas muy diferentes. En este caso, deseamos modificar la apariencia de estas partes de la pgina, y
realizaremos esto al cambiar las clases aplicadas al poema.
heuelf.
ltwldlike-lhls.
YKCOWRE8BAJ
sevot yhtils en! dn. ,glllirb S8Wr
:eb8w ent ni e\bmlg eoe etyV diO
,sevogOfob ~I erew ysmim tiA
.et>argtuo
shtar Rmom ehl dnA
She punled 0W!f Ihi, fOf soma time, bul al 1m. btighl lhought tUud: heJ. ~/hy. it's a loolting-gl8$ book. 01 coursel And i11 "old
it
poem
JA88ERWOCKY
'Twas bfillig, and the sllthy laves
Oid gyre and gimble in tne webe:
AII minuy
wete the borogoves.
And the mame raths outgrabe.
Ejecutar el cdigo
Este ejemplo es para demostrar el uso sencillo de jQuery. En situaciones del mundo
real, este tipo de estilo se puede llevar a cabo slo con CSS.
$ (document) .ready(function() {
$ (' .poem-stanza') .addClass ('highlight');
}) ;
Juntos, $ () y . addClass () son suficientes para conseguir nuestro objetivo de cambiar la apariencia del texto del poema. Sin embargo, si esta lnea de cdigo se inserta
sola en el encabezado del documento, no tendr efecto. El cdigo JavaScript se ejecuta
generalmente tan pronto como se encuentra en el navegador, y en el momento en que se
procesa el encabezado, todava no hay HTML presente al que aplicar estilo. Necesitamos
retrasar la ejecucin del cdigo hasta despus de que el DOM est disponible para nuestro uso. El mecanismo tradicional para controlar cundo se ejecuta cdigo JavaScript es
llamar al cdigo desde los manejadores de evento. Muchos manejadores se encuentran
disponibles para eventos iniciados por el usuario, como c1icsdel ratn o pulsar teclas.
Si no tenemos jQuery disponible para nuestro uso, tendremos que basarnos en el manejador onload, que se activa despus de que la pgina (junto con todas sus imgenes) se
ha mostrado. Para activar nuestro cdigo desde el evento onload, situaremos el cdigo
dentro de una funcin:
function highlightPoemStanzas()
{
$(' .poem-stanza' I .addClass('highlight');
Aadir jQuery
Nuestro cdigo personalizado ir en el segundo archivo JavaScript, actualmente vaco, que hemos incluido desde HTML utilizando <script
S'rc="alice.js"
type=" text/j avascript"
></ s c r i.pt.>. Para este ejemplo, solamente necesitamos
tres lneas de cdigo:
">
ElII
1.
Empezar a trabajar
Esto hace que nuestro cdigo se ejecute despus de que la pgina est completamente cargada.
Existen desventajas a este enfoque. Hemos alterado el propio HTML para efectuar
este cambio de comportamiento. Este estrecho acoplamiento de estructura y funcin satura el cdigo, posiblemente requiriendo que se repitan las mismas llamadas de funcin
durante muchas pginas diferentes, o en el caso de otros eventos como clics del ratn,
durante cada instancia de un elemento en una pgina. Aadir nuevos comportamientos
requerira entonces alteraciones en mltiples lugares, aumentando la oportunidad para
error y complicando flujos de trabajo paralelos para diseado res y programadores.
Para evitar este peligro, jQuery nos permite programar llamadas de funcin a activarse
una vez que se ha cargado el DOM, sin esperar a las imgenes, con la construccin $ (document) . ready () . Con nuestra funcin definida como antes, podemos escribir:
Through
by lewi,
the Looking-Glass
CanDil
1. Looking-Glass
H.ouse
Therewas a boot Iying rlCaf Auceen the tabla, 800 while she sal W8tchl~ theWhite King (fOfshe W8S51illa little anxiousabout hlm, 3M had the Ink all feady lo
IhJOWovar hlm. in case:he f.lnlQd ag.ain), ,he turrMld 0Vt!f tne leaves. lo fin<!som. p8Ji thal she aHJld ,ead, ~-fOf ir, all In tome language
I don', know,"S'ne said lo
1MfM:1t.
It WIU lb hls.
YKCOWREBBAJ
aelo'Oi yhtHa eht dna ,gillirb _wr
;ebaw ehl ni eJbei'J dna et)'9 diD
,H~ehtw.wj4llJti/Jl'
l/A
.abIugtuo mhu MKlIm ffht dnA
She puzzled 0W!f this for some time, but al last. bflgtrt lhoughl strud: h.. "Why, Ir. a L<x*ing-glau boOl. of cecrse!And If I hold 1I up lo a glaa. the words wlll all go
th4! tight.way 8gain,"
Thls was the poem lhal Allc. reed,
JAB8fRWOCKY
$Idocument)
.readylhighlightPoemStanzas);
Esta tcnica no requiere ninguna modificacin HTML. En su lugar, el comportamiento se anexa completamente desde el archivo JavaScript. Aprenderemos ms adelante
cmo responder a otros tipos de eventos, separando sus efectos desde la estructura
HTML tambin.
Esta encarnacin es todava un despilfarro porque la funcin highlightPoemStanzas () se define solamente para utilizarse inmediatamente, y exactamente una vez.
Esto significa que hemos utilizado un identificador en el espacio de nombres global de
funciones que tenemos que recordar no utilizar de nuevo. JavaScript, como otros lenguajes de programacin, tiene una forma de evitar esta ineficiencia denominada funciones
annimas (algunas veces tambin denominada funciones lambda). Al utilizar funciones
annimas, podemos escribir el cdigo como se present originalmente:
$Idocument)
.readylfunction()
{
$1' .poem-stanza')
.addClassl'highlight');
})
Al utilizar la palabra clave funct ion sin un nombre de funcin, definimos una funcin exactamente donde se necesita, y no antes. Esto elimina saturacin y nos lleva a tres
lneas de JavaScript. Este estilo es extremadamente adecuado en cdigo jQuery, ya que
muchos mtodos toman una funcin como un argumento y dichas funciones raramente
son reutilizables.
Cuando se utiliza esta sintaxis para definir una funcin annima dentro del cuerpo
de otra funcin, se puede crear un cierre. ste es un concepto avanzado y potente, pero
se debera entender cuando se haga amplio uso de definiciones anidadas de funcin ya
que puede tener consecuencias inesperadas y ramificaciones en el uso de memoria. Este
tema se trata en el Apndice C.
El producto terminado
Ahora que nuestro JavaScript est en su lugar, la pgina se parece a la que se muestra en la figura 1.2:
w.~
Las estrofas del poema ahora estn en cursiva y encerradas en cajas, como se ha especificado por la hoja de estilo alice. c s s, debido a la insercin de la clase highlight
por el cdigo JavaScript.
Resumen
Ahora ya tenemos una idea de por qu un desarrollador elegira utilizar un marco
de trabajo JavaScript en lugar de escribir todo el cdigo desde el principio, incluso para
las tareas ms bsicas. Tambin hemos visto algunas formas en las que jQuery sobresale como marco de trabajo, y por qu podramos elegirlo sobre otras opciones. Tambin
sabemos en general qu tareas hace ms sencillas jQuery.
En este captulo, hemos aprendido cmo poner jQuery disponible para el cdigo
JavaScript en nuestra pgina Web, utilizar la funcin $ () para localizar una parte de la
pgina que tiene una clase dada, llamar a . addClass () para aplicar estilo adicional a
esta parte de la pgina, e invocar $ (documen t ) . ready () para hacer que este cdigo
se ejecute al cargarse la pgina.
El ejemplo sencillo que hemos utilizado demuestra cmo funciona jQuery, pero no
es de mucha utilidad en situaciones del mundo real. En el siguiente captulo, ampliaremos este cdigo al explorar el sofisticado lenguaje selector de jQuery, encontrando usos
prcticos para esta tcnica.
,,
""
.'
2
electores,
La librera jQuery aprovecha el potencial de los selectores CSS (Cascading Style Sheets
u Hojas de estilo en cascada) para permitimos acceder rpida y fcilmente a elementos o grupos de elementos en el DQM (Document Object Modelo Modelo de Objetos de
Documento). En este captulo, exploraremos algunos de estos selectores, as como los
selectores personalizados de jQuery. Tambin examinaremos los mtodos transversales DOM de jQuery que proporcionan incluso mayor flexibilidad para obtener lo que
queremos.
El DOM
Uno de los aspectos ms potentes de jQuery es su capacidad para que la seleccin de
elementos en el DOM sea sencilla. El DOM es una estructura en rbol de tipos. HTML,
como otros lenguajes de marcacin, utiliza este modelo para describir las relaciones de
cosas en una pgina. Cuando hacemos referencia a estas relaciones, utilizamos la misma
terminologa que utilizamos cuando hacemos referencia a relaciones familiares, padres,
hijos, etc.
Un sencillo ejemplo puede ayudamos a entender cmo la metfora del rbol familiar
se aplica a un documento:
e ht.ml
<:head>
<title>the
</head>
title</title>
IIPJI
,,
2. Selectores
<body>
<div>
ep>This
ep>This
ep>This
e/div>
e/body>
e/htrnl>
11m
Aqu, <h t ml > es el ancestro de todos los otros elementos; en otras palabras, todos
los otros elementos son descendientes de c ht.m Lc-. Los elementos -che ad y -ebody
no son slo descendientes, sino hijos de -cht.rnl., tambin. De igual forma, adems de
ser el ancestro de ehe ad y body, ht ml es tambin su padre. Los elementos <p>
son hijos (y descendientes) de <di V>, descendientes de body y <html , y hermanos
entre s. Para informacin sobre cmo visualizar la estructura de rbol familiar del DOM
utilizando software de terceros, consulte el Apndice B.
Un punto importante a destacar antes de empezar es que el conjunto de elementos
resultante desde selectores y mtodos siempre se encuentra situado en un objeto jQuery.
Es muy sencillo trabajar con objetos jQuery cuando queremos realmente hacer algo con
las cosas que encontramos en una pgina. Podemos fcilmente vincular eventos a estos
objetos y aadir les efectos, as como encadenar mltiples modificaciones o efectos juntos.
No obstante, los objetos jQuery son diferentes de los elementos DOM normales o listas de
nodo, y como tales no necesariamente proporcionan los mismos mtodos y propiedades
para algunas tares. En la ltima parte del captulo, por lo tanto, examinaremos formas
de acceder a los elementos DOM que se encuentran en un objeto jQuery.
La funcin factory
$0
Nombre etiqueta
$(/p/)
Selecciona
mento.
ID
#un-id
$(/#un-idl)
Clase
.una-clase
$(/.una-clase/)
Selecciona todos los elementos en el documento que tienen una clase de una-clase.
Tres bloques principales de estos selectores son nombre etiqueta, ID, y clase. Se pueden utilizar de forma independiente o en combinacin con otros selectores. La tabla 2.1
muestra un ejemplo del aspecto que tiene cada uno de estos tres selectores.
en el docu-
Como se ha mencionado en el captulo anterior, cuando anexamos mtodos a la funcin factory $ ( ) , se pasa en bucle automticamente e implcitamente por los elementos
situados en el objeto jQuery. Por lo tanto, podemos evitar normalmente la iteracin explcita, como un bucle for, que a menudo es necesario en programacin DOM.
Ahora que hemos tratado los aspectos bsicos, estamos listos para empezar a explorar algunos usos de selectores ms potentes.
Con independencia del tipo de selector que queremos utilizar en jQuery, siempre
empezamos con el signo de dlar y parntesis: $ () . Cualquier cosa que podemos utilizar en una hoja de estilo tambin se puede situar entre comillas y dentro de parntesis,
permitindonos aplicar mtodos jQuery al conjunto coincidente de elementos.
id=llselected-plays >
<li>Comedies
<ul>
I
<li><a href="/asyoulikeit/n>As
You
eli>All/s
Well That Ends Well</li>
eli>A Midsurnrner Night/s
Drearne/li>
Like
It</a></li>
11m
2.Selectores
<li>Twelfth
.horizontal
{
float, left;
list-style: none;
margin: l?;pX
Night</li>
</ul>
</li>
<li>Tragedies
<ul>
<li><a href="hamlet.pdf">Harnlet</a></li>
<li>Macbeth</li>
<li:>Romeo and Juliet</li>
</ul>
</lb
<li:>Histories
<ul>
<li>Henry
IV
}
.sub-level
(
background:
ll
V</a></li>
Comedes
o As You Uke lt
o AIt's Well That Ends Well
o A Midsummer NIght's Dream
o lWelfth Night
Histories
o Henry IV (email)
Pan!
PanlJ
o
Tragedles
o Hamlet
o Macbeth
o Romeo and Juliet
Histories
o Henry N (emall)
Part
Part
o HenrvV
o Richard II
HenryV
Richard lJ
Figura
#CCC
$ (document) .ready(function()
{
$(f#selected-plays
> li/) .addClass(/horizontal/);
})
II</li>
</ul>
</li>
</ul>
'"
La clase horizontal
flota el elemento a la izquierda del que le sigue, elimina el
boliche de l si es un elemento de lista, y aade un margen de 10 pxeles en todos los
lados.
En lugar de anexar la clase horizontal
directamente en nuestro HTML, lo aadiremos.dinmicamente
a los elementos de lista de nivel superior nicamente, Comedies,
Tragedies,
Histories,
para demostrar el uso de selectores de jQuery:
href=lImailto:henryiv@king.co.uk >email</a
<ul>
<li>Part
I</li>
<li>Part II</li>
</ul>
<li><a href="http://www.shakespeare.co.uk/henryv.htm">Henry
<li>Richard
Aplicar estilo a los otros elementos, los que no se encuentran en el nivel superior, se
puede realizar de varias formas.
Puesto que ya hemos aplicado la clase horizontal
a los elementos de nivel superior, una forma de seleccionar todos los elementos por debajo del nivel es utilizar una
pseudo-clase de negacin para identificar todos los elementos de lista que no tienen una
clase horizontal.
Observe la incorporacin de la tercera lnea de cdigo:
(document) .ready(function()
{
$(/#selected-plays
> li/) .addClass(/horizontal/);
$(/#selected-plays
li:not(.horizontal)/)
.addClass(/sub-level/);
})
I!'
lIIlII
2. Se/ectores
Digamos que queremos tener diferentes estilos para diferentes tipos de vnc;ulos.
Primero definimos los estilos en nuestra hoja de estilo:
(#selected-
Histories
o
o
o
o
o
o
o
o
Figura
a
color,
'"
#OOc;
).
lIiII
a.mailto
(
background,
url(images/mail.png)
padding-right,
18px;
no-repeat
right
top;
}
a .pdflink
(
background,
url(images/pdf.png)
padding-right,
18px;
no-repeat
right
top;
}
a.henrylink
{
background-color,
padding,
2px;
border,
lpx solid
#ff~;
#000;
2.3. Listaconfondosombreado.
Selectores de atributo
Los selectores de atributo son un subconjunto particularmente de utilidad de los selectores CSS.Nos permiten especificar un elemento por una de sus propiedades HTML,
como el atributo title
de un vnculo o el atributo alt de una imagen.
Por ejemplo, para seleccionar todas las imgenes que tiene un atributo al t , escribimos lo siguiente:
$ (limg [alt1 j)
Luego, aadimos las tres clases, mail t o, pdfl ink, y henryl Lrik, a los vnculos
apropiados utilizando jQuery.
Para aadir una clase para todos los vnculos de correo electrnico, construimos un
selector que busca todos los elementos ancla (a) con un atributo href ( [href) que empieza con mail to: (=mail to: 1 ), de la siguiente forma:
$( document) .ready(function()
(
$(/a[hrefA=mailto:l/)
.addClass(/mailto/);
}) ;
Para aadir una clase para todos los vnculos a archivos PDF, utilizamos el signo
de dlar en lugar del smbolo />. Esto es porque estamos seleccionando vnculos con un
atributo href que termina con. pdf:
$ (document) .ready(function()
{
$ (la [hrefA=mailto, 1/) .addClass (lmail to/) ;
$(/a[href$=.pdfl/)
.addClass(/pdflink/);
}) ;
Los selectores de atributo tambin se pueden combinar. Podemos, por ejemplo, aadir una clase henrylink para todos los vnculos con un valor href que empieza con
ht tp Ycontiene henry en cualquier lugar:
$Idocument) .readylfunctionl)
(
$(/a[hrefA=mailto:1/)
.addClassl/mailto/);
$1/a[href$=.pdf1/)
.addClassl/pdflink/);
$ (/a[hrefA=http1
[href*=henryl/l
.addClassl/henrylink/l;
}l ;
Con las tres clases aplicadas a los tres tipos de vnculos, deberamos ver la figura 2.4.
Observe el icono PDF a la derecha del vnculo Harnlet, el icono de sobre junto al vnculo
emal, y el fondo blanco y borde negro alrededor del vnculo Henry V.
KIlII
2. Selectores
<td>Macbeth</td>
<td>Tr~gedy</td>
<td>1606</td>
</tr>
o
...
<tr>
o
o
<tr>
Selectores personalizados
Para la amplia variedad de selectores CSS,jQuery aade sus propios selectores personalizados. La mayora de los selectores personalizados nos permiten elegir ciertos
elementos de una lnea, por as decirlo. La sintaxis es la misma que la sintaxis de pseudo-clase CSS, donde el selector empieza con dos puntos (:). Por ejemplo, para seleccionar el segundo elemento de un conjunto coincidente de selectores di v con una clase de
horizontal,
escribimos esto:
$(1 div.horizontal,eq(l)1)
Observe que: eq ( 1) selecciona el segundo elemento en el conjunto porque la numeracin de tabla JavaScript es de base cero, lo que significa que empieza con O. Por el contrario, CSSes de base uno, parla que un selector CSScomo $ (/di v: nth-child
(1) /)
seleccionara todos los selectores di v que son el primer hijo de su padre (en este caso,
sin embargo, utilizaramos probablemente $ (/di v: first -childj)
en su lugar).
<td>comedy</td>
<td></td>
</tr>
<.tr>
<td>All/s
Well
<td>Henry V</td>
<td>History</td>
<td>1599</td>
</tr>
</table>
Ahora podemos aadir un estilo a la hoja de estilo para todas las filas de tabla, y utilizar una clase alt para las filas pares:
tr
background-color,
#fff;
.alt (
background-color,
#ccc;
Por ltimo, escribimos nuestro cdigo jQuery, anexando la clase a las filas de tabla
pares (etiquetas e t r s ):
$ (document) .ready(function()
(
$(/tr,odd/) .addClass(/alt/);
})
Pero, iespere! Por qu utilizar el selector :odd para las filas pares? Bueno, como
con el selector : eq ( ) , los selectores : odd y : even utilizan la numeracin en base cero
nativa de JavaScript. Por lo tanto, la primera fila cuenta como O (par) y la segunda fila
cuenta como 1 (impar), etc. Con esto en mente, podemos esperar que nuestro sencillo
cdigo produzca una tabla que se parece a la figura 2.5:
<td>comedy</td>
<td>1601</td>
</tr>
<.tr>
<td>Hamlet</td>
<td>Tragedy</td>
<td>1604</td>
</tr>
<.tr>
2. Selectores
Observe que podemos ver resultados no deseados si existe ms de una tabla en una
pgina. Por ejemplo, puesto que la ltima fila en esta tabla tiene un fondo blanco, la primera fila en la siguiente tabla tendr el fondo gris "alterno". Una forma de evitar este
tipo de problema es utilizar el selector :nth - child () en su lugar. Este selector puede
tomar un nmero, odd, o even como su argumento. Sin embargo, : nth-child
() es
el nico selector jQuery que es en base uno. Para conseguir las mismas bandas de filas
que hemos realizado antes, y para que sea consistente entre mltiples tablas en un documento, el cdigo se parecera a esto:
$ (document) .ready(function()
(
$(/tr,nth-child(even)/)
.addClass(/alt/);
))
Para un ltimo toque de selector personalizado, supongamos por alguna razn que
queremos resaltar cualquier celda de tabla que haga referencia a una de las obras que
contienen Henry.
Todo lo que tenemos que hacer, despus de aadir una clase a la hoja de estilo para
que aparezca el texto en negrita y cursiva ( .highlight
{font-'(i'eight
:bold;
font-style:
i talics;
}), es aadir una lnea a nuestro cdigo jQuery, utilizando el
selector : contains
() .
$ (document) .ready(function()
(
$ (/tr,nth-child(even)/)
.addClass(/alt/);
$ (/td:contains(Henry)/)
.addClass(/highlight/);
})
Por lo tanto, ahora podemos ver nuestra hermosa tabla a rayas con las obras de Henry
destacadas de forma notable (vase la figura 2.6):
Selector.es de formulario
Cuando.se trabaja con formularios, los selectores personalizados de jQuery pueden
facilitar seleccionar simplemente 10'8 elementos que necesitamos. La tabla 2.2 describe
un conjunto de estos selectores.
Tabla
: text, :checkbox,
: radio, : image, :submit,
:reset, :password, :,file
: input
:button
:enabled
:disabled
:checked
:selected
e v
select,
y but ton.
Como con otros selectores, los selectores de formulario se pueden combinar para
mayor especificidad. Podemos, por ejemplo, seleccionar todos los botones de opcin
seleccionados (pero no las casillas de verificacin) con $ (/ : radio: checked/)
o
seleccionar todas las entradas de contrasea y entradas de texto deshabilitadas con
$ (/ : pas sword, : text : di sabled/ ) .Incluso con selectores personalizados, utilizamos
los mismos principios bsicos de CSS para crear la lista de elementos coincidentes.
Los selectores jQuery que hemos explorado hasta el momento nos permiten seleccionar un conjunto de elementos a medida que navegamos por el rbol DOM y filtrar los
resultados. Si sta fuera la nica forma de seleccionar elementos, nuestras opciones estaran bastante limitadas (aunque, francamente, las expresiones de selector son robustas
por derecho propio, especialmente cuando se compara con las opciones de programacin
DOM normal). Existen muchas ocasiones cuando seleccionar un elemento padre o ancestro es esencial; aqu es donde los mtodos transversales DOM de jQuery entran en juego.
Con estos mtodos a nuestra disposicin, podemos recorrer el DOM con facilidad.
Algunos de los mtodos tienen un equivalente casi idntico entre las expresiones
de selector. Por ejemplo, la lnea que primero hemos utilizado para aadir la clase al t,
EJI
,,
2. Selectores
(/ alt/)
t,
filter
()
{
&& this.hostname
IE~
!=
mil
As You Llke It
Comed y
IAU's Well t/lllt Ends weU C./ledY ,lE,]
Tragedy 1604
Hamlet
.addClass(/altj);
Sin embargo, en su mayor parte, las dos formas de seleccionar elementos se complementan entre s. Igualmente, el mtodo. f i 1ter () en particular tiene un enorme poder
porque puede tomar una funcin como su argumento.
La funcin nos permite crear pruebas complejas para determinar si los elementos se
deberan mantener en el conjunto que coincide. Supongamos, por ejemplo, que queremos
aadir una clase a todos los vnculos externos. jQuery no tiene selector para este tipo de
caso. Sin una funcin de filtro, estaramos forzados a pasar en bucle explcitamente por
cada elemento, comprobando cada uno por separado. Con la siguiente funcin de filtro,
sin embargo, podemos seguir basndonos en la iteracin implcita de jQuery y mantener
nuestro cdigo compacto:
$(/a/) .filter(function()
return this.hostname
)) .addClass(/external/);
"Ii!!
I&e~ii IV:el!r.I: h
Henry V
~g!!I'~4J
'Ti'agedy 1595
'~'i.:jIt!sto!i:';1596]
Hlstory
1599
El mtodo . next () selecciona solamente el siguiente elemento hermano. Para resaltar todas las celdas que siguen a la que contiene Henry, podramos utilizar el mtodo
. nextAll () en su lugar.
$ (document) .ready(function()
{
$ (/td:contains
(Henry)/) .nextAll()
}) ;
.addClass(/highlight/);
location.hostname
Para incluir la celda original (la que contiene Henry) junto con las celdas que siguen,
podemos aadir el mtodo. andSelf () :
Ms precisamente, el mtodo . f i 1ter () itera por el conjunto coincidente de elementos, comprobando el valor de retorno de la funcin. Si la funcin devuelve f alse, el
elemento se elimina del conjunto coincidente. Si devuelve true, el elemento se mantiene.
Ahora, echemos un vistazo a nuestra tabla a rayas de nuevo para ver qu ms es posible con los mtodos transversales.
$ (document) .ready(function()
{
$ (/td:contains(Henry)/)
.nextAll()
})
.andSelf()
.addClass(/highlight/);
.children()
.addClass(/highlight/);
});
Anteriormente hemos aadido una clase resaltada a todas las celdas que contenan
el texto Henry. Por el contrario, para aplicar estilo a la celda junto a cada celda que contiene Henry, podemos empezar con el selector que ya hemos escrito, y simplemente encadenar a ste el mtodo next ( ) :
$ (document) .ready(function()
{
$(/td:contains(Henry)/).next()
}) ;
Encadenar
.addClass(/highlight/);
EII
2. Selectores
de cdigo. Este encadenamiento no solamente ayuda a mantener el cdigo jQuery conciso, sino que tambin puede mejorar el rendimiento de un script cuando la alternativa
es volver a especificar un selector.
Tambin es posible dividir una sola lnea de cdigo en mltiples lneas para mayor
legibilidad. Por ejemplo, una sola secuencia de mtodos encadenada se podra escribir
como una lnea ...
$ (/td:contains(Henry)/)
.parent() .find(/td:eq(l)/)
.addClass(/highlight/)
.end() .find(/td:eq(2)/)
.addClass(/highlight/)
;
"Henry"
Ciertamente, el DOM transversal en este ejemplo es sinuoso hasta el punto del absurdo. En realidad no recomendaremos su uso, ya que existen mtodos claramente ms
sencillos y ms directos a nuestra disposicin. El objetivo del ejemplo es simplemente
demostrar la tremenda flexibilidad que nos permite el encadenamiento.
Encadenar puede ser como decir todas las palabras de un prrafo en un solo respiro, acabas rpidamente, pero puede ser difcil para cualquier otra persona entenderlo. Dividirlo en mltiples lneas y aadir comentarios puede ahorrar ms tiempo a la
larga.
myTag
$ (/#my-element/)
.get(O) .tagName;
.mil
myTag
$ (/#my-element/)
'"
[OJ .tagName;
No en vano esta sintaxis se parece a una tabla de elementos DOM; utilizar los corchetes es como retirar el envoltorio jQuery para llegar a la lista de nodo s, mientras que
al incluir el ndice (en este caso, O), es como arrancar un elemento DOM .
Resumen
Con las tcnicas que hemos tratado en este captulo, ahora deberamos poder aplicar
estilo a los elementos de nivel superior y subnivel en una lista anidada al utilizar selectores CSS bsicos, aplicar diferentes estilos a diferentes estilos de vnculos al utilizar
selectores de atributo, aadir bandas a una tabla al utilizar los selectores personalizados jQuery : odd y : even o el selector CSS avanzado: nth- child () , y resaltar texto
dentro de ciertas celdas de tabla al encadenar mtodos jQuery.
Hasta el momento, hemos utilizado el evento $ (document) . ready () para aadir
una clase a un conjunto coincidente de elementos. En el siguiente captulo, exploraremos formas en las que aadir una clase en respuesta a una variedad de eventos iniciados por el usuario.
.'
3
Eventos
ElII
3. Eventos
todo elemento en la pgina se puede manipular por JavaScript, lo que es de gran ayuda
para escribir cdigo sin tener que preocuparse por el orden en que se carga.
Por otro lado, un manejador registrado utilizando $ (document) . ready () se invoca cuando el DOM est complemente listo para su uso. Esto tambin significa que todos
los elementos son accesibles por nuestros scripts, pero no significa que se ha descargado
todo archivo asociado. Tan pronto como se ha descargado y analizado el HTML en un
rbol DOM, el cdigo puede ejecutarse.
Para asegurarse de que la pgina tiene aplicado estilo antes de que se ejecute el cdigo
JavaScript, es una buena prctica situar etiquetas <link z e L " stylesheet"
> antes
de las etiquetas scr-.pt dentro del elemento head del documento.
Considere, por ejemplo, una pgina que presenta una galera de imgenes; dicha
pgina puede tener muchas imgenes grandes, que podemos ocultar, mostrar. mover y
manipular con jQuery. Si configuramos nuestra interfaz utilizando el evento onload, los
usuarios tendrn que esperar hasta que cada una de las imgenes se ha descargado por
completo antes de que puedan utilizar la pgina. Incluso peor, si los comportamientos
todava no se han anexado a elementos que tienen comportamientos predeterminados
(como los vnculos), las interacciones de usuario podran producir resultados no deseados. Sin embargo, cuando utilizamos $ (document) . ready () para la configuracin,
la interfaz se prepara mucho antes con el comportamiento correcto.
{
tarea ...
11>
O bien, podramos
window.onload
doStuff
Ambos enfoques harn que la funcin se ejecute cuando se carga la pgina. La ventaja
de la segunda es que el comportamiento est ms separado del cdigo.
Observe que cuando asignamos una funcin como un manejador, utilizamos el nombre
de la funcin pero omitimos los parntesis finales. Con los parntesis, la funcin se
invoca inmediatamente; sin ellos, el nombre simplemente identifica la funcin, y se
puede utilizar para invocarla ms tarde.
Con una funcin, esta estrategia funciona bastante bien. Sin embargo, suponga que
tenemos una segunda funcin:
function
doOtherStuff()
(
11 Realizar otra tarea.
Luego podramos tratar de asignar esta funcin para que se ejecute cuando se carga
la pgina:
window.onload
EJI
doOtherStuff;
Sin embargo, esta asignacin supera a la primera. El atributo. onload puede almacenar solamente una referencia de funcin de cada vez, por lo que no podemos aadir
al comportamiento existente. El mecanismo $ (document) . ready () gestiona esta situacin. Toda llamada al mtodo aade la nueva funcin a una cola interna de comportamientos; cuando se carga la pgina, se ejecutarn todas las funciones. Las funciones
se ejecutarn en el orden en que se han registrado.
Para ser justos, jQuery no tiene el monopolio de la solucin a esta cuestin. Podemos
escribir una funcin JavaScript que forma una nueva funcin que invoca el manejador
onload existente, luego llama a un manejador pasado. Este enfoque, utilizado por
ejemplo por el addLoadEvent () de Siman Willison, evita conflictos entre manejadores rivales como hace $ (document) . ready ( ) , pero carece de algunos de los otros
beneficios que hemos tratado. Los mtodos especficos de navegador como documen t .
addEventListener
() ydocument. attachEvent
() ofrecenfuncionalidadsimiJar,
pero jQuery nos permite conseguir esta tarea sin preocupamos por inconsistencias de
navegador.
ElII
3. Eventos
podemos escribir:
})
$() .ready(function()
// Nuestro cdigo
jQuery(function($)
(
/
/ Cdigo que utiliza
(
aqu ..
lIlIII
anteriormente:
$.
});
Adems, la funcin factory puede tomar otra funcin como argumento. Cuando hacemos esto, jQuery lleva a cabo una llamada implcita a . ready () , por lo que para el
mismo resultado podemos escribir:
$(function()
{
// Nuestro cdigo
Aunque estas otras sintaxis son ms breves, los autores recomiendan la versin ms
larga para que quede claro lo que est haciendo el cdigo.
<script
jQuery .noConflict ();
</script>
<script src="rnyscript.jsll
Existen muchos otros momentos aparte de cargar la pgina en los que podramos
querer llevar a cabo una tarea. Igual que JavaScript nos permite interceptar el evento
de carga de pgina con -c bo'd'y >> o window. onload, proporciona enlaces
similares para eventos iniciados por el usuario como clics del ratn (onc 1i ck), campos
de formulario que se modifican (onchange), y ventanas que cambian de tamao (onresize). Cuando se asignan directamente a elementos en el DOM, estos enlaces tienen
desventajas similares a las que hemos detallado para onload. Por lo tanto, jQuery ofrece
una forma mejorada de gestionar estos eventos tambin.
11 11
aqu.
j);
<script
<script
Eventos sencillos
type="text/javascript"></script>
ll
id=1!switcher-defaultll>
3,Eventos
Aprende jQuery
<:div class="buttonn
Narrow Colunm
</div>
cdiv
class=l'buttonrr
Large Print
id=lIswitcher-narrowlI>
1,3
lID
el mtodo. bind () . Este mtodo nos permite especificar cualquier evento JavaScr,ipt, y
anexarle un comportamiento. En este caso, el evento se denomina click, y el comportamiento es una funcin que consta de nuestra lnea anterior:
id=,rswitcher-large">
'\...
</div>
</div>
$ (docurnent).ready(function()
Combinados con el resto del cdigo HTML de la pgina y algo de CSS bsico, obtenemos una pgina que se parece a la figura 3.1.
{
$ (/#switcher-large/) .bind(/click/,
$ {/body/l .addClass (/large/l ;
}) ;
})
function()
Ahora cuando se pulsa el botn, se ejecuta nuestro cdigo y el texto se agranda como
se muestra en la figura 3.2.
Style Switcher
I
A Chrlstmas
Dofault
~~
II
!I!
'Narrow
Column
,.:,' ~1~~~;,,~~i:.~
~~::
1.1
largo Prtnt
>;; , '
'J
10:"
Carol
by Charles Olckens
Carol
Preface
t HAVE endeevoured In this GhosUy te book, to ralse the GhoSI ot an Idea, whlchshall not put my raaders out or humour wlth
themselVes, wlth each other, wlth Ole season, or wlth me, May lt haunt lhelr houses pleasantly, and no ona wtsh to lay It.
C.D.
I HAVE endeavoured in this Ghostly little book, to raise the Ghost of an Idea, which
shall no! put my readers out of humour wi!h themselves, with each other, with !he
season, or wi!h me. May it haunt their houses pleasantly,and no one wish to lay it.
December, 1843.
1: Marley's
Ghost
MARlEY was dead: to begin with, There Is no doubt whatever about tha!. The reglster ot hls buriel was slgned by lhe clergyman, the
clerk, Ihe undertaker, and the chlef moumer. Scrooge slgned It: and Scrooge's name was 9000 upon 'Changa, ror anythlng he chose
lo put hls hand to. Old Martey was as dead as a doornall.
Mlndll donl mean lo say mar 1I<now, 01 my own knowledge, whal tIlere Is panlcularty dead about a door-nall. I mlghl haye besn
Inclinad, myselt, to regard a comn-ne as me deadest plece of lronmongery In the ttade. But the wfsdom 01 our ancestors Is In the
slmile; and my unhaUowed hands shall not distorb 11.cr the Country's done foro You witl therefore permlt me lo rapeat, emphatlcally,
.chapter (
font-size:
by Charles..Dlckens
Preface
Stave
A Chrlstmas
1.Semi
Nuestro objetivo, entonces, es aplicar la clase large a la etiqueta -cbody. Esto permitir que la hoja de estilo vuelva a aplicar formato a la pgina de forma apropiada.
Utilizando lo que hemos aprendido en el captulo anterior, ya conocemos la sentencia
necesaria para conseguir esto:
$ Ubody/) .addClass (/large/);
Sin embargo, queremos que esto ocurra cuando se hace clic en el botn, no cuando
se carga la pgina como hemos visto hasta el momento. Para hacer esto, presentaremos
e.o.
December, 1843.
Esto es lo que se necesita para vincular un evento. Las ventajas que hemos tratado
con el mtodo. ready () se aplican aqu, tambin. Mltiples llamadas a . bind () coexisten sin problema, aadiendo comportamiento adicional al mismo evento segn sea
necesario. Esta no es necesariamente la forma ms elegante o eficiente de realizar esta
tarea. A medida que avanzamos por este captulo, ampliaremos y mejoraremos este cdigo en algo de lo que estemos orgullosos.
"
3. Eventos
el i ck a cada uno de ellos, eliminando y aadiendo clases segn sea necesario. El nuevo
cdigo se muestra as:
$ (document) .ready(function() {
$ (/#switcher-default/) .bind(/click/, function() {
$ (/body/) .removeClass(/narrow/);
$ (/body/) .removeClass(/large/);
}) ;
$ (/#switcher-narrow/) .bind(/click/, function() {
$ (/body/) .addClass(/narrow/);
$ (/body/) .removeClass(/large/);
Contexto
de manejador
<body>,
1.3
devolvien.
de-evento
Nuestro conmutador se est comportando correctamente, pero no estamos proporcionando al usuario ninguna informacin sobre qu botn est actualmente activo. Nuestro
enfoque para gestionar esto ser aplicar la clase selected al botn cuando se hace clic,
y eliminar esta clase de los otros botones. La clase selected simplemente pone el texto
del botn en negrita:
j);
Aprende jQuery
.selepted {
font-weight:
bold;
.'
A Christmas
Situar esta lnea en cada uno de los tres manejadores aadir la clase cuando se hace
clic en un botn. Para eliminar la clase de los otros botones, podemos aprovechamos de
la caracterstica de iteracin implcita de jQuery, y escribir:
Carol
$(/#switcher
by Charles Dlekens
Pmface
I HAVE endeavoured In thls GhosUy IIWe book, lo ralse Ihe Ghost 01 an
Idea, WhICh shall Mal put rny readers out of humour wlth themselves, wlth
eaeh other, wlth the season, or wlth me. May it haunt thelr houses
pleasantly, and no ane wlsh lo ley It.
Thelr faithful Friend and Servant,
C. D.
December, 1843.
5tave 1: Marley',
Ghost
MARLEY was oeac: to begln wlth. Therels no doubl whatever about that
The reglster of hls bunal was slgned by Ille clergyman. Ille elell<. Ille
undartaxer, and the chlef mourner. Scrooge slgned it: and Scrooge's name
was good upon 'Changa, tor anythlng he chose lo put hls hand to. Old
Mariey W8S as dead as B door-nau.
.button/) .removeClass(/selected/);
Esta lnea elimina la clase de cada botn dentro del conmutador de estilo. Por lo tanto,
al situados en el orden correcto, tenemos el cdigo como:
$ (document) .ready(function() {
$ (/#switcher-default/) .bind(/click/. function() {
$ (/body/) .removeClass(/narrow/);
$ (/body/) .removeClass(/large/);
$(/#switcher .button/) .removeClass(/selected/);
$(this) .addClass(/selected/);
}) ;
$ (/#switcher-narrow/) .bind(/click/, function() {
$ (/body/) .addClass(/narrow/);
$ (/body/) .removeClass(/large/);
$(/#switcher .button/) .removeClass(/selected/);
$(this) .addClass(/selected/);
ElII
3. Eventos
}l;
$ (/#switcher-large/)
.bind(/click/,
function()
$ (/body/) .removeClass(/narrow/)
;
$ (/body/) .addClass(/large/);
$(/#switcher
.button/) .removeClass(/selected/);
$(this) .addClass(/selected/);
}l;
$(/#switcher
.button/) .removeClass(/selected/);
$ (thistaddClass(/selected/)
;
}l;
})
}l;
Ahora el conmutador
en la figura 3.4.
de estilo proporciona
informacin
apropiada
como se muestra
'"
Esta optimizacin aprovecha las tres caractersticas jQuery que hemos tratado. En
primer lugar, iteracin implcita es de nuevo de utilidad cuando vinculamos el mismo
manejador el iek a cada botn con una sola llamada a . bind () . En segundo lugar,
poner en cola comportamientos
nos permite vincular dos funciones al mismo evento
eliek, sin que el segundo sobrescriba el primero. Por ltimo, estamos utilizando las
posibilidades de uso de encadenamiento de jQuery para reducir la adicin y eliminacin
de clases a una lnea de cdigo cada vez.
S(ylo SWitcher
I
A Christmas
Oefawl
I LNa:~ I I
Colurnn
La~.
Prtnl
Carot
Preface
I HAVE endeavoured in lhis Ghostly little book, lo raise the Ghost of an Idea, whih
shall not put my readers out of humour with themselves, wilh each other, with lhe
sea son, or with me. May it haunt their houses pleasanlly, and no one wish lo lay it,
Mayor consolidacin
La optimizacin de cdigo que acabamos de completar es un ejemplo de refactorizacin, es decir, modificar cdigo existente para llevar a cabo la misma tarea en una
forma ms eficiente o elegante. Para explorar ms oportunidades
de refactorizacin,
echemos un vistazo a los comportamientos
que hemos vinculado a cada botn. El parmetro del mtodo. removeClass () es opcional; cuando se omite, elimina todas las
clases del elemento. Podemos mejorar nuestro cdigo un poco al hacer uso de esto de
la siguiente forma:
$ (document)
.ready(function()
$ (/#switcher-default/)
.bind(/click/,
$ (/body/) .removeClass();
function()
}) ;
$ (/#switcher-narrow/)
.bind(/click/,
function()
$ (/body/) .removeClass()
.addClass(/narrow/);
C.D.
})
December, 1843.
$ (/#switcher-large/)
.bind(/click/,
function()
$ (/body/) .removeClass()
.addClass(/large/);
})
informacin
$U#switcher
.button/) .bind(/cliCk/,
function()
$(/#switcher
.button/) .removeClass(/selected/);
$(this) .addClass(/selected/);
})
})
Observe que el orden de las operaciones ha cambiado un poco para acomodar la eliminacin general de nuestra clase; necesitamos ejecutar. removeClass () primero de
modo que no deshaga el . addClass () que realizamos al mismo tiempo.
$ (/#switcher-narrow/)
.bind(/click/,
function()
{
$ (/body/) .addClass(/narrow/)
.removeClass(/large/);
})
$ (/#switcher-large/)
.bind(/click/,
$ (/body/) .removeClass(/narrow/)
})
function()
{
.addClass(/large/);
$(/#switcher
.button/)
.bind(/click/,
function()
Solamente podemos eliminar de forma segura todas las clases porque estamos a cargo
del HTML en este caso. Cuando escribimos cdigo para reutilizar (como para un plug-in),
necesitamos respetar cualquier clase que pudiera estar presente y dejarla intacta.
3. Eventos
Ahora estamos ejecutando parte del mismo cdigo en cada uno de los manejadores
de los botones. Esto se puede separar fcilmente en nuestro manejador general click
de botn:
$ (document) .ready(function()
{
$(/#switcher
.button/) .bind(/click/.
function()
$ (/body/) .removeClass();
$(/#switcher
.button/) .removeClass(/selected/);
$ (this) .addClass (/selected/);
})
})
})
$ (document) .ready(function
11 {
$(/#switcqer
.button/) .click(function()
$ (/body/) .removeClass();
if (th~s.id == /switcher-narrow/)
(
$I!body /) .addClass I/narrow.':) ;
}
.
$ (/#switcher-narrow/)
.bind(/click/.
$ (/body/) .addClass(/narrow/);
}I;
$ (/#switcher-large/l
.bind (/click/.
$ (/body/) .addClass(/large/);
function()
$(/#switcher
.button/) .removeClass(/selected/);
$(this) .addClass(/selected/);
})
})
function
() (
Los mtodos de evento abreviados como ste existen para todos los eventos DOM
estndar:
.
Observe que necesitamos mover el manejador general por encima del especfico
ahora .. removeClass () necesita ocurrir antes de . addClass (), y.podemos contar
con esto porque jQuery siempre activa manejadores de evento en el orden en que se registraron.
Por ltimo, podemos libramos de los manejadores especficos por completo al hacer
uso una vez nuevamente del contexto de evento. Puesto que la palabra clave de contexto this nos proporciona un elemento DOM en lugar de un objeto jQuery, podemos
utilizar las propiedades DOM nativas para determinar el ID del elemento sobre el que
se hico clic. Podemos as vincular el mismo manejador a todos los botones, y dentro del
manejador llevar a cabo diferentes acciones para cada botn:
$ (document) .ready(function()
{
$(/#switcher
.button/) .bind(/click/.
$ (/body/) .removeClass();
if (this.id == /switcher-narrow/)
$ (/body/) .addClass(/narrow/);
function()
}
else if (this.id == /switcher-large/)
$ (/body/) .addClass(/large/);
}
$(/#switcher
.button/) .removeClass(/selected/);
$(this) .addClassl/selected/);
})
Eventos abreviados
Vincular unmanejador para un evento (como un sencillo evento c l .ck) es una tarea
tan sencilla que jQuery proporciona una forma ms concisa de logrario; los mtodos de
evento abreviados funcionan de la misma forma que sus equivalentes. bind () con
algunas menos teclas del teclado. Por ejemplo, nuestro conmutador de estilo se podra
escribir utilizando. click () en lugar de . bind () de la siguiente forma:
blur
change
click
dblclick
error
focus
keydown
keypress
keyup
load
mousedown
mousemove
mouseout
mouseover
mouseup
resize
scroll
select
submit
unload
lIl.!II
3. Eventos
Eventos compuestos
Despus del primer clie, los botones se ocultan todos, como se muestra en la figura
siguiente.
La mayora de los mtodos de gestin de eventos de jQuery corresponden directamente a eventos JavaScript nativos. Sin embargo, unos cuantos son manejadores personalizados aadidos por conveniencia y optimizacin entre navegadores. Uno de estos, el
mtodo. ready ( ), ya lo hemos tratado en detalle. Los mtodos. toggle () y . hover ()
son dos manejadores de evento personalizados; ambos se conocen como manejadores
de evento compuestos porque interceptan combinaciones de acciones de usuario, y responden a ellas utilizando ms de una funcin.
Mostrar y
ocultar
'-.
Figura
caractersticas avanzadas
none;
Podramos implementar esta caracterstica al almacenar el estado actual de los botones en una variable, y comprobar su valor cada vez que se hace clie en la etiqueta para
saber si aadir o eliminar la clase hidden en los botones. Tambin podramos comprobar directamente la presencia de la clase en un botn, y utilizar esta informacin para
decidir qu hacer. En su lugar, jQuery proporciona el mtodo. toggle (), que lleva a
cabo esta tarea por nosotros.
Figura
Una vez ms nos basamos en.iteracin implcita; esta vez, para ocultar todos los botones de una sola vez sin necesidad de un elemento que lo englobe.
Para este caso especfico,jQuery proporciona otro mecanismo para la accin que estamos llevando a cabo. Podemos utilizar el mtodo. toggleClass
() para comprobar
automticamente la presencia de la clase antes de aplicarla o eliminarla:
$ (document) .ready(function()
{
$ (j#switcher
h3!) .click (function
$(!#switcher
})
})
.button!)
() {
.toggleClass(!hidden!);
})
})
.button!)
.removeClass(!hidden!);
los
#afa;
fiII
3,
Eventos
}I ;
})
ll
dog,
'"
<r
How razorback-jumping
<!p>
<!div>
gymnasts!
<div>
$ (document) ,ready(function()
{
$(!#switcher
,button!) ,hover(function()
$(this) .addClass(!hover!);
}, function () (
$(this) ,removeClass(!hover!);
cdiv class=f'foo">
cspan class,.=l1bar >
<a href=lIhttp://www.example.comjll>
The Ruick brown fox jumps ayer the lazy
<la>
</span>
m-.
.'
A Christmas Carol
In Prose, Being a Ghost Story o, Christmas
by Charles Dlckens
Pteface
Para cualquier evento, existen mltiples elementos que podran ser responsables lgicamente de reaccionar.
Cuando se hace clic en el vnculo en esta pgina, por ejemplo, el <di v , <span>, y
<a> todos deberan tener la oportunidad de responder al clic, Despus de todo, los tres
estn bajo el cursor del ratn del usuario al mismo tiempo. El elemento <P>. por otro
lado, no es parte de esta interaccin en absoluto.
Una estrategia para permitir que mltiples elementos respondan a un clic se denomina
captura de eventos. Con captura de eventos, el evento se pasa primero al elemento ms
global, y luego sucesivamente a los ms especficos. En nuestro ejemplo, esto significa
que primero el evento se pasa a d .v, luego a c span, y por ltimo a <a>, como se
muestra en la figura 3.9.
El uso de . hover () tambin significa que evitamos dolores de cabeza causados por
propagacin de evento en JavaScript. Para entender esto, necesitamos echar un vistazo
a cmo JavaScript decide qu elemento gestiona un evento dado.
<div>
El viaje de un evento
Cuando ocurre un evento en una pgina, toda una jerarqua de elementos DOM tiene
la oportunidad de gestionar el evento. Considere un modelo de pgina como ste:
3. Eventos
manejador de evento. Esta secuencia de burbujeo es probable que no se desee; para los
botones en nuestro conmutador de estilo de ejemplo, podra significar que el que aparezca resaltado se desactive prematuramente.
El mtodo . hover () es consciente de estos problemas de burbujeo, y cuando utilizamos ese mtodo para anexar eventos, podemos ignorar los problemas causados por
el elemento errneo con un evento mouseover o mouseout. Esto hace que. hover ()
sea una alternativa muy atractiva para vincular los eventos individuales de ratn.
Si solamente se tiene que realizar una accin cuando el ratn entra o abandona un
elemento, pero no ambos, podemos vincular los eventos mouseenter y mouseleave
de jQuery, que tambin eluden los problemas de burbujeo. Sin embargo, estos eventos
se emparejan tan a menudo, que. hover () es por lo general la opcin correcta.
<div>
r-~--="""'"
})
}J;
Esta alteracin hace que se pueda hacer clic sobre todo el rea del conmutador de
estilo para alternar su visibilidad. La desventaja es que hacer clic en un botn tambin
contrae el conmutador de estilo despus de que el estilo en el contenido se ha alterado.
Esto se debe al burbujeo de evento; el evento se gestiona primero por los botones, luego
Se pasa al rbol DOM hasta que llega a <di v id= swi tcher
, donde nuestro nuevo
manejador se activa y oculta los botones.
Para solucionar este problema, necesitamos acceder al objeto event. sta es una
construccin JavaScript que se pasa al manejador de evento de cada elemento cuando
11
11
m.
3. Eventos
.:
se invoca. Proporciona informacin sobre el evento, como dnde se encontraba el cursor del ratn en el momento del evento. Tambin proporciona algunos mtodos que se
pueden utilizar para afectar el progreso del evento por el DOM.
Para utilizar el objeto event en nuestros manejadores, solamente necesitamos aadir
un parmetro a la funcin:
}
el se if (this.id == /switcher-large/)
$ (/body/) .addClass(/large/);
$(/#switcher
.button/) .removeClass(/selected/};
$(this) .addClass(/selected/);
event.stopPropagation{)
II ;
})
Este cdigo se asegura de que el elemento sobre el que se hace clic sea <di v
id=" swi tcher
, no uno de sus subelementos. Ahora hacer clic en los botones no plegar el conmutador de estilo, y hacer clic en el fondo del conmutados-s, Sin embargo,
hacer clic en la etiqueta, <h3 , ahora no hace nada, porque tambin es un subelemento.
En lugar de situar esta comprobacin aqu, podemos modificar el comportamiento de
los botones para conseguir nuestros objetivos.
11
$ (document) .ready(function(}
{
$(/#switcher
.button/) .click(function(event)
$ (/body/) .removeClass();
if (ths.id == /switcher-narrow/)
$ (body/)
. addClass (/narro~i) ;
$ (document) .ready(function()
$ (/#switcher/) .click(function(event}
{
$(/#switcher
.button/) .toggleClass(/hidden/};
}} ;
)}
})
Acciones predeterminadas
Si nuestro manejador de evento click se registrara sobre un elemento de vnculo
a en lugar de un d .v genrico, tendramos otro problema. Cuando un usuario
hace die sobre un vnculo, el navegador carga una nueva pgina. Este comportamiento
no es un manejador de evento en el mismo sentido que hemos venido discutiendo; en su
lugar, se trata de la accin predeterminada para un die sobre un elemento de vnculo. De
forma similar, cuando se pulsa la tecla Intro mientras el usuario edita un formulario, se
activa el evento submi t en el formulario, pero entonces el envo del formulario ocurre en
realidad despus de esto. Sino se desean estas acciones predeterminadas, invocar. stopPropaga ti on () sobre el evento no ayudar. Estas acciones no ocurren en ningn sitio
en el flujo normal de la propagacin de evento. En su lugar, el mtodo. preventDefaul t () servir para detener el evento antes de que se active la accin predeterminada.
ElII
3. Eventos
Delegacin de evento
El burbujeo de eventos no siempre es un obstculo; a menudo lo podemos utilizar
para obtener beneficio. Una tcnica estupenda que hace uso del burbujeo se denomina
delegacin de evento. Con ello, podemos utilizar un manejador de evento sobre un solo
elemento para realizar el trabajo de muchos.
.'
}
})
})
$ (document) .ready(function()
(
$ (/#switcher/)
.click(function(event)
(
if ($ (event.target)
.is(/.button/))
(
$ (/body/) .removeClass();
if (event.target.id
== /switcher-narrow/)
$ (/body/) .addClass(/narrow/);
}
if (event.target.id
== /switcher-large/)
$ (/body/) .addClass(/large/);
else
$(/#switcher
.button/) .removeClass(/selected/);
$(event.target)
.addClass(/selected/);
el se if (event.target.id
== /switcher-large/)
$ (/body/) .addClass(/large/);
}
$(/#switcher
.button/)
.removeClass(/selected/);
$ (event.target)
.addClass(/selected/);
event.stopPropagation()
;
}
})
})
})
})
.mil
3. Eventos
}
})
Existen momentos en los que habremos terminado con un manejador de evento que
hemos registrado previamente. Quiz el estado de la pgina ha cambiado tanto que la
accin ya no tiene sentido. Normalmente es posible gestionar esta situacin con sentencias condicionales dentro de nuestros manejadores de evento, pero puede ser ms elegante quitar la vinculacin del manejador por completo.
Suponga que queremos que nuestro conmutador de estilo que se puede contraer permanezca expandido siempre que la pgina no utiliza el estilo normal. Aunque el botn
Narrow Column O Large Print est seleccionado, hacer clc en el fondo del conmutador
de estilo no debera hacer nada. Podemos realizar esto al invocar el mtodo. unbind ( )
para eliminar el manejador para contraer cuando se hace clic en uno de los botones no
predeterminados del conmutador de estilo.
$.I/#swi tcher-narrow,
#switcher-large/l.
click Ifunction
$I/#switcher/)
.unbindl/click.collapse/);
}J;
1)
}J;
El sufijo. eollapse
es invisible para el sistema de gestin de evento; los eventos
el iek se gestionan por esta funcin, igual que si escribiramos. bind (1 eliek/)
. Sin
embargo, la incorporacin del espacio de nombres significa que podemos desvincular slo
este manejador, sin afectar al otro manejador eliek que escribimos para los botones.
Existen otras formas de hacer que nuestra llamada . unbind () sea ms especfica,
como veremos en un momento. Sin embargo, el espacio de nombres de evento es una
herramienta de utilidad en nuestro arsenal. Es especialmente de utilidad en la creacin
de plug-ins, como veremos ms adelante en el libro.
$Idocument) .readylfunctionl)
(
$I/#switcher/)
.clicklfunctionlevent)
(
if 1!$levent.target)
.isl/.button/))
(
$I/#switcher
.button/) .toggleClassl/hidden/);
}
})
$I/#switcher-narrow,
#switcher-large/)
$I/#switcher/)
.unbindl/click/);
}) ;
.clicklfunctionl)
}) ;
Ahora cuando se hace clic en un botn como Narrow Column, el ranejador eliek
en el conmutador de estilo <di v se elimina, y hacer clic en el fondo de la caja ya no
lo contrae. Sin embargo, el botn ya no funciona. Est anexado al evento eliek del
conmutador de estilo <di v tambin porque volvimos a escribir el cdigo de gestin
de botn para utilizar delegacin de evento. Esto significa que cuando invocamos
$ (/#switeher
1) . unbind (/ cliek/),
se eliminan ambos comportamientos.
};
$I/#switcher/)
toggleStyleSwitcher);
1"
3. Eventos
Observe que aqu estamos utilizando una nueva sintaxis para definir una funcin. En
lugar de definir la funcin al empezar con la palabra clave function,
asignamos una
funcin annima a una variable local. Se trata de una eleccin de estilo para hacer que
nuestros manejadores de evento y otras definiciones de funcin se parezcan ms entre
s; las dos sintaxis son funcionalmente equivalentes.
Tambin, recuerde que. bind () toma una referencia de funcin como su segundo
argumento. Es importante recordar, cuando se utiliza una funcin con nombre aqu, omitir los parntesis despus del nombre de funcin; los parntesis harn que se invoque
la funcin en lugar de que se le haga referencia. Ahora que la funcin tiene un nombre,
podemos vincularla nuevamente ms adelante sin repetir la definicin de funcin:
$ (/#switcher/)
.click(toggleStyleSwitcher);
$ (/#switcher-narrow,
#switcher-large/)
.click(function()
$ (/#switcher/) .unbind(/click/,
toggleStyleSwitcher);
}) ;
$ (/#switcher-default/)
.click(funebion()
(
$ (/#switcher/) .click(toggleStyleSwitcher);
})
})
Un mtodo abreviado se encuentra tambin disponible para la situacin en la que queremos desvincular un manejador de evento inmediatamente despus de la primera vez
, que se activa. Este mtodo abreviado, denominado. one ( ) r se utiliza de esta forma:
$ (doument) .ready(function()
(
$ (/#switcher/) .one(/click/,
toggleStyleSwitcher);
$ (document) .ready(function()
(
var toggleStyleSwitcher
= function(event)
if (!$(event.target)
.is(/.button/)
{
$(/#switcher
.button/) .toggleClass(/hidden/);
})
.bind(/click.collapse/,
toggleStyleSwitcher);
.'
$ (/#switcher-narrow,
#switcher-large/)
.click(function()
$ (/#switcher/) .unbind(/click.collapse/);
})
$ (/#switcher-default/)
.click (function
$ (/#switcher/)
.bind(/click.collapse/,
})
})
() (
toggleStyleSwitcher);
};
A Chrlstmas
Carol
Preface
3. Eventos
El mtodo. trigger
() proporciona el mismo conjunto de mtodos abreviados que
.bind () . Cuando se utilizan estos mtodos abreviados sin argumentos, el comportamiento es activar la accin en lugar de vincularla:
$ (/#switcher-default/)
break;
case /N/:
.~(/#switcher-narrow/)
break;
$ (document) .ready(function()
$ (/#switcher/) .click();
})
case
Eventos de teclado
Como otro ejemplo, podemos aadir mtodos abreviados de teclado a nuestro conmutador de estilo. Cuando el usuario escribe la primera letra de uno de los estilos, hacemos que la pgina se comporte como si se hiciera clic sobre el botn correspondiente.
Para implementar esta caracterstica, necesitaremos explorar eventos de teclado, que se
comportan algo diferente de los eventos de ratn. Existen dos tipos de eventos de teclado: aquellos que reaccionan al teclado directamente (keyup y keydown) y aquellos que
reaccionan a entrada de texto (keypress). Un solo evento de entrada de ,carcter podra
corresponder a varias teclas, por ejemplo cuando la tecla Mays en combinacin con
la tecla X crea la letra mayscula X. Aunque los detalles especficos de implementacin
difieren de un navega dar a otro (no es de sorprender), una regla general es la siguiente:
si desea saber qu tecla ha pulsado el usuario, debera observar el evento keyup o keydown; si desea saber qu carcter termin en pantalla como resultado, debera observar
el evento keypress.
Para esta caracterstica, simplemente queremos saber cuando el
usuario pulsa la tecla D, N, o L, por lo que utilizaremos keyup.
A continuacin, necesitamos determinar qu elemento debera estar pendiente del
evento. Esto es un poco menos obvio que con los eventos de ratn, donde tenemos un
cursar de ratn obvio que nos habla del destino del evento. En su lugar, el destino de un
evento de teclado es el elemento que actualmente tiene el foco del teclado. El elemento
con foco se puede cambiar de varias formas, incluidos clics del ratn y pulsaciones de la
tecla Tab. No todos los elementos pueden tener el foco, tampoco; solamente los elementos que tienen comportamientos predeterminados dirigidos por teclado como campos
de formulario, vnculos y elementos con una propiedad. t ab tndex-son candidatos.
En este caso, realmente no nos importa qu elemento tiene el foco; queremos que
nuestro conmutador funcione siempre que el usuario pulsa una de las teclas. El burbujeo
de eventos ser de nuevo de utilidad, ya que podemos vincular nuestro evento keyup
al elemento doeument y tener la seguridad que con el tiempo cualquier evento de tecla
burbujear hasta nosotros.
Por ltimo, necesitaremos saber qu tecla se puls cuando nuestro manejador keyup
se activa. Podemos inspeccionar el objeto event para esto. La propiedad . keyCode del
evento contiene un identifica dar para la tecla que se ha pulsado, y para teclas alfabticas,
este identificador es el valor ASCII de la letra mayscula. Por lo tanto podemos habilitar
el valor y activar el clic de botn apropiado:
$ (document) .ready(function()
(
$ (document) .keyup(function(event)
{
switch
(String.fromCharCode(event.keyCode))
case /D/:
.click();
.click();
~'"'tt
/L/:
$ (/#switcher-Iarge/)
break;
.click () ;
}
j);
})
Pulsar estas tres teclas ahora simula clics del ratn sobre los botones, siempre y cuando
ese evento de tecla no se interrumpa por caractersticas como la de "buscar texto cuando
empiezo a escribir" de Firefox.
Corno alternativa a utilizar . trigger
() para simular este clic, exploremos cmo
separar cdigo en una funcin de modo que ms de un manejador pueda invocarlo, en
este caso, el iek y keyup. Aunque no necesario en este caso, esta tcnica puede ser de
utilidad al eliminar redundancia de cdigo.
$ (document)
.ready(function()
/1
})
sobre
los botones
del conmutador
.removeClass(/hover/);
// Permitir
que el conmutador
de estilo se amplie
var toggleStyleSwitcher
= function(event)
{
if (! $ (event. target) .is (/ .button/))
{
$(/#switcher
.button/)
o colapse
.toggleclass(/hidden/);
};
$ (/#switcher/)
.click(toggleStyleSwitcher);
// Simular un clic de modo que empezamos
$ (/#switcher/) .click();
en un estado
// La funcin setBodyClass()
cambia el estilo
// El estado del conmutador
de estilo tambin
var setBodyClass
= function(className)
(
$ (/body/) .removeClass()
;
$ (/body/) .addClass(clasSName);
$(/#switcher
$(/#switcher-/
if (className
de pgina.
se actualiza.
.button/) .removeClass(/selected/);
+ className) .addClass(/selected/);
== /default/) (
$ (/#switcher/)
.click(toggleStyleSwitcher);
}
else
$ (/#switcher/) .unbind(/click/,
toggleStyleSwitcher);
$(/#switcher
.button/) .removeClass(/hidden/);
};
// Invocar setBodyClass()
cuando se hace
$ (/#switcher/)
.click(function(event)
{
clic
colapsado
en un botn
de estilo
,
Aprende jQuery 1.3
3. Eventos
if
($(event.target) .is(/.button/))
{
if (event.target.id
== /switcher-default/)
setBodyClass(/default/)
;
}
if
(event.target.id
==
setBodyClass(/narrow/)
else
if
(event.target.id
setBodyClass(/large/)
==
/switcher-large/)
// Invocar
setBodyClass()
cuando
case /D/,
setBodyClass(/default/)
break;
case /N/,
setBodyClass
(/narrow/) ;
break;
case /L/,
setBodyClass(/large/)
() .
Utilizar manejadores de evento de teclado para reaccionar a pulsar una tecla por
el usuario con. keyup ( ) .
$ (document) .keyup(function(event)
(
switch (String.fromCharCode(event.keyCode))
break;
}
}lo
})
}
})
/switcher-narrow/)
Resumen
Las posibilidades de uso que hemos tratado en este captulo nos permiten:
Permitir que mltiples libreras JavaScript coexisten en una sola pgina utilizando
. noConflict
().
Utilizados juntos, podemos utilizar estas posibilidades de uso para crear pginas bastante interactivas. En el siguiente captulo, aprenderemos cmo proporcionar feedback
visual para el usuario durante estas interacciones.
,
,
--."
/~.........
"'" .
.' (~
.~.'"
"t;
t' !
. "'(j)'
'.
"'(3).
'I'~.'U""
-.
~"~
/~.', ~
~ ,.
..---.,,
. ~
","".
,/
l.'~O ..
>'--".
".
,,
.'
I ~..
.'
"(!l..
;'
~"
-::.
I~
'
~.
.~(':'"':"~~~"-"'I,
,~~'
'b.".,
r--....
..
'
'.
r-:.:
.1 '.'
~
<!>
1
/'~"
F"
.'~\-(!)".,.:
ti~,
:
()
o~'~
'
" .
x.,
'!\,.c;,.. "'r':'~.
."
"~
4:>
@l)~;/
-:",'f.5{. ..~,/
0...
'-..\ ,..--''.
/~~'
~'.'.@
. '.
....
_-'~<,
"~'/
'A
---_.-..
--'iW
'.~
' - --rsp --
.,
",
/'
._~
--::::'
,.::\.
'()
(@I;.--.,.
..
. -.......
''''1F
,_"
'V'
.., ''''''''
..'-..
'{
""
~.
'~.
' @)
,.'.; hg,~;.
O-
,.~:
'"
'. '.
\~,~
..
_
@r.-...., '"
{,
'.
---~.
'-
t,,,,
7\w,; "
1"\
..
r.) '...
..
,~~
~...,'
~it,/
\~,
~~-r.
'\
\ ../~'0-----..,- .~.'
,.~..
I
_\ '
fr~l.,~",
- .!~ ] ...
,
,~
"""
-~.
...
,.--~:\
~$C"\l\,
'1.:;:;>
..,
\-~!
A!>
, ~. ..''
:""'>',,,-,
.:
.~
~,~?.f~(~'
QP\ /'W \
. --",
. -, ~,
#"~.
\'1,.~../. /"'h'~h'
.'~
.'
". .'-"
a.:;--..""','
>
. "
.'
fectos
Si las acciones dicen ms que las palabras, entonces en el mundo JavaScript, los efectos
hacen que las acciones digan an ms. Con jQuery, podemos aadir fcilmente impacto a nuestras acciones por medio de un conjunto de sencillos efectos visuales, e incluso
disear nuestras propias animaciones ms sofisticadas.
Los efectos jQuery aaden ciertamente atractivo, como es evidente cuando vemos
elementos que aparecen gradualmente en lugar de aparecer todos a la vez. Sin embargo,
tambin pueden proporcionar importantes mejoras de usabilidad que ayudan a orientar
al usuario cuando existe algn cambio en una pgina (especialmente comn en aplicaciones AJAX), En este captulo, exploraremos una serie de estos efectos y los combinaremos de formas interesantes,
E!II
4. Efectos
.css('propertY','value')
.css({propertyl:
'valuel',
'property-2':
'value2'})
lIlJII
$ (document) .ready(function()
(
$('#switcher-large')
.click(function()
}) ;
})
A continuacin, el tamao de fuente se puede descubrir fcilmente al utilizar el mtodo . css (): $ ( di v. speech
css ( fontSi ze
Sin embargo, puesto que el
valor devuelto incluir un px final, necesitaremos retirar esa parte para llevar a cabo
clculos con el valor. Igualmente, cuando pretendemos utilizar un objeto jQuery ms
de una vez, generalmente es una buena idea guardar en cach el selector al almacenar
el objeto jQuery resultante en una variable tambin.
I
Utilizamos el mtodo. css () de igual forma que hemos estado utilizando. addClass () ; es decir al encadenarlo a un selector y vincularlo a un evento. Para demostrar
esto, regresaremos al ejemplo del conmutador de estilo del captulo anterior, pero con
diferente HTML:
cdiv id=11switcher'l>
cdiv class="lahel'I>Text
Sizec/div>
<buttan id= switcher-default
>Defaultc/button>
<buttan id="switcher-large >Biggerc/button>
<buttan
id=llswitcher-small">Smallerc/button>
11
11
ll
</div>
cdiv class=l'speech">
<p>Fourscore and seven years ago our fathers brought forth
on this continent a new nation, conceived in liberty,
and dedicated
to the proposition
that all men are created
equal.</p>
</div>
Al vincular a una hoja de estilo con algunas reglas de estilo bsicas, la pgina inicialmente se parece a la figura 4.1.
Abraham Lincoln's Gettysburg Address
I )
EDefault'~@lrgger ~
smaller}
Fourscore and seven years ago our fathers brought forth on thls contlnent a new natlon, conceved In Ilberty, and dedlcated
to the proposltlon that all men are created equal.
$ (document) .ready(function()
(
var $speech = $('div.speech')
$('#switcher-large')
.click(function()
var num = parseFloat($speech.css('fontSize'),
})
})
I )
10);
Text Slze
I :
IIEII
4. Efectos
$ (document) .ready(function()
{
var $speech = $(!div.speech');
$('#switcher-large') .click(function()
{
var num = parseFloat($speech.css('fontSizer)
num *= 1.4;
$speech.css('fontSize',
num + 'px
j);
j);
10 );
l);
Recuerde del captulo anterior que podemos acceder a la propiedad id del elemento
DOM referenciado por this, que aparece aqu dentro de las sentencias if y else if.
Aqu, es ms eficiente utilizar thi s que crear un objeto jQuery slo para comprobar el
valor de una propiedad.
,
Es tambin interesante tener una furma de devolver el tamao de fuente a su valor
inicial. Para permitir que el usuario realice esto, podemos simplemente almacenar el
tamao de fuente en una variable inmediatamente cuando el DOM est listo. Luego
podemos utilizar este valor siempre que se hace die en el botn Default. Para gestionar
este clic, podramos aadir otra sentencia else if. Sin embargo, quiz una sentencia
swi tch sera ms apropiado.
) . ready (funct ion () {
var $speech = $('div_speech');
var defaultSize = $sp~ech.css(lfontSizel);
$('#switcher button') .click(function()
{
var num = parseFloat(
$speech.css('fontSize'),
switch (this.id) {
case 'switcher-large':
num *= 1.4;
break;
case 'switcher-small':
num 1= 1.4;
break;
default:
num = parseFloat(defaultSize,
10);
}
$speech.css('fontSize',
num + IpXI);
(documerit
Ahora cuando un usuario hace die en el botn Bigger, el texto se hace ms grande.
Otro clic, y el texto se hace todava ms grande, como se muestra en la fi~ura 4.2.
Abraham
lincoln'sGettysburg
Address
Text Slze
@oefaiHt, E'Big~e~,~,smalfe,
Para hacer que el botn Smaller reduzca el tamao de la fuente, dividiremos en lugar
de multiplicar: num / = 1. 4. Mejor an, combinaremos los dos en un solo manejador
. click () en todos los elementos but.t.on dentro de <di v id=" switcher" >. Luego,
despus de averiguar el valor numrico, podemos multiplicar o dividir dependiendo del
ID del botn sobre el que se hizo die. Aqu tiene el aspecto que tiene el cdigo ahora:
$ (document) .ready(function()
{
var $speech = $('div.speech');
$ ('#switcher button') .click(function()
var num = parseFloat{
$speech.css('fontSize
if (this.id == 'switcher-large')
{
num *= 1.4
else if (this.id == 'switcher-small')
num 1= 1.4;
l)
$speech.css(!fontSize'{
})
j);
num + 'px) j
10 ) i
})
la );
j);
lIi!II
4. Efectos
Text Sze
Fourscore and seven years ago our fathers brougtbrorth on thls contlnent a new naton, concelved in liberty, and dedicated
to the proposltlon that all men are created equal.
read more
})
Luego, cuando el usuario hace dic en el vnculo read more al final del primer prra/ fo, ese vnculo se oculta y se muestra el segundo prrafo:
$ (document) .ready(function()
(
$('p:eq(l)
') .hide();
$ ('a.more') .click(furlction()
$ ( 'p :eq (1) ,) .show() ;
$(this) .hide();
return false;
}) ;
})
Observe el uso del return false para impedir que el vnculo active su accin predeterminada. Ahora el texto se parece a lo que se muestra en la figura 4.4:
-,
Text Slze
tDefauftq
~.Rigger'3
tSmaller,)
Foursc.ore and seven years ago our fathers brought forth on thls contlnent a new natlon, concelved in liberty, and dedlcated
to the proposltlon that al! men are created equal.
Now we are engaged tn a great dvH war, testlng whether that naton, or any nation so conceived and so dedicated, can long
endure. We are met on a great battlefleld of that war. We have come to dedlcate a portlon of that fleld as a final
restlng-place for those who here gavethelr
uves that the naton mlght Uve. It Is altogether fitting and proper that we
should do ttus. But~ in a larger sense, we cannot dedlcate, we cannot consecrate, we cannot hallow, this ground.
Los mtodos. hide () y . show () son rpidos y de utilidad, pero no son muy vistosos. Para aadir atractivo, podemos asignarles una velocidad.
Efectos y velocidad
Cuando incluimos una velocidad (o ms precisamente, una duracin) con . show ()
o . hide ( ) , se anima, es decir, ocurre durante un perodo especfico de tiempo. El mtodo. hide ( speed '), por ejemplo, reduce la altura, anchura y opacidad de un elemento simultneamente hasta que todos llegan a cero, en cuyo punto, se aplica la regla
CSS display: none. El mtodo. show ( speed ') aumentar la altura del elemento
de arriba a bajo, anchura de izquierda a derecha, y opacidad de O a 1, hasta que sus contenidos son visibles completamente.
I
E!II
4. Efectos
Aplicar velocidad
Esta vez cuando capturamos la apariencia del prrafo a la mitad, se puede parecer a
lo que se muestra en la figura 4.6:
Con cualquier efectojQuery, podemos utilizar una de las tres velocidades preestablecidas: 'slow', 'normal', y , fast '. Utilizar. show ( , slow' ) hace que el efecto mostrar se complete en .6segundos, . show ( 'normal' ) en.4 segundos, y . show ( , f as t ' )
en .2segundos. Para mayor precisin, podemos especificar un nmero de milisegundos,
por ejemplo . show ( 850) . A diferencia de los nombres de velocidad, los nmeros no
se sitan entre comillas.
Incluyamos una velocidad en nuestro ejemplo cuando mostramos el segundo prrafo
del Discurso de Gettysburg de Lincoln:
$ (document) .ready(function()
(
$ ('p,eq(l)') .hide ();
$ ('a. more') .click (function () {
$ ( 'p: eq (1) , ) . show ( "sLow ') ;
$ (this) .hide () ;
return false
)) ;
))
Fourscore and seven years ago our fathers brought forth on thls contlnent
dedlcated to the proposltlon that al! men are created equal.
a new
Now we are en9aged in a great ovil war, testing whether that nation, or any nation so coocetved and so dedlcated, can
long endure. We are met on a great battlefleld of that war. We have come to dedlcate a partlon of that field as a final
restlng-place for those who here gave tnelr uves that the natlon mlght IIve. It is altogether fitting and proper that we
should do thls. But, in a larger sense, we cannot dedica te, we cannot consecrate, we cannor hallow, this ground.
Text Slze
a new
Aparecer
Aunque los mtodos . show () Y . hide () son llamativos, a veces pueden ser
demasiado buenos. Afortunadamente, jQuery ofrece un par de otras animaciones
precreadas para un efecto ms sutil. Por ejemplo, para hacer que todo el prrafo aparezca al aumentar gradualmente la opacidad, podemos utilizar. fadeln ( , slow' ) en
su lugar:
$ (document) .ready(function()
$ ('p: eq (1) ,) .hide () ;
$('a.more')
.click(function()
$ ('p:eq(l)') .fadeln(' a Low
$ (this) .hide () ;
return false
)) ;
;
!Text Slze
Cuando capturamos la apariencia del prrafo en aproximadamente la mitad del efecto, vemos algo como lo que se muestra en la figura 4.5:
))
EJI
(
r
Efectos compuestos
Algunas veces tenemos una necesidad de alternar la visibilidad de elementos, en
lugar de mostrarlos de una vez como hicimos en el ejemplo anterior. Alternar se puede
conseguir al comprobar primero la visibilidad de los elementos coincidentes y luego al
anexar el mtodo apropiado. Utilizando los efectos de aparecer y desaparecer gradualmente, podemos modificar el script de ejemplo para que se parezca a esto:
$ (document) .ready(function()
(
var $firstPara
= $('p,eq(l)
');
$firstPara.hide();
$ ( 'a. more' ) .click (function () {
if ($firstPara.is('
:hidden'))
$firstPara.fadeln('slow')
$(this) .text('read
less');
else (
$firstPara.fadeOut('slow')
$(this) .text('read
more');
return
))
))
false
lImJI
4. Efectos
( $link. text ()
$link.text{'read
el se {
$link.text('read
return
})
})
==
"read
less
more"
(options})
.,
",
$ (document) .ready(function()
(
var $firstPara
= $('p:eq(l) ');
$firstPara.hide()
;
$ ('a.more') .click(function()
(
$firstPara.slideToggle('alow');
var $1ink = $(this);
if
.animate ({
propertyl:
property2:
) {
valuel' ,
'value2'
I
),
l);
duration:
'value',
easing:
value
I
more');
complete:
function ()
alert{'The animation
},
queue: boolean,
step: callback
false
})
Esta vez $ (ths) se habra repetido, por lo que lo estamos almacenando en la variable $1 Lnk por rendimiento y legibilidad. Tambin, la sentencia condicional comprueba
el texto del vnculo en lugar de la visibilidad del segundo prrafo, ya que solamente lo
estamos utilizando para cambiar el texto.
is finished. ') i
Por ahora, utilizaremos la primera forma del mtodo. anmate (), pero regresaremos
a la segunda forma ms adelante en el captulo cuando tratemos los efectos en cola.
Alternar el aparecer
$ (document) .ready(function()
$ ('p: eq (1) ,) .hide () ;
animation
is finished.
'value2'},
');
desaparecer paulatino
$('a.more')
.click(function()
{
$ ('p: eq (1) ,) .animate ({opacity:
'toggle'},
var $link = $(this);
if ( $link. text () == "read more" ) (
$link.text('read
less');
else (
$link.text('read
more');
.animate((propertyl:
'valuel', property2:
speed, easing,
function()
(
Cuando hemos tratado los efectos compuestos, ha observado que no todos los mtodos tienen un mtodo correspondiente para alternar? Correcto: aunque los mtodos
de desplazamiento incluyen. sl deTogg1e (), no existe. fadeTogg1e () correspondiente para continuar con . f ade 1n () y . f adeOu t ( ) . La buena noticia es que podemos
utilizar el mtodo. anmate () para crear nuestra propia animacin de alternar. Aqu,
reemplazaremos la lnea. sldeTogg1e
() del ejemplo anterior con nuestra animacin
personalizada:
2. Una velocidad opcional, que puede ser una de las cadenas preestablecidas o un
nmero de milisegundos.
alert('The
})
return
'slow');
false
Como ilustra el ejemplo, el mtodo. anmate () proporciona valores abreviados convenientes para propiedades CSS, ' show', h i de " Y togg1e " para facilitar el camino
cuando los mtodos abreviados no son del todo apropiados para la tarea determinada.
1
lIlllII
4. Efectos
Con el mtodo. animate (), podemos modificar cualquier combinacin de propiedades simultneamente. Por ejemplo, para crear un efecto deslizar y desvanecer simultneamente cuando alternamos el segundo prrafo, simplemente aadimos el par
propiedad-valor de height al mapa de propiedades de . animate () :
$ (document) .ready(function()
{
$ ( 'p: eq (1) ,) .hide () ;
$('a.more') .click(function()
$ ('p:eq (1) ') .animate ({
opacity: 'toggle',
height:
'toggle'
Abraham Li
Fou,"core
to the propositlon
-'
})
) {
false
Adems, no solamente tenemos a nuestra disposicin las propiedades de estilo utilizadas para los mtodos del efecto abreviado, sino tambin otras propiedades como: 1eft,
t op, fontSize,
margin, padding, y borderWidth. Recuerde al script que cambie
el tamao de texto de los prrafos. Podemos animar el aumentar y disminuir el tamao
con slo sustituir el mtodo. animate () por el mtodo. css () :
$ (document) .ready(function()
{
var $speech
= $('div.speech');
var defaultSize = $speech.css('fontSize')
i
$('#switcher
button') .click(function()
{
var num = parseFloat(
$speech.css('fontSize'),
switch
(this. id) {
case 'switcher-large':
num *= 1.4;
break;
case 'switcher-small
num /= 1. 4;
break;
default:
num = parseFloat(defaultSize,
10);
t:
Con un diseo de ancho flexible, necesitamos calcular la distancia que necesita recorrer la caja antes de alinearse a la derecha de la pgina. Asumiendo que el ancho del prrafo es 100por cien, podemos restar el ancho de la caja Text Size del ancho del prrafo.
Aunque el mtodo. width () de jQuery ser de utilidad para dichos clculos, no tiene
en cuenta el ancho del relleno derecho e izquierdo o el borde derecho e izquierdo. En
jQuery versin 1.2.6,tambin tenemos el mtodo. outerWidth () a nuestra disposicin.
Esto es lo que utilizaremos aqu para evitar tener que aadir anchos de relleno y bordes.
Para el objetivo de este ejemplo, activaremos la animacin al hacer die en la etiqueta Text
Size, por encima de los botones. Aqu tiene el aspecto que debera tener el cdigo:
$ (document) .ready(function()
{
$('div.label')
.click (function () {
var paraWidth
= $('div.speech
p') .outerWidth();
var $switcher
= $(this) .parent();
var switcherWidth
= $switcher.outerWidth();
$switcher.animate({left:
paraWidth
- switcherWidth,
height:
'+=20px',
borderWidth:
'spx'}, 'slow');
})
10 );
createc equal.
Figura
slow');
return
})
read more
},
var $link = $(this);
if ( $ link .text () == "read more"
$link.text('read
less');
else {
$link.text('read
more');
lmII
})
Observe que la propiedad height tiene += antes del valor del pxel. Esta expresin,
incorporada en jQuery 1.2, indica un valor relativo. Por lo tanto, en lugar de animar la
altura a 20 pxeles, la altura se anima a 20 pxeles mayor que la altura actual.
Aunque este cdigo aumenta con xito la altura del <di v y ensancha su borde, en
el momento la posicin 1eft no se puede cambiar. Necesitaremos habilitar cambiar su
posicin en el CSS.
}
$speech.animate({fontSize:
'slow') ;
})
})
num
"px
}.
Las propiedades adicionales nos permiten crear efectos mucho ms complejos, tambin. Podemos, por ejemplo, mover un elemento desde el lado izquierdo de la pgina al
II!PI
,
4. Efectos
Aprende jQuery 1.3
lIiD
embargo, esta vez, llevamos a cabo los tres efectos de forma secuencial, al situar cada
uno en su propio mtodo. animate () y encadenar los tres juntos:
$ (document) "teadY(function()
{
$('div.label')
.click(function()
,
(
var paraWidth
= $('div.speech
p') .outerWidth();
var $switcher
= $(this) .parent();
var switcherWidth
= $switcher.outerWidth();
$switcher
.animate({left:
paraWidth
- switcherWidth},
.animate({height:
'+=20px'},
'slow')
.anima te ({borderWidth:
'5px'}, 'slow');
}.);
Una mirada rpida a nuestra hoja de estilo muestra que ahora hemos establecido
<di v id=" swi tcher" > con posicin relativa:
#switcher
{
position:
j);
Recuerde que encadenar nos permite mantener los tres mtodos. animate () en la
misma lnea, pero aqu los hemos sangrado y situado cada uno en su propia lnea para
mayor legibilidad.
Podemos encolar cualquiera de los mtodos de efecto jQuery, no slo. animate (),
al encadenados. Podemos, por ejemplo, encolar efectos en <di v id=" swi tcher" > en
el siguiente orden:
relative;
Con el CSS tenido en cuenta, el resultado de hacer clic en Text Size, cuando la animacin se ha completado, se parecer a la figura 4.8.
AbrahamLincoln's
Gettysburg Address
,.-
"-..,
TextSlze
(~~
~BJgg3 (-'Smaller)
<,
() .
..-/'
() .
read more
Figura
Todo lo que necesitamos hacer es encadenar los efectos en el mismo orden en nuestro cdigo:
$ (document)
Efectos simultneos
.click(function()
var paraWidth
= $('div.speech
p') .outerWidth();
var $switcher
= $(this) .parent();
var switcherWidth
= $switcher.outerWidth();
$switcher
.fadeTo('fast',O.5)
.animate({
},
'left':
'slow')
paraWidth
- switcherWidth
.fadeTo('slow',l.O)
.slideUp ('slow' )
.slideDown('slow')
.ready(function()
$('div.label')
})
----------------
ll!!II
4. Efectos
(document) .ready(function()
{
$('div.label')
.click(function()
$ (document) .ready(function()
{
$('div.label')
.click(function()
{
var paraWidth
= $('div.speech
p') .outerWidth()
var $switcher
= $(this) .parent();
var switcherWidth
= $switcher.outerWidth();
var
var
;
},
"
'left': paraWidth
"e Low! )
- switcherWidth
1,
#fOO
I )
{
p') .outerWidth()
$switcher
= $(this) .parent();
switcherWidth
= $switcher.outerWidth();
- switcherWidth
}, 'slow')
.fadeTo('slow',l.O)
.slideUp('slow')
.css('backgroundColor','#fOO')
.slideDown('slow') ;
})
() ;
,slideDown('slow')
})
$switcher
.fadeTo('fast',0.5)
})
$switcherl'"uterWidth
})
paraWidth
.fadeTo('slow'
,1.0)
.slideUp (,s Low ')
.queue (function () {
$switcher
})
.animate({
'left':
$ ('div.speech
p') .outerWidth()
$(this) .parent();
.fadeTo('fast',0.5)
.animate({
var
var
. esa ( 'backgroundColor
.dequeueJ);
$ (document) .ready(function()
{
$('div.label')
.click(function()
var paraWidth
= $('div.speech
paraWidth
$switcher
var switcherWidth
$switcher
$switcher
.fadeTo('fast'
,0.5)
.animate({
'left': paraWidth - switcherwidth
}, {duration:
'slow', queue: false})
.fadeTo('slow',l.O)
.slideUp (,slow' )
.slideDown('slow')
;
})
})
lIiD
class=111abel >Text
<button
<button
<button
</div>
ll
Size</div>
id=lIswitcher-defaultll>Default</button>
id=lrswitcher-largetl>Bigger</button>'
id=tlswitcher-small">Smaller</button>
lI!IiI
4. Efectos
.click(function()
{
$(this) .slideUp('slow')
.next () . slideDown (1 s Low "} ;
cdiv class="speech">
<p>Fourscore and seven years a90 our fathers brought forth
on this continent a new nation, conceived in liberty, and
dedicated to the proposition that a11 men are created
equal.
</p>
<p>Now we are engaged in a great civil war, testing whether
that nation, or any nation so conceived and so dedicated,
can long endure. We are met on a great battlefield of
that war. We have come to dedcate a partian of that
field as a final resting-place
for those who here gave
their lives that the nation might live. It is altogether
fitting and proper that we should do this. But, in a
larger sense, we cannot dedcate, we cannot consecrate,
we cannat hallow, this ground.
</p>
<a href="#"
class="moreu>read
maree/a>
<p>The brave men, living and dead, who Btruggled
here have consecrated it, far above our poor
power to add or detracto The wor1d wi11 1ittle
note, nor long remember, what we say here, but it
can never forget what they did hare. It ia for ua
the living, rather, te be dedicated here to the
unfinished work which they who fought here have
thus far so nobly advanced.
</p>
<p>It is rather for ua te be here dedicated to the
great task remaining before us-that from
these honored dead we take increased devotion to
that cause for which they gave the 1ast fu11
measure of devotion-that we here highly
resolve that these dead shall not have died in
vain-that this nation, under God, shall
have a new birth of freedom and that government
of the people, by the people, for the people,
sha11 not perish from the earth.
</p>
</div>
})
})
'#eee') .hide();
Una captura de estos dos efectos confirma que, de hecho, se producen prcticamente
al mismo tiempo, como muestra la figura 4.9:
e brave men, livIng and dead, wha stnJggled hera have consecrated It, far above our poor power to add or detract.
rld wlll IIttle note nor Ion
m
sa h r
I
e e
wh t th
did here. It Is ~ rus
~~H~lii~~:w~"t~;~\t~ -
1~~~~']j~~~~
The
El tercer prrafo, que empez visible, est a mitad de camino en el desplazarse hacia
arriba al mismo tiempo que el cuarto prrafo, que empez oculto, est a mitad de camino en el desplazarse hacia abajo.
Rellamadas
Con el objetivo de permitir encolar efectos en diferentes elementos, jQuery proporciona una funcin de rellamada para cada mtodo efecto. Como hemos visto con los
manejadores de evento y con el mtodo . queue ( ) , las rellamadas son simplemente funciones pasadas como argumentos de mtodo. En el caso de los efectos, aparecen como
el ltimo argumento del mtodo.
Si utilizamos una rellamada para encolar los dos efectos de desplazamiento, podemos hacer que el cuarto prrafo se desplace hacia abajo antes de que el tercer prrafo
se desplace hacia arriba. Veamos primero cmo configurar el mtodo. slideDown ()
con la rellamada:
$ (doeument) .ready(funetion()
$ ( "p :eq (2) , )
_css('border',
'lpx salid #333')
.eliek(funetion()
{
$(this) .next() .slideDown('slow',function()
// el cdigo aqu se ejecuta despus de que el desplazamiento
// hacia abajo del tercer prrafo ha terminado
$ (doeument) .ready(funetion()
{
$ ( 'p,eq (2) , ) . ess ('border', 'lpx sol id #333');
$ ("p : eq (3) ,) .ess ('baekgroundColor',
'#eee ') .hide ();
})
lIiiI
})
})
'#eee') .hide();
j);
Por ltimo, aadiremos el mtodo. click () al tercer prrafo de modo que cuando
se hace clc, el tercer prrafo se desplaza hacia arriba (y fuera de la vista), mientras que
el cuarto prrafo se desplaza hacia abajo (a la vista):
$ (doeument) .ready(function()
$ ('p,eq(2)')
.ess('border',
lIiII
4. Efectos
J.
'slow')
.fameTo('slow',l.O)
.slideUp('slow',
function()
!$switcher
$( document) .ready(function()
(
var $thirdPara
= $ ('p:eq(2) ');
$thirdPara
.css('border',
'lpx solid #333')
.click(function()
{
$ (this) .next () .slideDown ( 'slow' ,function
$thirdPara.slideUp('slow')
;
})
})
.css('backgroundCola~"
'#fOO');
})
-slideDown('slowt)
} );
})
11
En pocas palabras
()
lID
'#ccc'). hide () ;
Utilizar $thirdPara
dentro de la rellamada . slideDown () se basa en las propiedades de cierres. Trataremos este importante tema, aunque difcil de dominar, en el
Apndice C.
Esta vez, una captura a mitad de camino durante los efectos revelar que tanto el
tercer como el cuarto prrafo son visibles, el cuarto ha terminado de deslizarse hacia
abajo y el tercero est a punto de empezar a desplazarse hacia arriba, como se ve en la
figura 4.10.
e breve men, living Bnd dead, who struggled here have consecrated it, far above our poor power to add or detracl The
lrtd wlll IIttle note, nor long remcmber, what we say here, but It can never forget what they dld here. lt 15far us the
'living, rather, to be dedlcated here to the unflnlshed wor1c whlch they who fought here have thU5 far so nobly advanced.
Ahora que hemos tratado las rellamadas, podemos regresar al cdigo anterior en este
captulo en el que encolamos un cambio de color de fondo cerca del final de una serie de
efectos. En lugar de utilizar el mtodo. queue ( ) , como hicimos anteriormente, simplemente podemos utilizar una funcin de rellamada:
$ (document) .ready(function()
(
$('div.label')
.click(function()
{
var paraWidth
= $('div.speech
p') .outerWidth()
var $switcher
= $(this) .parent();
var switcherWidth
= $switcher.outerWidth();
$switcher
.fadeTo('slow'
,0.5)
.animate({
'left': paraWidth
- switcherWidth
Con todas las variaciones a considerar cuando se aplican efectos, puede resultar difcil recordar si los efectos ocurrirn simultneamente o de forma secuencial. Un breve
detalle podra ayudar:
1. Efectos en un solo conjunto de elementos son:
2.
Resumen
Al utilizar los mtodos de efectos que hemos explorado en este captulo, ahora deberamos poder aumentar y disminuir incrementalmente el tamao del texto al utilizar el
mtodo. ess () o . animate () .Tambin deberamos poder aplicar varios efectos para
ocultar y mostrar gradualmente elementos de pgina de diferentes formas y tambin
animar elementos, simultneamente o de forma secuencial, en una serie de formas.
En los cuatro primeros captulos del libro, todos nuestros ejemplos han implicado
manipular elementos que se han insertado directamente en el HTML de la pgina. En el
siguiente captulo, exploraremos formas en las que podemos utilizar jQuery para crear
nuevos elementos e insertarlos en el DOM all donde elijamos.
\,
/'
Manipul
D
.
cron
'"
Como un mago que hace aparecer un ramo de flores de su chistera, jQuery puede
crear elementos, atributos y texto en una pgina Web, como por arte de magia. Pero,
espere, hay mucho ms. Con jQuery, tambin podemos hacer desaparecer cualquiera
de estas cosas. Y,podemos tomar ese ramo de flores y transformarlo en una paloma con
<divclass="magic"
id="flowerstodove">dove</div>.
Manipular
atributos
A lo largo de estos cuatro captulos del libro, hemos estado utilizando los mtodos
. addClass () y . removeClass () para demostrar cmo podemos cambiar la apariencia
de elementos en una pgina. Efectivamente, lo que estos dos mtodos hacen es manipular el atributo de clase (o, en jerga de programacin DOM, la propiedad className).
El mtodo. addClass () crea o aade al atributo, mientras que. removeClass () lo
elimina o lo acorta. Aada a estos el mtodo. toggleClass
() que alterna entre aadir
o eliminar una clase, y tenemos una forma eficiente y robusta de gestionar clases.
No obstante, el atributo class es slo uno de los varios atributos a los que podemos necesitar acceder o cambiar: por ejemplo, id y rel y href. Para manipular estos
atributos, jQuery proporciona los mtodos. attr () y . removeAttr (). Podramos
incluso utilizar. at tr () y . removeAt tr () para modificar el atributo class, pero los
mtodos especializados. addClass () y . removeClass () son mejores en este caso
porque gestionan correctamente casos donde mltiples clases se aplican a un solo elemento, como <di v c Las s " first
second" >.
mi
5. Manipulacin
DOM
lID
atributo comn para todos los vnculos, podramos hacerlo con una sola lnea de cdigo
dentro de nuestro manejador $ (document)
. ready () :
$ (document) .,ady(function()
{
$ (!div.chapter a!) .attr({/rel!:
})
lexternal/});
Esta tcnica funciona porque queremos que el nuevo atributo re1 tenga el mismo
valor para cada vnculo. Sin embargo, a menudo los atributos que aadimos o cambiamos deben tener diferentes valores para cada elemento. Un ejemplo de esto es que para
cualquier documento
dado, cada id debe ser nico si queremos que nuestro cdigo
JavaScript se comporte de forma predecible. Para establecer un id nico para cada vnculo; abandonamos
la solucin de una lnea en favor del mtodo. each () de jQuery.
$ (document) .ready(function()
{
$ (!div.chapter a!) .each(function(index)
$(this) .attr({
!rel!: !external!,
lid!, !wikilink-! + index
<div class="chapter">
<p class="squaretl>Our Professional Men and Gentlemen are
Squares (to which class 1 myself belong) and Five-Sided
Figures or <a
href=''http://en.wikipedia.org/wiki/Pentagonu>pentagons
})
})
})
<la>.
<!p>
<p class=tlnobility hexagonl!>Next above these come the
Nobility, of whom there are several degrees, beginning at
Six-Sided Figures, or <a
href=''http://en.wikipedia.org/wiki/Hexagontl>Hexagons</a>,
and from thence rising in the number of their sides till
they receive the honourable title of <a
href="http: !!en.wikipedia.org!wiki!Polygon"
>Polygonal< la>,
or many-Sided. Finally when the number of the sides
becomes so numerous, and the sides themselves so small,
that the figure cannot be distinguished
from a <a
href=''http://en.wikipedia.org/wiki/Circle''>circle</a>,
he
is included in the Circular or Priestly arder and this is
the highest class of all.
El mtodo.
each (), que acta como un iterador explcito, es en realidad una forma
ms conveniente del bucle foro Se puede emplear cuando el cdigo que queremos utilizar en cada elemento en el conjunto de elementos coincidentes del selector es demasiado complejo para la sintaxis de iteracin implcita. En nuestra situacin, a la funcin
annima del mtodo . each () se le pasa un ndice que podemos anexar a cada id.
Este argumento de ndice acta como un contador, empezando en para el primer vnculo y aumentando
en 1 con cada vnculo sucesivo. De esta forma, establecer el id en
/wikilink/ + index proporciona
al primer vnculo un id de wiki1ink0, al segundo un id de wiki1ink-l,
etc.
<!p>
De hecho, podramos haber optado por iteracin implcita aqu, porque el mtodo
. a t t r () puede tomar una funcin como su segundo argumento, similar a la forma en
que el mtodo . f i 1t er () puede hacerla con su nico argumento como vimos en un
captulo anterior (vase http://docs.j
query. com/Attributes/attr#keyfn
para detalles). Sin embargo, utilizar. each () parece ms conveniente para nuestras
necesidades.
<p><span class="pull-quote">It
is a <span class="droptl>Law
of Nature<!span>
with us that a male child shall have
<strong>one more side</strong>
than his father</span>,
so
that each generation shall rise (as a rule) one step in
the scale of development and nobility. Thus the son of a
Square is a Pentagon the son of a Pentagon, a Hexagon
and so on.
<!p>
<!-- ...
cdigo contina ..
<!div>
Ahora podemos pasar por cada uno de los vnculos dentro de <di v c.l ass chapter
>
Y aplicarles atributos uno a uno. Si solamente necesitramos
establecer un valor de
11
11
II!I
5. Manipulacin
DOM
$ (document) .ready(function()
{
$ (!div.chapter
a [href*=wikipediaJ!)
.each(function(index)
var $thisLink
= $(this);
$thisLink.attr({
!rel!: !external!,
!id!, !wikilink-!
+ index,
!title!,
!learn more about ! + $thisLink.text()
}) ;
}) ;
}) ;
$ (document) .ready(function()
{
$(/<a href,,"#top">back
to top<!a>!);
$ (/<a id="top"><!a>!);
}) ;
r~-::J'
! at Wikipedia!
lI
I1
la funcin factory
$0
Una cosa que merece la pena destacar aqu es que ahora estamos almacenando
$ (this)
en una variable denominada $thisLink,
simplemente porque acabamos
utilizndola ms de una vez. Con estos tres atributos establecidos, el HTML del primer
vnculo, por ejemplo, ahora se parece a esto:
ea href=''http://en.wikipedia.org/wiki/Pentagon"
id= wikilink-O
title="learn
more about
Wikipediall>pentagons</a:>
II'BI
Par1 1, Section 3
Concernlng the Inhabltants
an excerpt
of Flatland
Ou', Professlonal Men and Gentlemen are Squares (to whlch class I myself belong)
and Flve-Slded Figures o, Pentagons.
Next above these come the Noblllty, of whom there are several degrees, beglnnlng
at SixaSlded Figures, or ~
and from thence rlslng In the number ef thelr
sldes tili they recelve the honourable tltle of ~,
or many-Slded. Finaily
when the number of the sldes beoomes so numerous, and the sldes themselves so
small, that the figure cannot be dlstingulshed from a~,
he Is ncluded In the
Circular or Pnestly arder; and thls is the hlghest dass of all.
rel=flexternalr,
Pentagons
at
revisada
Desde el principio de este libro, hemos venido utilizando la funcin $ () para acceder
a elementos en un documento. En cierto sentido, esta funcin se encuentra en la base de
la biblioteca jQuery, ya que se utiliza cada vez que anexamos un efecto, evento, o propiedad a un conjunto coincidente de elementos.
An ms, la funcin $ () tiene todava un truco ms dentro de su parntesis, una caracterstica tan potente que puede cambiar no solamente la apariencia visual sino tambin
los contenidos de una pgina. Con slo insertar un fragmento de cdigo HTML dentro
de los parntesis, podemos crear una estructura DOM enteramente nueva de la nada.
It Is a taw of Nature wlth us that a male chlld shall have one more slde than hls
father, so that each generatlon shall rse (as a rule) ene step In the scale of
develapment and noblllty. Thus the son of a Square Is a Pentagon; the son of a
Pentagon, a Hexagon; and so on.
But this- ruJe applies not aiways to the Tradesman, and stlll less often to the
Soldlers, and to the Werkmen; whe indeed can hardly be sald to deserve the name
of human Figures, slnce they have not all thelr sldes equel, Wlth them therefore
the Law of Nature does nat hold; and the son of an Isesceles (Le. a Trlangle with
two sfdes equal) remalns Isosceles stlll. Nevertheless, aU hope 15 not such out,
even fi"om the lsosceles, that hls posterltv may ultlmately rise above hls degraded
condltion ....
Rarely-In
proportlon te the vast numbers of Isesceles blrths-Is
a genulne and
certlflable Equal-Slded Trlangle produced fi"om Isosceles parents. "WhDl.ud ofa
certtjlCtlle?" a Space1a;d crtdc may ast.' "/$ 1101lhe prrJC1'f!allon of SqllQn Son G ~rt!ftctJ(efrom
Narure hose/f. pnnoJng lile EquaJ...Jldedlll!Ss 01 Ih~ Fatlrer?" I reply ,hal no Lady olO1ly posmon wlll
marry an uncerlifo'd 1HiJngle.. Squan offtprl'W II(JJ sometlmllS resulted from a slightly 'TmplaT
Q
"
Deberamos recordar, una vez ms, el peligro inherente de poner cierta funcionalidad,
atractivo visual o informacin textual disponible solamente a aquellos con navegadores
Web que pueden (o tienen habilitado) utilizar JavaScript. La informacin importante
debera estar accesible a todos, no solamente a las personas que parece que estn
utilizando el software correcto.
Pero, dnde estn los vnculos para volver arriba y el ancla? No deberan aparecer
en la pgina? La respuesta es no. Aunque las dos lneas crean los elementos, todava no
aaden los elementos a la pgina. Para hacer esto, podemos utilizar uno de los muchos
mtodos de insercin jQuery.
jQuery tiene dos mtodos para insertar elementos antes de otros elementos:
. insertBefore
() y . before ( ) . Estos dos mtodos tienen la misma funcin; su diferencia se encuentra solamente en cmo se encadenan a otros mtodos. Otros dos mtodos. insertAfter
() y . after (), mantienen la misma relacin entre s, pero como
sugiere su nombre, insertan elementos detrs de otros elementos. Para los vnculos de
volver arriba utilizaremos el mtodo. insertAfter
() :
lmJI
5. Manipulacin
DOM
$ (document) .ready(function()
{
$ (!<a href="#top">back
to top<!a>/)
.insertAfter(/div.chapter
p/)
$ (!<a id="top"><!a>!);
})
$ (document) .ready(function()
{
$(/<a href="#top">back
to top<!a>!)
.insertAfter(!div.chapter
p!);
$ (/ <a id= "t.op" name t op" ></a>/)
.prependTo(/body!);
lIf.I
ti
) ;
p!) .after(/<a
href="#top">back
to top<!a>!);
Con. insertAfter
(), podemos continuar actuando sobre el elemento <a> creado al
encadenar mtodos adicionales. Con. after (), los mtodos adicionales actuarn sobre
los elementos coincidentes por el selector $ (/ di v . chapter p /) en su lugar.
Por lo tanto, ahora que hemos insertado los vnculos en la pgina (y en el DOM) despus de cada prrafo que aparece dentro de <di v c La s s chapter" >, aparecern los
vnculos back to top, como se ve en la figura 5.2.
e
"
Part 1, Section 3
Este cdigo tradicional inserta el ancla al principio del body: en otras palabras, al
principio de la pgina. Ahora, con el mtodo. insertAfter
() para los vnculos y el
mtodo . prependTo () para el ancla, tenemos un conjunto plenamente operativo de
vnculos back to top para la pgina.
Con vnculos as, no tiene mucho sentido hacer que aparezcan cuando el principio
de la pgina sigue siendo visible. Una mejora rpida al script empezara los vnculos
solamente despus del cuatro prrafo, por ejemplo.
Esto se consigue rpidamente con un pequeo cambio a la expresin selector:
. insertAfter
(/ di v. chapter p: gt (2) /) . Por qu e12 aqu? Recuerde que el indexado de JavaScript empieza en O; por lo tanto, el primer prrafo se indexa como O, el
segundo es 1, el tercero es 2, y el cuatro prrafo es 3. Nuestra expresin selector empieza
insertando los vnculos despus de cada prrafo cuando el ndice alcanza 3, porque se
es el primero mayor que 2.
El efecto de este cambio es ahora evidente, como se ve en la figura 5.3.
by Edwin A. Abbott
Next above these come the NobUity, af whom there are several degrees, begfnnlng
at SlxSlded Figures, or Hexagons and from then.ce r1slng In the number of their
sldes tlll they receve the honourable tltle of Polygonal, or many-Slded. Flnally
when the number o, the sldes becomes so numerous, and the sldes themselves so
small, that!he figure cannot be dlstlngulshed from o clrde, he 15Included In the
Circular or Prfestiy arder; .nd thls Is the hlghest dass of all.
Part 1, Section 3
concerning the Inhabltants of Flatland
an excerpt
Qur Professlonal Men and Gentlemen are Squares (to whlch
and Five-Sided Figures or Pentagons.
back te toa
It Is a Law of Nature wl!h us that a male chlld shall have one more Ilde than hls
father, 50 that each generatlon shall rlse (es a rule) one step in the scale of
development and noblllty. Thus the son of a Square 15a Pentagon; the son of a
Pentagon, a Hexagon; and so on.
b.ck te top
But thls rule applles not always te the Tradesman, and stlll less often lo the
Soldlers, and to the Workmen; who Indeed can hardly be sald te deserve the name
of human Figures, slnce they have not all thelr sldes equa, Wlth them therefore
the tsw of Nature does not hold and the son of en Isosceles (Le. a Trlangle wlth
two sldes equal) remains Isosceles stllI. Nevertheless( al! hope 15not such out,
even lrom the lsosceles, !hat hs posterlty m.y ultlmately rse abave hls degraded
condton ....
~
Rarely-In
proportlon
01 lsosceles blrths-Is
a genulne and
Figura 5.2. Los vinculas para volver arriba despus de cada prrafo.
Desafortunadamente, los vnculos no funcionan todava. Todava necesitamos insertar el ancla con id= 11 top". Para esto, podemos utilizar uno de los mtodos que inserta
elementos dentro de otros elementos.
Next above these come the Nobilttv, of whom there are several degrees, beginnlng
at Slx-Slded Figures, or ~
end from thence rislng In the number of thelr
sldes till they receive the honourable tltle of ~,
or many-Slded. Fln.lly
when the number of the sldes becomes so numerous, and the sldes themselves so
small, that the figure cannot be dlstlngulshed from elrele, he Is included in the
Clreular or Prfestiy arder; and !hls Is tne hlghest dass al all.
lt is a l..aw of Neture with us that a male chlld shall have one more .Ide than his
father, so that each generation shall rise (as a rule) one step In the scale Q'f
development and noblllty. Thus the son of a Square Is a Pentagon; the son of a
Pentagon, a Hexa.gon; and so on.
But this rule applles not .Iways to the l'rBdesman, and stlll tess often to tne
Soldle'rs, and to the Workmen; who Indeed can hardly be said te deserve the name
of human Figures, slnce !hey have not .11 thelr sldes equal. WI!h them therefore
!he Law of Noture does not hold; and the son al an tsoscetes (Le. a Trl.ngle wlth
two sldes equal) remalns Isosceles stlll. Nevertheless, ali hope 15not such out,
even from the lsosceles, !hat hls posterlty m.y ultlmately rse above hls degraded
condltlon ....
~
P.arely-In
certlfiable
mi
5. Manipulacin
DOM
Aprende jQuery 1.3
Mover elementos
Con los vnculos back lo top, hemos creado nuevos elementos y los hemos insertado
en la pgina. Tambin es posible tomar elementos de un lugar en la pgina e insertarlos
en otro lugar. Una aplicacin prctica de este tipo de insercin es el posicionamiento
dinmico y formato de notas a pie de pgina.
Cada uno de estos prrafos tiene un solo pie de pgina dentro de <span
class=" f oot.not;e "></span>. Al codificar elHTML de esta forma, podemos preservar
el contexto del pie de pgina. Con una regla CSS aplicada a la hoja de estilo para poner
en cursiva los pies de pgina, los tres prrafos se parecen a lo que aparece en la siguiente figura.
Un pie de pgina ya aparece en el texto Flatland original que estamos utilizando para
este ejemplo, pero tambin designaremos un par de otras partes del texto como pies de
pgina para la finalidad de esta explicacin:
ts
<p>Rarely—in
Triangle
produced
from Isosceles
parents.
<span
ll
marry
The blrth af a Ttue Equllateral Trtangle from Isosceres parents 15the subject of
rejolclng In our country for many furlongs round. After a strict exemrnetton
conducted by the Sanltary and SOCial Board the Infant, If certlfled as Regular, is
wlth solemn ceremonial admltted Into the class of Equllaterals. He Is then
Immedlately taken from hls proud yet sorrowlnq parents and adopted by some
chlldless Equllateral. TIu: Equllreral ts bowuJ by oaUt never ro pumil Me: child henceforth 10 enter
tus former hom~ or so mucJt as 10 /001: uptm Itls 1'f!la()1Uagaln./or fear test JJrBfreshly deveJ~
o~
nJd)t, lryfOrCB ofunconrclow
tmilation.fa/l bacJc agah'llnlo his hmxJtrary leve!
an uncertified
Triangle.
Sguare
offspring
has
is visited
either
Such a birth
requires,
as its
and continuous
development
How admira ble Is the Law of Compensatlon 1And how pgrfecl a proof of ,he MlUrat ftmess
ando 1 may olmost soy. rhe:dJvfne orlgin o/Ilre artnocrattc consrlRltion of the Sratl!f ofFlaltand! By a
judldous use of thls Law of Nature, the Pofygons and arcles are almost always
able to stie sedltlon In Its very cradle, taklng advantage of the lrreprasslbte and
boundless hopefulness of the human mlnd ....
of the Isosceles
<span class=lIfootnote">The
Equilateral
is
imitation,
into his
hereditary level.</span>
</p>
<p>How admirable
a proof
<span
of the natural
lIlII
Figura 5.4.
de pgina.
Ahora podemos tomar los pies de pgina e insertar los entre <di v e 1as s ="chapt e r ">
y <di v .i d "footer" >. Recuerde que incluso en casos de iteracin implcita, el orden
de insercin est predefinido, empezando al principio del rbol DOM y descendiendo.
Puesto que es importante mantener el orden correcto de los pies de pgina en su nuevo
lugar en la pgina, deberamos utilizar. insertBefore
(/#footer /) .
Esto situar cada pie de pgina directamente antes de <di v Ld " footer" > de modo
que el pie de pgina 1 se sita entre <di v class=" chapter" >y <di v I d "footer" ,
el pie de pgina 2 se sita entre pie de pgina 1 y <di v .i.d"footer" , etc. Utilizar
. insertAfter
(/ di v . chapter /) , por otro lado, hara que los pies de pgina aparezcan en orden inverso. Hasta el momento, nuestro cdigo se parece a esto:
$(d ocument) .ready(function() {
$(/span.footnote/) .insertBefore(/#footer/) ;
j);
Desafortunadamente, sin embargo, nos hemos encontrado con un gran problema. Los
pies de pgina estn en etiquetas span, lo que significa que se muestran inline por
defecto, uno detrs de otro sin separacin, como aparece en la figura 5.5.
lIfIiI
5. Manipulacin
DOM
itWltat nud ola cmij'tC4te'" a Spaulllllli crltic may osk: "ls nol the procnoIion ola Stuan Son a ceniftt:(JUj'rom NtlR1r6 herset; pl'OWng me
Equal-sldednes!
o/tAl! FtJJ.htrrl" I rq1/y that no Lady 01 any pasitlan wUJmarry 1m uncemfed 1Hangle. SqutllY. offiprflrg haJ sometJmes 1'e$ultm
from a sllghlJ)' lrrtJgwlar THangle; bUl tn almost f1W!1'JI sucn case ,he I~gularltyofthefirsr
genuarton ts vtsued on th! rhlrr/: whlch elthu /a/ls lo
anatn Ie Pentagona/ ranA;, OT reiapser 10 rhe THonguJar.T1tJ! EquJlacuaJ ir bound by oath never to permu flte child hl!Jlcefortlt lO en/u hts former
home 07 $0 mua. tU 10 1001 upon hls relatlcms agaJ.n.for fear #.SIrhefreshly dtveloped mganlsm may. by force o!tmeon.sdous
imflOt/on,faJl back
again 11IlO h1s ht.redltary leveJ.A.nd Jww perfect a proofofthe naturalftmen and.l may ahnosr soy, the divIne origtn o/Ihe ortnocranc conslftutiorl
oIrA.Sr.ru
ofFIarrd/
Figura
,
Aprende jQuery 1.3
IEII
no utilizar un elemento que los numere por nosotros automticamente? Hemos asignado
a la lista un Il) de notes y lo hemos insertado detrs de d v class="chapter">.
"
Marcar, numerar
vincular el contexto
Una solucin a este problema es modificar el CSS, haciendo que los elementos c spari se muestren como bloques, pero solamente si no estn dentro de -cd i v
c l a s s e " chapter" >:
span.footnote
font-style,
(
italic;
font-family:
"Times New Reman",
display: block;
margin: lem O;
Times,
serif
)
.chapter span.footnote
display:
inline;
Los pies de pgina estn empezando ahora a tomar forma, como muestra la figura 5.6.
})
)l;
"mrat nn!d ola certJ.flcateP" a Spacelt11td cruc mayo..rk: "b 1t00lhept'OCJ'Mlion o/a Squore Son a certtjicfIkfrom NlJIU1'8lime//, p10Vlng tlJe
Equal,sJdednas ofth! Fatlter'" 1nrply tltat no Lady ofany posfdan will many cm uncsrtifted Triangle. Square offiprlng has somlfimu reJulted
fromas/lg}lrly 1""KU/(JJ' 1HlI1Igl.; bur In olm." every suc cos. rh, JrreguJarlry oflb.flrsrgenuaJm
ts vis/red lb. thJJT/;wMch drher f.11s ro
attaln th~ PentagOllaJ nm.t:, or ~
ta te 1Hl11IguJar.
lle
fear
EquJlaJeroIls
And how peifllCr. proof ofrh. noJural /1m ess and. 1 may
Figura
tzImMt
agalll,
{01
Sr.U$ ofFltJJland/
Al menos ahora son pies de pgina distintos; an as todava se puede trabajar mucho
con ellos. Una solucin de pie de pgina ms robusta sera:
1. Marcar la ubicacin en el texto de dnde sale cada pie de pgina.
2. Numerar cada ubicacin, y proporcionar un nmero coincidente para el propio
pie de pgina.
3. Crear un vnculo desde la ubicacin de texto a su pie de pgina coincidente, y
desde el pie de pgina de vuelta a la ubicacin de texto.
Estos pasos se pueden conseguir desde el mtodo . each ( ) ; pero primero estableceremos un elemento contenedor para las notas en la parte inferior de la pgina:
$ (document)
$(/<01
.ready(function()
id="notes"></ol>/)
{
.insertAfter(/div
chapter/);
)) ;
Parece suficientemente razonable utilizar una lista ordenada <01 id= "notes" ></
01> para los pies de pgina; despus de todo, queremos que estn numerados. Por qu
AqU empezamos con el mismo selector que hemos utilizado con el ejemplo ms sencillo de pie de pgina, pero le encadenamos el mtodo . each ( ) . Dentro de . each ( )
empezamos con $ (thi s) , que representa cada pie de pgina en sucesin, y le encadenamos el mtodo. before () . El resultado de la tabla unida dentro del parntesis del mtodo. before () es un vnculo superndice, que se insertar antes de cada pie de pgina
span. El primero, por ejemplo, se parecer a esto cuando se inserta en el DOM:
ea
href="#foot-note-l"
id="context-l"
class=!lcontextn><SUP>l</sup></a>
La sintaxis puede parecer familiar a primera vista, por lo que dediquemos un momento a investigar lo que est sucediendo. Dentro de los parntesis del mtodo. before (),
empezamos con un par de corchetes cuadrados, [ ], que representan una tabla literal.
Todo elemento dentro de la tabla va seguido de una coma (excepto, muy importante, el
ltimo elemento). Hemos situado cada elemento en su propia lnea por legibilidad. Luego,
una vez que se construye la tabla, lo convertimos a una cadena de nuevo al utilizar el
mtodo JavaScript . j oin () . Este mtodo toma una cadena vaca como su argumento,
representado por un par de comillas sencillas, porque no queremos que aparezca nada
entre cada elemento de tabla cuando se muestra como HTML.
Observe el uso de Lnde x- L. Puesto que el contador empieza en 0, aadimos 1 para
empezarlos atributos href en #footnote-1,
los atributos iden #context -1 yel texto
del vnculo en 1. El href es particularmente importante porque debe coincidir exactamente con el atributo id del pie de pgina (no incluido el # por supuesto).
Para estar seguro, el mismo resultado se puede conseguir con una cadena concatenada extensa en lugar de una tabla unida:
mi
5. Manipulacin
DOM
Aprende jQuery 1.3
j )
+
$(this)
.befo!:"e(
[/<a href="#foot-note-/.
i,ridex+l,
/" id="context-/.
index+l,
/It class=lIcontextll>/,
Mucho se ha escrito en la Web sobre las diferencias de rendimiento entre tablas unidas
y cadenas concatenadas. Para aquellos que sean muy curiosos, el siguiente artculo
trata una serie de pruebas utilizando las dos tcnicas: http://www.sitepen.com/
blog/200B/OS/09/string-performance_an_analYSis/.
Sin embargo, en la mayora de situaciones, estas diferencias son imperceptibles. Si el
rendimiento de un script es un problema, existen una serie de otras reas que tienen
mucho mayor impacto (como guardar selectores en cach, que ya hemos tratado).
Nuestros tres marcadores de pie de pgina vinculados ahora se parecen a lo que
aparece en la figura 5.7.
Rarely-In
~
The blrth cf a True Equllateral TtIangle from I",sceles parents Is the subject of
rejolcln9 In our country for many furfongs round. Arter a strfct examlnatlo
conducted by Ihe Sanltary end Social Board. the Infant. If
gu ar, I
wlth solernn ceremonial admltted loto the d
eraIs. He 15 the
Immedlately taken I'rom hls
ng parents and ad~
chlldless Equll.teral. :
/<sup>/
+ (index+l)
/</a>/
J .join(//l
+ /</sup>/.
)
.appendTo(/#notes/)
)l;
)l;
a genuine and
/" id="context-/.
index+l,
/11 class="context">/,
/<sup>/ + (index+l)
/</a>/
.join (//)
Tres marcadores
de pie de pgina
+ /</sup>/.
.appendTo(/#notes!)
.append ( / a href="#context-/
/">contextc/a/
);
})
+ (index+l)
}l;
.ready(function()
$(/<01 id="notes"></ol>/)
,insertAfter
$ (/span.footnote/)
.each(function(index)
mi
(/div. chapter/)
(
- o.>qlM.U
.-._-- .
. (''''''_ _n rl!rtlflcat1?jrom
"WhaJ need of a cenJflcate'/" a SpactlandcrltJc maytl$k: "13not te procreanon OJO
_
~
NallIn Aenel[. provmg tA. Equal-ndednen o/tIoe Fatlo ,. 1 ,..ply thar no lAdy 01 a.y posUton wIll"""'l' an uncorifled
Tnangle. Square offiprlng hiB $ometJmts raultedjrom tJ sllghlly Irregular 1Hanglf!!: bu( In olmosllNf:l'Y such CQ.Jf!! 1M
IrreguJrlty ofth~ firsl general10n l.r vtslled 011tIu: thtrd; whlcn eitlrer lall~(o anatn u.e Penlog01lal ral'l~ or reJapses (O
th. Triallgul"" (r!1I!!mJ
Th.e EqullatertJt ts botmd by oalll nn>er fO pmnlf 1M eA/id hencelonh 10 en(eF~"l.rlomtulok]8 MCM-BiD
~
hb ",10/10113 agabl,lor fear les/ tM fraAIy deve/oped organ/sm '"".Y.
o(un co
(U=rf8I'
agamlnlO h/s huedItary Ieve/.
V",
(~4
ss1 . r7
M""
!
. S;. Iki Yv"
w;'o/f!
.:_
vnculos
anexados
181
5. Manipulacin
'1
L,
DOM
lfD
Lospies de pgina todava carecen de sus nmeros, sin embargo. Aunque se han situado dentro de un <01>, cada uno se debe situar individualmente en su propio <li>.
Losotros mtodosjQuerypara envolverelementosson .wrapAll () y .wraplnner () .
Vasehttp://docs
. jquery. com711anipulation/wrapAll
andhttp://docs
.
j query. com/Manipulation/wraplnner
para ms informacin.
Copiar elementos
,l
(document) .ready(function()
Hasta el momento en este captulo hemos insertado elementos recin creados, movido elementos desde una ubicacin en el documento a otra, y situado nuevos elementos
alrededor de existentes. Algunas veces, sin embargo, podemos querer copiar elementos. Por ejemplo, un men de navegacin que aparece en el encabezado de la pgina se
podra haber copiado y situado en el pie de pgina tambin. De hecho, siempre que se
pueden copiar elementos para mejorar una pgina visualmente, es una buena oportunidad de utilizar un script. Despus de todo, por qu escribir algo dos veces y duplicar
nuestra oportunidad de error cuando podemos escribirlo una vez y dejar que jQuery
haga el trabajo difcil?
Para copiar elementos, el mtodo. clone () de jQuery es justo lo que necesitamos;
toma cualquier conjunto de elementos coincidentes y crea una copia de ellos para uso
posterior. Como con el proceso de creacin de elementos que hemos explorado anteriormente en este captulo, los elementos copiados no aparecern en el documento hasta
que aplicamos uno de los mtodos de insercin. Por ejemplo, la siguiente lnea crea una
copia del primer prrafo dentro de <di v c La s s "chapter" :
/11
id= 11context _/ ,
index+l,
/11
class=trcontextll>/,
/<sup>/ + (index+l)
/</a>/
J .join(/ j)
/</sup>/,
.appendTo(/#notes/)
.append(
.wrap(/<li
})
})
/ a href="#context-/
/">context</a/
)
id="foot-note-j
+ (index+l)
/ ></li>/);
+ (Lndex-s
j )
$ (/div.chapter
Ahora cada uno de los elementos <li> viene completo con un id que coincide con
el href del marcador. Al final, tenemos un conjunto de pies de pgina numerados y
vinculados, como se ve en la figura 5.9.
1.
2.
Next abcve these come the Noblllty, of whom there are several degrees, beglnnlng
at SIx-Slded Figures, or Hexagons. and from thenca rlslng In the number of thelr
sldes tlll they receJve the honourable tltle of Polygonal, or many-Slded. Finally
when the number of the sldes becomes so numerous, and the sides themselves so
small, that the figure cannot be dl5tlngulshed from a elrele, he 15Induded In the
Circular or Pnestly arder; and thls 15the hlghe5t dass of all.
ne
Equila/.eral ts bound by oatlt ne.oey IDpermiJ me child hencefanll to emer h.isformer home 01'so much ar lb loot
upo1J his relations again, lor 'fear lest tbe ~hly
developed organism may.1Jyforce ofunconsciow imiltJtiOll,jall bad
again tmo bis fwoeditoJy <veI. (cenee.u)
It Is a Law of Nature wlth U5 that a male chld 5han have one more slde than his
father, so that eech generatJon sha rtse (as a rule) one step In the sea te of
development and 'nobllltv. Thus the son of a SQuare is a Pentaoon; the son of a
1111d.
lmay almost say, (he dtvJne orlgin O/Me artuocraitc constuuan o/
of Flatland
our Professlonal Men and Gentlemen are Squares (to whlch ctass 1 myself belong)
and Five-Slded Figures or Pentagons.
"W'1JIn.need al centftcare'!" a Spac.eltmd crma may llfl: "151JOI the procreado71 of a Square Son cutiftcatefrr>m
Nmure Iferselj; provmg ,he Equalwsfdedness o/tire FtnlJerJ" f rep1y rhar no Lody 01 any postuon wJll marry an uncertified
ttiangle. Square offsprlJrg has!fCmet!mes resultedfrom a sJightJy Irregular 1Tiang/e; buzin almos! every sud case te
IrreguJarity ofdie finl generalion iI vJsUed on tire thtrrJ; wh.ch etthu fails to attatn me Penragonal ran~ 01'reJapsu fa
lb. Tri<mgrtlar. Cco_,)
Q
p,eq(O)/) .c1one();
Para continuar el ejemplo, podemos hacer que el prrafo cIonado aparezca antes de
<di v class=" chapter" :
$ (/div.chapter
l:ImI
5. Manipulacin
DOM
Ahora el primer prrafo aparece dos veces, como se ve en la figura 5.11, y puesto que
la primera instancia ya no est dentro de <di v c La s s
chapter"
, no retiene los estilos asociados con el di v (ms notablemente, la anchura).
e
"
lEiI
of Flatland
Our Professlonal Men and Gentlemen are Squares (to whlch class 1 myself belong) and Five-Slded Figures or Pentagons.
Our ProfessJonal Men and Gentlemen are Squares (to whlch
and Flve-Slded Figures or Pentaaons.
Next above these come the Nobillty, of whom there are several degrees, beglnnlng
at Stx-Sded Figures. or Hexagons and from thence rfslng In the number of thelr
sldes tlll they reeetve the honourable tltle of Polygonal, or many-Slded. Flnally
when the number of the sldes becomes so numerous, and the sldes themselves so
small, that the ftgure eannot be dlstingulshed from a clrde, he 15induded In the
Circular or Prtestly order; and thls 15the hlghest dess of all.
It Is a L2w o, Nature with us that a maie chltd shatl haya one more slde than his
father, so that each generatlon shaU nse (as a rute) one step In the scale of
development and noblllty. ThU!~the son at a Square 15a Pentagon; the son of a
,~
Por lo tanto, utilizando una analoga con la que la mayora de la gente debera estar
familiarizada,
. clone () es a los mtodos de insercin como copiar es a pegar.
Clonar citas
Muchos sitios Web, como sus equivalentes impresos, utilizan citas para enfatizar pequeas partes de texto y atraer la atencin del lector. Podemos conseguir esto fcilmente
con el mtodo. clone () . En primer lugar, echemos otro vistazo al tercer prrafo de
nuestro texto de ejemplo:
<p>
<span class=!lpull-quote >It
is a Law of Nature
<span class="drop!l>with us</span> that a male child shall
have <strong>one more side</strong>
than his father</span>,
so that each generation shall rise (as a rule) one step in
the scale of development and nobility. Thus the son of a
Square is a Pentagon the son of a Pentagon, a Hexagon and
so on.
</p>
1l
.pul led {
background,
#e5e5e5;
position: absolute
width, 145px;
t op : -20px;
right, -180px;
padding, 12px 5px 12px 10px;
font: italic 1.4em "Times New Roman",
Times,
serif
La cita ahora recibe un fondo gris claro, algo de relleno, y una fuente diferente.
An ms importante, se posiciona de forma absoluta, 20 pxeles por encima y 20 pxeles a la derecha del ancestro posicionado (absolute
o relative)
ms cercano en
el DOM. Si ningn ancestro tiene posicionamiento
(aparte de static)
aplicado, la
cita se posicionar relativa al documento <body>. Debido a esto, necesitamos aseguramos en el cdigo jQuery que el elemento padre de la cita clonada tiene establecida
position:relative.
Aunque el posicionamiento
superior es bastante intuitivo, puede no quedar claro al
principio cmo se posicionar la cita 20 pxeles a la izquierda de su padre posicionado .
Derivamos el nmero primero del ancho total del cuadro de cita, que es el valor de la
propiedad width ms el relleno izquierdo y derecho, 145 px + 5 px + 10 px, o 160 px.
Luego establecemos la propiedad right
de la cita. Un valor de O alinear el lado derecho de la cita con el de su padre. Por lo tanto, para situar su lado izquierdo 20 px a la
derecha del padre, necesitamos moverlo en una direccin negativa 20 pxeles ms que
su ancho total, o -180 px.
De vuelta al cdigo
Ahora podemos llegar a jQuery. Empecemos con una expresin selector para todos
los elementos c s pari c La s s e "pull-quote"
, y anexemos un mtodo. each () de
modo que podemos llevar a cabo mltiples acciones segn pasamos por ellos:
$ (document) .ready(function()
(
$ (/span.pull-quote/) .each(function(index)
// ...
}) ;
}) ;
''-.....,
lfllI
5. Manipulacin
DOM
Una vez ms, almacenamos cualquier selector que utilizaremos ms de una vez en
una variable para mejorar rendimiento y legibilidad.
Ahora podemos estar seguros de que el CSS est establecido y listo para la cita. En
este punto podemos clonar cada e span, aadir la clase pulled a la copia, e insertarla
al principio del prrafo:
$ (document) .ready(function()
(
$ (/span.pull-quote/)
.each(function(index)
(
var $parentParagraph
= $(this) .parent(/p/);
$parentParagraph.css(/position/,
/relative/);
$(this) .clone()
.addClass(/pulled/)
.prependTo($parentParagraph);
)
})
It Is a Law of Naturo wlth us that a male chlld shall have one more ,"Ide than hls
father, so that each generatlon shan rlse (as a rule) one step In the sea le of
development and noblllty. Thus the son of a Square 15 a Pontagan; rhe son of a
Pentagon,
a Hexagon;
and so on.
But thls rule applles not always to the Tradesman, and stlll less aften to the
Soldlers, and to the Workmen; who Indeed can hardly be sald to deserve the name
of human figures, slnce they have not all thelr sldes equat. Wlth them therefore
tIle Law of N.turo does not hold; and the son af an !soscsles (I.e. a Triangle wlth
1m
Por lo tanto, empezamos el proceso de donado esta vez al almacenar el don en una
variable. La variable es necesaria esta vez porque no podemos trabajar en ella completamente dentro de la misma cadena. Observe, tambin, que despus de encontrar <span
c Laas vdr op:' >y reemplazar su HTML con unaelipsis (…), utilizamos. end ()
para regresar de la ltima consulta, . f ind (/ span . drop / ) . De esta forma, estamos insertando toda la copia, no solamente la elipsis, al principio del prrafo.
Al final, establecemos una variable ms, clonedText, a los contenidos de slo texto
de la copia; luego utilizamos estos contenidos de slo texto como un sustituto para el
HTML de la copia. Ahora, la cita se parece a la figura 5.13. Evidentemente, se ha aadido otro -cs pa n c Las s "pull-quote"
> al prrafo posterior para asegurarse de que el
cdigo funciona para mltiples elementos.
e
11m
5. Manipulacin
DOM
Aprende jQuery
.html(/…/)
.end ()
.wrap{/<div clasS="pulled-wrapperll></div>/);
var clonedText
= $clonedCopy.text();
$clonedCopy.html(clonedText)
;
})
rcular or
But this rule applles not always to the Tradesman, and stlll less aften to the
Soldlers, and te the Workmen; who Indeed can hardly be sald to deserve the name
of human Figures, slnce they nave not all thelr sldes equal. Wlth them therefore
the ~w of Nature does not hold; and the son of an lsosceles (Le. a Tnangle wlth
Me sldes equal) remalns IsosceJes stffl. Nevertheless, 811hope 15not such out,
even from the Isosceles, that hls posterlty may ultlmately rse above hls degraded
condltlon ...,
lt is a Law of Nature
._:<tata male chi/d
shl/ have (in" mere
sitie than hiSfather
It ts a L..awo, Nature wlth us that a male chlld shall heve one more slde than his
father, so that each generatlon shall rfse (as a rule) one step In the seale of
development and noblllty, Thus the son of a Square 15 a Pentagon; the son of a
Penrngon, a Hexagon; and so on.
But thls rule applles not always to the Tradesman, and stlflless often to the
Soldlers, 8'1d to the workmen; who Indeed can hardly be sald to deserve the name
of human Figures, slnee they have nat all thelr sldes equal. Wlth them therefore
the Law of Nature does not hold; and the son ot an Isosceles (I.e. a Trlangle wlth
two sldes equal) remalns Isoseeles stIl1. Nevertheless, al! hope Is not such out,
even from the tsoscetes, that hls posterlty may ultlmately rtse ebove hls degraded
condlton. ..
proportlon
of lsosceles blrths-Is
a genulne and
Rarely-In
proportion
a genulne and
The bfrth of a 'nue E.qullateral Tnangle from Isoscees parents Is the subject of
rejo1dng In our country for many furtongs round. After a str1ct examlnatlon
conducted by the S.nltary and Social Board, the Infant, II cert,"ed as Regular, Is
wft:h solemn ceremonJaI admltted Into the cass of EqulJaterals. He 15then
Immedlately taken from hls proud yet sorrowlng parents and adopted by some
chlldless Equll.teral. :
The blrth of 1hJe Equllateral Tnangle from lsosceles perents Is the subJect of
reJolclng in our cauntry for many fur10ngs round. After a strct examinatlon
conducted by the Sanltary and Social Board, the Infant, II certlfied as Regular, Is
wlth solemn ceremonial admltted loto the class of Equliate~is.
He 15then
frnmedlately taken from his proud yet sorrowlng parents and adopted by some
chlldless Equlleterat.
How admirable
background,
url(pq-top.jpg)
position:
absolute
width, 160px;
right, -lBOpx;
padding-top,
lBpx;
no-repeat
left
top;
background,
url(pq-bottom.jpg)
position:
relative
display,
block;
width, 140px;
italic
24px
1.4em
'
3 By a ludldous
"
no-repeat
left
bottom;
lOpx;
"Times
ftyrn Il!fiCr~
prentsJ,(lhe
O lOpx
l:quiTrd'a/:iH,.gle
subject olrejoicing
I
inOlP"oo~";
... ~,
~
Figura 5.13. Contenidos
font:
~, Ik,
11 is aEa'w ofNq{ure
... thot li'4nak child
shall halk one more
sitie thanhis father
~rely-In
padding,
ess or a
lt 15a Law of Nature wlth us that a male chlld 5hall have one more slde than hls
tather, so that each generatlon shall rtse (as a rule) one step In the scale of
development and noblllty. Thus the SOn of a Square Is a Pentagon; the son of a
Pentagon, a Hexagon; and so on.
.pulled
IBII
Aqu, algunas de las reglas anteriormente aplicadas a e apan c La s s "pu Ll ed" > se
aplican a <di v class= "pulled-wrapper"
> en su lugar. Un par de ajustes de ancho
y relleno toman en cuenta el diseo de los bordes de la imagen de fondo, y la regla. pulled tiene sus propiedades pos t o y display modificadas para que aparezcan correctamente para todos los navegadores.
En la figura 5.14 tiene un aspecto final de las citas recin adornadas en su hbitat.
.prependTo($parentparagraph)
})
1.3
New
Roman",
Times,
serif
. append ()
. appendTo ( )
lB
5. Manipulacin
DOM
.prepend
()
.prependTo ()
. after
()
.insertAfter()
. before
.insertBefore()
()
. wrap ()
. wrapAll ()
. wraplnner
()
5. Para reemplazar cada elemento coincidente con nuevos elementos o texto, utilizar:
. html ()
. text
.replaceAll()
.replaceWith()
()
. empty ()
. remove ()
Resumen
En este captulo hemos creado, copiado, reorganizado y embellecido contenido utilizando los mtodos de modificacin DOM de jQuery. Hemos aplicado estos mtodos a
una sola pgina Web, transformando un conjunto de prrafos genricos en un extracto
con pie de pgina, citas, vinculado y con estilo.
El apartado de tutorial del libro est casi acabado, pero antes de pasar a examinar ejemplos ms complejos, realicemos un viaje al servidor va los mtodos AJAX de jQuery.
"':,
,,
'.
I
.'
6
AIAX
En los ltimos aos, ha resultado comn juzgar sitios basndose en su uso en tecnologas especficas. Una de las palabras de moda ms destacadas utilizadas para describir nuevas aplicaciones Web es "realizado con AJAX". Esta etiqueta se ha utilizado para
significar muchas cosas diferentes, ya que el trmino engloba un grupo de posibilidades
de uso y tcnicas relacionadas.
Tcnicamente, AJAX es un acrnimo para Asynchronous JavaScript and XML (Iavaficript
asncrono y XML). Las tecnologas implicadas en una solucin AJAX incluyen:
La tecnologa AJAX ha sido aclamada como el salvador del escenario Web, transformando pginas Web estticas en aplicaciones Web interactivas. Han surgido muchos
marcos de trabajo para ayudar a los desarrolladores a domado, debido a las inconsistencias en las implementaciones de los navegadores del objeto XMLHttpRequest; jQuery
no es ninguna excepcin.
Perrntanos ver si AJAX puede realmente realizar milagros.
lmI
6.AJAX
lIiI
Como siempre, una implementacin del mundo real debera utilizar mejora progresiva para hacer que la pgina funcione sin requerir JavaScript. Aqu, para simplificar
nuestro ejemplo, los vnculos no hacen nada hasta que los aadimos comportamientos
conjQuery.
Aadir HTMl
/----------------------------------------------------------------------Las aplicaciones AJAX a menudo no son ms que una peticin de un bloque de HTML.
Esta tcnica, algunas veces referida como AHAH (Asynchronous HITP and HTML, o HTIP
asncrono y HTML), es casi trivial de implementar con jQuery. En primer lugar necesi- tamos insertar algo de HTML, que situaremos en un archivo denominado a, htrnl junto
con nuestro documento principal. Este archivo HTML secundario empieza as:
cdiv class=lIentryll>
class="term">ABDlCATIONc/h3>
<div class="part">~.</div>
<div c1ass="definition">
An act whereby a sovereign attests his sense of the high
temperature of the throne.
<div c1ass=!lquote">
<div class=l1quote-1inell>Poor Isabe11ats Dead, whose
abdication</div>
cd ,v c Las s s vquot.evLane " >Set al1 tongues wagging in the
Spanish nation.</div>
<div c1ass=l1quote-linel1>For that performance
ttwere
unfair to scold her:</div>
<div c1ass="quote-1inel1>She
wise1y 1eft a throne too
ch3
Vamos a necesitar una forma de activar el proceso de carga, por lo que aadiremos
algunos vnculos para nuestros manejadores de evento:
class="letters '>
cdiv
cdiv
class="letter
id="letter-a'1>
ch3>ca href="#">Ac/a><!h3>
</div>
cdiv
1!
id='lletter-brr>
href="#">Bc/a></h3>
class='1letter'l
ch3><a
c/div>
cdiv class="letter"
id="letter-c11>
ch3><a
href=II#II>Cc/a></h3>
</div>
cdiv
class=llletter
id="letter-d">
<h3>ca
href="#ll>Dc/a></h3>
11
c/div>
</div>
<div class="quote-author">G.J.</div>
</div>
</div>
The Devll's Dlctlonary
</div>
by Amorosa Blerce
<div class=t'entrytt>
<h3 class=!lterrn">ABSOLUTE</h3>
<div class="part >adj.</div>
<div class="definition">
Independent,
irresponsible.
An absolute rnonarchy is one
in which the sovereign does as he pleases so long as he
pleases the assassins. Not rnany abso1ute monarchies are
ll
c.
governed by chanceo
</div>
</div>
IEI
6.AJAX
IBI
ABDICATION
ABDICATION
A
n.
An act whereby a sovereign attests bis sense of the high temperature of!he throne.
Poor IsabelIa's Dead, whose abdication
Set aIl tongues wagging in the Spanish nation.
For that performance 'twere unfair to scold her:
She wisely lett a throne 100 hot to hold her.
lb History she'll be DO roya! riddle _
Merely a plain parched pea that jumped tbe griddle.
",
n.
or the throne.
,(!
GJ.
ABSOLUTE
Indepen~ent.
so long as he
been replaced
curtaJled, and
ABSOLUTE
adj.
lndependent, irresponsible. An absolute monarchy is one in which the sovereign does as he pleases so long as be
pleases the assassins. Not many absolute monarchies are left, most of them baving been replaced by l.Gnited
monarches, where!he sovereign's power for evil (and for good) is greatly curtailed, and by republics, which are
governed by chanceo
.dj.
Irresponslble. An absoluta monarchy is one In whtch the soverelgn does as he peeses
plsases the assasslns. Not many absoluta monarchles are le. mast of them havtng
by IImlted monarchles. where lile soverelgn's power Ior evll (and for 9000) is greatly
bY republlcs, Whlch are govemed by chanceo
ACKNOWLEDGE
v.l
To confess. Ac:knowledgement
AFFIANCED
ACKNOWLEDGE
pp.
v.t.
lb confess. Acknowledgemenr of one anotber's faults is the bighest duty imposed by our love of trutb.
()
});
})
Cuando probamos este ejemplo, las definiciones de diccionario aparecern probablemente de forma instantnea cuando se hace die en el botn. Esto es un riesgo de trabajo
en nuestras aplicaciones a nivel local; es dificil dar cuenta de los retrasos al transferir
documentos por la red. Suponga que hemos aadido que se muestre un cuadro de alerta
despus de cargarse las definiciones:
$ (document) . ready (function () {
$('#letter-a
a') .click(function()
{
$ ( '#dictionary'
) .load I ' a. html ' ) ;
alert ( Loaded!
i
return false
I
})
}) ;
Podramos asumir por la estructura de este cdigo que la alerta solamente se puede
mostrar despus de que se haya realizado la carga. La ejecucin JavaScript es normalmente sncrona, trabajando en una tarea detrs de otra en secuencia estricta.
Sin embargo, cuando se prueba este cdigo determinado sobre un servidor Web de
produccin, la alerta habr posiblemente ido y venido antes de que la carga se haya
completado, debido a retraso de red. Esto sucede porque todas las llamadas AJAX son
por defecto asncronas. De lo contrario, tendramos que llamado SJAX. Carga asncrona significa que una vez que se lanza la peticin HTTP para recuperar el fragmento
HTML, se reanuda inmediatamente la ejecucin del cdigo sin esperar. Cierto tiempo
despus, el navega dar recibe la respuesta del servidor y lo gestiona, ste siempre es un
comportamiento deseado; es poco amable bloquear todo el navegador Web mientras se
III!I
6. AJAX
espera a que se recuperen los datos. Si las acciones se deben retrasar antes que se haya
completado la carga, jQuery proporciona una rellamada para esto. A continuacin se
proporciona un ejemplo.
l1definitionll:
IIA convenient
deity invented
"guote": [
"Ls public worship, then, a a i.n
"Thkt fer devotions paid to Bacchus" ,
"The lictors
dare to run ti':s in, 11,
"And resolutely thump and whack US?11
] ,
vaut.hor v. "Jorace"
i
I!II
by the ... ,
:',
),
Extraer HTML bien formado bajo demanda es muy conveniente, pero hay momentos
en los que queremos que nuestro script pueda procesar datos antes de que se muestren.
En este caso, necesitamos recuperar los datos en una estructura que podemos recorrer
con JavaScript.
(
"term":
"part":
"BACKBITE"
.t.
I1V
"definition":
"To speak
of
him when ..
),
Con los selecto res de jQuery, podramos recorrer el HTML que recibimos y manipularlo, pero primero se debe insertar en el documento. Un formato de datos JavaScript
ms nativo puede significar incluso menos cdigo.
(
"term":
"BEARD1',
"pa r t :':
IIn.lI,
"definition
ll:
),
Para recuperar los datos, utilizaremos el mtodo $ . getJSON ( ) r que busca el archivo
y lo procesa, proporcionando el cdigo llamante con el objeto JavaScript resultante.
El trmino JavaScript Object Notation (JSON) se acu por Douglas Crockford para
sacar provecho de esta sencilla sintaxis. Esta notacin puede ofrecer una alternativa
concisa al formato XML:
En este punto, todos los mtodos jQuery que se han utilizado se han anexado a un
objeto jQuery que hemos creado con la funcin factory $ ( ) . Los selectores nos han permitido especificar un conjunto de nadas DOM con los que trabajar, y los mtodos han
operado sobre ellos de alguna forma. Esta funcin $ . getJSON ( ) , sin embargo, es diferente. No existe elemento DOM lgico al cual se pueda aplicar; el objeto resultante se
tiene que proporcionar al script, no incluido en la pgina. Por esta razn, getJSON () se
define como un mtodo del objeto global jQuery (un solo objeto denominado j Query
o $ definido una vez por la biblioteca jQuery), en lugar de una instancia individual de
objeto jQuery (los objetos que creamos con la funcin $ ( ) ).
Si JavaScript tuviera clases como otros lenguajes orientados a objetos, llamaramos a
$. getJSON () un mtodo de clase. Para nuestros fines, haremos referencia a este tipo
de mtodo como una funcin global; de hecho, son funciones que utilizan el espacio de
nombre jQuery para no entrar en conflicto con otros nombres de funcin.
Para utilizar esta funcin, le pasamos el nombre de archivo como antes:
Para informacin sobre algunas de las ventajas potenciales de JSON, as como implementaciones en muchos lenguajes de programacin, visite http://j
son. org/.
Podemos codificar nuestros datos utilizando este formato de muchas formas.
Situaremos algunas entradas de diccionario en un archivo JSON que denominaremos
b . j son, que empieza de la siguiente forma:
$ (document] .ready(function()
(
$('#letter-b a') .click(function()
$ . getJSON ('b.j son' ) ;
return false
})
})
IItermll:
I1BACCHUSll,
"par t
IIn.
v.
Este cdigo no tiene efecto aparente cuando hacemos clic en el vinculo. La llamada de
funcin carga el archivo, pero no le hemos dicho a JavaScript lo que hacer con los datos
resultantes. Para esto, necesitamos utilizar una funcin de rellamada.
IIEI
6.AJAX
La funcin $. getJSON () toma un segundo argumento, que es una funcin a invocar cuando la carga est completa. Como se ha mencionado antes, las llamadas AJAX
son asncronas, y la rellamada proporciona una forma de esperar a que se transmitan los
datos en lugar de ejecutar el cdigo. La funcin de rellamada tambin toma un argumento, que se completa con los datos resultantes. De modo que podemos escribir:
$ (document) .ready(function(}
{
$ ('#letter-b
a') .click (function () {
$.getJSON('b.json',
function(data}
)l;
return false
}}
}}
Aqu estamos utilizando una funcin annima como nuestra rellamada, como ha sido
comn en nuestro cdigo jQuery por brevedad. Se podra igualmente proporcionar una
funcin con nombre como la rellamada.
Dentro de esta funcin, podemos utilizar la variable da t a para recorrer la estructura
de datos segn sea necesario. Necesitaremos pasar por la tabla de alto nivel, creando el
HTML para cada elemento. Podramos hacer esto con un bucle estndar for, pero en su
lugar introduciremos otra de las funciones globales de utilidad de jQuery, $ . each ( ) .
Hemos visto su homlogo, el mtodo . each ( ) , en el captulo anterior. En lugar de trabajar en un objeto jQuery, esta funcin toma una tabla o mapa como su primer parmetro y una funcin de rellamada como su segundo. Cada vez que se pasa por el bucle,
el ndice actual de iteracin y el elemento actual en la tabla o mapa se pasan como dos
parmetros a la funcin de rellamada.
$ (document) .ready(function(}
{
$ ('#letter-b
a') .click (function () {
$.getJSON('b.json',
function(data}
$('#dictionary')
.empty(};
$.each(data,
function(entrylndex,
entry}
{
var htrnl = '<div class=lIentry">';
htrnl += I <h3 c l a ss "term" > I + entry [1 term 1] + I </h3:> I i
htrnl += "c d.i.v c las se vpar t vs ' + ent.xy l vpe r t t l + l</div>l
html += '<div class="definition">,
i
~
htrnl += entry['definition'] i
html += '</div>1 i
html += '</div>' i
$('#dictionary')
.append(html};
)l;
}}
return
DBI
Este enfoque supone que los datos son seguros para el consumo de HTML; no debera
contener ningn carcter < perdido-por ejemplo.
Todo lo que queda es gestionar las entradas con citas, lo que lleva otro bucle
$. each ():
$ (document) .ready(function(}
{
$('#letter-b
a') .click(function(}
{
$.getJSON('b.json',
function(data}
$('#dictionary')
.empty();
$.each(data,
function(entrylndex,
entry}
ll
}}
if
'</div>'
(entry [,author' J) {
htrnl += '<div class="quote-author">,
entry['author
1
]
}
html
+=
'</div>';
htrnl += '</div>'
htrnl += '</div>';
$('#dictionary')
.append(html)
}l;
}}
return
})
}}
false
Con este cdigo en su lugar, podemos hacer clic en el vnculo B y confirmar nuestros
resultados, como se ve en la figura 6.4.
false;
}l;
})
El formato JSON es conciso, pero no tolerante. Cada llave, corchete, comillas, y coma
debe estar presente y tenida en cuenta, o el archivo no se cargar. En la mayora de los
navegado res, no recibiremos ni siquiera un mensaje de error; el script simplemente
fallar en silencio.
mi
6.AJAX
Los scripts que se van a buscar de esta forma se ejecutan en el contexto global de la
pgina actual. Esto significa que tienen acceso a todas las funciones y variables definidas globalmente, entre otras jQuery. Podemos por lo tanto seguir el ejemplo JSON para
preparar e insertar HTML en la pgina cuando se ejecuta el script, y situar este cdigo
'
en e. J. s:
BACCHUS
n.
var entries
!";
lI!iI
"t.e rmv :
"pa r t !':
Jorace
CALAMITY
"
IIn.lI,
"definition":
tiA
and ...
11
L
BACKBrrE
v.l,
BEARD
n.
oommonly
n.
school
who..
"CHILDHOOD"
01 hls f1tends.
IIn.lI,
1Idefinitionll:
the old
{
"t.e rmv.
"par t v:
BEGGAR
of
cut off by !hose who justly execrate tIle absurd Chlne custom 01 shavlng
I1The
period
of
human life
intermediate
of
operated
...
11
L
{
BELLAOO.NNA
n.
"t.e rrnv.
"pa r t v.
~ It"lI.,
Figura
IICLARIONETII,
IIn.lI,
instrument
torture
by ..
}.
(
"term":
IIpartl!:
Ejecutar un script
nCOMFORTrr,
"n.lI,
"definition":
"A state
of
mind produced
by.
i.
De vez en cuando no queremos recuperar todo el JavaScript que necesitaremos cuando la pgina se carga por primera vez. Podramos no saber qu scripts sern necesarios
hasta que ocurre alguna interaccin de usuario. Podramos introducir etiquetas < ser ipt >
en el momento cuando se necesitan, pero una forma ms elegante de incorporar cdigo
adicional es hacer que jQuery cargue el archivo . j s directamente."
Incorporar un script es tan sencillo como cargar un fragmento HTML. En este caso,
utilizamos la funcin global $ . getScript (), que, como sus hermanos, acepta una URL
que localiza el archivo de script:
(
rrterrnrr: rrCORSAIRII,
IIpartll:
IIn.",
"de f .n i t Lono.
})
of
the
seas.
rr
1;
var
html
$.each(entries,
html
htrnl
htrnl
html
$ (docurnent) .ready(function()
{
$('#letter-c
a') .click(function()
$ . getScript
( 'c. j s ') ;
return
false
})
"A politician
html
})
function()
+=
+=
+=
+=
'<div class="entry">','
'<h3 class="term">'
+ t hi s l t t e rm "I + r</h3>'
'<div class=r'part">
+ this['partt]
+ t</div>t;
'<div class=ttdefinition,,>r
+ t h .s lt de f .n i t i on t l +
+= '</div>';
I
'</div>';
$('#dictionary')
.htrnl(htrnl);
e tiene el resultado
l!nI
6.AJAX
CAlAMJTY
A more than oommonly pIaln and unmlstakable remlnder !hat the affalrs of th1s IIte are not o( our own
orde~ng. CaIBmltl8s are 01 lwo klnds: mlstortuoo lo ourselves, and good fortune lo othOlS.
n.
CANNIBAL
A gastronome
of the old schoor Who preserves !he simple tastes and adheres to the nab.lral dlet of
!he
pro'POr!< pertod.
n.
advances.
;'
ti
n.
An I""trument 01 torture cperated by a persen wllh cotton In hls eara. There are lwo Instrumenls !ha!
are '"'""" !han a clanonet -lwo
cJanonets.
COMFORT
grass
CLARlONET
Virtue's
</guote>
</entry>
n.
CHfLDHOOD
l!iI
BIe"",
"
n.
</entry>
</entries>
c::entry term="DEFAME"
<:definition>
11
Estos datos se podran expresar de muchas formas, por supuesto, y algunas reflejaran
de forma ms aproximada la estructura que hemos establecido para el H1ML o JSON
utilizado anteriormente. Aqu, sin embargo, estamos ilustrando algunas de las caractersticas del XML diseado para que sea ms legible para las personas, corno el uso de
atributos para term y part en lugar de etiquetas.
Empezaremos nuestra funcin de una manera familiar:
$ (document) .ready(function() {
$('#letter-d a') .click(function() (
$.get('d.xml', function(data) (
part="V.t,,,>
})
return
<entry
})
false
part="adj.lI>
Unable to attack.
</definition>
</entry>
<:entry term=IIDELUSION" part="n.rr:>
<definition>
})
Mappel >
U
Esta vez es la funcin $ . get () la que hace nuestro trabajo. En general, esta funcin
simplemente va a buscar el archivo en la URL facilitada y proporciona el texto plano para
la rellarnada. Sin embargo, si la respuesta se sabe que es XML debido a su tipo MIME
proporcionado por el servidor, a la rellamada se le pasar el rbol XML DOM.
Afortunadamente, corno ya hemos visto, jQuery tiene considerables posibilidades
transversales DOM. Podemos utilizar. find (), . filter () y otros mtodos transversales en el documento XML igual que haramos en HTML:
$ (document) .ready(function() (
$ (,#letter-d a') .click (function () (
$.get('d.xml', function(data) {
r
IIII
6,AfAX
,
$('#dictionary') ,empty{);
$ (data) ,find{'entry') ,each{function{)
var $entry = $(this);
var html = 'cdiv class=uentryu>,;
html += "<hS class=lItermtr>,
+ $entry.attr( "t.e
rrn')
+ '</h3>';
html
+=
"
A
l1
"c
DANCE
v./,
To leap about lo the sound af tlttarlng rnuslc, preferably wltIl erms at>out your nelghllor's _
or
deughter, Them are many klnds af dances, bu! all !hose nlQulnng !he psrtlclpatlon af tI1e two sexes
hava two characterlstlcs In oommon: tIley are consplcuously Innocen~ and wannly Ioved by lile
vldous.
DAY n,
A Penod of twenty-Iour hou/'S, mosUy mlsspent Thls pertod Is d1v1dedInto two psrts, tIle day prcper
and tIle nlgh~ or day Improper tI1e formar devuted te slns af business, tI1e latler oonsecmted to tIle
other sort These two klnds ot social actMty overfap,
DEBT
n,
if ($quote,attr{'author'))
(
html += 'cdiv class="quote-authortl>
,
+ $quote.attr('authort)
+ 'c/div>'
}
htrnl += 'c/div>'
}
htrnl += '<!div>'
html += 'c/div>';
$('#dictionary') ,append(${html));
}) ;
}l;
return false;
Figura 6.6.
});
});
') ,each{function{)
{;
DEBT
n.
"'"k
DELUSION
n.
Esta nueva expresin selector limita las entradas devueltas segn corresponde, como
muestra la figura 6.7.
Figura 6.7.
ID
lE.iI
6. AJAX
mi
Hemos examinado cuatro formatos para nuestros datos externos, cada uno de los
cuales se gestiona de forma nativa por las funciones AJAX de jQuery. Tambin hemos
verificado que los cuatro pueden gestionar la tarea en cuestin, cargando informacin
sobre una pgina existente cuando el usuario lo solicita y no antes. Cmo, entonces,
decidimos cul utilizar en nuestras aplicaciones?
Nuestros ejemplos hasta este punto se han centrado en la tarea de recuperar archivos de datos estticos del servidor Web. Sin embargo, la tcnica AJAX entra en juego
solamente cuando el servidor puede configurar dinmicamente los datos basndose
en la entrada desde el navegador. Nos ha ayudado jQuery en esta tarea tambin; todos
los mtodos que hemos tratado hasta el momento se pueden modificar de modo quela
transferencia de datos se convierte en una calle de doble sentido.
Los fragmentos HTML requieren muy poco trabajo para implementar. Los datos
externos se pueden cargar e insertar en la pgina con un solo mtodo, que no
requiere ni siquiera una funcin de rellamada. Los datos no se estructuran necesariamente en una forma que los hagan reutilizables para otras aplicaciones. El
archivo externo est estrechamente unido a su contenedor.
Los archivos JSON estn estructurados para reutilizacin sencilla. Son compactos
y fciles de leer. La estructura de datos se debe recorrer para extraer informacin
y presentarla en la pgina, pero esto se puede realizar con tcnicasJavaScript estndar. Puesto que los archivos se pueden analizar con una sola llamada al eval ()
de JavaScript, leer un archivo JSON es extremadamente rpido. Cualquier uso
de eval () implica riesgos inherentes, sin embargo. Errores en el archivo JSON
pueden causar fallo silencioso o incluso efectos secundarios en la pgina, de modo
que los datos se deben elaborar cuidadosamente por alguien de confianza.
Los documentos XML son los reyes de la portabilidad. Puesto que XML se ha
convertido en la lingua franca del mundo del servicio Web, proporcionar datos en
este formato permite que los datos se puedan reutilizar en cualquier parte. Por
ejemplo, Flickr (http://flickr.com/),
del.icio.us (http://del.
icio. us /)
yUpcoming (http://upcoming
. org/) todos exportan representaciones XML
de sus datos, lo que ha permitido que surjan muchas interesantes aplicaciones
de sus datos. El formato XML es algo voluminoso, sin embargo, y puede ser algo
ms lento de analizar y manipular que otras opciones.
Puesto que demostrar estas tcnicas requiere interaccin con el servidor Web, necesitaremos utilizar cdigo del lado del servidor por primera vez aqu. Losejemplos facilitados
utilizarn el lenguaje de script PHP, que est ampliamente utilizado as como disponible
gratuitamente. No trataremos cmo configurar un servidor Web con PHP aqu; ayuda
sobre ello se puede encontrar en los sitios Web de Apache (http : // apache. org/) O
PHP (http://php
.rie t z ), O desde la empresa de hospedaje de su sitio.
I,
1,
1,
ti
)
I
,
author ,
=>
ICopete
'EDIBLE'
=>
array(
Sherany',
1,
of the
ID
6.AJAX
,,
part
'adj.
=>
1m
1,
'definition
=> 'Good to eat, and wholesome
to digest, as
a worm to a toad, a toad to a snake, a snake to a pig,
a pig to aman,
and a rnan to a worm.
)
EAVESDROP'
'EDUCATION'
=> array(
'part r => "n ,
I
'definition'
=> 'That which
discloses
to the wise
disguises
frorn the foolish
their lack of
understanding.
I
and
s ,
,..
?>
En una versin en produccin de este ejemplo, los datos probablemente se almacenaran en una base de datos y se cargaran bajo demanda. Puesto que los datos son parte
del script aqu, el cdigo para recuperarlo es bastante sencillo. Examinamos los datos
que se han publicado y diseamos el fragmento HTML a mostrar:
<?php
vJ.
.'
Secretiy lo overhear a catalogue of the crimes and Vltes of another or yourself.
A lady with one ofherears appJied
10 an open keyhole heard, nside,
Two female gossps in converse free The subject engaging them was sbe.
'1 think,' said one, 'and my husband thinks
'Iba! sbe's a prying, inquisitive minx!"
As soon as DO more of it she couId hear
The lady, indignant, removed her ear.
"I will no! stay,' she said, with a pout,
"Io hear my character lied about!'
Gopete Shenmy
.'
$terrn = strtoupper($_REQUEST['terrn']);
if (isset ($entries [$terrn])) {
$entry = $entries[$terrn];
$html = 'cdiv class="entryn>,
$html .= 'ch3 claS9=lItermll>'
$html .= $terrn;
$htrnl .= '</h3>';
;
i
if
(isset ($entry
r: author'
$htrn1 .= '<div
.'</div>l
$line
.'</div>l
] )) {
c1ass="quote-author">
I. $entry
.=
Una vez ms, observamos la ausencia de formato que ya vimos con los fragmentos
HTML anteriores, porque las reglas CSS no se han aplicado.
Puesto que estamos mostrando cmo se pasan los datos al servidor, utilizaremos
un mtodo diferente para solicitar entradas aparte de los botones solitarios que hemos
venido utilizando hasta el momento. En su lugar, presentaremos una lista de vnculos
para cada trmino, y haremos que un dic en cualquiera de ellos cargue la definicin correspondiente. El HTML que aadiremos para esto se parece a lo siguiente:
<div c1ass="letter'l
id=l'letter-e">
<h3>E</h3>
<u1>
<li><a href="e.php?term=Eavesdrop">Eavesdrap</a></li>
<li><a href="e.php?term=Ediblell>Edib1e</a></li>
<li><a href="e.php?term=Education">Education</a></li>
<li><a href="e.php?term=E1oquencell>E1oquence</a></1i>
<1i><a href="e.php?term=E1ysiumll>E1ysium</a></1i>
<li><a href="e.php?term=Emancipation >Emancipation</a>
</lb
<1i><a href="e.php?term=Emotionrr>Emotion</a></li>
<li><a href=lIe.php?term=Enve1ope">Enve1ape</a></li>
<li><a href=lle.php?term=Envy">Envy</a></li>
<1i><a href=ne.php?term=Epitaphrr>Epitaph</a></li>
<1i><a href=lIe.php?term=Evangelistll>Evange1ist</a></li>
</ul>
</div>
1t
[ 'author' ]
)
$html
a la peticin.
'</div>';
)
$htrnl .= '</div>';
$htrnl .= '</div>';
print ($htrnl) ;
?>
Ahora las peticiones a este script, que denominaremos e . php, devolvern el fragmento HTML correspondiente al trmino que se envi en los parmetros GET. Por ejemplo, cuando se accede al script con e. php?term:eavesdrop,
recibimos lo que se ve
en la figura 6.8.
Ahora tenemos que conseguir que nuestro cdigo JavaScript invoque el script PHP
con los parmetros correctos. Podramos hacer esto con el mecanismo . load () normal, anexando la cadena de consulta la URL y buscando datos con direcciones como
e . php? t e rme eave sd.rop directamente. En su lugar, sin embargo, podemos hacer que
jQuery construya la cadena de consulta basndose en un mapa que proporcionamos a
la funcin $ . get ( ) :
IDI
6.AJAX
$ (document) .ready(function()
{
$ (' #letter-e
a') .click (function () {
$.get('e.php',
('term': $(this) .text()},
$('#dictionary')
.html(data);
}) ;
return false
})
})
function(data)
1m
AJAX, incluso esta distincin es invisible para el usuario medio. Por lo general, la,nica
razn para elegir un mtodo frente a otro es ajustarse a las normas del cdigo del lado
del servidor, p proporcionar amplias cantidades de datos transmitidos; GET tiene un lmite ms estricto, Hemos codificado.nuestro ejemplo PHP para hacer frente igualmente
bien con cualquiera de los mtodos, por lo que podemos cambiar de GET a POST con
slo cambiar la funcin que invocamos:
$ (document)
Ahora que hemos visto otras interfaces AJAX que proporciona jQuery, la operacin
de esta funcin parece familiar. La nica diferencia es el segundo parmetro, que nos
permite proporcionar un mapa de claves y valores que forman parte de la cadena de
consulta. En este caso, la clave es siempre term pero el valor se toma del texto de cada
vnculo. Ahora, hacer clic en el primer vnculo en la lista hace que aparezca su definicin, como muestra la figura 6.9.
.ready(function()
{
$('#letter-e
a') .click(function()
{
$.post('e.php',
('term':
$(this) .text()},
$('#dictionary')
.html(data);
,/
function(data)
.
return
})
})
false
Los argumentos son los mismos, y la peticin ahora se realizar por medio de POST.
Podemos simplificar an ms el cdigo al utilizar el mtodo. load (), que utiliza POST
por defecto cuando se proporciona con un mapa de argumentos:
"
EAVESDROP
A
S
k
~
~
~
~
~
Emanoioeuon
~
~
~
~
~
&!creUy te>ave""'.r
v.1.
a catalogue of 1ho crtmes aOO vlces 01 ena1her or yourseW.
.:~,
~,
$ (document) .ready(function()
{
$('#letter-e
a') .click (function () {
$ (,#dictionary' ) .load ('e.php', {, term':
return false
}) ;
})
$ (this) .text () }) ;
Esta versin reducida funciona de igual forma cuando se hace clic en un vnculo,
como muestra la figura 6.10.
GopeIaS"",,"ny
EMANCIPATION
A
Figura 6.9. Hacer clic en un vnculo para mostrar su definicin.
Todos los vnculos aqu tienen direcciones asignadas, aunque no las estamos utilizando
en el cdigo. Esto proporciona un mtodo alternativo para navegar por la informacin
para usuarios que tienen desactivado JavaScript o no disponible (una forma de mejora
progresiva). Para impedir que se puedan seguir de forma normal cuando se hacen clic,
el manejador de evento tiene que devolver falseo
n.
A bondman's cI1angelillm
Ea """,
Edlble
E<lucatlon
Enve!ope
~
~
~
lmI
6.AJAX
Aprende jQuery 1.3
Serializar un formulario
$ (document) .ready(function()
{
$('#letter-~
form') .submit(function()
$ ( '#dictionary'
) .load ( 'f. php' ,
{ ,tetm': $ ( ,input [name=" term"] ,) .val () } ) ;
return Pfalse
.l:.,
j);
Enviar da tos al servidor a menudo implica que el usuario rellene formularios. En lugar
de basarse en el mecanismo normal de envo de formulario, que cargar la respuesta en
toda la ventana del navegador, podemos utilizar el conjunto de herramientas AJAX de
jQuery para enviar el formulario de forma asncrona y situar la respuesta dentro de la
pgina actual. Para probar esto, necesitaremos construir un formulario sencillo:
cdiv class="letter"
<h3>F</h3>
cform>
})
$ (document) .ready(function()
{
$('#letter-f
form') .submit(function()
$.get('f.php',
$(this) .serialize(),
$ ('#dictionary')
.html(data);
Esta vez devolveremos un conjunto de entradas del script PHP al buscar el trmino
de bsqueda facilitado como una subcadena de un trmino de diccionario. La estructura
de datos ser del mismo formato que antes, pero la lgica ser un poco diferente:
if
($entries
as $term
(strpos($term,
!== FALSE)
$html =
$htrnl .=
$html .=
$html .=
$htrnl
$html
$html
=> $entry)
strtoupper($
(
REQUEST['term']))
.,-
.=
'cdiv
class="quote-line">'.
$line
.'c/div>'
)
$html
$html
I</div>'
r
</div>
FIDDlE n.
An lns1Jument 10 nckle hUman 06'" by f11ctIon af. ho,.e'8 taH en th8 en!mll. ola cal
To Reme B81d Non>: "~Io smoJ<eyou tum
Ishall not ceaselo flddle wt11ieyou bUm."
To Nero Rome replled: "Pmy do your won~
"Ils rrry excuse that you wem IIddllng nn;t"
onn Pludge
~
.o
as $line)
(isset($entrY['author']))
false;
Ahora el mismo script funcionar para enviar el formulario, incluso a medida que
aumente el nmero de campos. Cuando realizamos una bsqueda, las entradas coincidentes se muestran, como se ve en la figura 6.11.
)
if
})
function(data)
;.,
})
return
.= 'cdiv class="part">'
.= $entry['part'];
.= '</div>';
$html
})
'cdiv class="entry">';
'ch3 class=l1term">'
$term;
'</h3>';
foreach
Este cdigo tiene el efecto pretendido, pero buscar campos de entrada por nombre y
anexarlos a un mapa uno a uno es complicado. En particular, este enfoque no se escala
.' bien ya que el formulario se vuelve muy complejo. Afortunadamente, jQuery ofrece un
mtodo abreviado para ello. El mtodo. serialize () acta sobre un objeto jQuery y
traduce los elementos DOM coincidentes en una cadena de consulta que se puede pasar
junto con una peticin AJAX. Podemos generalizar nuestro manejador de envo de la
siguiente forma:
id="letter-f">
cinput
type="text"
name=lItermll value=1I1I id="termll />
<input
type=lIsubmit"
name="searchl1
value=="searchl1
id="search" />
</form>
</div>
foreach
ID
~
~
~
~
~
ErnancipI!!!on
~
~
~Jlh
~
;
t ;
FIDEllTY n.
A vlrtue pecuHar ID !hose who ara about ID be betreyed.
Enve!ooe
print($html);
~....=:.=J
~
rc~
1m
6.AJAX
lImI
})
{
$ ( '<di v id= "loading
>L~ading... </div>
.insertBefore('#dictionary')
.ajaxStart(function()
{
$ (this) . show () ;
ll
})
})
t )
<div id=lIloadinglr>
Loading ...
</div>
Este mensaje es slo una parte de HTML arbitrario; podra incluir una imagen GIF
animada para proporcionar un ihrobber, por ejemplo. En este caso, aadiremos algunos
estilos al archivo CSS, de modo que cuando se muestra el mensaje, la pgina se parece
a la figura 6.12.
The D.vll's Dlctionary
$ (document) .ready(function()
{
$ ( <di v id= IIloading ti >Loading ... < / di v ' )
.insertBefore('#dictionary'l
.ajaxStart (function()
(
$ (this) .show () ;
}).ajaxStop(function()
$ (this) .hide ();
}) ;
I
})
by Ambrose Blerce
A
B
e
Q
E
~
~
~
~
~
Emancfpa1!on
E!!!2l!lm
~
~
~
];00
informacin al usuario.
$ (document) .ready(function()
{
$('#letter-a
a') .click(function()
$('#dictionary')
.load('a.html');
lmiI
6.AJAX
return
false
p;
p;
Podemos crear una pequea mejora aqu al hacer que el contenido cargado aparezca
gradualmente a la vista en lugar de aparecer de repente .. load () puede hacer que se
active una rellamada cuando se termine:
$ (document) .r~dy(function()
{
$ (' . t.erm ") .live ('click',
function O. (
$(this) .siblings(' .definition')
.slideToggle()
function()
al documento utilizando
'
});
})
$ (document) .ready(function()
{
$('#letter-a
a') .click(function()
(
$('#dictionary') .hide() .load('a.html',
$ (this) .fadelnO;
}) ;
return false
lIlIII
El mtodo . 1i ve () le dice al navegador que observe todos los clics en cualquier parte
,de la pgina. Si (y slo si) el elemento en el que se ha hecho clic coincide con el selector
" . term, entonces el manejador se ejecuta. Ahora el comportamiento de alternar ocurrir
en cualquier trmino, incluso si se aade por una transaccin AJAX posterior.
p;
})
AJAX Y eventos
Suponga que quisiramos permitir que cada nombre de trmino de diccionario controlara la visualizacin de la definicin que sigue; hacer clic en el nombre del trmino
mostrara u ocultara la definicin asociada. Con las tcnicas que hemos visto hasta el
momento, esto debera ser bastante sencillo:
$ (document) .ready(function()
{
$ (, .term' ) .click (function O (
$(this) .siblings(' .definition')
})
.slideToggle();
Cuando se hace clic en un trmino, el cdigo encuentra hermanos de! elemento que
tienen una clase def ini t ion, y la desliza hacia arriba o hacia abajo segn sea el caso.
Todo parece en orden, pero un clic no hace nada con este cdigo. Desafortunadamente,
los trminos todava no se han aadido al documento cuando hemos anexado los manejadores el i ck. Incluso si consiguiramos anexar manejadores el i ck a estos elementos, una vez que hacemos clic en una letra diferente los manejadores dejaran de estar
anexados.
ste es un problema comn con reas de una pgina completada por AJAX. Una
solucin popular es volver a vincular manejadores cada vez que se refresca el rea de
pgina. Sin embargo, esto puede ser complicado ya que el cdigo de vinculacin de
evento se tiene que invocar cada vez que cualquier cosa hace que la estructura DOM de
la pgina cambie.
Una alternativa a menudo superior se present en un captulo anterior. Podemos
implementar delegacin de evento, vinculando el evento a un elemento ancestro que
-Limitaciones de seguridad
Para su utilidad en la elaboracin de aplicaciones Web dinmicas, XMLHttpRequest
(la tecnologa de navegador subyacente detrs de la implementacin AJAX de jQuery)
est sujeta a lmites estrictos. Para impedir varios ataques cross-site scripting (XSS),generalmente no es posible solicitar un documento de un servidor que no sea el que alberga la pgina original.
sta es por lo general una situacin positiva. Por ejemplo, algunos citan la implementacin del anlisis JSON al utilizar eval () como inseguro. Si cdigo malicioso est
presente en el archivo de datos, se podra ejecutar por la llamada eval ( ) . Sin embargo,
puesto que el archivo de datos debe residir en el mismo servidor que la propia pgina
Web, la posibilidad de incorporar cdigo en el archivo de datos es en gran medida equivalente a la psbilidad de incorporar cdigo en la pgina directamente. Esto significa
que, para el caso de cargar archivos JSON de confianza, eval () no es una preocupacin
se seguridad significativa.
Sin embargo, existen muchos casos, en los que sera beneficioso cargar datos desde
una fuente de terceros. Existen varias formas de solucionar las limitaciones de seguridad
y permitir que esto suceda.
Un mtodo es basarse en el servidor para cargar los datos remotos, y luego proporcionarlos cuando los solicite el cliente. Se trata de un enfoque muy potente ya que el
servidor puede llevar a cabo pre-procesamiento en los datos segn se necesite. Por ejemplo, podramos cargar archivos XML que contienen feeds de noticias RSS desde varias
fuentes, agregarlas en una sola feed en el servidor y publicar este nuevo archivo para el
cliente cuando se solicita.
Para cargar datos desde una ubicacin remota sin implicacin del servidor, tenemos que actuar de forma diferente. Un enfoque popular para el caso de cargar archivos
JavaScript del exterior es incorporar etiquetas <script>
bajo demanda. Puesto que
jQuery puede ayudamos a insertar nuevos elementos DOM, es sencillo realizar esto:
$(document.createElement('script'))
.attr('src',
'http://example.com/example.js')
.appendTo('head')
;
llifI
6. AJAX
ll
ll
l)
}
html
.')');
Aqu, $data es una variable que contiene una representacin de cadena de un archivo JSON. Cuando se invoca este script, el parmetro de cadena de consulta callback
se anexa al archivo resultante que se devuelve al cliente.
Para demostrar esta tcnica, solamente necesitamos modificar ligeramente nuestro
ejemplo JSON anterior para invocar esta fuente de datos remota en su lugar. La funcin
$ . getJSON () hace uso de un carcter de marcador de posicin especial, ?, para conseguir esto.
$Idocument)
.readYlfunctionl)
'</div>'
htrnl += '</div>';
htrnl += '</div>';
$I'#dictionary')
.appendIhtml)
))
+=
?>
"
<?php
</h3>';
lIliI
})
return
})
})
false
Normalmente no se nos permitira ir a buscar JSON desde un servidor remoto (examples .lear~ingj
query. com en este caso). Sin embargo, puesto que este archivo est
configurado para proporcionar sus datos en el formato JSONP, podemos obtener los
datos al anexar una cadena de consulta a nuestra URL, utilizando? como un marcador
de posicin para el valor del argumento callback. Cuando se realiza la peticin, jQuery
reemplaza la ? por nosotros, analiza el resultado, y lo pasa a la funcin de xito como
data como si esto fuera una peticin JSON local.
Observe que las mismas precauciones de seguridad se mantienen aqu como antes;
cualquier cosa que el servidor decida devolver al navegador se ejecutar en el ordenador del usuario. La tcnica JSONP solamente se debera utilizar con datos procedentes
de una fuente de confianza.
Opciones adicionales
El cuadro de herramientas AJAX proporcionado por jQuery est bien surtido. Hemos
tratado varias de las opciones disponibles, pero simplemente nos hemos quedado en
la superficie. Aunque existen muchas variantes a tratar aqu, proporcionaremos una
visin de conjunto de algunas de las formas ms destacadas de personalizar las comunicaciones AJAX.
lIiDI
6. AJAX
lID
$.aj axSetup I(
url: ra.ht~lll
type: 'POST r ,
dataType: 'html'
});
$.ajaxl{
type: 'GET'
success: functionldata)
(
$I'#dictionary') .htmlldata);
}
}) ;
".,
"
$.ajax({
url: r a. htrnl '
type: 'GET',
dataType: 'html',
success: functionldata)
(
$I'#dictionary') .htmlldata);
I
Esta secuencia de operaciones se comporta igual que nuestro ejemplo $ . aj ax () anterior. Observe que la URLde la peticin se especifica como un valor predeterminado
por
la llamada $. aj axSetup
(), por lo que no se tiene que proporcionar cuando se invoca
$ . aj ax () . Por el contrario, se asigna al parmetro type un valor predeterminado
de
POST, pero esto se puede anular en la llamada $ . aj ax () a GET.
});
"
Necesitamos especificar explcitamente el mtodo de peticin, el tipo de datos que
se devolver y lo que hacer con los datos resultantes. Claramente, esto es un uso menos
eficiente de esfuerzo de programador; sin embargo, con este trabajo adicional viene una
gran cantidad de flexibilidad. Algunas de las posibilidades de uso especiales que vienen
con utilizar una llamada $ . aj ax () de bajo nivel incluyen:
Impedir que el navegador guarde en cach respuestas del servidor. Esto puede
ser de utilidad si el servidor produce sus datos dinmicamente.
Proporcionar
remoto.
para autenticacin
La primera y ms sencilla tcnica AJAX que hemos tratado fue ir a buscar un fragmento HTML y situarlo en una pgina. Algunas veces, sin embargo, el servidor ya proporciona el HTML que necesitamos, pero est rodeado por una pgina HTML que no
queremos. Cuando no es conveniente hacer que el servidor proporcione los datos en el
formato que deseamos, jQuery puede ayudamos en el lado del cliente.
Considere un caso como nuestro primer ejemplo, pero en el que el documento que
contiene las definiciones de diccionario es una pgina HTML completa como sta:
xmlns= '~http://www . w3 .org/1999/xhtml
xml: lang= 11en"
lang=11 entt>
<head>
<meta http-equiv=I1Content-Type"
content="text/htrnl
charset=utf-8 />
<title>The Devil's Dictionary:
H</title>
e ht.m'L
())
l1
con el host
<link rel=lIstylesheetll
href=lIdictionary.cssll
type=lItext/csslI media=lIscreenll />
<!head>
<body>
<div id=lIcontainerll>
<div id=lIheader >
<h2>The Devil's
Dictionary:
H</h2>
<div class=lIauthorll>by
Ambrose
Bierce</div>
<!div>
Para detalles sobre utilizar stas y otras opciones, consulte la Gua de referencia jQuery
o consulte la referencia API online (http://docs.j
query. com/Aj ax/j Query.
ajax).
rt
<div id=lIdictionary">
<div class="entry">
<h3 class="te::rm">HABEAS
CORPUS</h3>
<div class="part">n.</div>
<div class="definition">
A writ by which aman
may be taken out of jail
when confined
for the wrong crime.
La funcin $ . aj axSetup
() nos permite especificar valores predeterminados
para
cada una de las opciones utilizadas cuando se invocan los mtodos AJAX. Toma un
mapa de opciones idnticas a las disponibles para $. aj ax () , y hace que estos valores
se utilicen en todas las siguientes peticionesAJAX a menos que se anulen.
lIiII
6. AJAX
c/div>
cjdiv>
Para eliminar estos elementos extraos, podemos utilizar una nueva caracterstica del
mtodo .load () . Cuando se especifica la URL del documento a cargar, tambin podemos proporciqnar una expresin de selector jQuery. Si est presente, esta expresin se
utiliza para localizar una parte del doc,umento cargado. Solamente la parte coincidente
del documento se inserta en la pgina. En este caso, podemos utilizar esta tcnica para
extraer solamente las entradas de diccionario del documento e insertarlas:
cdiv class=tlentryll>
ch3 class=lIterml1>HABITc/h3>
cdiv class="part">n.c/div>
cdiv class="definition">
A shackle for the free.
c/div>
</div>
</div>
$ (document) .ready(function()
{
$('#letter-h
a') .click(function()
$('#dictionary/).load('h.html
/
</div>
</body>
</htmb
})
$ (document) .ready(function()
{
$ ('#letter-h
a') .click(function()
{
$('#dictionary')
.load('h.html');
return false
})
return
})
Podemos cargar todo el documento en nuestra pgina utilizando el cdigo que hemos
escrito anteriormente:
})
llliI
false
.entry');
Ahora las partes irrelevantes del documento se excluyen de la pgina, como mues, tra la figura 6.14.
The Devll's Dlctlonary
"
by Ambmse BIerce
HABEAS CORPUS
n.
A wrtt by whlch a men may be taken out 01aft when conftned for tl1e wrong orIme.
Sin embargo, esto produce un efecto extrao debido a las piezas de la pgina HTML
que no queremos incluir, como se ve en la figura 6.13.
lO
HABIT
A
BIerce
E'<llble
EducaUOn
lO
by Ambrose BIerce
HABEAS CORPUS
~
~
IDoo'
~
~
F
HALF
!he free.
n.
Oneoftwoequal
parislnlo whIch a tIllng may be dlvlded, orconsldered asdlvlded.ln
tIlefllurteenll1
oentury B heated dlscusslon arose among theoIoglsts ami phllooophe rs as lo _
Omnlsdence
oould patt en object InID II1ree halves; olld !he pIous Father Aldrovlnus pubDcIy pmyed In th8
calhedral al Rouen lila! God would derroostrate 111.aHlrmatIve 01 tIle proposItion In SOOle slgnal 8lld
unm_1e
way, and parUcular1y (If tt should pIease HIm) upon th8 body 01 tila! hardy blasphemer,
ManutJus Prodnus. who malntalned the nega1tve. ProcfnUs, however, was spared 10 die of the bita of
a >1per.
HANO
A
n.
at !he
pocIcet
A writ by which aman may be taken out of jaD when confined fer the wrong Clime.
~
~
~
~
~
Emanc!patlon
~
Eswe!ooe
IDoo'
l!!!m!!
Evana.lIs!
n.
E!oquence
Elvslum
Emenc!oa1!on
n.
shackle lo<
HAPPINESS
HABIT
n.
HALF
n.
One of two aqual parts Into whlch s Ihing may be dlvided, o, consldered as divided.
In Ihe fourtsenlh cenlury a healed disaJsslon arase amongllleotogists aOO
phcsopbers as lo whetherOmniscience
could part en object Into Ihree halves; and
lhe pious Falhe, Aldrovinus publlcJy prayed In !he call1edral al Rouen !ha! God
would demonslrale lile aflirmalive of lile prcposition in some signsl aOO
unmlstakable wav. and particularlv CIf itshould pisase Him} ueon lile bodv of Ihal
n.
Resumen
Hemos aprendido que los mtodos AJAX proporcionados por jQuery nos pueden
ayudar a cargar datos en formatos muy diferentes desde el servidor sin un refresco de
pgina. Podemos ejecutar scripts desde el servidor bajo demanda, y devolver datos al
servidor.
ID
6.AJAX
Tambin hemos aprendido cmo tratar con desafos comunes de tcnicas asncronas
de carga, como mantener manejadores vinculados despus de que ha ocurrido una carga
y cargar datos desde un servidor de terceros.
Esto termina la parte de tutorial del libro. Contamos con las herramientas principales
ofrecidas por jQuery: selectores, eventos, efectos, manipulacin DOM y peticiones de
servidor asncronas. stas no son las nicas formas en las que jQuery puede ayudamos;
trataremos algunas de las muchas posibilidades de uso conferidas por plug-ins jQuery
en captulos posteriores. Pero primero, examinaremos algunas combinaciones de estas
tcnicas que mejoran nuestras pginas Web en nuevas e interesantes formas.
ri
"
./
"
"
.'
7
Manip_ulacin
de tabla
En los seis primeros captulos, hemos explorado la librera jQuery en una serie de tutoriales que se han centrado en cada uno de los componentes jQuery y utilizado ejemplos
como una forma de ver esos componentes en accin, Desde el captulo 7 al 9 invertimos
el proceso; empezaremos con ejemplos de problemas del mundo real, y veremos cmo
podemos utilizar mtodos jQuery para solucionarlos.
Aqu, utilizaremos un librera online como nuestro sitio Web modelo, pero las tcnicas que preparamos se pueden aplicar a una amplia variedad de otros sitios tambin,
desde weblogs a portfolios, desde sitios empresariales dirigidos al mercado a intranets
corporativas. El captulo 7 y 8 se centran en dos elementos comunes de la mayora de
sitios (tablas y formularios), mientras que el captulo 9 examina un par de formas para
mejorar visualmente conjuntos de informacin utilizando barajadores y rotativos.
Puesto que el movimiento de los estndares Web se ha vuelto muy generalizado en
los ltimos aos, el diseo basado en tabla se ha ido abandonando en favor de diseos
basados en CSS. Aunque las tablas a menudo se empleaban como una medida necesaria en los aos 90 para crear diseos de mltiples columnas y otros diseos complejos,
nunca se pensaron para utilizarse de esa forma. Por otro lado, CSS es una tecnologa
expresamente creada para estas tareas de presentacin.
Pero ste no es el lugar para una discusin ampliada sobre el papel adecuado de las
tablas. Basta decir que en este captulo utilizaremos jQuery para aplicar tcnicas para
aumentar la legibilidad, usabilidad y atractivo visual de contenedores de datos tabulares
marcados semnticamente. Para un mayor detalle sobre aplicar HTML semntico yaccesible a tablas, un buen lugar en el que empezar es la entrada de blog de Roger J ohansson,
"Bring on the Tables" en http://www
. 456bereastreet.
com/archive/200410/
bring_on_the_tables/.
7. Manipulacin de labIa
Algunas de las tcnicas que aplicamos a tablas en este captulo se pueden encontrar
en plug-ins como Table Sorter de Christian Bach. Para ms informacin, visite el jQuery
Plugin Repository en http://plugins
. j query. com/.
En este captulo, tratamos:
Paginacin
Descripciones emergentes
Esta configuracin es sencilla, pero requiere que la pgina se refresque para cada
operacin de ordenar. Como hemos visto, jQuery nos permite eliminar esos refrescos de
pgina al utilizar mtodos AJAX. Si tenemos los encabezados de columna configurados
como vnculos como antes, podemos aadir cdigo jQuery para cambiar esos vnculos
por peticiones AJAX:
Filtrado
y paginar
Dos de las tareas ms comunes realizadas con datos tabulares son ordenar y paginar.
En una tabla extensa, ser capaz de reorganizar la informacin que estamos buscando es
de un valor incalculable. Desafortunadamente, estas operaciones de utilidad pueden ser
de lo ms difcil de poner en accin.
En primer lugar, examinaremos lo que se necesita para llevar a cabo una ordenacin
de tabla, reordenando datos en una secuencia que es de ms utilidad para el usuario.
ctbody>
El servidor puede reaccionar al parmetro de cadena de consulta al devolver los contenidos de la base de datos en un orden diferente.
Resaltar filas
</th>
</tr>
</thead>
</tbody>
</table>
Ordenar
Ordenar
lf.iI
11
$ (document) .ready(function()
{
$ ('#my-data
th a') .click(function()
$ ('#my-data
tbody') .load($(this)
return false;
})
})
{
.attr('href'));
Ahora cuando se hace clie en los anclas, jQuery enva una peticin AJAX al servidor
para la misma pgina. Cuando se utiliza jQuery para realizar una peticin de pgina utilizando AJAX, establece el encabezado HTTPx-Requested-WithenXMLHttpRequest
de modo que elservidor puede determinar que se est realizando una peticin AJAX.
El cdigo de servidor se puede escribir para que devuelva solamente el contenido del
propio elemento t.bcdy, y no la pgina de alrededor, cuando este parmetro est
presente. De esta forma podemos tomar la respuesta e insertarla en lugar del elemento
t body existente.
ste es un ejemplo de mejora progresiva. La pgina funciona perfectamente bien sin
ningn JavaScript, ya que los vnculos para ordenacin del lado del servidor siguen estando presentes. Cuando JavaScript est disponible, sin embargo, AJAX secuestra la peticin de pgina y permite que la ordenacin ocurra sin una carga de pgina completa.
Ordenacin JavaScript
>
cthead>
ctr>
cth class=lIname
-/
>
ll
Sin embargo, existen momentos, cuando o bien no queremos esperar respuestas del
servidor cuando ordenamos, o no tenemos un lenguaje de script del lado del servidor
disponible. Una alternativa viable en este caso es llevar a cabo la ordenacin por completo en el navegador utilizando programacin JavaScript del lado del cliente.
Por ejemplo, suponga que tenemos una tabla que lista libros, nombres de los autores,
fechas de publicacin y precios, como se ve en la figura 7.1.
IDDI
7. Manipulacin
de tabla
TIUo
Aulho,(s)
Hagen Graf
Nos gustara convertir los encabezados de tabla en botones que ordenen los datos
por sus columnas respectivas. Exploremos algunas formas de hacer esto.
.
_;m:mmlF.'I(;1I11m1
Feb2007
lfD
$oW.49
Learnlng Mambo: A
SIep.by-Step l\JlOrial
lo Building You,
Webs~.
Douglas Paterson
MoodIe E-I..earnlng
Course Oevelopmenl
WllUam Rice
May2006
$35.99
AJA)( 3M PHP:
Building Rasponslve
Web Applloatlons
Mar 2006
531.49
OpenVPN: Building
Bnd Integrallng Virtual
Prtvata Networ1<s
Mar1<usFellner
May2006
0002006
$oW.49
Observe nuestro uso de las etiquetas t.he ad y t body para segmentar los datos
en agrupaciones de fila. Muchos autores HTML omiten estas etiquetas, pero pueden
resultar de utilidad al proporcionamos selectores CSS ms convenientes a utilizar. Por
ejemplo, suponga que deseamos aplicar una distribucin tpica de fila par /frnpar a esta
tabla, pero solamente al cuerpo de la tabla:
$ (document) .ready(function()
$('table.sortable
tbody
$('table.sortable
tbody
n.
553.99
.'
{
tr:odd') .addClass('odd');
tr:even') .addClass('even');
Esto aadir colores alternas a la tabla, como se ve en la figura 7.2, pero deja el encabezado sin tocar.
ctable claS9=t'sortable">
c::thead>
TIUe
c::tr>
Autho,(s)
I~.'C].2!@i'.m,.a~
,~,;'
."
, ..;'\1::-:< ':~ ;f,;j-;;;~~"
<th></th>
<th>Title</th>
<th>Author(s) </th>
<th>Publish Date</th>
<th>Price</th>
</tr>
</thead>
<tbody>
c::tr>
11
c::tr>
<td><img
src" ../images/covers/small/1904811620
.png"
width=tl49"
height=1I61" alt="Learning
Mambo: A
Step-by-Step
Tutorial
to Building
Your Website"
/>
</td>
<td>Learning
Mambo: A Step-by-Step
Tutorial
to Building
</td>
<td>Douglas
Paterson</td>
<td>Dec 2006</td>
<td>$40.49</td>
</tr>
</tbody>
</table>
Your
Website
Ordenacin
alfabtica bsica
Ahora llevemos a cabo una ordenacin sobre la columna Title (ttulo) de la tabla.
Necesitaremos una clase en la celda del encabezado de tabla de modo que podamos seleccionarlo adecuadamente:
\;":""''''
lIiI
7. Manipulacin
de tabla
cthead:::.
<tr>
if
cth></th>
cth class="sort-alpha">Titlec/th>
<th>Author(s) </th>
<th>Publish ,Date</th>
cth>Pricec/th>
</tr>
</thead>
arr = [52,
97,
3,
62,
10,
63,
64,
1,
9,
3,
10,
3,
3,
4,
52,
62,
63,
64,
9,
})
97}
Por defecto, como vemos aqu, los elementos se ordenan lexicogrficamente (en orden
alfabtico). En este caso podra tener ms sentido ordenar los elementos numricamente.
Para hacer esto, podemos proporcionar una funcin comparador al mtodo . sort ( ) :
arr.sort(function(a,b)
if (a < b)
return -1;
if (a > b)
return 1;
return O;
}),
3,
3,
4,
9,
10,
52,
62,
63,
64,
97}
.text()
.text()
4},
($header.is(' .sort-alpha'))
(
~header.addClass('clickable')
.hover(function()
$header.addClass('hover')
,
function () {
$header. removeClass (,~hover' ) i
}) .click(function()
(
var rows = $table.find('tbody
> tr') .get(),
rows. sort (function(a,
b) (
var keyA = Sta) .children('td')
.eq(column)
.toUpperCase()
,
var keyB = $(b) .children('td')
.eq(column)
.toUpperCase()
,
if (keyA < keyB) return -1,
if (keyA > keyB) return 1,
return O;
lIfiI
})
, .
$.each(rows,
function(index,
$table.children('tbody')
})
row) (
.append(row)
}),
Lo primero a destacar es nuestro uso del mtodo . each () para crear la iteracin explcita. Aunque podramos vincular un manejador click a todos los encabezados que
tienen la clase sort-alpha
al invocar $ ( table. sortable
th. sort -alpha ') .
click (), esto no nos permitira capturar fcilmente una parte crucial de informacin:
la columna ndice del encabezado que se hace clic. Puesto que . each () pasa el ndice
de iteracin a su funcin de rellamada, podemos utilizarlo para encontrar la celda relevante en cada fila de los datos ms adelante.
Una vez que hemos encontrado la celda encabezado, recuperamos una tabla de todas
las filas de datos. Esto es un estupendo ejemplo de cmo. get () es de utilidad al transformar un objeto jQuery en una tabla de nadas DOM; aunque los objetos jQuery actan
como tablas en muchos aspectos, no tienen ninguno de los mtodos de tabla nativos
disponibles, como . sort ( ) .
Ahora que tenemos una tabla de nadas DOM, podemos ordenarlos, pero para hacer
esto necesitamos escribir una funcin comparador apropiada. Deseamos ordenar las filas
de acuerdo a los contenidos textuales de las celdas de tabla relevantes, por lo que sta
ser la informacin que la funcin comparador examinar. Sabemos qu celda examinar
porque capturamos el ndice de columna en la llamada . each ( ) .
Convertimos el texto en mayscula porque las comparaciones de cadena en JavaScript
son sensibles a mayscula y minscula y queremos que nuestra ordenacin no sea sensible a mayscula y minscula. Almacenamos los valores clave en variables para evitar
clculos redundantes, compararlos, y devolver un nmero positivo o negativo como se
ha tratado antes.
Por ltimo, con la tabla almacenada, pasamos en bucle por las filas y las insertamos
en la tabla. Puesto que . append () no clona nadas, esto las mueve en lugar de copiarlas. Nuestra tabla est ahora ordenada.
I
7. Manipulacin
de labia
Aprende jQuery 1.3
Esto es un ejemplo del equivalente de mejora progresiva, es decir, degradacin elegante. A diferencia de la solucin AJAX tratada anteriormente, esta tcnica no puede
funcionar sin JavaScript asumimos que el servidor no dispone de lenguaje de script
disponible para este ejemplo. Puesto que se necesita JavaScript para el tipo de trabajo,
estamos aadiendo la clase clickable por medio del cdigo solamente, asegurndonos as que la interfaz indica que la ordenacin es posible (con una imagen de fondo)
solamente si el script se puede ejecutar. La pgina se degrada en una que sigue siendo
funcional, aunque sin ordenacin disponible.
Hemos movido las filas, de ah que nuestros colores alternos de fila estn ahora descontrolados, como muestra la figura 7.3.
$header.removeClass('hover')
i
l,) .click(function()
(
var rows = $table.find('tbody
> tr') .get();
rows.sort(function(a,
b) (
var keyA = $(a) .c~ldren('td')
.eq(column)
.toUpperCase()
;
var keyB = $(b) .children('td')
.eq(column)
.toUpperCasel);
if (keyA < keyB) return -1;
if IkeyA > keyB) return 1;
return O;
1&1
.text()
.text()
l) ;
$.each(rows, function(index,
row) {
$table.children('tbody')
.append(row);
l) ;
alternateRowCo1ors($table);
l) ;
l) ;
l) ;
l) ;
Esto corrige el color de la fila, solucionando el problema, como se muestra en la figura 7.4.
Necesitamos volver a aplicar los colores de fila despus de llevar a cabo la ordenacin. Podemos hacer esto al situar el cdigo de color en una funcin que podemos invocar cuando sea necesario:
$ (document)
.ready(function()
var alternateRowColors
= function($table)
$('tbody
tr:odd',
$table)
.removeClass('even') .addClass('odd');
$ ('tbody tr:even',
$table)
.removeClass{'odd').addClass('even')
};
$('table.sortable')
.each(function()
var $table = $(this);
alternateRowColors($table);
$('th', $table) .each(function(column)
var $header = $(this);
if ($header.is(' .sort-alpha'
(
$header.addClass('clickable')
$header.addClass('hover');
l, functionl) (
mi
7. Manipulacin
de tabla
jQuery.fn.alternateRowColors
= function() {
$('tbody
tr:odd',
this)
.removeClass('even') .addClass('odd');
$('tbody
tr:even',
this)
.removeClass(lodd
,addClass('even') i
.toUpperCase();
if (keyA < XeyB) return
if (keyA > keyB) return
return O;
-1;
1;
j);
1)
return
mil
"
this
};
$.each(rows,
function(index,
row) (
row.sortKey
= $(row) .children('td')
.text() .toUpperCase();
}) ;
,. rows.sort(function(a,
b) {
})
$.each(rows,
function(index,
$table.children('tbody')
row.sortKey = null
if (a. sortKey
if (a.sortKey
return Di
})
.text()
.toUpperCase()
;
keyB = $(b) .children('td')
.eq(column)
.text()
var
return
return
-1;
1;
row) (
.append(row)
(),
Nuestro cdigo funciona, pero es bastante lento. El culpable es la funcin comparador, que est llevando a cabo una gran cantidad de trabajo. Este comparador se invocar muchas veces durante el transcurso de una ordenacin, lo que significa que cada
momento adicional que pasa procesando se magnificar.
El algoritmo de ordenacin utilizado por JavaScript no se define por el estndar.
2
Puede ser una sencilla ordenacin como una ordenacin burbuja (el mejor caso de 0(n )
en trminos de complejidad computacional) o un enfoque ms sofisticado como ordenacin rpida (que es 0(n log n)). Sin embargo, es seguro decir que duplicar el nmero
de elementos en una tabla ser ms del doble el nmero de veces que se invoca la funcin comparador.
El remedio para nuestro comparador lento es precalcular para la comparacin.
Empezamos con nuestra funcin de ordenacin actual y lenta:
.eq(column)
b. sor t xey)
b.sortKey)
Problemas de rendimiento
rows.sort(function(a,
b) (
var keyA = $(a) .children('td')
>
<
.eq(column)
$.each(rows,
function(index,
row) {
$(row).data('sortKey',
$ (row) .children('td')
.eq(column) .text() .toUpperCase(;
) ;
rows.sort(function(a,
b) (
if ($(a) .data('sortKey')
return -1;
if ($(a) .data('sortKey')
return 1;
<
$(b) .data('sortKey'
>
$(b) .data('sortKey'
lID
AprendejQuery
7. ManipuLacin de tabla
return O;
}) ;
$.eaeh(rows, funetion(index,
row) (
$table.ehildren('tbody')
.append(row);
$ (row) .removeData{'sortKey');
}) ;
Utilizar. data () en lugar de propiedades expanda puede ser, a veces, ms conveniente, ya que a menudo estamos trabajando con objetos jQuery en lugar de directamente con nadas DOM. Tambin evita problemas potenciales con prdidas de memoria de
Internet Explorer. Sin embargo, para el resto de este ejemplo, nos ceiremos a las propiedades expanda para practicar el alternar entre operaciones en nadas DOM y operaciones en objetos jQuery.
1.3
$.eaeh(rows, funetion(index,
row) (
var $eell ~ $(row) .ehildren('td') .eq(eolumn);
row.sortKey = $eell.find(' .sort-key') .text() .toUpperCase()
+ ' , ~ $eell.text() .toUpperCase();
-',
});
Tltl.
Autllor(s)
d:rrl:lIm:W
Ftttlllill!l
:1.1
11
11
<tr>
Ahora, tenemos que modificar nuestro cdigo de ordenacin para tener en cuenta
esta etiqueta sin molestar el comportamiento existente para la columna Title, que ya funciona bien. Al anexar la clave de ordenacin marcada a la clave que hemos calculado
previamente, podemos ordenar primero por el apellido si se invoca, pero sobre toda la
cadena corno seguridad:
Si dos apellidos son idnticos, la ordenacin utiliza toda la cadena para decidir la
posicin.
"));
La expresin regular utilizada aqu elimina cualquier carcter distinto de los nmeros
y puntos decimales, pasando el resultado a parseFloat (). El resultado de parseFloat () luego se tiene que comprobar, porque si no se puede extraer ningn nmero
del texto, se devuelve NaN(not a number). Esto puede causar estragos en . sort () .
Para las celdas de fecha, podemos utilizar el objeto JavaScript Date:
row.sortKey
= Date.parse('l
' + $eell.text());
El
7. Manipulacin
de tabla
Las fechas en esta tabla contienen un mes y ao solamente; Date. parse () requiere
una fecha especificada completamente, por lo que precedemos la cadena con 1. Esto proporciona un da para complementar el mes y ao, y la combinacin luego se convierte en
una marca de tiempo, que se puede ordenar utilizando nuestro comparador normal.
Podemos repartir estas expresiones entre funciones aparte, e invocar la apropiada
basndonos en la clase aplicada al encabezado de tabla:
return
})
o;
$.each(rows,
function(index,
$table.children('tbody')
row. sortKey = nul,~i
})
row) (
.append(row)
$table.alternateRowColors()
})
jQuery.fn.alternateRowColors
= function() (
$('tbody
tr:odd', this)
.removeClass('even')
.addClass('odd')
/
$('tbody
tr:even',
this)
.removeClass('odd') .addClass(reven') i
return this
})
})/
})
}/
$ (document) .ready(function()
(
$('table.sortable')
.each(function()
var $table = $(this)/
$table.alternateRowColors()
/
$('th', $table) .each(function(column)
var $header = $(this) /
var findSortKey;
if ($header.is('.sort-alpha')
{
findSortKey
function($cell)
{
return $cell.find('.sort-key')
.text() .toUpperCase()
+ ' , + $cell.text() .toUpperCase()
.'
o',
"
};
el se if ($header. is ( ,.sort-numeric' l I {
findSortKey
= function($cell)
{
var key = $cell.text() .replace(/A[A\d.l*/.
key.
parseFloat(key);
return isNaN(key)
? o : key;
}
");
}
Figura 7.6. Ordenar por fecha.
else if ($header.is('.sort-date'
{
findSortKey
= function($cell)
{
return Date.paree('l
+ $cell.text(
=:.
ntlo
I-::
Author(s}
};
if
(findSortKey)
{
$header.addClass('clickable')
.hover (function ()
$header.addClass('hover')/
}. function () (
$header.removeClass('hover')
/
}) .click (function () (
var rows = $table.find('tbody
> tr') .get() /
$.each(rows,
function(index,
row) (
var $cell = $ (row) .children('td')
.eq(column)
row.sortKey
= findSortKey($cell);
})
rows.8ort(function(a.
b) (
if (a.90rtKey
< b.sortKey)
if (a.8ortKey
> b.sortKey)
lID
return
return
-1/
1/
IEI
7. Manipulacin
r'"
de tabla
Resaltar columna
Puede ser una buena mejora de interfaz de usuario recordar visualmente al usuario
lo que se ha hecho en el pasado. Al resaltar la columna que se ha utilizado recientemente
para ordenar, podemos centrar la atencin del usuario en la parte de la tabla que es ms
probable que sea relevante. Afortunadamente, puesto que ya hemos determinado cmo
seleccionar las celdas de tabla en la columna, aplicar una clase a esas celdas es sencillo:
$table.find('td')
.removeClass('sorted')
.filter(' :nth-child('
+ (column
+ 1) + ') ')
.addClass('sorted')
;
Auttlor(s)
jQuery.fn.alternateRowColors
= function()
$('tbody
tr:odd',
this)
,removeClass('even') .addClass('odd')
$('tbody
tr:even',
this)
.removeClass{'odd')
.addClass{'even')
return this
$ (document) .ready(function()
(
$('table.sortable')
.each(function()
var $table = $(this);
$table.alternateRowColors()
;
$('th', $table) .each(function(column)
var $header = $(this);
var findSortKeYi
if ($header.is(' .sort-alpha'))
(
findSortKey
= function($cell)
(
return $cell.find('
.sort-key') .text() .toUpperCase()
+ ' , + $cell.text()
.toUpperCase()
;
};
SteveA1wa1
K SOOttAlIen
");
};
aaln
};
PhUlppe aaurnann, Henriette
aaumann, Pa1l1ck Grassle
Figura
if
(findSortKey)
(
$header.addClass('clickab1e')
.hover(function()
$header.addClass('hover')
;
}. function () (
$header.removeC1ass('hover')
;
}) .c1ick(function()
{
var sortDirection = 1;
if ($header. is ( , . sorted-asc' ) )
sortDirection = -1;
Nuestra ltima mejora de ordenacin es permitir ordenacin ascendente y descendente. Cuando el usuario hace clic en una columna que ya est ordenada, queremos invertir el orden actual de ordenacin.
Para invertirlo, todo lo que tenemos que hacer es invertir los valores devueltos por
nuestro comparador. Podemos hacer esto con una sencilla variable:
if
rows.sort(function(a,
b) {
if (a.sortKey < b.sortKey)
if (a.sortKey
> b.sortKey)
(a.sortKey
if (a.sortKey
<
>
b.sortKey)
b.sortKey)
return
return
-sortDirection;
sortDirection
lID
};
Este fragmento primero elimina la clase sorted de todas las celdas, luego la aade a
las celdas que estn en la misma columna que hemos utilizado para nuestra ordenacin.
Observe que tenemos que aadir 1 al ndice de columna que hemos encontrado anteriormente, ya que el selector : nth-child {)es en base uno en lugar de en base cero. Con
este cdigo en su lugar, recibimos una columna resaltada despus de cada operacin de
ordenacin, como muestra la figura 7.8.
"
e
})
return
return
-sortDirection
sortDirection;
r~"
ID
7. Manipulacin
de tabla
return
})
O;
}
e1se {
$header.addClass('sorted-desc');
$table.findl'td') .removeClass('sorted')
.filter(' :nth-child(' + (column + 1) + ')')
.addClass('sorted') ;
$table.alternateRowColors();
;
}
})
.'
]l;
})
Como un beneficio secundario, puesto que utilizamos clases para almacenar la direccin de ordenacin, podemos aplicar estilo a los encabezados de columna para indicar
el orden actual tambin, como se ve en la figura 7.9.
Los datos que se benefician de la ordenacin es probable que tambin sean un candidato para la paginacin. No es raro desear combinar estas dos tcnicas para la presentacin
de datos. Puesto que ambos afectan al conjunto de datos que est presente en una pgina,
sin embargo, es importante considerar sus interacciones mientras se implementan.
Tanto ordenar como paginar se pueden realizar tanto en el servidor, o en el navegador Web. Sin embargo, debemos mantener las estrategias para las dos tareas en sincrona; de lo contrario, podemos acabar con un comportamiento confuso. Suponga, por
ejemplo, que tenemos una tabla con ocho filas y dos columnas, ordenada inicialmente
por la primera columna.
Si los datos se vuelven a ordenar por la segunda columna, muchas filas pueden cambiar de lugar, como se ve en la figura 7.10.
1
2
H
Antes
Figura 7.9. Aplicar estilo a los encabezados
lID
$.each(rows, function(index,
row) {
$table.children('tbody')
.append(row);
row.sortKey = null
}) ;
$table.find('th') .removeClass('sorted-asc')
.removeClass('sorted-desc')
if (sortDirection _. 1) {
$header.addClaas('sorted-asc');
})
8
Despus
de columna.
Figura 7.10. Ordenar por la primera y segunda columna.
lImI
7. Manipulacin
II
de tabla
---
.--
Despus
Antes
Antes
Despus
Paginacin JavaScript
I~
no queremos que los encabezados o pies de pgina desaparezcan cuando nos movemos
a la segunda pgina. Para seleccionar las filas que contienen datos, ocultamos todas las
filas primero)uego seleccionamos las filas en la pgina actual, mostrando las filas seleccionadas. El mtodo. slice () mostrado aqu funciona como el mtodo de tabla del
mismo nombre; reduce la seleccin a los elementos entre las dos posiciones dadas.
La tarea ms propensa a error al escribir este cdigo es formular las expresiones a
utilizar en el filtro. sl ice () . Necesitamos encontrar los ndices de las filas al principio
y final de la pgina actual. Para la fila inicial, simplemente multiplicamos el nmero de
la pgina actual por el nmero de filas en cada pgina. Multiplicar el nmero de filas
por uno ms que el nmero de pgina actual nos da la fila inicial de la siguiente pgina;
el mtodo. slice () va a buscar las filas hasta y no incluido este segundo parmetro.
Mostrar el paginador
Para aadir interaccin de usuario a la mezcla, necesitamos situar un pagina dar
junto a la tabla: un conjunto de vnculos para navegar a diferentes pginas de datos.
Podramos hacer esto al insertar simplemente vnculos para las pginas en el cdigo
HTML, pero esto violara el principio de mejora progresiva que hemos estado adoptando. En su lugar, deberamos aadir los vnculos utilizando JavaScript, por lo que los
usuarios sin posibilidades de script disponibles no sean inducidos a error por vnculos
que no pueden funcionar.
Para mostrar los vnculos, necesitamos calcular el nmero de pginas y crear un nmero correspondiente de elementos DOM:
var nurnRows
var numpages
$table.find('tbody
tr') .length;
/ numPerPage)
= Math.ceil{nurnRows
$ (document) .ready(function()
{
$('table.paginated')
.each(function()
var currentPage = o;
var numPerpage = 10;
var $table = $(this);
$table.find('tbody
tr') .hide()
.slice(currentPage
* numPerpage,
(currentPage
+ 1) * numPerpage)
.show() ;
})
})
1t
'</span>')
}
$pager. insertBefore
($table) ;
Este cdigo muestra la primera pgina, diez filas de datos. Una vez ms nos basamos en la presencia de un elemento t.body para separar datos de los encabezados;
lmII
lliEI
7. Manipulacin de tabla
1m
Para corregir este problema, aprovecharemos una de las caractersticas ms avanzadas de los mtodos de vinculacin de eventos de jQuery. Podemos aadir un conjunto
de datos de eyento personalizado al manejador cuando lo vinculamos que seguir estando disponible cuando se invoque el,manejador. Con esta posibilidad de uso a nuestra
disposicin, podemos escribir:
$(I<:span class="page-numberll></span>r)
.text(page
+ 1)
.bind('click',
{newpage:
page} , function(event)
(
currentPage = event.data['newPage');
repaginate()
;
}) .appendTo($pager)
.addClass('clickable');
};
var numRows = $table.findl'tbody
tr') .length;
var numpages
= Math.ceillnumRows
/ numperpage);
var $pager = $('<div class="pager"></div>') i
for (var page = O; page < numPages;
page++)
{
$(I<span
clas9=lIpage-number"></span>') .text(page
.clicklfunctionl)
(
currentpage = page;
repaginate()
;
}) .appendTol$pager)
.addClass('clickable');
.'
+
1)
}
Spager.insertBefore($table);
})
n.
;
!"!t!!1ItlIQ4MIfflHillml
mi
7. Manipulacin
de labia
(currentPage
.show() ;
1) * numPerpage)
};
var numRows = $table.find('tbody
tr') .length;
var numpages = Math.ceil(numRows
/ numPerpage} i
var $pager
= $ ('c:::div class=lIpagertl></div>');
foro (var page = O; page < numpages;
page++)
{
$('c:::span class="page-numbertl></span>')
.text(page
.bind('click',
{newPage,
page} , function(event)
currentPage = event.data(tnewPage
i
repaginate() ;
$(this) .addClass('active')
.siblings() .removeClass('active');
}) .appendTo($pager)
.addClass('clickable');
1)
t]
11m
porque se encuentra contenido dentro de un manejador $ (document) . ready (! diferente. Podramos simplemente consolidar las dos piezas de cdigo, pero en su lugar
hagamos algo diferente. Podemos desacoplar los comportamientos, de modo que una
ordenacin in';ocael comportamiento ,repaginate
si existe, pero lo ignora de lo contrario. Para conseguir esto, utilizaremos un manejador para un evento personalizado.
En nuestra explicacin de gestin de evento anterior, nos limitamos a nombres de
evento que se activaban por el navegador Web, corno click y mouseup. Los mtodos
.bind () y . trigger
() no se limitan a estos eventos, sin embargo; podemos utilizar
cualquier cadena corno un nombre de evento. Utilizando esta posibilidad de uso, po/ demos definir un nuevo evento denominado repaginate
corno un sustituto para la
funcin que hemos estado invocando:
}
$pager. insertBefore
($table)
.find('span.page-number:first').addClass('active')
})
Ahora tenemos un indicador del estado actual del pagnador, corno muestra la figura 7.16.
$table.bind('repaginate',
function()
{
$table.find('tbody
t r v.) .hide()
.slice(currentPage
* numPerpage,
(currentPage
+ 1) * numPerpage)
.show() ;
}) ;
Podemos lanzar esta llamada en nuestro cdigo de ordenacin tambin. No har nada
si la tabla no tiene un paginador, por lo que podemos mezclar las dos posibilidades de
uso de la forma deseada.
El cdigo
terminado
Figura 7.16.
};
$ (document) .ready(function()
{
$('table.sortable')
.each(function()
var $table = $(this);
$table.alternateRowColors();
$('th', $table) .each(function(column)
var $header = $(this);
var findSortKey;
if ($header.is(' .sort-alpha'))
(
findSortKey
= function($cell)
{
return $cell.find('.sort-key')
.text() .toUpperCase()
+ ' , + $cell.text()
.toUpperCase()
;
r.
mi
7. Manipulacin
de tabla
"
lliiI
$('table.paginated') .each(function()
var currentPage = O;
var numPerpage = 10i
var $~able = $(this);
$table.bind('repaginate',
fun~tion()
$table.find('tbody
tr') .hide()
.slice(currentpage
* numPerPage,
(currentPage + 1) * numPerpage)
.show ();
}) ;
var numRows = $table.find('tbody
tr') .length;
var numpages = Math.ceil(nurnRows
/ numPerPage);
var $pager = $('<div class="pager ></div>');
for (var page = o; page < numPages; page++) {
$('<span class="page-number"></span>')
.text(page + 1)
.bind('click', {newPage, pagel, function(event)
(
currentPage = event.data{'newPage'];
$table.trigger('repaginate')
;
$(this) .addClass('active')
.siblings() .removeClass('active')
i
}) .appendTo($pager) .addClass('clickable');
");
};
else if ($header.is(' .sort-date')) (
findSortKey = function($cell)
(
return Date.parse('l
' + $cell.text());
};
r'
l1
if
(findSortKey) (
$header.addClass('clickable')
.hover(function()
$header.addClass('hover')
;
}, function () (
$header.removeClass{'hover')
;
}) .click(function()
{
var sortDirection
= 1;
if ($header.is(' .sorted-asc'))
sortDirection
= -1;
"
}
var rows = $table.find('tbody
, tr') .get();
$.each(rows, function(index,
row) (
var $cell = $ (row) .children('td') .eq(column);
row.sortKey = findSortKey($cell);
})
}
else (
$header.addClass('sorted-desc')
}
$table.find('td') .removeClass('sorted')
.filter (',nth-child (' + (column + 1) + ')')
.addClass('sorted') ;
$table.alternateRowColors();
$table.trigger('repaginate');
})
.addClass('active')
Resaltar filas
Una forma prctica de dirigir la vista del usuario a las filas resaltadas es proporcionar una indicacin visual sobre los datos que son importantes. Para examinar algunas
estrategias de resaltado, necesitamos una tabla con la que trabajar. Esta vez, empezaremos con una tabla de elementos de noticias. La tabla ser un poco ms complicada que
la ltima; incluir algunas filas utilizadas como subencabezados, adems de una fila de
encabezado principal. La estructura HTML es como sigue:
}
});
})
})
rows.sort(function(a,
b) {
if (a.sortKey < b.sortKey) return -sortDirection;
if (a.sortKey > b.sortKey) return sortDirection;
return O;
}I;
$.each(rows, function(index,
row) (
$table.children('tbody')
.append(row);
row.sortKey = null
}) ;
$table.find('th') .removeClass('sorted-asc')
.removeClass('sorted-desc')
;
if (sortDirection == 1) (
$header.addClass('sorted-asc')
;
})
$pager.insertBefore($table)
.find(rspan.page-number:first')
}I;
$ (document) .ready(function()
<table>
<thead>
<tr>
<th,Date</th,
<th,Headline</th,
lmI
7. Manipulacin
de tabla
lmiI
<th,Author<!th,
<th,Topic<!th,
</tr>
<!thead,
<tbody'
John Reslg
1I11rd.party
ReyBango
oonference
JohnReslg
announcement
conferenoe
ctr>
JQuery.comStte Red.slgn
cth colspan="4">2008c/th>
<!tr,
ctr>
<td,Sep 28<!td,
<td,jQuery,
Microsoft,
<td,John
Resig<!td,
<td,third-party<!td,
<!tr,
Kan Swedberg
jQuery VI 1.5.2
Paul Bakaus
!elease
Jun 26
JQuery UI 1.5.1
Paul8akaus
rele
Jun 26
Rey Bango
conference
Jun 9
Paul Bakaus
rol
Jun 4
John Reslg
release
oonference
and Nokia<!td,
ctr>
<td,Jan 15<!td,
<td,jQuery
1.2.2: 2nd Birthday
<td,John Resig<!td,
ctd>releasec/td>
<!tr,
<!tbody,
et.body
Present<!td,
Mar 7
Rlchartl Worth
Feb8
John Reslg
!el
Jan 23
Paul Bakaus
announcement
Jan 15
John ResIg
roIease
Mlke HosteUer
announcement
2007
Dec8
Doc6
Nov2
ror JQuery
Figura 7.17.
Bmdley Sapos
plug.-ln
Roy Bango
Ihlrd-parly
<tr>
cth
<!tr,
colspan="4":;.2007</th>
Como hemos visto, aplicar un diseo de franjas a las filas puede ser tan sencillo como
un par de lneas para aadir clases a las filas pares e impares:
ctr:>
<td,Dec 8<!td,
<td,jQuery
Plugins site
<td,Mike
Hostetler<!td,
ctd>announcement</td>
<!tr,
updated<!td,
ctr>
<td,Jan ll<!td,
<td,Selector
Speeds<!td,
<td,John
Resig<!td,
ctd>sourcec/td>
<!tr,
<!tbody,
$ (document)
.ready(function()
$('table.striped
$('table.striped
})
tr:odd) .addClass('odd');
tr:even) .addClass('even');
Aunque este cdigo funciona bien para estructuras sencillas de tabla, si introducimos
filas adicionales que no queremos que se le apliquen las franjas alternas de color (como
las filas subencabezado que estamos utilizando para los aos en nuestra tabla), el patrn
bsico par-impar no es suficiente. Si, por ejemplo, la fila 2006 se clasificara como even,
las filas antes y despus de ella seran odd, lo que probablemente no es deseable, como
muestra la figura 7.18.
<!table,
Observe el uso de mltiples secciones e t.body. Esto es cdigo HTML vlido para
agrupar conjuntos de filas juntas. Hemos situado los subencabezados de seccin dentro
de estas agrupaciones, utilizando elementos t.h. Con CSS bsico aadido, esta tabla
se muestra como se ve en la figura 7.17.
Figura 7.18.
Podemos garantizar que nuestro patrn de alternar fila empieza de nuevo con cada
ao al utilizar la pseudo-clase : nth -child () que hemos aprendido en un captulo anterior, como se ve en la figura 7.19.
l'
ElI!I
7. Manipulacin
de tabla
,r
II!II
Como eje~plo, modificaremos el diseo a franjas de nuestra tabla de noticias 'para colorear sus filas de tres en tres.
Figura 7.19.
$ (document) .ready(function()
{
$('table.striped
tr:nth-child(odd)
$('table.striped
tr:nth-child(even)
})
') .addClass('odd');
') .addClass('even');
Figura 7.21.
Cada grupo de filas ahora empieza con una fila odd, pero las filas subencabezado se
incluyen en este clculo. Por lo tanto, podramos no considerar las filas subencabezado
con la pseudo-clase :has () como muestra la figura 7.20.
En un captulo anterior presentamos el mtodo. f il ter () para seleccionar elementos de pgina de una forma muy flexible. Recuerde que. filter
() puede tomar no
solamente una expresin selector, sino tambin una funcin filtro, y podemos escribir:
$ (document) .ready(function()
{
$ ('table.striped
tbody') .each(function()
{
$ (this) .find ('tr: not ( :has (th) ) ,) .filter (function
return
(index % 6) < 3;
}) .addClass ( "odd ') ;
}) ;
})
Figura 7.20.
$ (document) .ready(function()
{
$('table.striped
tr:not(:has(th))
$('table.striped
tr:not(:has(th))
}I;
Excluirlas filassubencabezado.
:odd') .addClass('odd');
:even') .addClass('even');
Ahora los encabezados se excluyen, pero las agrupaciones empezarn con una fila odd
o even dependiendo de la clasificacin aplicada a la fila de datos anterior. Reconciliar
estos dos comportamientos puede ser complicado; una opcin sencilla es incorporar algo
de iteracin explcita utilizando el mtodo . each ( ) .
$( document) .ready(function()
{
$('table.striped
tbody') .each(function()
{
$(this) .find('tr:not(:has(th))
:odd') .addClass('odd');
$(this) .find('tr:not(:has(th))
:even') .addClass('even');
}) ;
});
Ahora cada agrupacin se alterna en franjas de forma independiente, y las filas subencabezado se excluyen de los clculos, como se ve en la figura 7.21.
(index)
Este cdigo realiza mucho en muy poco espacio, por lo que lo dividiremos en pequeas piezas. Primero, utilizamos el mtodo. each () como antes para segmentar nuestra
tarea al agrupar filas. Queremos que nuestras franjas de tres filas empiecen de nuevo despus de cada subencabezado, por lo que esta tcnica nos permite trabajar en una seccin
de cada vez. Luego, utilizamos. f ind () como en nuestro ltimo ejemplo para localizar
todas las filas que no tienen elementos -c t h (y por lo tanto, no son subencabezados).
Ahora, necesitamos seleccionar los tres primeros elementos de este conjunto, saltarse tres elementos, etc. Aqu es donde entra en juego. f i 1ter ( ) . La funcin filtro toma
un argumento que contiene el ndice del elemento dentro del conjunto coincidente, es
decir, el nmero de fila en el apartado de la tabla que estamos examinando. Si, y slo si,
nuestra funcin filtro devuelve true, el elemento permanecer en el conjunto.
El operador mdulo (%) nos proporciona la informacin que necesitamos. La expresin
index % 6 evala en el resto del nmero de fila cuando se divide entre 6; si este resto es
O,1, o 2, entonces marcaremos la fila como odd; si es 3, 4 5, la fila ser even.
El cdigo, segn se ha presentado, solamente marca los conjuntos odd de filas. Para
aplicar tambin la clase even, podramos escribir otro filtro que aplique el filtro contrario, o podramos ser un poco ms creativos:
$ (document) .ready(function()
{
$('table.striped
tbody') .each(function()
{
$(this) .find('tr:not(:has(th))
') .addClass('even')
.filter(function(index)
{
return
(index % 6) < 3;
}) .removeClass('even')
.addClass('Odd');
});
})
Aprende jQuery
Aqu aplicamos la clase even a todos las filas, y la eliminamos si aadimos la clase
odd. Nuestra tabla ahora tiene aplicado estilo alternando agrupaciones de fila, lo que
empieza de nuevo con cada nueva seccin de la tabla, como se ve en la figura 7.22.
HaadUn 8 ~ "
r
.<'
"',"
~t;':-:::i1;~,
...,... ~':.Y
. ;~'
})
seo 28 '
ti;;:
.'JOh~:~~{g',;il~t1~(
Aug31
:'R-eY-8;~'g'O'(?\::~\~:~~~~ferti~fe
~;r,"
Aug29
: Jahn Reslg
"ennooncement
Aug 15
Kan Swedberg
Jul14
Paut Bakaus
ralease
Jun 26
Paul Bakaus
release
. ..
Jun '26
"
';,;
:1'
f;;
conference
R~y"8anQ~':,>?:k;,: 'i;nf~r~~,ca
E.'"
'-"':;',.-
Jun 9
Observe que utilizamos la pseudo-clase : nth- child (n) como parte de la expresin
selector que apunta a la tercera columna donde est la informacin de autor, En caso de
que la estructura de tabla fuera a cambiar ms adelante, querramos que esta constante 3 estuviera solamente en un lugar en el cdigo, de modo que se pudiera actualizar
fcilmente. Por esta razn, almacenamos el resultado de nuestro selector en la variable
$authorCells
en lugar de repetir el selector cada vez que se necesita,
'f:
r.;.;'
.r
~~,..~{~}~f~~~~~~~~
~
~i~-party
ElD
$authorcells.clicklfunctionl)
// Resaltar
filas aqu,
})
li3III
1.3
.: -"".," ....'.,x\:
:.:1):. .. ;
Jun 4
Recuerde que a diferencia de los ndices JavaScript, la pseudo-clase : nth- child (n}
basada en CSSempieza a numerar en 1, no en o.
"John Reslg
Mar7
Rlchard Wonh
conrerenoe
Feb B
John Reslg
release
Jan 23
Paul Bakaus
Dee6
Cuando el usuario hace clie en una celda en la tercera columna, qltr~mos que el texto
de la celda se compare con el de la celda de la misma columna en cualquier otra fila, Si
coincide, la clase highl ight se alternar. Es decir, la clase se aadir si no est ya ah, y
se eliminar si lo est. De esta forma, podemos hacer clic en una celda de autor para eliminar el resaltado de la fila si ya se ha hecho clic en esa celda o una con el mismo autor.
"plu~ln
Nov2
Ihiril,party
Sep 17
ennouncement
Sep 10
John Reslg
release
Sep 6
John Reslg
conference
Aug24
Jchn Resig
release
Figura
l'
$Idocument)
.readyIfunction1)
(
var $authorCells
= $ l' t ab l.e.striped
t d .nth-child
$authorCells.clicklfunctionl)
(
var authorName
= $Ithis) ,textl);
$authorCells,eachlfunctionlindex)
(
if lauthorName
== $ (t.h.s l. text ()) (
$Ithis)
,parentl)
(3) ') ;
"l
,toggleClassl'highlight');
del usuario
;~
Otra mejora visual que podemos aplicar a nuestra tabla de artculos de noticias es resaltar la fila basndose en la interaccin del usuario, Aqu responderemos a hacer clic en
el nombre de un autor al resaltar todas las filas que tienen el mismo nombre en su celda
Author. Podemos modificar la apariencia de 'estas filas resaltadas al aadir una ,clase:
I :i
.
~ :1
~1
})
})
#content
tr.highlight
background,
#ff6;
Es importante que asignemos a esta nueva clase highl ight especificidad adecuada,
de modo que el color de fondo anular el de las clases even y odd.
Ahora necesitamos seleccionar la celda apropiada y anexarle comportamiento utilizando el mtodo. click ():
$Idocument)
var
.readylfunctionl)
$authorCells
$I'table.striped
})
t-
El cdigo funciona bien en este punto, excepto cuando un usuario hace clie en dos
nombres de autor en sucesin. En lugar de cambiar las filas resaltadas de un autor al siguiente como podramos esperar, acabamos con la clase highlight
en ambos grupos
de filas. Para evitar este comportamiento, podemos aadir una sentencia else al cdigo, eliminado la clase highlight
para cualquier fila que no tiene el mismo nombre de
autor que en el que se ha hecho clie:
$Idocument)
.readylfunctionl)
(
var $authorCells
= $I'table.striped
td,nth-child(3)
$authorCells.clicklfunctionl)
(
var authorName
= $Ithis) ,textl);
$authorCells.eachlfunctionlindex)
(
if (aut.horNarne == s Lth i.s) .textl))
(
$Ithis)
td,nth-child(3)
.parentl)
');
.toggleclassl'highlight');
');
:'. irr
u11'"
iIilL.:J!"J':;
-, I
mi
7. Manipulacin
de labia
else {
$(this).parent().removeClass('highlight');
}
if
})
(authorName
== $(this) .text(
(
$(this) .parent() .toggleClass('highlight');
}I ;
})
BiD
~lse (
$(this) .parent()
.remqveClass('highlight'l;
Ahora cuando hacemos clic en Rey 8ango, por ejemplo, podemos ver todos sus artculos mucho ms fcilmente, como aparece en la figura 7.23.
Headllne
.~11'I1Ua
IJ!FlI
11;
18<
!le1l28
'-:-:f:::\~ReyBlngo
conference
})
})
})
$tooltip
$(!<div
id=UtooltiplI></div>t)
.append'ro t ibody
t )
Existen tres operaciones bsicas que tendremos que llevar a cabo de forma repetida
en nuestra descripcin emergente:
Nov2
ReyBango
,,..--.~'t,
1hIrd-party
tivo, .
Si luego hacemos clic en John Resig en cualquiera de las celdas, se eliminar el resaltado de las filas de Rey Bango y se aadir a las de [ohn.
Descripciones emergentes
Aunque el resaltado de una fila podra ser una caracterstica de utilidad, hasta el
momento no es aparente para el usuario que la caracterstica exista. Podemos empezar
a remediar esta situacin al asignar a todas las celdas de autor una clase c1ickab1e,
a las que hemos aplicado estilo para cambiar el cursor del ratn a un puntero cuando
est dentro de la celda:
$ (documentl .ready(function()
{
var $authorCells
= $('table.striped
td:nth-child(3)
$authorCells
.addClass('clickable')
.click(function()
(
var authorName
= $(this) .text();
$authorCells.each(function(index)
');
positionTooltip
= function (event)
var tPosX = event.pageX
var tPosY = event.pageY + 20;
$tooltip.css({top:
tPosY, left: tposX});
};
Aqu utilizamos las propiedades pageX y pageY del objeto event para establecer las
posiciones top y 1eft de la descripcin emergente. Cuando se invoca esta funcin en
respuesta a un evento de ratn, como mousemove, event .pageX y event. pageY nos
dar las coordenadas del cursor del ratn, por lo que tPosX y tPosY harn referencia
a una ubicacin de pantalla 20 pxeles por debajo del cursor del ratn.
BiIiI
7. Manipulacin
de tabla
showTooltip
= function(event)
(
var authorName
= $(this) .text();
$tooltip
.text('Highlight
all articles
by
.show() ;
positionTooltip(event)
;
.addClass('clickable')
.hover~showTooltip,
hideTooltip)
.mousemove(positionTooltip)
.click{function(event)
(
var authorName
= $(this) .t~t();
$authorCells.each(function(index)
{
if (authorName
== $(this) .text(
(
$(this) .parent() .toggleClass('highlight');
, + authorName)
};
lIiiI
el se (
$(this) .parent() .removeClass('highlight');
}
})
})
Observe que los argumentos para los mtodos . hover () y . mousemove () estn
haciendo referencia a funciones que estn definidas en alguna otra parte. Como tal, ornitimos los parntesis que seguiran a llamadas a las funciones. La descripcin emergente
ahora aparece cuando pasamos por encima de una celda autor, como muestra la figura
7.24, se mueve con el movimiento del ratn y desaparece cuando movemos el cursar
del ratn fuera de la celda.
():
hideTooltip
= function()
$tooltip.hide()
;
Figura
};
$ (document) .ready(function()
{
var $authorCells
= $('table.striped
td:nthchild(3)
');
var $tooltip
= $('<div id="tooltip"></div>')
.appendTo('body');
J\Jn 4
var positionTooltip
= function(event)
var tPosX = event.pageX
var tPosY = event.pageY + 20;
$tooltip.css({top:
tPosY, left: tPOSX});
Fab8
Wort(M1d.(~ntMarch
Figura
};
var
~~rt.. jQlerrYI
showTooltip
= function(event)
(
var authorName
= $(this) .text();
$tooltip
.text('Highlight
all articles
by
.show () ;
positionTooltip(event)
;
};
var hideTooltip
= function()
$tooltip.hide()
;
};
$authorCells
, + authorName)
Jo~ Reslg
14.1~.,
800 UI Alpha
reIease
Rl~J'ftia~~~
'''~IHlghlight.
a.rticlu
by John Resig
Johi~eleiSStI'-_.J
lElI
7. Manipulacin
}
$tooltip
.text(action
.show() ;
de tabla
all articles
by
authorName)
Ahora la descripcin emergente ofrece una sugerencia ms inteligente cuando el puntero pasa por 'encima de una fila que ya est resaltada, como se ve en la figura 7.26.
28
Esto elige de forma correcta el texto de la descripcin emergente cuando el ratn entra
en una celda, pero tambin necesitamos volver a calcular la etiqueta en el momento en
que se hace clic en el ratn. Para ello, necesitamos invocar la funcin showTooltip ()
dentro del manejador de evento click:
$ (document) .ready(function()
{
var $authorCells
= $('table.striped
td:nth-child(3)
');
var $tooltip
= $('<div id=lItooltip"></div>')
.appendTo('body');
var positionTooltip
= function(event)
(
var tPosX = event.pageX;
var tPosY = event.pageY + 20;
$tooltip.css({top:
tPosY, left: tPOSX});
};
var
showTooltip
= function(event)
(
var authorName
= $(this) .text();
var action.=
'Highlight';
if ($(this) .parent() .is(' .highlight'))
action = 'Unhighlight' i
}
$tooltip
,text(action + ' all articles
.show () ;
positionTooltip(event)
;
};
var
by , + authorName)
hideTooltip
= function()
$tooltip. hide () ;
};
$authorCells
.addClass('clickable')
.hover(showTooltip,
hideTooltip)
.mousemove(positionTooltip)
.click(function(event)
(
var authorName
= $(this) .text();
$authorCells.each(function(index)
{
if (authorName
== $(this) .text()) (
$(this) .parent() .toggleClass('highlight');
}
el se (
$(this) .parent()
Aug31
jQuery
Ml~;;""3~!',l!~
Contera""" 2008 Agenda
~;~n~W;.~;
.~~~)5, R~l.k .!l.i!';c:ip,'!Q for)d~~,9'J'hf~'~~
j~114' ''J.ri~~~.y,
i5,'2
''''~7':\i>~:'_
;~'.
~:r
Ju'n 26,
jCiuery UI1.5, 1
Contraer
expandir secciones
Cuando un amplio conjunto de datos se divide en secciones, puede resultar de utilidad ocultar informacin en la que no estamos interesados en el momento. En nuestra
tabla de artculos de noticias, las filas se agrupan por ao contraer, u ocultar, un ao
de artculos puede ser una forma conveniente de obtener un visin global de todos los
datos de la tabla sin tener que desplazarse demasiado.
Para que se puedan contraer las secciones de la tabla de artculos de noticias, primero
necesitamos crear un elemento de pgina que se utilizar para activar el comportamiento. Una interfaz estndar para elementos que se pueden contraer es un signo menos, con
un correspondiente signo ms para elementos que se pueden ampliar. Insertaremos el
icono con JavaScript, siguiendo las tcnicas de mejora progresiva.
$ (document) .ready(function()
{
var collapselcon = r../images/bullet_toggle_minus.pngr
var collapseText = rCollapse this section'
var expandlcon
= '.. /images/bullet_toggle-plus.png';
var expandText = rExpand this section' i
$('table.collapsible
tbody') .each(function()
var $section
= $(this);
$('<img />') .attr('srcr
collapselcon)
.attr('alt',
collapseText)
.prependTo($section.find('th'))
;
}) ;
I
});
.removeClass('highlight');
}
}) ;
ahowTooltip.call(thia,
EiD
event);
}l;
}l;
lJIlI
7. Manipulacin
de tabla
t body
$ (document) .ready(function()
{
var collapselcon
= ' .. fimagesfbullet_toggle_minus.png';
var collapseText
= 'Collapse this section'
var expandlcon
= ' .. fimagesfbullet_toggle-plus.png';
var expandText
= tExpand this section'
$ ('table. collapsible
t body") .each (function ()
var $section
= $(this);
$('<img f,') .attr('src',
collapselcon)
.attr('alt',
collapseText)
.prependTo($section.find('th'))
.addClass('clickable')
.click(function()
{
if ($section.is(' .collapsed'))
$section.removeClass('col1apsed')
.find('tr:not(:has(th))
') .fadeln('fast');
$(this) .attr('src',
collapselcon)
.attr('alt',
collapseText);
}
else {
$section.addClass('collapsed')
.find('tr:not(:has(th))
') .fadeOut('fast');
$(this) .attr('src',
expandlcon)
.attr('alt',
expandText);
})
})
Los artculos del 2007 no se han eliminado; simplemente se han ocultado hasta que
hacemos clic en el icono para expandir el apartado que ahora aparece en esa fila.
Las filas de tabla presentan ciertos obstculos a la animacin, ya que los navegadores
utilizan valores diferentes (t ab 1e - row y block) para su propiedad di sp 1ay visible,
Los mtodos . hide () y . show (), sin animacin, se pueden utilizar siempre con
filas de tabla. Si se desea animacin, . fadeln () y . fadeOut () se pueden utilizan
tambin .
Filtrado
Anteriormente hemos examinado ordenar y paginar como tcnicas para ayudar a los
usuarios a centrarse en partes relevantes de los datos de una tabla. Vemos que ambos
se pueden implementar con tecnologa del lado del servidor, o con JavaScript. El filtrado completa este arsenal de estrategias de organizacin de datos. Al mostrar al usuario
solamente las filas de tabla que coinciden con un criterio dado, podemos eliminar distracciones innecesarias.
Ya hemos visto cmo realizar un tipo de filtro: resaltar un conjunto de filas. Ahora
ampliaremos esta idea para ocultar filas que no coinciden con el filtro.
Podemos empezar creando un lugar donde situar nuestros vnculos de filtrado. En una
estrategia tpica de mejora progresiva, insertamos estos controles utilizando JavaScript
de modo que las personas sin programacin disponible no ven las opciones:
$ (document) .ready(function()
{
$('table.filterable')
.each(function()
var $table = $(this);
$table.find('th')
.each(function(column)
if ($ (this) .is (' .filter-column'))
{
var $filters
= $('cdiv
class="filters"></div>');
$ ('<h3,<fh3,')
3. Alternar el estado actual del icono, cambiando sus atributos src y al t para que
refleje la accin que se activar ahora cuando se hace clie.
.text('Filter
by , + $(this) .text()
.appendTo($filters)
;
$filters. insertBefore
($table) ;
Con este cdigo en su lugar, hacer clic en el icono para contraer este apartado junto
a 2007 hace que la tabla se parezca a la figura 7.27.
})
})
})
Figura
BII
+ ': ')
lIfI
7. Manipulacin
de tabla
lID
Hoadllno
Headllne
Figura
Fllter
by Top.lc:
release
Opciones de filtro
Ahora podemos pasar a implementar un filtro. Para empezar, aadiremos filtros
para un par de temas conocidos. El cdigo para esto es bastante similar al ejemplo de
resaltar autor anterior:
Figura 7.29.
$ (document) .ready(function()
(
$('table.filterable')
.each(function()
var $table = $(this);
Ahora necesitamos ampliar las opciones de filtro para abordar el rango de temas
disponibles en la tabla. En lugar de incorporar en el cdigo todos los temas, podemos
recopilarlos del texto que se ha incorporado en la tabla. Podemos cambiar la definicin
de keywords para que sea:
var keywords
= ['conference',
'release'] i
$.each(keywords,
function(index,
keyword)
{
$('<div class=tlfilter"></div>')
,text(keyword)
.bind('click',
{key: keyword},
function(event)
(
$('tr:not(:has(th))',
$table) .each(function()
{
var value = $('td', this) .eq(column) .text();
if (value == event.data['key'])
{
$ (thi s) .show () ;
}
;
$(this) .addClass('active')
.siblings() .removeClass(lactive');
}) .addClass('clickable')
.appendTo($filters)
keywords[$(this)
+ (column
.text()]
+ 1) + ') ')
$(this) .text();
});
else (
$ (this) .hide () ;
})
var keywords
= {};
$table.find('td:nth-child('
.each(function()
(
});
$filters.insertBefore($table);
}
})
}l;
})
Empezando con una tabla esttica de palabras clave por las que filtrar, pasamos en
bucle por ellas y creamos un vnculo de filtrado para cada una. Como con en el ejemplo
de paginado, necesitamos utilizar el parmetro data de . bind () para evitar problemas
mi
l'
,,
7. Manipulacin de tabla
$('<div class=lIfilter">all</div>')
.click(function()
$table.find('tbody
tr') .show();
$(this) .addClass('active')
.siblings() .removeClass('active');
}) .addClass('clickable
active') .appendTo($filters);
lID
Filler by Tople:
oonference
announoement
reieeee
plug-ln
standanls
documenlalion
MOIIal
mlscellaneous
souroe
Esto nos proporciona un vnculo ali que simplemente muestra todas las filas de la
tabla, como se ve en la figura 7.31. Este nuevo vnculo se marca como act i ve para em-.
pezar.
$ (document) .ready(function()
(
$('table.striped')
.bind('stripe',
function()
$('tbody',
this) .each(function()
(
$(this) .find('tr:visible:not(:has(th
.removeClass('odd')
.addClass('even')
.filter(function(index)
{
return
(index % 6) < 3;
}) .removeClass('even')
.addClass('odd');
{
')
}) .trigger('stripe');
}),
Headllne
Filler by Tople:
thlrd-party
oonference
announoement
nlleasa
plug~n
standards
documentstl,on
tutotial
Headllne
ea
Filler by Tople:
11; 2008
all
mlscenaneous
thlrd-party
source
conference
announcement
M
',Jn~4
&:;:;::.:;:~_>
~~il
F~8
pI~n
,l
~.~
standards.
documentaBon
Morlal
mlscellaneous
Hemos aprendido con nuestro cdigo de ordenar y paginar que no podemos tratar
las diferentes caractersticas que escribimos como islas. Los comportamientos que creamos pueden interactuar en formas algunas veces sorprendentes; por esta razn, merece
la pena volver a visitar nuestros esfuerzos anteriores para examinar cmo coexisten con
las nuevas posibilidades de filtrado que hemos aadido.
sourca
EDil
7. Manipulacin
~-
de tabla
r.
Expandir y contraer
var
showTooltip
= function(event)
{
var aut'horName = $ (this) .text () ,
var ac~ion = 'Highlight' i
if ($ (this).parent () .is (, .hi9lVight'
action = lUnhighlight';
}
$tooltip
.text(action + ' all articles
.show() ,
positionTooltip(event)
,
$authorCells
.addClass('clickable')
.hover(showTooltip,
hideTooltip)
.mousemove(positionTooltip)
.click(function(event)
(
var authorName
= $(this) .text(),
$authorCells.each(function(index)
{
if (authorName
== $(this) .text(
(
$(this) .parent() .toggleclass('highlight'),
}
(
showTooltip.call(this,
$ (document) .ready(function()
(
$('table.striped')
.bind('stripe',
function()
{
$('tbody',
this) .each(function()
(
$(this) .find('tr:visible:not(:has(th
')
.removeClass(rodd')
.addClass('even')
.filter(function(index)
{
return
(index % 6) < 3,
}) .removeClass ('even' l addClass ('odd' ) ,
j),
}) .trigger('stripe'),
$ (document) .ready(function()
{
var $authorCells
= $('table.striped
td:nth-child(3)
'),
var $tooltip
= $('<div id="tooltip"></div>')
.appendTo('body'),
var positionTooltip
= function(event)
var tPosX = event.pageX
event
$tooltip.css({top:
,pageY
tPosY,
.removeClass('highlight'),
}
}),
Nuestra segundo ejemplo ha demostrado alternar color de fila, resaltar, descripciones emergentes, contraer/expandir, y filtrado. Tomadas juntas, el cdigo JavaScript
para esta pgina es:
tPosY,
authorName)
hideTooltip
= function()
$tooltip.hide()
,
El cdigo terminado
var
};
$(this) .parent()
},
var
else
})
by
20
left:
tPosX}),
event),
}),
}),
$ (document)
.ready(function()
var collapselcon
= '../images/bullet_toggle_minus.png',
var collapseText = 'Collapse this section' i
var expandlcon
= '../images/bullet_toggle-plus.png',
var expandText = 'Expand this section'
$('table.collapsible
tbody') .each(function()
var $section
= $(this),
$('<img />') .attr('src',
collapselcon)
.attr('alt',
collapseText)
.prependTo($section.find('th'
.addClass('clickable')
.click(function()
{
if ($section.is('
.collapsed'
(
$section.removeClass('collapsed')
.find('tr:not(:has(th
:not(.filtered)
.fadeln('fast')
,
$(this) .attr('src',
collapselcon)
.attr('alt',
collapseText),
el se (
$section.addClass('collapsed')
.find('tr:not(:has(th
')
')
BfI
mi
7. Manipulacin
de tabla
.fadeOut('fast',
function()
(
$(this).css('display',
"norie
}) ;
L,
}
})
})
})
.trigger('stripe');
$ (document) .ready(function()
(
$('table.filterable')
.each(function()
var $table = $(this);
$table.find('th')
.each(function(column)
if ($(this).is('.filter-column'))
var $filters
$ (, <h3></h3>')
$('cdiv
class="filterslI></div>')
}) .addClass('clickable
var keywords
active')
.appendTo($filters);
{};
$table.find('td:nth-child('
.each(function()
(
keywords
(column
1) + ') ')
});
$.each(keywords,
function(index,
$('cdiv
class="filterrr></div>')
keyword)
{
.text(keyword)
.bind('click',
{key: keyword},
function(event)
(
$('tr:not(:has(th))',
$table) .each(function()
{
var value = $('td', this) .eq(column) .text();
if (value == event.data['key'l)
(
$(this) .removeClass('filtered');
}
else (
$(this)
.addClass('filtered');
$(this) .addClass('active')
.siblings() .removeClass{'active') i
$table.trigger(/stripe')
;
}) .addClass ('clickable')
.appendTo ($filters)
}) ;
$filters.insertBefore($table)
}
})
})
})
lJJlI
Resumen
$(this) .attr('src',
expandlcon)
.attr('alt', expandText);
$section.parent()
..
8
Formularios
con funciones
-
"
.'\
Casi todo sitio Web que requiera informacin por parte del usuario emplear un
formulario en una forma u otra. A lo largo de la vida de Internet, los formularios han
desempeado el rol de mula de carga, llevando informacin desde el usuario final de
vuelta al editor del sitio Web, de forma fiable, pero con muy poca gracia o estilo. Quiz
esta ausencia de estilo ha sido causada por el repetido y arduo viaje al servidor y vuelta; o quiz tena que ver con los elementos inflexibles con los que el formulario tena
que trabajar y su falta de deseo de seguir la ltima moda. Cualquiera que sea la razn,
no ha sido hasta recientemente, con el resurgimiento de la programacin del lado del
cliente, que los formularios han encontrado nuevo vigor, propsito y estilo. En este captulo, examinaremos formas en las que podemos infundir nueva vida a los formularios.
Mejoraremos su estilo, crearemos rutinas de validacin, los utilizaremos para clculos,
y enviaremos sus resultados al servidor mientras nadie mira.
ED
mi
c::/li>
algo adicional a la mayora de ellos. Para demostrar mejora progresiva con respecto a
formularios, crearemos un formulario de contacto que podemos mejorar tanto en apariencia como comportamiento utilizando jQuery.
c::li>
<label for=1I1ast-namell>Last
Namec::/label>
< in~ut
clase=," required
type= text" name= IIlast
.
~d="la9t-namel~ ..,/>
<span> (required) c::/span>
ti
ti
-name 11
</li>
c::li>How would
you
like
to be contacted?
Laal Neme
I(requlnld)
19 by Phcne
9byFex
I
I
I(requlnld
_J (requlnld
for=l1by-emaill1>
<input type=l1checkbox"
name=l1by-contact-typell
value=I1E-maill1
id=l1by-emaill1 />
by E-Mail
</label>
j(raqulnld)
<input
class=l1conditional"
type=lItext"
name=lIemail"
id=l1email"
/>
<span>(required
when corresponding
checkbox
9 by E.Mell
,.'
<ul>
<li>
<label
checkedl</span>
</lb
checkboX checkea)
<li>
<label
for=lIby-phonell>
<input
<legend>personal
Info</legend>
<01>
<li>
c::label for="first-nametl>First
Namec::/label>
<input c Las s e vr'equd r'ed" type=lItext"
name="first-name
11
id=lIfirst-name"
/>
type="checkbox"
name="by-contact-type"
/>
class="conditional"
type="text
id="phone" />
<span> (required when corresponding
checkedl</span>
</lb
lt
name=lIphone"
checkbox
<-li>
<label
for="by-fax">
<input
type="checkboxlI
name=lIby-contact-type"
value=IIFax"
id="by-fax"
/>
by Fax
</label>
<input
class="conditional"
type=lItext"
name="fax"
id=lIfaxlI />
<span>(required
when corresponding
checkbox
checkedl</span>
</li>
</ul>
</li>
</01>
</fieldset>
Una cosa a destacar aqu es que cada elemento de pares de elementos se considera
un elemento de lista (db).
Todos los elementos se sitan dentro de una lista ordenada 01, y las casillas de verificacin (junto con sus campos de texto) se sitan dentro de una lista sin ordenar anidada (eu l ), Adems, utilizamos el elemento Labe I.
para indicar el nombre de cada campo. Para los campos de texto, Labe L precede a
<input>; para casillas de verificacin, engloba <input>. Aunque no existe estructura
mil
de elemento "estndar" para elementos dentro de un conjunto de campos, la lista ordenada parece ser lo ms parecido a cualquier cosa que represente el significado semntico
de los elementos en un formulario de contacto.
Con nuestro HTML en su lugar, estamos listos para utilizar jQuery para la mejora
progresiva.
Un enfoque alternativo que mantiene los elementos <1eqerid intactos implica situar
sus contenidos en una etiqueta e span:
$ (document) :!ready(function () (
$('legend') .wraplnner(l<span></s~an>');
}) ;
Situar un <span> dentro de <legend> tiene al menos dos ventajas frente a reemplazar <Le qerid con un <h3 >: mantiene el significado semntico de <legend> para
lectores de pantalla con soporte ]avaScript y requiere menos trabajo en la parte del script.
La desventaja es que hace que el estilo del encabezado sea un poco ms difcil de lograr.
Al menos, tenemos que establecer la propiedad position
de <fieldset>
y e spans.,
as como el padding-top
del f e Lds et; y el width de <span>:
La leyenda
La leyenda del formulario es un elemento muy difcil de aplicar estilo con CSS.
Las inconsistencias de navegador y las limitaciones de posicionamiento hacen que trabajar con ello sea un ejercicio de frustracin. An as, si nos preocupa utilizar elementos de pgina significativos, y bien estructurados, la leyenda es una eleccin atractiva,
si no visualmente llamativa, para mostrar un ttulo en el <fieldset
> de nuestro formulario.
Solos con HTML y CSS, estamos obligados a comprometer la eleccin de cdigo semntico o diseo flexible. Sin embargo, podemos cambiar el HTML cuando se carga la
pgina, convirtiendo cada <Leqerid en un <h3> para las personas qllevisualizan la
pgina, aunque las mquinas que leen la pgina, y aquellos con ]avaScript disponible,
siguen viendo <legend>. Esto se puede realizar de forma sencilla utilizando el mtodo
. replacewi th () de jQuery:
$ (document) .ready(function()
(
$('legend')
.each(function(index)
$(this) .replaceWith('<h3>'
(
+ $(this)
.text()
fieldset
{
position: relative
padding-top:
1.5em;
legend span (
position: absolute
width:
100%;
'</h3>');
}l;
Observe aqu que no podemos basamos en la iteracin implcita de jQuery. Con cada
elemento que reemplazamos, necesitamos insertar los contenidos de texto nicos de ese
elemento. Para esto nos basamos en el mtodo. each ( ) , que nos permite dirigimos al
texto determinado con $ (thi s) .
Ahora, cuando aplicamos un fondo azul y color de texto blanco a <h3> en la hoja
de estilo, el primer conjunto de campos del formulario se parece lo'que muestra la figura 8.2.
Personal Info
FlmI Name [
Las! Name
(mqulred)
El by Phone
!!I by
Fax
:::J
::J
.__ ::J
$ (document) .ready(function()
{
var requiredFlag = ' * ';
var conditionalFlag
=
**
I(mqulred)
El by E-MaIl
OOeeked)
$ ( 'form
l.
:input' )
.filter('.required')
.next('span')
.text(requiredFlag)
.end ()
.filter('.conditional')
.next('span')
})
.text(conditionalFlag);
.end()
DI
Utilizar . end () nos permite ampliar la cadena de mtodos de modo que continuamos
trabajando con el mismo conjunto de elementos y mantenemos la creacin de objetos al
mnimo. Todo mtodo . end () devuelve la seleccin un paso hacia atrs, volviendo el
conjunto coincidente de elementos a lo que era antes del ltimo mtodo transversal Aqu
utilizamos dos en una fila: el primer . end () revierte el conjunto coincidente a . f i 1ter ( , . required'
) y el segundo lo revierte a $ ( , form : input' ) . De esta forma, cuando . fi1ter
( , . conditiona1'
) selecciona elementos con c l as s "condi tiona1",
se aplica a todas las entradas de datos dentro del formulario. Ahora, puesto que un solo
asterisco (*) puede no captar inmediatamente la atencin del usuario, tambin aadiremos c1ass=" req-1abe1"
a Labe l para cada campo obligatorio y aplicaremos
font -weight :bo1d a esa clase. Para ello, podemos ampliar an ms la cadena.
$ (document) .ready(function()
var requiredFlag = ' * ';
var conditlonalFlag
= ' .*
'i
requiredKey = requiredFlag +
requiredKey.replace(/'\(.+)\)$/,
'$1');
conditionalKey
= conditionalFlag
+
conditionalKey.replace(/'\((.+}\)$/,
'$1');
//
$ (document) .ready(function()
var requiredFlag =
* ,.
var conditionalFlag
mi
cdigo
contina
j);
$ ( 'form :input' )
.filter(' .required')
.next('span') .text(requiredFlag)
.end()
.prev('label').addClass('req-label').end()
.end ()
.filter(' .conditional')
.next('span') .text(conditionalFlag);
"
Una cadena tan larga de mtodos puede ser difcil de seguir, por lo que un salto de
lnea consistente y un patrn de sangrando es esencial. El conjunto de campos con el
texto modificado y la clase aadida ahora se parece a la figura 8.3.
Personal
Info
FI t Horno
c=------n-
_n-=.J
o
:::oJo
LatNlIML
1-
El byPhono
1-
El by Fax
1-
E!I
Figura
No del todo mal. Los mensajes de campo obligatorio y condicional no eran en realidad tan malos despus de todo; simplemente eran demasiado repetitivos. Tomemos la
primera instancia de cada mensaje y mostrmoslo por encima del formulario junto a la
indicacin que estamos utilizando para simbolizarlo.
Antes de completar los elementos < span que albergan los mensajes con sus indicaciones respectivas, necesitamos almacenar los mensajes iniciales en un par de variables.
Luego podemos quitar los parntesis al utilizar una expresin regular:
A \
A,
'context'.replace(/regular-expression/,
'replacement')
Las cadenas de contexto de nuestros dos mtodos. replace () son las variables requiredKey y condi tiona1Key. Ya hemos examinado la parte de expresin regular de
esto, contenida dentro de dos barras inclinadas. Una coma separa la expresin regular
y la cadena de sustitucin, que en nuestros dos casos es '$1 El marcador de posicin
$1 representa el primer grupo en la expresin regular. Nuevamente, puesto que nuestra expresin regular tiene un grupo de uno o ms caracteres, con un parntesis en cada
lado, la cadena de sustitucin estar todo dentro de, y no incluidos, los parntesis.
I
T_
,
mil
mi
Ahora que hemos recuperado los mensajes del campo sin los parntesis, podemos
insertarlos, junto con sus indicaciones correspondientes, por encima del formulario:
$ (document) .ready(function()
(
$ (,input: condi tional ') .next (,spa'l') .andSelf ().hide ();
})
$ (document) .ready(function()
(
var requiredFlag =
* ';
var conditionalFlag
= ' ** '
})
P.rsonallnfo
flrstNama
L.aI1Namo
r.=.:::
1-
1-
I!J by E-Mail
.'
[_n_
-- HJ"
J"
I!i! by Phone
lB by Fax
L__
==:::J"
Las cinco nuevas lneas le deberan ser relativamente familiares ahora. Aqu tiene lo
que hacen:
1. Crear un nuevo elemento de prrafo.
2. Asignar al prrafo una clase de field-keys.
3. Anexar requiredKey
al prrafo.
5. Insertar el prrafo y todo lo que hemos anexado dentro de l delante del formulario
de contacto.
Cuando se utiliza. append () con una cadena HTML, como hacemos aqu, tenemos
que tener cuidado que cualquier carcter HTML especial se escape adecuadamente. En
este caso, el mtodo . text () que hemos utilizado cuando declaramos las variables ha
hecho esto por nosotros. Cuando definimos algunos estilos para. field-keys
en la
hoja de estilo, el resultado se parece a lo que aparece en la figura 8.4.
Nuestro trabajo jQuery para el primer conjunto de campos est casi completo.
El conjunto de campos ahora tiene su interfaz modernizada, como muestra la siguiente figura:
- ------------_._----
Personal Info
fl .1
L.aI1
N.",. [-----------JN.",. I
1-
!!! by
8byPhone
8byFax
Para hacer que aparezcan los campos de entrada de texto y las indicaciones, anexamos el mtodo. click () a cada casilla de verificacin. Haremos esto dentro del contexto de cada entrada de texto condicional de modo que podamos establecer un par de
variables para reutilizacin:
$ (document) .ready(function()
(
$('input.conditional') .next('span') .andSelf() .hide()
.end() .end()
.each(function()
{
var $thisInput = $(this);
var $thisFlag = $thisInput.next('span');
$thisInput.prev('label').find(':checkbox')
&IiI
$thislnput.show()
;
$~hisFlag.show()
;
$(this) .parent('label')
.click(function()
{
// cdigo contina
}) ;
})
})
.,
Aqu nuevamente hacemos uso de dos mtodos . end ( ) , esta vez de modo que podamos anexar el mtodo. each () al selector $ ( , input. condi tional ' ) original.
Ahora tenemos una variable para la entrada de texto actual y el indicador actual.
Cuando el usuario hace clic en la casilla de verificacin, vemos si est seleccionada;
si es as, mostramos la entrada de texto, mostramos la indicacin, y aadimos la clase
req-label
al elemento Labe L padre:
$ (document) .ready(function()
(
$('input.conditional')
.next('span')
.andSelf() .hide()
.end () .end ()
.each(function()
(
var $thislnput
= $(this);
var $thisFlag
= $thislnput.next('span');
$thislnput. prev ('label ') .find (, .checkbox ')
.click(function()
{
if (thia.checked)
{
$thislnput.ahow();
$thisFlag.show();
$(this) .parent('label')
.addClass('req-labe1');
"
Para comprobar si hay una casilla seleccionada aqu, se prefiere thi s . checked porque tenemos acceso directo al nodo DOM va la palabra clave this. Cuando el nodo
DOM no est accesible, podemos utilizar $ ( , selector'
) . is ( , : checked ") en su
lugar, ya que. is () devuelve un booleano (true o false).
Nos quedan por hacer dos cosas:
1. Aseguramos de que las casillas de verificacin no estn seleccionadas cuando la
pgina se carga inicialmente, ya que algunos navegadores mantendrn el estado
de elementos de formulario al refrescarse la pgina.
2. Aadir una condicin else que oculta los elementos condicionales y elimina la
clase req-label
cuando la casilla de verificacin no est seleccionada.
$ (document) .ready(function()
(
$ ('input.conditiona1')
.next('span')
.andSelf() .hide()
.end() .end()
.each(function()
(
var $thislnput
= $(this);
var $thisF1ag
= $thislnput.next('span');
$thislnput. prev (,label' ) .find (,,checkbox' )
.attr('checked',
falae)
.click(function()
{
if (this.checked)
(
})
})
y esto concluye la parte de estilo de esta transformacin de formulario. A continuacin, aadiremos algo de validacin del lado del cliente.
- Validacin de formulario
})
})
.addClass('req-label');
e11'e {
$thislnput. hide () ; .
$thisFlag.hide();
$(this) .parent('labe1')
,removeClass('req-label');
&11
Campos obligatorios
Para nuestro formulario de contacto, comprobaremos la presencia de la clase required en cada entrada de datos cuando el usuario entra o sale de cada entrada de datos.
Antes de empezar con este cdigo, sin embargo, deberamos regresar a nuestros campos
de texto condicionales. Para simplificar nuestra rutina de validacin, podemos aadir la
clase required
al <input> cuando se muestra, y eliminar la clase cuando el <input>
posteriormente se oculta. Esta parte del cdigo ahora se parece a esto:
$thislnput.prev('label')
.find(' ,checkbox')
.attr('checked',
false)
.click(function()
{
if (this.checked)
{
&!I
$thislnput.show()
.addClass('required');
$thisFlag.show()
,
$(this) .parent('label')
.addClass('req-label'),
else (
$thislnput.hide()
.removaClass('required');
$thisFlag.hidel)
,
$(this) .parentl'label')
.removeClassl'req-label'),
&El
$('<span></span>')
.addClass('error-message')
.text(errorMessage}
r . appendTo($listltem)
;
$listltem.addClass('war~ng')'
}
})
j),
})
Con las clases required en su lugar, estamos listos para responder cuando el usuario deja uno de estos campos vacos. Se situar un mensaje detrs del indicador obligatorio, y el elemento <1i > del campo recibir estilos para alertar al usuario por medio
de class="warning":
Nuestro cdigo funciona bien la primera vez que el usuario deja un campo en blanco;
.' sin embargo, dos problemas con el cdigo son evidentes cuando el usuario entra y deja
( ms tarde el campo, como se muestra en la figura 8.6.
Personallnfo
$ (document) .ready(function()
{
$('form
:input') .blur(function()
(
if ($(this) .hasClass('required'
(
var $listltem
= $(this) .parents('li:first'),
if Ithis. value == ,,) (
var errorMessage = 'This is a required
$ l'<span></span>')
.addClass('error-message')
.textlerrorMessage)
.appendTo($listltem)
,
$listltem.addClass('warning')
;
Flrst Nama
Lost Nom.
---J .
Mar"
I
Tum.,
J-I
field'
"
b)'E U
=::J -
I!!! byPhcna
I!!! by Fax
Figura 8.6. Dejar un campo en blanco.
}
j),
}) ;
El cdigo tiene dos sentencias if para cada entrada de formulario en bl ur: la primera comprueba la clase required, y la segunda comprueba la presencia de una cadena
vaca. Si ambas condiciones se cumplen, construimos un mensaje de error, lo situamos
en c s'pari c Las s "error-message"
, y lo anexamos al <li> padre.
Queremos proporcionar un mensaje algo diferente si el campQ es uno de los campos de texto condicionales only required when its corresponding checkbox is checked
(slo obligatorio cuando su casilla de verificacin correspondiente est seleccionada).
Concatenaremos un mensaje modificador al mensaje de error estndar. Para hacer esto,
podemos anidar una sentencia i f ms que comprueba la clase condi t ional solamente
despus de que se hayan cumplido las dos primeras condiciones if:
$Idocument) .ready(function()
{
$('form
:input') .blur(function()
(
if ($(this) .hasClass('required'
(
var $listltem
= $(this) .parentsl'li:first');
if
(this.value
== ") (
var errorMessage = 'This is a required field'
if ($(this) .hasClass('conditional'
{
errorMessage += " when its related
+
'checkbox ia checked';
I
$ (document)
$('form
.ready(function()
{
:input') .blur(function()
$(this).parents('li:first').removaClass('warning')
.find('span.error-message'}.remove()
if ($(this) .hasClass('required'
(
var $listltem
= $(this) .parents('li:first');
if (this.value
== ") {
var errorMessage = 'This is a required
if ($ Ithis) .hasClass ( 'conditional '
(
errorMessage += " when its related
i s checked' j
$ ('<span></span>')
.addClass('error-message')
.text(errorMessage)
field'
checkbox
mi
.appendTo($listltem)
;
$listItem.addClass(
'warning');
j);
Por ltimo, tenemos un script de validacin en funcionamiento para campos obligatorios y condicionalmente obligatorios. Incluso despus de incorporar y salir de campos
obligatorios repetidamente, nuestros mensajes de error ahora se muestran de forma correcta, como se ve en la figura 8.7.
$ (document) .ready(function()
{
// ...
cdigo contina
..
if (this.id == 'email')
{
var $listltem
= $(this) .parents('li:first');
if ($(this).is(':hidden'))
{
this.value =
}
if (this.value 1= II &&
11;
Personal Inlo
Flrat Nama
[MMk
lID
!/.+@.+\.[a-zA-Z){2.4}$/.test(this.value))
{
var errorMessage = 'Please use proper e-mail
+
(e.g. joe@example.com) Ii
$(I<span></span>l)
.addClass('error-message')
.text(errorMessage)
.appendTo($listltem);
$listltem.addClass('warning')
;
'--~.
format'
1"
. byE 11
c--__~-=---~
~
. byPhono
1~
I!!l by Fax
//
})
cdigo
contina
. . .
(this.checked)
{
$thislnput.show()
.addClass('required');
$thisFlag.show()
;
$ (this) .parent('label')
.addClass('req-label');
el se {
$thislnput.hide()
.removeClass('required').blur();
$thisFlag.hide()
;
$(this) .parent('label')
.removeClass('req-label');
Ahora cuando una casilla de verificacin no est seleccionada, los estilos de aviso
relacionados, y los mensajes de error estn fuera de la vista y de la mente.
Inserta el mensaje en
Formatos obligatorios
Existe un tipo ms de validacin a implementar en nuestro formulario de contacto:
formatos de entrada de datos correctos. Algunas veces puede ser de utilidad proporcionar un aviso si el texto se incorpora en un campo de forma incorrecta (en lugar de
simplemente dejado en blanco). Los principales candidatos para este tipo de aviso son
spar;
c La s s e "error-message"
>.
>y suscontenidos
EIiI
})
$ (document) .ready(function()
(
$('form') .submit(function()
(
$('#submit-message') ,remove();
$(' :input.required')
.trigger('blur');
var nmwarnings :1:1 $ (1 .warning,~, this)
if (numWarnings)
{
$ ('<div></div>')
.attr({
lid':
'submit-message',
'clasa':
.warning ,
Observe ahora que hemos colado una lnea para eliminar un elemento que todava
no existe: <di v id=" submi t -message" >. Aadiremos este elemento en el siguiente
paso, Simplemente estamos eliminndolo como medio de prevencin aqu porque ya
sabemos que necesitaremos hacerlo basndonos en los problemas que hemos encontrado al crear mltiples mensajes de error anteriormente en el captulo.
Despus de activar bl ur, recibimos el nmero total de clases warning en el formulario actual. Si no hay ninguna, crearemos un nuevo <di v id=" submi t -message" >
y lo insertaremos delante del botn Send donde es ms probable que lo vea el usuario.
Tambin impediremos que el formulario realmente se enve:
&iI
,length
})
.append('Please correct errara with
numWarnings +
fields')
.insertBefore('#send');
return falss
})
})
3 ~d.
[a-zA-Z] (2,4}$/.test(this.value)
Sin embargo, podemos hacer algo mejor que simplemente mostrar el nmero de errores, podemos listar los nombres de los campos que contienen errores:
$ (document) .ready(function()
(
$('form') .submit(function()
(
$('#submit-message')
.remove();
$(' :input.required')
.trigger('blur');
var numWarnings = $(1 .warning', this) .length
if (numWarnings)
{
var list = [l;
$('.warning
label').each(function()
list.push($(this).text());
}) ;
$ (' <div></div>
1)
.attr ((
'id': 'submit-message',
'class': 'warning'
.append('Please
};
}) ;
})
ltr-'r.',
&El
Elprimer cambio en el cdigo es la variable list establecida en una tabla vaca. Luego,
obtenemos cada etiqueta que es un descendiente de un elemento con la clase warning
y empujamos su texto en la tabla list (con la funcin nativa JavaScript push). Ahora,
el texto de cada una de estas etiquetas constituye un elemento aparte en la tabla listo
Modificamos nuestra primera versin del contenido <di v id=" submi t -message" >
un poco y le anexamos nuestra tabla listo Utilizando la funcin JavaScriptnativa j oin ()
para convertir la tabla en una cadena, unimos cada uno de los elementos de tabla con
un salto de lnea y un boliche, como se ve en la figura 8.9.
Ploase oonect """'"
-F1rs1Name
-wtName
&ni
especialmente si el usuario desea hacer clic en la mayora de ellas. Una opcin p"!raseleccionar, o deseleccionar, todas las casillas de verificacin es de utilidad en este tipo de
situacin. Po? lo tanto, creemos una.
Para empezar, creamos un nuevo.elemento <1i , lo completamos con un <1abe 1 ,
dentro del cual situamos <input t.ype "checkbox" id= "discover-all"
> y algo
de texto, y lo anexamos al elemento -e u L dentro de -e L class="discover"
>:
e
$ (document) .ready(function()
$ ('<1i></li>')
.html('<label><input
type="checkbox"
id="discover-allll
<em>check
all</em></label>')
.prependTo('li.discover
:> ul')
/>'
- by E-MaIl
})
I~
Figura 8.9. Unir los elementos de la labia con salto de lnea y boliche.
Ciertamente, el HTML para la lista de campos es de presentacin en lugar de semntico. Sin embargo, para una lista efmera, una que se genera por JavaScript como un ltimo paso y pensada para eliminarla lo ms pronto posible, perdonaremos este cdigo
rpido en aras de la sencillez y brevedad.
Ahora tenemos una nueva casilla de verificacin con una etiqueta que dice check
all (seleccionar todas). Pero todava no hace nada. Necesitamos anexarle el mtodo
. click
():
$ (document) .ready(function()
$ ('<1i></li>')
.htrnl('<label><input
type= checkbox" id=lIdiscover-all
<em>check
all</em></label>')
.prependTo('li.discover
:> ul');
$('#discover-all').click(function()
{
var $checkboxes
= $(this).parents('ul:first')
.find(':checkbox')
if (this.checked)
{
$checkboxea.attr('checked',
true};
el se {
$checkboxea.attr('checkedl,
11);
}
}) ;
}) ;
11
/>'
!!!I Magaztne
8w_
El Talevlslo"
ElMoYle
13 SchooI
!!!IMom
13 Blltboartl
13 Gramtl
El Detrttus
El HateMaIl
$ (document) .ready(function()
{
$ ('di></li>')
.htrnl('<label><input
type="checkbox
id="discover-all"
, <ern>check all</ern></label>')
.prependTo('li.discover
> ul');
$('#discover-a11')
.click(function()
(
var $checkboxes
= $(this) .parents('u1:first')
.find(' :checkbox');
lI
Para redondear nuestras mejoras en el formulario de contacto, ayudaremos al usuario a gestionar esta lista. Un grupo de la casillas de verificacin puede ser desalentador,
/>' +
mi
Jwr
8. Formularios con funciones
if
(this.checked)
{
$ (thia) .next O .text (' un-check
a11');
$checkboxes.attr('checked',
true) I
else (
$(thia) .next() .text(' check a11');
$checkboxes. attr ('checked',
") I
El cdigo terminado
Aqu est-el cdigo terminado para el formulario de contacto:
.,
$ (document) .ready(function()
(
// Mejorar estilo de elementos de formulario.
$('legend')
.each(function(index)
(
$(this) .replaceWith('<h3>'
+ $(this) .text()
l.
})
.parent('labe1')
.addClass('checka11');
+ '</h3>') I
}) I
}) I
El grupo de casillas de verificacin, junto con el cuadro check all, ahora se parece a
la figura 8.11.
Mlscellaneous
How dld you <IIscover us? (Check all !ha! apply)
o"
13 check
13 Magazine
"
I3webs1t8
8 Televlslon
S MovIe
El School
$ ('form :input' )
.filter(' .requiredr)
.next('span')
.text(requiredFlag)
.end()
.prev (' Labe l
addClass ('req-label') .end O
.end O
.filter(' ,conditional')
.next('span') .text(conditionalFlag);
SMom
B BUlboord
SGratIIII
13 Detritus
El HeteMall
Figura
// Alternar
casilla
de verificacin:
entradas
condicionales
un-check 0/1
I!f
Magazine
I!fW&b1llte
1f1l>levlslon
I!I Movle
$('input.conditional')
.next('span')
.andSelf() .hide()
.erid t ) .end()
.each(function()
(
var $thislnput
= $(this) I
var $thisFlag
= $thislnput.next('span')I
$thislnput.prev('label')
.find(' :checkbox')
.attr('checked',
false)
.click(function()
{
if (this.checked)
(
$thislnput.show()
.addClass('required')
I
$thisFlag.show()
I
$(this) .parent('label')
.addClass('req-label')
I
el se (
$thislnput.hide()
.removeClass('required')
.blur() I
$thisFlag.hide()
I
$ (this) .parent('label')
.removeClass('req-label')
I
I!f School
}),
Figura
}) I
de texto.
ea
BfI
// Validar
campos al perder foco.
$('form
:input') .blur(function()
(
$(this)
.parents('li:first')
.append('•
, + fieldList.join('<br
.ansertBefore('#send');
return false
.removeClass('warning')
.remove()
.find('span.error-message')
/>•
ea
'))
};
});
if
($(this) .hasClass('required'))
(
var $listltem
= $(this) .parents('li:first');
if (this. value == ")
{
var
if
errorMessage
'This
is
a required
// Casillas
$('form
checkbox
// Casillas
de verificacin
$ ('<li></li>')
is
(un)check
all.
/>'
.addClass('error-message')
.text(errorMessage)
.appendTo($listltem);
$listltem.addClass('warning')
(this.id == 'email')
(
var $listltem
= $(this) .parents('li:first');
if ($ (this) .is(' :hidden'))
{
this .val ue
$checkboxes.attr('checked',
.parent('label')
!=
errorMessage
+ ' (e.g.
1')
})
"
&&
!/ .+@.+\. [a-zA-Z] {2,4}$/ .test(this.value))
(this.value
};
var
con
.htrnl('<:label><input
type=ucheckbox"
id="discover-allu
<em>check
all</em></label>')
.prependTo('li.discover
> ul');
$('#discover-all')
.click(function()
{
var $checkboxes
= .$(this) .parents ('ul: first')
. find ( checkbox' ) ;
if (this.checked)
(
$(this) .next() .text(' un-check
all');
$checkboxes.attr('checked',
true) i
el se (
$(this) .next() .text(' check all');
('
$('<span></span>')
if
.removeAttr('checked')
field';
if
de verificacin
:checkbox')
})
"
'Please
use
proper
format'
joe@example.com)';
$('<span></span>')
.addClass(rerror-message')
.text(errorMessage)
.appendTo($listltem)
;
$listltem.addClass('warning')
.addClass('checkall');
Formularios compactos
}
}l;
// Validar
formulario
al enviar.
$('form') .submit(function()
(
$('#submit-message')
.remove() ;
$(' :input.required')
.trigger('blur');
var
numWarnings
if
$(' .warning',
this)
.length
(numWarnings)
(
var fieldList
=
[);
$(' .warning
label') .each(function()
fieldList.push($(this)
.text());
}l;
$('<div></div>')
.attr({
'id':
'submit-message',
'class':
'warning'
.append('Please
correct
numwarnings
errors
'
with
fields:<br
the following
/>')
, +
B!II
c:::form id=lIsearch
action=lIsearch/index.phpll
method=lIget >
c:::label for=lIsearch-text">search
the sitec:::/label>
<input type="text
name="search-text"
id=lIsearch-text
</form>
l1
ea
ll
ll
ll
II-!he .no
/>
Figura 8.15.
Sin estilo, vemos la etiqueta delante del campo, como se muestra en la figura 8.13.
8e.~h~.tte
Figura
Aunque esto no ocupa mucho espacio, en algunos diseos de sitio incluso esta lnea
de texto podra ser demasiado. Podramos ocultar el texto con CSS, pero luego esto no
proporciona al usuario forma de saber para qu es el campo. En su lugar, utilizaremos
CSS para posicionar la etiqueta sobre el campo, solamente si JavaScript est disponible,
al aadir una clase al formulario de bsqueda:
$ (docurnent) .ready(function()
var $search = $('#search')
)) ;
$ (docurnent) .ready(function()
(
var $search = $('#search') .addClass('overlabel');
var $searchlnput
= $search.find('input');
var $searchLabel
= $search.find('label');
$searchlnput
.focus(function()
(
$searchLabel.hide();
)l
.blur(function()
{
if (this.value
== ")
$searchLabel.show()
)
)) ;
(
.addClass('overlabel');
En una sola lnea estamos aadiendo una clase al formulario de bsqueda y almacenando el selector en una variable de modo que podemos hacerle referencia ms adelante.
La hoja de estilo utiliza la clase overlabel
para aplicar estilo a la etiqueta:
.overlabel
(
position: relative
)
.overlabel
label (
position: absolute
top: 6px;
left: 3px;
color: #999;
cursar: text
'1
))
(
;
La etiqueta ahora est oculta cuando el usuario escribe texto en el campo, como se
ve en la figura 8.16.
Ilt<..
Figura 8.16.
No solamente la clase aadida posiciona la etiqueta adecuadamente, sino que tambin deshabilita el texto para distinguirlo como un marcador de posicin, como muestra
la figura 8.14.
$searchlnput
.focus(function()
(
$searchLabel.hide();
))
II
Aplicarestilo a la etiqueta.
.blur(function()
{
if (this.value==
,,) (
$searchLabel.show()
))
$searchLabel.click(function()
$searchlnput.trigger('focuB');
}) ;
))
BliI
Necesitamos algn cdigo del lado del servidor para gestionar peticiones. Aunque
una implementacin del mundo real se basar normalmente en una base de datos para
/ producir una lista de terminaciones posibles, para este ejemplo podemos utilizar un
sencillo script PHP con los resultados incorporados:
<?php
if (strlen($_REQUESTC'search-text'])
print '[]';
exit
(
;
"
});
$searchLabel.click(function()
(
$searchlnput.trigger('focus')
;
})
})
En el servidor
if ($searchlnput.val())
$searchLabel.hide();
$searchlnput
.focus(function()
(
$searchLabel.hide() ;
})
.blur(function()
{
if (this.value == ")
$searchLabel.show()
}
eDI
I,
$possibilities = array();
foreach ($terms as $term) {
if (strpos($term, strtolower($_REQUEST['search-text']))
===
$possibilities
1) {
$terms = array(
access
action'
/1 Lista contina ...
'xarnl' ,
'xoops "
Una ventaja de utilizar la etiqueta en lugar de insertar un valor predeterminado directamente en la entrada de texto es que esta tcnica se puede adaptar a cualquier campo de
texto sin tener que preocuparse por un conflicto potencial con un script de validacin.
Autocompletar AJAX
<
O)
[] =
{
rr r
11.
str_replace
$possibilities).
(11
11 \
111,
$term)
'] ');
En el navegador
Ahora podemos realizar una peticin de este script PHP desde nuestro cdigo
JavaScript:
$ (document) .ready(function()
{
var $autocomplete = $('<ul class=lIautocompletetr></ul>')
.hide()
.insertAfter('#search-text');
$('#search-text')
$.ajax<{
.keyup (function ()
BllI
8. Formularios conJunciones
'url': '../search/autocomplete.php',
'data ': {' search-text':
$ (, #search-text r) . val () },
'dataType': 'json',
'type':
'GET',
'success': function(data)
if (data.1ength)
{
$autocomp1ete.empty(),
$.each(data,
function(index,
term) {
$('<li></li>')
.text(term) .appendTo($autocomp1ete)
}),
$autocomp1ete.show()
,
.
}) ,
})
-t
Id.1
de,ellct
deftnltlVe
d lgn .
d lgnlng
dOYOlopers
o.,
development
}),
$autocomplete.show()
'deep
deftnltlVe
d lgn
deslgnlng
developers
dOYOlopment
I~.m
$('#search-text')
eg
'off')
Esta modificacin establece el texto del cuadro de bsqueda en cualquiera que sea
el elemento de lista sobre el que se haya hecho clic. Tambin ocultamos las sugerencias
despus de esto.
DiI
if
(selectedltem
selectedltem
< O)
O;
(selectedltem
selectedltem
>= $autocomplete.find('li')
= $autocomplete.find('li')
.length)
(
.length - 1;
jde~eps
$autocomplete.find('li')
.removeClass('selected')
.eq(selectedltem)
.addClass('selected');
$autocomplete.show()
;
detlnl1lve
deslgn
developeno
development
La variable selectedItern
se establecer en null siempre que no haya un elemento seleccionado. Al invocar siempre setSelectedItern
() para cambiar el valor de la
variable, podemos estar seguros de que la lista de sugerencias solamente est visible
cuando existe un elemento seleccionado.
Las dos pruebas para el valor numrico de selectedItern
estn presentes para asegurar los resultados en el rango apropiado. Sin estas pruebas, selectedItern
terminara
con cualquier valor, incluso negativo. Esta funcin se asegura de que el valor actual de
selectedItern
siempre es un ndice vlido en la lista de sugerencias ..
Ahora podemos revisar nuestro cdigo existente para utilizar la nueva funcin:
$('#search-text')
.attr('autocomplete',
'off') .keyup(function()
$.ajax({
'url':
/search/autocomplete.php',
'data': ('search-text':
$ ('#search-text')
.val() l,
'dataType': 'json',
'type': 'GET',
'success': function(data)
if (data.length)
(
$autocomplete.empty()
;
$.each(data,
function(index,
term) (
$('<li></li>')
.text(term)
.appendTo($autocomplete)
.mouseover(function()
{
setSelectedltem(index);
..
})
.click(function()
(
$('#search-text')
.val(term);
$autocomplete.hide()
;
})
})
q'
'g
Ahora necesitamos permitir que las teclas del teclado cambien qu elemento est actualmente activo en la lista.
Gestionar
Podemos utilizar el atributo keyCode del objeto evento para determinar qu tecla se
ha pulsado. Esto nos permitir ver los cdigos 38 Y 4 O,correspondientes a las flechas
arriba y abajo, y reaccionar en consecuencia:
$('#search-text')
.attr('autocomplete',
'off') .keyup(function(event)
if (event.keyCode
> 40 I I event.keyCode
== 8) {
// Teclas con cdigos 40 e inferior
son especiales
// (lntro, teclas del cursor, escape, etc.).
// Cdigo de tecla 8 es retroceso.
$.ajax({
'url': r /search/autocomplete.php',
'data': ('search-text':
$('#search-text')
.val()},
'dataType':
'json',
'type':
'GET'
'success': function(data)
if (data.length)
(
$autocomplete.empty()
;
$.each(data,
function(index,
term) {
$ (,<1i></li>') .text (term)
.appendTo($autocomplete)
.mouseover(function()
(
setSelectedltem(index)
;
I
.click
setSelectedltem(O);
(function () (
$('#search-text')
.val(term);
$autocomplete.hide()
;
else (
setSelectedltem(null);
})
})
setSelectedltem(O);
});
})
doalgnlng
l;
mi
l
if
else (
setSelectedltem(null);
}
})
1m
mil
else if
(event.keyCode 38 &&
selectedltem 1== null) (
// Usuario pulsa la Flecha arriba.
setSelectedltem(selectedltem
- 1);
event.preventDefault()
Existe una ltima modificacin que haremos a nuestro comportamiento autocompletar. Deberamds ocultar la lista de sugerencias cuando el usuario decide hacer alguna
otra cosa en la pgina. En primer lugar, podemos reaccionar a la tecla Ese en nuestro
manejador keyup, y dejar que el usuario descarte la lista de esa forma:
}
(event.keyCode == 40 &&
selectedltem 1== null) (
// Usuario pulsa la Flecha abajo.
setSelectedltem(selectedltem
+ 1);
event.preventDefault();
else if
1==
null)
})
An ms importante, deberamos oculta! la lista cuando el campo de bsqueda pierde foco. El primer intento en esto es bastante sencillo:
'$('#search-text') .blur (function (event)
setSelectedltem(null);
})
Sin embargo, esto provoca un efecto secundario no deseado. Puesto que un clic de
ratn en la lista elimina foco del campo, este manejador se invoca y la lista se oculta.
Esto significa que nuestro manejador el i ck definido anteriormente nunca se invoca, y
resulta imposible interactuar con la lista utilizando el ratn.
Existe una solucin sencilla a este problema. El manejador bl ur siempre se invocar
antes del manejador el i ck. Una solucin alternativa es oculta! la lista cuando se pierde
el foco, pero esperar una fraccin de segundo primero:
$I'#search-text') .blur(function(event)
setTimeout(function()
(
setSelectedltem(null) ;
},
var populateSearchField
= function() (
$('#search-text') .vall$autocomplete
.findl'li') .eqlselectedltem) .text(;
setSelectedItem(null) ;
250);
}I;
};
Esto nos proporciona una oportunidad para que se active el evento click
mento de lista antes de que el elemento de lista se oculte.
Ahora nuestro manejador click puede ser una sencilla llamada a esta funcin.
Podemos invocar esta funcin cuando gestionamos la tecla Intro tambin:
Autocompletar
}
}) ;
Este manejador est anexado al evento keypress en lugar de keyup corno antes.
Tenemos que hacer esta alteracin de modo que podamos impedir que la pulsacin de
tecla enve el formulario. Si esperamos hasta que se activa el evento keyup, la presentacin estar ya en marcha.
frente a live
en el ele-
search
mi
En el extremo JavaScript, el cdigo para crear estas dos caractersticas es casi idntico, por lo que no entraremos en detalle aqu. Decidir cul utilizar es una cuestin de
equilibrio; live search proporciona ms informacin al usuario con menos esfuerzo, pero
tpicamente requiere ms recursos.
var populateSearchField
= function()
(
$('#sea!ch-text')
.val($autocomplete
.find('li') .eq(selectedltem)
.text());
setSel~ctedltem(null)
;
};
",
$ ('#search-text')
El cdigo terminado
$ (document) .ready(function()
(
var $search = $('#search') .addClass('overlabel');
var $searchlnput
= $search.find('input');
var $searchLabel
= $search.find('label');
($searchlnput.val())
$searchLabel.hide()
.'
$searchlnput
.focus(function()
(
$searchLabel.hide();
})
.blur(function()
(
if (this.value
== ")
$searchLabel.show()
r:
'
(
;
(
;
else
var
$autocomplete
$('<ul
selectedltem
(selectedltem
selectedltem
(selectedltem
selectedltem
>= $autocomplete.find('li')
= $autocomplete.find('li')
= null;
(event.keyCode
== 38 &&
selectedltem
!== null)
// Usuario ha pulsado Flecha arriba.
setSelectedltem(selectedltem
- 1);
event.preventDefault() i
else
setSelectedltem
= function(item)
selectedltem
= item;
if (selectedltem
=== null)
$autocomplete.hide()
;
return
if
fl
class=lIautocomplete ></ul>')
})
.insertAfter('#search-text')
var
setSelectedltem(null)
.hide ()
var
setSelectedltem(O);
$searchLabel.click(function()
$searchlnput.trigger('focus')
})
.val()},
}
})
/search/autocomplete.php',
'data', ('search-text',
$('#search-text')
r dataType ' : . r j son'
,
"t ype ", 'GET',
'success': function(data)
if (data.length)
(
$autocomplete.empty()
;
$.each(data,
function(index,
term)
$('<li></li>')
.text(term)
.appendTo($autocomplete)
.mouseover(function()
(
setSelectedltem(index)
;
}) .click(populateSearchField);
(event.keyCode
> 40 II event.keyCode
== 8) (
// Teclas con cdigos 40 e inferior
son especiales
// (Intro, teclas del cursor, Esc, etc.).
// Cdigo de tecla 8 es Retroceso.
$.ajax
if
Nuestro cdigo completo para la presentacin del campo de bsqueda y comportamientos autocompletar es de la siguiente forma:
if
'offl)
.attr(rautocomplete',
.keyup(function(event)
if
}
else
(event.keyCode
== 40 &&
selectedltem
!== null) (
// Usuario ha pulsado
Flecha abajo.
setSelectedltem(selectedltem
+ 1);
event.preventDefault()
;
< O)
o;
if
}
if
.length) (
.length - 1;
}
$autocomplete.find('li')
.removeClass('selected')
.eq(selectedltem)
.addClass('selected');
$autocomplete.show()
;
i.
else if (event.keyCode
== 27 && selectedltem
// Usuario ha pulsado
tecla Ese.
setSelectedltem(null)
;
!== null)
}
}) .keypress(function(event)
if
(event.keyCode
== 13 && selectedltem
!== null)
1m
t.mI
Intro.
}
}) .blur(function(event)
(
setTimeout (function () (
setSelectedltem(null) ;
},
})
250);
j);
</tr>
ctr plass="shipping">
<td class="itemtl>Shippingc/td>
<ftd class=lIquantity">S</td>
'ctd class="price">$2
pe r, Lt.ernc y t.d s
<td class="cost">$lO.OOc/td>
</tr>
<tr class="total">
<td class="item">Total</td>
<td class="quantity"></td>
ctd class="price"></td>
<td class="cost">$172.13</td>
</tr>
<tr class="actions">
<td></td>
ctd>
<input type="button"
value=IIRecalculate11
</td>
<td></td>
ctd>
name="recalculate"
id="recalculatell
cform action=Ucheckout.php"
ctable id=lIcart">
cthead>
ctr>
cth
cth
cth
cth
</tr>
</thead>
class=llitem11>Iteme/th>
class=lIquantityl1>Quantity</th>
class="price'I>Pricec/th>
class="cost >Totalc/th>
11
Building Telephony
</td>
<td class="quantityll>
<input
Systems
With Asterisk
type="text"
name="quantity-2"
id="quantity-2
maxlength="3"
class=l1subtotalll>
ctd class="itemll>Subtotalc/td>
ctd class="quantityll></td>
ctd class=llprice"></td>
ctd class="cost">$152.9Sc/td>
</tr>
ctr class=lItaxl1>
ctr
ctd
ctd
ctd
ctd
class=llitem1'>Taxc/td>
class=l1quantity"></td>
class="price">6%c/td>
class="cost">$9.18c/td>
value="l"
/>
</td>
<td class="price">$26.99c/td>
<td class="cost">$26.99</td>
</tr>
<tr>
<td class="item">
Smarty PHP Template
</td>
<td class=lIquantity">
cinput
ctfoot>
/>
<td class="item">
11
methoct="postll>
/>
Prograrnming
and Applications
type=tltext" name="quantity-l"
id=lIquantity-l"
maxlength="3"
value="2"
/>
</td>
<td class="price">$35.99</td>
<td class="cost">$71.98</td>
</tr>
<tr>
<td class="item">
Creating your MySQL Database
</td><td class="quantity">
<input
type="text"
name="quantity_3"
id="quantity-3"
maxlength="3"
value="1"
/>
mi
&lI
r"
p"
</td>
ctd
class="price">$17.99c/td>
ctd
class="cost">$17.99</td>
mi
Antes de pasar a manipular los campos de formulario, aplicaremos una lnea estndar
de cdigo de.fila de diferente color para mejorar la apariencia de la tabla:
</tr>
$ (docurnent) .~eady(function()
{
$ ('#cart "t body tr: nth-child (everO.,') .addClass
}) ;
ctr>
class="item">
Drupal: Creating 810g5, Forums,
Community Websites
</td>
ctd class="quantity">
ctd
<input
type="text
ll
Portals,
value=1I111
11
11
('alt' ) ;
Una vez ms, nos aseguramos de seleccionar solamente filas a colorear si estn en el
cuerpo de la tabla, como se ve en la figura 8.21.
name="quantity-4
id="quantity-4
and
maxlength="3
11
/>
</td>
ctd
class="pricer'>$35.99</td>
ctd
class="cost">$35.99</td>
</tr>
</tbody>
</table>
c/form>
Esta tabla presenta otro elemento pocas veces visto, -ct f oot;. Como -;:thead>, este
elemento agrupa un conjunto de filas de tabla. Observe que aunque el elemento viene
delante del cuerpo de la tabla, se presenta detrs del cuerpo cuando se muestra la pgina, como se ve en la figura 8.20.
Shlpplng
S2perttem
Tocal
Ut'ildlli
@i.~
QuanUty
Prlce
Total
$26.99
$26.99
D
D
D
$35.99
571.99
$17.99
$17.99
$35.99
$35.99
SubtolBl
$152.95
Tax
6%
$2 perltem
Shlpplng
Tocal
$9.18
$10.00
$1n.13
o 'i!lKi'i0i'd~
El orden de este cdigo fuente, aunque no intuitivo para los diseadores que piensan
visualmente sobre cmo se muestra la tabla, es de utilidad para aquellos con problemas
visuales. Cuando la tabla se lee en alto por dispositivos de ayuda para usuarios con necesidades especiales, el pie de pgina se lee antes que el contenido potencialmente extenso, permitiendo al usuario recibir un resumen de lo que va a venir.
Tambin hemos situado una clase en cada celda de la tabla, identificando qu columna de la tabla contiene esa celda. En el captulo anterior, hemos demostrado algunas formas de encontrar celdas en una columna al examinar el ndice de la celda dentro de su
fila. Aqu permitiremos que el cdigo ]avaScript sea ms sencillo al hacer que la fuente
HTML sea un poco ms compleja. Con una clase identificando la columna de cada celda,
nuestros selectores se pueden hacer ms sencillos.
}
})
Cuando capturamos pulsaciones de teclado para la funcin autocompletar de nuestro campo de bsqueda, observamos el evento keyup. Esto nos permite examinar la
mi
propiedad . keyCode del evento que nos ha dicho qu tecla se ha pulsado en el teclado.
Aqu, observamos el evento keypress en su lugar. Este evento no tiene una propiedad
. keyCode, pero en su lugar ofrece la propiedad. which. Esta propiedad informa del
carcter ASCII que est representado por la pulsacin de teclado que acaba de ocurrir.
Si la pulsacin de teclado resulta en un carcter (es decir, no es una tecla del cursor,
Supr, o alguna otra funcin de edicin) y ese carcter no est en el rango de cdigos
ASCII que representan numerales, entonces invocamos. preventDefaul
t () en el
evento. Como hemos visto antes, esto impide que el navegador acta sobre el evento; en
este caso, eso significa que el carcter nunca se inserta en el campo. Ahora, los campos
de cantidad pueden aceptar solamente nmeros.
mi
mismo smbolo. Por el contrario, necesitamos una cadena a pasar al mtodo. t extt ) de
jQuery cuando mostramos el resultado del clculo, de modo que utilizamos la funcin
String () para crear una nueva utilizando nuestra cantidad total calculada.
Cambiar una cantidad ahora actualiza el total automticamente, como se ve en la
figura 8.22.
.>
Clculos numricos
6%
})
})
td.quantity')
$2 por Item
(_0Iifi~
~Ki0I~
})
$('tr.shipping
15
input',
this) .val());
.text(String(totalQuantity));
Tenemos varias opciones respecto al evento a seguir para esta operacin de volver
a calcular. Observaremos el evento keypress, y activaremos el volver a calcular con
cada pulsacin del teclado. Podramos tambin observar el evento blur, que se activa
cada vez que el usuario abandona el campo. Aqu, podemos ser algo ms conservadores
con el uso de CPU, sin embargo, y solamente llevar a cabo nuestros clculos cuando se
activa el evento change. De esta forma, volvemos a calcular los totales solamente si el
usuario abandona el campo con un valor diferente de lo que tena antes.
La cantidad total se calcula utilizando un sencillo bucle . each ( ) . La propiedad
. value de un campo informar de la representacin de cadena del valor del campo,
de modo que utilizamos la funcin parselnt
() incorporada para convertir esto en un
entero para nuestro clculo. Esta prctica puede evitar situaciones extraas en las que la
suma se interpreta como concatenacin de cadena, ya que las dos operaciones utilizan el
Esto produce el mismo resultado que antes, pero nosotros ahora tenemos un lugar
adecuado para insertar nuestro clculo de coste total para cada fila:
$('td.quantity
input') .change (Eunction ()
var totalQuantity = O;
$('#cart
tbody tr') .each(function()
(
var price = parseFloat($('td.price',
.replace(rA\d.J*/,
"));
price = isNaN{price) ? O : price
var quantity =
parselnt ($ ('td.quantity
input',
var cost = quantity * price
$('td.cost',
this).text('$'
+ cost);
totalQuantity
+= quantity;
this) .text()
this) .val());
j);
$('tr.shipping
})
td.quantity')
.text(String(totalQuantity));
EifI
mi
Como vemos aqu, el total que debera ser $1079.70 se muestra como $1079.7. Incluso
peor, los lmites de precisin de JavaScript algunas veces pueden conducir a errores de
redondeo. Estos pueden hacer que los clculos aparezcan completamente rotos.
f
Tax
6%
Shlpplng
$2 perttem
52
Total
@iJCritet
@'t_gj~f~
Afortunadamente,
la solucin para ambos problemas es sencilla. La clase Number de
JavaScript tiene varios mtodos para tratar con este tipo de problema, y . toFixed
()
ajusta la cuenta aqu. Este mtodo toma un nmero de lugares decimales como parmetro, y devuelve una cadena que representa el nmero en coma flotante redondeado
a esos muchos lugares decimales:
6%
16
$2 perltem
~lliliiil~
SUbtlllal
$152.95
Tal<
Shlpplng
43
6%
$9.18
$2 per Item
$10.00
Total
$1T2.13
t1<iiiilC_~
~~
Tax
Shlpplng
6%
52
S2peritem
Total
@t'8Iil~
normales.
mi
ED
Redondear valores
Despus de una larga serie de operaciones aritmticas, el redondeo de nmeros en coma
flotante podria causar suficiente error acumulado que incluso . toFixed () no pueda
enmascararlo. Laforma ms segura de gestionar manipulaciones de moneda en grandes
aplicaciones es almacenar y manipular todos los valores en cntimos, como enteros; los
puntos decimales se pueden aadir para visualizacin solamente.
Para calcular impuestos, necesitamos dividir la cifra facilitada entre 100 y luego
multiplicar taxRate por el subtotal. Como el impuesto siempre se redondea, debemos
asegurarnos de que el valor correcto se utiliza tanto para la visualizacin como para clculos posteriores. La funcin Math. ee il () de JavaScript puede redondear un nmero
hacia arriba hasta el entero ms prximo, pero puesto que estamos tratando con dlares
y cntimos tenemos que ser un poco ms complicados:
var taxRate = parseFloat($('tr.tax
td.price') .text(
j
var tax = Math.ceil(totalCost
* taxRate * 100) j 100;
$('tr.tax
td.cost') .text('$' + tax.toFixed(2;
totalCost
+= taxi
Otros clculos
El resto de los clculos en la pgina siguen un patrn similar. Para el subtotal, podemos sumar nuestros totales para cada fila segn se calculan, y mostrar el resultado utilizando el mismo formato de moneda que antes, como se ve en la figura 8.27.
$('td.quantity
input') .change(function()
var totalQuantity = Di
var totalCost a O;
$('#cart
tbody tr') .each(function()
{
var price = parseFloat($('td.price',
this) .text()
.replace(jA(A\d.*/,
";
price = isNaN(price)
? O : price;
var quantity =
parselnt($('td.quantity
input', this) .val(;
var cost = quantity * price
$('td.cost',
this) .text('$' + cost.toFixed(2;
totalQuantity
+= quantity;
totalCost += cost;
j);
$ ('tr.shipping
td.quantity')
.text (String(totalQuantit
$('tr.subtotal
td.cost') .text('$'
+
totalCost.toFixed(2;
100;
"
6%
$2 por ltBm
Shlpplng
T_
~ttiKaJaliiO,
y;
~~l
j);
Toques finales
El clculo de envo es ms sencillo que el impuesto ya que no implica ningn redondeo en nuestro ejemplo. El transporte se multiplica por el nmero de artculos para
determinar el total:
$('tr.shipping
td.quantity')
.text(String(totalQuantity;
var shippingRate
= parseFloat($('tr.shipping
td.price')
.text().replace(r(A\d.l*j,
";
var shipping
= totalQuantity
* shippingRate;
$('tr.shipping
td.cost') .text('$' + shipping.toFixed(2;
totalCost
+= shipping;
6%
23
,Rii:II~
$2 perttem
@'i!<i!<d~
Hemos estado siguiendo el importe total a medida que hemos ido avanzando, por
lo que todo lo que nos queda por hacer para esta ltima celda es formatear totalCost
de forma apropiada:
td.cost')
.text('$'
+ totalCost.toFixed(2;
mi
.insertAfter($('td:nth-Child(2)',
.append($deleteButton)
;
Ahora, hemos replicado por completo cualquier clculo del lado del servidor que ocurrira, por lo que podemos ocultar el botn Recalculate, como muestra la figura 8.29.
$('#recalculate')
) ;
$ ('<td>&bsp;</td>')
.insertAfter ('#cart
.hide();
tfoot
this
t,f:'>nth-child(2) ,) ;
Necesitamos crear celdas vacas en las filas cabecera y pie de pgina como marcadores
de posicin de modo que las columnas de la tabla se alineen correctamente. Los botones
se crean y aaden en las filas del cuerpo solamente, como muestra la figura 8.30.
Tax
6%
Shlpplng
$2 perltem
Total
@~~~
Figura 8.29. Eliminar el botn Recalculate.
.'
Shipplng
~-~
Ahora necesitamos hacer que los botones hagan algo. Podemos cambiar la definicin
del botn para aadir un manejador click:
Eliminar elementos
$('<th> </th>')
.insertAfter('#cart
thead th:nth-child(2)
$('#cart tbody tr') .each(function()
{
$deleteButton
~ $('<irng />') .attr({
'width':
'16',
height ':
16 '
'src':
/imag8s/cross.png',
'alt': 'remove from cart',
'title': 'remove from cart',
'class': 'clickable'
) ;
$ ( "<t.do c y t do ' )
$2 perltem
Total
Este cambio una vez ms se hace eco de nuestro principio de mejora progresiva: en
primer lugar, asegrese de que la pgina funciona correctamente sin JavaScript. Luego,
utilice jQuery para llevar a cabo la misma tarea de forma ms elegante cuando sea posible.
');
$deleteButton
width
height
I
1:
1161,
1:
'src':
/images/cross.png',
'alt': 'remove from cart',
'title': 'remove from cart',
'class': 'clickable'
}) .click(functionn
{
l
..
$(this).parents('tr')
.val (O);
.find('td.quantity
input')
El manejador encuentra el campo quanti ty en la misma fila que el botn, y establece el valor en 0, como muestra la figura 8.31. Ahora, el campo se actualiza, pero los
clculos no estn en sincrona.
Necesitamos activar el clculo como si el usuario hubiera cambiado manualmente
el valor del campo:
$deleteButton
~ $('<irng />') .attr({
'width':
'16',
'height':
'16',
'sre': '../images/eross.png',
'alt': 'remove fraro cart',
'title
'remove froro cart',
1:
i~~"
Aprende jQuery U
class
'clickable'
}I.click(function()
{
$(thisl .parents('tr'l
.find('td.quantity
.val(O) .trigger('change');
I
BD
1:
input'l
}I ;
6%
$2pe<ltem
Tax
Shlpplng
__
....
"_1
Total
~
Figura 8.33. Ocultar la fila en la tabla.
Tax
6%
$2perHem
Shlpplng
YoIal
{I!I-.w-.,
Figura 8.31. Aadir un manejador al baln.
.:
Cuando la fila se oculta,el campo sigue presente en el formulario. Esto significa que
se enviar con el resto del formulario, y el elemento se eliminar en el lado del servidor
en ese momento.
Nuestro diseo de filas de lneas alternas se ha visto alterado al eliminar esta fila.
Para corregir esto, movemos nuestro cdigo de filas alternas existentes a una funcin
de modo que podemos invocarla de nuevo ms adelante. Al mismo tiempo, necesitamos modificar el cdigo para asegurarnos de que nuestra seleccin de fila alterna ignora
cualquier fila oculta.
Desafortunadamente, incluso si filtramos todas las filas ocultas, seguimos sin poder
utilizar el selector : nth-child (even), porque aplicar la clase al t a todas las filas visibles que son hijo par de su padre. Veamos lo que sucede cuando aplicamos el siguiente
cdigo modificado a cuatro filas de tabla cuando la segunda est oculta:
$('#cart
tbody tr'l .removeClass('alt')
.filter(' ,visible,nth-child(even)
') .addClass('alt');
Ahora el feedback visual. Ocultaremos la fila en la que se ha hecho clic, de modo que
el elemento se elimina claramente de la cesta, como muestra la figura 8.33.
$deleteButton
= $('<img
/>') .attr({
'width':
'16',
'height':
'16',
'sre': ' ../images/cross.png',
'alt': tremove from cart'
'title':
'remove from cart'
'class':
'clickable'
)) .click(function()
(
$(this) .parents('tr')
.find('td.quantity
.val(O) .trigger('change')
.end () .hide () ;
));
I
<tr> . . . </tr>
e t r- s t.y Lee "display:
none 11:>
e t r s . . . </tr>
<tr class="alt">
. . . </tr>
</tr>
Son visibles tres filas; slo la cuarta tiene aplicada la clase al t. Lo que necesitamos
es la expresin selector : visible: odd, ya que elegir cada dos filas despus de eliminar las ocultas de la seleccin (y justifica el cambio de un selector de ndice uno a otro
de ndice cero). Como se vio en el captulo2, utilizar: odd o : even podra producir resultados inesperados si tuviramos ms de un elemento -c t body. pero en este caso,
estamos en buena forma. Con el cambio de selector en su lugar, nuestra nueva funcin
se parece a esto:
var
input')
stripe = function()
{
$('#cart
tbody tr') .removeClass('alt')
.filter(' ,visible,odd')
.addClass('alt');
};
stripe()
&llI
Ahora podemos invocar esta funcin de nuevo despus de eliminar una fila:
=
$deleteButton
I
width
1:
16
$('<img
I
1>'1
.attr({
input'l
mi
})
.slideDown();
return
false
~i&-~
Flrstname:
Las! name:
__
Addmss:ooeo
Drl""
CIIy: ~~.
l?
ZlP: C
Stale:
4staveScll
==:::J
Schoon
=::J
I
I
I
J
You' 11 leva
~
Figura 8,36. Cuadro de envo como formulario editable.
&iI
$ (document) .ready(function()
{
$('shipping
form') .submit(function()
(
var postData = $(this) .serialize();
$.post('shipping.php',
postData);
return false
};
j);
var
mi
saveShipping
= function() {
var postData
= $('#shipping
,input') .serialize();
$.post("shipping.php',
postData,
function(data)
{
$('~shipping
form') .remove();
$ (data) .appendTo('#shippin~');
$('#shipping-name')
.click(editShipping),
}) ;
return false
};
$ ('#shipping-name')
.click(editShipping),
}) ;
})
.'
return
false
};
})
Pero, esto no funcionar. La forma en la que lo tenemos configurado ahora, el manejador de evento . submi t () se vincula al formulario Shipping to tan pronto como se
carga el DOM, pero el formulario no est en el DOM hasta que el usuario hace clic en el
nombre Shipping to. El evento no se puede vincular a algo que no existe.
Para solucionar este problema, podemos situar el cdigo de creacin de formulario
en una funcin denominada edi tShipping
() y el cdigo de envo del formulario o
eliminacin del formulario en una funcin denominada saveShipping
() . Luego podemos vincular la funcin saveShipping
() en la rellamada de $ . get (), despus de
que se haya creado el formulario. De igual forma, podemos vincular la funcin edi tShi pping () tanto cuando el DOM est listo y cuando el vnculo Edit shipping se vuelve
a crear en la rellamada de s . post () :
$ (document) .ready(function()
(
var editShipping
= function()
{
$.get('shipping.php',
function(data)
$('#shipping-name')
.remove();
$ (data) .hide() .appendTo('#shipping')
.slideDown();
$('#shipping
form') .submit(saveShipping),
})
return
i.
false
El cdigo ha formado un patrn circular de cierto tipo, en el que una funcin permite
la otra al volver a vincular sus respectivos manejadores de evento.
El cdigo terminado
Tomados juntos, el cdigo para la pgina de carrito de la compra son meramente 80
lneas, bastante pequeo considerando la funcionalidad que realiza, pero especialmente
cuando tenemos en cuenta el estilo dinmico que ha adquirido el cdigo para legibilidad
ptima. Muchas de las lneas en jQuery se podran haber combinado, si hubiramos estado particularmente preocupados con el nmero de lneas, debido a la posibilidad de
encadenar de jQuery. En cualquier caso, aqu tiene el cdigo terminado para la pgina
de carrito de compra, que concluye este captulo sobre formularios:
$ (document) .ready(function()
(
var stripe = function()
{
$('#cart
tbody tr') .removeClass('alt')
.filter(' :visible:odd') .addClass('alt')
};
stripe()
$('#recalculate')
.hide();
}) .change(function()
var totalQuantity
= O;
var totalCost
= O;
$('#cart
tbody tr') .each(function()
(
var price = parseFloat($(' .price', this)
.text () .replace
['\d.] * /,
";
price = isNaN(price)
? O , price;
var quantity =
parselnt($('
.quantity input', this) .val(), 10);
var cost = quantity * price
$ (,.cost " this). text (,$' + cost. toFixed (2 ;
totalQuantity
+= quantity;
(r
~"!n'
&DI
cost
+=
}) ;
return. false
});
IJD
};
$(' .subtotal .cost') .text('$' + totalCost.toFixed(2));
var taxRate = parseFloat($(' .tax .price') .text()) / 100;
var tax = Math.ceil(totalCost
* taxRate * 100) / 100;
$('.tax .cost').text('$' + tax.toFixed(2));
totalCost += taxi
$(' .shipping .quantity') .text(String(totalQuantity));
var shippingRate = parseFloat($('.shipping
.price')
.text() .replace(r'\d.]*/,
"));
var shipping = totalQuantity
* shippingRate;
$(' .shipping .cost') .text('$' + shipping.toFixed(2));
totalCost += shipping;
$(' .total .cost') .text('$' + totalCost.toFixed(2));
})
$('<th> </th>')
.insertAfter('#cart
thead th:nth-child(2) ');
$('#cart tbody tr') .each(function()
{
$deleteButton = $('<img />') .attr({
'width 1: '16',
'height': '16',
'src
/images/cross.png'
'alt': 'remove from cart
'title': 'remove from cart
c La s s ":
clickable
}) .click (function () {
$(this) .parents('tr') .find('td.quantity
.val (O) .trigger ('change' )
.end ().hide ();
stripe ();
l:
'
l,
$('#shipping-name')
})
.click(editShipping);
-',
Resumen
En este captulo hemos investigado formas de mejorar la apariencia y comportamento
de elementos de formulario HTML comunes. Hemos aprendido cmo mejorar el estilo
de formularios, ocultar y mostrar campos condicionalmente basndose en otros valores de campo, y validar contenidos de campos antes del envo y durante la entrada de
datos. Hemos tratado caractersticas como autocompletar AJAX para campos de texto,
permitiendo incorporar slo caracteres especficos en un campo, y llevar a cabo clculos
sobre valores numricos en campos. Tambin hemos aprendido a enviar formularios
utilizando AJAX en lugar de refrescar una pgina.
El elemento formulario es a menudo el pegamento que mantiene un sitio interactivo
junto. Con jQuery, podemos fcilmente mejorar la experiencia del usuario al completar
formularios mientras se preserva su utilidad y flexibilidad.
input')
});
})
this))
td:nth-child(2)
');
$ (document) .ready(function()
{
var editShipping = function() {
$.get('shipping.php',
function(data)
$('#shipping-name') .remove();
$(data) .hide() .appendTo('#shipping') .slideDown();
$('#shipping form') .9ubmit(saveShipping);
})
return
false
};
var saveShipping = function() {
var postData = $(this) .serialize();
$.post('shipping.php',
postData, function(data)
$('#shipping form') .remove();
$(data) .appendTo('#shipping');
$('#shipping-name') .click(editShipping);
____________________________
.'
9
Rotativos
Titular rotativo
Para nuestro primer ejemplo de rotativo, tomaremos un feed de noticias y desplazaremos los titulares, junto con extracto del artculo, a la vista uno de cada vez. Las historias fluirn hasta quedarse a la vista, se detendrn para leerse, y luego se desplazarn
mi
9. Rotativos
fuera de la vista como si fueran una cinta infinita de informacin dando vueltas continamente por la pgina.
Configurar la pgina
En su nivel ms bsico, esta caracterstica no es muy dificil de implementar. Pero como
pronto veremos, hacer que est lista para produccin requiere un poco de sutileza.
Empezamos, como siempre, con un bloque de HTML. Situaremos el feed de noticias
en la barra lateral de la pgina:
<:h3>Recent News</h3>
<:div id="news-feedU>
<a href="news/index,htmlll>News
</div>
Releases</a>
S8~
position: relative
height: 200px;
width: 17em;
overflow:
hidden;
}
.headline
mi
position:
absolute;
height: 200px;
top: 210px;
overflow:
hidden;
Recuperar el feed
Para recuperar el feed, utilizaremos el mtodo $ . get ( ) , una de las muchas funciones
AJAX de jQuery para comunicarse con el servidor. Este mtodo, como hemos visto antes,
nos permite operar sobre contenido desde una fuente remota al utilizar un manejador de
lIlIlII
9. Rotativos
xito. El contenido del feed se pasa a este manejador como una estructura XML. Luego
podemos utilizar el motor selector de jQuery para trabajar con estos datos.
mil
RecentNew8
IQuory. M!croto!!. and Nolda
$ (document) .ready(function()
(
$('#news-feed') .each(function()
var $container = $(this);
$container.empty();
$.get('news/feed.xml'.
function(data)
{
$ ('rss item'. data) .each(functionO
{
II Trabajar con los titulares aqu.
}) ;
}) ;
})
})
touery
UI18n:2
,Speakl
IQuery.comSII!! Red go
Raglatratlan Optn tgr !QueN
ConferaDa, 2008
IQuerI UI1.5.2
/'
$ (document) .ready(function()
(
$('#news-feed') .each(function()
var $container = $(this);
$container.empty() ;
$.get('news/feed.xml'.
function(data)
{
$('rss item', data) .each(function()
{
var $link = $ ('<a></a>')
.attr('href', $('link', this) .textO)
.text($('title', this) .text(;
var $headline = $('<h4></h4>') .append($link);
var pubDate = new Date(
$('pubDate'. this).text(;
var pubMonth ~ pubDate.getMonth()
+ 1;
var pubDay = pubDate.getDate();
var pubYear = pubDate.getFul1Year();
var $publication = $('<div></div>')
.addClass('publication-date')
.text(pubMonth + '1' + pubDay + '1'
+ pubYear);
var $summary = $('<div></div>')
.addC1ass('summary')
html ($ ('description'. this). text O) ;
$ ('<div></div>')
.append($headline)
.appendTo($container);
})
})
})
})
$ (' <div></div>')
.append($head1ine.
$publication.
.appendTo($container)
$summary)
});
Obtenemos el texto de los elementos <ti t Le s y <link> de cada elemento, y construimos el elemento <a> a partir de ellos. Este vnculo luego se sita en un elemento
<h4 >. Situamos cada elemento de noticias en <di v id= "news - feed" , pero por ahora
estamos omitiendo la clase headl ine en el <di v contenedor de cada noticia, de
modo que podemos ver ms fcilmente nuestro trabajo en progreso, como muestra la
figura 9.3.
}) ;
}) ;
})
La informacin de fecha en un feed RSS se codifica en formato RFC 822, que incluye
informacin de fecha, hora y zona horaria (por ejemplo, sun , 28 Sep 2 OO8 18 : 01 : 55
+ O O O O). Este formato no es particualrmente agradable a la vista, por lo que utilizamos el
Ea
9. Rotativos
lID
and NOIIIa
Recent Newa
IQueo( MIc!'QIoll and NaJIla
9/211I2008
We llaVe twa pleces of fanIasUc, albeIt
sernndlpltous, news tDday: 60th
MlcroBOft and Nakla are Ialclng 1Ile
maJarstep of adolUng jQuelY as par!
011llelr 011I0101
applloatlon
development plaiform.
'
Por ltimo, almacenamos el nmero total de titulares para uso posterior y definimos
una variable de tiempo de espera a utilizar para el mecanismo de pausa entre cada rotacin.
IQueo( UJ 1.6rc2
9/1912008
Hev evervone.
var pause
Como podemos ver, el ttulo, fecha, vnculo y resumen de cada noticia ahora estn en
su lugar. Todo lo que queda es aadir la clase headl ine con. addClass ( headl ine
(que ocultaremos a la vista debido al CSS definido anteriormente), y estamos listos para
continuar con nuestra animacin.
I
I )
Configurar el rotativo
Puesto que el elemento de noticias visible cambiar con el tiempo, necesitamos una
forma de mantener fcilmente registro de qu elementos son visibles y dnde estn. En
primer lugar, estableceremos dos variables, una para el titular actualmente visible, y otra
para el titular que acaba de no estar a la vista. Inicialmene, ambos valores sern O.
var currentHeadline = o, oldHeadline = o;
No hay necesidad todava de asignar a pause un valor en este momento; se establecer cada vez que ocurre la rotacin. Sin embargo, siempre debemos declarar variables locales utilizando var para evitar el riesgo de colisiones con variables globales del
mismo nombre.
10;
Ahora estamos listos para rotar los titulares, fechas y resmenes. Definiremos una
funcin para esta tarea de modo que podamos repetir fcilmente la accin cada vez
que lo necesitamos. En primer lugar, ocupmonos de actualizar las variables que estn
registrando qu titular est activo. El operador mdulo (%) nos permitir fcilmente pasar
en ciclo por los nmeros de titulares. Podemos aadir 1 al valor currentHeadline
cada vez que nuestra funcin se invoca, y hacer que este valor mdulo tome el valor
headlineCount
para limitar la variable a nmeros de titular vlidos.
Recuerde que hemos utilizado esta misma tcnica para pasar en ciclo por los colores
de fila cuando aplicbamos color alterno a filas de tabla.
mi
9. Rotativos
f1D
Tambin deberamos actualizar el valor oldHeadl ine de modo que podamos fcilmente manipular el titular que se est moviendo fuera de la vista.
var headlineRotate
= function() {
currentHeadline
= (oldHeadline + 1) % headlineCount
// Animar las posiciones de titular aqu.
oldHeadline = currentHeadline
};
$ (document) .rrady(function()
(
$('#news-feed') .each(function()
var $container = $(this);
$container.empty() ;
$.get('news/feed.xml',
function(data)
{
$('rss item', data) .each(function()
{
var $link = $(Ica></a>')
.attr('href', $('link', this).text())
.text($('title', this) .text());
var $headline = $('<h4></h4>') .append($link) ;
Ahora tenemos que llenar el vaco con el cdigo que mueve los titulares. En primer
lugar, aadiremos una animacin que mueve el titular antiguo fuera de la vista. Luego,
insertaremos otra animacin que pasa el nuevo titular a la vista.
var headlineRotate
= function() {
currentHeadline
=
(oldHeadline + 1) % headlineCount
$('div.headline') .eq(oldHeadline) .animate(
{topo -hiddenPosition},
'slow', function()
$(this) .css('top', hiddenPosition);
}) ;
$(rdiv,headline')
.eq(currentHeadline) ,anmate (
{top: aL'
slow', function () (
pause = setTimeout(headlineRotate,
5000);
})
var
var
var
var
var
.'
oldHeadline
currentHeadline
};
$('cdiv></div>')
.addClass('headline')
.append ($headline, $publication,
.appendTo($container) ;
})
var currentHeadline
= o, oldHeadline
= o;
var hiddenPosition
= $container.height()
+ 10;
$('div.headline') .eq(currentHeadline) .css('top',
var headlineCount
= $(rdiv.headliner)
.length
var pause
O);
var headlineRotate
= function() {
currentHeadline
=
(oldHeadline + 1) % headlineCount;
$('div.headline') .eq(oldHeadline) .animate (
{topo -hiddenPosition},
'slow', function()
$(this) .css('top', hiddenPosition);
})
En ambos casos, tambin tenemos una funcin de rellamada especificada para actuar
cuando se completa la animacin. Cuando el titular antiguo ha salido completamente
de la vista, hace que su propiedad top se restablezca en hiddenPosi tion de modo
que est listo para regresar ms tarde. Cuando el titular de noticias ha terminado con
su animacin, queremos que ponga en cola la siguiente transicin; esto se realiza con
una llamada a lafuncin}avaScript setTimeout (), que registra una funcin a invocar
despus de un perodo especificado. En este caso, estamos haciendo que headl ineRotate () se lance de nuevo en cinco segundos (5000milisegundos).
Ahora tenemos un ciclo de actividad; una vez que se completa una animacin, la
siguiente est lista para activarse. Queda invocar la funcin la primera vez; haremos
esto con otra llamada a setTimeout (), haciendo que la primera transicin ocurra 5
$summary)
$('div.headline') .eq(currentHeadlinet.animate(
(top: o), 'slow', function () (
pause = setTimeout(headlineRotate,
5000);
})
oldHeadline
};
pause
})
= currentHeadline;
setTimeout(headlineRotate,
5000)
}l;
})
A mitad de la animacin, podemos ver un titular cortado en la parte superior, y el siguiente que aparece a la vista cortado en la parte inferior, como muestra la figura 9.6.
Ea
9. Rotativos
Rac:ent News
IlaYo
.-c"'V<VQ'QIU
."tu
lItO'v.lUDuaaa
Ull.S.l
6/2712008
cortados.
};
Rac:entNewa
_
on :sun!ISY. :septelt1llW 26,
IAtlllMW.a,se1!two tracks of
~
setTimeout(headlineRotate,
250)
(beginner and
-...atI~_".
~ced
$container.hover(function()
clearTimeout(pause) i
}, function() (
pause
(), lo esta-
var headlineRqtate
= function()
if (Irotat'elnProgress) {
rotatelnProgress
= true;
currentHeadline
=
(oldHeadline + 1)
% headlineCount
$('div.headline') .eq(oldHeadline) .animate(
{top, -hiddenPosition},
'slow', function()
$(this) .CSS(ltop',
hiddenPosition) i
}) ;
$('div.headline') .eq(currentHeadline) .animate(
[Eop , o).
'slow', function () (
rotatelnProgress
= false
pause = setTimeout(headlineRotate,
5000);
)) ;
oldHeadline = currentHeadline;
lQuary
BiI
});
Cuando el ratn entra en el rea del titular, el primer manejador . hover () invoca
la funcin JavaScript clearTimeout
() . Esto cancela el cronmetro en progreso, impidiendo que se invoque headlineRotate
(). Cuando el ratn se aleja, el segundo manejador . hover () reinicia el cronmetro, invocando as headl ineRota te () despus
de 250 milisegundos de retraso.
Este sencillo cdigo funciona bien la mayor parte del tiempo. Sin embargo, si el usuario mueve el ratn por encima y fuera de <di v rpidamente y de forma repetida, puede
ocurrir un efecto poco deseado. Mltiples titulares estarn en movmiento a la vez, posicionndose uno encima de otro en el rea visible, como muestra la figura 9.7.
Desafortunadamente, necesitamos llevar a cabo cierta ciruga para extirpar este cncer. Antes de la funcin headlineRotate
(), introduciremos una variable ms:
>-
var rotateInProgress
= false
BB
9. Rotativos
pausa . falsa;
currentHeadline
= (oldHeadline + 1)
% headlineCount;
$('div.headline')
.eq(oldHeadline)
.animate(
{top: -hiddenPosition}.
'slow', function()
$(this) .css('top',
hiddenPosition);
})
mil
Dentro del archivo f eed. php, recuperamos el contenido de nuestro feed de noticias
del sitio remoto, luego imprimimos el contenido como el resultado del script.
'
<?php
!
header ('Con t errt v'I'ype : text/xml');
",
print file_get_contents('http://jquery.com/blog/feed');
?>
$('div.headline')
.eq(currentHeadline)
{top: O},
'slow', function()
(
rotatelnProgress
= false
if (Ipause) {
pause
.animate(
setTimeout(headlineRotate,
5000);
});
oldHeadline
= currentHeadline
};
if
(Ipause)
pause = setTimeout(headlineRotate,
5000);
}
$container.hover(function()
clearTimeout(pause)
;
pausa = falsa;
}, funct ion () {
if (1 pausa) {
pause = setTimeout(headlineRotate,
}
})
.'
250);
Por fin, nuestro rotativo de titulares puede soportar todo tipo de intentos del usuario para desbaratarle.
Recuperar un archivo remoto como ste podra llevar algo de tiempo, dependiendo
de un nmero de factores, por lo que deberamos informar al usuario de que la carga
est en progreso.
Para hacer esto, aadiremos una imagen de indicador de carga a la pgina antes de
, lanzar nuestra peticin AJAX.
var
El feed de noticias que hemos estado utilizando para nuestro ejemplo es un archivo
local, pero podramos querer recuperar un feed de otro sitio. Como.:hemos visto en un captulo anterior, las peticiones AJAXno se pueden, como regla, realizar a un sitio diferente
que el que alberga la pgina que se visualiza. All, tratamos el formato de datos JSONP
como un mtodo para eludir esta limitacin. Aqu, sin embargo, asumiremos que no podemos modificar la fuente de datos, por lo que necesitamos una solucin diferente.
Para permitir que AJAX vaya a buscar ese archivo, utilizaremos cdigo del lado del
servidor como un proxy para la peticin, para que JavaScript crea que el archivo XML
est en nuestro servidor aunque reside en uno diferente. Escribiremos un pequeo script
PHP para extraer el contenido del feed de noticias a nuestro servidor, y pasar esos datos
al script jQuery solicitante. Este script, que denominaremos feed. php, se puede invocar
de la misma forma que se fue a buscar feed. xml previamente:
$.get('news/feed.php',
//
})
...
;
function(data)
$loadinglndicator
= $('<img/>')
.attr({
'sre': 'images/loading.gif',
'alt':
Loading.
Please wait.
I
.addClass('news-wait')
.appendTo($container)
Ahora, cuando la pgina se carga por primera vez, si hay un retraso al recuperar el
contenido del titular, veremos una imagen de carga en lugar de un rea vaca, como
muestra la figura 9.8.
Esta imagen es un GIF animado, y en un navegador Web girar para significar que
se est llevando a cabo cierta actividad.
mi
9. Rotativos
&111
$ (document) .ready(function()
(
$('#news-f~ed')
.each(function()
var $container
= $(this);
$contai~er.empty()
;
RacentNews
var fadeHeight
= $container.height()
for (var yPos = O; yPos < fadeHeight;
$('<div></div>')
.addClass('fade-slice')
.appendTo($container)
;
\1
"";'1\'
/ 4;
yPos
+=
2)
}
});
})
Podemos fcilmente crear nuevas imgenes GIF animadas para utilizarse como indicadores de carga AJAX al utilizar el servicio en http: / / aj axload. info/.
Efecto degradado
Antes de dejar nuestro ejemplo de titular rotativo, dmosle un toque final, al hacer
que el texto del titular parezca que aparece progresivamente desde la parte inferior de
su contenedor. El efecto ser un degradado, apareciendo como si el texto fuera opaco en
la parte superior del efecto y transparente en la parte inferior.
Un solo elemento de texto no puede tener mltiples opacidades simultneamene,
sin embargo. Para simular esto, cubriremos el rea de efecto con una serie de elementos, cada uno de los cules tiene una opacidad diferente. Estos cortes sern elementos
<di v con algunas propiedades de estilo en comn, que podemos declarar en nuestra
hoja de estilo:
.fade-slice
(
position:
absolute;
width: 20ern
height: 2px;
background:
#efd;
z-index: 3
Todos tienen las mismas propiedades width y background - color que su elemento
contenedor, <di v id= "news- feed" >. Esto engaar el ojo del usuario al pensar que el
texto se est desvaneciendo, en lugar de cubrirse por otro elemento.
Ahora podemos crear los elementos ed i.v c Las s "fade-slice"
>. Para estar seguros de que tenemos el nmero correcto, primero determinaremos una altura en pxeles para toda el rea de efecto. En este caso, estamos eligiendo 25 por ciento de la altura
<di v Ld " news - f eed" >. Utilizaremos un bucle f or para iterar por la altura del rea,
creando un nuevo elemento de corte para cada segmento de 2 pxeles del degradado:
Ahora tenemos 25 cortes (uno para cada segmento de 2 pxeles del area de degradado de 50 pxeles), pero estn todos apilados en la parte superior del contenedor. Para
- que nuestro truco funcione, necesitamos que cada uno tenga una posicin y opacidad
diferente. Podemos utilizar la variable de iteracin yPos para determinar de manera
matemtica las propiedades opaci ty y top de cada elemento:
$ (document) .ready(function()
(
$('#news-feed')
.each(function()
var $container
= $(this);
$container.empty()
;
var
for
fadeHeight
= $container.height()
/ 4;
(var yPos = O; yPos < fadeHeight;
yPos '+= 2) (
$('<div></div>')
.css({
opacity:
yPos / fadeHeight.
top: $container.height()
- fadeHeight
+ yPos
}) .addClass('fade-slice')
.appendTo($container);
}
})
j);
Estos clculos pueden ser difciles de visualizar, por lo que situaremos los nmeros
en una tabla. Los valores de opacidad suben incrementalmente de transparente a opaco,
ya que los valores superiores empiezan en la parte superior del rea de degradado (150)
y crecen a la altura del contenedor:
150
0.04
152
0.08
154
0.12
156
0.16
158
ti
&DI
9. Rotativos
40
0.80
190
42
0.84
192
44
0.88
194
46
0.92
196
48
0.96
198
.addClass('news-wait')
.appendTo($container)
;
('
Recuerde que puesto la posicin superior del ltimo <di v clas s = " f ade - s 1 i ce " >
es 198,su altura de 2 pxeles claramente superpondr los dos pxeles inferiores del <div
contenedor de 200 pxeles de alto. Con nuestro cdigo en su lugar, el texto en el rea de
titular de la pgina ahora se funde desde transparente a opaco, a medida que solapa la
parte inferior del contenedor, como muestra la figura 9.9.
$.get('news/feed.php',
function(data)
$loadingIndicator.rernove()
;
$ ( 'rss itern', data). each (function () {
var $link = $('<a></a>')
.attr('href',
$('link',
this) .textll)
.text($('title',
this).textll);
var $headline
= $('<h4></h4>') .append($link);
var
var
var
var
var
RecentNewa
pubDate
= new Date($('pubDate',
this) .text());
pubMonth
= pubDate.getMonth()
+ 1;
pubDay
= pubDate.getDate();
pubYear
= pubDate.getFullYear();
$publication = $('<div></div>')
.addClass('publication-date')
.text(pubMonth
+ '1' + pubDay + ,/,
+ pubYear);
'
n .
" ..
""'
$surnmary = $('<div></div>')
.addClass('sumrnaryl)
.htrnl($('description',
this) .text());
$('<div></div>')
.addClass('headline')
.append ($headline,
$publication,
$surnrnary)
.appendTo($container)
;
}) ;
var
Ir<;
,,,"'.
a opaco.
El cdigo terminado
Nuestro primer rotativo est ahora completo. Los elementos de noticias se van ahora
a buscar desde un servidor remoto, se formatean, yse animan segn lo planificado, y
cuentan con un bonito estilo:
$ (docurnent) .ready(function()
(
$('#news-feed')
.each(function()
var $container
= $(this);
$container.ernpty()
;
var
for
fadeHeight
= $container.height()
/ 4;
(var yPos = O; yPos < fadeHeight;
yPos += 2) (
$('<div></div>')
.css({
opacity:
yPos I fadeHeight,
top: $container.height()
- fadeHeight
+ yPos
}) .addClass('fade-slice')
.appendTo($container);
var currentHeadline
= O, oldHeadline = O;
var hiddenPosition
= $container.height{) + 10;
$('div.headline')
.eq(currentHeadline)
.css('top',
var headlineCount
= $('div.headline')
.length
var pause
var rotateInProgress
= false;
var
O);
headlineRotate
= function()
if (!rotateInProgress)
{
rotateInProgress
= true
pause = false
currentHeadline
= (oldHeadline + 1)
% headlineCount
$('div.headline')
.eq(oldHeadline)
.anirnate(
{top: -hiddenPosition},
'slow', function()
$(this) .css('top',
hiddenPosition);
}l;
$('div.headline')
.eq(currentHeadline)
{top: O}, "a Low! , function Il (
.animate(
rotateInProgress
= false
if (!pause)
(
pause = setTimeout(headlineRotate,
5000)
&D
mi
9. Rotativos
};
if
cimg
currentHeadline
src="images/covers/medium/1847190871.jpgll
width="120"
alt=IICommunity
<sp,h
(!pause)
pause
= setTimeout(headlineRotate,
cimg
$eontainer.hover(funetion()
elearTimeout(pause)
;
pause
false;
cspan
The
Cookbook">
height="148
1t
Inside
osCommerce:
The
Cookbook"
/>
class="price">$44.99c/span>
c/a>
= setTimeout(headlineRotate.
<a href="images/covers/large/1847190979.jpg"
250) ;
title="Learn
OpenOffice.org
Programming:
});
})
7190901. jpg"
osCornmerce:
src=lIimages/covers/mediurn/1847190901.jpgll
alt="Deep
})
Inside
width="120"
}. funet ion () (
if (!pause) (
/>
clas9="price">$3S.99c/span>
title="Deep
pause
height="148"
Server Quickly"
<la>
<a href=" images/eovers/large/184
5000);
&a
OOoBasic
Spreadsheet
and
Calc
Macro
automation">
<img sre="images/covers/medium/1847190979.jpg"
width="120"
height="148"
alt="Learn
OpenOffice.org
Programming:
Un carrusel de imgenes
.'
cspan
Calc
Macro
automation"
/>
c/a>
<a href="images/eovers/large/1847190987.jpg"
title="Mierosoft
AJAX C# Essentials:
cimg
ASP.NET
2.0
Building
Applications">
src=lIimages/covera/medium/1847190987.jpg"
height='t148It
width="120"
AJAX C# Essentials:
Building
ASP.NET
2.0 Applieations"
/>
alt="Microsoft
Responsive
capan
class="price">$3l.99c/span>
c/a>
dmg
and
class="price">$3s.99c/span>
Responsive
Spreadsheet
OOoBasic
Web
Toolkit
7191002. jpg"
GWT
Java
src "images/eovers/medium/184
width=1I120"
height="148"
alt="Google
Web
cspan
Toolkit
GWT
AJAX
Prograrnming">
7191002. jpg"
Java
AJAX
Programming"
/>
class=rtprice">$40.49c/span>
<la>
<a href="images/eovers/large/1847192386.jpg"
title=tlBuilding
<img
width="120"
alt="Building
capan
Websites
with
Joomla!
1.5
Beta
1">
src="images/eovers/medium/1847192386.jpg"
height="148"
Websites
with
Joomla!
1.5
Beta
1"
/>
class="price">$40.49c/span>
c/a>
Configurar la pgina
</div>
</div>
Como siempre, empezamos diseando el HTML y CSS de modo que los usuarios
sin JavaScript disponible reciban una representacin llamativa y funcional de la informacin:
<:div id=Ufeatured-bookslI>
<:div class=lIcoversll>
<a href=" images/eovers/large/184
title="Community
Server
7190871. jpg"
Quickly">
,,,.--
&!I
9. Rotativos
#featured-books
{
position: relative
background,
#ddd;
width, 440px;
height,
186px;
overflow: scroll
margin: 1em auto;
padding,
O;
text-align: center;
z-index: 2;
}
#featured-books
.CQvers
position: relative
width, 840px;
z-index: 1;
BiI
el camino del posicionamiento que deseamos realizar para animar las portadas. Por lo
tanto, nuestra primera prioridad ser anular algunos estilos:
r
$ (document) .ready(function()
var spacing = 140;
$('#featured-books')
.css({
'widthr:
spacing * 3,
r height':
166px
roverflow':
hidden
} ) .f ind (,.covers a'). css ({
"f Loa t t : 'none',
'position': 'absolute',
,left " 1000
));
I
1 I
}
#featured-books
a
f Loa t : left;
margin: lOpx
height,
146px;
}
#featured-books
.price
display: none;
var
$covers
$covers.eq(O)
$covers.eq(l)
$covers.eq(2)
})
$('#featured-books
.css('left',
.css('left',
.css('left',
.covers
O);
spacing);
spacing
a');
2);
estndar.
Figura 9.11. Slo tres portadas sin desplazamiento.
&El
9. Rotativos
vez significa que necesitamos mover las portadas a la derecha. De forma similar, cuando se hace die en la portada derecha tendremos que mover las portadas a la izquierda.
Queremos que el carrusel gire, de modo que cuando las imgenes se van por el lado izquierdo, se anexan a la derecha. Para empezar, simplemente cambiaremos las posiciones
de las imgenes sin animacin.
(document) .ready(function()
var spacing = 140;
$('#featured-books')
.css({
'width': spacing * 3,
'height': '166px',
'overflow':
'hidden'
j) . f ind (,.covers a') .css ({
'float':
'none',
'position':
'absolute',
,left': 1000
j);
var
setUpCovers
var $covers
functian()
= $('#featured-hooks
event.preventDefault()
// Imagen derecha;
// desplazarse
hacia la izquierda
(para ver las
$covers.eq(2)
.css('left', spacing * 2)
.click(function(event)
(
$covers.eq(O)
.css('left',
1000);
$covers. eq (O)
.appendTo('#featured-books
.cavers');
setUpCovers();
event.preventDefault()
})
};
setUpCovers()
;
imgenes
a:la derecha).
Hacer die en la imagen #2 lleva a cabo el proceso a la inversa. Esta vez, es #0 el que
se oculta a la vista, y luego se mueve al final de la cola. Esto cambia #1 al puesto #0, #2
al #1, y #3 al #2.
Existen un par de detalles que tenemos que tener en cuenta para evitar anomalas de
interaccin de usuario:
1. Necesitamos invocar .preventDe f aul t () dentro de nuestro manejador el ick,
ya que nosotros hemos convertido todas las portadas en vnculos a la versin ms
grande. Sin esta llamada, el vnculo se seguir y nunca veremos nuestro efecto
de movimiento.
2. Necesitamos quitar el vnculo de todos los manejadores click al principio de
la funcin setUpCovers
(), o podremos acabar con mltiples manejadores
vinculados a la misma imagen a medida que el carrusel rota.
// Imagen central.
$covers.eq(l)
.css('left',
spacing);
})
La nueva funcin setUpCovers () incorpora el cdigo de posicionamiento de imagen que escribimos anteriormente. Al encapsular esto en una funcin, podemos repetir
el poscionamiento de la imagen despus de que se hayan reordenado los elementos;
esto ser importante, como pronto veremos.
En nuestro ejemplo, hay seis imgenes en total (que JavaScript har referencia con
los nmeros a 5), y los nmeros 0, 1, Y 2 son visibles. Cuando se hace clic en imagen
#0, queremos mover todas las imgenes a la derecha en una posicin. Primero movemos imagen #2 fuera del rea visible (con . e s s ( , 1e f t ' , 10 O O ) ), ya que no queremos
que est visible despus del movimiento. Luego, movemos la imagen al final de la lnea
,.. (#5) al principio de la cola (utilizando .prependTo ( ) ). Esto reordena todas las imgenes de modo que cuando se invoca setUpCovers
() de nuevo, el #5 anterior es ahora
#O,#Ose ha convertido en #1, y #1 se ha convertido en #2. El cdigo de posicionamiento
existente en esta funcin es por lo tanto suficiente para mover las portadas a sus nuevas
ubicaciones, como muestra la figura 9.12.
"
.covers a');
$covers.unbind('click') i
// Imagen izquierda;
// desplazarse
a la derecha
(para ver imgenes
a la izquierda).
$covers.eq(O)
.css (,left " O)
.click(function(event)
(
$covers.eq(2)
.css('left',
1000);
$covers.eq($covers.length
- 1)
.prependTo('#featured-books
.covers');
setUpCovers() ;
})
mi
mi
9. Rotativos
podemos aadir una animacin que hace que las portadas se deslicen en lugar de simplemente aparecer en sus nuevas posiciones. Esto requiere una revisin de la funcin
setUpCovers ( ) :
var setUpCovers = function() {
var $covers = $ ('#featured-books
$covers.unbind(lclick
i
.covers a')
1)
/1 Imagen izquierda;
a la izquierda).
lIiII
de portada, debemos aplazar la llamada hasta que la animacin se completa, por lo que
situamos la llamada en la rellamada de la animacin.
Un clic en.la imagen ms a la derecha lleva a cabo un conjunto similar de animaciones, pero al contrario. Esta vez, es la.imagen ms a la izquierda la que se mueva fuera
de la vista, y se debe mover al final de la cola antes de activar setUpCovers () cuando
se completa la animacin. La nueva imagen, ms a la derecha, por el contrario, se debe'
posicionar (spacing * 3) antes de que su animacin pueda empezar.
t,
})
})
1:
a la derecha).
Mostrar
conos
de accin
Nuestro carrusel de imgenes ahora rota sin problemas, pero no hemos proporcionado
ninguna indicacin al usuario de que haciendo clicen las portadas har que se desplacen.
Podemos ayudar al usuario al mostrar los iconos apropiados cuando el ratn pasa por
encima de las imgenes, como muestran las imgenes 9.14 a 9.16. En este caso, situaremos los iconos sobre las imgenes existentes. Al utilizar la propiedad opacity, podemos continuar para ver la portada por debajo cuando se muestra el icono. Utilizaremos
sencillos iconos monocromos para que la portada no sea demasiado obscura.
// Imagen central.
$covers. eq (1)
.css('left', spacing);
};
Cuando se hace die en la imagen izquierda, podemos mover las tres imgenes visibles a la derecha en el ancho de una imagen (reutilizando la variable spacing que
hemos definido anteriormente). Esta parte es sencilla, pero nosotros tambin tenemos
que hacer que la nueva imagen se desplace para situarse a la vista. Para hacer esto, tomamos la imagen del final de la cola, y primero establecemos que su posicin de pantalla
est fuera de la pantalla en el lado izquierdo (- spacing). Luego, lo pasamos a la vista
junto con los otros elementos, como muestra la figura 9.13.
Aunque la animacin se ocupa del movimiento inicial, todava necesitamos cambiar el
orden de la portada al invocar setUpCovers () de nuevo. Sino lo hacemos, el siguiente
clic no funcionar correctamente. Puesto que setUpCovers () cambia las posiciones
_________________________________
.'
~
Figura 9.14. Icono para desplazarse
I
Il
a la izquierda.
a la derecha.
Necesitaremos tres conos, uno para las portadas izquierda y derecha, que el usuario
decidir hacia qu lado desplazarse, y uno para la portada del centro, en el que el usua-
mi
9. Rotativos
lIiD
rio puede hacer clic para una versin ampliada. Podemos crear elementos HTML que
hagan referencia a los conos y almacenarlos en variables para uso posterior:
Ahora, todo lo que tenemos que hacer en nuestros manejadores hover es situar las
imgenes en la ubcacin DOM correcta y mostrarlas.
$leftRollover
= $('<img/>')
.attr('src,
'images/left.gif')
.addClass('control')
.css('opacity',
0.6)
. ess ( 'display I
I none 1) i
var $rightRollover
= $('<img/>')
.attr('src', 'images/right.gif')
.addClass('control')
.css('opacity',0.6)
.css('display',
'none')
var $enlargeRollover
= $('<irng/>')
.attr('src', 'images/enlarge.gif')
.addClass('control')
.css('opacity',
0.6)
.c ss ('display',
"norie t L,
var
var
.,.
})
Puede haber notado una gran cantidad de repeticin aqu. Para miniqUzar este cdigo adicional, podemos situar esto en una funcin que podemos invocar para cada icono
que se necesita crear:
{
$('#featured-books
.CQvers a )
l
.show();
// Imagen derecha;
desplazarse
a la izquierda
$covers.eq(2)
.css(11eft', spacing * 2)
.click(function(event)
(
$covers.eq(O)
.animate({'left':
-spacing},
'fast',
$(this) .appendTo('#featured-books
setUpCovers();
var $leftRollover
= createControl('images/left.gif');
var $rightRollover
= createControl('images/right.gif');
var $enlargeRollover
= createControl('irnagesJenlarge.gif');
})
(para ver
function()
.covers');
En el CSS para la pgina, establecemos que el z - index de estos controles sea mayor
que el de las imgenes, y luego los posicionamos de forma absoluta de modo que puedan solapar las portadas:
#featured-books
.control
position: absolute;
z-index: 3
left: o;
topo o;
// Imagen central
$covers.eq(l)
.css('left',
spacing)
.hover(function()
{
$enlargeRollover.appendTo(this)
}, function () {
$enlargeRollover.hide();
}) ;
};
a la izquierda).
event.preventDefault()
;
}) .hover(function()
{
$leftRo11over.appendTo(this)
}, func tion () {
$leftRollover.hide();
}) ;
function
createControl(src)
return $ (, <img/> 1)
,attr(
"s r c
are)
.addClass('control')
.css('opacity',O.6)
.css('display',
"norie t L:
$covers.unbind('click
mouseenter mouseleave')
// Imagen izquierda; desplazarse a la derecha (para ver imgenes
$covers.eq(O)
.css('left',
O)
.click(function(event)
(
$covers.eq(O)
.animate({'left':
spacing},
'fast');
$covers. eq (1) .animate ({ 'left': spacing * 2), 'fast');
$covers. eq (2) .animate ({ 'left': spacing * 3), 'fast');
$covers.eq($covers.length
- 1)
.css( 'left', -spacing)
.animate ({ 'left ': O), 'fast', function () (
$(this) .prependTo('#featured-books
.covers');
setUpCovers()
;
= function()
setUpCovers
var $covers
.show();
imgenes
a la derecha)
DI
9. Rotativos
Igual que hicimos anteriormente con el iek, desvinculamos los manejadores mouseenter y mouseleave al principio de setUpcovers () de modo que los comportamientos de pasar por encima no se acumulen. Aqu, utilizamos otra caracterstica del mtodo
. unb ind ( ) :manejadores para mltiples tipos de evento se pueden desvincular a la vez
al separar los nombres de tipos de evento con espacios.
Por qu mouseenter y mouseleave? Cuando invocamos el mtodo. hover (),
internamente jQuery traduce esto en dos vinculaciones de evento separadas. La primera
funcin que proporcionamos se vincula como un manejador para el evento mouseenter,
y la segunda se vincula a mouseleave. Por lo tanto, para eliminar los manejadores vinculados utilizando. hover (), necesitamos desvincular mouseenter y mouseleave.
Ahora cuando el cursor del ratn est sobre una portada, la imagen rollover apropiada
est superpuesta sobre la parte superior de la portada, como muestra la figura 9.17.
Aplicaremos un conjunto de reglas de estilo a esta nueva das e que son similares a
las que hemos-visto antes:
'
irng.enlarged ~
position: 'absc Lut e ,
z-index: Si
cursar: pointer
Este posicionamiento absoluto permitir que la portada flote sobre las otras imgenes
que hemos posicionado, porque el z - index es mayor que los que ya hemos utilizado.
Ahora necesitamos posicionar la imagen ampliada cuando se hace clic en la imagen del
centro en el carrusel:
/1 Imagen central; ampliar portada.
$eovers.eq(l)
.css('left', spacing)
.eliek(funetion(event)
(
$enlargedCover.attr('sre'.
"
Figura 9.17.
Ampliar imagen
Ahora, nuestra galera de imgenes es totalmente funcional, con un carrusel que permite al usuario navegar hasta la imagen deseada. Un clic en la imagen central lleva a
una vista ampliada de la portada en cuestin. Pero, podemos hacer mucho ms con esta
funcionalidad de ampliacin de imagen.
En lugar de llevar al usuario a una URL diferente cuando se hace die en la imagen
del centro, podemos superponer la portada del libro ampliado sobre la propia pgina.
lImI
$(this) .attr('href'))
.ess({
'left', ($('body') .width() - 360) / 2,
'top' , 100,
'width', 360,
'height', 444
}) .show ();
event.preventDefault()
;
})
.hover(function()
(
$enlargeRollover.appendTo(this)
.show();
}, funetion() (
$enlargeRollover.hide();
}l;
I )
!'~"';'
lIlII
9. Rotativos
- 360) /2,
})
.show()
.one('click', function() {
$enlargedCover.fadeOut();
event.preventDefault()
})
.hover(function()
(
$enlargeRollover.appendTo(this)
}, function () (
$enlargeRollover.hide() ;
})
.show();
Cuando se hace clic en la portada central, y se muestra la portada ampliada, necesitamos posicionar y mostrar el botn:
.'
$closeButton.css({
'left': ($('body') .width()
"t.op ' : 100
}) .show() ;
Learning JQuery
!!Ol>lII_l1ollIIcI
--
_.""
.~!~~L_ ....
<S.We1
lOu!rt.com alC!Btdnkln
""'pal:<>oatIng-,
Forums. PortaIa, and
CommunJtyWebsltes
""""""" ""'oa:oocot
__
._
...
_.J
Rocont_
Cr9atI~yourMySQI..
0Btsbase: PractIcal DesIgn
T1ps and TechnlQUeS
I!!-~.
- 360) / 2,
Las coordenadas del botn Cerrar son idnticas a las de la portada ampliada, por lo que
sus esquinas superior-izquierda estn alineadas, como se muestra en la figura 9.19.
YourCUt
Bulcllng TeIephony
Systems Wlth Ast8l1sk
lIiiI
"""---"""(
<
..
l.oremlpst.rnOOloteHa:
dofota magna BIIqua. lit enIm lid rnInIm venlam; q.M nostrucI tOOiIdbibUtuaamco
/8bOiIsnlilutalqulp ex
ea oommodo conseqUlI. DulI sute ln.Ite dolor In repn;Ihendertt ti vaIuptate veHt esse IIum dOOre eu
l'uglat nUlIa partatur. EXceptour aInt oooaocet cupldatat non ptOIdent, sunt In CUlpa quI o1'fIcta deserunt
moIItan/mldestl8borum.
Utilizamos el mtodo. one () para vincular este manejador el iek, que elude un
par de problemas potenciales. Con un . bind () regular del manejador, el usuario podra hacer clic en la imagen de nuevo a medida que se desvanece. Esto podra hacer
que el manejador se activara de nuevo. Tambin, puesto que estamos reutilizando el
mismo elemento de imagen cada vez que se ampla la portada, la vinculacin ocurrir
lI!IlI
9. Rotativos
,,
- 360) / 2,
})
show ()
one ('click', function () (
$closeButton.unbind('click')
$enlargedCover.fadeOut()
,
]l;
$closeButton
css ({
'left', ($('body') .width()
'top' , 100
lI!IiI
contenido textual en lugar de una imagen. Una vez ms, creamos un elemento de instancia nica al principio de nuestro cdigo JavaScript:
I
Puesto que el precio ser parcialmente transparente, un contraste alto entre el color
de fuente y el fondo funcionar mejor:
$(this) .attr('href'
.hide();
- 360) / 2,
})
show ()
.click(function()
{
$enlargedCover.click();
}) ;
.enlarged-price
(
background-color,
#373c40,
color, #fff,
width, 80px,
padding, Spx,
font-size: 18px;
font-weight, bold,
text-align, right,
position: absolute;
z-index: 6;
Antes de poder mostrar la etiqueta del precio, necesitamos completarlo con la informacin de precio real del HTML. Dentro del manejador eliek de la portada del centro,
la palabra clave this hace referencia al elemento de vnculo. Puesto que el precio est
en un elemento apan dentro del vnculo, obtener el texto es sencillo:
var price
event.preventDefault(),
)
.hover(function()
$enlargeRollover.appendTo(this)
}, function() (
$enlargeRollover
.show(),
hide(),
$priceBadge.css({
,right " ($ ("body ') .width () - 360) / 2,
'top' , 100
) .text (price) .show ();
lIl!I
9. Rotativos
un mtodo abreviado. El mtodo. offset () devuelve un objeto que contiene las coordenadas 1eft y top de un elemento relativo a la pgina. Luego podemos insertar el
width y height de la imagen en este objeto, y tener la informacin de posicin contenida en un paquete.
var startPos
startPos.width
startPos.height
$closeButton.unbind('click')
$prkeBadge.hide()
;
$enlargedCover.fadeOut()
;
}l;
r
$closeButton
.css ({
'1eft': endPoB.left,
'top' : endPos.top
$(this) .offset();
$(this) .width();
= $(this) .height();
IDI
.hide();
})
show ()
.click(function()
$enlargedCover.click()
}) ;
$priceBadge
css ({
'right': endPoB.left,
'top' : endPos.top
,..
})
.text(price)
show() ;
"
})
Observe que el botn Cerrar y la etiqueta de precio no se pueden situar hasta que la
animacin se completa, por lo que hemos movido su cdigo a una rellamada del mtodo
.an imat.e () . Tambin hemos aprovechado esta oportunidad para simplificar las llamadas . css () para estos elementos al reutilizar la informacin de posicin que hemos
calculado para la portada ampliada. Ahora tenemos una transicin suavizada de portada
pequea a grande, como muestra la serie de imgenes en las figuras 9.21 a 9.24:
($('body')
* 3;
* 3;
.width()
- endPos.width)
/ 2;
Ahora podemos utilizar estos dos objetos como mapas de atributos CSS, que se pueden pasar a mtodos como. css () y . animate () .
$enlargedcover.attr('src',
.caa(atartPoa)
.show ()
,animate(endPoB,
$enlargedCover
$(this) .attr('href'))
'normal',
.one('click',
function()
function()
Paso 1.
IJEI
AprendejQuery
9. Rotativos
1.3
ED
,/
utl
Figura 9.24. Transicin.
Paso 4.
Nuestra animacin funciona bien, pero depende de una conexin rpida al sitio. Si la
portada ampliada tarda algo de tiempo en cargarse, entonces los primeros momentos de
la animacin podran mostrar la X roja indicando una imagen rota, o seguir mostrando
la imagen anterior. Podemos hacer la transicin un poco ms elegante al esperar hasta
que la imagen se ha cargado por completo antes de iniciar la animacin:
$enlargedCover.attr('src'.
.css(startPos)
.show ();
$(this) .attr('href'))
})
$closeButton
.css({
'left': endPos.left,
'top' : endPos.top
met, consectetur adlplslclng ell1,sed do elusmod tempor InoIdldunt ut la
t enlm ad mlnlm venlam, quls nostrud exercllatlon uUamco !abono nlsl
utl
}l
.show()
.click(function()
mi
9. Rotativos
$enlargedCover.click()
}) ;
$priceBadge
.css ((
right ,: endPos.left,
'tap' : endPos.top
})
.text(price)
.show ();
&11
los titulares de noticias, deberamos proporcionar una indicacin al usuario de que est
ocurriendo cierta actividad al mostrar un indicador de carga entre tando.
El indicador ser otra imagen de instancia nica que se mostrar cuando sea apropiado:
r
var $waitThrobber = $('<irng/>')
.attr('src', timages/wait.gif')
.addClass('control')
.css('z-index',
4)
.hide o .
Para esta imagen, estamos utilizando un GIF animado, porque el movimiento reforzar
". al usuario de que la actividad se est llevando a cabo, como muestran la figura 9.25.
}) ;
};
if ($enlargedCover[O] .complete)
performAnimation();
}
else {
$enlargedCover.bind(lload',
performAnimation);
Hay dos casos que tenemos que considerar: la imagen est disponible casi instantneamente (quiz debido a guardado en cach), o necesita tiempo para cargarse. En la
primera situacin, el atributo complete de la imagen ser true, por lo que podemos
invocar nuestra funcin performAnimation
() inmediatamente. En el segundo caso,
tenemos que esperar a que se complete la carga de la imagen antes de llamar a performAnimation (). ste es un caso extrao en el que el evento load DOM estndar es de
ms utilidad para nosotros que el evento ready personalizado de jQuery. Puesto que"
load se activa en una ventana, imagen, o marco cuando todos sus contenidos se han
cargado por completo, podemos observar el evento para aseguramos de que la imagen
se muestra correctamente. Solamente entonces se ejecuta el manejador, y se lleva a cabo
la animacin.
Paso 3
Paso 2
Paso 1
Figura
Solamente llevar dos lneas situar nuestro indicador de carga en su lugar, ahora
que tenemos el elemento definido. Al principio de nuestro manejador de click para
la imagen central, antes de empezar a hacer cualquier trabajo, necesitamos mostrar el
indicador:
$waitThrobber.appendTo(this)
.show();
$waitThrobber.hide()
Esto es todo lo que se necesita para marcar la portada que se ampla con el indicador
de carga. La animacin aprece superpuesta en la esquina superior izquierda de la portada, como muestra la figura 9.26.
,. ""O . lile
w.w' (.~.
o>
([)
"'\iii
Paso 4
tre.
!'
,
~?
mil
9. Rotativos
El cdigo terminado
.css('left', -spacing)
animate ({ ,left ': o}, 'fast', function
$(this) .prependTo('#featured-books
Este cdigo representa solamente una pequea fraccin de lo que se puede hacer en
la Web con imagen animada y rotativos de texto. Todo junto, el cdigo es:
$ (document) . ready(function()
var spacing = 140
function createControl(src)
return $ (' <irng/>')
.attr{'src',
src)
.addClass('control')
.css('opacity',
0.6)
.ess ('display',
'nane')
})
$leftRollover
= createControl('images/left.gif');
$rightRollover
= createControl('images/right.gif');
$enlargeRollover
= createControl('images/enlarge.gif');
$enlargedCover
= $('<img/>')
.addClass('enlarged')
.hide()
appendTo (,body ') ;
var $closeButton
= createControl('images/close.gif')
.addClass('enlarged-control')
appendTo (,body ') ;
var $priceBadge
= $('<div/>')
.addClass('enlarged-price')
.css('opacity',O.6)
ess ( 'display',
'none
.appendTo('body')
;
var $waitThrobber
= $('<img/>')
.attr('src', 'images/wait.gif')
.addClass('control')
.css('z-index',
4)
.hide() ;
$ ('#featured-books')
.css({
'width': spacing * 3,
'height':
'166px',
'overflow':
'hidden'
find (,.covers a') .css ((
'float':
'none',
'position':
'absolute',
'left': 1000
derecha;
desplazarse
a izquierda
(para ver
imgenes
function ()
.covers');
});
$covers. eq (1) .animate ({ ,left ': O}, 'fast');
$covers.eq(2)
.animate({ 'left': spacing},
'fast');
$covers.eq(3)
.css('left', spacing * 3)
animate ({ ,left': spacing 2},
'fast');
event.preventDefault()
;
}) .hover(function()
(
$rightRollover.
appendTo (this) .show() ;
}, function()
(
$rightRollover.hide()
setUpCovers
= function() {
var $covers = $('#featured-books
.CQvera a') i
$covers.unbind('click
mouseenter
mouseleave') ;
// Imagen izquierda;
desplazarse
a derecha
(para ver imgenes
$covers.eq(O)
.css (,left', O)
.click(function(event)
(
$covers.eq(O)
.animate({'left':
spacing} , fast ');
$covers. eq (1) .animate ({ 'left' : spacing * 2}, 'fast');
$covers.eq(2)
.animate({'left':
spacing * 3}, 'fast');
$covers.eq($covers.length
- 1)
.show();
setUpCovers();
});
// Imagen
central;
ampliar
;
portada
$covers.eq(l)
.css('left',
spacing)
.click(function(event)
(
$waitThrobber.
appendTo (this) .show() ;
var price = $(this) .find(' .price') .text();
var startPos
= $(this) .offset();
startPos.width
= $(this) .width();
startPos.height
= $(this) .height();
var endPos = {};
endPos.width
= startPos.width
endPos.height
= startPos.height
endPos.top
= 100;
endPos.left
= ($('body')
$enlargedCover.attr('src',
var
C>,
$covers.eq(2)
.css('left', spacing * 2)
.click(function(event)
(
$covers. eq (O)
animate ({ 'left': -spacing},
'fast',
$(this) .appendTo('#featured-books
})
();
// Imagen
() (
.covers');
}) .hover (function () (
$leftRollover.appendTo(this)
}, function()
(
$leftRollover.hide()
;
var
var
var
var
setUpCovers()
});
event.preventDefault
a la izquierda).
lIfI
.css(startPos)
.show() ;
var performAnimation
$waitThrobber.hide()
3;
3;
.width()
- endPos.width)
$(this) .attr('href'))
function()
;
function()
(
.hide();
/ 2;
a la derecha)
~~~l'"
BIlI
9. Rotativos
/
}) ;
$closeButton
.css ({
'left': endPos.left,
'top' : endPos.top
.show ()
.click(function()
(
$enlargedCover.click()
j);
$priceBadge
.css ({
1 right ,: endPos.left,
Itop' : endPos.top
j)
})
.text(price)
.show () ;
},
if ($enlargedCover[O]
performAnimation()
.complete)
,
}
else (
$enlargedCover.bind('load',
performAnimation);
}
event.preventDefault()
j)
.hover(function()
(
$enlargeRollover
appendTo(this)
l, function() (
$enlargeRollover.hide()
,
})
.show(),
},
})
setUpCovers()
Resumen
En este captulo, hemos examinado los elementos de pgina que cambian en el tiempo, por s mismos o en respuesta a una intervencin del usuario. Estos rotativos pueden
diferenciar una presencia Web moderna de sitios diseados de forma tradicional. Hemos
tratado la presentacin de un feed XML de informacin en una pgina, al igual que rotar
elementos en y fuera de la vista en intervalos de tiempo. Adems de mostrar un conjunto de imgenes en una galera al estilo de un carrusel por la que se puede desplazar,
tambin hemos tratado ampliar una imagen para un primer plano con una animacin
suavizada y presentar controles de interfaz de usuario de una forma discreta.
Estas tcnicas se 'pueden combinar de muchas formas para dar vida a pginas que
de otra forma seran aburridas, a la vez que mejorar simultneamente la usabilidad de
nuestras aplicaciones basadas en Web. Las animaciones y efectos que seran tediosos de
conseguir de otra forma se podran realizar sin esfuerzo gracias al potencial de jQuery.
,,
~~"
'~.
\.":.:1
,.,
..' . /.-"'"
.~"
tr: .
<>
~
~
,
,&,.
'{:-."
.. ~--
....
10? "
'l;;f'"
~...-.,
.~
.'0, ~
\. ,6
~'"
,......
'C'
..."...\. _. '"
.....,'0 ..\
'd13""
___
, r.;
'. "'.
~).
.-'--.
. . ........
>$l'
----:-~ (' (9)"
'..
\./
._."
\
~f.. '
15"
.' \
_...
(J'
__
@'
1')
'0"
~
@ \\
"1'f.,""@'
IJ!.
o ~...
"
j<"' ":!.I
r@
<-,
,---~'
@1@-
"SI
~,.~....;',
~.
-,;,:.'~
,~, O"I!!J .,..,
. -r-,
"
.-....
,.'',,"'
r>~l
-.~
f~~'
,~ ..~.
~..,
~<>
//@
/<....,
@
-l
..
.~.-.:
~'V~._'
"\
'
.. _
(@J
O \ ~,--
"
10
Utilizar plug-ins
A lo largo de este libro, hemos examinado muchas de las formas en que se puede utilizar la librera jQuery para realizar una amplia variedad de tareas. An as, un aspecto
que ha quedado relativamente sin explorar es la ampliabilidad de jQuery. Tan potente
como su librera base, su elegante arquitectura de plug-in ha permitido a desarrol1adores
ampliar jQuery, haciendo que sea una librera an ms rica en caractersticas.
La creciente comunidad jQuery ha creado cientos de plug-ins, desde pequeos selectores de ayuda a widgets de interfaz de usuario a gran escala. Ya hemos tratado el
potencial de plug-ns y creado uno sencillo en un captulo anterior. En este captulo, examinamos cmo encontrar plug-ins desarrollados por otros e incorporarlos en nuestras
pginas Web. Exploraremos el popular plug-n Form y la librera oficial de plug-ins de
interfaz de usuario jQuery, y luego listaremos y describiremos brevemente una serie de
otros plug-ins populares "recomendados por el autor".
lEfI
El plug-in Forrn
El plug-in Form es un extraordinario ejemplo de un script que convierte una tarea difcil Ycompleja en algo terriblemente sencillo. El archivo plug-in, junto con la documentacin detallada, se encuentra disponible en http://malsup/com/jquery/form/.
Como base del plug-in se encuentra el mtodo. aj axForm () . Convertir un formulario convencional en un formulario AJAX requiere una sencilla lnea de cdigo:
r'
1m
$ (document) .ready(function()
$ (/ #myForm/) .ajaxForm ();
});
Este ejemplo preparar < form id=" myForm" > para enviarse sin tener que refrescar
la pgina actuaL Esta caracterstica es en s misma bastante atractiva, pero el verdadero
- potencial viene con el mapa de opciones que pasamos al mtodo. Por ejemplo, el siguiente
cdigo invoca. aj axForm () con las opciones target, beforeSubmi t, y success:
<head>
<meta
http-equiv="Content-Typel!
content=lItext/html
charset=utf-Sn/>
type=l1text/javascriptll><!script>
<script
src="jquery.js"
<script
src="jquery.plugin.jsll
$ (document) .ready(function()
{
function va1idateForm()
{
// el cdigo de validacin
//
</head>
beforeSubmit:
$ (document) .ready(function()
$ (/#myID/) .someP1ugin();
;
true
message:
})
/This p1ugin
});
La sintaxis de los plug-ins jQuery es, tpicamente, bastante similar a la sintaxis de los
mtodos dentro del propio jQuery. Ahora que hemos visto cmo incluir un plug-in en
una pgina Web, echemos un vistazo a algunos de los ms populares.
de formulario
para
abortar
el
ira aqu
envo
validateForrn,
success: function() {
a1ert(/Thanks
for your commenti/);
})
La opcin target indica el elemento, en este caso, un elemento con Ld " log", que
se actualizar por la respuesta del servidor.
La opcin beforeSubmit
lleva a cabo tareas antes de enviar el formulario. Aqu,
hace referencia a la funcin validateForm
() . Si la funcin devuelve false, el formulario no se enviar.
La opcin success lleva a cabo tareas despus de que el formulario se enva con xito.
En este ejemplo simplemente proporciona un mensaje de alerta para permitir al usuario
saber que el formulario se ha enviado. Otras opciones disponibles con. aj axForm () y
el similar. aj axSubmi t () incluyen:
url: La URL al que se enviarn los datos de formulario, si es diferente del atributo
action del formulario.
type: El mtodo utilizado para enviar el formulario, GETo POST.El predeterminado es el atributo method del formulario, o si no se facilita ninguno, GET.
is greati/
false
$ (/#test-form/) .ajaxForm({
target: /#log/,
<title>Example<!title>
devolver
};
type=lItext/javascriptll></script>
<script
src=!tcustorn.jsll type=lltext/javascript"></script>
})
podemos
mil
IPD
El plug-in Form proporciona una serie de otros mtodos para ayudar a gestionar
formularios y sus datos. Para un anlisis ms detallado de estos mtodos, as como ms
demos y ejemplos, visite http://www.malsup.com/jquery/form/.
alert(responseText)
j):
j);
,1
Consejos
trucos
El mtodo. aj axForm () es a menudo ms apropiado que el mtodo . aj axSubmit ( ) , a expensas de poca flexibilidad. Cuando queremos que el plug-in gestione todas
las vinculaciones de evento por nosotros, as como invocar el mtodo. aj axSubmi t ( )
por nosotros en el momento apropiado, deberamos utilizar. aj axFOl;m() . Cuando
deseamos control ms detallado sobre la gestin del evento submi t, ~e recomienda,
. ajaxSubmit ().
Tanto. aj axForm () como. aj axSubmi t () por defecto pasan a utilizar los valores action y method en el cdigo del formulario. Siempre y cuando utilicemos cdigo
apropiado para el formulario, el plug-in funcionar exactamente como esperamos sin
ninguna necesidad de modificacin. Como beneficio aadido, automticamente adquirimos las ventajas de mejora progresiva; el formulario es totalmente funcional sin
JavaScript habilitado.
.
Normalmente cuando se enva un formulario, si el elemento utilizado para enviar el
formulario tiene un nombre, sus atributos name y val ue se envan junto con el resto de
los datos de formulario. El mtodo. aj axForm () es proactivo en este sentido, aadiendo manejadores click a todos los elementos <input t ype " submit" > de modo que
sabe cul envi el formulario. Elmtodo . a j axSubmi t ( ) r por otro lado, es reactivo y no
tiene forma de determinar esta informacin. No captura el elemento que enva. La misma
distincin se aplica a elementos <input t.ype " image" > tambin: .-aj axForm () los
gestiona, mientras que . a j axSubmi t () los ignora.
A menos que se suba un archivo como parte del envo del formulario, los mtodos
. a j axForm () y . a j axSubmi t () pasan su argumento opt ions al mtodo $ . a j ax ( )
que es parte de jQuery. Por lo tanto, cualquier opcin vlida para $ . aj ax () se puede
pasar por medio del plug-in Form. Con esta caracterstica en mente, podemos hacer que
las respuestas de nuestro formulario AJAXsean an ms robustas, de esta forma:
$ (document) .ready(function()
$ (#myForm) .ajaxForm({
timeout: 2000,
error: function
(xml, status,
alert(e.message)
:
}
}) :
}):
Aunque el plug-in Form realiza una cosa, y lo realiza bien, jQuery UI realiza una
amplia variedad de cosas (y las hace bien). De hecho, jQuery UI no es tanto un plug-in,
sino una biblioteca completa de plug-ins.
Dirigido por Paul Bakaus, el equipo jQuery DI ha creado una serie de componentes
bsicos de interaccin y widgets completos para ayudar a que la experiencia Web sea
ms como la de una aplicacin de escritorio. Los componentes de interaccin incluyen
mtodos para arrastrar, soltar, ordenar y cambiar elementos de tamao. El conjunto actual de widgets incluye un men con efecto acorden, un selector de fecha, un cuadro
de dilogo, un deslizador, y pestaas, con algunos ms en desarrollo. Adems, jQuery
UI proporciona un amplio conjunto de efectos avanzados para complementar las animaciones principales jQuery.
Puesto que la librera UI completa es demasiado extensa para tratarla adecuadamente
en este captulo, limitaremos nuestra exploracin a efectos UI, el componente de interaccin Sortable (para ordenar lista de elementos), y el widget Dialog (para cuadro de
dilogo). Las descargas, documentacin y demos de todos los mdulos jQuery se encuentran disponibles en http://ui.jquery
. com/.
Efectos
El mdulo Efectos de jQuery DI viene con un archivo y un conjunto de archivos de
efectos individuales. El archivo principal proporciona animaciones para colores y clases,
as como aceleracin y desaceleracin avanzada.
Animaciones
e)
de color
Con el archivo de efectos principal referenciado en el documento, el mtodo. animate () se ampla para aceptar propiedades de estilo adicionales, como borderTopColor,
backgroundColor,
y color. Por ejemplo, ahora podemos cambiar gradualmente un
elemento de texto negro sobre fondo blanco a texto blanco sobre fondo negro:
IEI
',lO,
,)"",
,,'\"
"'r' '.
o bien, se puede
$ (document) .ready(function()
$ (/#mydiv/) .animate({
color, I#fff/.
backgroundColor,
1#0001
}./slow/);
j);
ID
$ (document) .ready(function()
{
$ (/#mydiv/) .animate({
color, .1#fff/.
backgroundColor,
1#0001
}. {
duration: /slow/,
easing: /easelnQuart/
}) ;
})
El elemento se muestra exactamente como debera, con el texto en su camino a convertirse en blanco y el color de fondo acercndose a negro.
Animaciones
Efectos adicionales
Los archivos de efectos individuales aaden varias transiciones, que se pueden implementar con el mtodo. effect () y algunas de las cules amplan la funcionalidad
de los mtodos de jQuery . show (), . hide (), y . toggle () tambin. Por ejemplo, el
efecto explode, que oculta elementos al ampliarlos en un nmero dado de piezas, se
puede conseguir con el mtodo. effect () :
$ (document) .ready(function()
(
$U#explode/)
.effectUexplode/.
}) ;
de clase
Los tres mtodos de clase con los que hemos trabajado en captulos anteriores
(. addClass (), . removeClass (), y . toggleClass
()) ahora toman un segundo argumento opcional para la duracin de la animacin. Podemos escribirlos como
.addClass {/highlight/,
/fast/}
o .removeClass {/highlight/,
/slow/}
o . toggleClass
{/highlight,
1000}.
{pieces:
16}.
800);
{pieces:
16}.
800);
Aceleracin
desaceleracin
avanzada
Las funciones avanzadas de aceleracin y desaceleracin varan l,avelocidad y distancia a las que ocurren las transiciones en varios puntos en el transcurso. Por ejemplo,
la funcin easelnQuart
termina una animacin a cuatro veces la velocidad a la que
empez. Podemos especificar una funcin personalizada de aceleracin y desaceleracin
en cualquiera de los mtodos principales de animacin jQuery o los mtodos de efecto jQuery VI. Esto se puede realizar al aadir un argumento o aadir una opcin a un
mapa de opciones, dependiendo de la sintaxis que se utiliza. Por ejemplo, especificar la
funcin easelnQuart
para nuestra animacin de color anterior se puede realizar con
un argumento adicional:
$ (document) .ready(function()
$ (/#mydiv/) .animate({
color, I#fff/.
backgroundColor:
1#0001
}, Islow/,
leaselnQuart/);
})
[J
Figura 10.2. Ocultar un elemento.
Componentes de interaccin
Entre los componentes de interaccin de jQuery VI est Sortable (para ordenar lista
de elementos), que puede transformar casi cualquier grupo de elementos en una lista de
arrastrar y soltar. En la figura 10.4, tenemos una lista no ordenada con algunos estilos
CSS aplicados a cada elemento.
,rr-r,oi"!
mil
ID
"
Podemos mejorar la interaccin de usuario al aadir opciones al mtodo. sortable () . Aunque este mtodo tiene cerca de treinta opciones disponibles, utilizaremos
unas pocas para nuestro ejemplo:
$ (document) .ready(function()
(
$ (/#sort-container!)
.sortable
opacity:
. s,
cursar: /move/,
axis, !y!
({
});
})
Las dos primeras opciones, opaci ty y cursor, se explican por s mismas. La tercera, axis, limita el movimiento del elemento a un eje determinado (en este caso, el eje y)
mientras que se ordena, como muestra la figura 10.6.
Ahora, para que la lista se pueda ordenar, simplemente escribimos el siguiente cdigo:
$ (document) .ready(function()
(
$ (!#sort-container!)
.sortable();
})
.sortablei),
ElI
mi
Como es evidente por el color de fondo ms claro del elemento ordenado, tambin
nos hemos aprovechado de una clase que se le aplica automticamente, ui - sortablehelper, al aplicar estilos a la clase en nuestra hoja de estilo.
Para ms informacin sobre todos los componentes de interaccin jQuery UT, visite
http://docs.jquery.com/UI#Interaction.
MyDlalog
Widgets
Adems de los componentes de construccin, jQuery DI incluye un conjunto de robustos widgets de interfaz de usuario que funcionan como los elementos que estamos
acostumbrados a ver en aplicaciones de escritorio. El widget Dialog, por ejemplo, utiliza
los componentes de arrastrar y cambiar de tamao para producir un cuadro de dilogo,
de modo que no tenemos que crear el nuestro.
Como con otros widgets de interfaz de usuario, Dialog acepta un gran nmero de
opciones. Su mtodo denominado. dialog () tambin puede tomar argumentos de
cadena que alteran lo que hace el cuadro de dilogo. En su nivel ms bsico, el mtodo . dialog () convierte un elemento existente en un cuadro de dilogo y lo muestra,
junto con los contenidos del elemento. Por ejemplo, podemos empezar con una sencilla
estructura <di v ,
<div id="dlg">My
Dialog</div>
Como era de esperar, este <di v parece bastante sencillo;un sencillobloque de texto,
como muestra la figura 10.7.
My rnalog
Podemos invocar el cuadro de dilogo bsico en nuestro archivo J avaScript tan pronto como el DOM est listo.
- ,.
$ (document) .ready(function()
$(/#dlg/) .dialog();
j);
My Dialog
,f.
Ahora, las diferentes reas estn claramente indicadas, y el cursor del ratn cambia
para proporcionar incluso ms feedback visual en las partes del cuadro de dilogo habilitadas para arrastrar y cambiar de tamao. Como con los otros mtodos jQuery DI,
. dialog () viene con un nmero de opciones. Algunas de las opciones afectan la apariencia del cuadro de dilogo mientras que otras permiten que los eventos se activen:
$ (document) .ready(function()
var $dlg = $ (/#dlg/) ;
var dlgText
= $dlg.text();
$dlg.dialog({
autoOpen: false
title: dlgText,
open: function()
$dlg.empty()
;
).
buttons:
(
/add message/:
function()
$dlg.append(/<p>Inserted
).
/erase messages/:
function()
$(/p/, $dlg) .remove();
)
})
$ (/#do-dialog/)
.click(function()
$dlg.dialog(/open/)
;
j);
})
(
message</p>/)
lIi!I
Hemos configurado el cuadro de dilogo para que est oculto inicialmente y se abra
cuando el usuario haga clic en un botn con id= "do-dialog".
Tambin hemos movido
el contenido de texto inicial del cuadro de dilogo al rea de ttulo y aadido dos botones,
uno con add message (aadir mensaje) como su texto y otro con erase messages (eliminar
mensajes) como su texto. Cada botn tiene una funcin asociada para anexar o eliminar
prrafos cuando se hace die. Despus de hacer clic en el botn de aadir mensaje tres
veces, el cuadro de dilogo con estas opciones se parece a la figura 10.10.
IDI
SUdor
!&C=
Oatepick.er
;~~~:;~~
Su
No
Tu
w.
Th
Fr
$a
Inserted message
[nsertecf
message
Inserted
message
..~;;-~~']~
~r~~~~~~~~
Icrem Ipsum dolor sit: .met, consedlllur odipisidng elit. sed do
eiu.mod tempof' Inddldunt ut labore et dolore magna afiqua. ut
enim ad mlntm venlam, qull nostrvd exercltation ull.mea
laborla ni" ut allqulp ex ee c:ommodo COt1sequat.
,a
.'
P1ogreosbar
H;ghtightl Em>'
o H.yl
Las otras opciones para configurar la visualizacin y comportamiento de los cuadros de dilogo se puede encontrar en http://does.j
query. com/UI/Dialog/
dialog#options.
Framewol'i<
loon8
(content
color
Sampkt ut-state-highlight
ayle.
praview)
[ A
AJe"1 Sample
ut-stetilH!lTor
styIe.
ThemeRoller
Una reciente incorporacin a la librera jQuery VI es ThemeRoller, un motor temtico
interactivo basado en Web para widgets VI (vase figura 10.11). ThemeRoller facilita la
creacin de elementos altamente personalizables, de aspecto profesional. Como hemos
indicado, el cuadro de dilogo que acabamos de crear tiene aplicado el tema predeterminado; este tema se mostrar desde ThemeRoller si no se proporcionan parmetros
personalizados.
,.
Generar un conjunto completamente diferente de estilos es cuestin de visitar ht tp : / /
ui . j query . com/ themeroller
/, modificar las varias opciones segn se desee, y pulsar
el botn Download This Theme (Descargar esta temtica). Un archivo. z ip de hojas de
estilo e imgenes luego se puede situar en el directorio apropiado. Por ejemplo, al elegir
algunos colores y texturas diferentes, podemos cambiar en unos minutos nuestro cuadro
de dilogo anterior para que se parezca a lo que muestra la figura 10.12.
Formularios
Hemos investigado algunas formas de manipular formularios en un captulo anterior.
Estos plug-ins pueden realizar tareas relacionadas con facilidad.
http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete
http://plugins.jquery.com/projeet/autoeompletex
mil
Escrito por el desarrollador jQuery [orn Zaefferer, el plug-in Autocomplete proporciona una lista de coincidencias posibles a medida que el usuario escribe en una entrada
de texto, como muestra la figura 10.13.
Month (local):
Danvllle
dolor si! amel, oonsectetuer adipiscing eli!, sed diam nonummy nibh
Hidden input
Single City (contana):
Ed~pl
E-Mail (local):
Single Bird (remate):
De Graff
/'
,oolor
Deflanee
SI'
XJUZij",J&&lL
Deerfteld
.;
Lorem ipsum dolor sil amel, oonsecteluer adipiscing slil, sed diam nonumm
.'
Validation
http://bassistance.de/jquery-plugins/jquery-plugin-validation
http://plugins.jquery_com/project/validate
Otro plug-in de J6m Zaefferer, Validation es una herramienta enormemente flexible para validar entrada de datos de formulario basado en un amplio rango de criterios
(vase figura 10.14).
a complete
fonn
Firstname
Lastname
:1
Username
Password
Masked input
http://digitalbush.com/projects/masked-input-plugin/
http://plugins.jquery.com/project/maskedinput
El plug-in Masked Input (vase la figura 10.16) ofrece una forma para que los usuarios incorporen datos de forma ms fcil, como fechas, nmeros de telfono, o nmeros
de la seguridad social, en un determinado formato. Sita automtieamente
ciertos caracteres (como una barra inclinada para las fechas) en el campo mientras permite que
se incorpore solamente un determinado conjunto de caracteres, segn se determina en
las opciones del plug-in.
The following example is a dernonstratlon from the usage tab.
Confirm
Phone
"
Tax ID
passwotd
Email
!!Iease agree to
SSN
muerer
Validating
lSiI
C!ur policy
W04-----1
L_. .
I
c=
99199/9999
J (999) 999-9999
] 99-9999999
I 999-99-9999
Product Key
L.....m_=:=J a'-999-a999
Eye Script
::::J
Tablas
jeditable
http://www.appelsiini.net/projects/jeditable
http://plugins. jquery. com/proj ect/j edi table
En un captulo anterior, hemos tratado tcnicas para organizar y mejorar datos tabulares. Muchos desarrolladores de plug-in han agrupado rutinas para ayudamos en
estas tareas.
~F'i
ID
Tablesorter
Flexigrid
http://code.google.com/p/flexigrid/
http://ptugins
. jquery. com/project/flexigrid
'~
Como jqGrid, Flexigrid es un plug-in de cuadrcula con todas las caractersticas.
Algunos de stas incluyen soporte JSON,paginacin, bsqueda rpida, mostrar y ocultar y cambiar el tamao de columnas, y ordenar filas (vase la figura 10.19).
http://tablesorter.com/
http://plugins.jquery.com/project/tablesorter
El plug-in Tablesorter (vase la figura 10.17)puede convertir cualquier tabla con elementos < t.he ad y < t body en una tabla que se puede ordenar sin refrescar la pgina.
Lascaractersticas especialesincluyen ordenar por mltiples columnas, analizadores para
ordenar muchos formatos diferentes (por ejemplo, fecha, hora, moneda, URL), ordenacin secundaria "oculta",y ampliabilidad por medio de un sistema de widgets.
Liiot
tIam
'c';"-~-'[_[~;;;'-"'''~-~'''I:--''''i<;['~I!DIIIi;<;:t
1lI~;"-,"-~",_......
-.!ih~~
)1:
..
/;:.r.l~.;~~~'1>~...I~~w~~,:..'~1.'\'(
A..- ..
~:
Bruce
Evans
22
~ i*~'t-$~'~i'
Clarlt
46
Kanl
..
$13.19
11%
-100.9
$15.89
Ii'
44%
26
20.9%
-12.1
~~._
..
"..,:,;.;'' '..:..;6..''"' ..,,~
Jan 18,20079:12NA
18
~~~*K''~\!
:Hcibd"""::,,,.;t as
Pr
28
lB
.,'tf~.i<.:
Jan 12,200311:14AM
~:111.21l92,5'1~1~:'&~:-%M'O'';i~;
,......
$9.99
JuI6. 20068:14M\'"
jqGrid
Imgenes
http://www.trirand.com/blog/
http://plugins.jquery.com/project/jqGrids
Un control ]avaScript compatible con AJAX,jqGrid (vase la figura 10.18)permite a
los desarrolladores representar dinmicamente y manipular datos tabulares en la Web.
Proporciona opciones para edicin en lnea, edicin de celda, navegacin de pagnador,
seleccin de mltiples elementos, sub-cuadrculas y cuadrculas en rbol. El plug-in
viene con una amplia documentacin en http://www.secondpersonplural.ca/
jqgriddocs/.
8 OJqG~d Examples
re &. loadlng Data
m I Manlpulatlng
8
Icrop
http://deepliquid.com/content/Jcrop.html
http://plugins.jquery.com/project/Jcrop
[crop (vase la figura 10.20)ofrece una forma rpida y sencilla de aadir recorte de
imagen a aplicaciones Web. Las caractersticas incluyen bloquear relacin de aspecto,
tamao mnimo y mximo, vnculos de interaccin y estilo personalizado.
Advanced
CJ Multl Selea
c:aMaster Detall
~~rr4
Magnify
t::JCrld as Subgrid
(?aReslzlng
Q;jSearch BI9 Sets
lB a+New stnce beta 3.0
I!l
CY:fi1r.~*'
a+ Row Edlting
m 1+ Data Mapplng
m 1+lntegratlons
ti! rUve Data Manlpulatlon
ID ,a+New In verslon 3.1
fB a+New In verslon 3.2
te a+New In verstcn 3.3
1-
i '!"
1:4
t:~::" .
lltem"4
..
.."..~[:~...:~Z:~~.".f}~~b~O ..
.
http://www.jnathanson.com/index.cfm?page=pages/jquery/magnify/
magnify
http://plugins.jquery.com/project/magnify
~!;,~:r~~~~!~~:~~~~~~;~:~~=='"==
Figura 10.18. Pluq-in jqGrid.
Ea
Jcrop
mi
Thumbnail Demo
"
Vcry fancy
captlon
te
thls Image
"
Thickbox
http://jquery.com/demo/thickbox/
Thickbox es un verstil plug-in lightbox que puede mostrar un sola imagen, mltiples
imgenes, contenido en lnea, contenido e f r ame, o contenido servido por medio de
AJAX en un cuadro de dilogo modal hbrido (vase la figura 10.23).
FancyBox
http://fancy.klade.lv/
Este clon de Lightbox enfatiza el estilo, con su apariencia al estilo Mac y un elegante
efecto de sombra. Adems de mostrar automticamente imgenes escaladas, el plug-in
FancyBox (vase la figura 10.22) puede mostrar contenido en lnea o e .f r ame.
l!IiI
T"
BlockUI
http://malsup.com/jquery/block/
http://plugins.jquery.com/project/blockUI
El plug-n BlockUI simula comportamiento sncrono, sin bloquear el navegador.
Cuando se activa, impedir la interaccin de usuario con la pgina (o parte de la pgina)
hasta que se desactive (vase la figura 10.24).
I
I
I
BIII
Flot
http://cqde.google.com/p/flot/
http://plugins
. j query. com/proj ect/flot
El plug-in Flot utiliza el elemento c anve s > para producir grficos de conjuntos de
datos y opcionalmente modificar esos grficos basndose en la interaccin de usuario
(vase la figura 10.26).Con la inclusin del script de traduccin Excanvas, Flot puede
mostrar grficos en Internet Explorer tambin, porque las instrucciones Canvas se con('vierten al formato VML propietario de Internet Explorer .
20
_ _ ._-'- I
-+--'
I
15
___
l'
.___
~.
1---
Jriited Stales
11I1
11I1
UnHed Kingdom
Denmark
No
_rway
Russla
jqModal
sL=:;r:~1< i=b:~ ~t
http://dev.iceburg.net/jquery/jqModal/
http://plugins.jquery.com/project/jqModal
El plug-in jqModal es una solucin ligera de cuadro de dilogo modal que tambin
es potente y flexible.Con un nfasis en ampliabilidad, deja mucha de la interaccin a los
desarrolladores Web que lo implementan (vase la figura 10.25).
01
1990
1992
1994
1996
I
1996
2000
2002
2004
view
Ci
~ i'iM%ffi5
(alert), View (<otloe)
a (dialog)
iS'rM;.y-:~~.~~.'l\'Jfr./W~?i~me.squit
Sparklines
http://omnipotent.net/jquery.sparkline/
http://plugins.jquery.com/project/sparklines
e,
Grficas
Como con la manipulacin de imagen, las grficas han sido tradicionalmente una
actividad del lado del servidor que requera gran cantidad de procesado. Los programadores creativos han desarrollado variasformas de crear grficas en el navegador, y
han agrupado estas tcnicas en los plug-ns que se muestran aqu.
Eventos
Como hemos visto una y otra vez, jQuery proporciona una gran cantidad de herramientas para interceptar y reaccionar a eventos de usuario como clics del ratn y pulsaciones de teclado. Sin embargo, muchas opciones se ponen disponibles en la librera
&El
principal aunque siempre habr ms tcnicas avanzadas que explorar. Estos plug-ins
facilitan la implementacin de algunos escenarios de evento menos comunes.
Resumen
En este captulo hemos examinadoformas en las que podemos incorporar plug-ins
de terceros en nuestras pginas Web. Hemos examinado el plug-in Form y jQuery DI
y hemos listado algunos otros. En el siguiente captulo, nos aprovecharemos de la arquitectura plug-n de jQuery para desarrollar algunos tipos diferentes de plug-ins por
nuestra cuenta.
CI;Imposile Inline ~
('
1!IIIIUI
.'
I!D
8$.
Bulle! !;haJ'IS
hoverlntent
http://cherne.net/brian/resources/jquery.hoverlntent.html
http://plugins.jquery.com/project/hoverlntent
El plug-in hoverIntent proporciona un solo mtodo para ocup~r ellugar del mtodo
. hover () cuando es importante impedir la activacin accidental de animaciones cuando
el usuario mueve el ratn sobre o fuera de un elemento. Intenta determinar la intencin
del usuario al monitorizar el cambio en velocidad del movimiento del ratn del usuario.
Este plug-in es especialmente efectivo cuando se utiliza con navegacin desplegable.
live query
http://github.com/brandonaaron/livequery/
http://plugins.jquery.com/project/livequery
Como el mtodo . 1i ve () incorporado de jQuery, el plug-in Live Query anexa dinrnicamente y mantiene vinculaciones de evento a elementos en el DOM, con independencia de cuando se creen los elementos. El plug-in proporciona una implementacin
alternativa que puede ser preferible en algunas situaciones.
r
/
"
11 Desarrollar
plug-ins
II!II
r
I
Para aadir una funcin al espacio de nombre j Query, podemos simplemente asignar la nueva funcin como una propiedad del objeto j Query:
jQuery.globalFunction
= function() (
alert(/This
is a test. This is only
a test./);
};
a test./);
functionTwo:
function(param)
(
alert(/The
parameter
is "/ + pai:am + /"./);
};
jQuery.globalFunction()
is only
I!!I
Este patrn crea esencialmente otro espacio de nombre para nuestras funciones
globales, denominado jQuery. rnyPlugin. Aunque informalmente llamamos a estas
,...funciones "globales", ahora son mtodos del objeto rnyPlugin, una propiedad del objeto global j Query. Por lo tanto tenemos que incluir el nombre del plug-in en nuestras
llamadas de funcin:
$.myPlugin.functionOne()
$.myPlugin. functionTwo
Si nuestro plug-in necesita proporcionar ms de una funcin global, podramos declararlas independientemente:
.'
jQuery.functionOne
= function()
alert(/This
is a test. This
(
is only
a test./);
i.
jQuery.functionTwo
= function(param)
(
alert(/The
parameter
is ,,/+ param + /"./);
};
Ahora, ambos mtodos estn definidos, por lo que podemos invocarlos en el modo
normal:
$.functionOne();
$.functionTwo(/test/)
;
(/test/) ;
Qu sentido tiene?
Ahora tenemos los fundamentos bsicos del desarrollo de plug-in entre nuestros
trucos. Despus de guardar nuestras funciones en un archivo denominado j query .
rnyplugin. j s, podemos incluir este script y utilizar las funciones desde otros scripts
en la pgina. Pero en qu es esto diferente de cualquier otro archivo JavaScript que
pudiramos crear e incluir? Ya hemos tratado los beneficios del espacio de nombre de
situar nuestro cdigo dentro del objeto j Query. Sin embargo, existe otra ventaja a escribir nuestra biblioteca de funcin como una extensin jQuery: puesto que sabemos que
jQuery estar incluido, las funciones pueden utilizar jQuery.
r.
is only
functionTwo:
function(param)
(
alert(/The
parameter
is "/ + param
a test./);
/"./);
}
});
l!liI
})
value)
lID
return
"
total
};
Observe que aqu, hemos utilizado el mtodo $ . each () para pasar por los valores
de la tabla. Podramos ciertamente utilizar un sencillo bucle for () aqu, pero puesto que
podemos estar seguros de que la librera jQuery se ha cargado antes de nuestro plug-in,
podemos utilizar la sintaxis con la que estbamos cmodos.
Para probar nuestro plug-in, crearemos una sencilla pgina para mostrar las entradas y salidas de la funcin:
= function()
happens./);
<body>
<p>Array contents:</p>
<ul id="array-contents"></ul>
<p>Array sum:</p>
<div id=lIarray-sum"></div>
</body>
Ahora escribiremos un pequeo script que anexa los valores de la tabla y la suma de
tabla a los marcadores de posicin que hemos creado.
$ (document) .ready(function()
(
var myArray
= [52, 97, 0.5, -22);
$.each(myArray,
function(index,
va1ue)
$ (/#array-contents/)
.append(/<li>/
+ va1ue
})
Podemos invocar luego este nuevo mtodo desde nuestro cdigo despus de utilizar
cualquier expresin selector:
+ /</li>/);
$(/div/)
.myMethod();
$ (/#array-sum/)
.append($.sum(myArray));
}) ;
Un vistazo a nuestra pgina HTML verifica que nuestro plug-in est funcionando
correctamente, como muestra la figura 11.1.
Array contenta:
52
O,
0.5
.Z
Atraysum:
+ /
e1ements./);
lm1I
Para examinar lo que podemos hacer con contexto de objeto, escribiremos un pequeo plug-in para manipular las clases en los elementos coincidentes. Nuestro nuevo
mtodo tomar dos nombres de clase y alternar qu clase se aplica a cada elemento
con cada invocacin.
jQuery.fn.swapClass
if (this.hasClass
function(classl,
(elassl))
(
this.removeClass(elassl)
class2)
Pero algo est mal. Cuando hacemos clie en el botn, se le aplica a todas las filas la
clase that, como muestra la figura 11.3.
Lorom
Ipsum dolor
Comectetur
.addClass(clasS2);
if
(this. hasClass
(claSs2))
this.removeClass(elass2)
OuIs no:rtrud
sIt ame'
.dlpJsJcJng
Sed do elusmod
incJdJdunf
ufl4bor8
VfJnJttm
tJxerclt1llion
.addClass(elasSl);
811t
tempor
MagnllS1lqUII
ut 8lIim ad mJnIm
else
mil
ex
ullsmco
68
oommodo
(5Swap-ctasses)
};
Figura
<u1>
<li>Lorem
ipsum
dolor
8it
ametc/li>
eli class="this">Consectetur
adipisicing
elite/li>
cli>Sed do eiusmod tempor incididunt
ut laborec/li>
e1i class=Uthat">Magna
aliquac::/li>
eli class="thislt>Ut
enirn ad minim veniame/li>
<:1i>Qui8 nostrud exercitation
ullarncO</li>
cli>Laboris
nisi ut aliquip ex ea cornmodoc/li>
eli class="that">Duis
aute irure dolorc/li>
<fuI>
<input
type="button"
value="Swap
classes"
id=:: 11swapll
/>
La clase this tiene estilo aplicado como texto en negrita, y la clase that como texto
en cursiva, como muestra la figura 11.2.
Lorem Ipsum d~r 1ft amet
Con . ctetur aclJpl.5clng .IIt
Sed do eiusmod
Ma{Jfl8SUque
tempor incidldunt
Ut _"1m ad mtnlm
Qula nostrud
utlabore
Necesitamos recordar que una expresin selector jQuery siempre puede coincidir
con cero, uno o mltiples elementos. Debemos permitir cualquiera de estos escenarios
cuando diseamos un mtodo plug-in.
En este caso, estamos invocando. hasClass (), que solamente examina el primer
elemento coincidente. En su lugar, necesitamos comprobar cada elemento de forma independiente y actuar sobre l.
La forma ms sencilla de garantizar un comportamiento adecuado con independencia
del nmero de elementos coincidentes es siempre invocar . each () sobre el contexto
del mtodo; esto refuerza la iteracin implcita, que es importante para mantener consistencia entre plug-in y mtodos incorporados.
Dentro de la llamada. each (), thi s hace referencia a cada elemento DOM en turno,
por lo que podemos ajustar nuestro cdigo a comprobar de forma separada y aplicar
clases a cada elemento coincidente.
jQuery.fn.swapClass
= funetion(clasBl,
this.eaeh(funetion()
(
var $element
= jQuery(this);
if ($element.hasClass(classl))
$element.removeClass(elaS9l)
Figura 11.2.
(
.addCla9s(ela992);
uJlamco
}
})
~~
class2)
else if ($element.hasClass(class2))
(
$element.removeCla99
(ela992) .addClass(classl);
vltl1lam
8X8rcllation
};
Ahora podemos invocar nuestro mtodo siempre que se haga clic sobre el botn:
$ (doeument)
.ready(funetion
La palabra clave thi s hace referencia a un objetojQuery dentro del cuerpo del mtodo de
objeto, pero hace referencia a un elemento DOMdentro de la invocacin . each ().
() (
$ (/#swap/) .eliek(funetion()
$ (fU/) .s.,apClass (fthis/,
return false
{
/that/);
Ahora cuando hacemos clie en el botn, las clases se intercambian sin afectar a los
elementos que no tienen aplicada ninguna clase, como muestra la figura 11.4.
'I-~~
lB
Lotem
lpsum
CoMect8tur
.css(/text-decoration/,
return false;
8lit
ut lIfIim
ad minlm venJINTI
n(sI
ut
ullamco
alIqulp ex ea commodo
SwaP"'IBS~
Figura 11.4.
Alternarestilos.
Encadenar mtodos
Adems de iteracin implcita, los usuarios jQuery deberan poder basarse en encadenar comportamiento. Esto significa que necesitamos devolver un objeto jQuery de todos
los mtodos plug-in, a menos que el mtodo est claramente pensado para recuperar una
informacin diferente. El objeto jQuery devuelto es normalmente el proporcionado como
this. Si utilizamos. each () para pasar por this, podemos devolvep su resultado:
jQuery.fn.swapClass
= function(classl,
return this.each(function()
{
var $element
= jQuery(this);
if ($element.hasClass(classl))
$element.removeClass(classl)
class2)
(
.addClass(class2);
}
el se if ($element.hasClass(class2))
(
$element.removeClass(class2)
.addClass(classl);
}
})
/underlineJ};
j);
});
ut labore
Magn llqua
En algunos casos, podemos querer que un mtodo plug-in cambie qu elementos DOM
se hacen referencia por el objeto jQuery. Por ejemplo, suponga que quisiramos aadir un
mtodo transversal DOM que encontrara los abuelos de los elementos coincidentes:
jQuery.fn.grandparent
= function()
var grandparents
= [];
this.each(function()
(
grandparents.push(this.parentNode.parentNode);
j);
grandparents
= jQuery.unique(grandparents);
return this.setArray(grandparents);
};
};
amet
ConnqteItr 8dlpI4IcJng
.~
Sed
tN
81ft
orWn IdrnJnlm
Qufs n9!!nJd
labods n-'
PUl.
tu-
lit
tabor!
wnJam
8X8ldtatlon
ul a1lgulp!IX
ultamea
e8 commodo
Inu. dolor
_ ~_.i\.
~'I5",""
Figura 11.5.
$ (document) .ready(function()
(
$ (/#swap/) .click(function()
$(/li/)
.swapClass(/this/,
/that/)
DI
Estilosubrayado.
cupidatat</div>
mi
"
target"
al aplicar estilo a
-,
})
connquat
lot&m
Ou
Sin embargo, este mtodo es destructivo. El objeto jQuery actual se modifica com~ efecto secundario; uno que es evidente si almacenamos el objeto jQuery en una variable:
$ (docu rnent) .~eady(function()
{
var $target ~ $(/.target/);
$target.grandparent()
.addClass(/highlight/);
$target.hide()
;
Commodo
1m
ipMIm
dolor
ait
Este cdigo debera resaltar los elementos abuelo, y luego ocultar los elementos des, tino. Sin embargo, el efecto actual es que los abuelos se ocultan en su lugar, como muesr tra la figura 11.8.
amet
utaiNredolor
In~,..hend.rit
Involuptata
\lo"
Deaerunl moml.,im
Cillumdolo,..
id ..tl8borum
Non proident
Exc.plur
_~~cut~~.~_da
Non proidenl
Figura 11.6.
Estructura anidada.
Ahora podemos localizar los elementos abuelo de los elementos al utilizar nuestro
nuevo mtodo:
$ (docurnent) .ready(function()
$(/.target/)
.grandparent()
Figura 11.8.
"
{
.addClass(/highlight/);
}l;
La clase highl ight pone en cursiva los elementos abuelo en la pgina, como muestra la figura 11.7.
Ocultarlos abuelos.
El objeto jQuery almacenado en $target ha cambiado para hacer referencia al abuelo. Para evitar esto, tenemos que hacer que el mtodo sea no destructivo. Esto es posible
por la pila interna que jQuery mantiene para cada objeto.
jQuery. fn.grandparent
~ function()
var grandparents
~ (J;
this.each(function()
{
grandparents.push(this.parentNode.parentNode)
}) ;
grandparents
~ jQuery.unique(grandparents);
return this.pushStack(grandparents);
};
Oeterunl mollit &f1im id ut laborum
UI:
en,"" Id mlnlm
ven.m
"
Jabone nist
'Ut a1iquip ex ea
Conwnodo cvnaequal
lorem ipaum dotor ail amet
dolor
Involuptale
'Vela~
OUumdolore
})
.addClass(/highlight/);
FLllilt.tnutl.~riatur
Exceplaur
Nonproidenl
SlJJ'Illn culpa qui ofIicia
Figura 11.7.
';'1'
;'
1m
Oeaenmt
Ul
..t
mollil ..,im jd
que podemos seleccionar y elegir los que son de utilidad para cada proyecto y omitir
los irrelevantes.'
Cuando n01encontramos repitiendo algo en nuestro cdigo muchas veces, puede
requerir la creacin de un mtodo abreviado. Por ejemplo, suponga que animamos frecuentemente elementos utilizando una'combinacin de las tcnicas incorporadas "deslizar" y "desvanecer". Agrupar estos efectos significa animar la height y opacity de
un elemento de forma simultnea. El mtodo. animate () facilita esto:
I.borum
Q,n-..d....,....
tIfm
ad mlnlm
Y8f'1iem
Ullamco.borianiai
l.laJiquipex
lB
Ou.aulelruredotot
infWPf!~'!'_.
InvoluptaUI
~l~~~:
.animate(
Clliu~doIore
--,
I
ExceplMJr
..,1 occaacat
Cllpic!IIIat.
(height:
/hide/, opacity:
/hide/});
Podemos crear un tro de mtodos abreviados para llevar a cabo esta animacin cuando mostramos y ocultamos elementos:
Sunlinculpa.~~
11.9.Objetosdestinoocultos.
Figura
o."Nnl
room.
labori.
function()
niai
lA. aliqui) ex ea
c-modo
l.oI8m j~um doler .it amel
-..
.
jQuery.fn.slideFadeln
= function()
return this.animate({
height: /show/,
opacity: /show/
Ouiaauleirutedolor
})
In,.~rit
Involuptate
Ollum doIore
,FusI"'nulMplJ~
ExoeptMJr ainloceaecet
};
VeIit
cuptdatat
---~-;-:..;.
-~~;~':::;':=~:;;;
..~-~.~~:
Non_
Slmlln
};
Qu;.noattud~tioIt
Ullamco
jQuery.fn .slideFadeOut
return this.animate({
height: /hide/,
opacity: /hide/
}) ;
jQuery.fn.slideFadeToggle
return this.animate({
height: /toggle/,
opacity: /toggle/
}) ;
function()
};
CU'P- qu offioia
Figura 11.10.
Encadenarmtodos.
callback)
};
jQuery.fn.slideFadeln
function(speed,
callback)
[""'."
I'J
l!mI
DI
return this.animate({
height,
!show!,
opacity,
!show!
}, speed, callback);
};
jQuery.fn.slideFadeToggle
return this.animate({
height,
!toggle!,
opacity,
!toggle!
}, speed, callback);
};
function(speed,
callback)
1ld...
d fad.UiiJ~'5lld"' d;fad~~
Figura 11.11.
.'
ll
11
11
/>
Nuestro script simplemente invocar nuestros nuevos mtodos cuando se hace die
en los botones:
$ (document) .ready(function()
{
$ (/#out!) .click (function () {
$(!p!) .slideFadeOut(!slow!)
return false;
}) ;
$(!#in!) .click(function()
{
$(!p!) .slideFadeln(!slow!);
return false;
})
Ahora hemos visto varios ejemplos de mtodos de plug-n, algunos de los cules toman
parmetros explcitos, y otros no. Como hemos explorado, la palabra dave this siempre
se encuentra disponible para proporcionar contexto para el mtodo, pero tambin podemos proporcionar informacin adicional para influir en la operacin del mtodo. Hasta
el momento, los parmetros han sido pocos, pero por supuesto, esta lista puede hacerse
mayor. Existen varios trucos que podemos utilizar para gestionar nuestros parmetros
de mtodo y facilitar la vida a aquellos que utilizan nuestros plug-ins.
Como nuestro ejemplo, empezaremos con un mtodo plug-in que proporciona una
sombra en un bloque de texto. Nuestra tcnica ser similar a la utilizada para el efecto
desvanecido en el rotativo de noticias del captulo 9: utilizaremos un nmero de elementos que son parcialmente transparentes, superpuestos en diferentes posiciones en
la pgina.
jQuery.fn.shadow
= function() {
return this.each(function()
{
var $originalElement
= jQuery(this);
for (var i = o; i < 5 i i++) {
$originalElement
.clone ()
.css ({
position,
!absolute!,
left, $originalElement.offset()
top' $originalElement.offset()
margin,
0,
zIndex: -1
opac t y : 0.1
})
.appendTo(!body!)
;
.left + i,
.top + i,
));
$ (!#toggle!) .click(function()
{
$(!p!) .slideFadeToggle(!slow!)
return false;
Parmetros de mtodo
}
;
));
};
});
Para cada elemento en el que se invoca este mtodo, realizamos una serie de dones
del elemento, ajustando su opacidad. Estos dones se posicionan de forma absoluta, en
distintos desplazamientos desde el elemento original.
lID
mi
Nuestro nuevo parmetro funciona segn lo anticipado, la sombra es mayor, utilizando dos veces ms trozos que antes, pero la interfaz del mtodo es menos que ideal,
como se ve en la figura 11.14.Estos tres nmeros se confunden fcilmente, y su orden
no se puede deducir lgicamente. Seria una mejora etiquetar los parmetros, en beneficio de la persona que escribe la llamada de mtodo, y cualquiera que ms tarde desee
leer e interpretarlo.
<body>
<hl>The
<!body>
quick
brown
fox jumps
over
the
1azy
I-..
--~---, I
dog.<!hl>
Por el momento, nuestro plug-in no toma parmetros, de modo que invocar el mtodo es sencillo, como se muestra en la figura 11.13.
Il\'IA'~~~lt~tl""\ttA
})
Parmetros sencillos
opacity,
zIndex)
var $origina1E1ement
= jQuery(this);
for (var i = o; i < slices; i++) {
$origina1E1ement
.c1one()
.css({
position:
!abso1ute!,
1eft: $origina1E1ement.offset()
top: $origina1E1ement.offset()
margin: o,
zIndex: zIndex,
opacity: opacity
Mapas d parmetro
Hemos-visto muchos ejemplos en la API jQuery de mapas que se proporcionan corno
parmetros de mtodo. sta puede ser una forma ms amigable de exponer opciones a
un usuario de plug-ins que la sencilla lista de parmetros que hemos utilizado. Un mapa
proporciona una etiqueta visual para cada parmetro, y tambin hace que el orden de
los parmetros sea irrelevante. Adems, siempre que podamos simular la API jQuery
en nuestros plug-ins. deberamos hacerlo para aumentar consistencia y por lo tanto facilidad de uso .
jQuery.fn.shadow
= function(opts)
{
return this.eachlfunction()
{
var $origina1E1ement
= jQuery(this);
fer (var i = o; i < opts.slices; i++)
$origina1E1ement
.c1one()
.css({
position:
!absolute!,
1eft: $origina1E1ement.offset()
top: $origina1E1ement.offset()
margin: o,
zIndex: opts.zlndex,
opacity: opts.opacity
.1eft + i,
.top + i,
})
.1eft + i,
.top + i,
.appendTol!body!);
}
j) ;
};
})
.appendTo(!body!);
}
});
};
Ahora, cuando invocamos nuestro mtodo, debemos proporcionar estos tres valores:
$ (document) .ready (function 1) {
$ I!hl!) .shadow(lO,
0.1, -1);
j);
Todo lo que hemos cambiado para permitir nuestra nueva interfaz es la forma en que
se referencia cada parmetro; en lugar de tener un nombre de variable aparte, se accede
a cada valor como una propiedad del argumento opts a la funcin.
Invocar este mtodo ahora requiere un mapa de valores en lugar de tres nmeros
individuales (vase figura 11.15).
$ (document) .ready(functionl)
$(!hl!) .shadow({
slices: 5,
'ifr~fr~i'
ID
Ilb~cty'~1$b..r,o~tQX.tw.n~
opac t y . 0.25,
zIndex: -1
))
q1(el1 ~Q
l~
DI
~-QQ-.I
Seguimos invocando nuestro mtodo utilizando un mapa, pero ahora podemos especificar solamente los parmetros que queremos que difieran de sus predeterminados:
1- .
$ (document) .ready(function()
$(/h1/) .shadow({
opac i ty . 0.05
)) ;
)) ;
. 1
$. extend
A medida que crece el nmero de parmetros para un mtodo, se hace menos probable que siempre deseemos especificar cada uno. Un conjunto razonable de valores
predeterminados puede hacer que una interfaz de plug-in sea ms utilizable.
Afortunadamente, utilizar un mapa para nuestros parmetros ayuda con esta tarea
tambin; es sencillo omitir cualquier elemento del mapa y reemplazarlo con un predeterminado.
jQuery.fn.shadow
= function(options)
var defaults = {
s L ices : 5,
opacity:
0.1,
zIndex: -1
};
var apta = jQuery.extend(defaults,
options);
return this.each(function()
(
var $originalElement
= jQuery(this);
for (var i = O; i < opts.slices i++)
$originlElement
.clone()
.css({
position:
/absolute/,
left: $originalElement.offset()
.left + i,
topo $originalElement.offset()
.top + i,
margin: O,
zIndex: opts.zIndex,
opacity:
opts.opacity
))
.appendTo(/body/);
)
)) ;
$ (document) .ready(function()
$(/h1/) .shadow();
)) ;
Funciones de rellamada
Por supuesto, algunos parmetros de mtodo pueden ser algo ms complicados que
un sencillo valor numrico. Un tipo de parmetro comn que hemos visto frecuentemente a lo largo de la API jQuery es la funcin de rellamada. Las funciones de rellamada
pueden llevar gran cantidad de flexibilidad a un plug-in sin requerir una gran cantidad
de preparacin cuando creamos el plug-in.
Para emplear una funcin de rellamada en nuestro mtodo, necesitamos simplemente
aceptar el objeto funcin como un parmetro e invocar esa funcin donde sea apropiado en nuestra implementacin de mtodo. Como ejemplo, podemos ampliar nuestro
mtodo de sombra de texto para permitir que el usuario personalice la posicin de la
sombra relativa al texto.
. I
jQuery.fn.shadow
= function(options)
var'defaults
= {
slices: 5,
opacity:
0.1,
z fndex . -1,
sliceOffset:
function(i}
return {x: i, y: i};
);
);
var
return this.each(function()
(
var $originalElement
= jQuery(this)
;
tor (var i = Di i < opts.slices; i++)
var offset ='opts,sliceOffset(i);
opts
options);
mi
11. Desarrollarplug-ins
$originalElement
.elone ()
.ess ({
position:
/absolute/,
left: $originalElement.offset().left
+ offset.x,
top: $originalElement.offset()
.top
+ offset.y,
margin: O,
zIndex: opts.zlndex,
opaeity: opts.opaeity
jQuery.fn.shadow
= funetion(options)
{
var opts = jQuery.extend({},
jQuery.fn.shadow.defaults,
options);
,..
})
.appendTo(/body/)
return this.eaeh(funetion()
(
var $originalElement
= jQuery(this);
for (var i = o; i < opts.slices; i++)
var offset = opts.slieeOffset(i);
$originalElement
.elone()
.ess({
position:
/absolute/,
left: $originalElement.offset()
topo $originalElement.offset()
margin: O,
zIndex: opts.zlndex,
opaeity:
opts.opaeity
}
})
};
lID
.left + offset.x,
.top + offset.y,
})
.appendTo(/body/);
}
})
};
});
})
Esto har que la sombra se site hacia arriba y a la izquierda, como muestra la figura
11.17, en lugar de hacia abajo y a la derecha.
La rellamada permite modificaciones sencillas en la direccin de la sombra, o posicionamiento mucho ms sofisticado si el usuario del plug-in proporciona la rellamada
apropiada. Si la rellamada no se especifica, entonces el comportamiento predeterminado
se utiliza una vez ms.
Predeterminados personalizables
Podemos mejorar la experiencia de utilizar nuestros plug-ins al proporcionar valores
predeterminados razonables para nuestros parmetros de mtodo, como hemos visto.
Sin embargo, algunas veces puede ser difcil predecir que ser un valor predeterminado
razonable. Si un script invocara nuestro plug-n mltiples veces con un conjunto diferente de parmetros que hemos establecido como predeterminados, la posibilidad de
jQuery.fn.shadow.defaults
elices: 5,
opacity: 0.1,
zIndex: -1,
sliceOffset: function(i)
return {x: i, y: i};
};
10;
lmI
11. Desarrollarplug-ins
sliceOffset:
function(i)
return {x: -i, y: i};
}
})
return
cas~ />/:
return
va1ue
>= parselnt(parts[3]);
va1ue
> parselnt(parts[3]
I;
}
})
Este script crear una sombra con 10 tramos, porque ste es el nuevo valor predeterminado, pero tambin situar sombra a la izquierda y hacia abajo, debido a la rellamada sliceOffset
que se proporciona junto con la llamada de mtodo, como se ve
en la figura 11.18.
/
I"~"""-I
var
va1ue
= parseF1oat(jQuery(e1ement)
switch
(parts[2])
case /</:
set)
return va1ue
case /<=/:
< parselnt(parts[3]);
return va1ue
case /=/:
case /==/:
return va1ue
case />=/:
<= parselnt
(parts [3] I ;
== parselnt(parts[3]);
Este cdigo le dice a jQuery que css es una cadena vlida que puede seguir a dos
puntos en una expresin de selector, y que cuando se encuentra, la funcin dada se debera invocar para determinar si el elemento se debera incluir en el conjunto resultado.
Se pasan cuatro parmetros a la funcin que se evala aqu:
index: El ndice del elemento DOM dentro del conjunto resultado. Esto es de
utilidad para selectores como: eq () y : I t ( ) .
set: El conjunto entero de elementos DOM que ha coincidido hasta este punto.
Este parmetro no suele ser necesario.
en la sombra.
jQuery.extend(jQuery.expr[/:/],
(
/css/: function(e1ement,
index, matches,
var parts = /([\W-]+)\s*([<>=l+)\s*(\d+)/
.exec(matches[3])
;
"EJ'"
lIImI
consequat
nisi</div>
su cdigo. Antes de esto, sin embargo, deberamos aseguramos de que el plug-in est
preparado par;!el pblico.
Existen algunas reglas a seguir al escribir plug-ins para que funcione bien con otro
cdigo. Ya hemos tratado algunas de ellas, pero las recopilamos aqu por comodidad.
<div>Cornmodo</div>
<div>Lorem
ipsum
dolor
sit
amet
ex
l1mI
ea</div>
</body>
Convenciones de nombrado
1~~~,~g,i~~~~.~~J
h ..~ .." ,
[~;=j~~~'~~
~~~~
I~J
~!~~~~,t~~~.~,~!
Figura 11.19. Documento HTML.
"
Con nuestro nuevo selector, se hace trivial resaltar los elementos ms pequeos en
esta lista, como muestra la figura 11.20.
--
[il~~I.f~~J"E~_~;1
~;-;~~~~~~~:I
&~~~"'~~lij
II'J,~,~~!N~_~~~*~I
(
va aqui
.ready(function()
$ (/div:css(width
})
La funcin toma un solo parmetro, al que pasamos el objeto global jQuery. El parmetro se nombra $, por lo que dentro de la funcin podemos utilizar el alias $ sin
conflictos.
Interfaces de mtodo
Todos los mtodos jQuery se invocan dentro del contexto de un objeto jQuery, de
modo que thi s hace referencia a un objeto que puede hacer referencia a uno o ms elementos DOM. Todos los mtodos deben comportarse correctamente con independencia
del nmero de elementos coincidentes. En general, los mtodos deberan invocar thi s .
each () para pasar por los elementos coincidentes, operando sobre cada uno en turno.
mi
Estilo de la documentacin
La documentacin archivada se debera anexar delante de cada definicin de
funcin o mtodo en formato ScriptDoc. Este formato se documenta en :tp: //www.
scriptdoc.org/.
Resumen
En este ltimo captulo, hemos visto cmo la funcionalidad que proporciona jQuery
no necesita limitar las posibilidades de uso de la librera. Los plug-ins que se encuentran
disponibles amplan el men de caractersticas substancialmente, y podemos fcilmente
crear el nuestro propio que ampla an ms los lmites.
Los plug-ins que hemos creado contienen varias caractersticas, incluidas funciones
globales que utilizan la librera jQuery, nuevos mtodos del objeto jQuery para actuar
sobre elementos DOM, mtodos ampliables que se pueden personalizar fcilmente, y
expresiones de selector mejoradas para encontrar elementos DOM en nuevas maneras.
Con estas herramientas a nuestra disposicin, podemos configurar jQuery, y nuestro
propio cdigo JavaScript, en la forma que queramos.
l'
f>W
I
I
,,
,..
Apndice A
Recursos online
Documentacin jQuery
Estos recursos ofrecen referencias y detalles sobre la librera jQuery.
Wiki jQuery
La documentacin en j query . com est en la forma de un wiki, lo que significa que
el contenido es editable por el pblico. El sitio incluye la API jQuery, tutoriales, guas
de inicio y mucho ms:
http://docs.jquery.com/
API jQuery
Adems de la documentacin oficial en j query . com, la API est disponible en la
siguiente ubicacin:
http://remysharp.com/jquery-api/
mi
1"
liD
.aspx
jQuery visual
Este navegador de API diseado por Yehuda Katz, y actualizado por Remy Sharp,
es tanto bonito como apropiado. Tambin proporciona visualizacin rpida de mtodos
para un nmero de plug-ins jQuery:
http://www.visualjquery.com/
/ Quirksmode
El sitio Quirksmode de Peter-Paul Koch es un extraordinario recurso para entender las
diferencias en la forma en que los navegadores implementan varias funciones JavaScript,
as como muchas propiedades CSS:
http://www.qirksmode.org/
Referencia JavaScript
Estos sitios ofrecen referencias y guas a JavaScript como lenguaje en general, en lugar
de jQuery en particular.
Dev.opera
Aunque centrado principalmente en su propia plataforma de navegador, el sitio Opera
para desarrolladores Web incluye una serie de artculos de utilidad sobre JavaScript:
http://dev.opera.com/articles/
JavaScript Toolbox
JavaScript Too1boxde Matt Kruse ofrece una gran variedad de libreras JavaScript, as
como consejo sobre mejores prcticas JavaScript y una coleccin de recursos JavaScript
examinados en otra parte en la Web:
http://www.javascripttoolbox.com/
Compresores
de cdigo JavaScript
Compresor YUI
Este compresor JavaScript de la librera de interfaz de usuario Yahoo! (Yahoo! UI
Library) se utiliza para reducir el tamao del cdigo fuente jQuery. La herramienta de
lnea de comando basada en [ava es una descarga gratuita, El cdigo resultante es muy
eficiente en tamao de archivo y rendimiento, y se puede reducir an ms con compresin Gzip si se desea:
http://developer.yahoo.com/yui/compressor/
E&lI
JSMin
Creado por Douglas Crockford, JSMin es un filtro que elimina comentarios y espacio
en blanco innecesario de archivos JavaScript. Normalmente reduce el tamao de archivo
a la mitad, resultando en descargas ms rpidas, especialmente cuando se combina con
compresin de archivo basada en servidor:
Dave Shea proporciona esta chuleta CSS de utilidad en un intento por hacer que el
proceso de diseo sea ms sencillo, y proporciona una referencia rpida a comprobar
cuando encuentra problemas:
http://mezzoblue.com/css/cribsheet/
http://www.crockford.com/javascript/jsmin.html
Pretty printer
Esta herramienta embellece JavaScript que se ha comprimido, restaurando los saltos
de lnea y sangrando donde es posible. Proporciona una serie de opciones para adaptar
los resultados:
ID
. Position is everything
Este sitio incluye un catlogo de errores de navegador en CSS junto con explicaciones de cmo soluconarlos:
http://www.positioniseverything.net/
http://www.prettyprinter.de/
Referencia (X)HTML
La librera jQuery se encuentra en su mejor momento cuando trabaja con documentos 'o,
semnticos HTML y XHTML, con forma to apropiado. El recurso a continuacin proporciona asistencia con estos lenguajes de marcacin.
Blogs de utilidad
Nuevas tcnicas y caractersticas se estn desarrollando e incorporando continuamente
para cualquier tecnologa viva. Mantenerse al tanto de las innovaciones puede ser fcil
al comprobar estas fuentes de noticias de desarrollo Web de vez en cuando.
El blog jQuery
[ohn Resig y otros colaboradores en el blog jQuery oficial publican anuncios sobre
nuevas versiones y otras iniciativas entre el equipo del proyecto, as como tutoriales y
otros datos.
http://jquery.com/blog/
http://www.w3.org/MarkUp/
Referencia CSS
Los efectos y animaciones que hemos visto una y otra vez se basan en el potencial
de las hojas de estilo en cascada. Para incorporar los detalles visuales que deseamos en
nuestros sitios, podemos necesitar recurrir a estos recursos CSS para orientacin.
learning jQuery
Karl Swedberg dirige este blog para tutoriales, tcnicas y anuncios jQuery. Autores
invitados incluyen miembros del equipo jQuery como Mike Alsup y Brandon Aaron:
http://www.learningjquery.com/
Ajaxian
Este blog actualizado con frecuencia iniciado por Dion Almaer y Ben Galbraith
proporciona una tremenda cantidad de noticias y caractersticas, y el tutorial sobre
JavaScript:
http://www.w3.org/Style/cSS/
http://ajaxian.com/
lIiI
[ohn Resig
lIiiI
DOM scripting
El blog de jeremy Keith empieza donde lo deja el popular libro de programacin
DOM, un recurso fantstico para JavaScript sencillo:
http://domscripting.com/blog/
JavaScript ant
Este sitio contiene un repositorio de artculos relacionados con JavaScripty su uso en
navegadores Web modernos, as como una lista organizada de recursos JavaScript:
http://javascriptant.com/
http://www.robertnyrnan.com/
As days pass by
l'
Stuart Langridge experimenta con uso avanzado del DOM del navegador:
http://www.kryogenix.org/code/browser/
A list apart
A List Apart explora el diseo, desarrollo y significado de contenido Web, con un
foco especial en estndares Web y mejores prcticas:
http://www.alistapart.com/
Snook
El blog de programacin/ desarrollo Web de [onathan Snook:
http://snook.ca/
Digitalus
manager/
Drupal: http://drupal.
Elblog de Matt Snider est dedicado a comprender JavaScripty sus marcos de trabajo:
DutchPIPE: http://dutchpipe
http://mattsnider.com/
Hpricot: http://code.whytheluckystiff
JobberBase: http://www.jobberbase.com/
Laconica: http://laconi
Piwik:http://piwik.org/
Pornrno: http://pommo
symfony:http://www.syrnfony-project.org/
SPIP:http://www.spip.net/
lean "t
Tres sitios de Christian Heilmann proporcionan entradas de blog, cdigo de muestra
y extensos artculos relacionados con JavaScript y desarrollo Web:
http://icant.co.uk/
http://www.wait-till-i.com/
http://www.onlinetools.org/
org/
.org/
. cal
. org/
. net/hpricot/
te-
ElI!I
Textpattem:
Trac:http://trac.edgewall.org/
WordPress: http://wordpress
Z-Blog:http://www.rainbowsoft.org/zblog
http://www.textpattern.com/
.org/
.
Para una lista completa, visite la pgina Sites Using jQuery en: http://docs
jquery.com/Sites_Using_jQuery.
/
'
r'
,,
'
pndice B
Herramientas
de desarrollo
firebug
La extensin Firebug para Firefox es indispensable para desarrollo jQuery:
http://www.getfirebug.com/
Algunas de las caractersticas de Prebug son:
<,
Un excelente inspector DOM para encontrar nombres y selectores para partes del
documento.
'r'!
mi
Apndice B. Herramientas
de desarrollo
E1I
y modificar en el momento con nuevas reglas CSS. Tambin proporciona otras ayudas
variadas de desarrollo, como una regla para medir elementos de pgina:
.
http://w..{w.microsoft.com/downloads/details.aspx?FamilyID=
e59c3964'- 672d-4511-bb3e-2d5eldb91038
Esto no solamente solapa Firebug en el mbito de inspeccin DOM, sino que tambin
contiene herramientas para tareas comunes como manipulacin de cookie, inspeccin
.de formulario, y cambio de tamao de pgina. Tambin puede utilizar esta barra para
desactivar rpida y fcilmente JavaScript para un sitio para asegurarse de que la funcionalidad se degrada bien cuando el navegador del usuario es menos compatible:
http://chrispederick.com/wark/web-developer/
http://msdn.microsoft.com/vstudio/express/vwd/
"
Venkman
Venkman es el depurador JavaScript oficial para el proyecto Mozilla. Proporciona
un entorno de solucin de problemas que es una reminiscencia del sistema GDB para
programas de depuracin que se escriben en otros lenguajes.
http://www.mozilla.org/projects/venkman/
DebugBar
Proporciona un inspector DOM as como una consola JavaScript para depurar:
http://www.debugbar.com/
Drip
Prdidas de memoria en cdigo JavaScript pueden causar problemas de rendimien, to y estabilidad para Internet Explorer. Drip ayuda a detectar y aislar estos problemas
de memoria:
http://Sourceforge.net/projects/ieleak/
http://sebastianzartner.ath.cx/new/downloads/RExT/
Safari contina siendo el recin llegado como plataforma de desarrollo, pero todava
existen herramientas disponibles para situaciones en las que el cdigo se comporta de
forma diferente en este navegador frente a otros lugares.
Men Develop
Microsoft Internet Explorer Developer Toolbar
La barra de herramientas de des arrollador proporciona principalmente una vista
del rbol DOM para una pgina Web. Los elementos se pueden localizar visualmente,
En Safari 3.1, una opcin en la pestaa de opciones avanzadas del men Preferences
(Preferencias) proporciona un men especial denominado Develop (Desarrollo). Con este
men activado, se encuentran disponibles un Inspector Web y Consola JavaScript.
lID
Inspector Web
Safari 3 incluye la posibilidad de inspeccionar elementos de pgina individuales
recopilar informacin especialmente sobre las reglas CSS que se aplican a cada una.
lID
http://www.nitobibug.com/
http://trac.webkit.org/wiki/web%20Inspector
Desarrollos actuales de WebKit han mejorado sustancialmente esta herramienta de
inspector Web, concediendo muchas de las excelentes caractersticas de Firebug como
un depurador JavaScript integrado denominado Drosera.
http://trac.webkit.org/wiki/Drosera
Aunque tiene una cuota de mercado limitada como navegador de escritorio, Opera
desempea un papel importante en sistemas incorporados y dispositivos mviles, y sus
posibilidades de uso se deberan considerar cuidadosamente en el desarrollo Web.
Charles
Dragonfly
Aunque todava en sus primeras etapas, Dragonfly es un prometedor entorno de depuracin para navegadores Opera en ordenadores y dispositivos mviles. El conjunto
de caractersticas de Dragonfly es similar al de Firebug, incluida depuracin JavaScript,
as como inspeccin y edicin CSS y DOM.
Otras herramientas
Aunque las herramientas anteriores se centran en un navegador
lidades tienen un mbito de aplicacin ms amplio.
Firebug Lite
Aunque la extensin Firebug est limitada al navegador Web Firefox. algunas de las
caractersticas se pueden replicar al incluir el script FrebugLite en la pgina Web. Este
paquete simula la consola Firebug, incluido permitir llamadas a console
.log () para
funcionar en todos los navegadores y no lanzar errores JavaScript:
.
http://www.getfirebug.com/lite.html
NitobiBug
Como Firebug Lite, NitobiBug es una herramienta multiplataforma que trata algunas
de las mismas cosas que el ms robusto y refinado Firebug. Su fortaleza se encuentra
http://www.xk72.com/charles/
Fiddler
Fiddler es otro proxy de depuracin HTTP de utilidad con caractersticas similares a
las de Charles. Segn su sitio, Fiddler "incluye un potente subsistema de script basado
en eventos, y se puede ampliar utilizando cualquier lenguaje .NET":
http://www.fiddlertool.com/fiddler/
Aptana
Este IDE (Integrated Development Environment o Entorno de desarrollo integrado) de
desarrollo Web basado en Java es gratuito y multiplataforma. Junto con las caractersticas
de edicin de cdigo estndar y avanzadas, incorpora una copia completa de la documentacin API jQuery, y tiene su propio depurador JavaScript basado en Firebug.
http://www.aptana.com/
"'0 \ ~
li.I
~
!l3
"""
):!\
/;.~
.
L.~
.~..
..
..~
@'
",
~
~
.')
15@).
-,
'.1
,~
~;
__ .
. 7$\'~'
\~
_-~
r'"'\
-@
'~,
~\
,f,1),.,/
~_~.
'""..- ...."
'~
\
~;{"~
,",
"i'i',
0.'
'.
....
1@"
,~
t@1'~
, .... ~"'"
:'.-'::'
, ~..
,
@)
:")
- \!J '"
,..-,.
~, ~',o:~'
'..
/
i\
~-._'
~:.,'"
,c"l'-~~~'
-~0\"
\
'@'i.
. ~'-...--..
O
'~
()
'\'4;
,/
.-,:'
l'
".
15'.
'
"<!I,
.".
~,"~\
\.~
.~ ';':'~,-'''''~i;-
fr -',
e
o
,~,
.'~,'
' /@J ?~ l~,:~
'~
"~
iWt
\ ,""
13"
f;.
'~
..
'\
.
(@';,
\"'~--'--.
.'
Apndice e
JavaScript
Closures
En este libro hemos visto muchos mtodos jQuery que toman funciones como parmetros. Nuestros ejemplos han creado, invocado y pasado funciones una y otra vez.
Aunque podemos hacer esto con solamente un conocimiento somero de la mecnica
interna JavaScript, a veces los efectos secundarios de nuestras acciones pueden parecer
extraos si no tenemos conocimiento de las caractersticas del lenguaje. En este apndice,
estudiaremos una de las construcciones basadas en funciones ms esotricas denominada c/osures. Nuestra explicacin implicar muchos pequeos ejemplos de cdigo, con
los que queremos mostrar un conjunto de mensajes. En lugar de utilizar un mecanismo
de registro especfico de un navegador (como console. Loq() de Firefox), o crear una
serie de cuadros de dilogo alert (), utilizaremos un pequeo mtodo de plug-in:
jQuery.fn.print
= function(message)
return this.each(function()
{
$(rcdiv
class="result"
/>')
,text(String(message))
.appendTo($(this)
.find(' .results'));
})
};
( 'hello'
Funciones internas
J avaScript es afortunado de incluirse entre los lenguajes de programacin que sopor"
tan declaraciones de funciones internas, Muchos lenguajes de programacin tradicionales, como C, recopilan todas las funciones en un nico mbito de nivel superior. Los
lIiIiI
lenguajes con funciones internas, por otro lado, nos permiten reunir pequeas funciones
de utilidad donde son necesarias, evitando la polucin del espacio de nombres.
Una funcin interna es simplemente una funcin que se define dentro de otra funcin. Por ejemplo:
function outerFn() {
function innerFn()
funciones padre. JavaScript, por otro lado, nos permite pasar funciones como si fueran
cualquier otro tipo de datos. Esto significa que las funciones internas pueden escapar
de sus captores.
La ruta de escape puede resultar en muchas direcciones diferentes. Por ejemplo, suponga que la funcin se asigna a una variable global:
var globalVar;
function outerFn() {
,
$('#example-3
.print('Outer function
function innerFn() {
'/
$ ( #example-3 I ) . print ( 'Inner function 1) ;
1)
Aqu, innerFn () es una funcin interna, contenida dentro del mbito de outerFn (). Esto significa que una llamada a innerFn () es vlida dentro de outerFn (),
pero no fuera de ella. El siguiente cdigo resulta en un error JavaScript:
.print('innerFn(),
');
1);
globalVar
innerFn
function outerFn() {
$('#example-2') .print('Outer functiont)
function innerFn() {
$('#example-l') .print(IInner Function');
}
$('#example-l')
innerFn ();
mi
$('#example-3')
outerFn() ;
$('#example-3')
global Var ();
.'
() desde
,);
.print('globalVar(),
,);
function outerFn() {
$('#example-2') .print('Outer function');
function innerFn() {
$(I#example-2
.print('Inner function');
.print('outerFn(),
Outer function
'globalVar ():
Inner function
1)
innerFn() ;
}
$ ('#example-2') .print('outerFn(),
outerFn() ;
');
Outer function
Inner function
Esta tcnica es especialmente til para pequeas funciones de una sola finalidad. Por
ejemplo, los algoritmos que son recursivos, pero tienen un envoltorio API no recursivo,
a veces se expresan mejor con una funcin interna como elemento de ayuda.
El
gran escape
Observe que una llamada a innerFn () desde fuera de outerFn () sigue devolviendo un error. Aunque la funcin ha escapado por medio de la referencia almacenada en
. la variable global, el nombre de la funcin sigue atrapado dentro del mbito de aplicacin de outerFn () .
Una referencia de funcin tambin puede encontrar su camino fuera de una funcin
padre por medio de un valor de retorno:
function outerFn() {
$('#example-4') .print('Outer function
function innerFn() {
$('#example-4') .print('Inner function');
l
);
return
innerFn;
}
$('#example-4') .print('var fnRef = outerFn(), ');
var fnRef = outerFn();
$('#example-4') .print (fnRef (),');
fnRef() ;
Aqu, no hay variable global modificada dentro de ou t erFn ( ) . En su lugar, ou terFn () devuelve una referencia a innerFn () . La llamada a outerFn () resulta en esta
referencia, que se almacena y se invoca en turno, activando el mensaje de nuevo:
l1iPI
~nRef();
fnRef();
var fnRef2
fnRef2 ();
fnRef2() ;
() :
Inner funetion
Elhecho de que las funciones internas se puedan invocar por medio de una referencia
incluso despus de que la funcin est fuera de mbito, significa que JavaScript necesita mantener disponibles funciones referenciadas siempre y cuando se puedan invocar.
Cada variable que hace referencia a la funcin se registra por el tiempo de ejecucin
JavaScript, y una vez que ha desaparecido la ltima, el recolector de basura JavaScript
viene y libera un poco de memoria.
Las funciones internas pueden por supuesto tener sus propias variables, que estn
restringidas en mbito de aplicacin en la propia funcin:
1)
o{,terFn() ;
globalVar
globalVar
globalVar
globalVar
1
= 2
= 3
= 4
Pero qu pasa si la variable es local a la funcin padre? Puesto que la funcin interna hereda el mbito de aplicacin de su padre, tambin se puede hacer referencia a
esta variable:
function outerFn() (
function innerFn()
var innerVar = Oi
innerVar++i
$('#example-5
.print('innerVar
"
function outerFn()
var outerVar = o;
function innerFn()
outerVar++
$(I#example-7
.print('outerVar
1)
return
1
1m
outerVar)
innerFn
innerVar);
v r fnRef = outerFn{);
fnRef() ;
fnRef ();
var fnRef2 = outerFn();
fnRef2 ();
fnRef2 ();
1
return
innerFn
var fnRef
fnRef() ;
fnRef();
var fnRef2
fnRef2 ();
fnRef2() ;
outerFn() ;
= out.e r Fn ()
Cada vez que se invoca la funcin, por medio de una referencia u alguna otra cosa,
se crea una nueva variable innerVar, incrementada, y se muestra:
innerVar
innerVar
innerVar
innerVar
:::;
1
= 1
= 1
= 1
Las funciones internas pueden hacer referencia a variables globales en la misma forma
que cualquier otra funcin:
var globalVar
= Oi
function outerFn()
function innerFn()
globalVar++;
$('#example-6') .print('globalVar
return
var fnRef
innerFn
=
outerFn();
, + global Var) ;
outerVar
outerVar
outerVar
outerVar
= 2
=
=
1
2
Obtenemos una mezcla de los dos efectos anteriores. Las llamadas a Lrme r Pn () por
medio de cada referencia incrementan outerVar independientemente. Observe que la
segunda llamada a outerFn () no vuelve a establecer el valor de outerVar, sino que
crea una nueva instancia de outerVar, vinculada al mbito de aplicacin de la segunda
'lamada de funcin. El resultado de esto es que despus de las llamadas anteriores, otra
llamada a fnRef () imprimir el valor 3, y una llamada siguiente a fnRef2 () tambin
imprimir 3. Los dos contadores estn completamente separados. Cuando una referencia
a una funcin interna encuentra su camino fuera del mbito de aplicacin en el que se
defini la funcin, esto crea un closure en esa funcin. Llamamos a las variables que no
son ni parmetros ni locales a la funcin interna variables libres, y el entorno de la llamada d' funcin exterio' las cierra' Esenc'alment', el hecho de'que la func'n haga'refere'cia a
una variable local e' la funcin ex'erior oto'ga a la variable un aplazamiento. La memoria
no se libera cuando la funcin se completa, ya que lo sigue necesitando el closure.
li!I
1m
Closures en jQuery
Cuando existe ms de una funcin interna, los closures pueden tener efectos que no
son tan fciles de anticipar. Suponga que emparejamos nuestra funcin de incremento
con otra funcin, sta incrementada por dos:
Los mtodos 'que hemos visto a lo largo de la librera jQuery a menudo toman al
menos una funcin como parmetro. Por 'conveniencia, a menudo utilizamos funciones
annimas de modo que podemos definir el comportamiento de funcin cuando se necesita. Esto significa que las funciones raramente estn en el espacio de nombre de nivel
superior; son normalmente funciones internas, lo que significa que pueden fcilmente
crear closures.
function outerFn()
{
var outerVar = o;
function
innerFn1()
outerVar++i
$('#example-B')
.print(' (1) outerVar
}
function
innerFn2()
{
QuterVar += 2;
$('#example-B')
.print(' (2) outerVar
+ outerVar)
outerVar);
}
return
outerVar
QuterVar
outerVar
outerVar
outerVar
outerVar
= 3
= 4
1
3
4
Las dos funciones internas hacen referencia a la misma variable local, de modo que
comparten el mismo entorno de cierre. Cuando innerFnl () incrementa outerVar
en 1, esto establece el nuevo valor de partida de outerVar cuando se invoca innerFn2 ( ) , y viceversa. Sin embargo, una vez ms, vemos que cualquier llamada siguiente
a outerFn () crea nuevas instancias de estos closures con un nuevo entorno de cierre
con el que coincidir.
Los seguidores de la programacin orientada a objetos observarn que hemos creado un nuevo objeto, con las variables libres actuando como variables de instancia, y los
closures actuando como mtodos de instancia.
Las variables son tambin privadas, ya que no se pueden referenciar directamente
fuera del mbito de aplicacin en el que se encuentran, permitiendo verdadera privacidad de datos orientados a objetos.
Casi todo el cdigo que escribimos utilizando jQuery acaba situndose dentro de una
funcin pasada como un argumento a $ (document) . ready ( ) . Realizamos esto para
garantizar que el DOM se ha cargado antes de ejecutarse el cdigo, lo que es normalmente un requisito para cdigo jQuery interesante. Cuando se crea una funcin y se pasa a
. ready ( ) , una referencia a la funcin se almacena como parte del objeto global jQuery.
Esta referencia se invoca luego en un momento posterior, cuando el DOM est listo.
Normalmente situamos la construccin $ (document) . ready () en el nivel superior de la estructura de cdigo, de modo que esta funcin no es en realidad parte de un
closure. Sin embargo, puesto que nuestro cdigo se escribe normalmente dentro de esta
funcin, el resto es una funcin interna:
$ (document) .ready(function()
var readyVar = o;
function
innerFn()
(
readyVar++
$('#example-9')
.print('readyVar
}
innerFn() ;
innerFn() ;
}) ;
, + readyVar);
Esto se parece a muchos de nuestros ejemplos anteriores, excepto que en este caso, la
funcin exterior es la rellamada pasada a $ (document) . ready () . Puesto que innerFn () se define dentro de ello, y hace referencia a rea?yVar que est en el mbito de aplicacin de la funcin de rellamada, innerFn () y su entorno crean un closure. Podemos
ver esto al observar que el valor de readyVar persiste entre llamadas a la funcin:
readyVar
readyVar
=
=
1
:2
El hecho de que la mayor parte del cdigo jQuery est dentro de un cuerpo de funcin es de utilidad, ya que esto puede proteger contra algunas colisiones de espacio de
nombre. Por ejemplo, es esta caracterstica la que nos permite utilizar j Query . no Con f 1i ct () para liberar el mtodo abreviado $ para otras libreras, mientras se puede seguir
definiendo el mtodo abreviado localmente para uso en $ (document) . ready ( ) .
lmI
Estos ejemplos han utilizado funciones annimas, como ha sido nuestra costumbre
en cdigo jQuery. Esto no cambia nada en la construccin de closures; los closures pueden proceder de funciones con nombre o annimas. Por ejemplo, podemos escribir una
funcin annima para informar del m.diee de un elemento dentro de un objeto jQuery:
Manejadores de evento
La construccin $ (document) . ready () normalmente engloba el resto de nuestro
cdigo, incluida la asignacin de manejadores de evento. Puesto que los manejadores
son funciones, se convierten en funciones internas. Puesto que estas funciones internas
se almacenan e invocan ms tarde, pueden crear closures. Un sencillo manejador el i ck
puede ilustrar esto:
$ (document) .ready(function()
var counter = o;
$('#example-lO
a.add') .click(function()
counter++i
$('#example-lO') .print('counter =
return false
})
counter);
Puesto que la variable counter se declara dentro del manejador . ready (), solamente se encuentra disponible para el cdigo jQuery dentro de este bloque y no para
cdigo de fuera. Se puede hacer referencia por el cdigo en el manejador di ck que, sin
embargo incrementa y muestra el valor de la variable. Puesto que se crea un closure, la
misma instancia de counter se hace referencia cada vez que se hace clic en el vnculo.
Esto significa que los mensajes muestran un conjunto en continuo crecimiento de valores, no simplemente 1 cada vez:
=
counter
counter
= 2
e
Puesto que la funcin ms interna se define dentro de la rellamada . each ( ) , este cdigo crea tantas funciones como vnculos hay. Cada una de estas funciones se anexa como
un manejador el i ck a uno de los vnculos. Las funciones tienen index en su entorno de
cierre, ya que es un parmetro para la rellamada . each () . Esto se comporta de la misma
forma como si el manejador click estuviera escrito como una funcin cori nombre:
$ (document) .ready(function()
{
$('#example-13
a') .each(function(index)
function
clickHandler()
(
$('#example-13')
.print('index
return false
})
})
Los manejadores de evento pueden compartir sus entornos de cierre, como hacen
otras funciones:
$ (document) .ready(function()
{
var counter = Oi
$('#example-ll
a.add') .click(function()
counter++
$('#example-ll') .print('counter =
return false
})
counter)
index);
.click(clickHandler);
La versin con la funcin annima es algo ms corta. La posicin de esta funcin con
nombre sigue siendo relevante, sin embargo:
$ (document) .ready(function()
(
function
clickHandler()
(
$ ('#example-14')
.print('index
return false
'
= '
+ index);
$(this)
counter
= '
j);
})
});
})
$ (document) .ready(function()
{
$('#example-12
a') .each(function(index)
$(this) .click(function()
(
$('#example-12')
.print('index
return false
/
lliII
index);
$ ('#example-14
a') .each(function(index)
$ (this) .click (clickHandler)
;
$('#example-ll
a.subtract')
.click(function()
counter--
$('#example-ll') .print('counter =
+ counter);
return false
j);
})
})
Esta versin activar un error JavaScript siempre que se haga clie en un vnculo porque index no se encuentra en el entorno de cierre de clickHandler
() . Sigue siendo
una variable libre, y por lo tanto no definida en este contexto.
Puesto que ambas funciones hacen referencia a la misma variable counter, las operaciones de incremento y decremento de los dos vnculos afectan al mismo valor en lugar
de ser independientes:
counter
counter
counter
counter
= 1
2
1
lI:l
1j,
lmlII
alert(outerVar)
}
outerVar.fn ~ innerFn
return innerFnn;
};
Aqu, un objeto denominado outerVar se crea y referencia desde dentro de la funcin interna innerFn () . Luego, se crea una propiedad de outerVar
que apunta a
innerFn (), y se devuelve innerFn () . Esto crea un closure en innerFn () que hace
referencia a outerVar, que a su vez hace referencia a innerFn () . Pero el bucle puede
ser ms insidioso que esto:
('
function
outerFn()
(
var outerVar
= {};
function innerFn()
alert ("he Ll.o') ;
outerVar.fn = innerFn
return innerFn;
Aqu el objeto A tiene una propiedad que apunta a B, y B tiene una propiedad que
apunta a e Incluso si el objeto A aqu es el nico que es una variable en el mbito actual, los tres objetos deben permanecer en memoria debido a los punteros hacia ellos.
Cuando A sale del mbito de aplicacin, sin embargo (como al final de la funcin en la
que se declar), entonces se puede liberar por el recolector de basura. Ahora B no tiene
nada apuntando hacia l, por lo que se puede liberar, y finalmente C tambin se puede
liberar. Puede ser ms difcil tratar con organizaciones de referencias ms complicadas,
como muestra la figura e2.
la
};
Aqu, hemos cambiado innerFn () de modo que ya no haga referencia a outerVaro Sin embargo, esto no rompe el bucle. Aunque outerVar no se hace nunca referencia desde innerFn (), sigue estando en el entorno de cierre de innerFn () . Todas
las variables en el mbito de outerFn () se les hace referencia implcitamente por innerFn () debido al closure. Por lo tanto, los closures facilitan la creacin accidental de
estos bucles.
ms compleja.
Ahora hemos aadido una propiedad al objeto C que hace referencia a B. En este
caso, cuando se libera A, B sigue teniendo un puntero hacia l desde e Este bucle de
referencia se tiene que gestionar especialmente por JavaScript, que debe observar que
todo el bucle se asla de las variables que estn en mbito.
};
})
Cuando se asigna el manejador el ck, esto crea un closure con di ven el entorno de
cierre. Pero di v ahora contiene una referencia de vuelta al closure, la propia propiedad
onclick. De esta forma, el bucle resultante no se puede liberar por Internet Explorer
incluso cuando nos alejamos de la pgina.
lIl1!I
la buena noticia
Ahora, escribamos el mismo cdigo, pero utilizando construcciones jQuery normales:
$ (document) .ready(function()
var $div = $('#foo');
$div.click(function()
alert ('hello' ) ;
})
})
Aunque todava est creado un closure, causando el mismo tipo de bucle que antes,
no tenemos una prdida de memoria lE de este cdigo. Afortunadamente, jQuery es
consciente del potencial de prdidas, y libera manualmente todos los manejadores de
evento que asigna. Siempre y cuando sigamos utilizando los mtodos de vinculacin de
evento jQuery para nuestros manejadores, no tenemos que temer prdidas.
Esto no significa que estemos totalmente liberados; debemos continuar teniendo cuidado cuando llevamos a cabo otras tareas con elementos DOM. Anexar objetos JavaScript
a elementos DOM puede seguir causando prdidas de memoria en Internet Explorer;
jQuery ayuda a que esta situacin sea menos frecuente.
Debido a esto, jQuery nos proporciona otra herramienta para ayudar a evitar estas
prdidas. En el captulo 7 vimos que el mtodo. data () nos permite anexar informacin a elementos DOM de la misma forma que lo hacemos con propiedades expando.
Puesto que estos datos no se almacenan directamente como un expando (jQuery utiliza un mapa interno para almacenar los datos utilizando las identificaciones que crea),
el bucle de referencia nunca se forma y nosotros evitamos el problema de prdida de
memoria. Siempre que un expando parece un mecanismo de almacenamiento de datos
conveniente, deberamos considerar si . data () es una alternativa ms segura.
Resumen
Los closures JavaScript son una potente caracterstica del lenguaje. A menudo son
bastante tiles al ocultar variables de otro cdigo, de modo que no pisamos nombres
de variables utilizadas en algn otro sitio. Debido a la dependencia frecuente de jQuery
de funciones como argumentos de mtodo, tambin se pueden crear sin darse cuenta
bastante a menudo. Entenderlo nos permite escribir cdigo ms eficiente y conciso, y
con un poco de cuidado y el uso de las precauciones incorporadas de jQuery, podemos
evitar los peligros relacionados con memoria que pueden introducir.
./
i't'\'&
,,
./
.'
Apndice O
Referencia rpida
Este apndice est pensado como una referencia rpida para la API jQuery, incluidos expresiones de selector y mtodos, Una explicacin ms detallada de este tema se
encuentra disponible en la documentacin jQuery en, http : / / docs . j query . com,
Expresiones de selector
La funcin factory jQuery $ () se utiliza para encontrar elementos en la pgina con
los que trabajar. Esta funcin toma una cadena compuesta de sintaxis a modo CSS, denominada una expresin de selector. Las expresiones de selector se tratan en detalle en
el captulo 2.
#id
element
.class
a, b
ab
a>b
de a.
lll!I
a+b
Elementos b a continuacin
a-b
:first
de a.
l:I!'a
:nth-chilq~formula)
: first-child
:last
:last-child
:not(a)
:even
:odd
: eq(index)
:gt (index)
resultado
(mayor
que)
"
:only-child
: input
:text
Elementos <input>
con t ype
:password
Elementos <input>
con type~"password".
: radio
Elementos <input>
con type~"radio".
:checkbox
con type~"
:submit
Elementos <input>
con type~"submit".
:image
Elementos <input>
con type~"image".
:reset
con t.ype
<input>,
e v
t.ext ".
checkbox".
:lt(index)
:header
Elementos de encabezado
:animated
:contains(text)
:empty.
:file
:has(a)
:enabled
:disabled
:parent
:checked
:hidden
:selected
:visible
Lo inverso de : hidden.
[attrl
Ia t t reva Lue l
[attr!
~valuel
:button
Elementos
<input>
e "
reset".
con t.ype
bu t t on
v ,
y elementos
but t.on .
Elementos <input>
con type~"file".
es value.
no es value.
[attrA~valuel
[attr$~valuel
[attr*~valuel
:nth-child(index)
:nth-child(even)
:nth-child(odd)
.filter(selector)
Elementos seleccionados
tado.
lI!IlI
ID
Mtodos de evento
.filter(callback)
Elementos seleccionados
devuelve true.
. eq(index)
El elemento seleccionado
Elementos
base O.
seleccionados
Elementos
facilitado.
seleccionados
slice
(start,
[endl )
.not(selector)
que no coinciden
con el selector
/
.add(selector)
.find(selector)
Elemento descendiente
contents
()
children
( [selectorl)
next ( [selectorl
prev ( [selectorl
prevAll ( [selectorl
siblings
. parents
( [selectorl
closest
se lector
offsetParent
()
. bi nd (type,
handler)
.one (type,
handler)
[dat.a} ,
[datal,
. unbind ( [typel ,
[handlerl)
El hermano inmediatamente delante de cada elemento seleccionado, opcionalmente filtrado por un selector.
.die(type,
.blur(handler)
.change(handler)
Vincular
cambia.
handler
.click(handler)
Vincular
mento .
handler
.dblclick(handler)
Vincular handler
elemento.
. error
( [selectorl)
parent ( [selectorl
. ready(handler)
nextAll ( [selectorl
filtrado
ve, absolute)
del
[handlerl)
(handler)
a invocar
cuando
.focus(handler)
andSel f ()
Los elementos seleccionados, ms el conjunto previo de elementos seleccionados en la pila jQuery interna.
. keydown(handler)
end ()
.keypress(handler)
map(callback)
.keyup(handler)
en la pila jQuery
1"
lB
.load (handler)
Vincular handler
cargarse.
.mousedown(handler)
.mouseenter(handler)
. mouseleave(handler)
dblclick
de
error
.mousemove(handler)
.mouseout(handler)
.mouseover(handler)
Vincular handler
en el elemento.
.mouseup(handler)
Vincular handler
en el elemento.
.resize(handler)
Vincular handler
tamao.
.scroll(handler)
.select(handler)
Vincular handler
elemento.
(~
()
focus ()
. keydown()
keypress
()
.keyup ()
.select()
submit ()
Mtodos de efecto
Estos mtodos de efecto se pueden utilizar para llevar a cabo animaciones en elementos DOM. Los mtodos de efecto se tratan en detalle en el captulo 4.
cambia de
show()
hide ()
.submit(handler)
Vincular handler
formulario.
show (speed,
[callbackl)
.unload(handler)
Vincular handler
de la memoria.
.hide(speed,
[calll:;Jackl )
toggle ( [speedl ,
[callbackl)
.hover(enter,leave)
.toggle(handlerl,
handler2,
... )
slideDown ( [speedl ,
[callbackl)
slideUp ( [speedl ,
[callback] )
. trigger
(type,
[data])
. triggerHandler(type,
[data] )
. blur()
. change ()
. click
()
lB
.slideToggle([speed]
[callbackl)
coincidentes
coincidentes
coincidentes
con un movimiento
desli-
con un movimiento
desli-
fadeln ( [speedl ,
[callback] )
.fadeOut( [speedl,
[callbackl)
al desvanecerlos
a opaco.
a transpa-
lIIiI
.fadeTo(speed,
opacity, [callbackl)
html (vaLue )
.animate(attributes,
[speedl, [easingl,
[callbackl)
text ()
.animate(attributes,
options)
.stop( [clearQueuel,
[jumpToEndl )
.queue ()
.queue(newQueue)
Reemplazar
.dequeue ()
Mtodos de manipulacin
value,
.text(value)
.queue(callback)
11III
.'
en value.
,..
val ()
.val(value)
.css(key)
.css(map)
Establecer valores
clave-valor.
.offset()
.position()
scrollTop ()
vertical
.scrollTop(value)
.scrollLeft()
.scrollLeft(value)
.height ()
de atributo
key .
key en value.
CSS, facilitados
como pares
.offsetParent ().
DOM
.attr(key)
.attr(key, value)
.attr(key, fn)
.attr(map)
.removeAttr(key)
.addClass(class)
key .
key en value .
key .
.removeClass(class)
.toggleClass(class)
.hasClass(class)
.html ()
.height(value)
Establecer
del primero
horizontal
del primer
horizontal de todos
coincidentes
en
value.
.width()
.width(value)
coincidentes
en
value.
innerHeight ()
coincidente,
incluido
innerWidth ()
.outerHeight
(includeMargin)
11II
Mtodos AJAX
.outerWidth
(includeMargin)
. append(content)
Insertar content
dente.
.appendTo(selector)
.prepend(content)
Insertar content
coi ncidente.
.prependTo(selector)
incluido
.after(content)
Insertar content
.insertAfter(sel~ctor)
. before(content)
.insertBefore
(selector)
.wrap(content)
.wrapAll(content)
wraplnner
$.ajax(options)
l'
.load (url,
[callback)
[data),
[data),
$ . get (url,
[callback)
[returnType)
,
)
$. getJSON (url,
[callback)
)
[data),
$.getScript(url,
[callback)
)
$. post (url,
[data),
[callback)
,
[returnType)
)
aj axComplete
Vincular handler
a invocar cuando se completa cualquier
transaccin AJPIX.
(content)
aj axError
replaceWi
th (content)
aj axSend (handler)
Vincular handler
saccin AJPIX.
replaceAll
(selector)
.ajaxStart
Vincular handler
a invocar cuando comienza cualquier transaccin AJPIX, y ninguna otra est activa.
empty ()
(handler)
con los
(handler)
remove ( [selector)
clone
(handler)
( [wi thHandlers))
data (key)
(handler)
Realizar una copia de todos los elementos coincidente, opcionalmente tambin copiando manejadores de evento.
Obtener el elemento de datos denominado key asociado con
el primer elemento coincidente.
da ta (key,
val ue)
removeData
(key)
aj axSuccess
$ . aj axSetup
serialize
(handler)
(options)
()
serializeArray
$ . param (map)
Vincularhandler
a invocar cuando termina cualquier transaccin
AJPIX, y ninguna otra est todava activa.
Vincular handler a invocar cuando cualquier transaccin AJPIX
se completa con xito.
Establecer opciones predeterminadas para todas las transacciones AJPIX siguientes.
Codificar los valores de un conjunto de controles de formulario
en una cadena de consulta.
()
In~'
,~
,
.
lndice
Mtodos variados
Estos mtodos no encajan bien en las categoras anteriores, pero son a menudo de
utilidad cuando se escriben scripts utilizando jQuery.
$.support
$.each(collection,
callback)
$.extend(target,
addition,
... )
$.grep(array,
callback,
[invert])
Filtrar array
$.makeArray(object)
$. map(array,
callback).
$. inArray (value,
$ . merge (arrayl,
array)
array2)
ejecutando
callback
para cada
al utilizar callback
y array2.
$ . unique (array)
$. trim(string)
$ . noConf 1 i ct
( [extreme] )
hasClass
Determinar
tada.
(className)
alfabtico
is (selector)
each (callback)
ejecutando callback
.length
get ()
get (index)
index (element)
a los ele-
al elemento coincidente
A
acciones, jQuery
acceder a elementos
en un documento, 30
alterar el contenido
de un documento, 30
animar cambios realizados a un
documento, 30
Asynchronous JavaScript y XML
(AJAX),30
11III
fndice alfabtico
ndice atjabtico
.fadelru). mtodo, 99
.fade'I'ogglef), mtodo, 99
posicionar con CSS, 101
efectos
alternar aparecer y desaparecer
paulatino, 99
animar mltiples propiedades, 100
crear, 98
posicionar con CSS, 101
apariencia de tabla,
filtrado
comportamiento
expandir,211
ocultar, 211
implementar, 211
interactuar con otro cdigo, 214
invertir los filtros, 213
opciones de filtro, 212
modificar
contraer secciones, 209
descripciones emergentes, 204
expandir secciones, 209
resaltar filas, 197
Aptana, herramienta, 387
Asynchronous HTTP y HTML, 137
Asynchronous JavaScript y XML, 134
atributos,
la funcin factory $0 revisada, 114
que no son clase, 112 _
manipular, 111
autocompletar, formularios compactos
autocompletar frente a live
search,253
completar el campo de bsqueda, 249
definir, 246
eliminar la lista de sugerencias, 253
en el navegador, 247
en el servidor, 247
gestionar las teclas del cursor, 251
insertar sugerencias en el campo, 252
navegacin por medio de teclado, 249
B
bajo demanda, .eargar datos,
aadir HTML, 137
cargar un documento XML, 146
definicin, 136
funciones jQuery globales, 141
trabajar con objetos JavaScript, 140
ltajo nivel, mtodo AJAX, 164
blogs
A list apart, 379
Ajaxian, 377
As days pass by, 379
DOM scripting, 379
el blog jQuery, 377
Estndares Web con imaginacin, 378
1can't, 378
JavaScript ant, 378
John Resig, 378
learning jQuery, 377
Recurso JavaScript de Matt Zinder, 378
Robert's talk, 378
Snook,378
e
clculos numricos, datos de formulario
numricos
analizar formato moneda,261
aplicar formato a moneda, 261
otros clculos, 264
redondear valores, 265
toques finales, 265
tratar con decimales, 262
caractersticas jQuery
abstraer fallos de navegador, 31
aprovechar conocimiento de CSS, 31
permitir mltiples acciones, 31
soportar extensiones, 31
trabajar con conjuntos, 31
lIfI
lIlI
ndice
ndice alfabtico
D
datos, AJAX
aadir HTML, 137
cargar un documento XML, 146
el mtodo AJAX de bajo nivel, 164
elegir de
archivos JavaScript, 150
archivos JSON, 150
documentos XML, 150
fragmentos HTML, 150
limitaciones de seguridad, 161
opciones adicionales, 163
recuperar un objeto JavaScript, 140
trabajar con objetos JavaScript, 140
datos de formulario numricos, trabajar
con,256
clculos numricos, 260
editar informacin de envo, 270
eliminar elementos, 266
E
efecto, mtodos, 409
efectos
animaciones personalizadas
alternar aparecer y desaparecer
paultino, 99
animar mltiples propiedades, 100
crear, 98
posicionar con CSS, 101
efectos simultneos, crear, 102
en cola, 102
mtodos bsicos, 93
rellamadas, 107
alfabtico
EDil
estilo de formulario
definicin, 221
expresin regular, 227
leyenda, 228
manipulacin de casilla
de verificacin, 238
evento, mtodos, 407
evento, objeto
.ist) mtodo, utilizar, 79
.preventDefaultO, mtodo, 77
.stopPropagationO, mtodo, 77
acciones predeterminadas, 77
definicin, 75
delegacin de evento, 78
destinos de los eventos, 76
propiedad evenUarget, 78
eventos
abreviados, 68
alterar, 75
acciones predeterminadas, 77
delegacin de evento, 78
destinos de los eventos, 76
detener la propagacin, 76
objeto event, 75
compuestos, 70
.hovert), mtodo, 70
.togglef), mtodo, 70
destacar elementos sobre
los que se hace clic, 71
mostrar caractersticas avanzadas, 70
ocultar caractersticas avanzadas, 70
conmutador de estilo,
contexto de manejador de evento, 65
habilitar otros botones, 63
mayor consolidacin, 67
de te dado, 84
de usuario,
hoverIntent,342
Live Query, 342
efectos secundarios del burbujeo
de eventos, 74
1m
ndice alfabtico
ndice alfabtico
:radio, 405
:reset, 405
:selected, 405
:submit, 405
:text, 405
:visible, 404
[attrl=value], 404
[attr$=value], 404
[attr*=value], 404
[attr],404
[attrl\=value],404
[attr=value],404
a - b, 404
a + b, 404
a> b, 403
a b, 403
.'
a,b,403
aadir pseudos-clase, 366
crear, 366
element, 403
parmetros
element, 367
index,367
matches, 367
set, 367
utilizar, 366
F
fadelru), mtodo, 97
fadeOutO, mtodo, 97
Fiddler, herramienta, 387
filas, apariencia de la pgina, 197
alternar color de filas, 198
avanzado, 200
resaltar filas, 197
basado en interaccin del usuario, 202
filtrado, apariencia de tabla
comportamiento expandir, 211
comportamiento ocultar, 211
implementar,211
interactuar con otro cdigo, 214
invertir los fi~tros, 213
opciones de filtro, 212
Firebug Lite, herramienta, 386
Firefox, herramientas
barra de herramientas
de desarrollador Web, 384
comprobador de expresiones
/
regulares, 384
Firebug, 383
Venkman, 384
Form, plug-in
.ajaxf'ormf), mtodo, 323
.ajaxSubmitf), mtodo, 323
definicin, 323
opcin
beforeSubmit, 323
success, 323
target, 323
formulario,
compactos
autocompletar, 246
completar el campo
de bsqueda, 249
eliminar la lista de sugerencias, 253
en el navegador, 247
en el servidor, 247
gestionar las teclas del cursor, 251
insertar sugerencias
en el campo, 252
navegacin por medio
de teclado, 249
sobre autocompletar, 246
completar el campo de bsqueda, 249
sobre formularios compactos, 243
definicin, 229
estilo
definicin, 221
expresin regular, 227
leyenda, 228
ID
manipulacin de casilla
de verificacin, 238
estilo de formulario mejorado, 222
mejorar un formulario bsico, 221
validacin, 231
campos obligatorios, 231
campos, 231
expresin regular, 235
formatos de entrada de datos, 234
formatos obligatorios, 231
regla, 231
tareas de cdigo, 235
ltima comprobacin, 231
validacin del lado del servidor, 231
formularios, plug-ins
Autocomplete, 333
Jeditable, 334
Masket input, 335
Validation, 334
funcin factory $0
bloques principales
clase, 42
evitar iteracin explcita, 37
nombre de etiqueta, 42
caractersticas, 42
definicin, 42
insertar mtodos con, 115
funciones globales,
aadir mltiples funciones, 346
crear un mtodo de utilidad, 347
ventaja, 347
funciones internas,
definicin, 389
el gran escape, 390
G
GNU, licencia pblica, 32
grficas, plug-ins
Flot, 341
Sparklines, 341
lB
lndice aifabtico
lndice alfabiico
H
herramientas
otras herramientas,
Aptana,387
Charles, 387
Fiddler, 387
Firebug Lite, 386
NitobiBug, 386
paquete TextMate jQuery, 387
para Firefox, 383
barra de herramientas
de des arrollador Web, 384
comprobador de expresiones
regulares, 384
Firebug, 383
Venkman, 384
para Internet Explorer, 384
DebugBar, 385
Drip, 385
Microsoft Internet Explorer
Developer Toolbar, 384
Microsoft Visual Web Developer, 385
para Opera, 386
Dragonfly, 386
Inspector W eb, 386
para Safari, 385
Inspector Web,386
men Develop, 385
HTML, elementos de formulario, 229
1
imgenes, carrusel
ampliar imagen
animar la ampliacin
de la portada, 309
aadir un indicador de carga, 314
aplazar las animaciones hasta
que la imagen se carga, 313
J
JavaScript
closures, 395
compresores de cdigo, 375
compressor YUI, 375
JSMin,375
Pretty printer, 376
referencia (X)HTML, 376
objeto,
"
$.getJSONO, funcin, "
como funcin global, 141
$.getJSONO, funcin, definicin, 141
$.getJSONO, funcin, mtodo
de clase, 141
funciones jQuery globales, 141
recuperar objeto, 140
ordenacin,
alternar la direccin
de ordenacin, 186
etiquetas de agrupacin, 175
manipular teclas de ordenar, 182
&1
ndice aIfabtico
ndice aIfabtico
ThemeRoller, 332
Widgets, 330
JSON,162
JSONP, 162
mtodos abreviados,
aadir, 356 ,
mostrar elementos, 357
ocultar elementos, 357
personalizados, 358
mtodos de objeto jQuery, 15
mtodos transversales, DOM
aplicar estilo a celdas especficas, 52
, definicin, 51
(
encadenar, 53
funcin filter, 52
recorrer el DOM, 52
ventajas de encadenar, 53
mover elementos, 118
marcar el contexto, 121
numerar el contexto, 121
vincular el contexto, 121
MSDN Script, 375
manejador de evento, 80
eliminar, 80
espacio de nombres de evento, 80
volver a vincular eventos, 81
manipulacin de tabla
filtrado, 211
modificar apariencia de la tabla, 197
ordenacin JavaScript, 173
ordenar y paginar, 172
paginacin
del lado del servidor, 186
JavaScript, 190
memoria, peligros de prdidas, 397
bucles de referencia accidentales, 398
problema de prdidas de memoria de
Internet Explorer, 399
mensajes de campo, formulario
expresin regular, 227
insertar, 225
leyenda, 227
NitobiBug, herramienta,
386
o
objeto evento
.istt) mtodo, utilizar, 79
.preventfzefaultf), mtodo, 77
.stopf'ropagationf), mtodo, 77
acciones predeterminadas, 77
definicin, 75
delegacin de evento, 78
destinos de los eventos, 76
propiedad evenUarget, 78
objeto JavaScript,
$.getJSONO, funcin,
como funcin global, 141
definicin, 141
mtodo de clase, 141
funciones jQuery globales, 141
recuperar, 140
ID
Opera, herramientas
Dragonfly, 386
ordenacin JavaScript, 173
alternar la direccin
de la ordenacin, 186
el poder de los plug-ins, 179
etiquetas de agrupacin de filas, 175
manipular teclas de ordenar, 182
ordenacin alfabtica bsica, 175
ordenar otros tipos de datos, 183
plug-ins, 179
rendimiento, 180
resaltar columna, 186
p
pgina, cargar
coexistir con otras libreras, 60
mtodos abreviados para cdigo, 60
mltiples scripts en una pgina, 58
planificacin de la ejecucin
de cdigo, 57
paginacin, datos
paginacin del lado del servidor, 188
paginacin JavaScript, 190
paginacin del lado del servidor
definicin, 188
ordenar y paginar, 188
paginacin JavaScript, 190
habilitar los botones del pagnador, 192
marcar la pgina actual, 183
mostrar el paginador, 191
paginacin con ordenacin, 194
parmetros de mtodo
definicin, 359
funciones de rellamada, 363
mapas de parmetro, 361
parmetros sencillos, 360
predeterminados personalizables, 364
valores de parmetro
predeterminados, 362
I!B
ndice alfubetico
ndice alfabtico
imgenes
Jcrop, 337
Magnify, 337
librera de plug-ins jQuery DI, 325
Lightbox
BlockDI,340
FancyBox, 338
jqModal, 340
Thickbox, 339
tablas,
Flexigrid, 337
jqGrid,336
Tablesorter, 336
proyecto jQuery
fase de desarrollo pblico, 32
jQuery 1.1, 32
.'
jQuery 1.1.3, 32
jQuery 1.2, 32
jQuery 1.2.6, 33
jQuery 1.3, 33
jQuery DI, 32
jQuery
expresiones de selector, 403
mtodos f
AJAX, 413
de efecto, 409
de evento, 407
de manipulacin DOM, 410
transversales DOM, 405
.
variados, 414
l'
(X)HTML
pgina principal de W3C, 376
rotativos
aadir un indicador de carga, 289
configurar, 282
definicin, 276
detenerse al pasar por encima, 286
efecto degradado, 290
funcin rotar titular, 283
recuperar un feed de un dominio
diferente, 288
titular rotativo, 277
.show), mtodo, 95
.show('fast'), mtodo, 96
.show('normal'), mtodo, 96
.show('slow'), mtodo, 96
Safari, herramientas
definicin, 385
inspector Web, 386
men Develop, 385
seguridad, limitaciones,
cargar datos remotos, 161
utilizar JSONP para datos remotos, 162
utilizar etiqueta HTML <iframe>, 162
selecto res .
cSS
aplicar estilo a niveles
de elementos de lista, 44
definicin, 43
EflI
de atributo
aplicar estilo a vnculos, 46
definicin, 46
personalizados
aplicar estilo a filas alternas, 48
definicin, 48
numeracin
en base
cero, 49
uno,49
selectores de formulario, 51
smbolos
$.ajax(options),413
$.ajaxSetup(options),413
$.each(collection, callback), 414
$.extend(target, addition, ..."),414
$.get(url, [data],[ callback],
[returnType]),413
$.getJSON(url, [data],[callback]), 413
$.getScript(url,[callback]),413
.
$.grep(array, callback,[invert]), 414
$.grep(array, callback,[invert]), 414
$.inArray(value, array), 414
$.inArray(value, array), 414
$.isFunction( object)
$.isFunction(object),414
$.makeArray(object),414
$.map(array, callback), 414
$.merge(arrayl, array2), 414
$.noConflict ([extreme]), 414
$.param(map),413
$.post(url, [data],[callback],
[returnType]),413
$.trim(string),414
$.trim(string),414
$.unique(array),414
$.unique(array),414
(X)HTML, referencia
.add(selector),406
.addClass(class),410
.after(content),412
mi
ndice alfabtico
ndice alfabtico
.ajaxComplete(handler),413
.ajaxComplete(handler),413
.ajaxError(handler),413
.ajaxSend(handler),413
.ajaxStart(handler),413
.ajaxStart(handler),413
.ajaxStop(handler), 413
.ajaxStop(handler), 413
.ajaxSuccess(handler),413
.ajaxSuccess(handler), 413
.andSelf0,406
.animate), mtodo, 98
.animate(attributes, [speed],
[easing],[ callback D, 410
.animate(attributes,options),41O
.append(content),412
.appendTo(selector),412
.attr(key),41O
.attr(key, fn), 410
.attr(key, value), 410
.attr(map),410
.before(content),412
.bind('load'), sintaxis, 314
.bind(type, [data],handler), 407
.blur0,408
.blur(handler),407
.changeO,408
.change(handler),407
.children([selectorD,406
.click0,408
.click(handler),407
.clone([withHandlersD,412
.closest selector, 406
.contents0,406
.css(key), 411
.css(key, value), 411
.css(map),411
.data(key), 412
.data(key, value), 412
.dblclickO, 409
.dblclick(handler),407
.dequeuer), 410
.die(type, [handler]), 407
.each(callback),414
.empty0,412
.end0,406
.eq(index),406
.errort), 409
.error(handler),407
.fadeIn([ speed ],[callback]), 409
.fadeOut( [speed],[ callback]), 409
.fadeTo(speed, opacity.] callback]), 410
.filter(callback),406
.filter( selector), 405
.find(selector),406
.focusO,409
.focus(handler),407
.getO,414
.get(index),414
.hasClass(class),410
.hasClass(className),414
.height0,411
.height(value),411
.hdet), 409
.hidet), mtodo, 83
.hide(speed,[callback]),409
.hover(enter,leave),408
.htmlt), 410
.htrnl(value),411
.index(element),414:
"
.innerHeight0,411
.innerWidth0,411
.insertAfter(selector),412
.insertBefore(selector),412
.is(selector),414
.keydowru), 409
.keydown(handler),407
.keypress), 409
.keypress(handler),407
.keyupt), 409
.keyup(handler),407
.length,414
ID
.scrollTop0,411
.scrollTop(value), 411
.select), 409
.select(handler),408
.serializef), 413
.serialize.Arrayl), 413
.show), 409
.showr). mtodo, 93
.show(speed,[callbackD,409
.siblings([selectorD,406
.slice(start, [endD, 406
.slideDown([speed ],[callback D, 409
.slideToggle([speed],[ callbackj), 409
.slideUp([speed],[callbackD,409
.stop([ clearQueue ],[jump ToEnd D, 410
.submit), 409
.submit(handler),408
.text0,411
.textvalue), 411
.toggle([speedl,[callbackD,409
.toggle(handler1,handler2,
...),408
.toggleClass( class), 410
.trigger(type, [data]), 408
.triggert), mtodo, 83
implementar degradacin, 83
mtodos abreviados, 84
pgina, contraer, 83
pgina, expandir, 83
.triggerHandler(type,[dataD,408
.unbind([type],[handler]),407
.unload(handler),408
.valO,411
.val(value),411
.width0,411
.width(value),411
.wrap), mtodo, 124
.wrap(content),412
.wrapAll(content),412
.wrapInner(content),412
W3C hypertext markup language,
pgina principal, 376
lEIlI
ndice alfabiico
tablas
apariencia
contraer secciones, 209
descripciones emergentes, 204
expandir secciones, 209
resaltar filas, 197
manipulacin
filtrado, 211
modificar apariencia de la tabla, 197
ordenacin JavaScript, 173
ordenar y paginar, 172
paginacin del lado del servidor, 186
paginacin JavaScript, 190
plug-ins
Flexigrid, 337
jqGrid,336
Tablesorter, 336
teclado, eventos de
.keyCode, propiedad, 84
aadir, 84
keydown,84
keypress, 84
keyup,84
TextMate jQuery, herramienta, 387
titular, rotativo
aadir un indicador de carga, 289
recuperar un feed de un dominio
diferente, 288
w
W3C,376
Wide Web Consortium,
(W3C), 376
x
XMLPath, lenguaje (XPath), 32