You are on page 1of 40

Fundamentos de JavaScript y AJAX

para desarrolladores y diseadores web


Jos Manuel Alarcn Agun

FUNDAMENTOS DE JAVASCRIPT Y AJAX PARA DESARROLLADORES Y DISEADORES WEB


No est permitida la reproduccin total o parcial de este libro, ni su tratamiento informtico, ni la transmisin de ninguna forma o por cualquier medio, ya sea electrnico, mecnico, por fotocopia, por registro u otros mtodos, sin el permiso previo y por escrito de los titulares del Copyright. Dirjase a CEDRO (Centro Espaol de Derechos Reprogrficos, www.cedro.org) si necesita fotocopiar o escanear algn fragmento de esta obra. DERECHOS RESERVADOS 2012, respecto a la primera edicin en espaol, por Krasis Consulting, S. L. www.Krasis.com ISBN: 978-84-939659-3-8

CREATIVIDAD: Diseo cubierta: Pablo Iglesias Francisco Fruta cubierta: Rambutn.


El rambutn o nefelio es un fruto originario de Malasia, comn en la isla de Java, que pertenece a la misma familia que el lichi, las Sapindceas, formada por ms de 1.000 especies de rboles y arbustos distribuidos por regiones clidas de todo el mundo. De hecho, por su aspecto se le conoce tambin como "Lichi peludo". Se trata de una fruta dulzona, muy agradable al paladar y de consistencia similar a la de las uvas. Tambin se le conoce en Centroamrica como "mamn chino".

Agradecimientos
Escribir un libro es una tarea muy dura. Hasta que uno lo intenta por primera vez no se da cuenta de cunto. Se necesita invertir muchsimas horas de trabajo que en trminos econmicos es casi imposible que salgan rentables (al menos en el caso un libro tcnico). Por ello, la principal razn para escribir un libro tcnico suele ser siempre el frikismo, el amor por la tecnologa y por la divulgacin, sobre todo si no es el primero (como es mi caso). Es complicado, por tanto, justificar en el trabajo las horas invertidas, por lo que casi todos los autores tcnicos que conozco utilizamos nuestras horas libres para escribir. Eso significa fines de semana de jornadas maratonianas, horas por la noche despus del trabajo y casi siempre sacrificar las vacaciones. Este libro lo escrib durante el verano de 2012. Bsicamente no tuve vacaciones y dej de lado en bastantes ocasiones a amigos, familia y especialmente a mi mujer. As que quiero, como siempre, agradecerle a Eva su compresin, su paciencia conmigo (engaada no vino, eso es verdad!), su amor, su amistad, su apoyo y asistencia sin los cuales ni esto, ni la empresa ni muchas otras cosas seran posibles, y por supuesto quiero dedicarle el libro con gran ( ) -1.2 X, Y, Z 1.2

http://bit.ly/SqOPQ0

Contenido
AGRADECIMIENTOS ............................................................................................... III CONTENIDO .............................................................................................................. V PRESENTACIN ...................................................................................................... XI CAPTULO 1: INTRODUCCIN AL LENGUAJE JAVASCRIPT ........................ 1 1.- Versiones de JavaScript y la problemtica de la compatibilidad .......................................1 2.- Editores de JavaScript para la Web..........................................................................................3 2.1.- Microsoft Visual Studio Express Edition .................................................................... 3 2.2.- Aptana Studio ................................................................................................................... 4 2.3.- JetBrains WebStorm ....................................................................................................... 5 2.4.- JS Fiddle .............................................................................................................................. 6 2.5.- Maquetta ............................................................................................................................ 7 3.- La etiqueta <script> .....................................................................................................................8 3.1.- El atributo type............................................................................................................... 10 3.2.- Inclusin de archivos externos................................................................................... 11 4.- Comentarios en el cdigo ....................................................................................................... 12 5.- Y si el navegador no soporta JavaScript? ........................................................................... 13 CAPTULO 2: TIPOS DE DATOS, VARIABLES Y FUNCIONES BSICAS ...15 1.- Declaracin de variables .......................................................................................................... 15 2.- Tipos de datos ............................................................................................................................ 17 2.1.- El tipo String o Cadena................................................................................................. 18 2.2.- Tipos numricos............................................................................................................. 20 2.3.- Variables Booleanas o indicadores ............................................................................ 22 2.4.- Variables Nulas ............................................................................................................... 23 3.- Conversin entre tipos de datos........................................................................................... 24 3.1.- Conversin implcita de tipos ..................................................................................... 24 3.2.- Conversin explcita de tipos ..................................................................................... 25 4.- Definicin bsica de funciones ............................................................................................... 28 5.- mbito de las variables ............................................................................................................ 30 6.- Notacin de variables y funciones ........................................................................................ 33 CAPTULO 3: OPERADORES DE JAVASCRIPT .................................................37 1.2.3.4.5.Operadores de JavaScript........................................................................................................ 37 Precedencia de operadores .................................................................................................... 38 Incrementos y Decrementos .................................................................................................. 40 Operadores lgicos................................................................................................................... 41 Operadores bit a bit ................................................................................................................. 43

vi Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

5.1.- La representacin de los nmeros ............................................................................ 44 5.2.- Los operadores de desplazamiento de bits............................................................. 48 6.- Operadores de asignacin....................................................................................................... 49 7.- Operaciones matemticas. El objeto Math. ........................................................................ 50 7.1.- Funciones Logartmicas y exponenciales ................................................................. 50 7.2.- Races cuadradas ............................................................................................................ 51 7.3.- Potencias de nmeros .................................................................................................. 51 7.4.- Funciones de acotacin y redondeo ......................................................................... 51 7.5.- Nmeros aleatorios ...................................................................................................... 52 7.6.- Funciones trigonomtricas .......................................................................................... 53 7.7.- Funciones mximo y mnimo ...................................................................................... 54 7.8.- La funcin Signo ............................................................................................................. 54 7.9.- Constantes matemticas definidas en Math ............................................................ 55 8.- La clusula with .......................................................................................................................... 56 CAPTULO 4: ESTRUCTURAS DE CONTROL DE FLUJO ...............................59 1.- Condicionales: La estructura if-else ...................................................................................... 59 1.1.- Cortocircuito de expresiones condicionales.......................................................... 63 2.- Bucles determinados. La clusula for................................................................................ 66 2.1.- Anidamiento de bucles ................................................................................................. 68 2.2.- Bucles for-in para enumeraciones ............................................................................. 69 3.- Bucles indeterminados. Estructuras while y do-while.................................................. 70 3.1.- Evitar los bucles infinitos.............................................................................................. 72 4.- Cmo salir a propsito de un bucle ..................................................................................... 74 5.- Evaluacin de casos. Estructura switch - case.................................................................. 77 CAPTULO 5: MATRICES EN JAVASCRIPT ........................................................83 1.2.3.4.5.Definicin de matrices ............................................................................................................. 84 Inicializando matrices................................................................................................................ 89 Matrices con varias dimensiones ........................................................................................... 90 Matrices asociativas................................................................................................................... 91 Mtodos del objeto Array....................................................................................................... 92 5.1.- Manipulacin de elementos ......................................................................................... 92 5.2.- Ordenacin, bsqueda y procesamiento ................................................................. 95

CAPTULO 6: MANEJO DE CADENAS DE TEXTO .........................................101 1.- Conceptos bsicos sobre cadenas de texto ..................................................................... 101 1.1.- Codificacin de caracteres: ASCII, UNICODE, UTF-16 ................................... 101 2.- Anlisis de cadenas de texto................................................................................................. 104 3.- Filtrado de cadenas de texto ................................................................................................ 109 4.- Comparacin de cadenas de texto ..................................................................................... 111 5.- Funciones para formato HTML ............................................................................................ 112 6.- ejemplo real: Conversin a nmeros romanos ............................................................... 113

vi

Contenido vii

CAPTULO 7: FECHAS, HORAS Y TEMPORIZADORES ................................119 1.2.3.4.5.Qu hora es? ........................................................................................................................... 120 Las partes del tiempo: formatos propios .......................................................................... 123 Hora Universal Coordinada.................................................................................................. 126 Mtodos de cambio de hora................................................................................................. 128 Temporizadores y cronmetros ......................................................................................... 129 5.1.- La precisin de los intervalos de tiempo ............................................................... 132 6.- Ejemplo: Un reloj dentro de una pgina web ................................................................... 134 7.- Ejemplo: Diferencias de tiempos. Cuenta atrs. .............................................................. 136 CAPTULO 8: PROGRAMACIN ORIENTADA A OBJETOS CON JAVASCRIPT.............................................................................................................141 1.- Conceptos bsicos de POO ................................................................................................. 143 2.- Definiendo objetos en JavaScript......................................................................................... 144 2.1.- Constructores .............................................................................................................. 147 2.2.- Determinando el tipo de un objeto ........................................................................ 149 2.3.- Por qu la palabra clave this establece propiedades?........................................ 150 2.4.- Controlando el valor de contexto con call y apply ............................................ 153 3.- Prototipos.................................................................................................................................. 154 3.1.- Bsqueda de miembros y cadena de prototipos ................................................. 157 4.- Herencia en JavaScript............................................................................................................ 160 4.1.- Robo de constructores .............................................................................................. 163 5.- Encapsulacin en JavaScript................................................................................................... 165 5.1.- Clausuras y la verdadera regla de mbito de variables ...................................... 167 5.2.- Definicin de variables privadas en JavaScript ...................................................... 169 5.3.- Verdaderas propiedades encapsuladas ................................................................... 170 6.- Inspeccionando los objetos: Reflexin ............................................................................... 174 7.- Funciones con nmero variable de argumentos .............................................................. 177 CAPTULO 9: MANIPULACIN DINMICA DE ELEMENTOS: EL BOM Y EL DOM ...........................................................................................................................181 1.- Orgenes del DOM ................................................................................................................. 181 1.1.- El BOM o DOM Level 0............................................................................................. 182 1.2.- Los DOMs intermedios y el DOM Level 1 ........................................................... 183 1.3.- Los DOM Level 2 y Level 3....................................................................................... 183 2.- Trabajo con el BOM o DOM Level 0................................................................................. 185 2.1.- El objeto window ......................................................................................................... 186 2.1.1.- Propiedades del objeto window ...................................................................... 187 2.1.2.- Acceso a marcos de ventanas........................................................................... 189 2.1.3.- Mtodos del objeto window ............................................................................. 190 2.1.4.- Generacin de ventanas propias ...................................................................... 192 2.1.5.- Ventanas modales ................................................................................................ 194 2.2.- El objeto location......................................................................................................... 196 2.2.1.- Propiedades de location ..................................................................................... 196 2.2.2.- Mtodos del objeto location ............................................................................. 197

viii Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

2.3.- El objeto history........................................................................................................... 198 2.4.- El objeto navigator....................................................................................................... 199 2.4.1.- Propiedades de navigator................................................................................... 200 2.5.- El objeto screen ........................................................................................................... 201 2.6.- El objeto document en el BOM ............................................................................... 202 2.6.1.- Colecciones del objeto document en el BOM ............................................. 203 2.6.2.- Acceso a los elementos de formularios en el BOM ................................... 205 3.- Acceso y manipulacin de elementos con el DOM........................................................ 207 3.1.- Los nodos del DOM ................................................................................................... 207 3.2.- Recorriendo la estructura jerrquica del DOM .................................................. 209 3.3.- Obtener referencias directas a elementos del DOM......................................... 212 3.3.1.- Colecciones vivas y estticas ........................................................................ 215 3.4.- Principales propiedades base de los nodos ........................................................... 216 3.5.- Atributos y propiedades especficas de los nodos .............................................. 219 3.6.- Modificacin dinmica de la estructura del DOM ............................................... 221 CAPTULO 10: EVENTOS EN LAS PGINAS ...................................................225 1.- Un poco ms de historia para ubicarnos ........................................................................... 226 2.- Gestores de eventos en el BOM ......................................................................................... 227 2.1.- Anular la accin por defecto en el BOM ............................................................... 230 2.2.- Subclasificacin de eventos en el BOM: deshabilitar botn durante el envo de un formulario..................................................................................................................... 230 3.- Eventos segn DOM LEvel 2 ................................................................................................ 233 3.1.- Dnde se captura de verdad un evento? ............................................................. 233 3.2.- Gestin de eventos segn el DOM Level 2 .......................................................... 237 4.- Gestin de eventos con Internet Explorer 8-.................................................................. 239 5.- Un modelo de eventos unificado ......................................................................................... 241 6.- El objeto event ......................................................................................................................... 243 6.1.- El objeto event en el DOM ....................................................................................... 244 6.2.- El objeto event en Internet Explorer...................................................................... 246 6.3.- Un objeto event unificado ......................................................................................... 248 7.- eventos que podemos capturar en una pgina................................................................. 249 7.1.- Eventos de ciclo de vida de la pgina ...................................................................... 250 7.1.1.- Ejemplo: Detectando que la pgina est lista ................................................ 251 7.1.2.- Ejemplo: Detectando que se abandona la pgina ......................................... 253 7.2.- Eventos del ratn......................................................................................................... 256 7.2.1.- Ejemplo: cartel que persigue al ratn ............................................................. 258 7.2.2.- Ejemplo: anular el men contextual selectivamente ................................... 260 7.2.3.- Ejemplo: deteccin del scroll de la pgina ..................................................... 260 7.2.4.- Ejemplo: desactivar un botn de radio........................................................... 261 7.3.- Eventos de teclado ...................................................................................................... 264 7.3.1.- Ejemplo: Permitir solamente valores numricos ......................................... 267 7.3.2.- Ejemplo: Evitar pegar informacin ................................................................... 269 7.3.3.- Ejemplo: Control bsico de un marcianito .................................................... 271 7.4.- Anexo: Control avanzado de un marcianito ......................................................... 274 7.5.- Otros eventos .............................................................................................................. 275

viii

Contenido ix

7.5.1.- Eventos de formularios y controles de entrada........................................... 275 7.5.2.- Eventos de mutacin del DOM ........................................................................ 275 7.5.3.- Otros eventos sueltos ........................................................................................ 276 CAPTULO 11: FUNDAMENTOS DE AJAX .......................................................277 1.- Interfaces de usuario avanzadas ........................................................................................... 278 2.- El objeto XMLHttpRequest .................................................................................................. 280 3.- Uso prctico de XMLHttpRequest ..................................................................................... 282 3.1.- Envo de datos al servidor ......................................................................................... 285 4.- Problemas tpicos de AJAX ................................................................................................... 286 4.1.- Llamadas fuera de dominio........................................................................................ 286 4.2.- Gestin de errores y llamadas que no vuelven.................................................... 287 4.3.- Contenidos no actualizados debido a cachs ....................................................... 288 5.- Devolucin de informacin: JSON...................................................................................... 289 6.- JSONP: accediendo a datos en otros dominios............................................................... 292 6.1.- Una biblioteca propia para JSONP .......................................................................... 294 6.2.- Ejemplo: mostrar informacin de Twitter ............................................................ 296 7.- Control de acceso entre dominios: CORS....................................................................... 300 7.1.- Funcionamiento bsico de CORS ............................................................................ 301 CAPTULO 12: ERRORES COMUNES Y DEPURACIN DE APLICACIONES JAVASCRIPT.............................................................................................................303 1.- Errores tpicos cometidos en JavaScript ............................................................................ 303 1.1.- Maysculas y minsculas ............................................................................................ 305 1.2.- Variables de distinto mbito o no declaradas....................................................... 306 1.3.- Usar = en lugar de == al comparar......................................................................... 307 1.4.- Olvidarse de cerrar llaves o parntesis.................................................................. 307 1.5.- Cuanto esto no es lo que te esperas.................................................................. 308 1.6.- Tipos por referencia y cambios inesperados ........................................................ 308 2.- Gestin de excepciones......................................................................................................... 309 2.1.- Captura de errores a nivel de pgina ..................................................................... 313 3.- Herramientas de depuracin ................................................................................................ 313 4.- Herramientas para desarrolladores de Chrome ............................................................. 315 4.1.- La seccin de elementos de pgina ......................................................................... 317 4.2.- Recursos de la pgina.................................................................................................. 319 4.3.- Anlisis de red .............................................................................................................. 320 4.4.- Anlisis de scripts ........................................................................................................ 321 4.5.- La lnea temporal.......................................................................................................... 323 4.6.- El Profiler ................................................................................................................... 327 4.7.- Auditora de optimizacin de pginas ..................................................................... 327 4.8.- La consola de JavaScript ............................................................................................. 329 4.8.1.- Escribiendo a la consola desde cdigo ........................................................... 332 4.8.2.- Mensajes de consola destacados ...................................................................... 334 4.8.3.- Agrupacin de mensajes..................................................................................... 335 4.8.4.- Medicin de tiempos y profiling ....................................................................... 336 5.- Depuracin paso a paso......................................................................................................... 337

x Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

5.1.- Puntos de interrupcin o breakpoints ................................................................... 344 5.1.1.- Puntos de interrupcin condicionales ............................................................ 345 5.1.2.- Detenerse automticamente en los errores................................................. 346 5.1.3.- Cambiar el flujo de ejecucin ........................................................................... 347 5.1.4.- Otros tipos de puntos de interrupcin.......................................................... 347 APNDICE A: EXPRESIONES REGULARES EN JAVASCRIPT ......................349 1.- Qu son las expresiones regulares ..................................................................................... 351 2.- El lenguaje de las expresiones regulares ............................................................................ 352 2.1.- Elementos de una expresin regular ...................................................................... 353 2.2.- Definicin de expresiones regulares en el cdigo............................................... 358 2.3.- Orden de precedencia ................................................................................................ 358 3.- Construccin y uso de expresiones regulares................................................................. 359 3.1.- Ejemplo 1: validar una direccin de email ............................................................. 359 3.2.- Ejemplo 2: encontrar todas las coincidencias ....................................................... 364 4.- Expresiones regulares y cadenas de texto ........................................................................ 366 4.1.- Sustitucin de cadenas................................................................................................ 367 NDICE ANALTICO ...............................................................................................369

Presentacin

ACERCA DEL LIBRO


JavaScript es el pegamento de Internet. Nacido en 1.995 como un lenguaje casi de juguete para validar formularios web, se ha convertido en indispensable. En la actualidad todos y cada uno de los ordenadores, tablets y mviles del mundo incorporan al menos un intrprete de JavaScript. Adems su influencia se ha incrementado para alcanzar todo tipo de mbitos: Cdigo de servidor: Node.js, RingoJS, Jaxer, EJScript Inteligencia para aplicaciones: PDF, Open Office, Photoshop Diversas plataformas de desarrollo: paquete javax.script en Java, JScript en .NET, QtScript en Qt, ActionScript en Flash Extensiones y plugins para todo tipo de productos: GMail, Google Docs, Chrome, Safari, Gadgets de Windows, Widgets de Mac Aplicaciones estilo Metro para Windows 8 Las API de miles de servicios Web como Twitter, Dropbox Etc

Un programador actual simplemente no puede permitirse el lujo de no conocer JavaScript.

UN LENGUAJE INCOMPRENDIDO
El hecho de ser un lenguaje interpretado y aparentemente sencillo provoca el rechazo inicial de muchos programadores, que lo subestiman. Sin embargo, la mayora de stos, aunque lo hayan denostado, no tiene ms remedio que usarlo dada su penetracin actual. Detrs de su aparente simplicidad se esconde un lenguaje de programacin multiparadigma, ya que es funcional, imperativo, dinmico y orientado a objetos, todo a la vez, lo que lo hace tremendamente verstil.

xii Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

Lo cierto es que se trata en general de un lenguaje muy incomprendido. Mucha gente lo utiliza sin entender bien cmo funciona por debajo, en qu se fundamenta. Esto conduce en ocasiones a resultados poco satisfactorios, bugs, problemas e incluso prdidas econmicas. En los ltimos aos han proliferado multitud de bibliotecas como jQuery o ExtJS que facilitan enormemente el uso de JavaScript en pginas web. Si bien esto es estupendo, ahorra mucho trabajo y es recomendable usarlas, lo cierto es que ha provocado tambin un efecto secundario poco beneficioso: un nuevo tipo de programadores web que no saben JavaScript, slo jQuery. Aplican recetas y plugins sacados de bsquedas de Google sin entender bien lo que estn haciendo ni por qu. Es por ello que, si aparecen errores o bugs, esta falta de conocimiento de los fundamentos se convierte en un problema. Adems, en desarrollo de pginas web, JavaScript es inseparable de los navegadores. Y no todos los navegadores son iguales ni se comportan del mismo modo al programarlos. A un gran porcentaje de los programadores web les resulta difcil discernir qu elementos de los que estn usando para programar forman parte del navegador y cules de JavaScript. Las mencionadas bibliotecas que nos abstraen de esas complejidades no nos ayudan a saberlo. Ms bien todo lo contrario. Es por ello que es ms importante que nunca dominar los fundamentos del lenguaje y conocer las particularidades de los navegadores sobre los que se ejecuta.

QU ESPERAR DE ESTA OBRA?


El libro est dividido en dos partes claramente diferenciadas: 1. Fundamentos del lenguaje: lo que hay que saber sobre la sintaxis de JavaScript, sus tipos de datos, funciones, estructuras de control, manejo de fechas, cadenas y otros tipos de datos, etc Resultar especialmente interesante a los principiantes, aunque incluso algunos programadores experimentados podrn encontrar en esta parte cosas que no saban. Abarca de los captulos 1 al 7, lo que supone alrededor de un tercio de los contenidos del libro. 2. Programacin del navegador: esta es la parte avanzada. Comienza con un repaso a fondo de la programacin orientada a objetos con JavaScript (que s, se puede hacer correctamente!), para analizar las diferentes maneras de interaccionar con el navegador desde el lenguaje, las diferencias existentes entre ellos, la comunicacin asncrona con los servidores con AJAX o la depuracin de aplicaciones entre otras muchas cosas. Encontrars algunas explicaciones que no son fciles de encontrar en otros libros de esta materia y te ayudar comprender los entresijos del lenguaje y los navegadores. Captulos 8 al 13 y apndice A. As que el libro contiene algo para todo el mundo. Los programadores noveles podrn partir prcticamente de cero para conocer lo ms bsico del lenguaje, que tambin les servir en gran medida para otros lenguajes que estudien en el futuro. Los

Presentacin xiii

programadores experimentados encontrarn materias ms avanzadas con explicaciones sobre cmo funcionan los navegadores, las clases, los eventos y dems elementos relacionados. Por ello este libro est orientado a todo tipo de profesionales de Internet: Diseadores web que no conocen JavaScript y desean iniciarse en el lenguaje. Programadores web que utilizan el lenguaje pero necesitan crear cdigo ms eficiente y profesional. Programadores de jQuery y otras bibliotecas similares que desean profundizar en el conocimiento del lenguaje que las sustenta, para entenderlas mejor, saber solucionar los problemas que les surjan y no depender tanto de ellas para cosas sencillas. Cualquier profesional que desee iniciarse en la programacin y hacerlo con el lenguaje ms popular del mundo.

Se espera que el lector sea un usuario habitual de Internet, conozca mnimamente como trabaja la Web, y disponga al menos de unas nociones bsicas de HTML y CSS. Se ha usado un estilo de escritura directo y sencillo, tratando de evitar los tecnicismos, accesible a cualquiera. Puede utilizarse como gua de aprendizaje, leyendo los captulos en orden, o bien como manual de referencia. No se trata este de un libro de recetas (aunque se ofrecen algunas), ni tampoco del tipo Aprende JavaScript por las tardes, sin esfuerzo y mientras ves la tele. El libro ofrece un estudio sistemtico del lenguaje por antonomasia de Internet, con aumento progresivo de dificultad hasta llegar a tener un nivel apreciable de dominio de JavaScript en los navegadores. Pero para ello el lector tendr que poner de su parte tambin. La nica forma de aprender a programar es programando as que debers practicar por tu cuenta todo lo explicado, e inventarte ejemplos propios. Ver el cdigo de las pginas web de otros tambin es muy til: nada ms fcil pues todas lo llevan a la vista, listo para ser analizado por cualquiera. Los ejemplos desarrollados a lo largo de los distintos captulos son intencionadamente simples. En cada parte se construyen ejemplos pequeos orientados a entender el concepto explicado en cada caso. De esta forma no te despistars de lo esencial y podrs asentar mejor los conocimientos. Hay algn cdigo ms elaborado, como por ejemplo el gestor universal de eventos, pero est totalmente explicado en el texto. Todos los ejemplos se pueden descargar desde la web de la editorial: www.krasispress.com. Busca el libro en el catlogo y podrs acceder a las descargas. He salpicado el texto de notas. Algunos captulos la verdad es que tienen muchas :-) Se trata de comentarios adicionales relacionados con lo que se est explicando, que

xiv Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

aportarn informacin extra no esencial, curiosidades, consejos, etc Espero que las encuentres de inters. Ah va la primera:

Nota: En mi blog tcnico, www.jasoft.org, publico con cierta frecuencia posts sobre desarrollo web que pueden resultarte interesantes y que pueden complementar a este libro. Puedes seguir en Twitter a @campusMVP para obtener cada da enlaces a artculos interesantes, noticias y otros recursos para programadores. Tambin en Facebook si lo prefieres: www.facebook.com/campusMVP. En www.campusmvp.com encontrars multitud de cursos on-line tutelados por los mejores profesionales del sector. chale un vistazo y anmate a prepararte con nosotros.

Ponte en contacto con la editorial a travs de su pgina web si quieres transmitirnos cualquier comentario o sugerencia. Ah! Y personalmente te agradecera mucho que, si te gusta el libro y te ha ayudado, nos dejes un comentario en la ficha del mismo en la tienda on-line, para que otros visitantes puedan conocer las opiniones de los lectores. He puesto el mximo empeo en hacer el libro ameno, exhaustivo, fcil de comprender y exento de erratas. Espero haberlo conseguido y que te sirva para aprender y ser mejor en tu trabajo. Comenzamos!

CAPTULO

Fechas, horas y temporizadores

Nada hay ms importante que el tiempo. En el ajetreado y estresante mundo actual vale incluso ms que el dinero para muchas personas. Este captulo se centra en el manejo con JavaScript de este preciado bien inmaterial. Un calendario es un sistema para organizar el tiempo con objetivos sociales, religiosos o administrativos. A cada periodo se le otorga un nombre (da, semana, mes, ao), y el calendario sita el momento actual frente a una referencia pasada elegida arbitrariamente (por ejemplo, en occidente, el momento en el que se considera que naci Jesucristo). La mayora de los calendarios modernos se rigen por el ciclo que sigue la tierra al rodear al sol, por lo que se denominan calendarios solares. En la mayor parte del mundo el calendario que se utiliza es el calendario Gregoriano, solar. ste debe su nombre al Papa Gregorio XIII y sustituy en 1582 al calendario Juliano instaurado por Julio Csar en el ao 46 a.C. En cuanto a la medida ms inmediata del tiempo, la unidad utilizada en el sistema internacional es el segundo, con sus unidades derivadas: el minuto (60 segundos) y la hora (60 minutos o 3.600 segundos). Un da del calendario consta de 24 horas.

Nota: La definicin oficial de 1 segundo es la duracin de 9.192.631.770 oscilaciones de la radiacin emitida en la transicin entre los dos niveles hiperfinos del estado fundamental del istopo 133 del tomo de cesio (133Cs), a una temperatura de 0 K.1

Por supuesto estas unidades de medida del tiempo las tenemos todos muy interiorizadas. Las conocemos y las utilizamos con naturalidad. Sin embargo un ordenador no lo tiene tan fcil. Una computadora no tiene conciencia del exterior y debe regirse por algn sistema interno que le marque el paso del tiempo.
119

120 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

Todos los ordenadores modernos incorporan un hardware especial que acta de reloj interno y que est calibrado para medir la cantidad de tiempo que ha transcurrido desde una determinada fecha arbitraria denominada tcnicamente epoch. Los sistemas operativos que corren por encima del hardware miden el tiempo en ticks que son unidades arbitrarias trasladables a unidades de tiempo real en el sistema internacional. Cada sistema operativo define su propio valor para cada tick. Por ejemplo, en Windows cada milisegundo de tiempo real contiene 10.000 ticks del procesador (http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx) o lo que es lo mismo, cada tick representa un nanosegundo o una diezmillonsima de segundo. La precisin que ofrece, obviamente, es muy elevada. La fecha de referencia del sistema operativo es el 1 de enero del ao 1 a media noche, y el sistema informa permanentemente del nmero de ticks transcurridos desde entonces (sin contar segundos intercalares: http://es.wikipedia.org/wiki/Segundo_intercalar). Otros sistemas operativos usan otras referencias. Por ejemplo Mac OS X usa como epoch el 1 de enero de 1904, el primer ao bisiesto del siglo XX, y Linux utiliza el 1 de Enero de 1970 que es el ao elegido de manera arbitraria por los programadores del primer sistema UNIX. Asimismo, cada lenguaje de programacin ofrece su propia resolucin temporal - la cantidad mnima de tiempo que puede medir- y su propia epoch o fecha de referencia. Por ejemplo la plataforma .NET utiliza el mismo ao que Windows, pero el lenguaje COBOL usa el 1/1/1601, SQL Server el 1/1/1753, y Cocoa (la plataforma de desarrollo de Apple) usa el 1/1/2001. En la variedad est el gusto :-) JavaScript utiliza como referencia temporal el 1 de Enero de 1970, como los sistemas UNIX, y la unidad ms pequea que puede medir es el milisegundo. Por todo lo que acabamos de ver los ordenadores internamente no trabajan con fechas, como nosotros, sino con nmeros muy elevados que se relacionan con determinadas referencias arbitrarias. Y los lenguajes que utilizamos para construir programas usan otras referencias diferentes encima del sistema operativo, pero representan tambin las fechas con nmeros largusimos que carecen de sentido cuando los ve una persona. Como hemos comprobado, la gestin del tiempo en los sistemas digitales dista mucho de ser un problema simple. Por fortuna los sistemas operativos y lenguajes modernos nos abstraen de toda esta complejidad para facilitarnos el uso del tiempo en los programas que construimos. Como veremos enseguida, JavaScript nos ofrece las herramientas que necesitamos para trabajar con el tiempo sin tener que preocuparnos de nada de lo anterior, que sin embargo es interesante conocer y debera formar parte de la cultura general de todo programador.

1.- QU HORA ES?


Esta es la ms simple de las preguntas que nos podemos hacer al empezar a trabajar con el tiempo en un lenguaje de programacin. JavaScript proporciona las funciones necesarias para determinar las caractersticas temporales del sistema desde donde accede cada usuario. Podemos averiguar la fecha

Fechas, horas y temporizadores 121

del ao y felicitarles as la Navidad, la hora del da para poder desearles las buenas noches, la franja horaria en la que se encuentran, etc... Todas las funciones relacionadas con unidades temporales (fecha y hora) se ofrecen como mtodos de la clase JavaScript llamada Date. Como hemos visto en la introduccin, una variable que contenga una fecha (o sea, un objeto de tipo Date) contiene en realidad un valor numrico que expresa el nmero de milisegundos transcurridos desde el 1/1/1970 a las 00:00:00 horas. Las diferencias entre instantes temporales tambin se devuelven en milisegundos, de manera que si dos variables temporales se diferencian en 15.000 implica que estn separadas slo por 15 segundos. Un da tiene 86.400.000 milisegundos. De todos modos generalmente no tendremos que lidiar con estas medidas tan precisas y ser suficiente con utilizar las unidades temporales ms habituales para nosotros: das, meses, horas o minutos. Para obtener la fecha y hora actuales en una variable basta con definir una nueva instancia de Date, as:
var hoy = new Date();

Ahora la variable hoy tendr un valor que representa la fecha y hora en el momento de ser creada. Cuando la intentemos mostrar por pantalla no se ver, sin embargo, el valor numrico del que hemos hablado (el nmero de milisegundos desde 1/1/1970) sino que se mostrar una cadena del estilo:
Fri Aug 3 18:56:28 UTC+0200 2012 //Internet Explorer Fri Aug 03 2012 18:56:28 GMT+0200 (Romance Daylight Time) //Chrome

que como vemos depender del navegador que estemos utilizando. Las fechas se muestran as porque, como vimos en su momento, todos los objetos tienen un mtodo especial llamado toString que es invocado automticamente cuando se quieren representar por pantalla de modo textual. En el caso de los objetos de tipo Date se devuelve en una expresin ms legible para un humano (aunque generalmente en ingls, luego veremos como poner todo en espaol) en lugar del nmero que alberga interiormente.

Nota: La especificacin para el mtodo toString de una fecha en el estndar ECMAScript indica lo siguiente: Este mtodo devolver un valor String. Sus contenidos son dependientes de la implementacin, pero su intencin es que muestre la fecha en la zona horaria actual en una forma apropiada para ser leda por un humano. Sin ms. Por ello difiere lo que se muestra de una implementacin de JavaScript a otra. Se puede leer completo en: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma262.pdf

122 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

Por fortuna JavaScript nos facilita un mtodo alternativo toLocaleString que nos permite mostrar la fecha y hora usando la configuracin del idioma actual del navegador (esto es, la del idioma seleccionado como preferido en el navegador del usuario, no la del sistema operativo, que no tienen porqu coincidir.
var hoy = new Date(); alert(hoy.toLocaleString());

que devolvera en castellano, por ejemplo:


viernes, 03 de agosto de 2012 18:56:28

Existen dos mtodos complementarios al anterior, toLocaleDateString y toLocaleTimeString que devuelven respectivamente las partes correspondientes a la fecha y a la hora. Si en lugar de querer obtener la fecha y hora actuales deseamos guardar en una variable una fecha y hora arbitrarias elegidas por nosotros, deberemos especificarla entre los parntesis al crear un nuevo objeto Date. Existen varios constructores diferentes de este estilo, a saber:
var fecha = new Date("mes da, ao horas:minutos:segundos") var fecha = new Date(ao, mes, da, [horas, [minutos, [segundos, [milisegundos]]]])

as pues para definir una variable que guarde la fecha 23 de Mayo de 1972, a las 21:00 horas escribiremos una de estas dos expresiones equivalentes:
var n = new Date(1972,4,23,21,0); var n = new Date("May 23, 1972 21:00");

Ntese que en el primer caso el mes se especifica como un nmero empezando a contar desde 0, por lo que el mes de Mayo, que es el quinto, se expresa como 4. Mucho cuidado con esto. En el segundo caso el mes se debe expresar por su nombre o abreviatura en ingls, en este caso May. El ao debe expresarse siempre con las cuatro cifras. En caso de facilitarse solamente dos se entender siempre que es un ao del siglo XX, por lo que si escribimos:
var n = new Date(72,4,23);

se entender que se trata del 23 de mayo de 1972. Esto es interesante resaltarlo ya que en otros lenguajes dependiendo del nmero de dos cifras que se pase se considerar que es un ao perteneciente al siglo XX o al XXI. En JavaScript no ocurre esto y siempre se les supondr el 19 delante. Existe una tercera variante del constructor de Date que nos permite pasarle como argumento un valor que representar el nmero de milisegundos desde el 1/1/1971. Raramente se utiliza.

Fechas, horas y temporizadores 123

El constructor de las fechas se adapta a las incongruencias que le facilitemos en el constructor, de modo que adapta a la posibilidad ms apropiada en cada caso aquellas fechas incorrectas que le pasemos. Por ejemplo:
var fecha = new Date(2012, 3, 31);

Intenta asignar el da 31 de abril de 2012. Pero abril slo tiene 30 das, as que la fecha no es correcta. Sin embargo en lugar de obtener un error JavaScript coger la fecha ms congruente con lo que le pasamos, que es el 1 de mayo (el da que sobra se lo suma a la fecha).

Nota: As que en realidad en JavaScript s que podramos aplicar sin problema lo del dicho: Hasta el cuarenta de mayo no te quites el sayo, ya que el 40 de mayo existe y se transforma en el 9 de Junio ;-)

Por ejemplo, especifiquemos una fecha como esta:


var fecha = new Date(2012, 20, 10);

que literalmente sera el 10 del mes 21 de 2012 (recuerda que los meses cuentan desde el 0 as que el 20 es en realidad el 21). Como esto no tiene sentido, JavaScript se suma los meses sobrantes de modo similar a lo que acabamos de ver con los das,, con lo que realmente la fecha que hemos definido es el 10 de septiembre de 2013!. Qu fecha sera esta entonces?:
var fecha = new Date(2012, 20, 40);

Pues el 10 de octubre de 2013, ya que el 20 se refiere al mes 21 contando desde enero del ao indicado (2012), o sea que es septiembre de 2013, y el 40 sube 10 das ms ese da de septiembre (que tiene 30 das), hasta el 10 de octubre. Lo mismo pasa con los nmeros negativos:
var fecha = new Date(2012, 4, -10);

Esta fecha sera el 20 de abril de 2012.

2.- LAS PARTES DEL TIEMPO: FORMATOS PROPIOS


Una vez que tenemos definida una variable que contiene un objeto Date sera interesante poder acceder a sus diversas partes de manera directa, es decir, saber directamente el da de la semana en el que estamos, o slo la hora, etc. Para ello la clase Date cuenta con una serie de mtodos que pasamos a enumerar a continuacin:

124 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

getTime: obtiene solamente la parte correspondiente a la hora, rechazando la fecha. Devuelve el nmero de segundos transcurridos desde el 1/1/ 1970. Es til para crear marcas de tiempo para ciertas aplicaciones especiales de comunicacin con el servidor. getDay: nos dice el da de la semana en el que nos encontramos, empezando a contar en domingo, que sera un 0. De este modo el lunes sera el 1, el martes el 2 y as sucesivamente. getDate: obtiene el da del mes dentro de la fecha dada. getMonth: devuelve el nmero correspondiente al mes contenido en el objeto Date. Se comienza a contar en 0 que correspondera al mes de Enero. getYear: devuelve el ao contenido en la variable de tipo fecha. Esta funcin tiene un comportamiento algo extrao puesto que para las fechas comprendidas entre 1900 y 2000 (ambos inclusive) devuelve slo las dos ltimas cifras del ao (1985 sera 85) mientras que para el resto de las fechas devuelve el nmero completo. Hay que tenerlo en cuenta porque para cualquier fecha actual devolver cuatro cifras, pero para una fecha del siglo pasado sern solamente dos. getFullYear: funciona igual que el anterior, pero en este caso el ao se devuelve siempre con las cuatro cifras correspondientes. Debemos usarlo generalmente en sustitucin de getYear. getHours: permite obtener el valor de la hora en una variable Date, sin incluir la fecha actual, ni los minutos ni los segundos. getMinutes: con este mtodo conseguimos averiguar los minutos de la hora indicada. getSeconds: permite obtener la parte correspondiente a los segundos en una variable de hora. getMilliseconds: facilita el nmero de milisegundos despus del segundo actual que est especificado dentro de una variable de tipo Date. Es decir, aunque la hora actual se muestre redondeada a 19:22:37, internamente hay unos cuantos milisegundos de precisin ms que podemos obtener, por lo que sera 19:22:37:849 (siendo 849 los milisegundos a mayores que devolver esta funcin).

Dado que JavaScript no nos proporciona mtodo alguno para poder devolver formatos personalizados, y lo mximo que facilita de manera directa es que devolvamos fechas largas en la lengua local, usaremos las funciones anteriores para devolver el formato que deseemos.

Fechas, horas y temporizadores 125

Por ejemplo, vamos a crear un formato especial que devuelve una fecha en un formato especial. En nuestro caso usaremos el ejemplo planteado al final del captulo anterior (convertir un nmero en su expresin textual) para conseguir fechas de este tipo:
Viernes, tres de Agosto de dos mil doce

con todas sus letras. El ejemplo lo tienes en el archivo Cod07_01.htm de las descargas del libro. Para conseguirlo, antes de nada, vamos a introducir una referencia a un archivo JavaScript con la funcin de conversin de nmero a texto vista en el captulo anterior, as como sus constantes y mtodos asociados:
<script type="text/javascript" src="numeroATexto.js"></script>

Esto har que est disponible en nuestra pgina (lo habitual es reunir en archivos .js las funciones reutilizables que tengamos para nuestras aplicaciones, agrupndolas por funcionalidad). Ahora vamos a definir un par de funciones auxiliares que nos resultarn de utilidad y que devolvern respectivamente el nombre del da de la semana y del da del mes utilizando los mtodos que acabamos de estudiar:
function getNombreDiaSemana(fecha) { var dias = ["domingo", "lunes", "martes", "mircoles", "jueves", "viernes", "sbado"]; return dias[fecha.getDay()]; } function getNombreMes(fecha) { var meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Noviembre", "Diciembre"]; return meses[fecha.getMonth()]; }

Como vemos simplemente devuelven el nombre apropiado desde una lista (contenida en un array) a partir de las funciones getDay y getMonth. Ahora, el resto del cdigo es trivial:
function formatoTextual(fecha) { return getNombreDiaSemana(fecha) + ", " + numeroATexto(fecha.getDate()) + " de " + getNombreMes(fecha) + " de " + numeroATexto(fecha.getFullYear()); } var hoy = new Date(); alert(formatoTextual(hoy)); //viernes, tres de Agosto de dos mil doce

En el archivo Cod07_02.htm se ofrece una versin alternativa y orientada a objetos de este cdigo, que de hecho extiendo la clase Date para que disponga directamente de un mtodo formatoTextual que nos permita simplemente escribir esto:

126 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

var fechaTexto = hoy.formatoTextual(); alert(fechatexto);

Nota: Todava no hemos llegado a la parte de programacin orientada a objetos por lo que el cdigo para lograrlo te ser ms difcil de entender, pero lo dejo para mostrar la forma ms correcta de hacer este tipo de cosas. En un prximo captulo quedar claro cmo funciona.

Para terminar este apartado veamos un truco poco conocido de las fechas JavaScript. Si en el constructor de una fecha especificamos como da del mes un 0 (obviamente un valor no vlido), JavaScript asigna a la fecha el ltimo da de ese mismo mes. Es un comportamiento extrao pero muy til ya que podemos aprovecharlo para averiguar el nmero de das que tiene un mes cualquiera de un ao dado:
function numDiasEnMes(mes, anio) { var comodin = new Date(anio, mes, 0); return comodin.getDate(); } alert( numDiasEnMes(2, 2012) );

que en este caso devuelve 29 ya que el ao 2012 fue bisiesto y por lo tanto el mes de febrero tuvo 29 das.

3.- HORA UNIVERSAL COORDINADA


De acuerdo con las especificaciones ECMA-Script que normalizan el lenguaje, JavaScript dispone de funciones para el manejo de unidades temporales estndar, lo que se conoce como Universal Coordinated Time, UTC u Hora Universal Coordinada. Este baremo para medir la hora es ms conocido por todo el mundo como GMT (o Greenwich Meridian Time, hora en el meridiano de Greenwich) y todos estamos acostumbrados a utilizarlo. Prcticamente todas las funciones vistas en el apartado anterior para obtener las partes de un objeto Date se han implementado tambin para horas universales. Slo hay que aadir la palabra UTC despus de get en sus nombres. As tenemos: getUTCDay getUTCDate

Fechas, horas y temporizadores 127

getUTCMonth getUTCFullYear getUTCHours getUTCMinutes getUTCSeconds getUTCMilliseconds

Todos estos mtodos tienen en cuenta la diferencia horaria del sistema en el que nos encontramos respecto al meridiano de Greenwich, de forma que es posible que un mtodo get de hora local visto en el apartado anterior, y un mtodo get de hora UTC ofrezcan resultados completamente diferentes. Por ejemplo, la fecha:
n = new Date(2013,0,1,0,15);

Correspondiente a los 15 primeros minutos del da de Ao Nuevo del ao 2013 en Espaa (GMT+1), es realmente una hora menos en Greewich, por lo que esa fecha en hora local sera ya el 2013, pero en hora UTC sera todava 2012. Las funciones toUTCString y toGMTString son equivalentes y devuelven las fechas expresadas en el meridiano de Greenwich. As, el siguiente cdigo:
var fecha = new Date(2013,0,1,0,15); alert(fecha + "\n" + fecha.toUTCString());

Mostrar el resultado de la figura 1.

Figura 1.- Diferencia entre la hora local y la de Greenwich

La getTimezoneOffset se ocupa de decirnos los minutos de diferencia existentes entre la hora local y la GMT, y puede resultar muy til cuando la diferencia horaria entre donde est el servidor y los usuarios es importante. Usando esta funcin podramos escribir nosotros mismos todas las funciones UTC que acabamos de ver con suma facilidad. Para el caso de Espaa esta funcin devuelve el nmero -60 o -120, ya que hay una hora de diferencia en invierno pero dos en verano

128 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

con el horario de ahorro energtico. En realidad puede devolver casi cualquier valor pues existen pases con diferencias horarias con GMT que no son horas completas. Por ejemplo Venezuela est en GMT-04:30 (o sea, cuatro horas y media por detrs), y Nepal est en GTM+05:45 (5 horas y tres cuartos por delante). JavaScript nos abstrae de todas estas dificultades y siempre devuelve la diferencia horaria correcta con cdigo similar a este:
Var fecha = Date(); alert(fecha.getTimezoneOffset());

4.- MTODOS DE CAMBIO DE HORA


Al igual que podemos guardar en una variable fechas y sus partes a travs de los mtodos get... y getUTC.., es posible igualmente fijar a posteriori estos valores. La clase Date posee unos mtodos set... que estn pensados para modificar el contenido de las variables de este tipo para reflejar fechas y horas diferentes. Ninguno de estos mtodos afecta a la hora o fecha reales del sistema, slo a los valores almacenados en las variables que tratemos con ellos. As podemos almacenar fechas arbitrarias en una variable de tipo temporal previamente definida. A continuacin se detallan los mismos: setDate: Permite asignar un nuevo da del mes a la fecha contenida en una variable. setMonth: Asigna un nuevo valor para el mes en la fecha contenida en la variable. Recuerda que los meses empiezan a contar desde 0 para enero. setYear: Permite cambiar el valor del ao en una fecha.- Si se usan slo dos dgitos como argumento se considerar un ao dentro del rango 1900-2000. setFullYear: idntico al mtodo anterior pero se deben especificar siempre los cuatro dgitos del ao. Este mtodo permite especificar opcionalmente el mes y el da del mes como segundo y tercer parmetro respectivamente. setTime: permite asignar una nueva hora pasando como argumento el nmero de milisegundos transcurridos desde la medianoche del 1/1/1970. No se utiliza demasiado por razones obvias. setMilliSeconds: fija el nmero de milisegundos que pasan del segundo en la hora actual de una variable. setSeconds: permite fijar el nmero de segundos actuales en la variable. Opcionalmente se pueden especificar tambin los milisegundos como segundo parmetro.

Fechas, horas y temporizadores 129

setMinutes: fija los minutos actuales en la hora contenida en una variable. Tiene como parmetros opcionales el nmero de segundos y el de milisegundos transcurridos. setHours: nos permite fijar la hora actual para una variable tipo Date. Tiene como tres parmetros opcionales los minutos, segundos y milisegundos.

Del mismo modo que antes haba funciones get... para horas locales y getUTC... para horas GMT, en el caso de los mtodos set.. ocurre igual y existen: setUTCDate setUTCMonth setUTCFullYear setUTCMilliSeconds setUTCSeconds setUTCMinutes setUTCHours

que funcionan de la misma manera pero refirindose sus parmetros a hora universal UTC y no a la hora local del sistema donde se ejecuten.

5.- TEMPORIZADORES Y CRONMETROS


Adems de medir el tiempo, algo verdaderamente til en cualquier plataforma de desarrollo es tener la capacidad de ejecutar cdigo a intervalos regulares de tiempo. Un programa en JavaScript, segn todo lo que hemos visto hasta el momento, es una sucesin continua de lneas de cdigo que se ejecutan una tras otra por orden para obtener un resultado. Sin embargo en la realidad no solo llega con ejecutar el cdigo en el momento de cargar una pgina, sino que es necesario que ste se ejecute en el momento apropiado: ante algo concreto que ocurra en una pgina o al cabo de determinado tiempo. El primer caso se soluciona gracias a los eventos de HTML, que estudiaremos en un captulo posterior y nos permitirn reaccionar ante diferentes situaciones que se den en una pgina (como pulsar un botn o pasar el cursor sobre un texto). La segunda situacin se resuelve con el uso de temporizadores. Los temporizadores son objetos sin representacin fsica que se encargan de ejecutar una determinada tarea al cabo de un cierto tiempo. La orden para poner en marcha un temporizador es:

130 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

tempID = setTimeout(Rutina, Tiempo);

donde Rutina es el nombre (debe ir entre comillas) de un procedimiento o funcin que el temporizador se encargar de ejecutar; y Tiempo es un valor expresado en milsimas de segundo que indica cunto tiempo tardar ste en ejecutar la rutina especificada. Al fijar un temporizador con setTimeout se puede anotar el valor devuelto en una variable. Este valor es un nmero que identifica de manera nica al temporizador recin definido. El inters de este identificador reside nicamente en usarlo con el mtodo complementario clearTimeout que lo toma como argumento para anular el temporizador relacionado. Segn esto, si por ejemplo se dispone en el Script de una funcin llamada miFuncin y se quiere activar sta al cabo de dos segundos habra que escribir:
var miId = setTimeout(miFuncin(), 2000);

En caso de que, por cualquier motivo, sea necesario detener este temporizador antes de que llegue a actuar y ejecute la funcin, haremos:
clearTimeout(miId);

En lugar del nombre de una funcin podramos pasarle tambin una cadena de texto con el cdigo a ejecutar:
setTimeout(alert(Hola), 2000);

Sin embargo esto es considerado una mala prctica y solamente se soporta por compatibilidad con versiones antiguas del lenguaje. En la actualidad raramente lo vers en ningn sitio ya que, entre otras cosas, puede interferir con los procesos de minimizacin de cdigo que se llevan a cabo para mejorar el rendimiento de descarga de las pginas.

Nota: El proceso de minimizacin de cdigo JavaScript consiste en retirar de un archivo de cdigo todo lo superfluo para que ocupe el menor espacio posible. Se retiran comentarios, retornos de carro, tabulaciones, espacios pero tambin se puede refactorizar e incluso reducir el nombre de las variables para que ocupen menos. Se pueden conseguir reducciones de tamao espectaculares, haciendo que el cdigo se descargue antes, y ahorrando ancho de banda. En ocasiones el proceso va unido a otro denominado Ofuscacin, que bsicamente trata de hacer el cdigo menos legible y difcil de seguir para un humano, dificultando que se copie o se cacharree con l. Muchas veces el proceso de minimizado se acompaa de otro denominado bundling, que consiste en combinar varios archivos de cdigo .js en uno solo para reducir tambin el nmero de peticiones que una pgina debe realizar al servidor, lo que tambin ahorra tiempo y ancho de banda. Estos procesos los llevan a cabo ciertos programas especializados de manera

Fechas, horas y temporizadores 131

automtica. Los ms conocidos son JSCompress (http://jscompress.com), JSMin de Douglas Crockford (http://www.crockford.com/javascript/jsmin.html), YUI Compressor de Yahoo (http://refresh-sf.com/yui/) o el AJAX MInifier de Microsoft (http://ajaxmin.codeplex.com/). Todos son gratuitos.

Tambin es posible pasarle directamente una funcin annima definida como primer parmetro, as:
setTimeout( function(){alert(Hola);}, 2000);

Pero tampoco se utiliza a menudo, prefirindose por claridad la primera de las variedades de uso. Si necesitamos ejecutar la funcin repetidamente, a intervalos regulares de tiempo, es posible llamar repetidas veces al temporizador de nuevo con el mtodo que acabamos de estudiar o, mucho mejor, se puede usar el mtodo setInterval. ste es exactamente igual al anterior en cuanto a parmetros y forma de uso, pero la llamada se repite continuamente cada intervalo de tiempo especificado, hasta que lo detengamos con una llamada a su funcin complementaria clearInterval. Por ejemplo:
id = setInterval(Mifuncion(), 2000);

O bien:
id = setInterval(Mifuncion, 2000);

llamar continuamente a la funcin indicada cada dos segundos. Slo dejar de invocarla cuando llamemos a clearInterval pasndole como parmetro el identificador devuelto al crear el temporizador (guardado en la variable id en la lnea anterior).

Nota: Tanto a setTimeout como a SetInterval se les pueden pasar como parmetros opcionales los argumentos que necesite la funcin que vamos a ejecutar. Tantos como sea necesario:
setTimeout(Mifuncion, 2000, parametro1, parametro2);

Esto funciona en todos los navegadores del mercado a excepcin de en Internet Explorer, por lo que no es muy recomendable. Si necesitas pasar parmetros a la llamada a la funcin es mejor que la envuelvas en otra funcin auxiliar sin parmetros y que llames a sta.

132 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

Nota: Hay que tener en cuenta que estos cuatro mtodos de temporizadores no forman parte en realidad del lenguaje JavaScript sino que son mtodos proporcionados por los navegadores web (a travs de su objeto intrnseco window, que ya estudiaremos) y que pueden ser utilizados desde nuestro cdigo JavaScript embebido en una pgina web. Si queremos usar el cdigo descrito fuera de un navegador no funcionar. Sin embargo otros lenguajes basados en JavaScript suelen incluir su propia implementacin nativa para facilitar la compatibilidad. Por ejemplo Node.js ofrece las cuatro funciones, que funcionan del modo descrito en este captulo.

5.1.- La precisin de los intervalos de tiempo


El tiempo del intervalo para un temporizador puede ser cualquier valor. Sin embargo, si nos pasamos ponindolo demasiado pequeo, veremos que pueden ocurrir cosas malas. Aparte de poder llegar a bloquear la ejecucin del navegador, a partir de determinado valor que vara de un navegador a otro (entre los 15 y los 25 milisegundos), el temporizador no tiene resolucin suficiente y entonces da igual lo que bajemos el tiempo puesto que no habr diferencia. En cualquier caso debemos evitar los procesos peridicos lanzados con intervalos muy pequeos. Todo lo que sea inferior a 100 milisegundos no parece muy recomendable salvo en casos muy puntuales, as que deberamos mantenernos por encima de esa zona de confort. En el epgrafe anterior afirm que setInterval llamaba a una funcin cada x milisegundos, especificados como segundo parmetro. Sin embargo esto no es exactamente as, y en ocasiones puede tener importancia esta distincin. JavaScript solamente posee un hilo de ejecucin, por lo que todas las funciones se ejecutan dentro de ste (dejando de lado la salvedad de la API de Web Workers de HTML, un tema avanzado). Esto significa no se pueden ejecutar dos scripts al mismo tiempo en una pgina. El mtodo setTimeOut y setInterval ayudan a emular la ejecucin en paralelo de cdigo, ya que podemos lanzar procesos al cabo de cierto tiempo o peridicamente, que parecen ejecutarse en otro hilo. Pero es solo una ilusin. En realidad, tanto los intervalos de estos temporizadores como cualquier otro evento asncrono que se provoque (a travs de la interfaz, por ejemplo), se encolan para su ejecucin para cuando el motor de JavaScript (mono-hilo, recordmoslo) est disponible. Veamos que pasa cuando ejecutamos una funcin cada cierto tiempo corto. Imaginemos una funcin relativamente larga de ejecutar (que tarde sobre 70 ms) ejecutada cada 100 ms:

Fechas, horas y temporizadores 133

Figura 2.- Ejecucin de una funcin larga a intervalos cortos

Esto no deja de ser una simplificacin ya que hay otros posibles eventos ejecutndose en el tiempo del proceso de JavaScript (eventos de la interfaz de usuario u otros temporizadores), pero no sirve para explicar el fenmeno. En este caso como la funcin tarda menos tiempo que el intervalo en ejecutarse dar tiempo a lanzarla con el periodo que hemos indicado en setInterval. Lo que JavaScript hace es introducir en una cola de ejecucin los eventos asncronos que debe ejecutar, y los ejecuta en el momento en el que puede hacerlo. En el ejemplo de la figura la funcin se encola cada 100 ms y como tras cada ejecucin an sobra tiempo, al ir a ejecutarla nuevamente no hay nada pendiente en la cola y la ejecuta inmediatamente. Este sera el comportamiento normal deseable. Imaginemos ahora un proceso que tarda ms en ejecutarse que el intervalo de repeticin que hemos especificado (se puede simular mostrando desde el evento peridico un dilogo bloqueante mediante alert que bloquea la ejecucin hasta que lo aceptamos- y tardando ms tiempo del indicado en aceptarlo). Lo que ocurre lo vemos reflejado en la siguiente figura:

Figura 3.- Tareas repetitivas muy largas

En este caso la primera vez que se ejecuta funcin se tarda ms tiempo del especificado en el intervalo en terminarla. Mientras tanto el cdigo JavaScript est detenido. Al pasar los siguientes 100 ms (el intervalo de repeticin) JavaScript no puede ejecutar la funcin puesto que est en un bloqueo as que lo que hace es introducirla en la cola de ejecucin de eventos asncronos, a la espera de un momento libre para ejecutarla. Al acabo de otros 100 ms se debera introducir en la cola otra

134 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

repeticin de la tarea, pero en realidad se descarta pues slo puede haber una de cada tipo. Finalmente al cabo de 335 milisegundos, se termina la primera ejecucin y se lanza inmediatamente la que est en la cola (que es la segunda todava). Con lo cual el intervalo, que era de 100 ms, se ha convertido en este caso en un intervalo mucho ms largo. Conclusin: en condiciones extremas los intervalos no son fiables, con posibles grandes variaciones, por lo que no podemos contar siempre con que nuestra funcin se ejecutar todas las veces que pensbamos. Esto puede tener importancia en ciertos tipos de aplicaciones y debemos tenerlo en cuenta. Si realmente es importante para nosotros que una tarea se repita en un intervalo de tiempo preciso tras cada ejecucin (es decir, que se ejecute x milisegundos despus de haber terminado la primera ejecucin, ojo) lo que tenemos que hacer es emplear un temporizador simple con setTimeOut y relanzarlo desde la propia funcin al final de su ejecucin:
function periodica() { //Hacemos lo que sea que puede tardar setTimeOut(periodica, 100); }

Es decir, iniciamos otro nuevo intervalo al terminar la ejecucin del anterior. OJO: con esto no conseguimos repeticiones cada cierto tiempo, sino que la funcin se repita con un periodo de tiempo predecible entre cada ejecucin, que no es lo mismo como ilustra la siguiente figura.

Figura 4.- Ejecucin constante al terminar la funcin

6.- EJEMPLO: UN RELOJ DENTRO DE UNA PGINA WEB


Con ayuda de los temporizadores y nuestros conocimientos del lenguaje y del manejo de fechas y cadenas de texto vamos a construir un pequeo reloj digital como el que se ve en la figura. ste marcar dentro de una pgina web la hora con todos los dgitos. Esto quiere decir que rellenaremos con ceros si es necesario cada parte de la hora para que aparezca 05 en lugar de slo 5.

Fechas, horas y temporizadores 135

Figura 5.- Un reloj digital en una pgina Web

El cdigo necesario (Cod07_04.htm) es el siguiente:


<!DOCTYPE html> <html> <head> <title>Reloj Digital</title> <script type="text/javascript"> function mostrarHora() { //Asigno la fecha y hora actual var h = new Date(); //Muestro la fecha actual en su zona document.getElementById("fecha").textContent = h.toLocaleDateString(); //Descompongo el tiempo en sus partes var horas = h.getHours().toString(); if (horas.length == 1) horas = "0" + horas; var mins = h.getMinutes().toString(); if (mins.length == 1) mins = "0" + mins; var segs = h.getSeconds().toString(); if (segs.length == 1) segs = "0" + segs; document.getElementById("reloj").textContent = horas + ":" + mins + ":" + segs; setTimeout("mostrarHora()", 1000); } </script> </head> <body onload="mostrarHora()"> <div id="fecha" style="text-align:center;font-size:30pt;"> </div> <div id="reloj" style="text-align:center;font-size:80pt; fontweight:bold; font-family:Courier New;"> </div> </body> </html>

136 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

En este cdigo hay un par de cosas que necesitamos y que todava no hemos estudiado, pero son sencillas: el evento onload de una pgina, que ejecuta un cdigo cuando sta ha terminado de cargar, y el mtodo getElementbyId, que permite localizar elementos dentro de la pgina. Obviemos por el momento esto (lo vamos a ver en un prximo captulo con detalle). El cdigo que queda para crear el reloj es realmente sencillo y fcil de seguir con lo que sabemos hasta ahora.

7.- EJEMPLO: DIFERENCIAS DE TIEMPOS. CUENTA ATRS.


Para terminar este captulo vamos a hacer un ejemplo un poco ms complicado, pero sencillo de todos modos. Nos servir para ver algunos detalles ms sobre cmo trabajar con el tiempo y los temporizadores. Se trata de crear un cronmetro de cuenta regresiva, que mostrar en pantalla el tiempo que queda para que pase un determinado periodo de tiempo. Puede ser til, por ejemplo, para informar en pantalla a los alumnos de una prueba de evaluacin sobre cunto tiempo les queda para terminar (ver figura 6).

Figura 6.- Nuestro cronmetro de cuenta regresiva

Para programar algo as, lo primero es colocar la interfaz de usuario en la pgina:

Fechas, horas y temporizadores 137

<!DOCTYPE html> <html> <head> <title>Cuenta regresiva</title> <link type="text/css" href="crono.css" rel="stylesheet" /> </head> <body> <div class="marco"> <div id="reloj">00:00</div> <select id="tiempo"> <option value="5">5 min</option> <option value="10">10 min</option> <option value="15">15 min</option> <option value="20">20 min</option> <option value="25">25 min</option> <option value="30">30 min</option> </select> <input type="button" id="botonCrono" value="Iniciar" onclick="comenzarParar();" /> </div> </body> </html>

Hemos definido un <div> que contiene a los dems elementos. Dentro de ste hay otro <div> que servir para mostrar la cuenta atrs y debajo de ste un control de seleccin con unos determinados rangos de tiempo que podemos seleccionar, seguido de un botn que servir para iniciar y detener el contador. En la cabecera se ha referenciado una hoja de estilos que le dar un aspecto agradable a todo el conjunto. En el evento onclick del botn se llama a la funcin comenzarParar que ser la encargada de poner en marcha el cronmetro o detenerlo si ya estaba funcionando. Veamos el aspecto que tiene:
var dObjetivo = null; var divreloj = null; var idTimer = 0; function comenzarParar() { if (idTimer != 0) { //parar clearInterval(idTimer); idTimer = 0; document.getElementById("botonCrono").value = "Iniciar"; pintarTiempo(0, 0); } else { //arrancar var tDescuento = parseInt(document.getElementById("tiempo").value, 10); dObjetivo = new Date(); //hora actual como referencia dObjetivo.setMinutes(dObjetivo.getMinutes() + tDescuento); document.getElementById("botonCrono").value = "Parar"; pintarTiempo(tDescuento, 0); idTimer = setInterval(tick, 900); } }

138 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

Primero se definen tres variables globales que es necesario compartir entre varias funciones que vamos a crear. Acto seguido se define la funcin comezarParar. Dado que sta va a tener un doble propsito se hace divide su lgica entre dos ramas de un condicional. Vamos a fijarnos antes de nada en la rama de arrancar que es la del else. Lo que se hace es guardar en una variable local auxiliar (tDescuento) el tiempo seleccionado por el usuario en la lista desplegable, convirtindolo en un nmero entero antes, con parseInt. Este es un tiempo en minutos. A continuacin se averigua la fecha y hora actuales, guardndolas de momento en la variable global dObjetivo que contendr la fecha y hora destino en la que la cuenta regresiva deber detenerse. Como debemos contar (ms bien descontar) el nmero de minutos elegido por el usuario, la fecha objetivo ser igual a la actual ms esos minutos elegidos por el usuario. Para poder sumar esos minutos a la hora actual hacemos uso del mtodo setMinutes, para lo cual le sumamos a los minutos actuales (getMinutes) el tiempo que queremos descontar. Por ejemplo, si ahora son las 20:00:00 y queremos contar 5 minutos, le sumamos esos 5 minutos a la parte de minutos de la hora actual. As, para saber el tiempo que ha transcurrido slo debemos restar de esa hora objetivo la hora actual. A las 20:05:00 sabremos que el contador ha terminado y debemos detenerlo.

Nota: No debemos preocuparnos de si lo que sumamos con setMinutes sobrepasa los 60 minutos, ya que como hemos visto la clase Date es suficientemente inteligente para adaptarse. As que si son las 20:55 y le sumamos 10 minutos a los minutos (es decir, le diramos que queremos las 20:65) la hora resultante son las 21:05 ya que se recalcula todo automticamente. Es importante hacer estas sumas y restas con la fecha completa (como de hecho lo estamos haciendo) porque podemos comenzar la cuenta cerca de las 00:00 de la noche y si slo considerramos la hora nos conducira a errores.

Ahora que ya sabemos la hora objetivo lo nico que hacemos es cambiar el texto del botn para que ponga Parar, pintamos el tiempo inicial (con una funcin pintarTiempo que no es interesante para el propsito de este ejemplo) y lanzamos un temporizador que llamar cada 900 ms a una funcin llamada tick. Fjate en que se almacena el identificador del temporizador en la variable global idTimer. Con este identificador global conseguimos dos cosas: poder parar el temporizador cuando queramos, y averiguar si est actualmente en marcha o no (es la condicin del if con el que comienza la funcin). Si est parado se hace lo que acabamos de ver, y si est en marcha se detiene con una llamada a clearTimer, dejando el resto de elementos comoestaban. La funcin tick tiene el siguiente aspecto:

Fechas, horas y temporizadores 139

function tick() { var dif = (dObjetivo - new Date()) / 1000; if (dif > 0) { var minutos = Math.floor(dif / 60); var segundos = Math.floor(dif % 60); pintarTiempo(minutos, segundos); } else { comenzarParar(); } }

Esta funcin lo que hace es averiguar la diferencia que existe entre la hora objetivo calculada en la funcin anterior y la hora actual. En JavaScript cuando se restan dos fechas se obtiene la diferencia entre stas en milisegundos. As que si la dividimos entre 1000 tenemos la diferencia entre ambas en segundos, que es lo que nos interesa para pintar el contador regresivo.

Nota: Hay que tener mucho cuidado con las operaciones que se realizan con fechas. Si restamos dos fechas obtenemos su diferencia como era de esperar. Sin embargo si se suman dos fechas (fecha1 + fecha2) lo que conseguimos es transformarlas a cada una de ellas en cadenas de texto y que stas se concatenen, que no es generalmente lo que querremos. Sumar dos fechas no tiene sentido matemticamente, mientras que restarlas s. Si lo que queremos es sumar un determinado intervalo a una fecha (por ejemplo 5 minutos, 9 horas o 3 meses) debemos proceder como se ha visto hace un momento, es decir, utilizar la funcin setXXXX correspondiente sumndole ah la cantidad que necesitemos. Es un muy importante tener en cuenta esto.

Bien, una vez que ya sabemos la diferencia en segundos que existe entre la fecha y hora actual y la objetivo, si sta es menor que cero es que ya la hemos sobrepasado y por lo tanto debemos parar el contador, para lo cual llamamos a comenzarParar (raa else del condicional). Si todava estamos en el intervalo lo nico que tenemos que hacer es ver cuntos minutos y segundos faltan: Minutos: dividimos la diferencia en segundos entre 60 (hay 60 segundos en un minuto) y nos quedamos con la parte entera. Segundos: nos quedaremos con el resto de la divisin anterior (operador %), que son los segundos que sobran del ltimo minuto.

Una vez hechas estas divisiones, pintamos esos minutos y segundos. Listo! El ejemplo es sencillo pero nos ha ayudado a ver cmo se trabaja con diferencias entre fechas, que no es tan obvio como podra parecer a priori. En el correspondiente archivo descargable (Cod07_05.htm) est el cdigo completo con comentarios para su estudio. Tiene algunas otras cosas interesantes, como por ejemplo el uso de media

140 Fundamentos de JavaScript y AJAX para desarrolladores y diseadores web

queries de CSS3 para adaptar automticamente y en tiempo real el tamao del contador al tamao de la pantalla que lo muestra.