100% encontró este documento útil (1 voto)
836 vistas

Aprende A Desarrollar Con JavaScript

Cargado por

Alberto Briceño
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
100% encontró este documento útil (1 voto)
836 vistas

Aprende A Desarrollar Con JavaScript

Cargado por

Alberto Briceño
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 337

Aprender 

a desarrollar con JavaScript
Este libro, que trata sobre el aprendizaje en el desarrollo con JavaScript, se dirige a los lectores que deseen adquirir 
las  habilidades  necesarias  para  dominar  esta  área,  fundamental  en  los  desarrollos  Web.  Es  completamente  esencial 
dominar  el  software  existente  que  permite  adquirir  el  conocimiento  del  lenguaje  JavaScript,  si  desea  conseguir  el 
conocimiento suficiente dentro del sector específico relacionado con las tecnologías de la Web 2.0. 
 
Partiendo de la base de que el lector solo tiene conocimientos básicos de programación, el autor comenzia recordando 
y aportando conocimiento sobre algoritmia. A continuación, explica los conceptos principales del lenguaje JavaScript. 
Los  diferentes  conceptos,  principios  o  funcionalidades,  se  descubren  a  través  de  ejemplos  concretos,  fácilmente 
reutilizables en otros desarrollos. 
 
En  la  medida  en  que  el  lenguaje  JavaScript  se  integra  con  otras  tecnologías  Web  (o  lenguajes),  como  el  inevitable 
HTML,  las  hojas  de  estilo  CSS,  los  lenguajes  orientados  a  la  programación  del  lado  servidor  como  PHP  u  otras 
herramientas  como  Ajax,  este  libro  también  le  permitirá  dar  sus  primeros  pasos,  adentrándose  en  estas  diferentes 
tecnologías. 
 
El autor se apoya en ejemplos que siguen una progresión lógica a lo largo de los capítulos. 
 
Tiene a su disposición elementos adicionales que se pueden descargar desde esta página. 
 
Los capítulos del libro: 
Presentación del lenguaje JavaScript – Desarrollo a partir de algoritmos – Conceptos principales del lenguaje JavaScript 
–  Procesamiento  condicionado  –  Procesamiento  iterativo  bucles  –  Tablas  –  Procedimientos  y  funciones  –  Enfoque 
orientado  a  objetos  en  JavaScript  –  Principales  objetos  en  JavaScript  –  Utilizar  formularios  para  introducir  datos  – 
Modelo DOM – Exploración del flujo XML via DOM – Gestión de las cookies en JavaScript – Almacenamiento local de datos 
– Almacenamiento remoto: formato XML   – Almacenamiento remoto: formato JSON –  Geolocalización – Diseño HTML 5 
CANVAS – Gráficos de gestión – Creación de documentos PDF – Creación de códigos QR 

Christian VIGOUROUX 
Christian VIGOUROUX es Doctor en la universidad de Rennes 1, en el área de componentes de gestión (IAE­ Instituto 
de Gestión de Rennes). Ahí enseña desde hace casi de 30 años informática de gestión, encargado principalmente de la 
enseñanza en Técnicas de Internet, Ingeniería de software e Informática decisional en el  máster de Sistemas de 
información y control de gestión, que él dirige. Adicionalmente, desarrolla actividades de consultoría en grandes 
empresas, para la implantación de soluciones decisionales y la implantación de arquitecturas de software. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Definición e histórico rápido

JavaScript, término que nos encontraremos muy a menudo en este libro con las siglas JS, es un lenguaje inventado 
por  Brendan  Eich  en  1995,  que  sirve  principalmente  para  programar   procesamientos  del  lado  "cliente"  en  los 
desarrollos  Web.  La  primera  versión  de  este  lenguaje  fue  bautizado  por  LiveScript.  El  objetivo  era  proporcionar  un 
lenguaje de script al navegador (browser) Netscape Navigator 2. 

Rápidamente,  LiveScript  fue  renombrado  por  JavaScript,  y  una  organización,  el  ECMA,  se  hizo  responsable  de  los 
aspectos  relativos  a  la  estandarización.  En  paralelo,  Microsoft  desarrolló  su  propia  solución  de  scripting  para  su 
navegador Internet Explorer. 

La  programación  del  lado  "cliente"  de  JavaScript  permite  añadir  una  cierta  interactividad  a  las  páginas  Web.  En 
particular,  las  páginas  podrán  reaccionar  a  las  acciones  del  usuario,  como  la  selección  en  una  lista  desplegable,  la 
selección de una casilla de selección o un clic en un botón de un formulario. 

El código JavaScript, almacenado como archivos en un servidor Web, es accesible, a través del protocolo HTTP, por el 
navegador del puesto "cliente", usando una llamada del usuario a través de la introducción de una URL o con un clic 
en un enlace de hipertexto. El código JavaScript es no compilado y se interpreta por un motor dedicado, incorporado 
al navegador. 

El lenguaje JavaScript ha sufrido muchas evoluciones a lo largo del tiempo y se soporta prácticamente por todos los 
principales navegadores (Microsoft Internet Explorer, Mozilla Firefox, Opera, Safari, Google Chrome...), que están en 
los  ordenadores,  independientemente  de  su  sistema  operativo  (diferentes  versiones  de  Microsoft  Windows,  Unix, 
Linux, Mac OS X...). 

JavaScript  se  dejó  de  lado  durante  mucho  tiempo  porque  tenía  la  reputación  de  ser  difícil  de  depurar  y  tener 
comportamientos  muy  diferentes  entre  un  navegador  y  otro.  Se  han  añadido  muchas  mejoras  a  lo  largo  de  las 
versiones (JavaScript 2.0 actualmente). 

Puede  encontrar  la  descripción  completa  de  las  novedades  de  JavaScript  en  el  sitio  web  de  Mozilla 
(https://developer.mozilla.org/es/docs/Web/JavaScript). 

Para  terminar,  JavaScript  ha  recuperado  su  esplendor  con  la  aparición  de  muchas  librerías  de  calidad  y  frameworks 
(Ajax, jQuery, Dojo...). Por tanto, JavaScript es una piedra angular en los desarrollos de la "Web 2.0". 

También mencionamos la confusión de los desarrolladores principiantes entre JavaScript y Java. No hay que confundir 
Java y JavaScript. JavaScript es un lenguaje de programación de scripts desarrollado por Netscape Communications, 
mientras  que  Java  es  un  lenguaje  de  programación  informático  orientado  a  objetos,  creado  por  James  Gosling  y 
Patrick Naughton, empleados de Sun Microsystems. La sintaxis de los dos lenguajes es parecida, porque derivan los 
dos del C++. 

Comparativo Java/JavaScript: 

Java  JavaScript 

Autor  Desarrollado por Sun Microsystems  Desarrollado  por  Netscape 


Communications 

Formato  Compilado como de byte­code  Interpretado 

Almacenamiento  Applet  descargado  como  un  elemento  Código insertado en la página Web 


de la página Web 

Uso  Se  usa  para  desarrollar  todo  tipo  de  Se  usa  únicamente  para  "dinamizar" 
aplicaciones  las páginas Web 

Ejecución  Se  ejecuta  en  la  JVM  (Java  Virtual  Se ejecuta por el navegador 


Machine) del navegador 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Programación  orientada  a  Orientado a objetos  Manipula  objetos  pero  no  permite 
objetos (POO)  definirlos 

Tipado  Fuertemente tipado  Sin control de tipo 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Requisitos previos para un aprendizaje sencillo del lenguaje

Muy  a  menudo,  JavaScript  se  considera  como  un  lenguaje  muy  accesible  desde  el  punto  de  vista  técnico. 
Evidentemente, en desarrollos sencillos los principiantes podrán hacer sus intentos de manera fácil. Además, existe 
una documentación importante sobre el tema (libros, sitios de Internet, foros, vídeos...). 

Por el contrario, para aplicaciones profesionales, ya no será posible conformarse con descargar scripts y adaptarlos 
para  integrarlos  en  sus  propias  páginas  HTML.  Se  deberá  hacer  una  inversión  real  en  formación  y  son  necesarias 
competencias mínimas en desarrollo de software. 

De  manera  ideal,  para  controlar  JavaScript  en  las  mejores  condiciones,  hay  que  tener  algunos  conocimientos  de 
algoritmia, haber desarrollado previamente en un lenguaje de scripting o incluso, mejor, en un lenguaje evolucionado 
como C++ o Java. 

Este libro, accesible para los principiantes en desarrollo Web y en JavaScript en particular, repasará muchos requisitos 
previos  indispensables,  en  concreto  de  algoritmia  (enfoque  procedimental  inicial)  y  del  lenguaje  HTML  (sin  hacer  un 
estudio exhaustivo), antes de abordar realmente JavaScript. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Herramientas necesarias

Es frecuente oír que "el desarrollo Web no necesita muchas herramientas". En un primer enfoque, es cierto que para 
desarrollar páginas Web con lenguajes HTML y JavaScript es posible utilizar herramientas sencillas (y gratuitas). Un 
editor  de  texto  como  Notepad  y  un  navegador  pueden  ser  suficientes.  Incluso  no  es  obligatoria  una  conexión  a 
Internet. 

Por el contrario, para desarrollos importantes, puede ser útil tener piezas de software más evolucionadas (gratuitas o 
de  pago).  Para  elaborar  sus  scripts,  puede  utilizar  editores  de  texto  (gratuitos),  que  ofrecen  prestaciones  más 
completas  (coloración  sintáctica,  gestión  multiarchivo,  completar  automáticamente  el  código,  acceso  FTP  integrado, 
soporte  de  múltiples  lenguajes  Web...).  Por  ejemplo,  Notepad++  (http://notepad­plus­plus.org/)  o  Aptana  Studio 
(http://www.aptana.com/products/studio3/download) pueden sustituir a Notepad. 

Kompozer (http://kompozer.net/) también es un software gratuito y puede ser una alternativa interesante. Se trata de 
un software clasificado dentro de la categoría de IDE (Integrated Development Environment). 

También existen muchos generadores de código o IDE gratuitos o de pago. El más conocido es Adobe Dreamweaver. 

Para que sirva de orientación, muchos ejemplos utilizados en este libro se han desarrollado con Aptana Studio 3.4.1. 

Los principales ejemplos de este libro se pueden descargar libremente desde la página Información. Para facilitarle su 
uso,  estos  scripts  están  clasificados  por  capítulos.  Se  ha  hecho  un  esfuerzo  particular  a  nivel  de  la  calidad  de  estos 
scripts (comentarios, indentación, nomenclatura de variables...) para facilitar su reutilización. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Posicionamiento de JavaScript respecto a otras tecnologías de 
desarrollo Web (HTML, CSS, PHP...)

Ubicamos  también  rápidamente  el  lenguaje  JavaScript  respecto  a  otros  lenguajes  o  tecnologías  habituales  en  los 
proyectos  de  desarrollo  Web.  Sepa  que  el  código  JavaScript  se  utiliza  de  manera  aislada  muy  raramente.  Las 
secuencias  de  código  JavaScript  son,  la  mayor  parte  de  las  veces,  para  animar  los  scripts  HTML  (HyperText  Markup 
Language).  Para  decir  las  cosas  de  una  manera  más  sencilla,  en  la  visualización  de  páginas  Web,  el  lenguaje  HTML 
describe principalmente el contenido, mientras que el JavaScript, como se ha comentado anteriormente, gestiona la 
interactividad. 

Muy  a  menudo,  el  formateo  de  la  información  mostrada  (secuencias  de  texto,  tablas,  imágenes...)  no  se  asegura 
directamente  con  directivas  (etiquetas)  del  lenguaje  HTML,  sino  usando  una  tecnología  adicional  (sin  duda,  es 
exagerado hablar de lenguaje), el CSS (Cascading Style Sheets), también llamado "hojas de estilo en cascada". 

También es muy importante entender que el lenguaje JavaScript está orientado al lado "cliente". Por lo tanto, es inútil 
pedirle  actuar  en  el  lado  "servidor".  No  puede  acceder  a  las  bases  de  datos  almacenadas  en  el  servidor  y  buscar 
datos  almacenados  en  las  tablas.  Hay  lenguajes  adicionales,  muy  utilizados  en  los  proyectos  Web,  como  PHP, 
Microsoft  ASP.NET  e  incluso  Java,  que  tendrán  precisamente  este  papel.  Estos  lenguajes,  usando  consultas  SQL, 
preguntan a las bases de datos y un intérprete (software de lado "servidor") genera sobre la marcha el código HTML, 
que contiene la información leída de las tablas. Posteriormente se envía al navegador del puesto "cliente", usando el 
protocolo  HTTP.  Solo  queda  que  el  navegador  descodifique  (descifre)  el  código  HTML  (y  JavaScript  si  es  necesario) 
para conseguir una visualización sencilla consultable por un usuario humano. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Presentación de la noción de algoritmo

Un  algoritmo  es  la  descripción  de  las  operaciones  necesarias  para  obtener  un  resultado  a  partir  de  valores  de 
entrada:  los  "datos".  Un  programa  es  un  algoritmo  escrito  en  un  lenguaje  concreto.  Volveremos  sobre  esto  más 
adelante. 

Una receta de cocina se puede considerar como un algoritmo. Para que sirva de ejemplo, la fabricación de un pastel 
se basa en ingredientes (leche, mantequilla, harina, azúcar...) y se aplicará un procedimiento metódico (receta de la 
abuela)  para  utilizar  estos  ingredientes  (mezcla,  tiempo  de  cocción...).  Habrá  comprobado  en  su  día  a  día  que 
utilizamos algoritmos sin darnos cuenta realmente (recetas, noticias, planos de diseño, plantillas...). 

Volvamos  sobre  nuestro  ejemplo  de  la  receta  de  cocina.  En  su  ausencia,  es  posible  conseguir  el  plato  con  una 
sucesión  de  intentos  (ensayos,  tiempo  de  cocción  aproximado).  Evidentemente,  esta  forma  de  proceder  (incluso  si 
para algunos es satisfactoria) no es eficaz (se pierde tiempo y es un lío de ingredientes). 

La programación va a ser el medio de definir y especificar al ordenador el conjunto de operaciones necesarias para 
resolver  un  problema.  Se  trata  de  la  traducción  a  un  lenguaje  comprensible  por  la  máquina  de  las  secuencias  de 
acciones  que  se  deben  aplicar  a  los  datos,  en  el  marco  de  un  procesamiento  informático.  Aquí  también  es  posible 
hacer una comparación con los idiomas; un mismo ordenador puede entender (ejecutar) varios lenguajes informáticos 
(Pascal,  C,  C++,  Java,  Objective­C,  JavaScript...).  A  partir  de  un  algoritmo  idéntico  (una  especie  de  modelo  lógico), 
será posible traducirlo de varias maneras programáticas. 

En resumen, en el procesamiento de un problema, hay que distinguir dos fases principales: 

l La búsqueda y redacción de una solución; un algoritmo (análisis del problema).  

l La expresión del algoritmo en un lenguaje de programación para su explotación en el ordenador (codificación). 

En  este  capítulo  se  exponen  los  principios  generales  de  la  algoritmia  y  se  pone  el  acento  en  la  formulación  de 
algoritmos  en  lenguaje  descriptivo,  en  detrimento  del  lenguaje  JavaScript,  que  se  verá  en  detalle  en  los  siguientes 
capítulos. 

Para que sirva de ejemplo, esto es lo que dice la enciclopedia Wikipedia sobre este asunto: un algoritmo (del griego y 
latín, dixit algorithmus, y este a su vez del matemático persa Al­Juarismi), es un conjunto prescrito de instrucciones o 
reglas  bien  definidas,  ordenadas  y  finitas  que  permite  realizar  una  actividad  mediante  pasos  sucesivos,  que  no  generen 
dudas a quien deba realizar dicha actividad. Dados un estado inicial y una entrada, siguiendo los pasos sucesivos, se llega 
a un estado final y se obtiene una solución. Los algoritmos son el objeto de estudio de la algoritmia. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Noción de variable

1. Presentación de las nociones de variable y tipo

Un algoritmo manipula objetos sobre los que puede realizar acciones. Los objetos simples son: 

l números (3.14159, 1980, 9...), 

l caracteres ("A", "9"...) y cadenas de caracteres ("PAULINA"...), 

l valores booleanos o lógicos (verdadero o falso). 

Para  poder  manipular  estos  objetos,  hay  operaciones  disponibles.  Estos  objetos,  así  como  las  operaciones 
asociadas,  se  deben  definir  perfectamente.  Analicemos  los  tres  ejemplos  siguientes,  que  son  situaciones  de 
intercambio entre un cliente y un vendedor. 

Ejemplo 1: 

l "Buenos días, quisiera 1 kg y 1 kg." 

l "??" 

Ejemplo 2: 

l "Buenos días, señor, quisiera 1 kg de arroz y 1 kg de vino." 

l "Aquí está su kilo de arroz y ¿qué más quería?" 

Ejemplo 3: 

l "Buenos días señor, quisiera 1 kg de arroz y 1 litro de vino." 

l "Le he puesto todo en esta bolsa." 

En estos ejemplos, comprobamos la necesidad de: 

l citar la naturaleza de los objetos que vamos a manipular (arroz, vino...), 

l no  utilizar  estos  objetos  de  cualquier  manera  (el  arroz  se  pesa,  el  vino  se  bebe...)  es  decir,  para  cada 
naturaleza de objeto, hay operaciones particulares. 

Se llama tipo a la asociación: 

l de una naturaleza de objeto (arroz, vino, o incluso enteros, reales...), 

l y las operaciones asociadas (pesar, lavar, cocinar el arroz, sumar, multiplicar enteros...). 

2. Tipos básicos y operaciones asociadas

Hay cuatro tipos básicos: entero, real, booleano y carácter. 

El tipo entero: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


l Los valores son números enteros. 

l Notación: se utiliza la notación decimal (ejemplos: 365, ­15). 

l Operaciones: adición, sustración, multiplicación, división entera, módulo (resto de la división entera), etc. 

El tipo real: 

l Los valores son números reales. 

l Notación: el punto anglosajón se sustituye por la coma (ej.: 124.89, 0.136, 1986). 

l Operaciones: las que se usan habitualmente con los números reales en aritmética. 

El tipo booleano: 

l Solo hay dos valores booleanos: verdadero o falso. 

l Notación: Verdadero y Falso. 

l Operaciones: se utilizan los operadores lógicos usuales (No, O e Y). 

Recordemos el funcionamiento de los operadores lógicos No, Y y O, con esta tabla resumen: 

A  No A 

Verdadero  Falso 

Falso  Verdadero 

A  B  A O B 

Verdadero  Falso  Verdadero 

Falso  Verdadero  Verdadero 

Falso  Falso  Falso 

Verdadero  Verdadero  Verdadero 

A  B  A Y B 

Verdadero  Falso  Falso 

Falso  Verdadero  Falso 

Falso  Falso  Falso 

Verdadero  Verdadero  Verdadero 

En resumen:  

l El contrario de Falso es Verdadero e inversamente (cf. tabla de No). 

l Con  el  O  lógico,  es  suficiente  con  que  uno  de  los  operandos  (A,  B)  sea  Verdadero  para  que  el  resultado  A  O  B  sea 
Verdadero (cf. tabla de O). 

l Con  el  Y  lógico,  los  dos  operandos  (A,  B)  deben  ser  simultáneamente  Verdadero  para  que  el  resultado  A  Y  B  sea 
Verdadero (cf. tabla del Y). 

3. Interés de los tipos

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Hagamos  aquí  un  pequeño  esfuerzo  de  abstracción,  imaginando  un  lenguaje  (de  comunicación)  basado 
exclusivamente en dos tipos. 

La definición de estos tipos (naturaleza de los objetos y operaciones asociadas) es cercana a la "vida real". Este 
lenguaje permitirá manipular los objetos de tipo "Sólido" y de tipo "Líquido". 

Caractericemos estos dos tipos como sigue: 

Sólido: 

l Naturaleza: materia con forma propia 

l Operaciones: fundir, comer 

Líquido: 

l Naturaleza: materia que tiende a fluir 

l Operaciones: hervir, beber, vaciar 

y escribimos un primer algoritmo: 

Inicio 

Sólido: mantequilla, queso, caucho 

Líquido: aceite, agua, vino, refresco 

Beber aceite, fundir mantequilla, fundir vino, comer caucho, beber sidra, cocinar caucho 

Fin 

Hay dos ventajas que se perciben con el uso de tipos en nuestro "lenguaje": 

l Para describir objetos de la misma naturaleza, que admiten las mismas operaciones, es suficiente con describir el tipo 
una vez para todos y anunciar que tal o cual objeto es de tal o cual tipo. Las repeticiones se evitan. 

l El  tipado  (uso  de  tipos)  proporciona  un  medio  para  detectar  un  determinado  número  de  errores  sin  ejecutar  el 
algoritmo, simplemente examinando las operaciones respecto al tipo anunciado. 

Sin realizar las acciones descritas en este algoritmo, vemos que la operación fundir vino es errónea, porque el vino 
es un objeto declarado de tipo Líquido y la operación fundir no está asociada a este tipo. La operación comer caucho 
es  correcta,  aunque  el  caucho  sea  indigesto.  Beber  sidra  no  es  posible,  porque  la  sidra  no  se  ha  citado  como 
elemento de tipo Líquido. Para terminar, es inútil declarar el agua y el refresco, porque no se usan. 

4. Uso de variables en las expresiones

La  manera  más  habitual  de  manipular  los  objetos  es  hacerlos  intervenir  en  cálculos.  Para  esto,  se  utilizan  los 
operadores elementales sobre un operando (operadores unarios) o sobre dos operandos (operadores binarios). 

Una expresión es la asociación de operadores y operandos. Las reglas gobiernan el orden de evaluación de los 
diferentes términos de una expresión: 

l Una operación se evalúa inicialmente si su prioridad es más fuerte que la de las operaciones adyacentes (ejemplo: el 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


cálculo de 3+5/2 empieza por 5/2). 

l En  caso  de  igualdad  de  prioridad,  la  evaluación  tiene  lugar  de  izquierda  a  derecha  (ejemplo:  3+2­5  se  evalúa 
empezando por 3+2). 

l Siempre podemos utilizar paréntesis para forzar el orden de evaluación (ejemplo: 3*(2­5) se evalúa empezando por 
2­5). 

5. Tabla resumen de los operadores

La  siguiente  tabla  lista  los  operadores  que  se  usan  en  algoritmia,  así  como  la  prioridad  existente  entre  estos 
operadores durante la evaluación de expresiones. 

Resulta evidente que prácticamente siempre estos operadores se encontrarán (con las mismas notaciones) en los 
lenguajes de programación. Volveremos más tarde en este libro sobre ellos, aplicados a JavaScript. 

Operador  Notación  Tipo de operandos  Tipo de resultado 

+ y ­ unario  + ­  Entero o Real  El del operando 


Negación lógico  No  Booleano  Booleano 

Potencia  **  Entero o Real  Entero o Real 

Multiplicación  *  Entero o Real  Entero o Real 


División de reales  /  Real  Real 
Cociente de enteros  Div  Entero  Entero 
Resta (módulo)  Mod  Entero  Entero 

Adición  +  Entero o Real  Entero o Real 


Sustración  ­  Entero o Real  Entero o Real 

Comparaciones  >,  <,  >= ,  <= ,  = ,  Cualquier tipo  Booleano 


<>  

Y lógico  Y  Booleano  Booleano 

O lógico  O  Booleano  Booleano 

Los  operadores  se  clasifican  por  orden  de  prioridad  decreciente  en  esta  tabla  (el  No  es,  por  ejemplo, 
prioritario respecto al O). 

El orden de los caracteres se rige por la tabla ASCII. En esta tabla, cada carácter ocupa una posición numérica; el 
65 para la letra "A", el 97 para la letra "a", lo que hace pensar que "a" es más grande que "A". 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Manipulación de las variables

1. Nomenclatura de las variables

Durante  el  análisis  de  un  problema,  a  menudo  tenemos  que  descomponer  este  en  subproblemas,  que  se  deben 
resolver  en  un  orden  secuencial  concreto.  Cada  subproblema  genera  resultados  que  se  pueden  utilizar  en  los 
subproblemas que siguen. Por tanto, para poder manipular estos resultados, conviene asignarles un nombre. Esta 
nomenclatura se hace a través de un identificador. También se habla muy a menudo de variable en memoria. 

A cada variable en memoria, se le asocia las siguientes características: 

l su  denominación,  que  se  debe  hacer  con  sentido  (dos  resultados  diferentes  se  designan  por  identificadores 
diferentes), 

l su tipo (conjunto al que pertenece el valor que designa). 

Estas características se precisan durante la declaración de la variable en memoria. 

Sintaxis de la declaración: 

Tipo IDENTIFICADOR 

Tipo es el tipo e IDENTIFICADOR es la denominación de la variable en memoria. 

Ejemplos: 

Real PI 
Car SEPARADOR 
Bool TEST 
Ent NBMESES, NBDIAS 

Una vez que se define una variable en memoria, no se puede cambiar su tipo. 

Cualquier variable en memoria utilizada en un algoritmo se debe haber declarado con antelación. 

En lo sucesivo, se ha elegido nombrar  a  las  variables  en  memoria  en  mayúsculas,  para  mejorar  su  legibilidad. 
Debe  saber  que  hay  muchos  lenguajes  de  programación  que  son  sensibles  a  la  diferencia  entre  mayúsculas  y 
minúsculas de las variables en memoria (una variable CANTIDAD es diferente de una variable Cantidad). 

Evidentemente,  en  programación  (JavaScript  en  nuestro  caso),  se  pueden  proponer  diferentes  convenciones  de 
nomenclatura. 

En  JavaScript,  para  las  variables  en  memoria  (y  las  funciones),  la  convención  comúnmente  aceptada  es  el 
"camelCaps", es decir, que los nombres deben empezar sistemáticamente por una minúscula y después se insertan 
mayúsculas  al  inicio  de  cada  palabra  que  aparece  en  el  nombre  de  la  variable.  Por  ejemplo,  una  variable  como 
ACUMULADO_ANUAL  (la  convención  en  esta  presentación  de  la  algoritmia)  se  codificará  como  acumuladoAnual  en 
JavaScript. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Puede observar que, en este libro, muchos scripts JavaScript no usan la convención camelCaps. La elección ha sido 
no modificar los nombres de las variables en memoria de los algoritmos subyacentes. 

2. Asignación

La asignación consiste en almacenar e incluso imputar una expresión a una variable en memoria. La sintaxis que se 
mantiene en esta presentación de la algoritmia es: 

IDENTIFICADOR <­ expresión 

La asignación se representa con el símbolo "<­" (y no con "=", que sirve para hacer comparaciones de igualdad). 

La expresión debe ser del mismo tipo que los valores designados por el identificador. Esta expresión se convierte en 
el nuevo valor, designado por IDENTIFICADOR. 

Las  convenciones  que  se  mantienen  aquí  pueden  ser  diferentes  de  las  que  se  usan  en  determinados  lenguajes  de 
programación.  Para  JavaScript,  la  asignación se  representa  con  "= ",  mientras  que  la  comparación  en  igualdad  es 
"= = ".  Lo  ha  entendido  con  este  pequeño  ejemplo,  pero  es  necesario  estar  muy  atento  durante  la  codificación  en 
programación. Tendremos la ocasión de volver sobre esta dificultad varias veces a lo largo de este libro. 

Para ilustrar las diferentes nociones descritas, en adelante se presentan ejemplos en este libro. Esto le permitirá 
descubrir  los  mecanismos  de  la  algoritmia  en  cada  situación.  Después  puede  (también  es  el  objetivo  de  esta 
presentación) escribir sus propios algoritmos para procesamientos que usted codificará finalmente en JavaScript. 

3. Ejercicio n.°1: Inversión del contenido de dos variables en memoria

Enunciado 

Se  le  pide  invertir  el  contenido  de  dos  variables  en  memoria  de  tipo  entero.  La  primera  variable  se  llamará,  por 
ejemplo,  A  y  la  segunda  B.  El  valor  inicial  de  A  será,  por  ejemplo,  5,  mientras  que  el  de  B  será  3.  Utilizando  un 
algoritmo debe invertir los contenidos para que al final A contenga 3 y B, 5. 

Inicio 

Ent A, B, C 

A <­ 5 
B <­ 3 
C <­ A 
A <­ B 
B <­ C  

Fin 

Para que sirva de ejemplo, el contenido de las variables en memoria a lo largo del desarrollo del algoritmo será: 

l A <­ 5 (A contiene 5, B está vacío) 

l B <­ 3 (A contiene 5, B contiene 3) 

l C <­ A (A contiene 5, B contiene 3, C contiene 5) 

l A <­ B (A contiene 3, B contiene 3, C contiene 5) 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


l B <­ C (A contiene 3, B contiene 5, C contiene 5) 

Terminamos con algunas reglas generales de formato y sintaxis: 

l Puede  prever  una  línea  en  blanco  (interlineado)  entre  las  secciones  principales  de  su  algoritmo  (declaraciones, 
inicializaciones, cálculos, visualización de resultados...) e incluso, por qué no, justo después de Inicio y antes de Fin. 

l Prevea un trazo vertical para relacionar la palabra clave Inicio con la palabra clave Fin. 

l Observe que las palabras clave aparecen en Negrita/Cursiva en las correcciones (inicial únicamente en mayúscula). 

l Los  nombres  de  las  variables  estarán  completamente  en  MAYÚSCULAS  (contrario  a  las  convenciones  habituales  en 
JavaScript). 

4. Visualización de los resultados

En el ejercicio anterior, la inversión del contenido de las dos variables A y B se hace sin dificultad. Por el contrario, el 
contenido de estas dos variables no se ha presentado en la pantalla (o en el visor). Es útil mostrar en pantalla el 
resultado  de  los  procesamientos,  al  menos  el  resultado  final.  Esta  visualización  (o  escritura)  de  los  resultados  se 
debe solicitar explícitamente. 

A nivel de algoritmia, se va a considerar que la escritura se hace después en una sucesión de líneas, sin indicación 
particular del formato de visualización (negrita, cursiva, fuente de caracteres específica...). 

El orden de escritura se realiza por la instrucción Escribir(e1, e2, ..., ei, ..., en), donde las "ei" pueden representar: 

l una expresión, 

l una cadena de caracteres representada entre comillas, 

l el orden Alineación, que hace empezar la impresión en la línea siguiente. 

Ejemplo n.°1: 

Escribir("El cuadrado de 4 es ", 4 * 4) 
provoca la impresión de: 
El cuadrado de 4 es 16 

Ejemplo n.°2: 

Escribir("La nota en español es ", 10 + 4, Alineación, "La nota en informática es ", (18 + 12) / 2) 
provoca la impresión de: 
La nota en español es 14 
La nota en informática es 15 

Ejemplo n.°3: 

Escribir("La nota en español es ", 10 + 4) 
Escribir("La nota en informática es ", (18 + 12) / 2) 
provoca la impresión de: 
La nota en español es 14 
La nota en informática es 15 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Ejemplo n.°4: 

Real MAT, INFO 
MAT <­ 15 
INFO <­ 13 
Escribir("La media es ", (MAT + INFO) / 2) 
provoca la impresión de: 
La media es 14 

Ejemplo n.°5: 

Real MAT, INFO, MED 
MAT <­ 15 
INFO <­ 13 
MED <­ (MAT + INFO) / 2 
Escribir("La media es ", MED) 
provoca la impresión de: 
La media es 14 

En  la  gran  mayoría  de  los  lenguajes  de  programación,  la  instrucción  de  visualización  de  mensajes  en  pantalla  no 
permite la presentación simultánea de una información alfanumérica y numérica. Por tanto, también convendría en la 
algoritmia  integra  esta  restricción,  usando  la  función  Numero_a_cadena.  En  la  mayor  parte  de  las  correcciones  de 
ejercicios propuestos en este capítulo esta función no se ha utilizado. 

Ejemplo n.°6: 

Real MAT, INFO 
MAT <­ 15 
INFO <­ 13 
Escribir("La media es ", Número_a_cadena((MAT + INFO) / 2)) 
provoca la impresión de: 
La media es 14 

5. Ejercicio n.°2: Superficies de círculos

Enunciado 

Calcular (y mostrar en pantalla) la superficie de dos círculos de radios predeterminados (5,5 metros y 3,5 metros, 
por ejemplo), así como la diferencia entre estas dos superficies 

Corrección 

Inicio 

Real RADIO1, RADIO2, PI, SUPERFICIE1, SUPERFICIE2, DIFERENCIA  

RADIO1 <­ 5.5 
RADIO2 <­ 3.5 
PI <­ 3.14 

SUPERFICIE1 <­ PI * RADIO1 * RADIO1 
SUPERFICIE2 <­ PI * RADIO2 * RADIO2 
DIFERENCIA <­ SUPERFICIE1 ­ SUPERFICIE2 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Escribir("Superficie 1 = ", SUPERFICIE1, Alineación, "Superficie 2 = ", 
SUPERFICIE2, Alineación, "Diferencia = ", DIFERENCIA) 

Fin 

6. Introducción por el teclado

Los algoritmos no tienen un interés general si, durante cada ejecución, proporcionan siempre el mismo resultado. 

Para  acceder  a  los  datos  que  el  usuario  ha  introducido  por  el  teclado  (o  se  han  leído  de  un  archivo),  a  nivel  de 
algoritmia tendremos una instrucción dedicada. La entrada de datos en el periférico de entrada se hará a través de 
la instrucción Leer. 

La entrada de datos por Leer se asignará a una variable en memoria (declarada con antelación). La instrucción Leer 
se deberá preceder obligatoriamente de un mensaje explicativo (Escribir("Su entrada de datos:") por ejemplo) para 
indicar al usuario la entrada de datos esperada. 

Ejemplo: 

Inicio 

Co Declaraciones Fco 
Car NOMBRE, APELLIDO 

Co Introducción del nombre por el teclado Fco 
Escribir("Nombre: ") 
NOMBRE <­ Leer 

Co Introducción del apellido por el teclado Fco 
Escribir("Apellido: ") 
APELLIDO <­ Leer 

Co Visualización de la pantalla para control Fco 
Escribir("La identidad es ", NOMBRE, " ", APELLIDO) 

Fin 

NB: 

Co significa inicio de comentario 

Fco significa fin de comentario 

Los comentarios situados en un algoritmo (y en un programa informático) no juegan un papel efectivo. En el caso de 
un lenguaje de programación como JavaScript, serán ignorados por la máquina durante la ejecución del programa. 
Sin  embargo,  son  necesarios,  porque  permiten  al  programador  (o  a  terceras  personas  que  deban  intervenir 
posteriormente  en  el  algoritmo  o  programa)  entender  más  fácilmente  el  razonamiento  codificado.  Los  comentarios  se 
sitúan, como mínimo, al inicio de cada porción de código específico. 

7. Ejercicio n.°3: Superficie y volumen de una esfera

Enunciado 

Calcular y mostrar la superficie y el volumen de una esfera, cuyo valor del radio se introducirá por el teclado 

Corrección 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


Inicio 

Co Declaraciones Fco 
Real PI, RADIO, SUPERFICIE, VOLUMEN 

Co Introducción del radio por el teclado Fco 
Escribir("Radio: ") 
RADIO <­ Leer 

Co Cálculos Fco 
PI <­ 3.14 

SUPERFICIE <­ 4 * PI * RADIO * RADIO 
VOLUMEN <­ SUPERFICIE * RADIO / 3 

Co Visualización de los resultados Fco 
Escribir("Radio  de  la  esfera  =   ",  RADIO,  Alineación,  "Superficie  =   ",  SUPERFICIE,  Alineación, 
"Volumen = ", VOLUMEN) 

Fin 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Funciones predefinidas

Una función predefinida es un "microprograma" autónomo, al que es posible pedir un procesamiento (un cálculo en 
general), pasando uno o varios argumentos. Una vez que el cálculo está asegurado, la función restituye un valor de 
retorno  (la  respuesta)  al  solicitante  (secuencia  de  código  que  llama  a  la  función).  Esta  noción  seguramente  le  es 
familiar si, por ejemplo, ha utilizado funciones nativas en Microsoft Excel (SUMA, BUSCAR...). 

Veremos más tarde en esta presentación de la algoritmia (y también, sobre todo, en JavaScript) cómo desarrollar sus 
propias funciones. 

El objetivo aquí no es enumerar la lista de funciones habituales en algoritmia (además pueden variar de un autor a 
otro), sino mostrarle cómo se pueden usar. Se utilizará una presentación a través de ejemplos o ejercicios. 

1. Ejercicio n.°4: Visualización de la longitud de un nombre

Enunciado 

Escribir un algoritmo que permita introducir por el teclado un nombre para mostrar el número de caracteres 

Complemento  del  ejercicio:  Una  función  Longitud(variable_cadena)  predefinida  se  utilizará  para  determinar  el 
número de caracteres de la palabra. 

Correcciones 

Inicio 

Co Declaraciones Fco 
Car NOMBRE 

Co Introducción del nombre por el teclado Fco 
Escribir("Nombre:") 
NOMBRE <­ Leer 

Co Visualización del resultado Fco 
Escribir(NOMBRE, " contiene " , Longitud(NOMBRE), " carácter(es)") 

Fin 

E incluso: 

Inicio 

Co Declaraciones Fco 
Car NOMBRE 
Ent NB_CAR 

Co Introducción del nombre por el teclado Fco 
Escribir("Nombre: ") 
NOMBRE <­ Leer 

Co Visualización del resultado Fco 
NB_CAR <­ Longitud(NOMBRE) 
Escribir(NOMBRE, " contiene " , NB_CAR, " carácter(es)") 

Fin 

2. Ejercicio n.°5: Determinación de iniciales

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Enunciado 

Escribir  un  algoritmo  que  permita  la  extracción  de  las  iniciales  de  una  persona,  cuyo  apellido  y  nombre  se 
introducirán por el teclado (ejemplo: AS para Ángel Sánchez) 

Complemento: se utilizará una función Sub_cadena(CADENA, POSICION_INICIO, [POSICION_FIN]) predefinida. 

Un argumento de función que no es sistemáticamente necesario se indica por convención entre corchetes. 

En  caso  de  la  función  Sub_cadena,  si  el  tercer  argumento  no  está,  la  extracción  se  hará  a  partir  del  carácter  en 
posición POSICION_INICIO, hasta el final de la cadena de caracteres. 

En muchos lenguajes de programación, este tercer argumento (aquí POSICION_FIN) es, en realidad, un número 
de caracteres que se ha de extraer a partir de la posición POSICION_INICIO). 

En  lo  sucesivo,  encontrará  ejemplos  concretos  de  la  aplicación  de  la  función  Sub_cadena,  así  como  de  funciones 
adicionales (Izquierda, Derecha, Concatenar...). 

Car NOMBRE, APELLIDO, INICIALES 
NOMBRE <­ "Ángel" 
Sub_cadena(NOMBRE, 1, 3) vale ”Áng" 
Izquierda(NOMBRE, 4) vale ”Ánge" 
Sub_cadena(NOMBRE, 3, 2) vale ”el" 
Sub_cadena(NOMBRE, 3) vale ”el" 
Sub_cadena(NOMBRE, Longitud(NOMBRE), Longitud(NOMBRE)) vale ”l" 
Sub_cadena(NOMBRE, Longitud(NOMBRE)) vale ”l" 
Sub_cadena(NOMBRE, Longitud(NOMBRE)­1, Longitud(NOMBRE)) vale ”el" 
Derecha(NOMBRE, 2) vale ”gel" 
Izquierda(APELLIDO, 1) & Izquierda(NOMBRE, 1) vale ”SA" 
APELLIDO <­ "Sánchez" 
INICIALES <­ Sub_cadena(APELLIDO, 1, 1) & Sub_cadena(NOMBRE, 1, 1) vale ”SA" 
INICIALES <­ Concatenar(Sub_cadena(NOMBRE, 1, 1), Sub_cadena(APELLIDO, 1, 1)) vale ”AS" 

El ampersand (&) sirve para concatenar dos elementos de tipo carácter. 

Corrección 

Inicio 

Co Declaraciones Fco 
Car APELLIDO, NOMBRE, INICIAL_APELLIDO, INICIAL_NOMBRE 

Co Introducción del apellido Fco 
Escribir("Apellido: ") 
APELLIDO <­ Leer 

Co Introducción del nombre Fco 
Escribir("Nombre: ") 
NOMBRE <­ Leer 

Co Determinación de las iniciales Fco 
INICIAL_APELLIDO <­ Sub_cadena(APELLIDO, 1, 1) 
INICIAL_NOMBRE <­ Sub_cadena(NOMBRE, 1, 1) 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Co Visualización de las iniciales Fco 
Escribir(APELLIDO, " ", NOMBRE, " tiene como iniciales: ", INICIAL_APELLIDO, INICIAL_NOMBRE) 

Fin 

E incluso: 

Inicio 

Co Declaraciones Fco 
Car APELLIDO, NOMBRE, INICIALES 

Co Introducción del apellido Fco 
Escribir("Apellido: ") 
APELLIDO <­ Leer 

Co Introducción del nombre Fco 
Escribir("Nombre: ") 
NOMBRE <­ Leer 

Co Visualización de las iniciales Fco 
INICIALES <­ Izquierda(APELLIDO, 1) & Izquierda(NOMBRE, 1) 
Escribir(APELLIDO, " ", NOMBRE, " tiene como iniciales: ", INICIALES) 

Fin 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Procesamientos condicionados

En muchas situaciones, las acciones solo se realizan si se cumplen determinadas condiciones: 

l Una ecuación de segundo grado tiene 0, 1 o 2 soluciones reales, según sea el discriminante negativo, nulo o positivo. 

l Si una cantidad de artículos en stock baja de un determinado umbral, hay que hacer un pedido. 

l Si hace bueno, entonces vamos a la playa. En caso contrario hacemos algoritmia juntos. 

l Si no hace bueno, entonces hacemos algoritmia juntos. 

Cada una de estas opciones está condicionada por una expresión booleana que, mientras sea verdadera, implica la 
ejecución del procesamiento asociado. 

La sintaxis de la algoritmia para programar los procesamientos condicionados es sencilla: 

Si Condición 

Entonces 

T1 

[En caso contrario 

T2] 

Finsi 

Algunas observaciones sobre esta estructura tan intuitiva: 

l Condición es una expresión con resultado booleano (Verdadero o Falso). 

l T1 y T2 son los procesamientos. 

l Finsi significa el fin del si. 

l Existe una forma simplificada, sin alternativa (sin En caso contrario T2). 

l Comprobar la condición se hace en una hipótesis de condición verdadera. 

l Dibujar un trazo vertical (a la izquierda) entre Si y Finsi será un medio mnemotécnico para no olvidar el Finsi. 

l Piense en indentar los procesamientos T1 y T2. 

El organigrama de flujo correspondiente a esta estructura es el siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


En el ejemplo que se presenta a continuación, a una variable NBLU se le asigna un valor numérico introducido por el 
teclado y el algoritmo indica si se trata de un valor par o impar: 

Inicio 

Co Declaraciones Fco 
Ent NBLU 

Co Introducción por el teclado Fco 
Escribir("Número: ") 

NBLU <­ Leer 

Co Determinación de la parte Fco 
Si NBLU Mod2 = 0 

Entonces 

Escribir(NBLU, " es par") 

En caso contrario 

Escribir(NBLU, " es impar") 

Finsi 

Fin 

1. Ejercicio n.°6: Polinomio de segundo grado

Enunciado 

Calcular las raíces de un polinomio de segundo grado Ax2 +Bx+C (con A<>0 aunque esta prueba no se hará aquí). 
Los valores A, B y C se introducirán por el teclado. 

Corrección 

Inicio 

Co Declaraciones Fco 
Real A, B, C, DELTA 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Co Introducción de los argumentos Fco 
Escribir("A: ") 
A <­ Leer 

Escribir("B: ") 
B <­ Leer 

Escribir("C: ") 
C <­ Leer 

Co Cálculo del discriminante Fco 
DELTA <­ (B * B) ­ (4 * A * C) 

Co Determinación del número de raíces Fco 
Si DELTA < 0 

Entonces 

Escribir("Sin soluciones") 

En caso contrario 

Si DELTA = 0 
Entonces 
Escribir("Solución única = ", ­B / (2 * A)) 

En caso contrario 

Escribir("Dos raíces: ", (­B+DELTA**0.5)/(2*A), " y ", (­B­DELTA**0.5)/(2*A)) 

Finsi 

Finsi 

Fin 

El  interés  de  este  ejercicio,  además  de  que  revise  un  poco  las  matemáticas,  es  mostrar  que  es  posible  anidar 
estructuras condicionales. La aplicación no es difícil, pero implica un mínimo de rigor, fundamentalmente no olvidar 
cerrar  sus  estructuras  con  un  Finsi  y  también  indentar  (añadir  un  nivel  de  desplazamiento)  los  procesamientos, 
incluidos después de los Entonces y En caso contrario. 

2. Ejercicio n.°7: Etiqueta del mes sin cifrar

Enunciado 

Imprimir en letras el mes correspondiente a un número dado por el teclado (comprendido entre 1 y 12). El control de 
la entrada de datos no se prevé. 

Corrección 

Inicio 

Co Declaraciones Fco 
Ent MESES 

Co Introducción del número del mes Fco 
Escribir("Número del mes (1 a 12): ") 
MESES <­ Leer 

Co Visualización del resultado Fco 
Si MESES=1 

Entonces 

Escribir("Enero") 

En caso contrario 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Si MESES=2 

Entonces 

Escribir("Febrero") 

En caso contrario 

… 

Finsi 

Fin 

Evidentemente, la solución propuesta es opuesta a su nivel de elaboración, pero desde el punto de vista técnico es 
óptima. Por ejemplo, la entrada de datos de la cifra 2 provocará la visualización correcta ("Febrero"). 

También  habría  sido  posible  "superponer"  12  pruebas  sucesivas,  como  se  indica  a  continuación.  Esta  solución  es 
poco satisfactoria porque, independientemente del valor introducido por el teclado, se ejecutan las 12 pruebas. 

Inicio 

Co Declaraciones Fco 
Ent MESES 

Co Introducción del número del mes Fco 
Escribir("Número del mes (1 a 12): ") 
MESES <­ Leer 

Co Visualización del resultado Fco 
Si MESES=1 

Entonces 

Escribir("Enero") 

Finsi 
Si MESES=2 

Entonces 

Escribir("Febrero") 

Finsi 
… 
Si MESES=12 

Entonces 

Escribir("Diciembre") 

Finsi 

Fin 

La  estructura  de  control  Siguiente  ...  Finsiguiente  es  una  solución  elegante  para  gestionar  este  tipo  de 
problemática. La sintaxis es la siguiente:  

Siguiente VARIABLE/EXPRESION 

Valor_1: Accion_1 
… 
Valor_n: Accion_n 
[Otrocaso: Acción por defecto] 

Finsiguiente 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


En el caso donde la variable VARIABLE (o la expresión EXPRESION) sea igual a Valor_1, el procesamiento Accion_1 
se disparará (igual para Valor_2 con, en este caso, la ejecución de Accion_2 y así sucesivamente). 

En determinados lenguajes de programación, la implementación de la estructura  Siguiente  ...  Finsiguiente  es  un 


poco  particular.  Después  de  detectar  la  condición  verdadera,  todas  las  acciones  asociadas  a  las  condiciones 
siguientes se ejecutan, ya sean estas condiciones verdaderas o falsas. En estos lenguajes, hay que prever la adición de 
una palabra clave particular que provoque la salida hacia Finsiguiente. 

La estructura  Siguiente ... Finsiguiente (o su equivalente) no está implementada en todos los lenguajes de 
programación. 

3. Ejercicio n.°8: Etiqueta del mes sin cifrar (Siguiente ... Finsiguiente)

Inicio 

Co Declaraciones Fco 
Ent MESES 

Co Introducción del número del mes Fco 
Escribir("Número del mes (1 a 12): ") 
MESES <­ Leer 

Co Visualización del resultado Fco 
Siguiente MESES 

1: Escribir("Enero") 
2: Escribir("Febrero") 
... 
12: Escribir("Diciembre") 
Otrocaso: Escribir("Error de entrada de datos del n.° de mes") 

Finsiguiente 

Fin 

En  este  ejercicio  se  muestra  un  mensaje  de  error  dentro  de  Otrocaso.  En  contrapartida,  será  necesario  que  el 
usuario  del  algoritmo  (o  del  programa)  lo  ejecute  de  nuevo  porque,  de  momento,  no  se  ha  previsto  ningún 
dispositivo para que se haga una nueva entrada de datos. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


Estructuras iterativas

1. Concepto de iteraciones

En la mayor parte de los problemas, determinadas acciones se deben ejecutar varias veces. 

Cuando el número de repeticiones es grande, resulta pesado rescribir n veces la misma secuencia de código. Esta 
rescritura es imposible en el caso en que el número de repeticiones (iteraciones) es desconocido a priori (trazar un 
conjunto de datos hasta que no haya más). 

Es necesario poder expresar la repetición de una acción que, una vez inicializada, continuará hasta que se produzca 
un determinado evento. Este evento de parada se especificará en el algoritmo con una condición. 

2. Estructuras iterativas básicas

Vamos a estudiar cuatro tipos de iteraciones (bucles), que tendrán su equivalente en los principales lenguajes de 
programación. 

Bucle "Mientras" con una comprobación inicial de iteración: 

Mientras Condición Hacer 

Acciones 

Volverhacer 

Bucle "Hasta que" con una comprobación inicial de iteración: 

Hastaque Condición Hacer 

Acciones 

Volverhacer 

Bucle "Mientras" con una comprobación final de iteración: 

Hacer 

Acciones 

Mientras Condición Volverhacer 

Bucle "Hasta que" con una comprobación final de iteración: 

Hacer 

Acciones 

Hastaque Condición Volverhacer 

Estos cuatro bucles tienen un determinado número de puntos en común: 

l Hastaque es una abreviación para Hasta que 

l Mientras es una abreviación para Mientras 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


l Condición, es una expresión booleana de resultado Verdadero o Falso 

l Acciones representa una secuencia de acciones 

Con las dos últimas iteraciones para las que se hace la comprobación del final de bucle, las Acciones se realizan al 
menos una vez. 

Los bucles "Mientras" y "Hasta que" tienen un funcionamiento muy parecido, en la medida en que es suficiente con 
invertir  la  condición  para  pasar  de  una  sintaxis  a  otra.  Por  ejemplo,  CONTADOR  >  10  en  el  caso  de  un  bucle 
"Mientras" se convertirá en CONTADOR <= 10 en caso de un bucle "Hasta que". 

El siguiente diagrama de flujo corresponde a las estructuras "Mientras" y "Hasta que" (con una comprobación inicial 
de iteración): 

En caso de un bucle Hastaque: 

l la flecha que une "Condición" a "Acciones" corresponde al estado Falso de la Condición, 

l la flecha que une "Condición" a "Acciones siguientes" corresponde al estado Verdadero de la Condición. 

En caso de un bucle Mientras: 

l la flecha que une "Condición" a "Acciones" corresponde al estado Verdadero de la Condición, 

l la flecha que une "Condición" a "Acciones siguientes" corresponde al estado Falso de la Condición. 

3. Ejercicio n.°9: Media de 10 números

Enunciado 

Calcular y mostrar la media de 10 números que se introducirán por el teclado 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Corrección 

Inicio 

Co Cálculo de la media de 10 números que se introducirán por el teclado Fco 

Co Declaraciones Fco 
Real NBLU, CPT, SUMA, MEDIA 

Co Inicializaciones Fco 
CPT <­ 1 
SUMA <­ 0 

Co Iteración Fco 
Mientras CPT < 11 Hacer 

Escribir("Número n.° ", CPT, ": ") 
NBLU <­ Leer 
SUMA <­ SUMA + NBLU 
CPT <­ CPT + 1 

Volverhacer 

Co Visualización del resultado Fco 
MEDIA <­ SUMA / 10 
Escribir("Media: ", MEDIA) 

Fin 

4. Ejercicio n.°10: Media de una serie de n números

Enunciado 

Calcular y mostrar la media de n números reales que se introducirán por el teclado (lista terminada con un cero) 

Aprovechamos este enunciado un poco más complejo para mostrar que una misma problemática se puede resolver 
utilizando múltiples algoritmos. 

Corrección n.°1 

Inicio 

Co Declaraciones Fco 
Real NBLU, CPT, SUMA, MEDIA 

Co Inicializaciones Fco 
CPT <­ 0 
SUMA <­ 0 
NBLU <­ 1 Co Para permitir pasar por la iteración, al menos una vez Fco 

Co Bucle de lectura Fco 
Hastaque NBLU = 0 Hacer 

Escribir("Número (0 para terminar): ") 
NBLU <­ Leer 
CPT <­ CPT +1 
SUMA <­ SUMA + NBLU 

Volverhacer 

Co Visualización del resultado Fco 
MEDIA <­ SUMA / (CPT­1) 
Escribir("Media de los ", CPT ­ 1, "números = ", MEDIA) 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Fin 

En  esta  corrección,  la  entrada  del  número  cero  no  provoca  la  salida  inmediata  del  bucle.  Por  tanto,  es  necesario 
reducir  el  valor  de  la  variable  CPT  (contador  de  la  cantidad  de  números  que  se  introducen  por  el  teclado)  en  el 
cálculo de la media. También es necesario pensar en asignar un valor inicial a la variable NBLU (aquí 1) antes de la 
iteración,  para  que  se  pueda  iniciar.  Para  terminar,  con  esta  versión  de  corrección,  se  produciría  un  problema 
(división por cero) si el primer número introducido por el teclado es un 0. 

Corrección n.°2 

Inicio 

Co Declaraciones Fco 
Real NBLU, CPT, SUMA, MEDIA 

Co Inicializaciones Fco 
CPT <­ 0 
SUMA <­ 0 

Co Bucle de lectura Fco 
Hacer 

Escribir("Número (0 para terminar): ") 
NBLU <­ Leer 
CPT <­ CPT +1 
SUMA <­ SUMA + NBLU 

Mientras NBLU <> 0 Volverhacer 

Co Visualización del resultado Fco 
Si CPT­1=0 
Entonces 

Escribir("No se ha introducido ninguna cifra ") 

En caso contrario 

MEDIA <­ SUMA / (CPT­1) 
Escribir("Media de los ", CPT ­ 1, "números = ", MEDIA) 

Finsi 

Fin 

En  esta  corrección,  se  ha  utilizado  un  bucle  Mientras  con  una  comprobación  final  de  bucle.  Aquí  no  es  necesario 
asignar  un  valor  ficticio  a  la  variable  NBLU  antes  del  bucle.  Además,  una  estructura  condicional  después  de  la 
iteración permite evitar una posible división por 0. 

Corrección n.°3 

Inicio 

Co Declaraciones Fco 
Real NBLU, CPT, SUMA, MEDIA 

Co Inicializaciones Fco 
CPT <­ 0 
SUMA <­ 0 

Co primera entrada de datos Fco 
Escribir("Número (0 para terminar): ") 
NBLU <­ Leer 

Co Bucle de lectura Fco 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Mientras NBLU <> 0 Hacer 

CPT <­ CPT +1 
SUMA <­ SUMA + NBLU 
Escribir("Número (0 para terminar): ") 
NBLU <­ Leer 

Volverhacer 

Co Visualización del resultado Fco 
Si CPT=0 
Entonces 

Escribir("No se ha introducido ninguna cifra") 

En caso contrario 

MEDIA <­ SUMA / CPT 
Escribir("Media de los ", CPT, "números = ", MEDIA) 

Finsi 

Fin 

En esta corrección, se ha mantenido un bucle Mientras con una comprobación inicial de este. La particularidad es 
que  se  hace  una  primera  entrada  de  datos  por  el  teclado  (variable  NBLU)  antes  de  la  iteración,  lo  que  obliga  a 
continuación a prever la entrada de los números siguientes de la secuencia, al final de la iteración. El interés de esta 
solución es que el cero final no se tiene en cuenta en la variable CPT. 

5. Ejercicio n.°11: El común divisor más grande, por el método de las divisiones 
sucesivas

Enunciado  

Calcular el MCD de dos números enteros leídos por el teclado (método de la división) 

El desarrollo del cálculo es la siguiente: 

l Introducir los números A y B por el teclado 

l Calcular el RESTO de la división entera de A por B 

l Cuando este RESTO es nulo, B es el MCD buscado 

l Sustituir A por B 

l Sustituir B por este RESTO 

l Empezar de nuevo a nivel del cálculo del RESTO 

Aprovechamos  este  enunciado  para  destacar  que  los  bucles  Mientras  y  Hastaque  se  pueden  utilizar 
indistintamente en la resolución de los problemas iterativos; basta con invertir lógicamente la condición verificada. 
Es necesario observar que el bucle Mientras es sistemáticamente implementado en los lenguajes de programación 
(en general llamado While o Do While). El bucle Hastaque (que se traduciría por un Until o Do Until) no es, 
por el contrario, sistemáticamente implementado. 

Corrección n.°1 

Inicio 

Co Declaraciones Fco 
Ent A, B, RESTO 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


Co Introducción de los dos números Fco 
Escribir("Primer número: ") 
A <­ Leer 
Escribir("Segundo número: ") 
B <­ Leer 

Co Bucle de procesamiento Fco 
RESTO <­ A Mod B 
Mientras RESTO <> 0 Hacer 

A <­ B 
B <­ RESTO 
RESTO <­ A Mod B 

Volverhacer 

Co Fin de procesamiento Fco 
Escribir("MCD = ", B) 

Fin 

Corrección n.°2 

Inicio 

Co Declaraciones Fco 
Ent A, B, RESTO 

Co Introducción de los dos números Fco 
Escribir("Primer número: ") 
A <­ Leer 
Escribir("Segundo número: ") 
B <­ Leer 

Co Bucle de procesamiento Fco 
RESTO <­ A Mod B 
Hastaque RESTO = 0 Hacer 

A <­ B 
B <­ RESTO 
RESTO <­ A Mod B 

Volverhacer 

Co Fin de procesamiento Fco 
Escribir("MCD = ", B) 

Fin 

6. Estructura iterativa Para

Las  estructuras  iterativas  Hastaque Hacer  … Volverhacer  y Mientras  Hacer … Volverhacer  se  pueden  sustituir 
por la estructura iterativa Para Hacer … Volverhacer cuando el número de iteraciones es conocido antes del inicio 
de la estructura y solo en este caso. 

Esta iteración, un poco confusa al inicio, tiene la particularidad de presentar un determinado automatismo respecto 
a la gestión del contador de iteraciones realizadas. 

Su sintaxis general es: 

Para VARIABLE De EXPRESION_INICIO A EXPRESION_FIN [No EXPRESION_NO] Hacer 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Acciones 

Volverhacer 

Veamos sus particularidades: 

l VARIABLE es una variable entera, que se debe declarar al inicio del algoritmo.  

l EXPRESION_INICIO es una constante entera (por ejemplo, 1) o una variable entera, que se debe declarar al inicio del 
algoritmo e inicializar antes de la estructura iterativa. 

l EXPRESION_FIN  es  una  constante  entera  (por  ejemplo,  10)  o  una  variable  entera,  que  se  debe  declarar  al  inicio  del 
algoritmo e inicializar antes de la estructura iterativa. 

l EXPRESION_NO  es  una  constante  entera  (por  ejemplo,  2)  o  una  variable  entera,  que  se  debe  declarar  al  inicio  del 
algoritmo e inicializar antes de la estructura iterativa. Lo más habitual es que No EXPRESION_NO no se prevea en este 
tipo de iteración. 

l EXPRESION_NO  puede  ser  negativo.  En  este  caso,  EXPRESION_INICIO  debe  ser  >  (o  eventualmente  = )  a 
EXPRESION_FIN. 

l La estructura  Para gestiona el incremento del contador del bucle (VARIABLE). Por tanto, no es conveniente intervenir 


sobre este contador en las Acciones, aunque no está prohibido. 

l En informática, un argumento opcional se representa como sigue: [argumento]. Cuando el argumento es obligatorio, 
los [] no se ponen. 

7. Ejercicio n.°12: Cálculo de la media de 10 números

Enunciado 

Calcular la media de 10 números que se introducirán por el teclado, con un bucle Para 

Corrección 

Inicio 

Co Cálculo de la media de 10 números que se introducirán por el teclado Fco 

Co Declaraciones Fco 
Ent CPT 
Real NBLU, SUMA, MEDIA 

Co Inicializaciones Fco 
SUMA <­ 0 

Co Iteración Fco 
Para CPT De 1 A 10 Hacer 

Escribir("Número n° ", CPT, ": ") 
NBLU <­ Leer 
SUMA <­ SUMA + NBLU 

Co NB: sobre todo, no hay que modificar el valor de la variable CPT en el bucle Fco 

Volverhacer 

Co Visualización del resultado Fco 
MEDIA <­ SUMA / 10 
Escribir("Media: ", MEDIA) 
Co NB: Es necesario evitar dividir aquí la SUMA por CPT Fco 
Co en la medida en que en determinados lenguajes Fco 
Co CPT valdrá 11 en salida Fco 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


Fin 

Como se indica en los comentarios en el algoritmo anterior, es mejor no utilizar directamente el valor de la variable 
CPT  (que  ha  servido  para  contar  los  números  que  se  introducen  por  el  teclado)  porque,  según  las  variantes  de 
implementación de los lenguajes de programación, CPT podría valer 10 u 11. 

8. Ejercicio n.°13: Deducir el número de vocales de una palabra

Enunciado 

Contar el número de vocales de una palabra introducida por el teclado 

Recordatorio:  se  utilizará  una  función  Longitud(CADENA)  para  determinar  el  número  de  caracteres  de  la  palabra 
introducida. La función Sub_cadena(CADENA, POSICION_INICIO, [POSICION_FIN]) también será necesaria. 

Corrección 

Inicio 

Co Declaraciones Fco 
Car PALABRA 
Ent NB_VOCALES, CONTADOR 

Co Introducción de la palabra por el teclado Fco 
Escribir("Palabra: ") 
PALABRA <­ Leer 

Co Poner en mayúsculas la palabra Fco 
PALABRA <­ Mayúsculas(PALABRA) 

Co Inicialización de las variables Fco 
NB_VOCALES <­ 0 

Co Determinación del número de vocales Fco 
Para CONTADOR De 1 ALongitud(PALABRA) Hacer 

Co Analizar la letra actual Fco 
Siguiente Sub_cadena (PALABRA, CONTADOR, CONTADOR) 

"A": NB_VOCALES <­ NB_VOCALES + 1 
"E": NB_VOCALES <­ NB_VOCALES + 1 
"I": NB_VOCALES <­ NB_VOCALES + 1 
"O": NB_VOCALES <­ NB_VOCALES + 1 
"U": NB_VOCALES <­ NB_VOCALES + 1 

Finsiguiente 

Volverhacer 

Co Visualización del resultado Fco 
Escribir(PALABRA, "contiene: ", NB_VOCALES, " vocal(es)") 

Fin 

Por  la  primera  vez,  vemos  una  estructura  condicional  (Siguiente  ...  Finsiguiente)  integrada  en  una  estructura 
iterativa (Para). Evidentemente, esta estructura condicional habría podido estar basada en un Si ... Finsi. 

En función de la problemática que se ha de resolver, habrá comprobado que es necesario combinar lo mejor posible 
las  estructuras  condicionales  (Si  ...  Finsi  o  Siguiente  ...  Finsiguiente)  con  las  diferentes  variantes  de  bucles 
(Mientras, Hastaque y Para) anidándolas, utilizándolas secuencialmente, etc. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-
Tabla de dimensión única

Una  tabla  agrupa  varios  valores  del  mismo  tipo.  Globalmente,  podemos  nombrar  todos  los  valores  o  designar  de 
manera precisa uno de ellos con una operación de scripting. 

Por ejemplo, consideremos ALFABETO como el conjunto de letras del alfabeto. En este caso: 

l ALFABETO designa una tabla que podrá servir para almacenar el conjunto de letras del alfabeto. 

l ALFABETO(14) podría representar la letra "N". 

l El entero 14 se llama índice. 

En un algoritmo, como sucede con las variables (simples) vistas hasta ahora, las tablas se deben declarar antes de 
poder utilizarlas. La sintaxis de declaración es: 

Tipo IDENTIFICADOR(INF: SUP) 

Observe que a nivel de esta declaración: 

l IDENTIFICADOR  es  el  nombre  global  de  la  tabla  (nombre  libremente  elegido  por  el  programador,  en  mayúsculas  si 
es posible). 

l Tipo indica el tipo de los elementos de la tabla, y todos los elementos de la tabla tienen el mismo tipo  (Entero, 
Real, Bool, Carácter). 

l INF y SUP son, respectivamente, los extremos inferior y superior del intervalo de variación del índice de la tabla. Una 
tabla como esta tiene N elementos, donde N = SUP ­ INF + 1. 

l INF  y  SUP  son  constantes  definidas  con  antelación  (sin  dimensionamiento  "dinámico",  aunque  determinados 
lenguajes de programación lo permiten). 

l En determinados lenguajes de programación, el valor INF no se puede expresar. En este caso, el valor INF se considera 
implícitamente como 1 (algunas veces también 0). Cuando es posible, es mejor evitar el uso del índice con valor cero. 

La tabla ALFABETO mencionada anteriormente se podría declarar como sigue: 

Car ALFABETO(1:26) 
Car ALFABETO(0:25) ­­­> es un poco particular pero también muy usual. 

Veamos  ahora  cómo  utilizar  este  tipo  de  tabla  (asignación  de  valores  a  las  diferentes  "celdas"  y  lectura  de  estos 
valores a continuación). La sintaxis es intuitiva: 

IDENTIFICADOR(ÍNDICE) 

Observe a nivel del uso de las tablas: 

l IDENTIFICADOR es el nombre de la tabla. 

l ÍNDICE es una expresión entera, cuyo valor debe pertenecer al intervalo (INF: SUP). 

l La notación IDENTIFICADOR(ÍNDICE) designa a un elemento de la tabla, identificado por su índice en la tabla. 

1. Ejercicio n.°14: Contar los números pares en una tabla

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Enunciado 

Determinación de la cantidad de números pares en una tabla (entrada de datos inicial a través del teclado). 

Corrección 

Inicio 

Co Determinación de la cantidad de números pares en una tabla Fco 

Co Declaraciones Fco 
Ent TB(1: 10) 
Ent NB_PARES 
Ent IND  

Co Inicializaciones Fco 
NB_PARES <­ 0 

Co Carga de la tabla Fco 
Para IND De 1 A 10 Hacer 

Escribir("TB(", IND, "): ") 
TB(IND) <­ Leer 

Volverhacer 

Co Determinación de la cantidad de números pares Fco 
Para IND De 1 A 10 Hacer 

Si TB(IND) Mod 2 = 0 Entonces 

NB_PARES <­ NB_PARES + 1 

Finsi 

Volverhacer 

Escribir("Cantidad de números pares de la tabla = ", NB_PARES) 

Fin 

En el procesamiento de las tablas, es preferible el bucle Para porque el conjunto de las celdas se utiliza a menudo o 
se analiza. 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Tabla con dimensiones múltiples

Cuando los elementos de una tabla son ellos mismos tablas, se habla de tabla de varias dimensiones. 

A  nivel  de  la  declaración  de  este  tipo  de  tabla,  hay  que  declarar  los  límites  del  índice  para  cada  una  de  las 
dimensiones, lo que no es ya una sorpresa: 

Tipo IDENTIFICADOR(INF1: SUP1, ..., INFi: SUPi, ..., INFn: SUPn) 

Para acceder a las diferentes celdas de una tabla de varias dimensiones, hay que indicar un valor de índice para cada 
una de ellas. A modo de ejemplo, para una tabla de dos dimensiones (tabla de líneas divididas en columnas como una 
matriz 2D en Microsoft Excel), el primer índice normalmente designa el número de la línea y el segundo el número de 
la columna de la celda a la que se hace referencia. Por tanto, la sintaxis es: 

IDENTIFICADOR(ÍNDICE1, ..., ÍNDICEi, ..., ÍNDICEn) 

1. Ejercicio n.°15: Minihoja de cálculo

Enunciado 

Sea la tabla TB de dos dimensiones con cuatro líneas y cinco columnas. Realizar los siguientes procesamientos: 

l introducir  por  el  teclado  valores  en  las  tres  primeras  líneas  y  las  cuatro  primeras  columnas  (se  conserva  la  última 
línea y la última columna libres, para los totalizadores de líneas y columnas), 

l añadir las columnas de última línea y las líneas en última columna. 

Corrección 

Inicio 

Co Declaraciones de las variables Fco 
Ent TB(1: 4, 1: 5) 
Ent LÍNEA, COLUMNA 

Co Inicialización de la tabla TB con ceros Fco 
Para LÍNEA De 1 A 4 Hacer 

Para COLUMNA De 1 A 5 Hacer 

TB(LÍNEA, COLUMNA) <­ 0 

Volverhacer 

Volverhacer 

Co Inicialización de la tabla TB con los valores leídos Fco 
Para LÍNEA De 1 A 3 Hacer 

Para COLUMNA De 1 A 4 Hacer 

Escribir("TB(", LÍNEA, ",", COLUMNA, ")=") 
TB(LÍNEA, COLUMNA) <­ Leer 

Volverhacer 

Volverhacer 

Co Añadir en columna 5 y línea 4 Fco 
Para LÍNEA De 1 A 3 Hacer 

Para COLUMNA De 1 A 4 Hacer 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


TB(LÍNEA, 5) <­ TB(LÍNEA, 5) + TB(LÍNEA, COLUMNA)  
TB(4, COLUMNA) <­ TB(4, COLUMNA) + TB(LÍNEA, COLUMNA) 

Volverhacer 

Volverhacer 

Fin 

La inicialización de las celdas de la tabla a cero al inicio del procesamiento puede ser útil en determinados lenguajes 
de  programación  porque  los  valores  iniciales,  de  la  línea  4  y  de  la  columna  5  en  nuestro  ejemplo,  pueden  ser  no 
nulos. 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Procedimientos, funciones y paso de argumentos

1. Los objetivos

Estos nuevos mecanismos permiten al programador tratar un problema sin preocuparse, inicialmente, de las reglas 
detalladas de los subproblemas. Se trata de herramientas muy similares a las funciones matemáticas. 

En  programación,  un  procedimiento  o  una  función,  representa  un  algoritmo  que  opera  con  argumentos  o 
argumentos formales (valores ficticios de alguna manera). La ejecución de este algoritmo se genera con la llamada 
del procedimiento o de la función. Los datos de este algoritmo llamado son los argumentos efectivos (que provienen 
del algoritmo que llama). 

El  interés  metodológico  de  estos  mecanismos  en  una  primera  etapa  consiste  principalmente  en  convertir  los 
subproblemas  en  procedimientos  (o  en  funciones)  y  tratar  el  problema  general  (o  principal)  como  si  estos 
subproblemas estuvieran solucionados. En una segunda etapa, se describen estos procedimientos o funciones. Otro 
interés  consiste  en  el  hecho  de  que,  si  el  mismo  subproblema  se  debe  resolver  varias  veces  con  argumentos 
efectivos diferentes, el uso de un procedimiento o función permite una mejor legibilidad del algoritmo. 

2. Los procedimientos

Comencemos el estudio de este mecanismo con la sintaxis de la declaración: 

Procedimiento NOMBRE_PROCEDIMIENTO([Tipo1 IDFO1, ..., Tipoi IDFOi])  

Cuerpo del procedimiento 

Fin_procedimiento 

En esta declaración: 

l NOMBRE_PROCEDIMIENTO es un nombre elegido libremente por el programador. 

l IDFOi es el nombre del enésimo argumento formal del procedimiento. 

l Tipoi es el tipo del enésimo argumento formal del procedimiento. 

l El procedimiento no devuelve valores a menos que intervenga sobre las variables (accesibilidad) globales. 

l Procedimiento y Fin_procedimiento son palabras reservadas. 

La llamada de un procedimiento desde otro o desde el algoritmo principal se hace respetando el siguiente esquema: 

NOMBRE_PROCEDIMIENTO(IDEF1, IDEFi, ..., IDEFn) 

con: 

l NOMBRE_PROCEDIMIENTO es un nombre elegido libremente por el programador, 

l IDEFi es el nombre del enésimo argumento efectivo. 

3. Ejercicio n.°16: Llamada de un procedimiento con paso de argumentos

Enunciado 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Llamar a un procedimiento que muestra el doble de los valores efectivos pasados como argumento (los dos valores 
pasados como argumento se introducen por el teclado). 

Corrección 

Inicio 

Co Uso de un procedimiento que muestra el doble de una pareja de valores Fco 

Co Procedimiento DOBLE Fco 
Procedimiento DOBLE(Ent X, Ent Y) 

X <­ X * 2 
Y <­ Y * 2 
Escribir("El VALOR DOBLADO es (", X, ",", Y, ")") 

Fin_procedimiento 

Co Procesamiento que llama Fco 
Ent A, B, C, D 
Escribir("Programa que dobla los valores de una dupla") 
Escribir("Valor 1 de la primera dupla: ") 
A <­ Leer 
Escribir("Valor 2 de la primer dupla: ") 
B <­ Leer 
DOBLE(A, B) 
Escribir("Valor 1 de la segunda dupla: ") 
C <­ Leer 

Escribir("Valor 2 de la segunda dupla: ") 
D <­ Leer 
DOBLE(C, D) 

Fin 

En la corrección que se presenta, en realidad se introducirán dos duplas de números por el teclado (A y B y después 
C y D), para mostrar la reutilización del procedimiento DOBLE. 

Las variables A y B (después C y D) son cualificadas con argumentos efectivos. Durante la llamada del procedimiento 
DOBLE, al argumento efectivo A se le asigna el argumento formal X, y al argumento efectivo B, el argumento formal 
Y. Después, el procedimiento DOBLE realiza un doblado de los valores que se pasan como argumentos y muestra los 
resultados.  Es  necesario  observar  que  no  hay  retorno  de  valores  con  destino  el  procedimiento  que  llama.  Los 
valores  A  y  B  conservarán  sus  valores  iniciales.  No  es  posible  tampoco  que  el  procedimiento  DOBLE  actúe 
directamente sobre las variables A y B (e incluso C y D). 

En un paso de argumentos entre un procedimiento que llama (o un algoritmo principal) y un procedimiento llamado, 
hay que considerar algunas reglas: 

l Los argumentos efectivos (si hay varios) se deben separar por comas a nivel de la llamada. 

l El  argumento  o  los  argumentos  formales  se  deben  declarar  dentro  de  los  paréntesis  que  siguen  al  nombre  de  la 
función (o del procedimiento) llamado. 

l Los argumentos formales (si hay varios) se deben separar por comas. 

l Cada argumento efectivo corresponde a un argumento formal y los dos deben ser del mismo tipo. 

Es posible pasar valores de tipos diferentes entre un procedimiento y otro (o una función). 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


4. Las funciones

La  diferencia  esencial  entre  los  procedimientos  vistos  anteriormente  y  las  funciones  es  que,  en  el  caso  de  las 
funciones, se envía un valor de vuelta al procedimiento que llama (o al algoritmo principal). 

La sintaxis de la declaración es muy parecida a la de un procedimiento: 

Función NOMBRE_FUNCIÓN([Tipo1 IDFO1, ..., Tipoi IDFOi]) Tipo_resultado 

Cuerpo de la función (conteniendo Devolver expresión) 

Fin_función 

En esta declaración:  

l La llamada a la función proporciona un valor del tipo Tipo_resultado indicado (Entero, Real, Bool, Carácter). 

l NOMBRE_FUNCIÓN es un nombre elegido libremente por el programador. 

l IDFOi es el nombre del enésimo argumento formal de la función. 

l Tipoi es el tipo del enésimo argumento formal de la función. 

l La función debe devolver una expresión (de tipo Tipo_resultado) en formato Devolver expresión. 

l Función, Resultado, Devolver y Fin_función son palabras reservadas. 

La llamada a una función desde otro procedimiento o desde el algoritmo principal se hace respetando el siguiente 
esquema:  

RESULTADO = NOMBRE_FUNCIÓN (IDEF1, IDEFi, ..., IDEFn) 

con: 

l NOMBRE_FUNCIÓN es un nombre elegido libremente por el programador, 

l IDEFi es el nombre del enésimo argumento efectivo, 

l RESULTADO es el nombre de la variable que recupera la respuesta proporcionada por la función. 

5. Ejercicio n.°17: Llamada de una función con paso de argumentos

Enunciado 

Uso de una función de cálculo del máximo de dos valores introducidos por el teclado y pasados como argumentos 

Corrección 

Inicio 

Co  Uso  de  una  función  de  cálculo  del  máximo  de  dos  valores  introducidos  por  el  teclado  y  pasados  como 
argumentos Fco 
Co Función de cálculo del máximo Fco 
Función MAXI(Ent X, Ent Y) Ent 

Si X > Y 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Entonces 

Devolver X 

En caso contrario 

Devolver Y 

Finsi 

Fin_función 

Co Procesamiento que llama Fco 
Ent A, B, C, D, E 
Escribir("Cálculo del máximo de 2 números") 
Escribir("Valor 1: ") 
A <­ Leer 
Escribir("Valor 2: ") 
B <­ Leer 
Escribir("El + grande es ", MAXI(A, B)) 
Escribir("Valor 3: ") 
C <­ Leer 
Escribir("Valor 4: ") 
D <­ Leer 
E <­ MAXI(C, D) 
Escribir("El + grande es ", E) 

Fin 

En esta corrección, una misma función MAXI se llama dos veces con argumentos efectivos diferentes (A y B, después 
C y D). 

Las  reglas  de  paso  de  argumentos  entre  un  procedimiento  que  llama  (o  un  algoritmo  principal)  y  una  función 
llamada son idénticas a las vistas anteriormente en el marco de una llamada de procedimiento. 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Metodología de aprendizaje

En  los  capítulos  siguientes,  se  propone  un  aprendizaje  progresivo  del  lenguaje  JavaScript,  con  un  enfoque 
pedagógico.  En  ningún  momento  se  tratará  de  ser  exhaustivo.  Por  el  contrario,  se  intentará  conseguir  que  usted 
descubra paso a paso JavaScript, retomando en particular los algoritmos desarrollados en los capítulos anteriores. 

Hubiera sido posible, para cada uno de los algoritmos que se han estudiado, proporcionar inmediatamente el código 
JavaScript. La elección que se ha tomado es presentar el algoritmo y el código JavaScript en capítulos diferentes del 
libro. Este enfoque ofrece una ventaja sustancial, ya que sensibiliza al lector respecto a la importancia del análisis de 
un problema, centrando el esfuerzo en conseguir un algoritmo de calidad, claro, fácil de interpretar y fiable, antes de 
traducir este algoritmo a un lenguaje de programación, sea el que sea. 

Después  de  la  presentación  del  lenguaje  JavaScript  (hasta  el  capítulo  Procedimientos  y  funciones),  se  estudia  el 
enfoque  llamado  "Programación  orientada  a  objetos"  de  JavaScript  (en  el  capítulo  Enfoque  orientado  a  objetos  en 
JavaScript)  y  después  veremos  los  principales  objetos  "nativos"  (que  no  tendrá  que  desarrollar  usted  mismo),  así 
como las propiedades y métodos asociados (capítulo Principales objetos en JavaScript). 

El libro termina con capítulos más técnicos, enumerados en la tabla de contenidos, fundamentalmente el estudio de 
los formularios, del modelo DOM (Document Object Model), la persistencia de datos, la geolocalización, el diseño, los 
gráficos de gestión, la generación de documentos PDF y los códigos QR. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Variables (declaración y tipado)

Para facilitar la localización de los ejercicios de JavaScript, se conservará la numeración que se ha visto en el capítulo 
Desarrollo a partir de algoritmos. 

1. Ejercicio n.°2: Superficies de círculos

Para empezar suavemente nuestro aprendizaje, retomemos el algoritmo del ejercicio n.°2 (Superficies de círculos), 
que  hemos  visto  en  el  capítulo  Desarrollo a  partir  de  algoritmos.  Excepcionalmente,  para  este  primer  ejercicio,  se 
recordará el algoritmo. 

Enunciado 

Calcular (y mostrar en pantalla) la superficie de dos círculos de radios predeterminados (5,5 metros y 3,5 metros, 
por ejemplo), así como la diferencia entre estas dos superficies 

Corrección en lenguaje descriptivo de algoritmia 

Inicio 

Real RADIO1, RADIO2, PI, SUPERFICIE1, SUPERFICIE2, DIFERENCIA  
RADIO1 <­ 5.5 
RADIO2 <­ 3.5 
PI <­ 3.14 
SUPERFICIE1 <­ PI * RADIO1 * RADIO1 
SUPERFICIE2 <­ PI * RADIO2 * RADIO2 
DIFERENCIA <­ SUPERFICIE1 ­ SUPERFICIE2 
Escribir("Superficie 1 = ", SUPERFICIE1,  Alineación, "Superficie 2 = ", SUPERFICIE2,  Alineación, "Diferencia 
= ", DIFERENCIA) 

Fin 

Corrección en JavaScript 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!--
NOMBRE DEL SCRIPT: Cap3_2.htm
REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Calcular (y mostrar) la superficie de dos círculos de radios
predeterminados (5,5 metros y 3,5 metros, por ejemplo)
y las diferencias entre sus dos superficies
-->

<!-- Inicio script HTML -->


<html>
<!-- Inicio encabezado script HTML -->
<head>
<!-- Etiqueta meta -->
<meta http-equiv="Content-Type" contenido="text/html;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


charset=utf-8" />

<!-- Título del script HTML -->


<title>Cap3_2</title>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - Ejercicio Cap3_2</h1>

<!-- Inicio script JavaScript -->


<script>

/* Mostrar el numero del script */


alert("Ejercicio Cap3_2");

/* Declaración de variables locales */


var radio1, radio2, pi, superficie1, superficie2, diferencia;

/* Inicialización de las variables */


radio1 = 5.5;
radio2 = 3.5;
pi = 3.14;

/* Cálculos */
superficie1 = pi * radio1 * radio1;
superficie2 = pi * radio2 * radio2;
diferencia = superficie1 - superficie2;

/* Mostrar los resultados */


document.write("Superficie 1: " + superficie1 + "<br />");
document.write("Superficie 2: " + superficie2 + "<br />");
alert("Diferencia: " + diferencia);

</script>

<!-- Mostrar el código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=
’view-source:’ + window.location">
Código fuente
</a>
</center>

</body>

</html>

Comentarios del código JavaScript 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


En  el  script  HTML  que  se  ha  presentado,  el  código  JavaScript  se  ha  integrado  en  la  sección <body> ...
</body>.  Veremos  más  adelante  que  el  código  JavaScript  se  hubiera  podido  situar  en  otros  lugares  del  código 
HTML. En resumen, así es como se puede ubicar el código JavaScript en un desarrollo Web en HTML: 

l Caso  1:  dentro  de  las  etiquetas  <script> ... </script>  en  la  sección  <body> ... </body>  del 
documento HTML principal, como en el caso del script comentado. 

l Caso  2:  dentro  de  las  etiquetas  <script> ... </script>  en  la  sección  <head> ... </head>  del 
documento HTML principal. Este será el caso de las funciones personales que desarrollaremos más adelante. 

l Caso  3:  en  un  archivo  externo  (de  extensión  .js),  para  las  funciones  que  queremos  poder  llamar  desde  varios 
scripts Web. 

De momento, no insistimos en los casos 2 y 3. Estos modos de implementación del código JavaScript se verán desde 
el punto de vista sintáctico, más adelante en este libro. También se presentarán ejemplos. 

El código HTML DOCTYPE siguiente: 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

es  la  declaración  del  tipo  de  documento.  Sirve  para  indicar  al  navegador  el  tipo  de  código  HTML  en  el  que  está 
escrito el script (página) HTML; puede ser HTML­3.2, HTML­4, XHTML... 

En su formulación detallada, esta directiva tiene la siguiente estructura: 

<!DOCTYPE HTML PUBLIC "type_HTML" "address_DTD">

donde: 

l type_HTML es el identificador de la versión de HTML utilizada, 
l address_DTD  es  la  URL  de  un  Document  Type  Definition  (DTD),  es  decir,  de  un  documento  que  indica  las 
propiedades de cada elemento (etiquetas y atributos) para este tipo de código HTML. 

La secuencia HTML siguiente es un ejemplo típico de comentarios: 

<!-- NOMBRE DEL SCRIPT: Cap3_2.htm


REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Calcular (y mostrar) la superficie de dos círculos de
radios predeterminados (5,5 metros y 3,5 metros, por
ejemplo)y las diferencia entre sus dos superficies
-->

Recordemos  que  los  comentarios  son  explicaciones  integradas  en  el  script,  que  no  se  interpretarán  por  el 
navegador. Estas líneas son, en cambio, fundamentales para entender las diferentes secuencias de código HTML del 
script. En este caso, el objetivo del comentario es recordar el procesamiento que realiza el script. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Consideramos  que  el  lector  también  tiene  conocimientos  mínimos  en  HTML y  conoce  las  etiquetas 
<html>, 
</html>,  <head>, </head>,  <title>, </title>,  <body> y </body>. En caso necesario, se puede acceder 
a muchos recursos sobre el lenguaje HTML en Internet. 

Detengámonos en la etiqueta meta HTTP-equiv: 

<meta HTTP-equiv="Content-Type" content="text/html; charset=utf-8" />

La sintaxis general de esta etiqueta es: 

<meta HTTP-equiv="palabra clave aquí" content="valor clave" />

Esta etiqueta va a permitir: 

l indicar el encoding de la página Web a través de la palabra clave  Content-Type. Por ejemplo, para un encoding 
UTF-8: 

<meta HTTP-equiv="Content-Type" content="text/html; charset=UTF-8" />

l indicar  que  no  hay  que  guardar  la  página  en  la  caché  del  navegador  (la  página  no  se  guardará  en  los  archivos 
temporales del usuario), con la palabra clave pragma: 

<meta http-equiv="pragma" content="no-cache" />

l indicar que, pasada una fecha de expiración, la página ya no estará disponible, con la palabra clave expires: 

<meta HTTP-equiv="expires" content="Tue, 20 Aug 1996 14:25:27 GMT" />

l requerir  la  actualización  de  la  página  cada  n  segundos,  con  la  palabra  clave  refresh.  Por  ejemplo,  para  una 
actualización cada 15 segundos: 

<meta http-equiv="refresh" content="15" />

l dirigir al internauta a otra página después de n segundos, con la palabra clave refresh. Por ejemplo, se obtendrá 
una redirección a la página yahoo.es, después de la visualización del script actual, durante dos segundos: 

http-equiv="refresh" content="2;URL=http://www.yahoo.es/" />

Ahora  centramos  nuestra  atención  en  nuestro  código  JavaScript.  El  script  empieza  con  una  directiva  <script> 
(precedida de un comentario expresado en HTML): 

<!-- Inicio script JavaScript -->


<script>

El  comando  alert  (como  veremos  más  adelante,  se  trata  de  un  método)  muestra  un  mensaje  con  el  título  del 
ejercicio, en forma de ventana "pop up": 

alert("Ejercicio Cap3_2");

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La ventana se presenta como sigue, ejecutando el script: 

Sin duda, habrá observado que cada instrucción de JavaScript termina con un punto y coma. 

Después se declara un conjunto de variables. Estas variables corresponden, evidentemente, a las que se han visto 
en  el  algoritmo.  No  hay  razones  fundamentales  para  modificar  su  sintaxis.  El  resto  de  los  cambios  de 
mayúsculas/minúsculas  se  pueden  prever  para  respetar  una  normalización  de  nombres  de  variables,  métodos... 
(normalización camelCase, por ejemplo). 

var radio1, radio2, pi, superficie1, superficie2, diferencia;

Aquí, las declaraciones se hacen en una sola línea, con el prefijo var, que no es una declaración de tipo. A priori, en 
JavaScript  el  tipo  no  existe,  sino  que  las  variables  se  asocian  a  un  tipo  en  el  momento  en  que  se  les  asigna  un 
contenido. 

Para las inicializaciones, se usa el signo =. Para el primer radio, esto resulta: 

radio1 = 5.5;

El  signo  de  asignación  =   utilizado  aquí  no  se  debe  confundir  con  el  signo  ==,  que  servirá  para  realizar 
comparaciones en igualdad. 

Los cálculos no presentan dificultades particulares. Por ejemplo, para la primera superficie, el código es: 

superficie1 = pi * radio1 * radio1;

A  continuación,  para  terminar,  pasamos  a  la  visualización  del  resultado.  El  comando  document.write  permite 
mostrar  el  resultado  de  los  cálculos  en  la  ventana  del  navegador.  A  título  de  ejemplo,  para  la  primera  superficie, 
esto se hace: 

document.write("Superficie 1: " + superficie1 + "<br />");

document.write  es  una  sintaxis  orientada  a  objetos,  en  la  que  el  método  write  se  aplica  a  un  objeto 
document.  Volveremos  a  tratar  la  programación  orientada  a  objetos  (POO)  en  el  capítulo  Enfoque  orientado  a 
objetos en JavaScript. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


Los diferentes elementos que se van mostrar se separan unos de otros con un + y no hay restricciones de conversión 
de valores numéricos en cadenas de caracteres, como sí sucede a menudo en otros lenguajes de programación. 

La  cadena  <br/>  muestra  que  es  posible  integrar  etiquetas  HTML  en  una  visualización  de  JavaScript.  Aquí 
<br /> provoca un cambio de línea antes de la siguiente visualización. 

La  visualización  de  la  diferencia  entre  las  dos  superficies  queda  asegurada  con  el  método  alert,  que  ya 
conocemos: 

alert("Diferencia: " + diferencia);

Los elementos que muestra el método alert se organizan como con el método document.write. 

La sección escrita en JavaScript termina con </script>: 

</script>

La siguiente secuencia (no comentada en el detalle aquí) permitirá al usuario visualizar el código HTML/JavaScript de 
la página con un clic en un enlace de hipertexto: 
 

<!-- Visualización del código fuente -->


<br /><br /><br />
<center >
<a href="JavaScript:window.location=’view-source:’+window.location">
Código fuente
</a>
</center>

2. Ejercicio n.°3: Superficie y volumen de una esfera

Enunciado 

Calcular y mostrar la superficie y el volumen de una esfera cuyo radio se introduce por el teclado. 

La novedad respecto al ejercicio anterior (Ejercicio n.°2), es la entrada del radio por el teclado. 

Corrección en JavaScript 

La corrección se reproduce completamente (no será el caso en el resto de los ejemplos). 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!--
NOMBRE DEL SCRIPT: Cap3_3.htm

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Calcular (y mostrar) la superficie y el volumen de una esfera
cuyo radio se introduce por el teclado
-->

<!-- Inicio script HTML -->


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type" contenido="text/html;
charset=utf-8"/>
<!-- Título del script HTML -->

<title>Cap3_3</title>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - Ejercicio Cap3_3</h1>

<!-- Inicio script JavaScript -->


<script>

/* Mostrar el nombre del script */


alert("Ejercicio Cap3_3");

/* Declaración de variables locales */


var pi, radio, superficie, volumen;

/* Inicialización de las variables */


pi = 3.14;
radio = prompt("Radio de la esfera: ");

/* Cálculos */
superficie = 4 * pi * radio * radio;
volumen = superficie * radio / 3;

/* Mostrar los resultados */


document.write("Radio de la esfera: "
+ radio + "<br/>");
document.write("Superficie: " + superficie
+ "<br/>Volumen: " + volumen);

</script>

<!-- Mostrar el código fuente -->

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


<br /><br /><br />
<center>
<a href="JavaScript:window.location=
’view-source:’ + window.location">
Código fuente
</a>
</center>

</body>

</html>

Comentarios del código JavaScript 

A  nivel  de  inicializaciones,  la  variable  pi  toma  el  valor  3,14  (valor  aproximado)  y  la  variable  radio  se  inicializa 
introduciendo su valor por el teclado (método prompt). El único argumento de este método es una etiqueta. 

/* Inicialización de las variables */


pi = 3.14;
radio = prompt("Radio de la esfera:");

3. Ejercicio n.°4: Número de letras de una palabra

Enunciado 

Escribir un algoritmo que permita introducir por el teclado un nombre y mostrar el número de letras 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var nombre;

/* Introducción del nombre por el teclado */


nombre = prompt("Nombre:");

/* Visualización del resultado */


document.write("El nombre " + nombre +" contiene " + nombre.length
+" letra(s)");

Comentarios del código JavaScript 

Nos anticipamos al enfoque "Programación orientada a objetos" (POO) en JavaScript. La variable nombre es de tipo 
String.  En  este  tipo  de  objeto,  es  posible  utilizar  métodos  específicos  o  acceder  a  los  valores  de  propiedades 
como length (número de caracteres). 

El  valor  de  la  propiedad  length  aquí  se  muestra  directamente  con  la  llamada  al  método  document.write. 
También hubiera sido posible declarar una variable adicional en memoria, como  longitudNombre por ejemplo, y 
asignarle el valor de nombre.length, antes también de mostrar su valor con document.write. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


4. Ejercicio n.°5: Determinación de las iniciales

Enunciado  

Escribir  un  algoritmo  que  permita  la  extracción  de  las  iniciales  de  una  persona,  cuyo  apellido  y  nombre  se 
introducirán por el teclado (ejemplo: ÁS para Ángel Sánchez) 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var apellido, nombre, inicial_apellido, inicial_nombre;

/* Introducción del apellido */


apellido = prompt("Apellido:");

/* Introducción del nombre */


nombre = prompt("Nombre:");

/* Determinación de las iniciales */


/* NB: La numeración de las letras en una cadena empieza por 0 */
inicial_apellido = apellido.charAt(0);
inicial_nombre = nombre.substring(0, 1);

/* Visualización de las iniciales */


document.write("Las iniciales de " + nombre + " " + apellido + "
son " + inicial_nombre + inicial_ apellido);

Comentarios del código JavaScript 

Aunque  habíamos  utilizado  la  propiedad  length  en  el  ejemplo  anterior,  aquí  usamos  el  método  charAt  para 
determinar la inicial del apellido y el método substring para la inicial del nombre. 

El método  charAt, con el argumento  0, extrae el primer carácter de la variable  apellido, es decir, la inicial (en 


una cadena de caracteres, la numeración de los caracteres empieza por cero). 

El  método  substring  necesita  dos  argumentos:  el  primero  indica  la  posición  del  primer  carácter  que  se  debe 
extraer (0, como para el método  charAt) y el segundo el número de caracteres que hay que extraer ( 1 para una 
sola letra, es decir, la inicial). 

Por tanto, el método substring puede sustituir al método charAt en todos los casos. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Presentación de la sintaxis

La  estructura  condicional  en  JavaScript  es  muy  parecida  sintácticamente  a  la  que  se  ha  visto  con  anterioridad  en 
lenguaje descriptivo de algoritmia. 

Por supuesto, de manera clásica, el bloque de instrucciones que se ha de ejecutar en caso de que la condición sea 
verdadera queda delimitado por llaves ({}). También es posible prever una secuencia de instrucciones alternativa con 
la palabra clave else. Esta secuencia también se encerrará entre llaves. 

El lenguaje JavaScript es muy permisivo respecto a la ubicación de estas llaves. De esta manera, encontrará scripts 
con las siguientes construcciones: 

if (condición)
{
Acciones_1;
}
else
{
Acciones_2;
}

if (condición) {
Acciones_1;
}
else {
Acciones_2;
}

if (condición) { Acciones_1; } else { Acciones_2; }

donde: 

l condición representa una comparación que genera un resultado booleano true o false, 

l Acciones_1 y Acciones_2 representan secuencias de instrucciones (en general en varias líneas). 

Observe  que,  para  realizar  una  comprobación  de  comparación  de  igualdad,  el  operador  es  el  doble  igual  (==);  no 
confundir con el igual sencillo (=), que sirve para realizar comparaciones. 

En las comprobaciones de comparación con constantes, es mejor, por ejemplo: 

if (5 == contador)
{
Acciones_1;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


}
else
{
Acciones_2;
}

que 

if (contador == 5)
{
Acciones_1;
}
else
{
Acciones_2;
}

ya  que  confundir  = =   con  =   es  más  fácil  de  detectar  en  el  primer  caso,  porque  JavaScript  devuelve  un  error.  En  el 
segundo caso (si pone = en lugar de ==) la secuencia Acciones_1 se ejecutará siempre, porque la evaluación de 
contador = 5 siempre dará true (JavaScript estima que la asignación tiene éxito). 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Ejemplos

1. Ejercicio n.°6: Polinomio de segundo grado

Enunciado 

Calcular las raíces de un polinomio de segundo grado Ax2+Bx+C (con A<>0 en valor absoluto, aunque esta prueba 
no se realiza aquí). Los valores A, B y C se introducirán por el teclado 

Corrección (parcial) en JavaScript 

/* Introducción de los argumentos */


a = prompt("a:");
b = prompt("b:");
c = prompt("c:");

/* Cálculo del discriminante */


delta = (parseInt(b) * parseInt(b)) - (4 * parseInt(a) * parseInt(c));

/* Visualización de los argumentos */


document.write("a: " + a + "<br />");
document.write("b: " + b + "<br />");
document.write("c: " + c + "<br />");
document.write("Discriminante delta: " + delta + "<br />");

/* Determinación de las raíces */


if (delta < 0)
{
document.write("Sin soluciones");
}
else
{
if (delta == 0)
{
document.write("Solución única: " + (-b / (2 * a)));
}
else
{
document.write("Solución n.°1: " + (-b + Math.sqrt(delta)) /
(2 * a) + "<br />");
document.write("Solución n.°2: " + (-b - Math.sqrt(delta)) /
(2 * a));
}
}

Comentarios del código JavaScript 

Observe que ha sido necesario anidar dos estructuras condicionales para tratar el problema. Es posible no anidar 
las estructuras (equivalente a tres  Si ... Finsi sucesivos a nivel de algoritmia), pero esta solución no sería óptima. 
Observe también el sentido particular aportado a nivel de la alineación de las llaves y a nivel de la indentación de 
los bloques de instrucciones. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Para determinar la raíz cuadrada del discriminante (delta), ha sido necesario recurrir al método  sqrt, del objeto 
JavaScript  Math.  Tendremos  la  ocasión  de  revisar  este  objeto  más  adelante  en  este  libro.  El  cálculo  de  la  raíz 
cuadrada  también  se  hubiera  podido  realizar  elevando  delta  a  la  potencia  0,5.  La  operación  de  elevación  a  la 
potencia (exponenciación) se representa con ˆ. 

2. Ejercicio n.°8: Impresión de la etiqueta de un mes

Enunciado 

Imprimir en letras, el mes correspondiente a un número dado por el teclado (comprendido entre 1 y 12). El control 
de la entrada de datos no se realiza. 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var mes;

/* Introducción del número de mes */


Mes = parseInt(prompt("Número del mes (de 1 a 12):"));

/* Visualización del resultado */


switch (mes)
{
case 1:
document.write("Mes n.° " + mes +": Enero");
break;
case 2:
document.write("Mes n.° " + mes +": Febrero");
break;
case 3:
document.write("Mes n.° " + mes +": Marzo");
break;
case 4:
document.write("Mes n.° " + mes +": Abril");
break;
case 5:
document.write("Mes n.° " + mes +": Mayo");
break;
case 6:
document.write("Mes n.° " + mes +": Junio");
break;
case 7:
document.write("Mes n.° " + mes +": Julio");
break;
case 8:
document.write("Mes n.° " + mes +": Agosto");
break;
case 9:
document.write("Mes n.° " + mes +": Septiembre");
break;
case 10:
document.write("Mes n.° " + mes +": Octubre");
break;

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


case 11:
document.write("Mes n.° " + mes +": Noviembre");
break;
case 12:
document.write("Mes n.° " + mes +": Diciembre");
break;
default:
document.write("Error de entrada de datos en
el número de mes");
}

Comentarios del código JavaScript 

En lugar de anidar, como en el ejercicio anterior, las estructuras condicionales (algo que resulta pesado de escribir 
en nuestro caso), aquí se utiliza la estructura switch. 

Observe a nivel de la entrada de datos del número del mes en la variable ’mes’ (no tipado a nivel de su declaración) 
que  se  necesita  una  conversión  con  el  método  parseInt.  Una  vez  que  se  realiza  la  entrada  de  datos  y  la 
conversión, la variable mes será de tipo entero en el resto del procesamiento. 

La variable mes se comprueba con la estructura condicional  switch. En caso de que la variable mes valga 1, se 
visualiza "Enero" y así sucesivamente. 

En  caso  de  que  haya  una  entrada  de  datos  errónea  en  el  número  de  mes,  entonces  se  ejecuta  la  instrucción 
integrada en el caso default. 

Observemos también el papel primordial de la instrucción  break. En su ausencia al final de cada uno de los casos, 
tan  pronto  como  la  condición  se  verifica,  se  ejecuta  el  procesamiento  asociado,  pero  también  el  resto  de  los 
procesamientos  siguientes  (incluso  si  la  condición  no  se  respeta  para  estos  procesamientos).  Por  ejemplo,  la 
entrada  de  datos  del  valor  5  como  número  de  mes  generaría  la  visualización  de  Mayo,  Junio,  Julio,  ..., 
Diciembre. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Presentación de la sintaxis de los bucles

En el marco del capítulo Desarrollo a partir de algoritmos, hemos estudiado cinco tipos de bucles que permiten tratar 
todos los casos de procesamientos iterativos: 

l Bucle Hasta que, con una comprobación de la condición al inicio de la iteración. 

l Bucle Mientras que, con una comprobación de la condición al inicio de la iteración. 

l Bucle Hasta que, con una comprobación de la condición al final de la iteración. 

l Bucle Mientras que, con una comprobación de la condición al final de la iteración. 

l Bucle Para. 

Estas  estructuras  iterativas  no  se  implementan  en  todos  los  lenguajes  de  programación.  Por  ejemplo,  es  posible 
pasar del bucle Hasta que al bucle Mientras que, modificando la condición. 

Por el contrario, el bucle Para prácticamente siempre está presente en los lenguajes. Su particularidad es que solo se 
usa cuando el número de iteraciones es conocido al inicio del procesamiento. Siempre es posible recurrir a un bucle 
Mientras que (o Hasta que). 

En JavaScript, la elección de las estructuras iterativas se reduce a: 

l while: bucle Mientras que, con una comprobación de la condición al inicio de la iteración, 
l do ... while: bucle Mientras que, con una comprobación de la condición al final de la iteración, 
l for: bucle Para. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Bucle while

1. Sintaxis

El bucle while permite traducir una lógica de Mientras que, con una comprobación inicial de estructura. La sintaxis 
es la siguiente: 

while(condición)
{
secuencia de código
}

Con el bucle while se ejecuta una secuencia de código mientras la condición entre paréntesis sea verdadera. 

Por  supuesto,  con  esta  iteración  es  necesario  que  el  estado  de  la  condición  pueda  evolucionar  a  lo  largo  de  la 
secuencia del código integrado en las llaves. También es necesario estar muy atento al hecho de que la condición se 
pueda evaluar la primera vez que se pasa por ella. Se trata de un motivo de funcionamiento erróneo frecuente. Muy 
a menudo, la condición también se realiza sobre el estado de una variable de tipo contador. Por supuesto, para que 
el  contador  pueda  alcanzar  un  valor  límite,  hay  que  modificarlo  durante  la  secuencia  de  código  (incremento  o 
decremento). 

Para terminar, observe en los scripts de este libro y en muchos de los ejemplos disponibles en Internet la siguiente 
sintaxis alternativa (que ya habíamos mencionado para la estructura condicional if): 

while(condición) {
secuencia de código
}

2. Ejercicio n.°9: Media de 10 números  que se introducirán por el teclado

Enunciado 

Calcular y mostrar la media de 10 números leídos por el teclado 

Siendo  rigurosos,  este  ejercicio  se  podría  realizar  con  un  bucle  Para  porque  el  número  de  iteraciones  (10)  es 
conocido al inicio del procesamiento. 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var nblu, cnt, suma, media;

/* Inicializaciones */
cnt = 1;
suma = 0.0;

/* Bucle de procesamiento */
while (cnt<=10)

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


{
nblu = parseFloat(prompt("Número n° " + cnt + ": "));
suma = suma + parseFloat(nblu);
cnt = cnt + 1;
}

/* Visualización del resultado */


media = suma / 10;
document.write("Media: "+ media);

Comentarios del código JavaScript 

El script no presenta dificultades particulares de interpretación. 

Conviene prestar atención a la implementación del bucle while en JavaScript. La media se divide por 10 al final del 
procesamiento.  Una  división  por  el  contador  del  bucle  cnt  habría  dado  un  resultado  no  satisfactorio  porque  la 
división se hubiera hecho por 11. 

No olvide realizar las conversiones en el bucle a tipo real para la variable  nblu (con el método parseFloat para 
los números reales) porque la variable nblu, aunque se haya declarado al inicio de script, no tiene tipo explícito. 

Puede que haya observado la presencia de un espacio entre la palabra clave  while y la condición; este espacio es 
opcional y permite aligerar la sintaxis. 

3. Ejercicio n.°10: Media de una serie de n números  que se introducirán por el teclado

Enunciado 

Calcular y mostrar la media de n números reales introducidos por el teclado (la lista termina con un cero). 

Aquí nos enfrentamos a un problema que no es posible solucionar con una estructura iterativa de tipo Para ( for en 
JavaScript). 

Veamos cómo realizar este cálculo con un while. 

Corrección (parcial) en JavaScript 

/* Inicializaciones */
cnt = 1;
suma = 0.0;

/* Introducción de un primer número */


nblu = parseFloat(prompt("Número (0 para terminar): "));

/* Bucle de procesamiento */
while (nblu != 0)
{
suma = suma + parseFloat(nblu);
nblu = parseFloat(prompt("Número (0 para terminar): "));
cnt = cnt + 1;
}

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Visualización del resultado */
if (cnt == 1)
{
document.write("No se ha introducido ningún número");
}
else
{
media = suma / (cnt-1);
document.write("Media: "+ media);
}

Comentarios del código JavaScript 

Para  que  la  condición  sea  evaluable  en  la  primera  pasada  de  nblu != 0,  es  necesario  haber  introducido  un 
número por el teclado antes del bucle  while. No hay que olvidar, en la secuencia de código integrado en el bucle, 
prever un segundo prompt para que sea posible la lectura de los siguientes números. 

En cuanto a visualización, hay que prever una comprobación para aislar el caso particular de una secuencia de cifras 
que solo contenga el "marcador de fin de lista 0". En este caso, sobre todo hay que evitar la división por cero. En 
realidad, en JavaScript, no hay error del navegador, sino que el valor que se muestra sería NaN (Not a Number). 

Algunas notas en relación con las condiciones: 

l Para  indicar  diferencia,  el  operador  es  !=   (en  lugar  de  <>,  que  hemos  visto  en  el  capítulo  Desarrollo  a  partir  de 
algoritmos). 

l Para  comparar  con  1  en  la  visualización  del  resultado,  hay  que  prever  un  doble  igual  (= = ).  El  signo  igual  (= )  en 
JavaScript se reserva a la asignación. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Bucle do while

1. Sintaxis

El bucle do while permite traducir una lógica de Mientras que, con una comprobación al final de la estructura. La 
sintaxis es la siguiente: 

do
{
secuencia de código
} while(condición)

Con el bucle do while, se ejecuta una secuencia de código mientras la condición entre paréntesis sea verdadera. 

Hay  una  diferencia  notable  respecto  al  bucle  while.  Aquí  la  secuencia  de  código  se  ejecuta  al  menos  una  vez, 
porque la comprobación de la condición se realiza al terminar la primera vuelta del bucle. 

2. Ejercicio n.°10: Media de una serie de n números  que se introducirán por el teclado

Enunciado 

Calcular y mostrar la media de n números reales introducidos por el teclado (la lista termina con un cero) 

Corrección (parcial) en JavaScript 

/* Inicializaciones */
cnt = 0;
suma = 0.0;

/* Bucle de procesamiento */
do
{
nblu = parseFloat(prompt("Número (0 para terminar): "));
cnt = cnt + 1;
suma = suma + parseFloat(nblu);
} while (nblu != 0)

/* Visualización del resultado */


if (cnt == 1)
{
document.write("No se ha introducido ningún número");
}
else
{
media = suma / (cnt-1);
document.write("Media: "+ media);
}

Comentarios del código JavaScript 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Aquí no ha sido necesario realizar una lectura antes del bucle porque la evaluación de la condición  nblu != 0 se 
hace en las condiciones correctas, ya que la comprobación se realiza al final de la iteración. 

Observe también que la inicialización del valor del contador cnt se hace con un cero. 

Para terminar, como sucedía anteriormente, se añade el cero final (pero esto no tiene implicaciones en una adición) 
y se contabiliza en la cantidad de números que forman parte de la lista. Por tanto, es necesario realizar una división 
por contador-1 a nivel del cálculo de la media. 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Bucle for

1. Sintaxis

Recordemos simplemente que este bucle solo se utiliza cuando el número de iteraciones que se van a realizar se 
conoce al inicio del procesamiento. 

La sintaxis es la siguiente: 

for (contador = valor inicial; valor final de contador;


incremento del contador)
{
secuencia de código
}

No insistimos en el funcionamiento de este tipo de bucle porque ya se visto ampliamente en el capítulo Desarrollo a 
partir de algoritmos. 

Evidentemente  la  gestión  de  la  progresión  del  contador  está  a  cargo  de  la  estructura  for.  Por  tanto,  no  es 
necesario  prever  un  valor  inicial  para  el  contador  antes  del  bucle  (solo  se  hace  la  declaración  del  contador).  El 
valor inicial, el valor final y el paso de incremento/decremento del contador se tienen en cuenta por el bucle. No 
hay que cambiar el valor del contador en la secuencia de código. 

2. Ejercicio n.°12: Media de una serie de 10 números   que se introducirán por el 


teclado

Enunciado 

Calcular la media de 10 números que se introducen por el teclado, con un bucle for. 

Este  ejercicio  ya  se  ha  realizado  con  antelación  con  un  bucle  while  (Ejercicio  n.°9).  Recordemos  que  siempre  es 
posible cambiar un bucle for por un bucle while (aunque no obligatoriamente a la inversa). 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var nblu, cnt, suma, media;

/* Inicializaciones */
suma = 0.0;

/* Bucle de procesamiento */
for (cnt=1; cnt<=10; cnt++)
{
nblu = parseFloat(prompt("Número n°" + cnt));
suma = suma + parseFloat(nblu);
}

/* Visualización del resultado */


media = suma / 10;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


document.write("Media: "+ media);

Comentarios del código JavaScript 

La declaración del contador  cnt se podría haber omitido. Sin embargo, es preferible hacerla explícitamente, como 
aquí (en determinados lenguajes de programación, este olvido generaría un error). 

Observe que, a nivel del cálculo de la media, se ha mantenido un enfoque prudente, la división de la suma por 10. 
Podría haberle tentado hacer una división por cnt, pensando que el bucle Para que termina con un valor de cnt de 
10. Este sería un grave error porque en JavaScript, en la salida de este bucle, el contador vale 11. 

3. Ejercicio n.°13: Contar el número de vocales  en una palabra

Enunciado 

Contar el número de vocales de una palabra introducida por el teclado 

En  el  capítulo  Desarrollo  a  partir  de  algoritmos  de  este  libro,  para  este  ejercicio  habíamos  introducido  la  función 
Longitud(CADENA),  para  determinar  el  número  de  caracteres  de  la  palabra  introducida  y  la  función  Sub_cadena
(CADENA,  POSICION_INICIO,  [POSICION_FIN]),  para  localizar  las  letras  sucesivas  en  la  palabra.  Van  a  ser 
necesarias funciones equivalentes en JavaScript.  

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var palabra, nb_vocales, contador;

/* Introducción de la palabra */
Palabra = prompt("Palabra:");

/* Conversión en mayúsculas (para evitar hacer 12 comprobaciones) */


Palabra = palabra.toUpperCase();

/* Inicialización de las variables */


nb_vocales = 0;

/* Determinación del número de vocales */


for (contador=0; contador<=palabra.length; contador++)
{
switch (palabra.charAt(contador))
{
case "A":
nb_vocales = nb_vocales + 1;
break;
case "E":
nb_vocales = nb_vocales + 1;
break;
case "I":
nb_vocales = nb_vocales + 1;
break;
case "O":
nb_vocales = nb_vocales + 1;

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


break;
case "U":
nb_vocales = nb_vocales + 1;
break;
}
}

/* Visualización del resultado */


document.write(palabra, " contiene " + nb_vocales + " vocales");

Comentarios del código JavaScript 

Ya  lo  habíamos  visto  en  la  versión  "algoritmia"  de  este  ejercicio;  es  mejor  convertir  a  mayúsculas  la  palabra 
introducida por el teclado (variable palabra) como sigue: 

/* Conversión en mayúsculas (para evitar hacer 12 comprobaciones) */


Palabra = palabra.toUpperCase();

No insistimos en la estructura for en sí misma porque ya domina su sintaxis desde el ejercicio anterior. 

Para evitar una batería de if anidados con objeto de evaluar si las letras sucesivas son vocales, se ha mantenido 
el  principio  del  uso  de  un  switch  (más  elegante).  Este  switch  tiene  como  condición  la  evaluación  del  valor 
devuelto por el método  palabra.charAt, que permite extraer las letras una por una. También habrá observado 
la particularidad ya mencionada de la numeración de las letras en una cadena a partir de cero. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Tablas de dimensión única

En el capítulo Desarrollo a partir de algoritmos, hemos visto de pasada el potencial de las tablas de dimensión única y 
de dimensiones múltiples. Veamos cómo se gestionan en JavaScript. 

1. Sintaxis

En JavaScript, una tabla de dimensión única es una variable en memoria "compuesta", en la que va a ser posible 
almacenar varios datos independientes, de tipos diferentes, con una indexación de cada uno de los valores con un 
número (o índice). 

Por tanto, el acceso a cada dato de la tabla se hará con este valor de índice. 

Una particularidad respecto a este índice es que su valor para la primera celda de la tabla es 0. 

El lenguaje JavaScript proporciona varias maneras de crear una tabla: 

l la sintaxis literal, 

l la sintaxis llamada "Programación orientada a objetos". 

Con  una  sintaxis  literal,  la  declaración  de  una  tabla  de  nombre  tabSemana  de  siete  celdas,  que  contiene  las 
etiquetas de los días de una semana, se hace como sigue: 

var tabSemana = ["Lunes", "Martes", "Miércoles", "Jueves",


"Viernes", "Sábado", "Domingo"];

Observe que la declaración está acompañada de la inicialización de cada una de las celdas de la tabla tabSemana 
(de la celda de índice 0 a la celda de índice 6). 

Con una sintaxis de "Programación orientada a objetos", tendríamos: 

var tabSemana = new Array("Lunes", "Martes", "Miércoles", "Jueves",


"Viernes", "Sábado", "Domingo");

Hubiéramos  podido  declarar  la  tabla  tabSemana  sin  asignarle  valores.  Se  puede  considerar  asignaciones 
posteriores, como por ejemplo para el Lunes: 

tabSemana[0] = "Lunes";

Lo que es verdaderamente particular en la gestión de las tablas en JavaScript es la extrema flexibilidad: 

l sin dimensionamiento a priori (siempre es posible extender el tamaño de la tabla en función de las necesidades), 

l posibilidad de mezclar en una misma tabla datos de tipos diferentes, 

l posibilidad de utilizar tablas asociativas (tablas cuyos índices se sustituyen por valores textuales). 

En un procesamiento, para acceder al contenido de un valor de tabla asociado a una posición de índice particular, la 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


sintaxis será: 

document.write("El cuarto día de la semana es " + tabSemana[3]);

Es necesario recordar siempre que la numeración de los índices empieza en cero. 

Para terminar, debe saber que JavaScript ofrece muchos métodos que se aplican en las tablas ( Array). Con estos 
métodos  puede  fácilmente  insertar,  eliminar  y  encontrar  elementos  en  una  tabla.  También  existen  métodos  de 
ordenación (sort,  reverse) para clasificar fácilmente los valores contenidos en una tabla, sin tener que recurrir a 
la pesada escritura de un algoritmo de ordenación. 

2. Ejercicio n.°14: Contar los números pares en una tabla

Enunciado 

Determinar la cantidad de números pares en una tabla (entrada de datos inicial de valores por el teclado). 

Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


/*
i : Contador de bucle
nbPares : Acumulado de la cantidad de números pares
tabla : Tabla de números
*/
var i, nb_pares;
var tabla = new Array;

/* Inicializaciones */
nbPares = 0;
for (i=1; i<=5; i++)
{
tabla[i] = parseInt(prompt("tabla[" + i +"]: "));
}

/* Determinar la cantidad de números pares en la tabla */


for (i=1; i<=5; i++)
{
if (tabla[i]%2 == 0)
{
nbPares = nbPares + 1;
}
}

/* Visualización del resultado */


document.write("La tabla contiene " + nbPares + " números pares");

Comentarios del código JavaScript 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


No hay nada realmente nuevo en este script, excepto el cálculo del módulo. Este cálculo sirve aquí para determinar 
la paridad de cada contenido de celdas de la tabla. Se hace con el operador %. 

Puede que haya observado que, en este script, la celda con índice 0 no se ha utilizado (la numeración del bucle for 
empieza en 1). Esta elección hace más comprensible el algoritmo. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Tablas de dimensiones múltiples

Es frecuente que necesitemos una tabla de dimensiones múltiples para gestionar problemas, fundamentalmente en 
matemáticas, estadística... 

JavaScript ofrece esta posibilidad. 

1. Sintaxis

Como para las tablas de dimensión única, JavaScript permite declarar las tablas de dimensiones múltiples de varias 
maneras: 

l con una sintaxis literal, 

l con una sintaxis llamada "Programación orientada a objetos". 

Con una sintaxis llamada "Programación orientada a objetos" (incluso llamada JSON ­ JavaScript Object Notation), la 
declaración de una tabla de nombre  tabMatriz de dos líneas, divididas en cuatro columnas con inicialización, se 
hace como sigue: 

/* Declaración de la tabla tabMatriz */


var tabMatriz tabla = new Array();

/* Declaración de la primera "línea" de la tabla tabMatriz */


tabMatriz[0]=new Array()

/* Inicialización de las 4 "columnas" de la primera "línea" */


tabMatriz[0][0] = "Uno";
tabMatriz[0][1] = "Dos";
tabMatriz[0][2] = "Tres";
tabMatriz[0][3] = "Cuatro";

/* Declaración de la segunda "línea" de la tabla tabMatriz */


tabMatriz[1]=new Array()

/* Inicialización de las 4 "columnas" de la segunda "línea" */


tabMatriz[1][0] = "Once";
tabMatriz[1][1] = "Doce";
tabMatriz[1][2] = "Trece";
tabMatriz[1][3] = "Catorce";

2. Ejercicio n.°15: Minihoja de cálculo

Enunciado 

Sea la tabla tb de dos dimensiones, con cuatro líneas y cinco columnas. Realizar los procesamientos siguientes: 

l introducir por teclado valores en las tres primeras líneas y las cuatro primeras columnas (se conservan la última línea 
y la última columna libres para los totalizadores de líneas y columnas), 

l añadir columnas en la última línea y líneas en la última columna. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Corrección (parcial) en JavaScript 

/* Declaración de variables locales */


var tb = new Array(5);
var numLinea, numColumna;
var valor;

/* Declaración de 5 "columnas" por "línea" para la tabla tb */


for (var numLinea=1; numLinea<tb.length; numLinea++)
{
/* Creación de las "columnas" (numeradas de 0 a 5) */
tb[numLinea]=new Array(6);
}

/* Inicialización de la tabla tb */
valor = 1;
for (numLinea=1; numLinea<=3; numLinea++)
{
for (numColumna=1; numColumna<=4; numColumna++)
{
tb[numLinea][numColumna] = valor;
valor = valor + 1;
}
}

/* Puesta a cero de los totales en línea n.°4 */


for (numColumna=1; numColumna<=5; numColumna++)
{
tb[4][numColumna] = 0;
}

/* Puesta a cero de los totales en columna n.°5 */


for (numLinea=1; numLinea<=4; numLinea++)
{
tb[numLinea][5] = 0;
}

/* Determinación de los totales en línea n.°4 y en columna n.°5 */


for (numLinea=1; numLinea<=3; numLinea++)
{
for (numColumna=1; numColumna<=4; numColumna++)
{
/* Totalización en línea n.°4 */
tb[4][numColumna] = tb[4][numColumna]
+ tb[numLinea][numColumna];
/* Totalización en columna n.°5 */
tb[numLinea][5] = tb[numLinea][5]
+ tb[numLinea][numColumna];
/* Totalización general en línea n.°4-columna n.°5 */
tb[4][5] = tb[4][5] + tb[numLinea][numColumna];
}
}

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Visualización del total general */
/* NB: Total de 78 suponiendo que se mantiene la técnica de llenado
de la tabla tb */
document.write("Total general en tb[4][5] = " + tb[4][5]);

Comentarios del código JavaScript 

En  primer  lugar,  la  tabla  tb  se  declara  como  una  tabla  de  una  sola  dimensión,  con  cinco  celdas,  implícitamente 
numeradas de 0 a 4, como sigue: 

var tb = new Array(5);

Observe que la línea de número cero no se utilizará en adelante. Esta elección se ha hecho porque el uso posterior 
de esta línea no sería muy intuitiva. 

Luego, las líneas de esta tabla se dividen en columnas, como se ve a continuación: 

/* Declaración de 5 "columnas" por "línea" para la tabla tb */


for (var numLinea=1; numLinea<tb.length; numLinea++)
{
/* Creación de "columnas" (numeradas de 0 a 5) */
tb[numLinea]=new Array(6);
}

De hecho, se declaran seis columnas (numeradas de 0 a 5) y la columna número cero se ignora. 

La  inicialización  de  las  "celdas"  de  la  tabla  tb  (únicamente  las  líneas  1  a  3  y  las  columnas  1  a  4)  se  hace  con  la 
siguiente notación: 

tb[numLinea][numColumna] = valor;

El valor asignado es 1, en progresión a partir de 1 (por tanto, de 1 a 12). La entrada de datos se hubiera podido 
realizar a partir de una entrada de datos por teclado. 

Los  procesamientos  siguientes  (puesta  a  cero  de  la  línea  n.°4  y  de  la  columna  n.°5),  no  merecen  comentarios 
particulares. 

Los totales en la línea n.°4, en la columna n.°5 y en la celda [4][5] también se hacen con un conjunto de bucles for 
anidados. La tabla general es naturalmente de 78, dando por hecho que la técnica de llenado de la hoja de cálculo 
se mantiene. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Los procedimientos

Recordemos  brevemente  el  interés  de  los  procedimientos  en  programación  (puede  volver  al  capítulo  Desarrollo  a 
partir  de  algoritmos,  para  más  explicaciones).  Querer  codificar  en  JavaScript  procesamientos  demasiado  complejos, 
utilizando  un  número  importante  de  variables  y  objetos  e  implicando,  por  ejemplo,  a  bucles  y  estructuras 
condicionales anidadas, puede ser un freno importante para el mantenimiento del script. Esto es incluso más cierto 
cuando  el  código  está  mal  organizado  (ausencia  de  comentarios,  indentaciones  aleatorias,  nombres  de  variables  y 
objetos poco significativos, etc.). 

Otro  aspecto  importante  para  codificar  con  procedimientos  es  la  posible  reutilización  de  estos  procedimientos  en 
contextos diferentes. Será posible pasar argumentos a estos procedimientos. Si estas secuencias de código llamadas 
desde un procesamiento principal devuelven un valor, hablamos en este caso de funciones. Esta factorización reduce 
la  longitud  global  del  código  fuente  y  permite,  sobre  todo,  aislar  (e  incluir  en  un  script  físicamente  diferente)  una 
secuencia de instrucciones, para la que no tendremos más preguntas que hacer respecto a su funcionamiento. Por 
tanto, estos procedimientos (o funciones) se podrán considerar como piezas de software utilizables en la construcción 
de una arquitectura de software. 

1. Sintaxis

function miProcedimiento(argumentoFormal1[, argumentoFormal2, ...)


{
/* Secuencia de código sin valor devuelto al procesamiento que llama */
}

donde 

function miProcedimiento(argumentoFormal1[, argumentoFormal2, ...) {


/* Secuencia de código sin valor devuelto al procesamiento que llama */
}

después  de  la  palabra  clave  function,  hay  que  poner  un  nombre  de  procedimiento,  seguido  de  una  serie  de 
argumentos formales entre paréntesis. En caso de argumentos múltiples, conviene separarlos por comas. 

Es  sorprendente  que  se  utilice  la  palabra  clave  function  cuando  en  este  párrafo  hablamos  de  procedimiento. 
Veremos más adelante que function es una palabra clave que sirve indistintamente a los procedimientos y a las 
funciones en JavaScript. 

La particularidad, ya mencionada, es que un procedimiento no devuelve un valor. 

La llamada del procedimiento se hace con la siguiente sintaxis: 

miProcedimiento(argumentoEfectivo1[, argumentoEfectivo2, ...);

2. Ejercicio n.°16: Llamada de un procedimiento con argumentos

Enunciado 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Llamar a un procedimiento que muestre el doble de dos argumentos efectivos, pasados como argumentos (los dos 
argumentos se van a introducir por el teclado). 

Corrección (parcial) en JavaScript 

/* Procedimiento de doblado */
function doblado(x, y)
{
/* Doblado */
x = x * 2;
y = y * 2;
/* Visualización de la dupla de valores después del doblado */
document.write("La dupla doblada es (" + x + ", " + y +")<br />");
}

/* Visualización del nombre del script */


alert("Ejercicio Procedure");

/* Declaración de variables locales */


var a, b, c, d;

/* Introducción de los argumentos a y b */


a = parseInt(prompt("Argumento a:"));
b = parseInt(prompt("Argumento b:"));

/* Llamada al procedimiento que dobla */


doblado(a, b);

/* Introducción de los argumentos c y d */


c = parseInt(prompt("Argumento c:"));
d = parseInt(prompt("Argumento d:"));

/* Llamada al procedimiento de doblado */


doblado(c, d);

Comentarios del código JavaScript  

Si  es  posible,  el  procedimiento  doblado  se  coloca  antes  de  las  llamadas  ( doblado(a, b); doblado (c,
d);), pero no es obligatorio. 

En  primer  lugar,  se  introducen  dos  valores  enteros  a y  b  por  el  teclado.  Estos  dos  valores  serán  los  argumentos 
efectivos del procedimiento doblado. Los valores de  a y de  b se asignan respectivamente a los argumentos x e y 
(que de esta manera también se consideran como enteros). A continuación, el procedimiento garantiza el doblado 
de cada uno de los valores y muestra la dupla de los valores doblados. 

Caso particular de procedimiento sin argumentos 

Los procedimientos también se utilizan sin argumentos, como se muestra en el siguiente script: 

/* Procedimiento Hola_mundo */
function Hola_mundo()

/* Visualización de un Hola Mundo */

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


document.write("Hola mundo <br />");
}

/* Visualización del nombre del script */


alert("Ejercicio Procedimiento_sin_argumentos");

/* Primera llamada al procedimiento Hola_mundo */


Hola_mundo();

/* Segunda llamada al procedimiento Hola_mundo */


Hola_mundo();

Los paréntesis después del nombre del procedimiento también son necesarios cuando no hay argumentos. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Las funciones

1. Sintaxis

Una función es un procedimiento que devuelve un valor a la secuencia de código que llama. 

El resultado devuelto se debe asignar a una variable o mostrar a través del método alert o document.write. 

miVariable = miFuncion(argumentoEfectivo1[, argumentoEfectivo2, ...);

alert("Resultado: " + miFuncion(argumentoEfectivo1[, argumentoEfectivo2, ...);

document.write("Resultado: " + miFuncion(argumentoEfectivo1[,


argumentoEfectivo2, ...);

A nivel de la función, devolver un valor se hace como sigue: 

function miFuncion(argumentoFormal1[, argumentoFormal2, ...)


{
/* Secuencia de código que determina un valor
para devolver (valorDevuelto) */

/* Valor de retorno */
return valorDevuelto;
}

2. Ejercicio n.°17: Llamada de una función con argumentos

Enunciado 

Uso de una función de cálculo del máximo de dos valores introducidos por teclado y pasados como argumentos. 

Corrección (parcial) en JavaScript 

/* Función maxi (determina el máximo de dos cifras) */


function maxi(x, y)
{
/* Determinación del máximo */
if (x > y)
{
return x;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


}
else
{
return y;
}
}

/* Visualización del nombre del script */


alert("Ejercicio Función");

/* Declaración de variables locales */


var a, b, c, d;

/* Introducción de los argumentos a y b */


a = parseInt(prompt("Argumento a:"));
b = parseInt(prompt("Argumento b:"));

/* Llamada a la función maxi */


alert("Máximo: " + maxi(a, b));

/* Introducción de los argumentos c y d */


c = parseInt(prompt("Argumento c:"));
d = parseInt(prompt("Argumento d:"));

/* Llamada a la función maxi */


document.write("Máximo: " + maxi(c, d));

Comentarios del código JavaScript 

El código de la función maxi es fácil de interpretar. Devolvemos los argumentos efectivos a y b, después  c y d, que 
alimentan la función que se encarga de determinar el valor máximo. El resultado (x o  y según el caso) se devuelve 
al  código  que  llama  a  la  instrucción,  a  través  de  return.  La  función  no  se  encarga  aquí  de  la  visualización  del 
máximo.  El  programa  que  llama  recupera  el  máximo  y  se  ocupa  de  esto  (uso  del  método  alert  o  del  método 
document.write).  

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Introducción

Aunque la implementación del modelo de programación orientada a objetos (POO) no esté tan completa en JavaScript 
como en C++ o Java, JavaScript ofrece los mecanismos principales gestionados por estos lenguajes. 

Recordemos los conceptos más importantes de la POO: 

l Encapsulación:  reunión  de  un  conjunto  de  propiedades  (parte  de  tratamiento  de  datos)  y  de  funciones,  también 
llamadas métodos (parte de procesamientos), dentro de un objeto tipo (quizás es más correcto hablar de clase), con la 
posibilidad de crear (instanciar) objetos a partir de esta clase. 

l Herencia:  posibilidad  de  "fabricar"  una  nueva  clase  a  partir  de  una  clase  existente;  esta  nueva  clase  hereda  las 
propiedades y métodos de la clase padre (se pueden añadir nuevas propiedades/métodos a la nueva clase). 

l Polimorfismo:  un  método  del  mismo  nombre  asociado  a  varias  clases  puede  tener  comportamientos  diferentes  para 
algunas de estas clases. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Programación orientada a objetos a través de ejemplos

JavaScript siempre ha sido una pieza esencial en los desarrollos Web, principalmente para la programación del lado 
"cliente", es decir, del lado del navegador. Habitualmente, sin sumergirse de lleno en el lenguaje, los desarrolladores 
producen  código  JavaScript  de  calidad  mediocre,  contentándose  con  adaptar  el  código  fuente  recuperado  de  sitios 
Web y manipulando los conceptos POO lo menos posible. 

En  paralelo,  han  aparecido  un  gran  número  de  librerías  JavaScript  y  su  uso  permite  producir  aplicaciones  de  mejor 
calidad. El dominio de estas librerías supone tener conocimientos básicos de POO en JavaScript. 

Por  tanto,  el  objetivo  de  la  exposición  que  sigue  es  presentarle  lo  que  hay  que  saber  sobre  este  asunto.  Los 
conceptos se van a explicar a través de una serie de ejemplos. 

Algunos lectores que ya tengan una importante experiencia en otros lenguajes POO (PHP 5, Java, C++...) al principio 
se pueden sentir incómodos con los aspectos específicos de la POO en JavaScript, la POO por prototipado. 

1. Secuencia 1: Declaración de los objetos JavaScript de manera "Inline"

Se trata de la manera más sencilla de declarar un objeto en JavaScript. 

/* Declaración inline de un objeto JavaScript */


/* NB: Esta técnica no permite la herencia a partir del objeto
más adelante */
var Adicion = {
x: 5,
y: 10,
calculo: function()
{
return this.x + this.y;
}
};

/* Uso del objeto Adicion */


document.write("Suma: " + Adicion.calculo());

El resultado obtenido de la ejecución será el siguiente: 

Suma = 15

En este tipo de declaración de objeto, es posible prever la especificación de atributos (propiedades) y también de 
métodos. 

La palabra clave this sirve para indicar que se está haciendo referencia a los atributos del objeto en sí mismo. 

Está claro que con este tipo de declaración no será posible reutilizar este tipo de definición para crear un objeto de 
las  mismas  características  (o  parecidas).  Por  tanto,  este  método  se  utilizará  poco  (o  nada)  porque  no  permite  la 
herencia. No se preocupe, porque volveremos sobre esto más en detalle, a lo largo de esta exposición. 

2. Secuencia 2: Creación de objetos JavaScript con un constructor

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


También es posible crear nuestros objetos JavaScript con un constructor (concepto bien conocido en los lenguajes 
POO). En JavaScript, será suficiente con escribir una función y llamarla posteriormente con la palabra clave  new. Por 
tanto, la función jugará el papel de clase sin serlo realmente. 

Veamos con un ejemplo el desarrollo que es necesario seguir: 

/* Definición de una función constructor, de nombre Coche */


var Coche = function()
{
/* Atributo(s) del objeto */
this.tieneMotor = true;
/* Método(s) del objeto */
this.avanzar = function()
{
document.write("avanza");
}
}

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Visualización del atributo tieneMotor del objeto simca1100 */


if (simca1100.tieneMotor)
{
document.write("El coche simca1100 tiene un motor<br />");
}
else
{
document.write("El coche simca1100 no tiene motor !<br />");
}

/* Llamada al método avanzar del objeto simca1100 */


document.write("El coche simca1100 ");
simca1100.avanzar();

En nuestro ejemplo, se define en primer lugar una función  Coche. Integra un atributo booleano que indica que los 
coches  tienen  un  motor  y  un  método  (función)  de  nombre  avanzar,  que  mostrará  "avanza"  cuando  se  pida,  a 
partir de un objeto de tipo Coche (se entenderá rápidamente). 

Posteriormente,  se  construye  un  objeto  de  nombre  simca1100  a  partir  del  constructor  Coche  (siento  que  el 
término "constructor" pueda ser confuso en un ejemplo basado en coches): 

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

Ahora, la propiedad (atributo)  tieneMotor se puede consultar para el objeto  simca1100 instanciado y también 


se puede ejecutar el método avanzar. Cuando se ejecute, tendremos: 

El coche simca1100 tiene un motor


El coche simca1100 avanza

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


3. Secuencia 3: Variables privadas en una instancia de objeto

En  el  ejemplo  de  la  secuencia  anterior,  habrá  observado  que  las  propiedades  (atributos)  llevan  como  prefijo  la 
palabra clave this. Esto es lo que las hace usables desde el exterior (caso de la propiedad  tieneMotor). Por el 
contrario, por necesidades locales del constructor (cálculo interno), puede declarar variables no expuestas, usando 
como prefijo la palabra clave var. 

Veamos un ejemplo concreto: 

/* Definición de una función constructor de nombre Coche */


var Coche = function()
{
/* Variable(s) local(s) no accesible(s) desde el exterior del objeto */
var numeroRuedas = 4;
/* Método(s) del objeto */
this.avanzar = function()
{
document.write("avanza");
}
}

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método avanzar del objeto simca1100 */


document.write("El coche simca1100 ");
simca1100.avanzar();

/* Intento de visualización de la variable local del constructor Coche */


document.write("<br />");
document.write("El coche simca1100 tiene " + simca1100.numeroRuedas +
" ruedas");

Se usa una variable local numeroRuedas en el constructor con el prefijo  var. Esto solo es accesible, como estaba 
previsto, desde dentro del constructor, como se muestra en la ejecución de este script: 

El coche simca1100 avanza


El coche simca1100 tiene undefined ruedas

4. Secuencia 4: Paso de argumento(s) a un constructor

En el ejemplo siguiente, vamos ver que es posible pasar uno o varios argumentos (lo habíamos visto ya para las 
funciones clásicas) a un constructor: 

/* Definición de una función constructor de nombre Coche */


var Coche = function(modelo)

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


{
/* Atributo(s) del objeto informado durante la instanciación */
this.modelo = modelo;
}

/* Instanciación de un objeto simca1100 a través del constructor Coche


con paso de argumento */
var miCoche = new Coche("simca1100");

/* Visualización del atributo modelo del objeto miCoche */


document.write("Tengo un " + miCoche.modelo);

El argumento modelo está en los paréntesis que siguen al nombre del constructor: 

var Coche = function(modelo)

y está disponible en el cuerpo del constructor por: 

this.modelo = modelo;

A  continuación,  es  suficiente  a  nivel  de  la  instanciación  del  objeto  miCoche  con  pasar  como  argumento  un  valor 
("simca1100" en nuestro caso): 

var miCoche = new Coche("simca1100");

La propiedad (atributo) modelo del objeto se mostrará por: 

document.write("Tengo un " + miCoche.modelo);

5. Secuencia 5: No compartición de los métodos por las instancias de objetos

En  la  medida  en  que  los  métodos  se  declaran  durante  la  instanciación  de  los  objetos,  sus  definiciones  están 
duplicadas en memoria. 

En un ejemplo pequeño, el impacto es bajo. 

Por el contrario, si su aplicación manipula muchos objetos con métodos múltiples y complejos en los constructores, 
esto se convierte en inmanejable. 

El siguiente ejemplo destaca el problema que acabamos de comentar: 

/* Definición de una función constructor de nombre Coche */


var Coche = function()
{
/* Atributo(s) del objeto */

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


this.tieneMotor = true;
/* Método(s) del objeto */
this.avanzar = function()
{
document.write("avanza");
}
this.retroceder = function()
{
document.write("retrocede");
}
}

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Instanciación de un objeto renault12 a través del constructor Coche */


var renault12 = new Coche();

/* Comprobación de la igualdad de métodos avanzar de los objetos simca1100


y renault12 */
if (simca1100.avanzar == renault.avanzar)
{
document.write("Método avanzar compartido por los objetos simca1100 y
Renault12<br />");
}
else
{
document.write("Método avanzar no compartido por los objetos simca1100
y Renault12<br />");
}

La ejecución confirma que el método avanzar no está factorizado: 

Método avanzar no compartido por los objetos simca1100 y Renault12

La noción de prototipo que vamos a descubrir a continuación va a resolver este problema. 

6. Secuencia 6: Noción de prototipo

Un prototipo es un conjunto de elementos (atributos/propiedades y métodos) que se va a asociar a un constructor 
(sin  "almacenamiento"  en  el  constructor  en  sí  mismo).  Durante  la  ejecución,  cuando  una  propiedad  de  objeto 
solicitada en el código no se encuentra en el constructor del objeto en cuestión, se realizará una búsqueda en esta 
lista "adicional". 

Veamos un ejemplo completo: 

/* Definición de una función constructor de nombre Coche */


/* NB: El constructor aquí está vacío */
var Coche = function() {};

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


/* Comprobación de la existencia por defecto de un prototipo para
cualquier constructor */
document.write("Prototipo del constructor: " + Coche.prototype);

/* Añadir un método zigzaguear al prototipo del constructor Coche */


Coche.prototype.zigzaguear = function()
{
document.write("zigzaguea peligrosamente<br />");
};

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método zigzaguear del objeto simca1100, accesible a través


del prototipo del constructor Coche */
document.write("<br />¿Qué hace el simca1100? ");
simca1100.zigzaguear();

/* Instanciación de un objeto renault12 a través del constructor Coche */


var renault12 = new Coche();

/* Comprobación del método zigzaguear compartido o no, entre los objetos


simca1100 y renault12 */
if (simca1100.zigzaguear == renault12.zigzaguear)
{
document.write("Método zigzaguear compartido por los objetos
simca1100 y renault12<br />");
}
else
{
document.write("Método zigzaguear no compartido por los objetos
simca1100 y renault12<br />");
}

La opción que se ha utilizado en el ejemplo es codificar un constructor vacío. Después, se realiza una comprobación 
para demostrar que cualquier constructor tiene un prototipo: 

document.write("Prototipo del constructor: " + Coche.prototype);

Posteriormente, se ha asociado un método zigzaguear al prototipo relacionado con el constructor Coche: 

Coche.prototype.zigzaguear = function()
{
document.write("zigzaguea peligrosamente<br />");
};

Después de la instanciación habitual de un objeto simca1100 a partir del constructor  Coche, se hace una llamada 
al método zigzaguear para el objeto simca1100. 

También se instancia un segundo objeto, renault12, a partir del constructor Coche para demostrar que esta vez 
el método zigzaguear está compartido (es común) por los dos objetos. 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La ejecución da: 

Prototipo del constructor: [object Object]


¿Qué hace el simca1100? Zigzaguea peligrosamente
Método zigzaguear compartido por los objetos simca1100 y renault12

7. Secuencia 7: Sobrecarga de un método

Para una instancia dada de objeto, es posible sobrecargar (modificar) un método (o una propiedad/atributo). 

Veamos un ejemplo concreto de cómo aplicarlo: 

/* Definición de una función constructor, de nombre Coche */


/* NB: El constructor aquí está vacío */
var Coche = function() {};

/* Añadir un método cargar al prototipo del constructor Coche */


Coche.prototype.cargar = function()
{
document.write("carga<br />");
};

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método cargar del objeto simca1100, accesible a través


del prototipo del constructor Coche */
document.write("El simca1100 ");
simca1100.cargar();

/* Instanciación de un objeto renault12 a través del constructor Coche */


var renault12 = new Coche();

/* Modificación (sobrecarga) del método cargar para el objeto


simca1100 */
simca1100.cargar = function()
{
document.write("carga rápidamente <br />");
};

/* Llamada al método cargar (sobrecargado) del objeto simca1100 */


document.write("El simca1100 ");
simca1100.cargar();

/* Llamada al método cargar (no sobrecargado) del objeto renault12 */


document.write("El renault12 ");
renault12.cargar();

La ejecución da como resultado: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


El simca1100 carga
El simca1100 carga rápidamente
El renault12 carga

Puede comprobar que la modificación (sobrecarga) solo impacta al objeto simca1100. 

8. Secuencia 8: Extensión de un prototipo

La extensión es la adición posterior de un método suplementario a nivel de un prototipo de constructor. Veamos un 
ejemplo de extensión: 

/* Definición de una función constructor de nombre Coche */


/* NB: El constructor aquí está vacío */
var Coche = function() {};

/* Añadir un método acelerar al prototipo del constructor Coche */


Coche.prototype.acelerar = function()
{
document.write("acelera<br />");
};

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método acelerar del objeto simca1100, accesible a través


del prototipo del constructor Coche */
document.write("El simca1100 ");
simca1100.acelerar();

/* Añadir (sobrecargar) el método frenar accesible a través del prototipo


del constructor Coche */
Coche.prototype.frenar = function()
{
document.write("frena");
};

/* Llamada al método frenar (añadido al prototipo del constructor Coche)


a partir del objeto simca1100 */
document.write("El simca1100 ");
simca1100.frenar();

La ejecución da como resultado: 

El simca1100 acelera
El simca1100 frena

Cuando se ejecuta el método  simca1100.frenar, en primer lugar el método frenar se busca en el constructor 
Coche y, como este método no se define, se realiza una búsqueda en la extensión, es decir, en el prototipo. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


9. Secuencia 9: Mecanismo de la herencia

Todavía  no  habíamos  visto  la  noción  de  herencia,  que  permite,  en  los  lenguajes  de  POO  clásicos,  establecer  una 
relación  de  tipo  "Clase  hija­Clase  padre"  entre  clases  de  un  modelo  arborescente  con,  para  la  clase  hija,  una 
herencia (en ocasiones modificada por sobrecargas) de propiedades/atributos y métodos de su clase padre. 

En  JavaScript,  el  mecanismo  de  herencia  será  un  poco  diferente.  Se  obtendrá  por  extensión  de  prototipos  (un 
prototipo extendido a partir de otro). 

Veamos su aplicación con un ejemplo concreto: 

/* Definición de una función constructor, de nombre Vehiculo */


/* NB: El constructor aquí está vacío */
var Vehiculo = function() {};

/* Añadir un método acelerar al prototipo del constructor Vehiculo */


Vehiculo.prototype.acelerar = function()
{
document.write("acelera<br />");
};

/* Añadir un método frenar al prototipo del constructor Vehiculo */


Vehiculo.prototype.frenar = function()
{
document.write("frena<br />");
};

/* Definición de una función constructor de nombre Coche */


/* NB: El constructor aquí está vacío */
var Coche = function() {};

/* Copia de todos los elementos (atributos y métodos) del prototipo


del constructor Vehiculo */
/* en el prototipo del constructor Coche */
/* NB: Sobre todo no hacer Coche.prototype = Vehiculo.prototype porque
en este caso el prototipo sería compartido */
for (clave in Vehiculo.prototype)
{
Coche.prototype[clave] = Vehiculo.prototype[clave];
}

/* Sobrecarga del prototipo del constructor Coche (adición de un método


frenar) */
Coche.prototype.frenar = function()
{
document.write("frena");
};

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método acelerar del objeto simca1100, accesible desde

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


la copia del prototipo del constructor Vehiculo */
document.write("El simca1100 ");
simca1100.acelerar();

/* Llamada al método frenar del objeto simca1100 accesible a través del


prototipo del constructor Coche */
document.write("El simca1100 ");
simca1100.frenar();

Cuando se ejecuta, el resultado obtenido será el siguiente: 

El simca1100 acelera
El simca1100 frena

Durante la ejecución, los elementos (métodos  acelerar y  frenar en nuestro caso) del prototipo del constructor 


Vehiculo se copian en el prototipo del constructor Coche: 

/* Copia de todos los elementos (atributos y métodos) del prototipo


del constructor Vehiculo en el prototipo del constructor Coche */
/* NB: Sobre todo no hacer Coche.prototype = Vehiculo.prototype porque
en este caso el prototipo sería compartido */
for (clave in Vehiculo.prototype)
{
Coche.prototype[clave] = Vehiculo.prototype[clave];
}

Por tanto, el simca1100 de tipo Coche puede: 

l acelerar con el método acelerar del prototipo del constructor Vehiculo, 

l frenar con el método frenar (añadido como sobrecarga) al prototipo del constructor Coche. 

10. Secuencia 10: Límite de la herencia de la secuencia 9

En la secuencia anterior, solo hemos copiado las propiedades del prototipo  Vehiculo en otro prototipo,  Coche. 


¿Estamos  seguros  de  que,  después  de  esta  operación,  cualquier  objeto  de  tipo  Coche  también  se  considera  un 
Vehiculo? 

Comprobémoslo con un ejemplo un poco diferente: 

/* Definición de una función constructor, de nombre Vehiculo */


/* NB: El constructor aquí está vacío */
var Vehiculo = function() {};

/* Añadir un método acelerar al prototipo del constructor Vehiculo */


Vehiculo.prototype.acelerar = function()
{
document.write("acelera<br />");
};

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Definición de una función constructor de nombre Coche */
/* NB: El constructor aquí está vacío */
var Coche = function() {};

/* Copia todos los elementos (atributos y métodos) del prototipo


del constructor Vehiculo en el prototipo del constructor Coche */
/* NB: Sobre todo no hacer Coche.prototype = Vehiculo.prototype porque
en este caso el prototipo sería compartido */
for (clave in Vehiculo.prototype)
{
Coche.prototype[clave] = Vehiculo.prototype[clave];
}

/* Instanciación de un objeto simca1100 a través del constructor


Coche */
var simca1100 = new Coche();

/* Constructor utilizado para la creación del objeto simca1100,


¿es Coche? */
document.write("simca1100 tiene como constructor Coche: ");
document.write(simca1100 instanceof Coche);

/* Constructor utilizado para la creación del objeto simca1100


¿es Vehiculo? */
document.write("<br />simca1100 tiene como constructor Vehiculo: ");
document.write(simca1100 instanceof Vehiculo);

La  ejecución  muestra  que  el  objeto  simca1100  se  considera  solo  como  un  objeto  de  tipo  Coche  (y  no 
Vehiculo): 

simca1100 tiene como constructor Coche: true


simca1100 tiene como constructor Vehiculo: false

11. Secuencia 11: Un segundo límite a nuestra herencia

Si un método se añade al prototipo de un tipo "padre" después de que se haya hecho la copia de los elementos 
entre  el  prototipo  "padre"  y  el  prototipo  "hijo",  entonces  este  método  no  está  disponible  en  los  objetos 
instanciados con el tipo "hijo", como se muestra en el siguiente ejemplo: 

/* Definición de una función constructor de nombre Vehiculo */


/* NB: El constructor aquí está vacío */
var Vehiculo = function() {};

/* Añadir un método acelerar al prototipo del constructor Vehiculo */


Vehiculo.prototype.acelerar = function()
{
document.write("acelera<br />");
};

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


/* Definición de una función constructor de nombre Coche */
/* NB: El constructor aquí está vacío */
var Coche = function() {};

/* Copia todos los elementos (atributos y métodos) del prototipo


del constructor Vehiculo en el prototipo del constructor Coche */
/* NB: Sobre todo no hacer Coche.prototype = Vehiculo.prototype porque
en este caso el prototipo sería compartido */
for (clave in Vehiculo.prototype)
{
Coche.prototype[clave] = Vehiculo.prototype[clave];
}

/* Añadir el método frenar al prototipo del constructor Vehiculo */


Vehiculo.prototype.frenar = function()
{
document.write("frena<br />");
};

/* Instanciación de un objeto barco a través del constructor Vehiculo */


var barco = new Vehiculo();

/* Llamada al método frenar para el objeto barco */


document.write("El barco ");
barco.frenar();

/* Instanciación de un objeto simca1100 a través del constructor Coche */


var simca1100 = new Coche();

/* Llamada al método frenar para el objeto simca1100 */


document.write("el simca1100 ");
simca1100.frenar();

Cuando se ejecuta, nos encontramos con lo siguiente, como era de esperar: 

El barco frena
el simca1100

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Presentación

Hemos  visto  en  el  capítulo  anterior  cómo  crear  y  utilizar  nuevos  objetos  en  JavaScript. En  realidad  este  lenguaje 
propone de manera nativa una serie de objetos que hay que conocer. 

Observe que los desarrolladores Web se contentan justamente con estos objetos nativos. 

En  este  capítulo  vamos  a  listarlos,  pero  no  de  manera  exhaustiva.  Es  fácil  encontrar  documentación  y  ejemplos  de 
estos objetos. También hay repositorios completos accesibles en Internet. 

Nuestro objetivo es ser lo más completos posible y sobre todo, aprender a implementar estos objetos, así como sus 
métodos y sus propiedades, a través de ejemplos didácticos y comentados. 

Puede consultar en Internet repositorios completos sobre este tema, fundamentalmente Mozilla Developer Network, en 
la dirección: https://developer.mozilla.org/es/docs/Web/JavaScript 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Los objetos básicos

Los objetos se abordarán por orden alfabético en este capítulo. 

1. Objeto Array

En la medida en que este objeto se ha estudiado en el capítulo Tablas, no volveremos aquí sobre él. 

2. Objeto Date

La gestión de las fechas es una preocupación frecuente en los desarrollos Web. 

Para que sirva de ejemplo, a continuación se enumeran los principales métodos de este objeto: 

l getDate() 
l getDay() 
l getFullYear() 
l getHours() 
l getMilliseconds() 
l getMinutes() 
l getMonth() 
l getSeconds() 
l getTime() 
l getTimezoneOffset() 
l getYear() 
l setDate() 
l setFullYear() 
l setHours() 
l setMilliseconds() 
l setMinutes() 
l setMonth() 
l setSeconds() 
l setTime() 
l setYear() 
l toGMTString() 
l toLocaleString() 

La gran mayoría de los métodos que se han listado anteriormente se van a estudiar con un primer ejemplo llamado 
FECHA_01.htm. 

Ejemplo 1 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


El  código  fuente  del  ejemplo  se  reproduce  completamente  más  adelante  (código  integrado  en  la  sección  HTML 
<body> del script). 

Empecemos por el método  getDate(), que da el número de día del mes, para un objeto de tipo Date. En nuestro 
caso, la fecha analizada es el día de hoy. Se instancia una fecha fechaDeHoy con valor la fecha de hoy. La función 
getDate() aplicada al objeto fechaDeHoy da el número del día del mes. El resultado se muestra para control. 

/* Método getDate -> devuelve el n.° del día


del mes de la fecha de sistema */
var fechaDeHoy = new Date();
var diaMes = fechaDeHoy.getDate();
document.write("Número del día de la fecha de sistema: " + diaMes);

El  método  getDay  devuelve  el  número  del  día  de  la  semana  para  un  objeto  de  tipo  Date.  El  procesamiento  se 
hace de nuevo sobre la fecha del día de hoy. El método getDay() proporciona un resultado entre 0 y 6. Una tabla 
de correspondencia podría dar el nombre del día (no está previsto en nuestro ejemplo). 

/* Método getDay -> devuelve el n.° del día en la semana


(n.° de 0 a 6) de la fecha de sistema */
var fechaDeHoy = new Date();
var diaSemana = fechaDeHoy.getDay();
document.write("<br />Número del día de la semana (número de 0 a 6)
de la fecha de sistema: " + diaSemana);

El número del mes (comprendido entre 0 y 11) se obtiene a partir de una fecha, con el método getMonth(). Una 
vez más, el procesamiento se hace sobre la fecha del día. 

/* Método getMonth -> devuelve el n.° del mes (n.° de 0 a 11)


de la fecha de sistema */
var fechaDeHoy = new Date();
var mes = fechaDeHoy.getMonth();
document.write("<br />Número del mes de la fecha de sistema: "
+ (Mes + 1));

El  número  del  año  (con  cuatro  posiciones)  se  obtiene  a  partir  de  una  fecha  con  el  método  getFullYear(). En 
nuestro ejemplo el procesamiento se hace sobre la fecha del día. 

/* Método getFullYear -> devuelve el n.° del año


(con 4 posiciones) de la fecha de sistema */
var fechaDeHoy = new Date();
var año = fechaDeHoy.getFullYear();
document.write("<br />Número del año de la fecha de sistema: "
+ año);

Para  recuperar  la  hora  (comprendida  entre  0  y  23)  a  partir  de  un  objeto  Date,  hay  que  recurrir  al  método 
getHours(). 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Método getHours -> devuelve l hora (n.° de 0 a 23) de
la fecha de sistema */
var fechaDeHoy = new Date();
var hora = fechaDeHoy.getHours();
document.write("<br />Número de la hora de la fecha de sistema: "
+ hora);

Para los minutos, el método se llama getMinutes(). 

/* Método getMinutes -> devuelve el n.° de minutos (n.° de 0 a 59)


de la fecha de sistema */
var fechaDeHoy = new Date();
var minuto = fechaDeHoy.getMinutes();
document.write("<br />Número del minuto de la fecha de sistema: "
+ minuto);

Y para terminar, para los segundos el método es getSeconds(). 

/* Método getSeconds -> devuelve el n.° del segundo (n.° de 0 a 59) */


var fechaDeHoy = new Date();
var segundo = fechaDeHoy.getSeconds();
document.write("<br />Número del segundo de la fecha de sistema: " +
segunda);

Pasemos ahora a los métodos que permiten asignar valores (setters). 

Por ejemplo, es posible indicar la fecha correspondiente al 15 del mes para la fecha actual, como sigue: 

/* Método setDate -> define un n.° de día en el mes respecto


a la fecha de sistema (el 15 del mes, en nuestro caso) */
var fechaDeHoy = new Date();
fechaDeHoy.setDate(15);
document.write("<br />El 15 del mes correspondiente a la fecha de sistema:
" + fechaDeHoy);

Con  la  secuencia  de  código  siguiente,  puede  realizar  una  "vuelta  atrás  "  de  un  mes  respecto  a  una  fecha  de 
referencia (aquí, la fecha del día). 

/* Método setMonth -> define la fecha un mes atrás


respecto a la fecha de sistema */
var fechaDeHoy = new Date();
fechaDeHoy.setMonth(fechaDeHoy.getMonth()-1);
document.write("<br />Un mes más respecto a la fecha de sistema: "
+ fechaDeHoy);

El mismo procesamiento también es posible para una "vuelta atrás" de un año: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


/* Método setFullYear -> define la fecha un año atrás respecto a
la fecha de sistema */
var fechaDeHoy = new Date();
fechaDeHoy.setFullYear(fechaDeHoy.getFullYear()-1);
document.write("<br />Un año más respecto a la fecha de sistema:
" + fechaDeHoy);

Solo  falta  ver  cómo  convertir  en  versión  española  la  fecha  de  sistema.  Para  esto,  usamos  el  método 
toLocaleDateString(): 

/* Método toLocaleDateString -> convierte la fecha de sistema


en una cadena fecha, en versión locale=ES */
var fechaDeHoy = new Date();
var dateLocale = fechaDeHoy.toLocaleDateString();
document.write("<br />Fecha de sistema (version locale=ES): " + dateLocale);

Un procesamiento idéntico se puede aplicar para obtener las horas, minutos y segundos en formato español: 

/* Método toLocaleTimeString -> convierte la fecha de sistema


en una cadena horas/minutos/segundos en versión locale=ES */
var fechaDeHoy = new Date();
var horaLocal = fechaDeHoy.toLocaleTimeString();
document.write("<br />Horas/Minutos/Segundos (version locale=ES): " +
horaLocal);

Este script permite visualizar la siguiente pantalla durante su ejecución (el jueves, 15 de enero del 2015): 

Ejemplo 2 

En este segundo ejemplo, siempre relacionado con la fecha, vamos a mostrar la hora actual en formato hh:mm:ss. 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


El código situado en la sección HTML <body> es el siguiente: 

<!-- Inicio script JavaScript -->


<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("DATE_02");

/* Llamada de la función mostrarHoraActual */


var miHora = setInterval (
function()
{
mostrarHoraActual()
}, 1000
);

</script>

<!-- Elemento span de visualización del timer -->


Hora actual: <span id="horaActual"></span>

El primer argumento de  setInterval  es  una  función  que  invoca  a  una  función  llamada  mostrarHoraActual 
(que veremos más adelante) y una duración expresada en  milisegundos (1000 = 1 segundo), correspondiente 
al ritmo de actualización de la visualización de la hora de sistema en formato hh:mm:ss. 

Un  span identificado por  horaActual también está previsto para recibir la visualización generada por la función 


mostrarHoraActual. 

Pasemos al código de la función mostrarHoraActual, ubicado en la sección HTML <head>. 

/* Función mostrarHoraActual */
function mostrarHoraActual()
{
/* Recupera la hora de sistema */
var miHoraReferencia = new Date();

/* Conversión de la hora de sistema en formato local (hh:mm:ss) */


var hhmmss = miHoraReferencia.toLocaleTimeString();

/* Visualización en el span horaActual */


document.getElementById("horaActual").innerHTML = hhmmss;
}

La  hora  de  sistema  (fecha  de  sistema)  se  recupera  instanciando  un  objeto  de  tipo  Date  en  la  variable 
miHoraReferencia. 

A  continuación,  se  hace  una  conversión  de  la  parte  horas/minutos/segundos  de  esta  fecha,  en  formato  local 
(hh:mm:ss). 

El script de la función termina mostrando esta información en la división mencionada anteriormente. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


La visualización en pantalla se presenta como sigue: 

Ejemplo 3 

Estudiemos  un  último  ejemplo  relacionado  con  la  gestión  del  tiempo,  pero  sin  utilizar  explícitamente  la  noción  de 
objeto, en el que vamos a programar un cronómetro (timer) simple. 

El código ubicado en la sección HTML <body> es el siguiente: 

<!-- Formulario con botones de inicio y de parada del timer -->


<div>
<input
tipo="button"
value="Inicio del timer"
onclick="iniciarTimer()"
/>
<input
tipo="button"
value="Parada del timer"
onclick="pararTimer()"
/>
</div>

<!-- División de la visualización del timer -->


<br /><br />
<div id="visualizacionTimer">Timer</div>

El  código  empieza  con  un  formulario  de  dos  botones,  que  ejecuta  una  función  de  inicio  de  un  timer  y  después  la 
parada de este mismo timer. 

Posteriormente, está prevista una capa para la visualización del timer. 

Estudiemos ahora las funciones de la sección HTML <head>. 

El código de la función iniciarTimer es: 

/* Función iniciarTimer */
function iniciarTimer()

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


{
/* Valor de inicio del timer */
valorTimer = 11;

/* Llamada a la función de actualización del timer */


actualizarTimer();
}

Esta  función  fija  el  valor  de  inicio  del  timer  (11  en  nuestro  caso)  y  llama  a  la  función  de  actualización  del  timer 
(decremento de una unidad de todos los segundos). 

La función actualizarTimer contiene este código: 

/* Función actualizarTimer */
function actualizarTimer()
{
if (valorTimer > 0)
{
/* Decrementar una unidad (segundo) */
valorTimer = valorTimer - 1;
/* Visualización del valor actualizado del timer */
document.getElementById("visualizacionTimer")
.innerHTML = valorTimer;
/* Actualización llamando a la función actualizarTimer */
if(valorTimer > 0)
{
/* Actualización cada segundo (1000 milisegundos) */
miTimer = setTimeout("actualizarTimer()", 1000);
}
}
}

La  función  actualizarTimer  se  llama  a  ella  misma  (noción  de  recursividad  en  programación)  cada  segundo  a 
través del método setTimeout("actualizarTimer()", 1000). 

La actualización se interrumpirá cuando la cuenta alcance el valor de cero. 

La visualización del valor actual del timer se hace por: 

/* Visualización del valor actualizado del timer */


document.getElementById("visualizacionTimer").innerHTML = valorTimer;

Para terminar, el timer también se puede interrumpir con un clic en un botón dedicado del formulario, ejecutando la 
función pararTimer. 

El código de la función pararTimer es el siguiente: 

/* Función pararTimer*/
function pararTimer()
{

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


clearTimeout(miTimer);
}

El  método  clearTimeout(),  al  que  se  le  pasa  el  nombre  del  timer  que  debe  detener  ( miTimer),  provoca  la 
parada del timer. 

La visualización obtenida en pantalla es: 

3. Objeto Math

De nuevo, de este objeto, no se prevé hacer la revisión de todos los métodos. Puede consultar un repositorio como 
el  de  Mozilla  Developper  Network,  para  obtener  la  lista  exhaustiva  de  métodos,  en  la  siguiente  dirección: 
https://developer.mozilla.org/en­US/docs/Web/JavaScript/Reference/Global_Objects/Math 

El  objeto  Math  es,  como  Array  y  Date,  un  objeto  nativo.  Los  métodos  asociados  sirven  para  manipular  los 
elementos numéricos. 

Es  necesario  observar  que  Math  no  es  un  constructor;  por  tanto,  escribir  miNumero = new Math()  sería  un 
error. 

A continuación, se muestra una aplicación de los principales métodos. 

Empezamos por el método abs, que devuelve el valor absoluto de un número que se pasa como argumento. 

/* Valor absoluto de -13 */


document.write("Valor absoluto de -13: " + Math.abs(-13));

El método ceil proporciona el valor entero inmediatamente superior a un número que se pasa como argumento. 

/* Valor superior de 12.5 */


document.write("<br />Valor superior (entero inmediatamente superior)
de 12.5: " + Math.ceil(12.5));

El método floor devuelve el valor entero inmediatamente inferior de un número que se pasa como argumento. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Valor inferior de 12.5 */
document.write("<br />Valor inferior (entero inmediatamente inferior)
de 12.5: " + Math.floor(12.5));

El método  max es particularmente interesante, porque devuelve el máximo, no solo de dos números, sino de una 
serie de números. Por tanto, evita una multitud de comprobaciones en cascada. 

/* Valor máximo entre 2, 5, -3, 12 */


document.write("<br />Valor máximo entre 2, 5, -3, 12: " +
Math.max(2, 5, -3, 12));

El método min es el opuesto del método max, es decir, determina el valor mínimo. 

/* Valor mínimo entre 2, 5, -3, 12 */


document.write("<br />Valor mínimo entre 2, 5, -3, 12: "
+ Math.min(2, 5, -3, 12));

El método pow sirve para elevar a una potencia (exponenciación). Necesita dos argumentos. 

/* Valor 5 elevado a 2 */
document.write("<br />Valor 5 elevado a 2: " + Math.pow(5, 2));

A  menudo  es  útil  hacer  tiradas  aleatorias  de  números  aleatorios.  El  método  random  genera  un  número 
comprendido entre 0 y 1 de manera aleatoria. A continuación, es fácil volver a procesar este valor para obtener, por 
ejemplo, una tirada de un dado de 6 caras (caras numeradas de 1 a 6). 

/* Valor aleatorio (comprendido entre 0 y 1) */


document.write("<br />Valor aleatorio (comprendido entre 0 y 1): " +
Math.random());

El método round también es muy útil: permite redondear un número al entero más cercano. 

/* Valor redondeado de 12.4 */


document.write("<br />Valor redondeado de 12.4: " + Math.round(12.4));

/* Valor redondeado de 12.6 */


document.write("<br />Valor redondeado de 12.6: " + Math.round(12.6));

El método  sqrt también se usa frecuentemente. Sirve para obtener la raíz cuadrada de un número que se pasa 
como argumento. 

/* Valor raíz cuadrada de 25 */


document.write("<br />Raíz cuadrada de 25: " + Math.sqrt(25));

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Terminamos con los métodos trigonométricos. 

/* Valor arcocoseno de 0.5 (expresado en radianes) */


document.write("<br />Arcocoseno de 0.5: "
+ Math.acos(0.5)
+ " radianes");

/* Valor arcoseno de 0.5 (expresado en radianes) */


document.write("<br />Arcoseno de 0.5: "
+ Math.asin(0.5)
+ " radianes");

/* Valor coseno de 0.5 (expresado en radianes) */


document.write("<br />Coseno de 0.5: "
+ Math.cos(0.5)
+ " radianes");

/* Valor seno de 0.5 (expresado en radianes) */


document.write("<br />Seno de 0.5: "
+ Math.sin(0.5)
+ " radianes");

Ejecutando, obtenemos: 

4. Objeto window

En esta sección vamos a hacer un repaso rápido (no exhaustivo) de los métodos y propiedades asociadas al objeto 
DOM window. 

El objeto window representa la ventana del navegador. 

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Observe  que,  en  los  navegadores  que  ofrecen  la  funcionalidad  de  multiventana  (pestañas),  como  Firefox  por 
ejemplo, cada pestaña contiene un objeto window. 

Ilustremos el uso de los diferentes métodos con cinco ejemplos. 

Ejemplo 1 

En este primer ejemplo, de nuevo el código está totalmente integrado en la sección HTML <body>. 

El objetivo del código es sencillo: abrir una ventana pop­up desde la pestaña actual. Observe que el procesamiento 
solo se ejecuta correctamente si el navegador autoriza la creación de ventanas de tipo "pop­up". A menudo, esta 
posibilidad está prohibida (opción del navegador) para evitar la aparición de ventanas publicitarias intrusivas. 

El código del método open es muy simple: 

/* Apertura de la ventana */
/* Argumentos (en orden de aparición):
- URL (Opcional): Indica la dirección URL de la página que se ha de abrir.
Si no se especifica ninguna URL, una nueva ventana con about: blank se abre
- Nombre de la ventana (Opcional): Especifica el atributo destino o
el nombre de la ventana
Los siguientes valores se soportan:
_blank: URL se carga en una nueva ventana (valor por defecto)
_parent: URL se carga en el contenedor padre
_self: URL remplaza la página actual
_top: URL sustituye los juegos de contenedores que se pueden cargar
Nombre: El nombre de la ventana
- Especificaciones detalladas de la ventana:
* height=píxeles: Altura de la ventana (100 píxeles mínimo)
* left=píxeles: Posición de la ventana respecto a la izquierda de la ventana
* location=yes|no|1|0: Presencia o no de una barra de dirección
* menubar=yes|no|1|0: Presencia o no de una barra de menús
* resizable=yes|no|1|0: Posibilidad o no de redimensionar la ventana
* scrollbars=yes|no|1|0: Presencia o no de barras de scroll
* estado=yes|no|1|0: Presencia o no de una barra de estado
* titlebar=yes|no|1|0: Presencia o no de una barra de título
* toolbar=yes|no|1|0: Presencia o no de una barra de herramientas
* width=píxeles: Longitud de la ventana en píxeles
*/
miVentana = window.open("", "VENTANA_01", "width=200, height=100,
location=yes, titlebar=yes");

Los  muchos  comentarios  situados  en  el  código  fuente  indican  de  manera  precisa  el  papel  de  los  diferentes 
argumentos. En nuestro ejemplo, no está prevista la URL (por tanto, a priori la ventana estará sin contenido). La 
ventana aquí se llama (VENTANA_01). Para terminar, se indican sus dimensiones (longitud y altura se expresan en 
píxeles) y la ventana aparece con una barra de direcciones (location) y una barra de título (titlebar). 

Es posible, fundamentalmente en caso de la ausencia de URL, programar un contenido para la nueva ventana como 
sigue: 

/* Escribir un mensaje en la ventana */


miVentana.document.write("Ventana creada en <b>JavaScript</b>");

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


Solo falta situarse en esta ventana con el método focus: 

/* Focus en la ventana */
miVentana.focus();

La ejecución del script da como resultado la siguiente visualización: 

Ejemplo 2 

En este segundo ejemplo, además de la apertura (creación) de una nueva ventana, vamos a ver el cierre. El código 
está repartido entre la sección HTML  <body> (el formulario tiene dos botones, para crear y cerrar la ventana) y la 
sección HTML <head>. 

Empezamos por el formulario: 

<form>
Apertura de una ventana pasando la URL como argumento</br>
<input
type="button"
value="Abrir una ventana yahoo.es"
onclick="abrirVentana(’http://www.yahoo.es)"
/>
<br /><br /><br />
Cierre de la ventana</br>
<input
type="button"
value="Cierre de la ventana"
onclick="cerrarVentana()"
/>
</form>

El primer  input de tipo  button invoca a la función JavaScript llamada  abrirVentana, pasándole la URL de un 


sitio que se ha de mostrar en esta ventana ( http://www.yahoo.es). 

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


El segundo input invoca a una función, llamada cerrarVentana, cuyo papel es cerrar la ventana. 

Pasemos al código fuente de la función abrirVentana. 

/* Función abrirVentana */
function abrirVentana(URL)
{
miVentana = window.open(
URL, "VENTANA_02",
"width=400,
height=200,
location=1,
titlebar=yes,
resizable=yes"
);
}

Este  código  no  tiene  secretos.  La  URL  se  pasa  como  argumento  en  primera  posición  en  los  paréntesis.  A 
continuación viene el nombre de la ventana (VENTANA_02) y sus especificaciones técnicas: 

l width: longitud de la ventana expresada en píxeles, 
l height: altura de la ventana expresada en píxeles, 
l location: presencia de una barra de direcciones (1 equivale a yes), 
l resizable: posibilidad para el usuario de redimensionar la ventana. 

El código de la función cerrarVentana es el siguiente: 

/* Función cerrarVentana */
function cerrarVentana()
{
miVentana.close();
}

El método close cierra la ventana. Después de la ejecución, se obtiene: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


Un clic en el botón llamado Abrir una ventana yahoo.es provoca: 

Ejemplo 3 

El comportamiento de este script va ser muy parecido al del ejemplo anterior: un formulario con un único botón para 
lanzar la creación y el cierre de la ventana 10 segundos después. 

El código del formulario es el siguiente: 

<!-- Formulario -->


<form>
Apertura de una ventana pasando la URL como argumento<br />
<input
tipo="button"
value="Apertura de una ventana yahoo.es (durante 10 segundos)"
onclick="abrirVentana(’http://www.yahoo.es)"
/>
</form>

El código del método abrirVentana llama a la función cerrarVentana después de 10 segundos. 

/* Función abrirVentana */
función abrirVentana(URL)
{
/* Apertura de la ventana */
miVentana = window.open(
URL,
"VENTANA",
"width=400,
height=200,
location=1,
titlebar=yes,
resizable=yes");

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Visualización de la ventana durante
10 segundos */
timeout = setTimeout("cerrarVentana()", 10000);
}

El método setTimeout usa dos argumentos: 

l el nombre del método que se ha de ejecutar, el método cerrarVentana en nuestro caso, 

l el tiempo de espera antes de ejecutarlo, 10.000 milisegundos, es decir, 10 segundos. 

Cuando se ejecuta el script, la visualización es: 

Cuando se hace clic en el botón, se abre una ventana de Yahoo y se muestra durante 10 segundos. 

Ejemplo 4 

En  este  ejemplo,  vamos  a  ver  cómo  detectar  la  resolución  gráfica  de  la  pantalla  del  usuario.  En  función  de  la 
resolución, será posible adaptar el formato de los contenidos Web. 

La secuencia de código es muy sencilla: 

/* Determinación de la resolución (longitud y altura) */


var longitud = window.screen.availWidth;
var altura = window.screen.availHeight;
var resolucion = "Longitud (píxeles): " + longitud + "<br />" +
"Altura (píxeles): " + altura;
document.write("Resolución: "+ resolucion);

La propiedad  availWidth da la resolución en longitud (expresada en píxeles) y la propiedad  availHeight la 


resolución en altura. La visualización obtenida es: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


Ejemplo 5 

En  este  quinto  ejemplo,  vamos  a  implementar  dos  scripts,  WINDOW_05.htm  y  WINDOW_06.htm,  que  se  van  a 
llamar mutuamente. Con este ejemplo, tendremos la oportunidad de estudiar un determinado número de métodos y 
propiedades específicos de los objetos de tipo window. 

En el script WINDOW_05.htm, tenemos un formulario en el que hay un botón de llamada del segundo script: 

<!—Acceso a la página WINDOW_06.htm -->


<form post="WINDOW_06.htm">
<input
tipo="button"
value="Acceso a la página WINDOW_06.htm"
onclick="accederWINDOW_06()"
/>
</form>

El botón activa una función llamada accederWINDOW_06, que se encuentra en la sección HTML <head> del script 
WINDOW_05.htm. Su código fuente es: 

/* Función accederWINDOW_06 */
function accederWINDOW_06()
{
/* Acceso a la página WINDOW_06.htm */
miVentana = window.open("WINDOW_06.htm", "_self");
}

El código no tiene secretos. Se trata de una llamada al script WINDOW_06.htm, que se va a mostrar en la misma 
pestaña (argumento _self). 

La ejecución del script da la siguiente visualización: 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Pasemos a ver el código del archivo WINDOW_06.htm. En la sección HTML <body>, hallamos el siguiente código: 

<!-- Inicio script JavaScript -->


<script type="text/JavaScript">

/* Mostrar el nombre del script */


alert("WINDOW_06");

/*Información de la URL de la página actual /*

/* Propiedad host */
document.write("</br>Propiedad location.host: "
+ window.location.host);

/* Propiedad hostname */
document.write("</br>Propiedad location.hostname: "
+ window.location.hostname);

/* Propiedad href */
document.write("</br>Propiedad location.href: "
+ window.location.href);

/* Propiedad pathname */
document.write("</br>Propiedad location.pathname: "
+ window.location.pathname);

/* Propiedad port */
document.write("</br>Propiedad location.port: "
+ window.location.port);

</script>

La visualización de los valores de las propiedades da como resultado, en nuestro caso: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


Recordemos  que  la  mayor  parte  de  los  scripts  JavaScript  de  este  libro  se  han  probado  en  un  servidor  Web  local 
(Apache). La instalación de este servidor se ha realizado a través del paquete EasyPHP (http://www.easyphp.org). 

La propiedad host está formada por la dirección del servidor (dirección local 122.0.1.1 en nuestro caso), seguida 
del puerto de comunicaciones del servidor (8100). 

También hay un botón de retorno a la página anterior ( WINDOW_05.htm), en esta sección HTML <body>: 

<!—Vuelta a la página anterior -->


<div>
<input tipo="button" value="Volver a la página anterior"
onclick="volverPaginaAnterior()" />
</div>

Este botón llama a una función llamada volverPaginaAnterior, cuyo código es: 

/* Función volverPaginaAnterior */
función volverPaginaAnterior()
{
/* Volver a la página anterior */
window.history.back()
}

El método  window.history.back() provoca el retorno al script que se encuentra inmediatamente antes de la 
página actual en el histórico de navegación, es decir, en nuestro caso WINDOW_05.htm. 

El  código  JavaScript  estudiado  con  este  ejemplo  es  muy  interesante,  fundamentalmente  cuando  se  debe 
implementar un control de acceso entre las páginas de un sitio Web. 

5. Objeto navigator

Este  objeto  contiene  las  propiedades  de  su  navegador.  El  lenguaje  JavaScript  tiene  la  reputación  de  ser  sensible 
(comportamientos  diferentes)  al  navegador,  incluso  a  la  versión  del  navegador  en  la  que  se  ejecuta.  En  las 
propiedades del objeto navigator, encontrará lo necesario para resolver este problema. 

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


En el ejemplo que se presenta a continuación, se comprueban las principales propiedades. 

En  la  sección  HTML  <body>,  encontrará  principalmente  un  botón  de  llamada  a  una  función  que  lista  las 
propiedades, así como una capa de visualización: 

<!-- Llamada a la función de visualización de las características


del navegador -->
<div>
<input
tipo="button"
value="Características del navegador"
onclick="comprobarNavegador()"
/>
</div>

<!-- Capa de visualización de las características del navegador -->


<br /><br />
<div id="mostrarInfosNavegador"></div>

La función comprobarNavegador tiene el código siguiente: 

/* Función comprobarNavegador */
function comprobarNavegador()
{
var caracteristicasNavegador = "";
caracteristicasNavegador = "Código del navegador: "
+ navigator.appCodeName + "<br />";
caracteristicasNavegador += "Nombre del navegador: "
+ navigator.appName + "<br />";
caracteristicasNavegador += "Versión: "
+ navigator.appVersion + "<br />";
caracteristicasNavegador += "Soporte a las cookies: "
+ navigator.cookieEnabled + "<br />";
caracteristicasNavegador += "Sistema operativo: "
+ navigator.platform + "<br />";
caracteristicasNavegador += "User-agent header: "
+ navigator.userAgent + "<br />";
caracteristicasNavegador += "User-agent language: "
+ navigator.systemLanguage + "<br />";

/* Mostrar las características del navegador */


document.getElementById("mostrarInfosNavegador")
.innerHTML = caracteristicasNavegador;

Los  propiedades  appCodeName,  appName  y  appVersion  son  particularmente  interesantes  para  detectar  el 
navegador. 

La propiedad  cookieEnabled también se usa muy frecuentemente para saber si el navegador soporta o no las 
cookies. En caso de tener en cuenta las cookies, será necesario implementar otras soluciones de almacenamiento 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


(local o remoto). La noción de cookie se estudiará en detalle en el capítulo Gestión de las cookies en JavaScript. 

La  propiedad  userAgent  también  se  usa  mucho  porque  contiene,  en  formato  cadena  de  caracteres,  toda  la 
información necesaria para una detección precisa del navegador en el que se ejecuta el script. 

Para que sirva como ejemplo, con mi propia configuración, la ejecución da el siguiente resultado: 

6. Objeto String

Como  en  la  mayoría  de  los  lenguajes  de  programación,  el  procesamiento  de  las  cadenas  de  caracteres  es  muy 
importante. JavaScript ofrece para esto un juego completo de métodos. Vamos a estudiar los principales métodos 
con un ejemplo comentado. 

El siguiente código se sitúa en la sección HTML <body>. 

Empecemos definiendo dos variables de texto: 

/* Definición de variables de tipo String */


var apellido = new String("Sánchez");
var nombre = " Ángel ";
document.write("Apellido: " + apellido);
document.write("<br />Nombre: " + nombre);

Para  la  variable  apellido,  se  ha  recurrido  explícitamente  a  un  constructor.  Las  dos  variables  se  muestran  a 
continuación por control. 

Determinemos ahora la inicial del apellido: 

/* Inicial del apellido */


document.write("<br />Inicial del apellido: " + apellido.charAt(0));

El  método  charAt(),  con  argumento  0,  permite  esta  operación  fácilmente.  Observe  que  los  caracteres  de  una 
cadena se numeran empezando por cero. 

- 20 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Determinamos ahora la posición que ocupa en la tabla ASCII la inicial del nombre: 

/* Carácter Unicode (posición en tabla ASCII) de la inicial del nombre */


document.write("<br />Carácter Unicode (posición en la tabla ASCII) de
la inicial del nombre: " + nombre.charCodeAt(0));

El método utilizado es  charCodeAt(), utilizando como argumento la posición de la letra en la cadena. En nuestro 
caso, la respuesta será 193, porque la letra "Á" está en la posición 193 en la tabla ASCII. 

Desde  los  años  60,  el  código  ASCII  (American  Standard  Code  for  Information  Interchange)  se  ha  convertido  en  el 
estándar en materia de codificación y de intercambio entre ordenadores. Permite la codificación de caracteres en 8 
bits, es decir, 256 caracteres posibles. 

Ahora, veamos cómo concatenar (yuxtaponer o añadir) dos cadenas de caracteres: 

/* Concatenación del apellido y del nombre */


var identidad= apellido.concat(" ");
identidad= identidad.concat(nombre);
document.write("<br />Apellido & Nombre: " + identidad);

La concatenación es un poco sorprendente en JavaScript; el método concat() se aplica a la cadena de base, a la 
que se añade una extensión (una constante u otra variable). 

Estudiemos  ahora  las  múltiples  técnicas  de  localización  o  extracción  de  una  subcadena  en  una  cadena  de 
caracteres. La exposición no será completa porque JavaScript, como la mayoría de los lenguajes de programación, 
soporta también las expresiones regulares, concepto que no se estudia en este libro. 

Empecemos con la localización de la primera aparición de una letra (comenzando por la izquierda) en una cadena de 
caracteres: 

/* Posición de la primera letra "e" en el nombre (atención porque


la numeración empieza por 0) */
var posicion_primera_e = nombre.indexOf("e") + 1;
document.write("<br />La primera ’e’ del nombre está en la posición:
" + posicion_primera_e);

El método utilizado es  indexOf(), pasando como argumento la letra que buscamos ("e" en nuestro caso). Habrá 
observado en el ejemplo que el valor mostrado se incrementa en 1; no olvide que, en las cadenas de caracteres, la 
numeración de las letras empieza por cero. 

También  es  posible  encontrar  la  última  ocurrencia  de  una  letra  (búsqueda  desde  la  derecha)  con  el  método 
lastIndexOf(): 

/* Posición de la última letra "e" en el nombre (atención porque


la numeración empieza por 0) */
var posicion_ultima_e = nombre.lastIndexOf("e") + 1;
document.write("<br />La última ’e’ del nombre está en la posición: " +

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 21 -


posicion_ultima_e);

Para los métodos indexOf() y lastIndexOf(), la respuesta es 0 si no se encuentra ninguna ocurrencia. 

Pasemos a la sustitución de una subcadena por otra en una cadena de caracteres: 

/* Sustitución de una cadena de caracteres */


var origenNombre = nombre.replace("nge", "egn");
document.write("<br />Origen del nombre: " + origenNombre);

En este ejemplo, la subcadena "nge" se sustituye por "egn" con el método replace().  

También  es  frecuente  que  queramos  extraer  una  subcadena  a  partir  de  una  cadena  de  caracteres.  Hay  varios 
métodos disponibles para esto. 

Empecemos por el método slice(): 

/* Extracción de una subcadena con el método slice(posicion_inicio,


position_fin - 1) */
var apodo = nombre.slice(0, 4);
document.write("<br />Apodo (método slice): " + apodo);

El método  slice() asegura aquí la extracción del primer carácter (numerado con cero) hasta el quinto no incluido. 
Esto puede parecer sorprendente, por lo que la respuesta en nuestro caso será "Ánge". 

El método substr()también se usa: 

/* Extracción de una subcadena con el método substr(posicion_inicio,


longitud) */
apodo = nombre.substr(0, 4);
document.write("<br />Apodo (método substr): " + apodo);

Con  el  método  substr(),  el  segundo  argumento  tiene  un  significado  diferente;  se  trata  de  la  longitud  de  la 
subcadena extraída. La respuesta también será "Ánge". 

Para terminar, la tercera posibilidad es el uso del método substring(): 

/* Extracción de una subcadena con el método substring(posicion_inicio,


position_fin - 1) */
apodo = nombre.substring(0, 4);
document.write("<br />Apodo (método substring): " + apodo);

La  única  diferencia  entre  slice()  y  substring()  es  que  el  segundo  argumento  es  opcional  en  el  caso  del 
método  substring().  En  ausencia  del  segundo argumento  del  método  substring(),  la  extracción  se  hace 
hasta que el último carácter de la cadena se estudie. 

El método split() asegura la división de una cadena de caracteres en sus diferentes palabras: 

- 22 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Separación de una frase */
var autor = "Ángel Sánchez es el redactor de este libro";
var tablaAutor = autor.split(" ");
document.write("<br />El nombre del autor de este libro: " +
tablaAutor[1]);

En  el  mensaje  de  control,  se  reproduce  el  nombre  del  autor  (Ángel),  el  nombre  que  ha  sido  almacenado  en  la 
posición 1 de la tabla tablaAutor (no olvide la numeración de los elementos de las tablas a partir de cero). 

Veamos también cómo asegurar las conversiones de cadenas de caracteres en mayúsculas (método toUpperCase
()) y en minúsculas (método toLowerCase()): 

/* Conversión en mayúsculas */
document.write("<br />El apellido en mayúsculas: " +
apellido.toUpperCase());

/* Conversión en minúsculas */
document.write("<br />El nombre en minúsculas:
" + nombre.toLowerCase());

Para terminar, eliminamos los espacios no significativos al inicio y al final de la cadena de caracteres: 

/* Eliminación de los espacios no significativos al inicio y final


de la cadena de caracteres */
var identidad= " Ángel Sánchez ";
document.write("<br />Identidad con espacios no significativos:
" + "[" + identidad+ "]");
document.write("<br />Identidad sin espacios no significativos:
" + "[" + identidad.trim() + "]");

Los corchetes ([]) situados en los dos métodos document.write tienen como objetivo materializar la eliminación 
de los espacios no significativos (en el segundo caso) asegurado por el método trim(). 

La visualización obtenida es la siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 23 -


- 24 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack
Controles en la entrada de datos con JavaScript

1. Control de entrada de datos en un campo de texto

El objetivo aquí va a ser simple; controlar que el usuario ha realizado correctamente una entrada de datos por el 
teclado,  en  un  campo  de  tipo  texto,  dentro  de  un  formulario  HTML,  utilizando  para  ello  una  función  JavaScript.  En 
este primer script, no se comprueba el tipo de datos (numérico, alfanumérico, lógico...). Estos aspectos se verán en 
las siguientes secciones. 

Presentación del script HTML/JavaScript 

Para este script, se reproduce el código fuente completo a continuación: 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!-- NOMBRE DEL SCRIPT: FORM_01.htm


REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Gestión de formulario (control de entrada)
-->

<!-- Inicio script HTML -->


<html>
<!-- Inicio encabezado script HTML -->
<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type"
contenido="text/html; charset=utf-8" />
<!-- Título del script HTML -->
<title>FORM_01</title>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Función de comprobación de entrada */


function noVacio(campo, mensajeAlerta)
{
if (campo.value.length == 0)
{
/* Mostrar un mensaje de alerta */
alert(mensajeAlerta);
/* Foco en el campo con error */
campo.focus();
/* Valor de retorno */
return false;
}
/* Valor de retorno */
alert("Su nombre es "
+ document.getElementById(’nombre’).value);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


return true;
}

</script>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - FORM_01</h1>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Mostrar el nombre del script */


alert("FORM_01");

</script>

<!-- Formulario de entrada HTML -->


<form>
Su nombre (campo obligatorio):
<input
type=’text’
id=’nombre’
/>
<input
type=’button’
onclick="noVacio(document.getElementById(’nombre’),
’Entrada obligatoria’)"
value=’Comprobación de la entrada de datos’
/>
</form>

<!-- Mostrar el código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=’view-source:
’ + window.location">
Código fuente
</a>
</center>

</body>

</html>

Comentarios del script del formulario HTML 

En primer lugar, vemos el formulario HTML: 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<!-- Formulario de entrada HTML -->
<form>
Su nombre (campo obligatorio):
<input
type=’text’
id=’nombre’
/>
<input
type=’button’
onclick="noVacio(document.getElementById(’nombre’),
’Entrada obligatoria’)"
value=’Comprobación de la entrada de datos’
/>
</form>

En HTML, un formulario se delimita por las etiquetas  <form> ... </form>. Dentro de estas etiquetas se deben 


escribir las etiquetas específicas correspondientes a los controles de entrada de datos (widget) que queramos que 
aparezcan en el formulario: 

l Campo de entrada de datos simple 

l Campo de entrada de datos multilínea 

l Campo oculto (entrada de contraseña) 

l Botón de radio 

l Botón checkbox (casilla de selección) 

l Listas desplegables 

l Selector de archivo 

l Botones de función (envío, anulación...) 

En este libro, que trata principalmente de JavaScript, no está previsto ver en detalle las etiquetas de gestión de los 
diferentes  dispositivos  de  entrada  de  datos.  Encontrará  una  documentación  abundante  en  Internet  y  en  muchos 
libros dedicados a HTML. 

En contraposición, en los ejemplos que vienen a continuación, se comentará la etiqueta HTML <input>. 

En el script anterior, una primera etiqueta  <input> de tipo  text muestra en el formulario un campo rectangular 


en el que el usuario podrá realizar su entrada de datos: 

<input
type=’text’
id=’nombre’
/>

El valor text del atributo tipo sirve para indicar que se trata de una entrada de datos de tipo texto. En este campo 
de  entrada  de  datos,  puede  introducir  datos  de  tipo  texto,  numéricos  e  incluso  alfanuméricos.  El  control  de  la 
naturaleza de la entrada de datos es justamente el papel de una secuencia de código JavaScript. 

El atributo id es una información que permitirá identificar este campo de entrada de datos en el código JavaScript. 
El nombre lo elige libremente el programador, pero debe poder servir para su posterior identificación. La definición 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


de la zona de texto termina con un  />, que es una abreviatura de </input>. Recordemos que las etiquetas HTML 
están  emparejadas  muy  a  menudo,  de  tal  manera  que  la  etiqueta  de  apertura  se  escribe  genéricamente 
<etiqueta> y la de cierre </etiqueta>. 

En  lo  que  respecta  a  las  convenciones  de  escritura  a  nivel  del  HTML,  debe  saber  que  no  es  sensible  a  las 
mayúsculas/minúsculas (puede escribir sus etiquetas en MAYÚSCULAS o en minúsculas). En este libro, se ha hecho 
la elección arbitraria de presentar el código HTML en minúsculas. 

El  segundo  control  de  entrada  de  datos  es  un  botón  cuya  función  consiste  en  ejecutar  la  comprobación  del  valor 
introducido en la zona de texto, identificada por el id nombre: 

<input
type=’button’
onclick="noVacio(document.getElementById(’nombre’),
’Entrada obligatoria’)"
value=’Comprobación de la entrada de datos’
/>

El tipo del control es button. 

El  atributo  onclick  es  el  disparador  que  provoca  la  ejecución  del  código  integrado  en  las  comillas  que  siguen 
("noVacio(document.getElementById(’nombre’), ’Entrada obligatoria’)"). 

El atributo onclick precisa que la función JavaScript  noVacio (que estudiaremos más adelante) se ejecutará con 
un clic en el botón. Observe que, en nuestro ejemplo, el botón no se ha identificado con un nombre (se podría haber 
utilizado el atributo name para hacerlo) porque en nuestro caso este botón es el único de nuestro formulario. 

La función noVacio, que se llama con un clic en el botón, tiene dos argumentos: 

l document.getElementById(’nombre’), que indica el campo que se va comprobar por la función, 
l un  mensaje  (’Entrada obligatoria’),  que  se  mostrará  por  la  función  en  caso  de  que  no  haya  entrada  de 
datos en la zona de texto, identificada por el id nombre. 

Observe  también  las  restricciones  del  uso  de  las  comillas  en  la  formulación  de  la  operación  de  ejecución  en  el 
onclick. 

Comentarios del script de la función JavaScript noVacio 

Pasemos  ahora  a  estudiar  la  función  JavaScript  noVacio.  En  este  caso,  la elección  ha  sido  ubicar  el  script 
HTML/JavaScript  en  la  sección <head> ... </head>.  También  se  podría  haber  situado  en  la sección 
<body> ... </body>. Este ha sido a menudo el caso en los ejemplos del inicio de este libro. Para terminar, las 
funciones JavaScript se pueden ubicar en un archivo separado (identificado con un nombre) y hacer referencia a él 
desde el script actual. 

La  primera  línea  de  la  función  menciona  el  nombre  de  la  función  (noVacio),  así  como  el  nombre  de  los  dos 
argumentos  formales  alimentados  por  document.getElementById(’nombre’) y  por  ’Entrada
obligatoria’: 

function noVacio(campo, mensajeAviso)

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Posteriormente, se evalúa la longitud del texto introducido en la zona de texto nombre por la función length: 

if (campo.value.length == 0)

El  argumento  formal  campo  corresponde  evidentemente  a  la  zona  de  texto  y  value  es  la  propiedad  que 
representa al contenido de esta zona. 

Si  la  longitud  es  nula,  se  muestra  una  alerta  (’Entrada obligatoria’)  y  el  foco  se  sitúa  en  el  campo  de 
entrada de datos, para que se pueda hacer la entrada de datos ( método focus() aplicado a  campo). En caso 
contrario, se muestra el nombre (’Su nombre es ...’). 

Para que la ejecución de la función se interrumpa, obligatoriamente hay que prever un  return en cada caso. En 
nuestro script, no importa el valor devuelto (true, false...) porque no se ha previsto comprobar el valor devuelto 
más adelante. 

Resultado de la ejecución 

La ejecución de este script da el siguiente resultado, en caso de una validación sin entrada de datos en el campo de 
texto nombre: 

y este es el caso inverso (mensaje de confirmación mostrando el valor introducido): 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


2. Control del tipo numérico de una entrada de datos en un campo de texto

El objetivo es un poco diferente del perseguido en el ejemplo anterior. Aquí se aplicará un control de tipo numérico a 
la entrada de datos, que se hace en una zona de texto. 

Como  el  procesamiento  presenta  muchas  similitudes  con  el  script  anterior,  solo  se  presentará  y  comentará  una 
parte del script. 

Presentación del script del formulario HTML 

El código del formulario es el siguiente: 

<!-- Formulario de entrada HTML -->


<form>
Cantidad (entrada de un número entero, por favor):
<input
type=’text’
id=’numero’
/>
<input
type=’button’
onclick="esNumero(document.getElementById(’numero’),
’Indique un número entero, por favor’)"
value=’Validación entrada’
/>
</form>

El campo de entrada de datos de tipo text no es muy diferente del anterior; se llama numero. 

Para el botón de ejecución del control de tipo numérico, se construye la función esNumero, con dos argumentos: 

l document.getElementById(’numero’), que indica el campo que la función va a comprobar, 
l un  mensaje  (’Indique un número entero, por favor’),  que mostrará la función, en caso de que la 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


entrada de datos no sea un número entero. 

Presentación (parcial) del script de la función JavaScript esNumero 

En la función  esNumero, dentro de la sección  <head> ... </head>, se realiza una comprobación de la entrada 


de datos, con la siguiente secuencia de código: 

/* Definición de los valores aceptados */


var valoresAceptados = /ˆ[0-9]+$/;
/* Prueba de cardinalidad */
if (campo.value.match(valoresAceptados))
{
/* Valor de retorno */
alert("Ha indicado " + document.getElementById(’numero’).value);
return true;
}
else
{
/* Mostrar un mensaje de alerta */
alert(mensajeAlerta);
/* Poner el foco en el campo erróneo */
campo.focus();
/* Valor de retorno */
return false;
}
}

Se declara una variable valoresAceptados y se inicializa con una expresión regular, que contiene los caracteres 
aceptados para una entrada de datos de un número entero. 

Solo falta comprobar el contenido (propiedad  value) del campo, respecto a esta lista de signos aceptados (cifras 
de 0 a 9), para indicar un error de entrada de datos o no (visualización de una confirmación del valor de entrada de 
datos en este caso). 

En el marco de este libro, no está previsto presentar de manera exhaustiva las múltiples posibilidades ofrecidas por 
las expresiones regulares. Puede consultar muchos recursos en Internet sobre este tema, fundamentalmente: 

l http://www.w3schools.com/jsref/jsref_obj_regexp.asp  

l https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/RegExp  

l http://www.javascriptkit.com/javatutors/re.shtml  

Resultado de la ejecución 

Si no se introduce un valor, se muestra el siguiente mensaje: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


En caso de una entrada de datos correcta, obtenemos: 

3. Control de caracteres alfabéticos de una entrada de datos en un campo de texto

Como se puede imaginar, el problema es parecido al del ejemplo anterior. 

La diferencia se va a presentar a nivel de la expresión regular (la variable valoresAceptados):  

/* Definición de los valores aceptados */


var valoresAceptados = /ˆ[a-zA-Z]+$/;

Los valores aceptados serán únicamente las letras del alfabeto, tanto en mayúsculas como en minúsculas. 

4. Control de caracteres alfabéticos y numéricos de una entrada de datos en un campo 
de texto

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Aquí,  para  controlar  que  el  usuario  pueda  introducir  tanto  cifras  enteras  como  cadenas  alfabéticas  (minúsculas  o 
mayúsculas), la expresión regular se modificará como sigue: 

/* Definición de los valores aceptados */


var valoresAceptados = /ˆ[0-9a-zA-Z]+$/;

Evidentemente,  el  resto  de  los  signos,  como  los  caracteres  acentuados,  por  ejemplo,  serán  rechazados  por  la 
función de comprobación. 

5. Control de la longitud de una entrada de datos en un campo de texto

Este problema es frecuente, fundamentalmente cuando se trata de forzar una entrada de datos de una contraseña 
de un tamaño mínimo o máximo. 

El código del formulario HTML es el siguiente: 

<form>
Campo (entre 5 y 10 caracteres obligatoriamente):
<input
type=’text’
id=’entrada’
/>
<input
type=’button’
onclick="longitudEntrada(document.getElementById(’entrada’),
5, 10, ’Escriba entre 5 y 10 caracteres, por favor’)"
value=’Comprobación de la entrada’
/>
</form>

La función longitudEntrada tiene cuatro argumentos: 

l document.getElementById(’entrada’), donde entrada es el nombre del campo de texto, 
l 5, el valor mínimo de la longitud aceptada para la entrada de datos, 
l 10, el valor máximo de la longitud aceptada para la entrada de datos, 
l ’Escriba entre 5 y 10 caracteres, por favor’, es el mensaje de error que se ha de mostrar en 
caso de error. 

A nivel de la función JavaScript longitudEntrada, el código es: 

/* Comprobación de la longitud de la entrada de datos */


if (campo.value.length >= longitudMinima && campo.value.length <=
longitudMaxima)

6. Control de entrada de datos en una dirección de e­mail

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Una  vez  más,  se  trata  de  aplicar  un  control  basado  en  una  expresión  regular  para  comprobar  la  estructura  de  la 
dirección que introduce el usuario. Como es evidente, no habrá comprobación de una dirección de e­mail realmente 
asociada a un usuario. 

La comprobación se hace respecto a la siguiente expresión regular: 

/* Definición de los valores aceptados */


var valoresAceptados = /ˆ[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-
9]{2,4}$/;

El control se realiza como sigue, con el uso del método match: 

/* Comprobación de la estructura de la dirección de e-mail */


if (email.value.match(valoresAceptados ))
{
/* Valor de retorno */
alert("Estructura de dirección de e-mail correcta");
return true;
}
else
{
/* Visualización de un mensaje de alerta */
alert(mensajeAviso);
/* Foco en el campo de error */
email.focus();
/* Valor de retorno */
return false;
}

7. Control de la selección de una lista desplegable  (versión simplificada)

Abandonamos  ahora  los  campos  de  tipo  text,  cuyos  los  controles  pueden  ser  múltiples  usando  expresiones 
regulares, para abordar las listas desplegables (o listas de selección). 

Presentación del script del formulario HTML 

El código del formulario HTML se presenta como sigue: 

<!-- Formulario de entrada HTML -->


<form>
Deporte que practica:
<select id=’lista’>
<option>Su deporte favorito</option>
<option>Golf</option>
<option>Fútbol</option>
<option>Natación</option>
<option>Tenis</option>
</select>
<input

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


type=’button’
onclick="controlarEleccionLista(document.getElementById(’lista’),
’Seleccione un deporte en la lista’)"
value=’Comprobación de la entrada de datos’
/>
</form>

La etiquetas  <select> ... </select> engloban las opciones propuestas para la elección del usuario. La lista 


desplegable, identificada por el id lista, se pasa como argumento a la función controlarEleccionLista, con 
un clic en el botón habitual de envío. 

Presentación del script JavaScript de la función controlarEleccionLista 

El código de la función controlarEleccionLista se muestra completo esta vez: 

/* Función que comprueba si se ha hecho una elección en una lista


desplegable */
function controlarEleccionLista(lista, mensajeAlerta)
{
if (lista.value == "Su deporte favorito")
{
/* Mostrar un mensaje de alerta */
alert(mensajeAlerta);
/* Poner el foco en el campo erróneo */
lista.focus();
/* Valor de retorno */
return false;
}
else
{
/* Valor de retorno */
alert("Su deporte favorito: " + lista.value);
// alert("Su deporte favorito: "
// + document.getElementById(’lista’).value);
return true;
}
}

El  código  de  esta  función  no  presenta  dificultades  particulares.  El  valor  asociado  a  la  elección  realizada  se 
comprueba  al  inicio  del  procesamiento.  Si  la  elección  es  siempre  el  valor  inicial  (Su deporte favorito),  se 
muestra el mensaje de alerta habitual. En caso contrario, se presenta la etiqueta seleccionada. 

Resultado de la ejecución 

El  resultado  obtenido  de  la  ejecución  es  el  siguiente  si  se  hace  clic  en  el  botón Comprobación  de  la  entrada  de 
datos sin haber seleccionado nada de la lista desplegable: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


Si se realiza una selección, la visualización se presenta como sigue: 

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


8. Control de la selección en una lista desplegable  (versión extendida)

En el ejemplo anterior, en la lista (<select> ... </select>), solo se incluía el atributo básico  id. Hay otros 


atributos disponibles: 

l <option selected>opción por defecto</option>,  para  indicar  que  una  opción  particular  será 
seleccionada por defecto. 

l <select name="miLista" size="5">, para indicar que en la lista serán visibles cinco opciones. Para ver 


el resto, será necesario desplegar el scroll. 

l <select name="miLista" multiple>,  para  especificar  que  se  pueden  seleccionar  varias  opciones 
simultáneamente en la lista. 

La  etiqueta  <optgroup> ... </optgroup>  también  permite  dividir  una  lista  desplegable  en  niveles 
jerárquicos. 

Presentación del script del formulario HTML 

<!-- Formulario de entrada de datos HTML -->


<form name=’formulario’>
Deporte practicado:
<select id=’lista’ size =’7’ multiple>
<optgroup label=" Deportes de equipo ">
<option value="futbol" selected>Fútbol</option>
<option value="voley">Voley Ball</option>
</optgroup>
<optgroup label=" Deportes individuales ">
<option value="golf">Golf</option>
<option value="natacion" selected>Natación</option>
<option value="tenis">Tenis</option>
</optgroup>
</select>
<input
tipo=’button’
onclick="controlarEleccionLista(document.getElementById(’lista’))"
value=’Validación entrada’
/>
</form>

La  lista  desplegable  se  divide  en  dos  grupos,  con  etiquetas  ’Deportes de equipo’  y  ’Deportes
individuales’.  La  lista  se  desplegará  totalmente  porque  se  prevén  siete  líneas  de  visualización  (dos  líneas 
para  los  grupos  y  cinco  deportes)  por  la  integración  del  atributo  size=7.  En  cada  uno  de  los  grupos,  se 
preselecciona un deporte (atributo selected) y es posible la entrada de datos de varios deportes al mismo tiempo 
(atributo multiple). 

La  función  a  la  que  se  llama  con  un  clic  en  el  botón  de  envío  es  controlarEleccionLista  y  tiene  un  único 
argumento, el identificador de la lista. 

Presentación del script JavaScript de la función controlarEleccionLista 

El código fuente de la función controlarEleccionLista se presenta íntegramente a continuación: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


/*
Función que muestra las opciones (múltiples) terminadas
en una lista desplegable
*/
function controlarEleccionLista(lista)
{
for ( i = 0; i < document.forms.formulario.lista.options.length; i++)
{
if (document.forms.formulario.lista.options[i].selected)
{
alert("Deporte seleccionado: " +
document.forms.formulario.lista.options[i].text)
}
}
// Valor de retorno
return true
}

Un  bucle  for  recorre  los  cinco  deportes  propuestos  en  la  lista  desplegable.  La  secuencia 
document.forms.formulario.lista.options.length  determina  justamente  el  número  de  opciones 
presentes  en  la  lista  desplegable  de  nombre  lista,  del  formulario  de  nombre  formulario  (cf.  <form
name=’formulario’>, en la descripción del formulario en HTML). 

Posteriormente, options[i].selected permite comprobar si el usuario ha mantenido la opción o no y, si se da 
el caso, mostrar la etiqueta del deporte seleccionado (atributo text). 

Resultado de la ejecución  

El resultado obtenido con la ejecución es el siguiente: 

Las dos confirmaciones siguientes aparecen cuando se hace la validación con el botón Validación entrada: 

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


9. Control de selección con un botón de radio

Ofrecer  una  selección  entre  varias  opciones  con  un  conjunto  de  botones  de  radio  es  una  solución  interesante. 
Constituye una alternativa a la selección simple en una lista desplegable, en la medida en que la selección de un 
conjunto de botones de radio no permite la multiselección. 

Presentación del script del formulario HTML 

<!-- Formulario de entrada HTML -->


<form name="lista_deportes">
Deporte favorito: <br />
<input
type="radio"
name="deportes"
value="golf">
Golf
</input><br />
<input
type="radio"
name="deportes"
value="futbol">
Fútbol
</input><br />
<input
type="radio"
name="deportes"
value="natacion">
Natación
</input><br />
<input
type="radio"
name="deportes"
value="tenis">

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


Tenis
</input><br />
<input
type=’button’
onclick="seleccionarDeporte
(’Seleccione su deporte favorito’)"
value=’Comprobación de la entrada’
/>
</form>

Una vez más, nuestro formulario se debe llamar a nivel de la etiqueta form: 

<form name="lista_deportes">

Después hay un título para el conjunto de botones: 

Deporte favorito:<br />

y se presenta la lista de botones de radio: 

<input
type="radio"
name="deportes"
value="golf">
Golf
</input>

El tipo para las etiquetas  input es  radio y se indica un nombre común (atributo  name;  deportes, en nuestro 


caso). El atributo value se rellena con un valor diferente para cada botón. Para terminar, un comentario (Golf en 
nuestro ejemplo) termina la sintaxis. 

Para  la  función  seleccionarDeporte,  asociada  al  evento  onclick  del  botón  de  envío,  solo  se  prevé  un 
argumento, un mensaje de alerta, que se mostrará en caso de que no se seleccione ningún botón de radio: 

<input
type=’button’
onclick="seleccionarDeporte
(’Seleccione su deporte favorito’)"
value=’Comprobación de la entrada’
/>

Presentación del script JavaScript de la función seleccionarDeporte 

El  script  JavaScript,  relativamente  largo,  de  la  función  seleccionarDeporte  se  reproduce  completamente  a 
continuación: 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/*
Función de comprobación del valor seleccionado
en un conjunto de botones de radio
*/
function seleccionarDeporte(mensajeAlerta)
{
/*
Recuperación de los deportes propuestos
en el formulario en una tabla
*/
var tabDeportes = document.forms.lista_deportes.deportes;
/* Determinación del número de deportes propuestos */
var numeroDeportes = tabDeportes.length;
// alert("Número de deportes: " + numeroDeportes);
if (numeroDeportes > 0)
{
/* Recorrido de la tabla de los deportes propuestos */
var i = 0;
var deporteSeleccion = false;
while (i < numeroDeportes)
{
/* Prueba si el deporte es el seleccionado */
if (tabDeportes[i].checked)
{
alert("Su deporte favorito es " + tabDeportes[i].value);
/* Modificación del booleano deporteSeleccion a true*/
deporteSeleccion = true;
}
i = i + 1;
}
}
/* Mensaje de alerta si no se ha seleccionado ningún deporte */
if (!deporteSeleccion)
{
/* Mensaje de alerta */
alert(mensajeAlerta);
/* Valor de retorno */
return false;
}
else
{
/* Valor de retorno */
return true;
}
}

El  procesamiento  empieza  recuperando  en  una  tabla  la  lista  de  los  botones  de  radio  integrados  en  el  formulario 
HTML: 

/* Recuperación de los deportes propuestos en el formulario en una tabla */


var tabDeportes = document.forms.lista_deportes.deportes;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


La sintaxis  lista_deportes.deportes indica que se hace referencia al conjunto de botones de radio llamados 
deportes del formulario de nombre lista_deportes. 

El número de deportes propuestos en el formulario HTML se determina a continuación: 

/* Determinación del número de deportes propuestos */


var numeroDeportes = tabDeportes.length;

Para terminar, un bucle  while recorre los diferentes botones de radio para determinar si han sido seleccionados o 
no  (normalmente  solo  uno).  Observe  que,  en  caso  de  no  selección,  también  se  ha  previsto  un  control  con  una 
estructura condicional. 

Si el botón de radio se ha seleccionado: 

if (tabDeportes[i].checked)

entonces se muestra su nombre (atributo value): 

alert("Su deporte favorito es " + tabDeportes[i].value);

Un último mecanismo basado en una variable booleana deporteSeleccion también permite mostrar un mensaje 
de alerta (la variable mensajeAviso pasado como argumento a la función) si no se ha seleccionado ningún botón 
de radio. 

/* Mensaje de alerta si no se ha seleccionado ningún deporte */


if (!deporteSeleccion)
{
// ...
}
else
{
// ...
}

Resultado de la ejecución 

El resultado obtenido con la ejecución es el siguiente: 

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La confirmación siguiente aparece cuando se hace la validación con el botón Comprobación de la entrada: 

10. Control de la selección con casillas de selección

La selección dentro de un conjunto de casillas de selección presenta similitudes con la selección con botones radio. 
La principal diferencia es que, en este caso, es posible la selección múltiple. 

Presentación del script del formulario HTML 

<form name="lista_deportes">
Deportes favoritos:<br />
<input
tipo="checkbox" name="deportes[]" value="golf">Golf
</input><br>
<input
tipo="checkbox" name="deportes[]" value="futbol">Fútbol
</input><br>
<input
tipo="checkbox" name="deportes[]" value="natacion">Natación
</input><br>
<input
tipo="checkbox" name="deportes[]" value="tenis">Tenis
</input><br>
<input
tipo=’button’

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


onclick="seleccionDeportes
(’Seleccione sus deportes favoritos’)"
value=’Comprobación de la entrada’
/>
</form>

Como sucede con los botones de radio, el formulario se llama  lista_deportes (el atributo  name tiene el valor 


fijo).  El  atributo  type  es  checkbox  (en  lugar  de  radio).  El  atributo  name  es  una  tabla  ( deportes[])  y  cada 
input tiene su propio valor en value y se llama de manera diferente. 

La  programación  del  botón  de  envío  es  casi  idéntica  a  la  del  apartado  anterior.  Se  llama  a  una  función 
seleccionDeportes con un mensaje de alerta como argumento. 

Presentación del script JavaScript de la función seleccionDeportes 

El código de la función se muestra aquí íntegramente, aunque sea muy parecido al visto en el párrafo anterior. 

/*
Función de comprobación de los valores seleccionados
en un conjunto de casillas de selección
*/
function seleccionDeportes(mensajeAlerta)
{
/*
Recuperación de los deportes propuestos
en el formulario en una tabla
*/
var tabDeportes = document.forms.lista_deportes.elements["deportes[]"];
/* Determinación del número de deportes propuestos */
var numeroDeportes = tabDeportes.length;
// alert("Número de deportes: " + numeroDeportes);
/* Recorrido de la tabla de los deportes propuestos */
var i = 0;
var numeroDeportesSeleccionados = 0;
while (i < numeroDeportes)
{
/* Prueba si el deporte se ha seleccionado */
if (tabDeportes[i].checked) {
/* Incremento del número de deportes seleccionados */
numeroDeportesSeleccionados = numeroDeportesSeleccionados + 1;
alert("Su deporte favorito es " + tabDeportes[i].value);
}
i = i + 1;
}
/* Mensaje de alerta si no se ha seleccionado ningún deporte */
if (numeroDeportesSeleccionados == 0) {
/* Mensaje de alerta */
alert(mensajeAlerta);
/* Valor de retorno */
return false;
} else {
/* Valor de retorno */

- 20 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


return true;
}
}

Algo específico es, sin duda, la recuperación de los deportes mostrados en el formulario HTML: 

/*Recuperación de los deportes propuestos en el formulario en una tabla */


var tabDeportes = document.forms.lista_deportes.elements["deportes[]"];

Resultado de la ejecución 

El resultado obtenido cuando se ejecuta el script es el siguiente: 

Las siguientes confirmaciones aparecen cuando se ejecuta la validación con el botón Comprobación de la entrada: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 21 -


- 22 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack
Introducción

1. Definición del DOM

DOM  (Modelo  de  Objeto  de  Documento  o  Document  Object  Model)  es  el  modelo  de  acceso  a  los  diferentes 
componentes de los documentos HTML e incluso XML. 

En  el  capítulo  Exploración  del  flujo  XML  vía  DOM,  veremos  en  detalle  cómo  explotar  el  flujo  XML  en  los  scripts 
JavaScript. 

Gracias al DOM, dispone de una descripción estructurada del script HTML, y también proporciona el modo de acceso 
a los elementos constitutivos del modelo. 

Como desarrollador, este será un gran aliado para acceder a estos elementos y manipularlos con un lenguaje de 
programación (JavaScript, por ejemplo, pero no en exclusiva). 

DOM va a ser para nosotros un esquema de acceso a las partes que forman una página Web (formulario, campo...) 
con etiquetas de marcado. 

Este modelo proporciona una jerarquía de programación que organiza las propiedades, métodos y eventos. 

El  estudio  y  la  correcta  comprensión  del  modelo  DOM  son  indispensables  para  poder  utilizar  lo  mejor  posible  las 
principales librerías JavaScript, como Prototype, jQuery, MooTools... 

El  modelo  DOM  es  un  árbol  formado  por  objetos  Node  (nodos).  Se  trata  de  una  estructura  arborescente  con  un 
nodo de tipo raíz y nodos hijo. En el siguiente ejemplo (script HTML), el nodo head es un hijo del nodo  <html>. El 
nodo  <head>  es  padre  del  nodo <title>.  Las  etiquetas  <input>  integradas  en  la  sección  <body> ...
</body>  representan  un  ejemplo  de  nodos  del  mismo  nivel,  que  tienen  un  mismo  padre,  el  formulario  llamado 
formulario_entrada. 

<html>
<head>
<title>
</title>
</head>
<body>
<form name="formulario_entrada ">
<input ... </input>
<input ... </input>
</form>
</body>
</html>

El modelo DOM es aplicable a cualquier documento de tipo XML. 

2. Definición de la arborescencia

Noción de nodo 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Un  lenguaje  de  marcado  como  HTML  o  cualquier  otro  lenguaje  basado  en  XML  se  puede  esquematizar  como  una 
arborescencia jerárquica. Los diferentes componente de una arborescencia como esta son nodos del árbol. Por este 
motivo, el objeto central del modelo DOM es el objeto Node. Los otros nodos dependen de él. 

Interfaz Node 

La interfaz Node va ser nuestra caja de herramientas para recorrer los diferentes niveles de la arborescencia DOM. 
Está formada por propiedades y métodos para asegurar los movimientos en el árbol. 

Las propiedades (clasificadas por orden alfabético) 

l atributes: lista de atributos del nodo actual. 
l childNodes: lista de nodos hijos. 
l firstChild: primer hijo de un nodo. 
l lastChild: último hijo de un nodo. 
l nextSibling: siguiente nodo del mismo tipo. 
l nodeName : nombre del nodo. 
l nodeType: tipo del nodo. 
l nodeValue: valor contenido en el nodo. 
l padreNode: nodo padre. 
l previousSibling: nodo anterior de un tipo concreto. 

Los métodos (clasificados por orden alfabético) 

l appendChild(): adición de un nodo hijo. 
l cloneNode(): duplicación de un nodo. 
l deleteData(): borrado de datos en caracteres. 
l getAtribute(): búsqueda del valor de un nodo atributo. 
l getAtributeNode(): búsqueda de un nodo atributo. 
l hasChildNodes(): control de la existencia de nodos hijos. 
l insertBefore(): inserción de un nodo. 
l removeAtribute(): borrado del valor de un nodo atributo. 
l removeAtributeNode(): borrado de un nodo atributo. 
l removeChild(): eliminación de un nodo. 
l replaceChild(): sustitución de un nodo hijo. 
l setAtribute(): definición del valor de un nodo atributo. 
l setAtributeNode(): definición de un nodo atributo. 

El  objeto  document  es  la  raíz  de  todos  los  nodos  de  un  script  Web.  Este  objeto  particular  tiene  sus  propios 
métodos, que se aplican al documento en su globalidad: 

l createElement: creación de un nuevo elemento en la arborescencia. 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


l createTextNode: creación de un nodo de tipo texto. 
l createAtributo: creación de un nodo de tipo atributo. 
l getElementById:  recuperación  del  elemento  con  un  id  especificado  (ya  muy  estudiado  en  los  ejemplos 
anteriores del libro). 

l getElementsByName: recuperación del elemento que tiene el nombre específico. 
l getElementsByTagName: recuperación del elemento con un tag específico. 

Ejemplo 

Dado  un  documento  Web  con  un  tag  div, con el atributo  id  igual  a  ’container’, vamos  a  poner  dentro  otra 
capa (div) con el texto ’Buenos días, mundo’: 

// Búsqueda del elemento div con identificador container


var antiguoContainer = document.getElementById(’container’);

// Creación en memoria de un elemento div


var nuevaDiv = document.createElement(’div’);

// Creación del nodo de tipo texto


var textoDiv = document.createTextNode(’Buenos días, mundo’);

// Asignación del nodo textoDiv al nodo nuevaDiv


nuevaDiv.appendChild(textoDiv);

// Integración del nuevo div


antiguoContainer.appendChild(nuevaDiv);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Aprendizaje del modelo DOM

En  una  serie  de  ejemplos,  vamos  a  ver  cómo  es  posible  con  JavaScript  escribir  texto  (y  elementos  DOM  más 
complejos) en un documento HTML. 

1. Script "Hello World"

En  este  primer  script,  vamos  a  ver  cómo  mostrar  una  cadena  de  caracteres  "Hello  World",  en  el  cuerpo  del 
documento HTML, añadiendo también etiquetas de formato (negrita). 

El siguiente script no está escrito en su integridad; solo se muestra la secuencia JavaScript en cuestión, integrada 
en la sección HTML <body> del script: 

<!-- Inicio script JavaScript -->


<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("DOM_01");

/* Visualización Hello World! con el método document.write */


document.write("Hello World!<br />");

/* Visualización Hello World! con el método document.write */


/* palabra World en negrita */
document.write("Hello <b>World!</b>");

</script>

Cuando se ejecuta el script, se obtiene la visualización, con el método  alert, de un cuadro de diálogo con el título 
del ejercicio (DOM_01): 

En  este  ejemplo,  se  ve  cómo  integrar  en  la  secuencia  que  se  va  a  mostrar  etiquetas  de  formato  como  <b> ...
</b>  (negrita).  En  realidad,  todas  las  etiquetas  y  atributos  de  etiquetas  HTML  se  pueden  integrar  en  el  método 
document.write. En general, se puede construir todo el documento HTML programándolo con JavaScript. 

2. Diferencia entre write y writeln

En este pequeño ejemplo, vamos a ver la diferencia entre los métodos write y writeln.  

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


<!-- Inicio script JavaScript -->
<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("DOM_02");

/* Diferencia entre document.write y document.writeln */


/* NB1: Con el método writeln el retorno de carro
de fin de línea está implícito */
/* NB2: El método writeln necesita estar dentro
de la secuencia por un conjunto de <pre> ... </pre> */
document.write("<pre>");
document.write("Línea número 1<br />");
document.write("Línea número 2<br />");
document.write("Línea número 3<br /><br />");
document.writeln("Línea número 4");
document.wrteln("Línea número 5");
document.write("Línea número 6");
document.write("</pre>");

</script>

La visualización de lo que se obtiene en la sección body cuando se ejecuta este script, es la siguiente: 

Con el método write, para ir a la línea siguiente, hay que integrar explícitamente una etiqueta  <br /> (break) al 


final del mensaje que se ha de escribir. Esta restricción no es necesaria para el método writeln. 

Observe también que el método  writeln necesita estar dentro de la secuencia por un conjunto de  <pre> ...


</pre>. 

3. Gestión de los enlaces hipertextos

En este nuevo ejemplo, aprenderemos a gestionar los enlaces hipertextos. La secuencia de código se integra una 
vez más en la sección HTML <body> del script: 

<!-- Definición de varios enlaces "hypertexto" consecutivos

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


en el documento -->
Motor de búsqueda <a href="http://www.google.es"
id="google">Google</a><br />
Sitio de información <a href="http://www.yahoo.es"
id="yahoo">Yahoo</a><br />
Enciclopedia <a href="http://www.wikipedia.es"
id="wikipedia">Wikipedia</a>

<!-- Inicio script JavaScript -->


<script type=’text/JavaScript’>

/* Salto de líneas */
document.write("<br /><br />");

/* Mostrar el número de enlace(s) ’hipertexto’ del documento */


document.write("Número de enlace(s) ’hipertexto’ del documento: " +
document.links.length + "<br />");

/* Mostrar el identificador del segundo enlace ’hipertexto’


del documento */
document.write("Identificador del segundo enlace ’hipertexto’
del documento: " + document.links[1].id + "<br />");

/* Mostrar la URL del tercer enlace ’hipertexto’ del documento */


document.write("URL del tercer enlace ’hipertexto’ del documento: "
+ document.links[2].href);

</script>

Se programan tres enlaces hipertextos (google, yahoo y wikipedia) con etiquetas HTML <a href> ... </a>. 

Posteriormente, se muestra el número de enlaces del documento, el identificador del segundo enlace y la URL del 
tercer enlace: 

La numeración de los enlaces se realiza de 0 a n­1. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


4. Gestión de las imágenes

Vamos  a  aprender  a  gestionar  imágenes  con  un  ejemplo.  La  secuencia  de  código  se  integra  en  la  sección  HTML 
<body> del script: 

<!-- Definición de varias imágenes consecutivas en el documento-->


<img
id="van_van_1" border="1" src="van_van_01.png"
width="150" height="100">
</img><br /><br />
<img
id="van_van_2" border="2" src="van_van_02.png"
width="150" height="100">
</img><br /><br />
<img
id="van_van_3" border="1" src="van_van_03.png"
width="150" height="100">
</img><br /><br />
<img
id="van_van_4" border="2" src="van_van_04.png"
width="220" height="150">
</img><br /><br />

<!-- Inicio script JavaScript -->


<script type="text/JavaScript">

/* Mostrar el número de imagen o imágenes del documento */


document.write("Número de imagen o imágenes del documento: "
+ document.images.length + "<br />");

/* Mostrar el identificador de la primera imagen */


document.write("Identificador de la primera imagen: "
+ document.images[0].id + "<br />");

/* Mostrar el atributo border de la segunda imagen */


document.write("Atributo border de la segunda imagen: "
+ document.images[1].border + "<br />");

/* Mostrar el atributo src de la tercera imagen */


document.write("Atributo src de la tercera imagen: "
+ document.images[2].src + "<br />");

/* Mostrar los atributos width y height de la cuarta imagen */


document.write("Atributo width de la cuarta imagen: "
+ document.images[3].width + "<br />");
document.write("Atributo height de la cuarta imagen: "
+ document.images[3].height + "<br />");

</script>

Cuatro imágenes se presentan con etiquetas HTML <img>, con determinados atributos (id, border, src, width, 
height). 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Posteriormente, se muestra diferente información respecto a estas imágenes: 

l el número de imágenes del documento; 

l los atributos de las imágenes. 

La numeración de las imágenes se realiza de 0 a n­1. 

La ejecución del script da el siguiente resultado: 

5. Gestión de formularios y de sus etiquetas

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


En este ejemplo, vamos a ver cómo gestionar los formularios y las etiquetas integradas en estos formularios. Para 
limitar las explicaciones, solo se ubicarán en los diferentes formularios etiquetas HTML input. 

El código (parcial) del script es el siguiente: 

<!-- Definición de varios formularios consecutivos en el documento-->


<b>Formulario número1:</b>
<form name="form1" id="idForm1" method="post">
Campo 1: <input type="text" id="campo1" size="20"><br />
Campo 2: <input type="text" id="campo1" size="20"><br />
</form>
<br />
<b>Formulario número2:</b>
<form name="form2" id="idForm2">
Campo 3: <input type="text" id="campo3" size="20"><br />
Campo 4: <input type="text" id="campo4" size="20"><br />
</form>
<br />
<b>Formulario número3:</b>
<form name="form3" id="idForm3">
Campo 5: <input type="text" id="campo5" size="20"><br />
Campo 6: <input type="text" id="campo6" size="20"><br />
</form>
<br /><br />

<!-- Inicio script JavaScript -->


<script type="text/JavaScript">

/* Mostrar el número de formulario(s) del documento */


document.write("Número de formulario(s) del documento: "
+ document.forms.length + "<br />");

/* Mostrar el nombre del primer formulario */


document.write("Nombre del primer formulario: "
+ document.forms[0].name + "<br />");

/* Mostrar el identificador del segundo formulario */


document.write("Identificador del segundo formulario: "
+ document.forms[1].id + "<br />");

</script>

En este script, se visualiza diferente información de los formularios y las etiquetas input integradas en ellos: 

l Número de formulario(s) del documento: 

document.write("Número de formulario(s) del documento: "


+ document.forms.length + "<br />");

l Nombre del primer formulario: 

document.write("Nombre del primer formulario: "

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


+ document.forms[0].name + "<br />");

l Identificador del segundo formulario: 

document.write("Identificador del segundo formulario: "


+ document.forms[1].id + "<br />");

El script no presenta dificultades particulares. Tenga en cuenta las siguientes observaciones: 

l La numeración de los formularios se realiza de 0 a n­1. 

l La propiedad length indica el número de elementos de cada colección (forms, input...). 

La ejecución del script da el siguiente resultado: 

6. Gestión de los anchors

Ahora  veamos  cómo  gestionar  los  anchors  con  un  pequeño  ejemplo.  El  siguiente  código  (parcial)  se  sitúa  en  la 
sección HTML <body> de nuestro script: 

<!-- Definición de anchors (pueden estar seguidos por un href) -->


<a name="html">Curso número1 (HTML)</a><br />
<a name="css">Curso número2 (CSS)</a><br />
<a name="xml">Curso número3 (XML)</a><br />

<!-- Definición de un enlace hipertexto a google.es (no se

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


contabilizará como un anchor) -->
Acceso a un <a href="http://www.google.es">complemento del curso</a>
(cf. motor de búsqueda google)

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Salto de línea */
document.write("<br /><br />");

/* Mostrar el número de anchor(s) del documento */


document.write("Número de anchor(s) del documento: " +
document.anchors.length + "<br />");

/* Mostrar el título del primer anchor del documento */


document.write("primer anchor del documento: "
+ document.anchors[0].text + "<br />");

/* Mostrar el nombre del segundo anchor del documento */


document.write("segundo anchor del documento: "
+ document.anchors[1].name);

</script>

En este script se programan tres anchors HTML: 

<a name="html">Curso número1 (HTML)</a><br />


<a name="css">Curso número2 (CSS)</a>
<a name="xml">Curso número3 (XML)</a>

En general, los enlaces de hipertexto apuntan a scripts externos (encadenamiento entre páginas de un mismo sitio 
o  entre  sitios  web  diferentes)  con  una  sintaxis  <a href="dirección absoluta/dirección relativa
de la página destino ">Nombre del enlace </a>. 

En nuestro script, también hubiera sido posible programar accesos a los tres anchors (aquí no se ha hecho) con una 
formulación  del  tipo  <a href="#nombre_anchor">nombre del enlace </a>.  Por  ejemplo,  en  nuestro 
caso, para el primer anchor sería: 

<a href="#html">Acceso a la explicación de HTML</a>

Por el contrario, se ha utilizado un enlace hipertexto que apunta a http://www.google.es: 

Acceso a un <a href="http://www.google.es">complemento del curso </a>


(cf. motor de búsqueda google)

En la sección JavaScript de nuestra página, encontrará el recuento del número de anchors de la página: 

document.write("Número de anchor(s) del documento: "

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


+ document.anchors.length + "<br />");

y después la visualización del título del primer anchor: 

document.write("primera anchor del documento: "


+ document.anchors[0].text + "<br />");

y del nombre del segundo anchor: 

document.write("segundo anchor del documento: "


+ document.anchors[1].name);

Cuando se ejecuta el script, la visualización obtenida es: 

El enlace a http://www.google.es no se contabiliza como anchor. 

7. Gestión de la navegación entre páginas Web

Vamos a abordar la navegación entre páginas Web. No nos centraremos en las técnicas más avanzadas de paso de 
argumentos entre páginas ni en los mecanismos de conservación de información (persistencia). Para que sirva de 
ejemplo, encontrará más adelante en este libro un capítulo dedicado a la gestión de cookies (cf. capítulo Gestión de 
las cookies en JavaScript). 

Las cookies se presentan como pequeños archivos de texto, que pueden contener un número limitado de datos. Esta 
técnica  puede  ser  interesante  para  conservar  contenidos  de  variables  en  memoria,  reutilizables  a  lo  largo  de  la 
navegación, a través de muchas páginas de su sitio Web (conservación de identificadores, contraseñas, preferencias de 
usuario...). 

En el marco de este ejemplo, se van a implementar dos scripts. 

El código fuente (situado en la sección HTML <body>) del primer script se presenta a continuación: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


<!-- Inicio script JavaScript -->
<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("DOM_07_1");

/* Enlace hipertexto que da acceso al document DOM_07_2.htm */


document.write("Acceso al documento <a
href=’DOM_07_2.htm’>DOM_07_2.htm</a><br />");

/* Enlace hipertexto que da acceso al document DOM_07_3.htm */


document.write("Acceso al document <a href=’DOM_07_3.htm?libro=ENI
JavaScript’>DOM_07_3.htm (paso de un argumento)</a>");

</script>

El  script  anterior  no  tiene  ninguna  particularidad.  Evidentemente,  los  dos  enlaces  definidos  que  dan  acceso  a  las 
páginas DOM_07_02.htm y DOM_07_03.htm se habrían podido programar en HTML. 

El  segundo  enlace  llama  al  script  DOM_07_03.htm,  pasándole  un  argumento  llamado  libro,  con  el  valor  "ENI
JavaScript": 

<a href=’DOM_07_3.htm?libro=ENI JavaScript’>DOM_07_3.htm


(paso de un argumento)</a>

La visualización da el siguiente resultado: 

Pasemos ahora al segundo script ( DOM_07_2.htm), llamado por el documento principal DOM_07_1.htm. El código 
(en la sección HTML <body>) se muestra parcialmente a continuación: 

<!-- Inicio script JavaScript -->


<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("DOM_07_2");

/* Visualización de la URL de la página que da acceso al documento */


document.write("URL de la página que da acceso al documento: "
+ document.referrer);

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


</script>

La URL del documento que llama se mostrará en este script: 

document.write("URL de la página que da acceso al documento: "


+ document.referrer);

En nuestro caso, la visualización da como resultado: 

Terminemos  con  el  tercer  script  (DOM_07_3.htm),  al  que  también  se  llama  desde  el  documento  principal 
DOM_07_1.htm, pero esta vez pasando un argumento. La reproducción del código fuente es más completa porque 
el JavaScript se sitúa en la sección HTML <head> y en la sección HTML <body>: 

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type"
contenido="text/html; charset=utf-8" />

<!-- Título del script HTML -->


<title>DOM_07_3</title>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Función historyBack */
function historyBack()
{
/* Volver a la página anterior */
window.history.back();
}

</script>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


<h1>Ediciones ENI - JavaScript - DOM_07_3</h1>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Mostrar el nombre del script */


alert("DOM_07_3");

/*
Mostrar la URL de la página
que da acceso al documento
*/
document.write("URL de la página que da acceso al documento: "
+ document.referrer + "<br />");

/*
Mostrar el valor del argumento
pasado por la página anterior
NB: param tendrá la cadena ?param=Eni%20JavaScript
*/
var param = window.location.search;
document.write("Argumento (antes de la recodificación): "
+ param + "<br />");
/*
Codificación del argumento (sustituyendo %20
por un espacio en nuestro caso)
*/
param = unescape(param);
document.write("Argumento (después de la recodificación): "
+ param + "<br />");

/*
Eliminación del nombre del argumento
(libro en nuestro caso)
*/
param = param.substring(param.lastIndexOf("=") + 1);
document.write("Valor del argumento: "
+ param);

</script>

<!-- Formulario -->


<br /><br />
<form>
<input
type="button"
id="botonHistoryBack"
value="Volver a la página anterior"
onclick="historyBack()"
/>
</form>

La ejecución del script sigue esta secuencia: 

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


l Visualización de la URL que llama (como en el documento DOM_07_2.htm). 

l Procesamiento y visualización del argumento pasado por el script DOM_07_1.htm: 

/*
Mostrar el valor del argumento pasado
por la página anterior
NB: param tendrá la cadena ?param=Eni%20JavaScript
*/
var param = window.location.search;
document.write("Argumento (antes de la recodificación): "
+ param + "<br />");
/*
Codificación del argumento (sustituyendo %20
por un espacio en nuestro caso)
*/
param = unescape(param);
document.write("Argumento (después de la recodificación): "
+ param + "<br />");

window.location.search  aísla  en  la  URL  la  parte  que  contiene  el  argumento  (?libro=Eni%
20JavaScript).  La  función  unescape  permite  sustituir  los  caracteres  codificados  durante  la  llamada  al 
documento desde DOM_07_1.htm. El espacio representado en la URL por la secuencia ’%20’ se restituye. 

La visualización da el siguiente resultado: 

Al  final  del  script,  encontrará  un  miniformulario  con  un  botón  que  llama  a  una  función  JavaScript  de  nombre 
historyBack  (ubicada  en  la  sección  HTML  <head>).  Esta  función  provoca  el  retorno  al  script  que  llama 
(DOM_07_1.htm): 
 

window.history.back();

8. Visualización de las características generales  del documento

Sin querer ser exhaustivo, el script va a mostrar cómo acceder a algunas características generales (título, URL, fecha 
de última modificación...) del script actual:  

<!-- Inicio script HTML -->

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type"
contenido="text/html; charset=utf-8" />
<!-- Título del script HTML -->
<title>DOM_08</title>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - DOM_08</h1>

<!-- Inicio script JavaScript -->


<script type="text/javascript">

/* Mostrar el nombre del script */


alert("DOM_08");

/* Mostrar el título del documento */


document.write("Título del documento: "
+ document.title + "<br />");

/* Mostrar el nombre de dominio del documento */


document.write("Dominio del documento: "
+ document.domain + "<br />");

/* Mostrar la URL absoluta del documento */


document.write("URL absoluta del documento: "
+ document.URL + "<br />");

/* Mostrar la fecha de última modificación del documento */


document.write("Fecha de última modificación del documento: "
+ document.lastModified);

</script>

Se muestran diferentes características generales del script: 

l el título del documento: 

document.write("Título del documento: "


+ document.title + "<br />");

l el dominio del documento: 

document.write("Dominio del documento: "

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


+ document.domain + "<br />");

l la URL (absoluta) del documento: 

document.write("URL absoluta del documento: "


+ document.URL + "<br />");

l la fecha de última modificación: 

document.write("Fecha de última modificación del documento: "


+ document.lastModified);

La ejecución del script, da el siguiente resultado: 

9. Gestión de los botones en los formularios

Con  el  ejemplo  propuesto  en  la  sección  dedicada  a  la  gestión  de  los  formularios  y  de  sus  etiquetas,  habíamos 
estudiado esta gestión en JavaScript. 

Ahora  vamos  a  ir  más  lejos  con  los  formularios  en  los  que  vamos  a  ubicar  los  campos  de  entrada  de  los  datos 
(etiquetas HTML input). 

Ejemplo 1 

En un primer ejemplo, nos centramos principalmente en la recuperación de información (nombre, identificador) de los 
botones  de  formularios.  En  la  sección  HTML  <body>,  nuestro  documento  contiene  (presentación  parcial)  la 
descripción HTML de tres formularios: 

<!-- Formulario con un botón para desactivar -->


<form name="formulario1">
Un clic en el botón de confirmación lo va a desactivar<br><br />
<input
type="button"
id="miBoton"
value="OK"
onclick="desactivarBoton();"

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


/>
</form>

<!-- Formulario con 2 botones (obtención del título) -->


<br /><hr><br />
<form name="formulario2">
Pulse en uno de los botones para mostrar el nombre (título)<br /><br />
<input
type="button"
id="miBoton1"
value="Boton1"
onclick="mostrarNombreBoton(this.value);"
/><br />
<input
type="button"
id="miBoton2"
value="Boton2"
onclick="mostrarNombreBoton(this.value);"
/><br />
</form>

<!-- Formulario con 2 botones y 1 enlace hipertexto


(obtención del identificador) -->
<br /><hr><br />
Pulse en uno de los botones o el enlace hipertexto
para mostrar el identificador <br /><br />
<form name="formulario3">
<input
type="button"
id="miBoton3"
value="Boton3"
onclick="mostrarIdentificadorElement(this.id);"
/><br />
<input
type="button"
id="miBoton4"
value="Boton4"
onclick="mostrarIdentificadorElement(this.id);"
/><br />
<a
href="#"
id="miEnlace"
onclick="mostrarIdentificadorElement(this.id);">
Enlace hipertexto
</a>
</form>

Cada  botón  ( <input type="button" ...>)  llama  a  una  función  JavaScript.  Para  que  sirva  de  ejemplo,  el 
primer botón del primer formulario llama a la función JavaScript  desactivarBoton cuando se hace clic en él (se 
dispara el evento onclick). 

Estudiemos ahora en detalle la programación asociada a cada botón. 

Para el botón con identificador miBoton del primer formulario, el código del botón (sección HTML <body>) es: 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<input
type="button"
id="miBoton"
value="OK"
onclick="desactivarBoton();"
/>

y el código fuente de la función que ejecuta (sección HTML <head>): 

/* Función desactivarBoton */
function desactivarBoton()
{
document.getElementById("miBoton").disabled=true;
}

document.getElementById("miBoton")  designa  al  botón  identificado  con  un  id  igual  a  miBoton 
y .disabled=true hace que este botón no sea accesible. 

Para el botón con identificador miBoton1 del segundo formulario, el código del botón (sección HTML <body>) es: 

<input
type="button"
id="miBoton1"
value="Boton1"
onclick="mostrarNombreBoton(this.value);"
/>

y el código fuente de la función que ejecuta (sección HTML <head>) es: 

/* Función mostrarMiBoton */
function mostrarMiBoton(MiBoton)
{
alert("El título del botón seleccionado es "+ MiBoton);
}

El argumento  this.value que se pasa a la función  mostrarMiBoton representa a la etiqueta mostrada en el 


botón ( value="Boton1") y se muestra por el método alert de la función mostrarMiBoton. 

El  botón  identificado  con  el  identificador  miBoton2,  que  no  se  comenta  aquí,  también  llama  a  la  función 
mostrarMiBoton. 

Para el botón con identificador miBoton3 del tercer formulario, el código (sección HTML <body>) es: 

<input
type="button"
id="miBoton3"

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


value="Boton3"
onclick="mostrarIdentificadorElement(this.id);"
/>

y el código fuente de la función que ejecuta (sección HTML <head>) es: 

/* Función mostrarIdentificadorBoton */
function mostrarIdentificadorBoton(idBoton)
{
alert("El botón seleccionado tiene como identificador " + idBoton);
}

El  argumento  this.id  que  se  pasa  a  la  función  mostrarIdentificadorBoton,  que  representa  al 
identificador  del  botón  (id="miBoton3"),  se  muestra 
por  el  método  alert  de  la  función 
mostrarIdentificadorBoton. 

El  botón  identificado  por 


miBoton4,  que  no  se  comenta  aquí,  también  llama  a  la  función 
mostrarIdentificadorBoton. 

Para  terminar,  para  el  enlace  hipertexto  identificado  con  miEnlace  en  el  tercer  formulario,  el  código  del  botón 
(sección HTML <body>) es: 

<a
href="#"
id="miEnlace"
onclick="mostrarIdentificadorElement(this.id);">
Enlace hipertexto
</a>

y el código fuente de la función que ejecuta (sección HTML <head>) es: 

/* Función mostrarIdentificadorElement */
function mostrarIdentificadorElement(idElement)
{
alert("El identificador del enlace seleccionado es " + idElement);
}

Ya  tiene  suficiente  experiencia  para  detectar  que  la  función  mostrarIdentificadorElement  también  se 
hubiera podido utilizar por los botones vistos anteriormente. 

Recapitulemos lo que sucede con la ejecución de este script. Los formularios se muestran como sigue: 

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Un clic en el botón OK del primer formulario desactiva este botón. 

Un clic en el botón Botón1 muestra esto: 

Un clic en el botón Botón3, muestra esta visualización: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


Para terminar, un clic en el enlace hipertexto muestra esto: 

Ejemplo 2 

Estudiemos un segundo ejemplo relativo a los formularios y sus botones con un script un poco más complejo. 

En la sección HTML <body>, tenemos: 

<!-- Formulario formulario1 con tres botones -->


Formulario número1: <br />
<form name="formulario1">
<input
type="button"
id="miBoton1"
value="Botón1"
onclick="mostrarPropiedadesBoton(this.value, this.id);"
/><br />
<input
type="button"
id="miBoton2"
value="Botón2"
onclick="mostrarPropiedadesBoton(this.value, this.id);"
/><br />
<input
type="button"
id="miBoton3"
value="Botón3"
onclick="mostrarPropiedadesBoton(this.value, this.id);"
/>
</form>

<!-- Formulario formulario2 con dos botones -->


<br /><hr><br />
Formulario número2: <br />

- 20 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<form name="formulario2">
<input
type="button"
id="miBoton4"
value="Botón4"
onclick="mostrarPropiedadesBoton(this.value, this.id);"
/><br />
<input
type="button"
id="miBoton5"
value="Botón5"
onclick="mostrarPropiedadesBoton(this.value, this.id);"
/>
</form>

<!-- Inicio script JavaScript -->


<script type="text/JavaScript">
/*
Mostrar el número de etiquetas input
en el conjunto de los formularios
*/
var listaInput = document.getElementsByTagName(’input’);
var numeroInput = listaInput.length;
document.write("<br /><hr><br />");
document.write("Número de etiquetas input en el conjunto de
los formularios: " + numeroInput + "<br />");

/*
Mostrar el número de etiquetas input
en el segundo formulario
*/
var lista2Input = document.forms[1].getElementsByTagName(’input’);
var nombre2Input = lista2Input.length;
document.write("Número de etiquetas input en el segundo formulario: "
+ nombre2Input);

</script>

Se  visualizan  dos  formularios.  El  primer  formulario  contiene  tres  campos  de  entrada  de  datos  de  tipo  <input
type="button" ...> y el segundo formulario contiene dos. 

Cada  botón  tiene  los  atributos  (propiedades)  id  y  value  y  ejecuta  una  misma  función 
mostrarPropiedadesBoton.  Para  cada  llamada  a  la  función  mostrarPropiedadesBoton,  se  pasan  dos 
argumentos: la etiqueta del botón ( this.value) y el identificador (this.id). 

Después de la visualización de los dos formularios, se presenta la siguiente información: 

l el número de etiquetas input en los formularios; 

l el número de etiquetas input en el segundo formulario. 

La instrucción: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 21 -


var listaInput = document.getElementsByTagName(’input’);

crea una tabla (lista) con los elementos DOM de nombre input en nuestro documento. 

Después se determina el número de elementos: 

var numeroInput = listaInput.length;

y mostrará: 

document.write("Número de etiquetas input en el conjunto de


los formularios: "
+ numeroInput + "<br />");

Para  determinar  el  número  de  elementos  DOM  de  nombre  input  en  el  segundo  formulario,  la  sintaxis  es  muy 
parecida: 

var lista2Input = document.forms[1].getElementsByTagName(’input’);

En  esta  sintaxis,  forms[1]  indica  que  solo  los  input  del  segundo  formulario  (numerado  con  1)  se  deben 
contabilizar. 

Queda ver el contenido de la función mostrarPropiedadesBoton (sección HTML <head>): 

/* Función mostrarPropiedadesBoton */
function mostrarPropiedadesBoton(miBoton, idBoton)
{
alert("El título del botón seleccionado es
" + miBoton + " y este botón pertenece al formulario "
+ document.getElementById(idBoton).form.name);
}

El procesamiento no tiene sorpresas. 

Observe  que  document.getElementById(idBoton).form.name  muestra  el  nombre  del  formulario 


(formulario1 o formulario2) en el que está el botón sobre el que se ha hecho clic. 

Recapitulando una vez más lo que sucede cuando se ejecuta el script, los formularios se muestran como sigue: 

- 22 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Un clic en el botón Boton1 del primer formulario muestra lo siguiente: 

Un clic en el botón Boton4 del segundo formulario provoca esta visualización: 

10. Gestión de las tablas (etiqueta HTML table)

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 23 -


La gestión de las tablas HTML (etiqueta table) es una de las opciones más interesantes. 

De  nuevo,  veamos  a  través  de  una  serie  de  ejemplos  lo  que  puede  hacer  con  las  tablas  HTML  con  un  mínimo  de 
conocimientos en JavaScript. 

Ejemplo 1 

El  objetivo  es  aprender  a  modificar  las  características  de  una  tabla  (border,  cellspacing,  cellpadding  y 
caption) con JavaScript. 

Recordemos brevemente a qué corresponden estos cuatro atributos: 

l atributo border: grosor del marco (por defecto 1) expresado en píxeles, 

l atributo cellspacing: tamaño del borde entre las celdas expresado en píxeles, 

l atributo cellpadding: espacio comprendido entre el contenido de las celdas y los bordes de la tabla expresado en 
píxeles, 

l atributo caption: nombre la tabla. 

El resultado de la ejecución del script se propone en la presentación de este ejemplo. 

Vemos el contenido de la sección HTML <body> de nuestro ejemplo: 

<!-- Tabla HTML -->


<table id="miTabla" border="1" cellspacing="1"
cellpadding="1">
<!-- Definición de la línea número0 de la tabla (título) -->
<tr>
<td>Modelo</td>
<td>Potencia</td>
</tr>
<!-- Definición de la línea número1 de la tabla -->
<tr>
<td>Ferrari 512 BB</td>
<td>380</td>
</tr>
<!-- Definición de la línea número2 de la tabla -->
<tr>
<td>Lamborghini Miura</td>
<td>385</td>
</tr>
<!-- Definición de la línea número3 de la tabla -->
<tr>
<td>Porsche 964 3.6</td>
<td>360</td>
</tr>
</table>

<!-- Formulario con botones -->


<br /><br />
<form>
Modificación de los valores de atributos de la tabla <br /><br />

- 24 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<input
type="button"
id="botonBorder"
value="Modificación atributo border"
onclick="modificarBorder();"/>
<br />
<input
type="button"
id="botonCellspacing"
value="Modificación atributo cellspacing"
onclick="modificarCellspacing();"
/><br />
<input
type="button"
id="botonCellpadding"
value="Modificación atributo cellpadding"
onclick="modificarCellpadding();"
/><br />
<input
type="button"
id="botonCaption"
value="Modificación del título de tabla"
onclick="AñadirCaption();"
/>
</form>

La tabla (una fila con títulos de columnas y tres filas de datos (dos columnas llamadas  Modelo y  Potencia)) no 


necesita ningún comentario. Observe los atributos que se asocian por defecto a esta tabla: 

l atributo id: miTabla 
l atributo border: 1 
l atributo cellspacing: 1 
l atributo cellpadding: 1 

En esta tabla se ha implementado un formulario con cuatro botones. Los botones tienen la función (en el orden de 
su presentación en el formulario) de: 

l modificar el valor del atributo border, 

l modificar el valor del atributo cellspacing, 

l modificar el valor del atributo cellpadding, 

l añadir un título (atributo caption). 

Para las cuatro llamadas a las funciones JavaScript, no hay paso de argumentos. Las cuatro llamadas se asocian al 
evento onclick. 

Pasemos ahora a estudiar las cuatro funciones JavaScript (sección HTML <head>). 

El código de la función modificarBorder es: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 25 -


/* Función modificarBorder */
function modificarBorder()
{
if (document.getElementById(’miTabla’).border == "1")
{
/* Pasar a un grosor de 5 */
document.getElementById(’miTabla’).border = "5";

}
else
{
/* Pasar a un grosor de 1 */
document.getElementById(’miTabla’).border = "1";
}
}

Se  hace  una  comprobación  sobre  el  grosor  del  borde  de  la  tabla,  localizada  por  su  identificador 
(getElementById): 

if (document.getElementById(’miTabla’).border == "1")

Si el grosor del borde es igual a 1 (el valor por defecto en el código HTML visto anteriormente), entonces el grosor 
se cambia a 5 (e inversamente, se devuelve a 1 en caso contrario). 

El código de la función modificarCellspacing es: 

/* Función modificarCellspacing */
function modificarCellspacing()
{
if (document.getElementById(’miTabla’).cellSpacing == "1")
{
/* Pasar a un cellspacing de 40 */
document.getElementById(’miTabla’).cellSpacing = "40";
}
else
{
/* Pasar a un cellspacing de 1 */
document.getElementById(’miTabla’).cellSpacing = "1";
}
}

Como  puede  ver,  el  código  es  muy  parecido  al  de  la  función  anterior;  solo  cambia  el  atributo  cellSpacing  (en 
lugar de border). 

El  código  de  la  tercera  función, 


modificarCellpadding,  no  se  muestra  aquí.  Solo  se  cambia  el  atributo 
cellSpacing por cellPadding. 

La última función, AñadirCaption, es la siguiente: 

- 26 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Función AñadirCaption */
function AñadirCaption()
{

/* Instanciar y mostrar el título de la tabla */


var miTitulo = document.getElementById(’miTabla’).createCaption();
miTitulo.innerHTML = "Coches de deporte";

Se crea un título para la tabla con identificador miTabla a través de una función llamada createCaption. 

Posteriormente, se hace la asignación del título en la parte superior de la tabla por: 

miTitulo.innerHTML = "Coches de deporte";

Veamos el resultado de la ejecución de este script. Empecemos por el estado inicial (antes del uso de los botones): 

Después del uso de estos cuatro botones, la visualización es la siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 27 -


Ejemplo 2 

En  este  segundo  ejemplo,  el  objetivo  es  automatizar  con  JavaScript  la  implementación  de  un  trazo  horizontal  de 
encabezado que se muestre por encima de la tabla HTML (también se dibujará un trazo al pie de la tabla). No hay 
dificultad alguna desde un punto de vista técnico, pero nos permitirá de descubrir un atributo HTML relativamente 
desconocido, frame. 

Recordemos que este atributo HTML puede tener dos valores: 

l above: visualización de bordes externos en la parte superior de la tabla únicamente, 
l below: visualización de bordes externos en la parte inferior de la tabla únicamente. 

Además de la tabla HTML vista en el ejemplo 1, se construye un formulario: 

- 28 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<!--Formulario con los botones -->
<br /><br />
<form>
Añadir/Eliminar trazos de delimitación de la tabla <br /><br />
<input
type="button"
id="botonTrazoEncima"
value="Trazo encima de la tabla"
onclick="situarTrazoEncima();"
/><br />
<input
type="button"
id="botonTrazoDebajo"
value="Trazo debajo de la tabla"
onclick="situarTrazoDebajo();"
/><br />
</form>

Hay  dos  botones 


<input type="button" ...>  en  el  formulario:  el  primero  llama  a  la  función 
situarTrazoEncima y el segundo a la función situarTrazoDebajo.  

El código del primer procedimiento es: 

/* Función situarTrazoEncima */
function situarTrazoEncima()
{
document.getElementById(’miTabla’).frame = "above";
}

Y del segundo es: 

/* Función situarTrazoDebajo */
function situarTrazoDebajo()
{
document.getElementById(’miTabla’).frame = "below";
}

En los dos casos, la propiedad (atributo HTML) frame se configura para la tabla identificada por miTabla. 

Cuando se ejecuta el script, el estado inicial de la tabla es el siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 29 -


Después de hacer clic en el primer botón, la visualización se presenta como sigue: 

Y después de ejecutar el segundo botón, la visualización se convierte en: 

- 30 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Ejemplo 3  

Nos basamos de nuevo en la tabla propuesta en los ejemplos 1 y 2. A continuación (en la sección HTML  <body>), 
se definen dos formularios: 

<!-- Formulario mostrar -->


<br /><hr><br />
<form name="mostrar">
Mostrar una celda de la tabla<br /><br />
Número de línea (entre 0 y 3):
<input
type="txt"
id="numLinea1"
value=""
/><br />
Número de columna (entre 0 y 1):
<input
type="txt"
id="numColumna1"
value=""
/><br />
<input
type="button"
id="botonMostrarCelda"
value="Mostrar una celda"
onclick="mostrarCelda()"
/><br />
</form>

<!-- Formulario modificación -->


<br /><hr><br />
<form name="modificación">
Modificación de una celda de la tabla<br /><br />
Número de línea (entre 0 y 3):

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 31 -


<input
type="txt"
id="numLinea2"
value=""
/><br />
Número de columna (entre 0 y 1):
<input
type="txt"
id="numColumna2"
value=""
/><br />
<input
type="button"
id="botonMostrarCelda"
value="Modificación de una celda"
onclick="modificarCelda()"/>
<br />
</form>

En  el  primer  formulario,  hay  un  botón  <input


type="button" ...>,  para  ejecutar  una  función  de  nombre 
mostrarCelda,  basándose  en  un  número  de  línea  y  de  columna  introducido  con  antelación  en  dos  zonas  de 
entrada de datos <input type="txt" ...> (numLinea1 y numColumna1). 

Estructuralmente, el segundo formulario es idéntico; hay un botón <input type="button" ...> para ejecutar 


la función de nombre modificarCelda. 

Pasemos al código JavaScript de la función mostrarCelda (situado en la sección HTML <head>): 

/* Función mostrarCelda */
function mostrarCelda()
{
/*
Mostrar el número de la línea
seleccionada en la tabla
*/
var numeroLinea =
paseInt(document.getElementById(’numLinea1’).value);
alert("Número de línea: " + numeroLinea);
/*
Mostrar el número del columna
seleccionada en la tabla
*/
var numeroColumna =
parseInt(document.getElementById(’numColumna1’).value);
alert("Número de columna: " + numeroColumna);
/*
Mostrar el número de líneas de la tabla
*/
var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);
alert("Número de línea(s) de la tabla: " + numeroLineas);
/*
Mostrar el número de columnas de la tabla

- 32 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


(determinando el número de celdas de la línea de título)
*/
var numeroColumnas =
parseInt(document.getElementById(’miTabla’)
.rows[0].cells.length);
alert("Número de columna(s) de la tabla: " + numeroColumnas);
/*
Mostrar la celda
*/
if ((numeroLinea >= 0) && (numeroLinea <= (numeroLineas - 1))
&& (numeroColumna >= 0) && (numeroColumna <= (numeroColumnas - 1)))
{
/* Mostrar las celdas (columnas) de la línea */
alert("Código HTML de la línea: "
+ document.getElementById(’miTabla’)
.rows[numeroLinea].innerHTML);
/* Añadir en la tabla las celdas de la línea actual */
var tabLinea =
document.getElementById(’miTabla’)
.rows[numeroLinea].cells;
/* Mostrar */
alert("Contenido de la celda: "
+ tabLinea[numeroColumna].innerHTML);
}
else
{
alert("Su número de línea o su número de columna
es errónea");
}
}

El primer objetivo de la función es recuperar en variables en memoria el número de la línea y de la columna de la 
celda que se desea visualizar: 

var numeroLinea = parseInt(document.getElementById(’numLinea1’).value);

var numeroColumna = parseInt(document.getElementById(’numColumna1’).value);

Posteriormente,  para  que  se  pueda  realizar  un  control  de  coherencia  del  número  de  la  línea  y  del  número  de  la 
columna que se introducirán en el formulario, se debe determinar el número de líneas y de columnas de la tabla: 

var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);

var numeroColumnas =
parseInt(document.getElementById(’miTabla’).rows[0].cells.length);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 33 -


Para terminar, pasemos a la visualización del contenido de la celda de destino. En un primer momento, se muestra 
el código HTML completo de la línea, con el método alert: 

/* Mostrar las celdas (columnas) de la línea */


alert("Código HTML de la línea: " +
document.getElementById(’miTabla’).rows[numeroLinea].innerHTML);

Por  ejemplo,  para  la  línea  número  2  de  la  tabla,  el  resultado  será:  <td>Lamborghini
Miura</td><td>385</td> 

Recordemos  que  la  propiedad  innerHTML  proporciona  el  contenido  HTML  del  elemento  de  tabla  (aquí,  una  línea 
entera). 

Los diferentes elementos de la línea (celdas o columnas) se sitúan a continuación en una tabla en memoria: 

var tabLinea =
document.getElementById(’miTabla’).rows[numeroLinea].cells;

Esto permite mostrar el valor de la columna de destino (sin el código HTML) como sigue: 

alert("Contenido de la celda: " + tabLinea[numeroColumna].innerHTML);

Por ejemplo, para el número de línea 2 y el número de columna 1, el resultado mostrado será 385. 

Solo se implementa un control de validación para comprobar el número de la línea y de la columna: 

if ((numeroLinea >= 0) && (numeroLinea <= (numeroLineas - 1)) &&


(numeroColumna >= 0) && (numeroColumna <= (numeroColumnas - 1)))

La  segunda  función,  modificarCelda,  tiene  un  código  fuente  muy  parecido  al  de  la  función  mostrarCelda. 
Nos centramos en algunas diferencias. 

Como sucedía anteriormente, las celdas de la tabla de la línea implicada se ubican en una tabla en memoria: 

/* Añadir en la tabla las celdas de la línea actual */


var tabLinea =
document.getElementById(’miTabla’)
.rows[numeroLinea].cells;

Posteriormente, solo falta modificar el contenido de la celda de destino. En nuestro ejemplo, el valor de sustitución 
es una constante (" Nuevo valor"). Evidentemente, en una aplicación más evolucionada, este valor se introduciría 
a través de un formulario. El código para esta sustitución (modificación) es el siguiente: 

/* Modificación */
tabLinea[numeroColumna].innerHTML="Nuevo valor";

- 34 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Cuando se ejecuta, la visualización inicial se presenta como sigue: 

Si  introducimos  1  como  número  de  línea  y  1  como  número  de  columna  en  el  primer  formulario,  aparecen  las 
siguientes visualizaciones: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 35 -


Para terminar, si introducimos 1 como número de línea y 1 como número de columna en el segundo formulario, la 
tabla se modifica como sigue: 

Ejemplo 4 

Partimos de la tabla propuesta en los ejemplos anteriores (que, en su versión inicial, tiene tres coches de deporte). 
El objetivo en este nuevo ejemplo va a ser insertar en primera línea (directamente bajo el título) un nuevo vehículo, 
así como un segundo al final de la tabla. Para no complicar el código del ejemplo (y las explicaciones relacionadas), 
los datos insertados serán valores constantes. Sabrá cómo personalizar fácilmente este código para que los datos 
se puedan introducir por el teclado. 

Para la adición en la cabecera de tabla (bajo el título), el formulario es el siguiente: 

<!-- Formulario de adición en primera línea o en última línea -->


<br /><hr><br />
Añadir líneas<br /><br />

- 36 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<form name="formularioAñadir">
<input
type="button"
id="AñadirLineaInicioTabla"
value="Añadir una línea (inicio de tabla)"
onclick="añadirLineaInicioTabla()"
/><br /><br />
<input
type="button"
id="AñadirLineaFinTabla"
value="Añadir una línea (fin de tabla)"
onclick="añadirLineaFinTabla()"
/><br />
</form>

Dos botones <input type="button" ... > llaman a las funciones Java­Script AñadirLineaInicioTabla 


y añadirLineaFinTabla. 

Cuando se ejecuta el script, el estado inicial de la tabla es el siguiente: 

Estudiemos el código JavaScript de la función añadirLineaInicioTabla (ubicado en la sección HTML <head>): 

/* Función añadirLineaInicioTabla */
function añadirLineaInicioTabla()
{

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 37 -


/*
Añadir una línea vacía en posición 1
(bajo el título)*/
var tabLinea=document.getElementById(’miTabla’)
.insertRow(1);

/*
Añadir una columna 0 (Modelo) en la línea creada
y almacenar un valor
*/
var columna0=tabLinea.insertCell(0);
columna0.innerHTML="Ferrari F40";

/*
Añadir una columna 1 (Potencia) en la línea creada
y almacenar un valor
*/
var columna1=tabLinea.insertCell(1);
columna1.innerHTML="478";
}

En primer lugar, conviene insertar una línea (vacía de momento) bajo el título, en la tabla ’miTabla’. Observe que 
la  numeración  de  las  líneas  empieza  en  las  tablas  HTML  por  0;  la  línea  insertada  será,  por  tanto,  la  número  1.  El 
método es insertRow. 

var tabLinea=document.getElementById(’miTabla’).insertRow(1);

Una vez que la línea se ha insertado, hay que prever la descripción de las columnas (dos en nuestro caso) y poner 
en ellas los datos. Para la primera columna (también numerada por 0), el código es: 

var columna0=tabLinea.insertCell(0);
columna0.innerHTML="Ferrari F40";

La tabla HTML después de esta inserción se presenta como sigue: 

- 38 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


El código JavaScript de la función añadirLineaFinTabla es muy parecido al anterior: 

/* Función añadirLineaFinTabla */
function añadirLineaFinTabla()
{
/*
Mostrar el número de líneas de la tabla
*/
var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);

/*
alert("Número de línea(s) de la tabla: " + numeroLineas);
*/

/*
Añadir una línea vacía después de la última línea
actual de la tabla
*/
var tabLinea = document.getElementById(’miTabla’)
.insertRow(numeroLineas);

/*
Añadir una columna 0 (Modelo) en la línea creada
y almacenar un valor
*/
var columna0 = tabLinea.insertCell(0);
columna0.innerHTML = "Porsche 959";

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 39 -


/*
Añadir una columna 1 (Potencia) en la línea creada
y almacenar un valor
*/
var columna1 = tabLinea.insertCell(1);
columna1.innerHTML = "450";
}

Es necesario, en primer lugar, determinar el número de líneas presentes en la tabla HTML: 

var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);

Después añadimos una línea al final de la tabla, con el método insertRow: 

/*
Añadir una línea vacía después de la última línea
actual de la tabla
*/
var tabLinea = document.getElementById(’miTabla’)
.insertRow(numeroLineas);

Solo falta introducir el contenido en las dos columnas (como anteriormente para la primera línea). Para la segunda 
columna (numerada con 1), correspondiente a la potencia, el código es: 

var columna1 = tabLinea.insertCell(1);


columna1.innerHTML = "450";

La tabla HTML después de esta inserción se presenta como sigue: 

- 40 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Solo falta ver cómo eliminar una línea de la tabla HTML, cuyo número de línea se proporciona por teclado, a través 
de  un  campo  <input type="text" ...>.  En  nuestro  script  HTML  (sección  <body>),  se  añade  un  segundo 
formulario después del que nos ha servido para añadir líneas. Su código HTML es el siguiente: 

<!-- Formulario de borrado de líneas -->


<br /><hr><br />
Eliminación de líneas<br /><br />
<form name="formularioEliminación">
Número de línea a eliminar (número a partir de 1):
<input
type="txt"
id="numLinea"
value="" />
/><br /><br />
<input
type="button"
id="botonEliminarLineaTabla"
value="Eliminación de una línea"
onclick="eliminarLineaTabla()"
/>
</form>

Este formulario no tiene sorpresas. Incluye un campo de entrada de datos (identificado por  numLinea) y un botón 
de llamada a la función eliminarLineaTabla. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 41 -


Estudiemos el código de esta función: 

/* Función eliminarLineaTabla */
function eliminarLineaTabla()
{
/*
Mostrar el número de la línea que se ha de eliminar
en la tabla
*/
var numeroLinea =
parseInt(document.getElementById(’numLinea’).value);
/* alert("Número de línea a eliminar: " + numeroLinea); */
/*
Mostrar el número de líneas de la tabla
*/
var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);
/* alert("Número de línea(s) de la tabla: " + numeroLineas); */
/*
Eliminación de la línea
*/
if ((numeroLinea >= 1) && (numeroLinea < numeroLineas))
{
/* Eliminación */
document.getElementById(’miTabla’).deleteRow(numeroLinea);
}
else
{
/* Número de línea errónea */
alert("Número de línea errónea");
}
}

Para que sea posible indicar si un número de línea es incorrecto (inferior a 1 o superior o igual al número de líneas), 
se determina el número de líneas de la tabla: 

var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);

La eliminación se realiza a través del método deleteRow como sigue: 

document.getElementById(’miTabla’).deleteRow(numeroLinea);

Si se solicita la eliminación de la línea número 4, la visualización de la tabla se convierte en: 

- 42 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Ejemplo 5 

Terminamos  nuestro  ejemplo  con  un  script  en  el  que  vamos  a  colorear  las  diferentes  líneas  de  la  tabla  HTML  con 
JavaScript: 

l la línea de título, en naranja, 

l las líneas de datos con número par, en plata (silver), 

l las líneas de datos con número impar, en blanco (white). 

Siempre utilizaremos nuestra tabla HTML habitual (una línea de título y tres líneas de datos): 

Modelo  Potencia 

Ferrari 512 BB  380 

Lamborghini Miura  385 

Porsche 964 3.6  360 

El código HTML del formulario (sección  <body>) que incluye los botones de llamada a las funciones JavaScript es el 
siguiente: 

<!-- Formulario -->


<br /><br />

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 43 -


<form>
Color del título (naranja) y de las líneas
(alternativamente plata/blanco) de la tabla <br /><br />
<input
type="button"
id="botonColorearTituloTabla"
value="Color del título"
onclick="colorearTituloTabla()"
/><br />
<input
type="button"
id="botonColorearLineasTabla"
value="Color de las líneas"
onclick="colorearLineasTabla()"
/>
</form>

Un  primer  botón  <inputtype="button" ... >  con  identificador  botonColorearTituloTabla  llama  a 
una  función  de  nombre  colorearTituloTabla  y  un  segundo  botón  <input
type="button" ... >  con 
identificador botonColorearLineasTabla llama a una función con nombre colorearLineasTabla. 

Analicemos el código de la función colorearTituloTabla (sección HTML <head>): 

/* Función colorearTituloTabla */
function colorearTituloTabla()
{
/* Mostrar el número de columnas de la tabla
(determinando el número de celdas de la línea de título)
*/
var numeroColumnas =
parseInt(document.getElementById(’miTabla’).rows[0].cells.length);
alert("Número de columna(s) de la tabla: " + numeroColumnas);
/*
Añadir en la tabla memoria (tabLinea) las celdas
de la línea número0 (título)
*/
var tabLinea =
document.getElementById(’miTabla’).rows[0].cells;
/*
Modificación del color de las celdas de la línea número0 (título) */
for ( numeroColumna = 0; numeroColumna<numeroColumnas; numeroColumna++)
{
/*
Color de la celda actual
en naranja (código RGB #FFA500)
*/
tabLinea[numeroColumna].bgColor = "#FFA500";
}
}

En primer lugar, se determina el número de columnas (calculando el número de celdas de la línea n°0): 

- 44 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


var numeroColumnas =
parseInt(document.getElementById(’miTabla’).rows[0].cells.length);

Posteriormente, también como hemos visto en ejemplos anteriores, las celdas de la línea número 0 (línea de título) 
se ubican en una tabla en memoria (tabLinea) como sigue: 

var tabLinea=
document.getElementById(’miTabla’).rows[0].cells;

Solo falta utilizar un procesamiento iterativo (bucle for en nuestro código) para recorrer las celdas de esta tabla y 
colorearlas (en naranja para el título) como sigue: 

tabLinea[numeroColumna].bgColor = "#FFA500";

Terminemos por el código de la función colorearLineasTabla: 

/* Función colorearLineasTabla */
function colorearLineasTabla()
{
/* Mostrar el número de líneas de la tabla
*/
var numeroLineas =
parseInt(document.getElementById(’miTabla’).rows.length);
alert("Número de línea(s) de la tabla: " + numeroLineas);
/*
Mostrar el número de columnas de la tabla
(determinando el número de celdas de la línea de título)
*/
var numeroColumnas =
parseInt(document.getElementById(’miTabla’).rows[0].cells.length);
alert("Número de columna(s) de la tabla: " + numeroColumnas);
/*
Color de las líneas (fuera del título)
alternativamente en silver/white
*/
for (i = 1; i<numeroLineas; i++)
{
/*
Añadir en la tabla memoria (tabLinea)
las celdas de la línea actual
*/
var tabLinea =
document.getElementById(’miTabla’).rows[i].cells;
/*
Modificación del color de las celdas
de la línea actual
*/
for ( numeroColumna=0; numeroColumna<numeroColumnas;
numeroColumna++)

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 45 -


{
if (i% 2 == 0)
{
/*
Color de la celda actual
en blanco (código RGB #C0C0C0)
*/
tabLinea[numeroColumna].bgColor = "silver";
}
else
{
/*
Color de la celda actual en blanco
(código RGB #FFFFFF)
*/
tabLinea[numeroColumna].bgColor = "white";
}
}
}
}

Aquí, de nuevo, hay muchos puntos comunes con los ejemplos anteriores. Se determina el número de líneas de la 
tabla HTML: 

var numeroColumnas =
parseInt(document.getElementById(’miTabla’).rows[0].cells.length);

El número de columnas también se calcula como en la función colorearTituloTabla. 

Posteriormente, un bucle  for recorre las líneas de la tabla HTML, empezando con la línea número 1 (primera línea 
de datos): 

for (i=1; i<numeroLineas; i++)

La línea actual se almacena en la tabla en memoria tabLinea, ya vista en la función mostrarTituloTabla: 

var tabLinea =
document.getElementById(’miTabla’).rows[i].cells;

Un segundo bucle  for (idéntico al de la función  mostrarTituloTabla) recorre las dos columnas de la tabla. En 


cada vuelta del bucle, se hace una comprobación de paridad (i%2 == 0) y, para las líneas con numeración par, el 
color que se mantiene (con la propiedad bgColor) es el color plata (silver): 

tabLinea[numeroColumna].bgColor = "silver";

y el color blanco (white), para las líneas con numeración impar: 

- 46 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


tabLinea[numeroColumna].bgColor = "white";

Para los códigos de los colores, es posible utilizar el pseudónimo de los colores (orange, silver, white...) o el código 
RGB asociado al color (# seguido de seis códigos hexadecimales; por ejemplo, #FFA500 para el color naranja). 

La visualización de la tabla se presenta a continuación, después de la aplicación de las funciones de coloración del 
título y de las líneas de datos: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 47 -


Noción de flujo XML

El  formato  de  datos  XML  (eXtensible  Markup  Language)  es  omnipresente  en  las  aplicaciones  informáticas.  XML  es  un 
lenguaje de marcado extensible. Este lenguaje se llama extensible porque permite crear extensiones con su propio 
vocabulario y su gramática. Para que sirva como ejemplo, XHTML, XSLT, RSS son extensiones. 

XML  se  utiliza  principalmente  para  automatizar  los  intercambios  de  datos  entre  sistemas  heterogéneos.  Permite 
definir conjuntos de datos complejos, como estructuras arborescentes. 

Encontrará  en  Wikipedia  una  presentación  muy  completa  de  XML,  en  la  dirección: 
http://es.wikipedia.org/wiki/Extensible_Markup_Language  

DOM,  el  modelo  de  acceso  a  los  diferentes  componentes  de  los  documentos  HTML  e  incluso  XML,  que  hemos 
estudiado en el capítulo Modelo DOM, va a ser la herramienta principal para recorrer los archivos XML. 

En  este  capítulo,  también  veremos  por  primera  vez  cómo  acceder  a  los  archivos  remotos  con  el  objeto 
XMLHttpRequest. 

Para  ilustrar  las  posibilidades  en  materia  de  exploración  de  flujo  XML,  se  van  a  estudiar  muchos  ejemplos.  En  los 
primeros, se ofrecerán comentarios detallados. 

Además, las diferentes técnicas expuestas serán muy útiles cuando abordemos el almacenamiento remoto (capítulo 
Almacenamiento remoto (Ajax ­ PHP ­ MySQL ­ XML). 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Ejemplos

1. Ejemplo 1: Visualización del contenido de un mail codificado en XML

El objetivo en este primer ejemplo va a ser mostrar en HTML un flujo de datos XML recuperado en un sitio Web. 

Archivo email.xml 

El documento en cuestión (email.xml) tiene una estructura muy simple: 

<email>
<de>María González-Aller</de>
<a>Ángel Sánchez</a>
<asunto>Importante</asunto>
<mensaje>Partido de tenis el sábado a las 10 horas</mensaje>
</email>

Como  habrá  comprobado,  se  trata  de  un  mensaje  de  tipo  mail  (codificado  aquí  en  XML)  entre  un  autor  (María 
González­Aller) y un destinatario (Ángel Sánchez). 

Sección HTML <body> 

En el script HTML/JavaScript (llamado DOM_01.htm), el código de gestión del flujo XML se muestra íntegramente en 
la sección HTML <body>. 

El script empieza con la colocación en la página Web del mensaje XML. En realidad, el mensaje no aparece a este 
nivel, sino que solo se trata de establecer una capa HTML (que incluye etiquetas span identificadas). 

En  general,  la  etiqueta  <div>  se  emplea  para  contener  y  anotar  otros  elementos  HTML  (input,  span...), 
mientras que la etiqueta <span> se usa para enmarcar e identificar palabras o grupos de palabras. 

El código implementado para la visualización del contenido del mail es el siguiente: 

<!-- Mostrar un mensaje de tipo mail codificado en XML -->


<h3>Mostrar un mensaje de tipo mail codificado en XML</h3>
<div>
<b>Autor: </b> <span id="de"></span><br />
<b>Destino: </b> <span id="a"></span><br />
<b>Asunto: </b> <span id="asunto"></span><br />
<b>Mensaje: </b> <span id="mensaje"></span>
</div>

Cada  elemento  span  está  identificado,  lo  que  permitirá  registrar  el  mensaje  con  los  datos  efectivos  leídos  en  el 
archivo XML email.xml. 

El script JavaScript se sitúa en esta misma sección HTML <body>, que se lista aquí íntegramente (más adelante, se 
comentará en detalle): 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


<!-- Inicio script JavaScript -->
<script type="text/javascript">
/* Creación de un objeto XMLHttpRequest para intercambiar datos
con el servidor en formato texto, XML o JSON

NB: Los archivos XML se parsean automáticamente por el objeto


y son accesibles con los métodos del DOM
*/
if (window.XMLHttpRequest)
{
// Código específico para los navegadores
// IE7+, Firefox, Chrome, Opera, Safari
var xmlhttp = new XMLHttpRequest();
}
else
{
// Código específico para los navegadores IE6, IE5
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

/* Apertura del archivo XML email.xml en modo síncrono (false) */


xmlhttp.open("GET", "email.xml", false);

/* Lanzar la consulta HTTP al servidor */


xmlhttp.send();

/* Creación del documento XML en memoria */


var xmlDoc = xmlhttp.responseXML;

/* Mostrar el campo Autor */


document.getElementById("de").innerHTML =
xmlDoc.getElementsByTagName("de")[0].childNodes[0].nodeValue;

/* Mostrar el campo Destino */


document.getElementById("a").innerHTML =
xmlDoc.getElementsByTagName("a")[0].childNodes[0].nodeValue;

/* Mostrar el campo Asunto */


document.getElementById("asunto").innerHTML =
xmlDoc.getElementsByTagName("asunto")[0].childNodes[0].nodeValue;

/* Mostrar el campo Mensaje */


document.getElementById("mensaje").innerHTML =
xmlDoc.getElementsByTagName("mensaje")[0].childNodes[0].nodeValue;

</script>

El script empieza con la instanciación de un objeto de la clase XMLHttpRequest. Este objeto se llama xmlhttp y 
en nuestro caso sirve para comunicar con el servidor remoto, en el que hay un archivo XML de nombre email.xml. 
Observe que, para las versiones antiguas del navegador Microsoft Internet Explorer (versiones 6 y anteriores), hay 
que recurrir a un objeto ActiveX y poner un objeto XMLHttpRequest. 

Posteriormente, la apertura del archivo remoto se hace con el método  open del objeto xmlhttp. El método open 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


necesita tres argumentos: 

l El  método  de  acceso  (GET  o  POST):  en  general,  se  utiliza  el  valor  GET  y  es  suficiente.  El  valor  POST  se  reserva 
para enviar argumentos voluminosos al servidor y cuando los argumentos se registran por un formulario. 

l El nombre del archivo que se va a leer (email.xml en nuestro caso). 

l El  comportamiento  síncrono  o  asíncrono  de  la  consulta  enviada  al  servidor,  el  modo  síncrono  (false)  elegido  en 
nuestro caso, sirve para indicar que cualquier actividad del navegador se suspende durante la ejecución de la consulta 
(este valor no es el valor aconsejado). 

La consulta se envía a continuación al servidor por el método send, que aquí se utiliza sin argumentos. 

La  respuesta  enviada  por  el  servidor,  es  decir,  el  archivo  XML,  se  asigna  a  continuación  a  una  variable  llamada 
xmlDoc: 

/* Creación del documento XML en memoria */


var xmlDoc = xmlhttp.responseXML;

Esta variable se va a explotar con los métodos DOM para extraer el contenido útil. 

Por ejemplo, para la recuperación del campo autor del mail, el código es: 

/* Visualización del campo Autor*/


document.getElementById("de").innerHTML =
xmlDoc.getElementsByTagName("de")[0].childNodes[0].nodeValue;

Con el método DOM getElementsByTagName, se extrae del flujo XML el nombre del autor (María González-
Aller, en nuestro caso) y se asigna al elemento HTML llamado de. 

La  secuencia  [0].childNodes[0].nodeValue  indica  que  hace  referencia  al  primer  tag  de  nombre  de  del 
documento y al valor de su primer hijo. 

La visualización es la siguiente: 

2. Ejemplo 2: Lista de marcas de coches  (archivo coches.xml)

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


En este segundo ejemplo, el objetivo es listar el conjunto de marcas de coches de deporte guardadas en un archivo 
XML. Por supuesto, este procesamiento presenta similitudes con el procesamiento visto en el primer ejemplo. 

El objetivo en este primer ejemplo va a ser mostrar en HTML un flujo de datos XML recuperado de un sitio Web. 

Archivo coches.xml 

El documento coches.xml es el que se va a utilizar en el script del segundo ejemplo y también en el resto de los 
ejemplos de este capítulo. Es el siguiente: 

<coches>
<coche origen="ITALIA" grupo="FIAT">
<marca>FERRARI</marca>
<modelo>512 BB</modelo>
<motor>V12 FERRARI</motor>
<cilindrada>5</cilindrada>
<potencia>380</potencia>
<velocidad_punta>280</velocidad_punta>
<sitio_web>
http://es.wikipedia.org/wiki/Ferrari_Berlinetta_Boxer
</sitio_web>
</coche>
<coche origen="ITALIA" grupo="VOLKSWAGEN">
<marca>LAMBORGHINI</marca>
<modelo>MIURA</modelo>
<motor>V12 LAMBORGHINI</motor>
<cilindrada>3.9</cilindrada>
<potencia>385</potencia>
<velocidad_punta>280</velocidad_punta>
<sitio_web>
https://es.wikipedia.org/wiki/Lamborghini_Miura
</sitio_web>
<sitio_web>
http://en.wikipedia.org/wiki/Lamborghini_Miura
</sitio_web>
</coche>
<coche origen="ALEMANIA" grupo="VOLKSWAGEN">
<marca>PORSCHE</marca>
<modelo>964 TURBO</modelo>
<motor>FLAT 6 PORSCHE</motor>
<cilindrada>3.6</cilindrada>
<potencia>360</potencia>
<velocidad_punta>295</velocidad_punta>
<sitio_web>
https://en.wikipedia.org/wiki/Porsche_964
</sitio_web>
</coche>
</coches>

Sección HTML <body> 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


En el script HTML/JavaScript (llamado DOM_02.htm), encontrará la instanciación de un objeto para el acceso remoto 
(XMLHttpRequest o ActiveX Microsoft.XMLHTTP, según el navegador), la apertura del archivo y el envío de la 
consulta y, al final, la creación del documento DOM en memoria. 

En este script, no hay zonas de visualización  span en una capa HTML; la información simplemente se va a mostrar 
en la página Web con el método document.write. 

La  secuencia  de  código  empieza  por  la  creación  de  una  tabla  en  memoria,  llamada  marca,  en  la  que  se 
almacenarán los nodos marca del archivo coches.xml: 

/* Recuperación del conjunto de los nodos marca (tabla memoria) */


var marca = xmlDoc.getElementsByTagName("marca");

Posteriormente, pasamos a la visualización: 

/* Mostrar la marca del primer coche */


document.write("Marca coche número1: " +
marca[0].childNodes[0].nodeValue + "<br />");

/* Mostrar la marca del segundo coche */


document.write("Marca coche número2: " +
marca[1].childNodes[0].nodeValue + "<br />");

/* Mostrar la marca del tercer coche */


document.write("Marca coche número3: " +
marca[2].childNodes[0].nodeValue);

Evidentemente, esta solución de visualización no es del todo satisfactoria porque depende del número de coches 
(tres) del archivo XML coches.xml. Veremos en un ejemplo más adelante cómo resolver esta dificultad. 

En  nuestro  ejemplo, 


marca[0].childNodes[0].nodeValue  designa  la  primera  ocurrencia  de  la  etiqueta 
marca y después el valor del primer hijo de esta etiqueta. 

Cuando se ejecute, tendremos la siguiente visualización: 

3. Ejemplo 3: Lista de las marcas de coches  con un bucle

Habíamos indicado un límite molesto en el ejemplo anterior; veamos cómo salvar esta dificultad con un bucle. 

El código es muy simple: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


/*
Bucle para mostrar de las marcas de los coches
*/
/* Recuperación del conjunto de los nodos marca (tabla memoria) */
var marca = xmlDoc.getElementsByTagName("marca");
alert("Número de coches: " + marca.length);
for (i = 0; i<marca.length; i++)
{
/* Mostrar la marca del coche actual */
/* NB: La numeración de los coches empieza por cero */
document.write("Marca del coche número" + (i+1) + ": "
+ marca[i].childNodes[0].nodeValue + "<br />");
}

Después  de  recuperar  los  nodos  marca  en  una  tabla,  es  posible  recorrer  esta  tabla  con  un  bucle 
for.  Los 
elementos  de  la  tabla  se  enumeran  de  manera  clásica  de  cero  hasta  marca.length - 1  (siendo  length  el 
número de elementos de la tabla). 

En  cada  pasada  del  bucle,  la  marca  se  mostrará  con  marca[i].childNodes[0].nodeValue,  siendo  i  el 
índice del bucle for. 

La visualización obtenida es la siguiente: 

Por lo tanto, es estrictamente idéntico al ejemplo anterior. 

4. Ejemplo 4: Lista de nodos conectados a la raíz

El objetivo de este ejemplo es quizás de orden técnico. Se trata de conocer la lista de los nodos conectados a la raíz 
y el nombre de esta raíz: 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


El código, cuando el documento XML se ha creado en memoria, es el siguiente: 

/* Mostrar la lista de los nodos relacionados con la raíz */


document.write("Lista de los nodos relacionados con la raíz:<br />")
var listaNodosRaiz = xmlDoc.documentElement.childNodes;
for (i=0; i<listaNodosRaiz.length; i++)
{
/* Mostrar solo los nodos de tipo 1 */
if (listaNodosRaiz[i].nodeType == 1)
{
document.write(" - " + listaNodosRaiz[i].nodeName + "<br />");
}
}

/* Mostrar el nombre del nodo raíz */


document.write("<br />");
document.write("El nodo raíz es "
+ xmlDoc.documentElement.nodeName + "<br />");

/* Mostrar el tipo del nodo raíz */


document.write("El tipo del nodo raíz es "
+ xmlDoc.documentElement.nodeType);

Se crea una tabla en memoria llamada listaNodosRaiz, con: 

var listaNodosRaiz = xmlDoc.documentElement.childNodes;

Esta tabla se recorre con un bucle for. 

Una  particularidad  es  que,  para  mostrar  solo  los  nodos  directamente  conectados  a  la  raíz,  hay  que  prever  una 
comprobación del tipo de nodo, como sigue: 

if (listaNodosRaiz[i].nodeType == 1)

La visualización se obtiene con: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


document.write(" - " + listaNodosRaiz[i].nodeName + "<br />");

Después de este bucle  for, a título de ejemplo, el nombre y el tipo del nodo raíz (coches) también se muestran 
en pantalla. 

La indicación nodeType puede tomar los siguientes valores en un árbol DOM (fuente developer.mozilla.org): 

l 1: Nodo elemento, 

l 2: Nodo atributo, 

l 3: Nodo texto, 

l 4: Nodo de sección CDATA, 

l 5: Nodo de referencia a una entidad, 

l 6: Nodo de entidad, 

l 7: Nodo de instrucción de procesamiento, 

l 8: Nodo de comentario, 

l 9: Nodo de documento, 

l 10: Nodo de tipo de documento, 

l 11: Nodo de fragmento de documento, 

l 12: Nodo de notación. 

5. Ejemplo 5: Lista de los campos (nodos) de cada coche

En este ejemplo, vamos a listar los campos (nodos) de cada coche. 

En nuestro caso, obtendremos la siguiente visualización: 

También  hemos  aprovechado  este  recorrido  por  los  campos  para  mostrar  los  dos  enlaces  Web  que  describen  el 
segundo coche de nuestro archivo coches.xml. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Pasemos al estudio del código JavaScript situado en la sección HTML <body>. 

Después  de  la  creación  del  objeto  XMLHttpRequest,  el  acceso  al  archivo  XML  coches.xml  y  la  creación  del 
documento DOM en memoria, analizamos la secuencia de código específica de este ejemplo. 

La primera secuencia tiene que ver con la lista de campos (nodos) de cada coche: 

/*
Mostrar la lista de campos (nodos) de cada coche
NB: La lista se basa en la del primer coche
*/
/*Mostrar el título de la lista */
document.write("Lista de los campos (nodos) de cada coche:<br />")
/* Constitución de la lista de los nodos hijos
de coche (basada en el primer coche) */
listaCamposCoche =
xmlDoc.getElementsByTagName("coche")[0].childNodes;
/* Inicialización del valor del primer hijo (marca) */
campoCoche =
xmlDoc.getElementsByTagName("coche")[0].firstChild;
/* Recorrido de los hijos */
for (i=0; i<listaCamposCoche.length; i++)
{
/* Prueba el tipo del nodo para mostrar solo los nodos elementos */
/*
nodeType: 1 -> nodo elemento
nodeType: 2 -> nodo atributo
nodeType: 3 -> nodo texto
nodeType: 4 -> nodo de sección CDATA
nodeType: 5 -> nodo de referencia a una entidad
nodeType: 6 -> nodo de entidad
nodeType: 7 -> nodo de instrucción de procesamiento
nodeType: 8 -> nodo de comentario
nodeType: 9 -> nodo de documento
nodeType: 10 -> nodo de tipo de documento
nodeType: 11 -> nodo de fragmento de documento
nodeType: 12 -> nodo de notación
*/
if (campoCoche.nodeType == 1)
{
document.write(" - " + campoCoche.nodeName + "<br />");
}
/* Pasar al campo siguiente */
campoCoche = campoCoche.nextSibling;
}

Después de haber formado la lista de los nodos que dependen (hijos) del nivel coche, nos basamos en la primera 
ocurrencia de coche como sigue: 

listaCamposCoche =
xmlDoc.getElementsByTagName("coche")[0].childNodes;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Nos situamos en el primer hijo: 

campoCoche =
xmlDoc.getElementsByTagName("coche")[0].firstChild;

Solo  falta  recorrer  los  campos,  usando  el  método  nextSibling  (pasando  al  nodo  siguiente  del  mismo  nivel). 
Observe que hay que filtrar una vez más para mostrar solo en caso de nodo de tipo 1 (nodo elemento). 

Una segunda secuencia posterior sirve para mostrar los dos enlaces Web, que describen el segundo coche: 

/*
Mostrar el número de sitios Web que describen
el segundo coche (con número 1)
*/
document.write("<br />");
document.write("Lista de los sitios Web que describen el segundo coche:<br />")
listaCamposCoche = xmlDoc.getElementsByTagName("coche")[1].childNodes;
campoCoche = xmlDoc.getElementsByTagName("coche")[1].firstChild;
for (i=0; i<listaCamposCoche.length; i++)
{
if (campoCoche.nodeType == 1 && campoCoche.nodeName == "site_web")
{
document.write(" - " + campoCoche.nodeName + ": "
+ campoCoche.childNodes[0].nodeValue + "<br />");
}
/* Pasar al campo siguiente */
campoCoche = campoCoche.nextSibling;
}

Observe  que  el  desarrollo  es  muy  similar  al  del  procesamiento  anterior.  La  única  diferencia  está  a  nivel  de  la 
comprobación: 

if (campoCoche.nodeType == 1 && campoCoche.nodeName == "site_web")

6. Ejemplo 6: Sustitución de un valor de nodo

Aunque  se  trate  de  una  operación  menos  frecuente,  veamos  cómo  es  posible  modificar  un  valor  en  el  documento 
XML en memoria, después de su lectura desde el archivo  coches.xml. El código está, una vez más, ubicado en la 
sección HTML <body>: 

/* Sustitución de un valor de nodo (marca) en el primer coche */


marcaCoche = xmlDoc.getElementsByTagName("marca")[0].childNodes[0];
marcaCoche.nodeValue = "FERRARI ITALIA";

/* Control de la sustitución terminada */


marcaCoche = xmlDoc.getElementsByTagName("marca")[0].childNodes[0];
textoMarcaCoche = marcaCoche.nodeValue;

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


document.write("A partir de ahora, la marca del primer coche es: "
+ textoMarcaCoche);

No hay nada complicado en realidad. Después de haber detectado la primera ocurrencia de la etiqueta  coche, es 
suficiente con intervenir sobre el valor del nodo (nodeValue). A continuación, se realiza un control para comprobar 
el impacto de la modificación. 

Cuando se visualiza el script, obtenemos: 

7. Ejemplo 7: Acceso a los atributos

Volvamos al contenido del archivo XML coches.xml: 

<coches>
<coche origen="ITALIA" grupo="FIAT">
...
</coche>
<coche origen="ITALIA" grupo="VOLKSWAGEN">
...
</coche>
<coche origen="ALEMANIA" grupo="VOLKSWAGEN">
...
</coche>
</coches>

Veamos cómo acceder a los atributos origen y grupo de los diferentes coches: 

/* Acceso a los atributos del primer coche (con número 0) */


primerCoche = xmlDoc.getElementsByTagName("coche")[0].attributes;

/* Mostrar el valor del atributo origen


del primer coche (con número 0) */
document.write("Origen del primer coche: "
+ primerCoche.getNamedItem("origen").nodeValue + "<br />");

/* Acceso a los atributos del tercer coche (con número 2) */


tercerCoche = xmlDoc.getElementsByTagName("coche")[2].attributes;

/* Mostrar el valor del atributo origen


del tercer coche (con número 2) */
document.write("Origen del tercer coche: "
+ tercerCoche.getNamedItem("origen").nodeValue + "<br />");

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


/* Mostrar el valor del atributo grupo
del tercer coche (con número 2) */
document.write("Grupo del tercer coche: "
+ tercerCoche.getNamedItem("grupo").nodeValue);

El  código  está  muy  comentado  y  no  necesita  explicaciones  adicionales.  Solo  señalemos  que  la  propiedad 
attributes devuelve una colección de atributos específicos del elemento dado. 

La visualización obtenida cuando se ejecuta el script es la siguiente: 

8. Ejemplo 8: Acceso a un nodo padre

Durante  la  navegación  por  un  árbol  XML,  puede  ser  interesante  acceder  al  nodo  padre  del  nodo  actual.  Veamos 
cómo realizar esta operación con una pequeña secuencia de código: 

/* Bucle para mostrar la marca de los coches */


marcasCoches = xmlDoc.getElementsByTagName("marca");
alert("Número de coches: " + marcasCoches.length);
for ( i=0; i<marcasCoches.length; i++)
{
/* Mostrar la marca del coche actual
y de su nodo padre */
document.write("Marca del coche número "
+ (i+1)
+ ": "
+ marcasCoches[i].childNodes[0].nodeValue
+ " (tiene como padre "
+ marcasCoches[i].parentNode.nodeName
+ ")<br />");
}

En nuestro ejemplo, recorremos la tabla en memoria marcasCoches, que contiene todos los nodos marca, con un 
bucle for. 

Con la instrucción marcasCoches[i].parentNode.nodeName, se recupera el nombre del nodo padre. 

No es ninguna sorpresa descubrir que cada nodo marca tiene como padre el nodo coche: 

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


9. Ejemplo 9: Recorrer hacia atrás los nodos

Estudiemos también con un pequeño script cómo recorrer hacia atrás una lista de nodos (del último al primero): 

/* Mostrar los nodos hijos (hacia atrás) del nodo coche


para el tercer coche (con número 2) */
listaCamposCoche = xmlDoc.getElementsByTagName("coche")[2].childNodes;
campoCoche = xmlDoc.getElementsByTagName("coche")[2].lastChild;
for ( i=0; i<listaCamposCoche.length; i++)
{
if (campoCoche.nodeType == 1)
{
document.write(" - "
+ campoCoche.nodeName
+ ": "
+ campoCoche.childNodes[0].nodeValue
+ "<br />");
}
/* Pasar al campo anterior */
campoCoche = campoCoche.previousSibling;
}

En primer lugar, se construye la lista de los nodos hijos del tercer coche (numerado con 2): 

listaCamposCoche =
xmlDoc.getElementsByTagName("coche")[2].childNodes;

Posteriormente, la ubicación en el último hijo se hace como sigue: 

campoCoche = xmlDoc.getElementsByTagName("coche")[2].lastChild;

A continuación, tenemos una estructura iterativa con, esta vez, el uso del método previousSibling: 

campoCoche = campoCoche.previousSibling;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


El resultado de la ejecución es el siguiente: 

10. Ejemplo 10: Sustitución sistemática  de un valor de atributo

Recordemos los valores de atributos para nuestros tres coches: 

<coches>
<coche origen="ITALIA" grupo="FIAT">
...
</coche>
<coche origen="ITALIA" grupo="VOLKSWAGEN">
...
</coche>
<coche origen="ALEMANIA" grupo="VOLKSWAGEN">
...
</coche>
</coches>

Es posible efectuar una sustitución sistemática de estos valores como sigue: 

/* Sustitución del valor del atributo origen


para todos los coches */
coche = xmlDoc.getElementsByTagName("coche");
for (i=0; i<coche.length; i++)
{
/* Sustitución */
coche[i].setAttribute("origen", "EUROPA");
/* Control de la sustitución */
document.write("País del constructor del coche número"
+ (i+1)
+ ": "
+ coche[i].getAttribute("origen")
+ "<br />");
}

El método  setAttribute aplicado a cada elemento de la tabla coche permite modificar el valor de este atributo. 
Recordemos que coche es una tabla que reagrupa todos los nodos coche del archivo coches.xml. 

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


También se realiza un control, después de la modificación, con el método getAttribute. 

La ejecución del script da la siguiente visualización: 

11. Ejemplo 11: Conversión XML en HTML

Para hacer la visualización del flujo XML más sencilla, puede ser pertinente realizar una conversión en código HTML. 

Construimos una tabla HTML de dos columnas a partir de los nodos  marca  y  modelo de nuestro flujo XML como 


sigue: 

/*
Creación de la tabla HTML
*/
/* Etiqueta HTML de inicio de tabla */
document.write("<table border=’1’>");
/* Establece la línea de nombres de columnas */
document.write("<tr>");
document.write("<td>");
document.write("marca");
document.write("</td>");
document.write("<td>");
document.write("modelo");
document.write("</td>");
document.write("</tr>");
/* Recorrido de la lista de coches */
var coche = xmlDoc.getElementsByTagName("coche");
for (i=0; i<coche.length; i++)
{
/* Establece una nueva línea en la tabla HTML */
document.write("<tr>");
/* Apertura de la primera columna (marca del coche) */
document.write("<td>");
/* Escritura de la marca del coche */
document.write(coche[i]
.getElementsByTagName("marca")[0]
.childNodes[0]
.nodeValue);
/* Cierre de la primera columna */
document.write("</td>");
/* Apertura de la segunda columna (modelo del coche) */
document.write("<td>");

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


/* Escritura del modelo del coche */
document.write(coche[i]
.getElementsByTagName("modelo")[0]
.childNodes[0]
.nodeValue);
/* Cierre de la segunda columna */
document.write("</td>");
/* Cierre de la línea en la tabla HTML */
document.write("</tr>");
}
/* Etiqueta HTML de fin de tabla */
document.write("</table>");

El  script,  un  poco  largo,  no  tiene  ninguna  dificultad.  Una  tabla  coche  se  construye  a  partir  de  la  lista  de  nodos 
coche: 

var coche = xmlDoc.getElementsByTagName("coche");

Después se recorre con un bucle for. 

La recuperación de los dos valores de nodo (campo) para cada coche se obtiene como sigue: 

document.write(coche[i]
.getElementsByTagName("marca")[0]
.childNodes[0]
.nodeValue);

document.write(coche[i]
.getElementsByTagName("modelo")[0]
.childNodes[0]
.nodeValue);

El resto del código está formado por el formato HTML de la tabla. 

La tabla HTML tendrá la siguiente apariencia: 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


12. Ejemplo 12: Eliminación de un nodo en un flujo XML

Nos falta ver cómo eliminar un nodo de un documento DOM en memoria. 

El método removeChild es fácil de implementar. 

En contrapartida, vamos a tener que desarrollar un ejemplo un poco más interesante para realizar una eliminación 
de nodo. 

Sección HTML <body> 

En esta parte, se llama consecutivamente a tres funciones JavaScript, que estudiaremos más adelante: 

/* Carga de los coches desde el archivo XML en un árbol */


cargarCoches();

/* Mostrar la lista de los coches */


mostrarCoches();

/* Eliminar el primer coche */


var confirmationEliminacionCoche = confirm("¿Eliminar el primer
coche?");
if (confirmationEliminacionCoche == true)
{
eliminarCoche();
}

La  secuencia  es  muy  lógica.  En  primer  lugar,  se  lee  el  archivo  XML  coches.xml  para  formar  nuestro  árbol  y 
después se visualiza antes de la eliminación de un nodo controlado con un  confirm (se trata del primer uso del 
método  confirm en este libro). Una vez que se ha realizado la eliminación, se vuelve a visualizar el árbol, como 
veremos más adelante. 

Sección HTML <head> 

La primera función, cargarCoches, no tiene nada de nuevo: 

/* Función cargarCoches */
function cargarCoches()
{
/* Creación de un objeto XMLHttpRequest para intercambiar datos
con el servidor en formato texto, XML o JSON

NB: Los archivos XML se parsean automáticamente


por el objeto y son accesibles con los métodos del DOM
*/
if (window.XMLHttpRequest)
{
// Código específico para los navegadores
// IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


else
{
// Código específico para los navegadores IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

/* Apertura del archivo XML coches.xml en modo síncrono (false)*/


xmlhttp.open("GET", "coches.xml", false);

/* Lanzar la consulta HTTP al servidor */


xmlhttp.send();

/* Creación del documento XML en memoria */


xmlDoc = xmlhttp.responseXML;

/* Establece el título del procesamiento */


document.write("<h1>Ediciones ENI - JavaScript - DOM_XML_12</h1>");
}

La función mostrarCoches retoma el código visto en el ejemplo anterior; por tanto, no se muestra aquí. 

La tercera función, eliminarCoche, es más interesante: 

/* Función eliminarCoche */
function eliminarCoche()
{
/* Mostrar el número de coche(s) antes del borrado */
alert("Número de coche(s) antes del borrado: "
+ xmlDoc.getElementsByTagName(’coche’).length);
/* Borrar el primer coche */
cocheEliminado = xmlDoc.getElementsByTagName("coche")[0];
xmlDoc.documentElement.removeChild(cocheEliminado);
/* Mostrar el número de coche(s) después del borrado */
alert("Número de coche(s) después del borrado: "
+ xmlDoc.getElementsByTagName(’coche’).length);
document.write("<br /><br />Lista de los coches después del borrado");
mostrarCoches();
/* Valor de retorno */
return true;
}

El borrado del primer coche se hace con la secuencia: 

/* Borrar el primer coche */


cocheEliminado = xmlDoc.getElementsByTagName("coche")[0];
xmlDoc.documentElement.removeChild(cocheEliminado);

Esta  función  también  llama  a  la  función  mostrarCoches  cuando  se  hace  la  eliminación  del  primer  coche,  por 
control: 

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


mostrarCoches();

Obtenemos esta visualización cuando se ejecuta el script: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


Noción de cookie

Gracias  a  las  cookies,  es  posible  escribir  en  el  puesto  del  usuario  información  de  manera  permanente.  Sin  esta 
posibilidad,  sería  necesario  recurrir  a  un  lenguaje  de  programación  "orientado  a  servidor"  (PHP,  Microsoft  ASP.NET, 
por ejemplo), para almacenar datos en un sistema de gestión básico de datos (MySQL, PosgreSQL...). 

Las  cookies,  que  se  presentan  como  pequeños  archivos  de  texto,  pueden  contener  un  número  limitado  de  datos, 
pero esta técnica puede ser muy valiosa para conservar contenidos de variables en memoria, reutilizables a lo largo 
de la navegación a través de muchas páginas de su sitio Web (conservar identificadores, contraseñas (aunque esto 
sea peligroso), preferencias de usuario...). 

Observe que es posible impedir, en la gran mayoría de los navegadores, que se usen las cookies. Es cierto que esta 
técnica es relativamente intrusiva. Un sitio Web podría, por ejemplo (si no se previene), almacenar en su disco duro 
sus  preferencias  respecto  a  compras  y  consultas  y,  de  esta  manera,  proponerle  durante  una  sesión  en  Internet 
posterior productos y servicios correspondientes a sus expectativas. En realidad, pocos usuarios bloquean el uso de 
las cookies, porque una gran mayoría de sitios Web las usan (el bloqueo volvería casi imposible la navegación por el 
sitio la mayor parte del tiempo). 

Referencia: http://www.w3schools.com/js/js_cookies.asp  

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Escritura de una cookie

La creación de una cookie se hará a través de una función JavaScript, que vamos a crear (poco importa su nombre) 
como sigue: 

/* Definición de la función Javascript de creación de una cookie */


function creacionCookie(nombreCookie, valorCookie, expiracionCookie,
rutaCookie, dominioCookie, seguridadCookie)
{
document.cookie = nombreCookie + ’ = ’ + escape(valorCookie) + ’ ’ +
((expiracionCookie == undefined)? ’’: (’; expires=’ +
expiracionCookie.toGMTString())) + ((rutaCookie == undefined)? ’’:
(’; path=’ + rutaCookie)) + ((dominioCookie == undefined)? ’’:
(’; domain=’ + dominioCookie)) + ((seguridadCookie == true)? ’;
seguridadCookie’: ’’);
}

// La función escape codifica los caracteres especiales sustituyéndolos


// por una secuencia %sustituyendo donde sustituyendo es un número
// hexadecimal

/* Creación de una cookie llamando a la función creacionCookie */


var dateExpiration = new Date();
dateExpiration.setTime(dateExpiration.getTime() + 300 * 1000);
// NB: - dateExpiration es un objeto de tipo date (por defecto inicializado
// a la fecha del sistema)
// - La fecha de fin de validez de la cookie (se eliminará),
// se calcula a partir de la fecha del sistema (5 minutos más tarde
// aquí, es decir, 300 segundos)
creacionCookie("miCookie", "Ediciones ENI", dateExpiration, "/");
// Valor de la cookie: Ediciones ENI
// Expiración de la cookie: En 5 minutos (300 segundos)
// Accesibilidad: Accesible por todo el sitio

/* Mensaje de control */
document.write("La cookie miCookie (contiene Ediciones ENI) se ha escrito
correctamente en el disco duro");

La función creacionCookie tiene dos argumentos obligatorios: el nombre y el valor de la cookie. 

El valor de la cookie puede contener caracteres especiales. La función JavaScript  escape() permite sustituir estos 
caracteres especiales (acentos...) por códigos hexadecimales. Evidentemente, cuando se lee la cookie, se realiza una 
codificación inversa, con la función unescape(). 

Según  la  fuente  developper.mozilla.org,  las  funciones  escape  y  unescape  permiten  proteger  las  cadenas  de 
caracteres,  codificando  y  descodificando  los  caracteres  especiales.  Con  escape,  cada  carácter  que  se  pueda 
interpretar como un carácter especial se formatea con %NN, donde NN representa el valor hexadecimal del carácter en el 
conjunto de caracteres ISO Latin 1 (ISO­8859­1). 

La codificación por la función  escape() no se ha hecho aquí porque el nombre previsto para la cookie ( miCookie) 


no lo necesita. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


dateExpiration es un objeto de tipo fecha que no es obligatorio. Ahí almacenamos la fecha del sistema, más un 
intervalo de 5 minutos, como sigue: 

var dateExpiration = new Date();


dateExpiration.setTime(dateExpiration.getTime() + 300 * 1000);

En  caso  de  ausencia  de  este  argumento  opcional,  la  cookie  será  automáticamente  eliminada  al  final  de  la  sesión 
(secuencia de código, en general de PHP, durante la cual la conservación de las cookies está prevista). 

El argumento rutaCookie indica la ruta en el servidor. Con el valor /, la cookie será utilizable en todo el sitio Web. 
Si el argumento no se indica o si es null, el valor por defecto será la URL de la página Web. 

El  argumento  dominioCookie  juega  casi  el  mismo  papel  que  rutaCookie,  pero  esta  vez  para  el  dominio 
indicado. 

Para  terminar,  es  posible  proporcionar  un  último  argumento,  relacionado  con  la  seguridad.  El  argumento 
securityCookie deberá ser igual a true para un uso en conexiones seguras https. 

Cuando se ejecuta del script, obtenemos: 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Lectura de una cookie
Creemos  una  función  de  nombre  lecturaCookie  para  leer  la  cookie  miCookie,  vista  en  la  sección  anterior.  El 
valor deseado de retorno para esta función será el valor de la cookie, es decir, ’Ediciones ENI’. 

En primer lugar, nuestra función lee el contenido completo de la cookie. Posteriormente la función  lecturaCookie 
aísla el elemento deseado (el valor) para devolverlo. 

El código (parcial) del script es el siguiente: 

/* Definición de la función JavaScript de lectura de una cookie */


function lecturaCookie(nombreCookie)
{
/* Prueba la presencia de la cookie */
if (document.cookie.length == 0)
{
/* Valor de retorno null */
return null;
}
else
{
/* Añadir en la tabla tabElements los elementos de la cookie */
/* NB: Nos basamos en el separador punto y coma */
var tabElements = document.cookie.split(";");
/* Buscar el = separando el nombre del elemento,
del valor del elemento para el primer elemento (número 0) */
var posicionIgual = tabElements[0].indexOf("=", 0);
/* Determinación del nombre del elemento */
var nombreElement = tabElements[0].substring(0, posicionIgual);
/* Determinación del valor del elemento */
var valorElement = tabElements[0].substring(posicionIgual+1);
/* Si el nombre del elemento contiene
el nombre correcto de la cookie */
if (nombreElement == nombreCookie)
{
/* Volver al valor del elemento
(con reimplantación de los caracteres especiales) */
/* NB: Este elemento contiene normalmente Ediciones ENI */
return unescape(valorElement);
}
/* Valor de retorno */
return null;
}
}

/* Lectura de una cookie llamando a la función lecturaCookie */


/* NB: La cookie tiene como valor "Ediciones ENI" en nuestro caso. */
if (lecturaCookie("miCookie") == null) {
document.write("La cookie miCookie no se ha encontrado");
}
else
{
document.write("El valor de la cookie miCookie es: "
+ lecturaCookie("miCookie"));

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


}

El script empieza comprobando la presencia del archivo cookie: 

if (document.cookie.length == 0)

Si no se encuentra, se devuelve un valor null. 

En caso contrario, el flujo de datos se almacena en una tabla de elementos de nombre  tabElements, basándose 
en  la  presencia  de  separadores  de  duplas  "punto  y  coma"  (uso  de  la  función  split).  Solo  falta  trazar  la  primera 
dupla (numerada con 0), que es la que nos interesa. Esta dupla tiene por nombre de elemento el nombre de la cookie 
en sí misma, y como valor, el contenido (la cadena "Ediciones ENI"), en nuestro caso. Para aislar el nombre del 
elemento y el contenido, se usan funciones de procesamiento de cadenas nativas,  indexOf y  substring. El valor 
de  retorno  de  la  función  lecturaCookie  será,  en  este  caso,  el  valor  del  elemento  número  0  (primera  dupla  del 
archivo cookie). 

La visualización obtenida cuando se ejecuta el script es la siguiente: 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Eliminación de una cookie

La técnica utilizada para eliminar el archivo de cookie es básica. Es suficiente con crear de nuevo la cookie (como se 
hace en la función  creacionCookie) y poner una fecha de expiración anterior a la fecha de sistema (adición de un 
plazo negativo, por ejemplo). 

El código de la función  borradoCookie será, por tanto, muy similar al de la función  creacionCookie, como se 


puede ver a continuación: 

/* Definición de la función Javascript de borrado de una cookie */


function borradoCookie(nombreCookie, valorCookie, expiracionCookie,
rutaCookie, dominioCookie, seguridadCookie)
{
document.cookie = nombreCookie + ’ = ’ + escape(valorCookie) + ’ ’ +
((expiracionCookie == undefined)? ’’: (’; expires =’ +
expiracionCookie.toGMTString())) + ((rutaCookie == undefined)? ’’:
(’; path = ’ + rutaCookie)) + ((dominioCookie == undefined)? ’’:
(’; domain = ’ + dominioCookie)) + ((seguridadCookie == true)? ’;
seguridadCookie’: ’’);
}
// La función escape codifica los caracteres especiales sustituyéndolos
// por una secuencia %sustituyendo donde sustituyendo es un número
// hexadecimal

/* Eliminación de una cookie llamando a la función borradoCookie */


var dateExpiration = new Date();
dateExpiration.setTime(dateExpiration.getTime() - 1);
// NB: - dateExpiration es un objeto de tipo date (por defecto
// inicializado a la fecha del sistema)
// - La fecha de fin de validez de la cookie (se eliminará) se calcula
// a partir de la fecha de sistema (-1 -> la cookie se elimina
// inmediatamente)
borradoCookie(’miCookie’, ’’, dateExpiration, ’/’);
// Nombre de la cookie: miCookie
// Valor de la cookie: Vacía
// Expiración de la cookie: inmediata (fecha de expiración anterior
// a la fecha de sistema)
// Accesibilidad: Accesible inmediatamente

/* Mensaje de control */
document.write("La cookie miCookie se ha eliminado del disco");

El script no merece ningún comentario particular. 

La ejecución del script genera la siguiente visualización: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack
Presentación general de las soluciones

En el capítulo anterior, hemos visto cómo almacenar pequeñas cantidades de información en las cookies (4 KB como 
máximo). 

Hay dos soluciones, llamadas Web Storage, que son alternativas al uso de cookies: 

l el almacenamiento de la sesión, 

l el almacenamiento local. 

Como para las cookies, el almacenamiento con estas dos interfaces llamadas respectivamente  sessionStorage y 
localStorage  se  lleva  a  cabo  en  el  lado  navegador.  Por  tanto,  no  hay  que  confundir  estas  dos  técnicas  con  un 
almacenamiento remoto en base de datos. Además, en el próximo capítulo veremos cómo implementar este tipo de 
soluciones usando el protocolo SOAP (Simple Object Access Protocol), una librería PHP dedicada NuSOAP y el sistema 
de gestión de base de datos MySQL. 

El Web Storage, también llamado DOM Storage, apareció con HTML 5. Sin embargo, este modo de almacenamiento es 
aceptado por la gran mayoría de los navegadores. 

La  ventaja  principal  del  Web Storage  respecto  a  las  cookies  es  la  posibilidad  de  almacenar  una  mayor  cantidad  de 
información  (5  MB  como  máximo).  Además,  contrariamente  a  lo  que  sucede  con  las  cookies,  las  interfaces 
sessionStorage y  localStorage no requieren tráfico HTTP en la red. Recordemos que las cookies se guardan 
en el disco duro del usuario (por lo que es necesaria una transferencia HTTP), mientras que la información gestionada 
por sessionStorage y localStorage son locales (sin transferencia HTTP). 

1. Almacenamiento con sessionStorage

La persistencia de datos está limitada a la duración de la sesión del usuario; los datos solo se conservan para la 
ventana activa (o la pestaña). Los datos almacenados solo se pueden recuperar a través del navegador que los ha 
almacenado. 

Es  necesario  observar  que,  en  la  descarga  del  almacenamiento  con  sessionStorage  (también  es  cierto  para 
localStorage), los datos no se cifran y esto puede tener un impacto en los datos almacenados en un puesto de 
trabajo utilizado por varios usuarios. 

Cuando se cierra el navegador, los datos se eliminan. 

2. Almacenamiento con localStorage

La  interface  localStorage  es  muy  parecida  a  la  anterior.  La  persistencia  se  gestiona  de  manera  diferente.  A 
priori, no hay límite temporal al almacenamiento. Los datos se conservan más allá del cierre de la ventana activa (o 
de  la  pestaña).  También  es  posible  utilizar  los  datos  almacenados  en  varias  ventanas  (o  pestañas)  de  un  mismo 
dominio. Como para el almacenamiento con sessionStorage, el mecanismo necesita utilizar el mismo navegador. 

Evidentemente, como para  sessionStorage, existen dos métodos dedicados para eliminar los datos guardados 
bajo demanda. 

Otro punto común entre  sessionStorage y  localStorage (igual que para las cookies) es que solo permiten 


almacenar cadenas de caracteres. Para almacenar tablas u objetos, será necesario utilizar JSON (JavaScript Object 
Notation). No se preocupe, se va a presentar un ejemplo completo en este capítulo. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Implementación de Web Storage a través de ejemplos
Como los métodos asociados a  sessionStorage y a localStorage son idénticos, en los dos ejemplos usamos 
localStorage. 

1. Ejemplo 1: Almacenamiento por localStorage de cadenas de caracteres

En  este  primer  ejemplo,  el  objetivo  va  a  ser  estudiar  las  posibilidades  que  ofrece  localStorage  en  la  gestión 
(creación, acceso y eliminación) de información de tipo cadenas de caracteres. 

Script completo 

El código fuente del script se muestra completo a continuación: 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!--
NOMBRE DEL SCRIPT: LOCAL_STORAGE_01.htm
REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Almacenamiento usando localStorage
-->

<!-- Inicio script HTML -->


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />

<!-- Título del script HTML -->


<title>LOCAL_STORAGE_01</title>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Declaración de variables comunes


a todas las funciones */
var titulo;
var nombrePersona;
var apellidosPersona;
var mailPersona;

/* Función escribirLocalStorage */
function escribirLocalStorage()
{
/* Verifica posibilidades de usar localStorage */

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


if (typeof localStorage != "undefined")
{
/* Almacenamiento del nombre (nombrePersona)
en el almacenamiento localStorage */
nombrePersona = "Ángel";
localStorage.setItem("nombrePersona",
nombrePersona);
/* Almacenamiento de los apellidos (apellidosPersona)
en el almacenamiento localStorage */
apellidosPersona = "Sánchez";
localStorage.setItem("apellidosPersona",
apellidosPersona);
/* Almacenamiento del mail (mailPersona)
en el almacenamiento localStorage */
mailPersona = "[email protected]";
localStorage.setItem("mailPersona",
mailPersona);
/* Mostrar el control */
titulo
= "Contenido del localStorage (después de la escritura)";
document.getElementById("titulo").innerHTML
= titulo;
document.getElementById("nombrePersona").innerHTML
= nombrePersona;
document.getElementById("apellidosPersona")
.innerHTML = apellidosPersona;
document.getElementById("mailPersona").innerHTML
= mailPersona;
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

/* Función leerLocalStorage */
function leerLocalStorage()
{

/* Prueba posibilidades de usar localStorage */


if (typeof localStorage != "undefined")
{
/* Recuperación del nombre (nombrePersona)
desde el almacenamiento localStorage */
nombrePersona = localStorage.getItem("nombrePersona");
/* Recuperación del apellidos (apellidosPersona)
desde el almacenamiento localStorage */
apellidosPersona
= localStorage.getItem("apellidosPersona");
/* Recuperación del mail (mailPersona)
desde el almacenamiento localStorage */
mailPersona
= localStorage.getItem("mailPersona");

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Mostrar el control */
titulo
= "Contenido del localStorage (después de la relectura)";
document.getElementById("titulo").innerHTML
= titulo;
document.getElementById("nombrePersona")
.innerHTML = nombrePersona;
document.getElementById("apellidosPersona")
.innerHTML = apellidosPersona;
document.getElementById("mailPersona")
.innerHTML = mailPersona;
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

/* Función eliminarLocalStorage */
function eliminarLocalStorage()
{

/* Prueba posibilidades de usar localStorage */


if (typeof localStorage != "undefined")
{
/* Eliminación de las entradas nombrePersona,
apellidosPersona y mailPersona
en el localStorage */
/* NB: sessionStorage.clear(); eliminará
también el conjunto de entradas
del localStorage */
sessionStorage.removeItem("nombrePersona");
sessionStorage.removeItem("apellidosPersona");
sessionStorage.removeItem("mailPersona");
/* Mostrar el control */
titulo
= "Contenido del localStorage (después del borrado)";
document.getElementById("titulo")
.innerHTML = titulo;
document.getElementById("nombrePersona")
.innerHTML = "";
document.getElementById("apellidosPersona")
.innerHTML = "";
document.getElementById("mailPersona")
.innerHTML = "";
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


</script>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - LOCAL_STORAGE_01</h1>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Mostrar el nombre del script */


alert("LOCAL_STORAGE_01");

</script>

<!-- Formulario con un botón de escritura,


un botón de lectura y un botón de borrado -->
<form>
<input
type="button"
id="botonEscritura"
value="Escritura en localStorage"
onclick="escribirLocalStorage();"
/>
<br />
<input
type="button"
id="botonLectura"
value="Lectura desde localStorage"
onclick="leerLocalStorage();"
/>
<br />
<input
type="button"
id="botonEliminacion"
value="Eliminación de la entrada en localStorage"
onclick="eliminarLocalStorage();"
/>
</form>

<!-- Mostrar el contenido del sistema de almacenamiento -->


<br />
<span id="titulo"></span><br />
<span id="nombrePersona"></span><br />
<span id="apellidosPersona"></span><br />
<span id="mailPersona"></span>

<!-- Mostrar el código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=’view-source:’ +

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


window.location">
Código fuente
</a>
</center>

</body>

</html>

Formulario con tres botones 

Empecemos por los tres botones <input type="button" ...> del formulario HTML: 

<!-- Formulario con un botón de escritura, un botón de lectura y


un botón de borrado -->
<form>
<input type="button" id="botonEscritura" value="Escritura en
localStorage" onclick="escribirLocalStorage();"/>
<br />
<input type="button" id="botonLectura" value="Lectura desde
localStorage" onclick="leerLocalStorage();"/>
<br />
<input type="button" id="botonEliminacion" value="Eliminación
de la entrada en localStorage" onclick="eliminarLocalStorage();"/>
</form>

El  primero  (id="botonEscritura")  ejecuta  una  función  llamada  escribirLocalStorage, que  sirve  para 
almacenar  tres  datos  (nombre,  apellido  y  dirección  de  mail  de  una  persona  en  un  sistema  de  almacenamiento 
localStorage). 

El papel del segundo botón ( id="botonLectura") es inverso. Ejecuta una función  leerLocalStorage, que 


leerá del sistema de almacenamiento localStorage los tres datos registrados. 

Para terminar, el último botón (id="botonEliminacion"), a través de la función  eliminarLocalStorage, 
eliminará los datos almacenados en el sistema de almacenamiento. 

Visualización del contenido del localStorage 

También se muestra el contenido del sistema de almacenamiento en el formulario: 

<!-- Mostrar el contenido del sistema de almacenamiento --><br />


<span id="titulo"></span><br />
<span id="nombrePersona"></span><br />
<span id="apellidosPersona"></span><br />
<span id="mailPersona"></span>

Función JavaScript escribirLocalStorage 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


Pasemos ahora a estudiar detalladamente las tres funciones mencionadas. 

En  la  función  escribirLocalStorage,  se  realiza  una  comprobación  para  saber  si  el  navegador  soporta  la 
gestión de un localStorage: 

/* Prueba las posibilidades de usar localStorage */


if (typeof localStorage != "undefined")
{
/* Procesamiento posible */
}
else
{
/* Mensaje de error (sin posibilidades de almacenamiento localStorage) */
alert("localStorage no soportado");
}

En  caso  favorable,  almacenamos  consecutivamente  la  información  en  el  localStorage (caso  para 
nombrePersona siguiente): 

/* Almacenamiento del nombre (nombrePersona) en el almacenamiento localStorage */


nombrePersona = "Ángel";
localStorage.setItem("nombrePersona", nombrePersona);

Recordemos que la variable en memoria  nombrePersona, a la que se asigna arbitrariamente " Sánchez", se ha 


declarado al inicio de script: 

/* Declaración de variables comunes a todas las funciones */


var nombrePersona;

Evidentemente,  en  una  aplicación  más  realista,  los  datos  no  serían  solo  constantes,  sino,  por  ejemplo,  datos  de 
formulario o incluso resultados de cálculo. 

Como  se  indica  al  inicio  de  la  presentación  de  este  ejemplo,  también  tenemos  una  actualización  de  tres  campos 
<span> ... </span> en el formulario, con tres botones para mostrar el contenido de nuestro localStorage: 

/* Visualización de control */
document.getElementById("nombrePersona").innerHTML = nombrePersona;

Función JavaScript leerLocalStorage 

Como  en  la  función  escribirLocalStorage,  se  comprueba  la  capacidad  del  navegador  para  gestionar  un 
localStorage. 

Después  se  recuperan  los  tres  datos  almacenados  en  el 


localStorage  con  la  función 
escribirLocalStorage,  utilizando  el  método  getItem  del  objeto  localStorage.  Para  el  nombre  de  la 
persona ( nombrePersona), la recuperación se hace como sigue: 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Recuperación del nombre (nombrePersona) desde el almacenamiento
localStorage */
nombrePersona = localStorage.getItem("nombrePersona");

Una  vez  que  el  contenido  del  almacenamiento  localStorage  se  lee,  como  para  la  función 
escribirLocalStorage, se actualizan los tres campos <span> ... </span>. 

Función JavaScript eliminarLocalStorage 

El  objetivo  de  esta  última  función  es  eliminar  completamente  el  contenido  del  sistema  de  almacenamiento 
localStorage. 

También se hace una comprobación de la capacidad del navegador para gestionar un localStorage. 

En el script que se ha presentado, se utiliza el método  removeItem del objeto localStorage para cada uno de 
los datos que se han de eliminar. 

/* Eliminación de las entradas nombrePersona, apellidosPersona y


mailPersona en el localStorage */
sessionStorage.removeItem("nombrePersona");
/* ... */

También  es  posible  eliminar  completamente  el  sistema  de  almacenamiento  localStorage  con  el  método 
Session Storage.clear();. 

Resultado de la ejecución 

Un clic en el botón Escritura en localStorage provoca la siguiente visualización: 

Después de la lectura del contenido del localStorage, la visualización se convierte en: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


Para terminar, después de eliminar el localStorage, la visualización obtenida es: 

2. Ejemplo 2: Almacenamiento en el localStorage de un objeto JavaScript

En este segundo ejemplo, el objetivo es asegurar con funciones JavaScript la grabación de la información (nombre, 
apellido y mail de una persona), en un sistema de almacenamiento  localStorage. Pero, esta vez, los tres datos 
se guardarán en un objeto JavaScript. Para asegurar el almacenamiento, tendremos que recurrir a una serialización 
JSON y a la inversa; para recuperar los valores será necesario una deserialización. 

Script completo 

El código fuente del script se muestra completo a continuación: 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!--
NOMBRE DEL SCRIPT: LOCAL_STORAGE_02.htm
REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Almacenamiento usando localStorage y JSON
-->

<!-- Inicio script HTML -->

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />

<!-- Título del script HTML -->


<title>LOCAL_STORAGE_02</title>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Función escribirLocalStorage */
function escribirLocalStorage()
{
/* Prueba posibilidades de usar localStorage y JSON */
if (typeof localStorage != "undefined" && JSON)
{
/* Definición de un objeto JavaScript
datosContactoPersona */
var datosContactoPersona =
{
nombre: document.getElementById("nombre").value,
apellidos: document
.getElementById("apellidos").value,
mail:document.getElementById("mail").value
};
/* Serialización en un objeto JSON
de nombre identidad */
localStorage.setItem("identidad",
JSON.stringify(datosContactoPersona));
alert("Registro en localStorage terminado");
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

/* Función eliminarLocalStorage */
function eliminarLocalStorage()
{
/* Prueba posibilidades de usar localStorage y JSON */
if (typeof localStorage != "undefined" && JSON)
{
/* Eliminación de la entrada identidad
en el localStorage */
/* NB: sessionStorage.clear(); eliminará
también las entradas
del localStorage */

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


sessionStorage.removeItem("identidad");
/* Actualización de los campos para mostrar
(<input type="text" ... />) */
document.getElementById("nombre").value = "";
document.getElementById("apellidos").value = "";
document.getElementById("mail").value = "";
/* Visualización de control */
alert("Eliminación de la entrada identidad
en el localStorage terminada");
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

</script>

</head>

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - LOCAL_STORAGE_02</h1>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Mostrar el nombre del script */


alert("LOCAL_STORAGE_02");

</script>

<!-- Tabla de entrada y para mostrar los campos nombre,


apellidos y mail -->
<table>
<tr>
<td>Nombre</td>
<td>
<input
type="text"
id="nombre"
value=""
size="40"
/>
</td>
</tr>
<tr>
<td>Apellidos</td>
<td>
<input

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


type="text"
id="apellidos"
value=""
size="40"
/>
</td>
</tr>
<tr>
<td>Mail</td>
<td>
<input
type="text"
id="mail"
value=""
size="40"
/>
</td>
</tr>
</table>
<!-- Formulario con botones de escritura,
lectura y borrado -->
<br />
<form>
<input
type="button"
id="botonEscritura"
value="Escritura en localStorage"
onclick="escribirLocalStorage();"
/>
<br />
<input
type="button"
id="botonLectura"
value="Lectura desde localStorage"
/>
<br />
<input
type="button"
id="botonEliminacion"
value="Eliminación de la entrada en localStorage"
onclick="eliminarLocalStorage();"
/>
</form>

<!-- Inicio script JavaScript -->


<script type=’text/javascript’>

/* Lectura desde el localStorage */


document.getElementById(’botonLectura’).onclick
= function() {
/* Prueba posibilidades de usar
localStorage y JSON */
if (typeof localStorage != "undefined" && JSON)
{
/* Deserialización del objeto JSON leído */

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


var datosContactoPersona
= JSON
.parse(localStorage
.getItem("identidad"));
/* Actualización de los campos para mostrar
(<input type="texte" ... />) */
document.getElementById("nombre").value
= datosContactoPersona.nombre;
document.getElementById("apellidos").value
= datosContactoPersona.apellidos;
document.getElementById("mail").value
= datosContactoPersona.mail;
/* Visualización de control */
alert("Lectura desde localStorage terminada");
}
else
{
/* Mensaje de error (sin posibilidades
de almacenamiento localStorage) */
alert("localStorage no soportado");
}
};

</script>

<!-- Mostrar el código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=’view-source:’
+ window.location">
Código fuente
</a>
</center>

</body>

</html>

Introducción de los datos que se van a guardar en el localStorage 

En este script, más evolucionado que el del ejemplo número 1, se le propone al usuario una entrada de datos para 
que  pueda  introducir  los  datos  (nombre,  apellidos  y  mail  de  una  persona)  y  almacenarlos  en  el  sistema  de 
almacenamiento localStorage: 

<!-- Tabla de entrada y para mostrar los campos nombre, apellidos y


mail -->
<table>
<tr>
<td>Nombre</td>
<td><input type="text" id="nombre" value="" size="40"/></td>
</tr>
<tr>

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


<td>Apellidos</td>
<td><input type="text" id="apellidos" value="" size="40"/></td>
</tr>
<tr>
<td>Mail</td>
<td><input type="text" id="mail" value="" size="40"/></td>
</tr>
</table>

Formulario de llamada a las funciones JavaScript 

La ejecución de las tres funciones se realiza con un formulario con tres botones:  

<!-- Formulario con botones de escritura, lectura y borrado -->


<br />
<form>
<input type="button" id="botonEscritura" value="Escritura en
localStorage" onclick="escribirLocalStorage();"/>
<br />
<input type="button" id="botonLectura"value="Lectura desde
localStorage"/>
<br />
<input type="button" id="botonEliminacion" value="Eliminación de
la entrada en localStorage" onclick="eliminarLocalStorage();"/>
</form>

Una  pequeña  particularidad  en  este  script  es  que  las  funciones  escribirLocalStorage  y 
eliminarLocalStorage están en la sección HTML <head> ... </head>, mientras que la función de lectura 
no se llama explícitamente y se ubica en la sección HTML <body> ... </body> en el mismo formulario. 

Ahora, estudiemos en detalle cada una de estas funciones. 

Función escribirLocalStorage 

En  la  función  escribirLocalStorage,  el  código  empieza  comprobando  la  posibilidad  de  utilizar  el 
localStorage en el navegador: 

/* Comprueba la posibilidad de usar localStorage y JSON */


if ( typeof localStorage != "undefined" && JSON)

Observe  que  el  código  es  ligeramente  diferente  al  ya  visto  en  el  ejemplo  número  1.  Se  hace  una  comprobación 
adicional sobre la compatibilidad con JSON. 

Encontrará una definición completa de JSON en el sitio oficial: http://www.json.org/ 

Ahora  veamos  la  secuencia  de  código  para  la  creación  de  un  objeto  JavaScript  datosContactoPersona 
construido a partir de tres campos de entrada de datos ( <input tipo="text" ... >): 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


/* Definición de un objeto Javascript datosContactoPersona */
var datosContactoPersona =
{
nombre: document.getElementById("nombre").value,
apellidos: document.getElementById("apellidos").value,
mail:document.getElementById("mail").value
};

Los objetos JavaScript no se pueden guardar como tal en un sistema de almacenamiento  localStorage porque 
solo se pueden tener en cuenta cadenas de caracteres. 

Conviene  transformar  nuestro  objeto  datosContactoPersona  en  una  cadena  de  caracteres  antes  del 
almacenamiento. Esta operación se llama serialización JSON. 

En los lenguajes Web, como JavaScript o PHP, la serialización consiste en transformar una variable compuesta (como 
una tabla o un objeto) en una cadena de caracteres. 

El código para realizar esta operación es el siguiente: 

/* Serialización en un objeto JSON de nombre identidad */


localStorage.setItem("identidad", JSON.stringify(datosContactoPersona));

El  método  setItem  se  usa  una  única  vez,  los  tres  datos  se  añaden  a  una  cadena  de  caracteres  única 
(identidad). La serialización queda asegurada con el método stringify. 

Los  navegadores  recientes  (incluido  Microsoft  Internet  Explorer  desde  su  versión  8)  soportan  la  función 
JSON.stringify. 

Para que sirva de ejemplo, consideremos los siguientes datos: 

l Nombre: Ángel 

l Apellido: Sánchez 

l Mail: [email protected] 

la serialización daría como resultado: 

{
"nombre":"Ángel",
"apellido":"Sánchez",
"mail":"[email protected]"
}

Función eliminarLocalStorage 

En esta función, el código también empieza comprobando la posibilidad de utilizar el  localStorage y JSON en el 
navegador. 

La eliminación del item identidad, guardado con la función escribirLocalStorage, se realiza como sigue: 

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Eliminación de la entrada identidad en el localStorage */
/* NB: sessionStorage.clear(); eliminará también las entradas
del localStorage */
sessionStorage.removeItem("identidad");

También se hace un borrado de los campos de visualización: 

/* Actualización de los campos para mostrar (<input type="text" ... />) */


document.getElementById("nombre").value = "";
/* ... */

Lectura de los datos desde localStorage 

Para este procesamiento, no hay ninguna función dedicada en la sección HTML <head> ... </head>. 

El código fuente de esta funcionalidad se ha situado al final de la sección HTML <body> ... </body>. 

La sintaxis: 

document.getElementById(’botonLectura’).onclick = function() {
/* ... */
}

asociada al botón identificado por  botonLectura, se ejecuta una función (sin nombre en este caso), al hacer clic 
en el botón. 

En  el  código  de  la  función,  encontrará  la  comprobación  habitual  de  la  posibilidad  de  utilizar  el  localStorage  y 
JSON en el navegador. 

Posteriormente,  se  hace  la  deserialización  del  objeto  JSON  almacenado  en  el  sistema  de  almacenamiento 
localStorage como sigue: 

/* Deserialización del objeto JSON leído */


var datosContactoPersona = JSON.parse(localStorage.getItem("identidad"));

JSON.parse() realiza un procesamiento inverso al de la función  JSON.stringify(). El método espera como 
argumento una cadena de caracteres JSON (identidad en nuestro caso) y la transforma en un objeto JavaScript. 
Esta transformación se llama deserialización. 

También se hace una actualización de los campos de visualización: 

/* Actualización de los campos para mostrar (<input type="text" ... />) */


document.getElementById("nombre").value = datosContactoPersona.nombre;
/* ... */

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


Resultado de la ejecución 

Empecemos  introduciendo  los  tres  campos  de  entrada  de  datos  como  está  previsto  y  validemos  con  un  clic  en  el 
botón ’ Escritura en localStorage ’: 

A continuación, borremos los campos de entrada de datos: 

Terminemos con la relectura de localStorage, con un clic en el botón ’Lectura desde localStorage’: 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Puede comprobar que los valores se han restaurado en los campos de entrada de datos. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


Presentación general de la solución

En los dos capítulos anteriores, hemos visto cómo almacenar datos en el puesto cliente, a través de cookies y objetos 
de Web Storage (sessionStorage y localStorage).  

Estas soluciones son satisfactorias para la persistencia de datos a pequeña escala (grabación de argumentos útiles 
durante la navegación entre las páginas de un mismo sitio Web, almacenamiento de las preferencias de usuario...). 
También es posible recurrir a objetos de Web Storage para realizar una entrada de datos en modo no conectado, con 
una sincronización con el servidor cuando se restablece la conexión. 

Es preferible la solución de persistencia con un almacenamiento de datos centralizado en un servidor remoto (si es 
preciso, con un complemento en Web Storage). La aplicación es evidentemente más compleja. Este es el objetivo de 
este capítulo. 

El  objetivo,  por  tanto,  va  a  ser  poder  acceder  a  los  datos  almacenados  en  un  sistema  gestor  de  bases  de  datos 
(SGBD) MySQL, con los protocolos HTTP y SOAP, a través de una librería de funciones PHP NuSOAP. 

En  los  dos  ejemplos  que  se  van  a  comentar,  se  ha  hecho  una  elección  arbitraria  a  nivel  del  SGBD,  MySQL.  Para  la 
librería NuSOAP, la observación es la misma. No obstante, la programación es muy genérica y no tendrá dificultades 
para hacer una aplicación personal en sus propios proyectos, incluyendo diferentes SGBD. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Implementación del almacenamiento remoto a través de ejemplos

Se van a presentar dos ejemplos completos de aplicación. 

Para estos ejemplos, se utilizará una tabla llamada coches, con tres campos: 

l codigo_coche de cuatro caracteres (código del coche). 
l nombre_coche de 20 caracteres (nombre del coche). 
l velocidad_maxima número en entero (velocidad máxima que puede alcanzar el coche, en un circuito, claro). 

En sus propios ejemplos, no podrá utilizar la base de datos que se usa en los ejemplos del libro. El identificador y la 
contraseña están ocultos en las reproducciones de los códigos "fuente" que siguen a continuación. 

Por tanto, tendrá que disponer de un SGBD MySQL al que pueda acceder. La obtención o reserva de un acceso a un 
servidor de este tipo queda fuera del marco de este libro. 

Por  lo  tanto,  para  que  pueda  comprobar  los  ejemplos,  tendrá  que  desarrollar  una  tabla  llamada  coches  en  su 
servidor MySQL e introducir el identificador y la contraseña de conexión en los scripts. 

Para facilitar el despliegue, se proporciona un script SQL de creación de la tabla coches. Tendrá que ejecutarlo en la 
ventana SQL de su interfaz de administración MySQL (PHPMyAdmin, normalmente). 

CREATE TABLE coches(


codigo_coche CHAR(4),
nombre_coche CHAR(20),
velocidad_maxima INTEGER
);

También  se  proporciona  un  conjunto  de  datos  de  prueba  para  la  explotación  de  los  ejemplos.  Puede  ejecutar  el 
siguiente script para rellenar su tabla coches: 

INSERT INTO coches (codigo_coche, nombre_coche,


velocidad_maxima)
VALUES ("V001", "Porsche 930 Turbo", 290);
INSERT INTO coches (codigo_coche, nombre_coche,
velocidad_maxima)
VALUES ("V002", "Porsche 964 Turbo", 300);
INSERT INTO coches (codigo_coche, nombre_coche,
velocidad_maxima)
VALUES ("V003", "Ferrari 430", 320);

Los  dos  scripts  SQL,  así  como  todos  los  scripts  de  los  ejemplos  de  este  libro,  se  pueden  descargar  gratuitamente 
desde la página Información. 

1. Ejemplo 1: Acceso Ajax sobre BDD MySQL (lista de los coches)

En un primer ejemplo, se recupera la lista de todos los registros de una tabla MySQL llamada coches. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Este primer ejemplo utiliza cuatro elementos principalmente: 

l un script HTML (que contiene las secuencias de código JavaScript), llamado cliente_ws_01.htm, 

l un script PHP llamado servidor_ws_01.php, 

l un script PHP nusoap.php, 

l una tabla MySQL llamada coches (mencionada anteriormente). 

Para  poder  utilizar  estos  scripts  en  sus  propios  ejemplos,  los  archivos  cliente_ws_01.htm, 
servidor_ws_01.php  y  nusoap.php  se  deberán  ubicar  en  su  cliente  FTP  habitual  (Mozilla  Filezilla,  por 
ejemplo), en un directorio (por ejemplo, de nombre js_nusoap) de su servidor Web. 

De nuevo, la obtención o reserva de un acceso a un espacio de publicación Web está fuera del marco de este libro. 

La primera miniaplicación que se va a presentar también es un buen ejemplo de lo que se llama comúnmente Ajax 
(Asynchronous JavaScript and XML). 

Ajax agrupa un conjunto de tecnologías (JavaScript, XML, CSS, XML, DOM y XMLHttpRequest), que permiten construir 
aplicaciones Web dinámicas que usen bases de datos y tengan "interfaces de usuario" ricas (RIA). 

DOM y JavaScript sirven para modificar la información presentada en el navegador. 

El  objeto  XMLHttpRequest  se  usa  para  asegurar  los  intercambios  de  datos  con  el  servidor  Web  de  modo 
asíncrono. 

XML estructura los flujos de datos entre el servidor Web y el navegador. Se pueden utilizar otras tecnologías, como 
JSON en lugar de XML, para codificar los flujos de datos entre el servidor Web y el navegador. 

Normalmente, Ajax es compatible con los principales navegadores, como Microsoft Internet Explorer, Mozilla Firefox, 
Google Chrome, Konqueror e incluso Opera. 

En nuestro ejemplo, se van a utilizar la gran mayoría de las tecnologías agrupadas en Ajax: 

l un  script  cliente  (HTML  +  JavaScript)  preparará  un  mensaje  SOAP/XMLHttpRequest,  con  destino  una  aplicación  de 
servidor escrita en PHP, 

l el script servidor accederá a una base de datos almacenada en un SGBD MySQL, 

l con una librería dedicada (NuSOAP), la respuesta (los registros correspondientes a una extracción SQL), es decir, un 
flujo XML, se enviará a la aplicación cliente, 

l la aplicación cliente, con métodos JavaScript de procesamiento del DOM, recuperará los datos para la visualización. 

Este ejemplo basado en Ajax es, por tanto, relativamente completo; solo falta tratar el CSS (dar formato, con una 
hoja de estilo, a los datos recuperados por el script cliente) y JSON (en nuestro caso, se ha seleccionado el formato 
XML para la estructura del mensaje de retorno del servidor). Tendremos la ocasión de descubrir el formato JSON en 
una serie de ejemplos, que se presentarán en el próximo capítulo. 

SOAP  es  un  protocolo  orientado  a  objetos  construido  sobre  XML  que  permite  la  transmisión  de  mensajes  entre 
aplicaciones remotas. Con este protocolo, un objeto puede invocar métodos de objetos físicamente situados en otros 
servidores. La transferencia de mensajes SOAP se hace habitualmente con el protocolo HTTP. 

Pasemos ahora al estudio detallado de estos diferentes scripts. 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Script nusoap.php 

Puede obtener esta librería PHP descargándola desde el sitio web http://sourceforge.net/projects/nusoap/ 

Para  nuestros  dos  ejemplos,  solo  es  necesario  el  script  nusoap.php.  Por  tanto,  será  necesario  extraerlo  del 
paquete (archivo comprimido) obtenido o buscarlos en los scripts que acompañan este libro, disponibles en el sitio 
Web de Ediciones ENI. 

El  script 
nusoap.php  se  deberá  situar  en  el  mismo  directorio  que  los  scripts  cliente_ws_01.htm  y 
servidor_ws_01.php (por ejemplo, js_nusoap). 

El comentario del contenido del archivo nusoap.php no está previsto en el marco de este libro. Sin embargo, debe 
saber que este archivo, de unas 6.000 líneas de código, contiene más de cien funciones. 

Script HTML cliente_ws_01.htm 

En la sección HTML  <body> ... </body> de este script, vamos a encontrar la llamada a una función JavaScript 


con nombre llamadaServidorRemoto. 

<!-- Inicio script JavaScript -->


<script tipo="text/JavaScript">

/* Visualización del nombre del script */


alert("WS_01");

/* Llamada a la función llamadaServidorRemoto


que lista los datos de la tabla MySQL remota coches */
llamadaServidorRemoto();

</script>

Después  de  la  ejecución  de  esta  función 


llamadaServidorRemoto,  se  informará  en  la  capa  de  nombre 
resultado cuando se recuperen los datos desde el servidor de datos MySQL. 

<!-- Capa de visualización del resultado en HTML -->


<div id="resultado"></div>

Pasemos ahora a lo más importante, el estudio detallado de las funciones JavaScript, que permiten la recuperación 
de los datos y su procesamiento. 

Función llamadaServidorRemoto 

El objetivo de la primera función, llamada llamadaServidorRemoto, es: 

l preparar una consulta SOAP, que se enviará al servidor remoto (servidor Apache en nuestro caso), 

l esperar el procesamiento en el lado servidor, 

l recuperar la respuesta del servidor remoto (respuesta en formato XML en nuestro caso), 

l deserializar la respuesta XML, 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


l visualizar los datos en la capa de visualización resultado. 

El código completo de esta función es el siguiente: 

/* Función llamadaServidorRemoto */
function llamadaServidorRemoto()
{

/* Mensaje SOAP transmitido al servidor */


mensajeSOAP = ’<?xml version="1.0" encoding="ISO-8859-1"?>’;
mensajeSOAP += ’<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"’;
mensajeSOAP += ’ xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"’;
mensajeSOAP += ’ xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"’;
mensajeSOAP += ’ xmlns:SOAP-ENC="ttp://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd">’;
mensajeSOAP += ’<SOAP-ENV:Body>’;
mensajeSOAP += ’<ns1:listarCoches xmlns:ns1=
"http://angel.sanchez.online.es"></ns1:listarCoches>’;
mensajeSOAP += ’</SOAP-ENV:Body>’;
mensajeSOAP += ’</SOAP-ENV:Envelope>’;
// alert("mensajeSOAP: " + mensajeSOAP);

/* Instanciación de un objeto de tipo XMLHttpRequest


NB: XMLHttpRequest es un objeto ActiveX o JavaScript que permite obtener
datos en formato XML, JSON, pero también HTML, incluso texto simple,
con consultas HTTP.
*/
if (window.XMLHttpRequest)
{
// Código para IE7+, Firefox, Chrome, Opera, Safari
httpRequest = new XMLHttpRequest();
}
else
{
// Código para IE6, IE5
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

/* Acceso al servidor SOAP */


httpRequest.open("POST", url, true);

/*
Aplicación del método overrideMimeType
para indicar una respuesta del servidor SOAP
en formato texto o XML
*/
if (httpRequest.overrideMimeType)
{
httpRequest.overrideMimeType("text/xml");
}

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/*
Preparación del encabezado del mensaje SOAP
(Content-Type, con valor text/xml)
NB: Cf https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
para el resto de argumentos posibles
*/
httpRequest.setRequestHeader("Content-Type", "text/xml");

/*
Envío de la consulta SOAP al servidor
con un timeout de 60000 ms (es decir 60 segundos)
NB: La consulta será errónea una vez alcanzado el plazo de espera
*/
httpRequest.send(mensajeSOAP);
valTimeout = setTimeout("timeout(httpRequest);", 60000);

/*
Parseo y copia de la respuesta en la capa HTML resultado,
proporcionada por el servidor SOAP
*/
httpRequest.onreadystatechange = parsearDOM;
}

La primera parte (la más compleja), consiste en preparar el mensaje SOAP, que se va a enviar al servidor remoto. 

Sin ser exhaustivos sobre los diferentes elementos que hay que integrar en este envelope SOAP (término utilizado 
para hacer referencia al mensaje), observemos los dos puntos en los que debe intervenir en caso de reutilizar el 
código de esta función en sus desarrollos personales. 

En  primer  lugar,  en  el  script  que  se  ha  presentado,  listarCoches  es  un  método  integrado  en  el  script 
servidor_ws_01.php, que estudiaremos más tarde. 

mensajeSOAP += ’<ns1:listarCoches xmlns:ns1=


"http://angel.sanchez.online.es"></ns1:listarCoches>’;

Posteriormente, aunque no sea obligatorio, también puede personalizar el nombre de dominio en esta misma línea 
de código: 

xmlns:ns1="http://angel.sanchez.online.es"

Para  el  resto  de  los  elementos  que  forman  el  envelope  SOAP,  diríjase  a  la  Wikipedia 
(http://es.wikipedia.org/wiki/SOAP)  o  incluso  a  la  página  en  español  del  W3C  sobre  este  tema  en  concreto 
(http://www.w3c.es/Traducciones/es/TR/2003/REC­soap12­part0­20030624/). 

Una vez que el envelope SOAP está preparado, conviene instanciar un objeto  XMLHttpRequest, que permitirá la 
comunicación con el servidor remoto. 

De  nuevo,  para  obtener  una  explicación  más  completa  de  la  noción  de  XMLHttpRequest, puede  dirigirse  a  la 
Wikipedia (http://es.wikipedia.org/wiki/XMLHttpRequest). 

En  resumen,  XMLHttpRequest  es  un  objeto  ActiveX  o  JavaScript  que  permite  obtener  datos  en  formato  XML, 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


JSON, pero también HTML, e incluso de texto plano, con ayuda de consultas HTTP. Para los navegadores de antigua 
generación  (Microsoft  Internet  Explorer  versión  6  o  versiones  anteriores),  será  necesario  recurrir  a  un  objeto 
ActiveX. Por tanto, se debe realizar una comprobación para determinar si el navegador necesita un ActiveX o no (en 
este caso, se utilizará un objeto JavaScript): 

/*
Instanciación de un objeto de tipo XMLHttpRequest
NB: XMLHttpRequest es un objeto ActiveX o JavaScript
que permite obtener datos en formato XML, JSON,
pero también HTML, incluso texto simple
con consultas HTTP.
*/
if (window.XMLHttpRequest)
{
// Código para IE7+, Firefox, Chrome, Opera, Safari
httpRequest = new XMLHttpRequest();
}
else
{
// Código para IE6, IE5
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

Posteriormente, se envía una consulta de conexión al servidor: 

/* Acceso al servidor SOAP */


httpRequest.open("POST", url, true);

El método open del objeto httpRequest instanciado anteriormente se utiliza con tres argumentos: 

l POST 
l url 
l true 

El argumento  POST sirve para indicar que la URL que se pasa al servidor, no tiene argumentos (en caso contrario, 
se  usaría  el  argumento  GET).  Es  necesario  indicar  que,  en  materia  de  seguridad,  el  paso  de  argumentos  a  un 
servidor utilizando la URL es una técnica poco fiable. 

El argumento url contiene la URL del script servidor solicitado (servidor_ws_01.php, en nuestro caso). El valor 
se ha configurado al inicio del script: 

/* Variables globales a todas las funciones JavaScript */


var httpRequest = null;
var valTimeout = null;
var url =
"http://angel.sanchez.online.es/js_nusoap/servidor_ws_01.php";
var mensajeSOAP = null;

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Encontrará  información  interesante  sobre  el  método  open  en  la  siguiente  dirección: 
https://developer.mozilla.org/es/docs/AJAX  

El  tercer  argumento  indica  que  nuestra  consulta  es  asíncrona.  Si  el  valor  fuera  true,  la  ejecución  de  la  función 
JavaScript esperaría la llegada de la respuesta del servidor. Esta es la primera A de AJAX. 

La secuencia de código siguiente sirve para indicar que la respuesta que se espera del servidor es de tipo texto o 
XML (XML en nuestro caso, como veremos más adelante): 

/*
Aplicación del método overrideMimeType,
para indicar una respuesta del servidor SOAP
en formato texto o XML
*/
if (httpRequest.overrideMimeType)
{
httpRequest.overrideMimeType("text/xml");
}

Solo falta añadir a nuestro mensaje SOAP una indicación respecto al Content-Type: 

/*
Preparación del encabezado del mensaje SOAP
(Content-Type con valor text/xml)
NB: Cf https://en.wikipedia.org/wiki/
List_of_HTTP_header_fields
para el resto de los argumentos posibles
*/
httpRequest.setRequestHeader("Content-Type", "text/xml");

Como se indica en el comentario del script, si lo desea encontrará una explicación detallada de la noción de Content­
Type en el sitio de Wikipedia (https://en.wikipedia.org/wiki/List_of_HTTP_header_fields ). 

Es ahora cuando la consulta se puede enviar al servidor y también se puede hacer una gestión de timeout: 

/*
Envío de la consulta SOAP al servidor
con un timeout de 60000 ms (es decir 60 segundos)
NB: La consulta será errónea una vez alcanzado el plazo de espera
*/
httpRequest.send(mensajeSOAP);
valTimeout = setTimeout("timeout(httpRequest);", 60000);

La variable  mensajeSOAP se envía al servidor a través del método  send, del objeto  httpRequest.  El  método 


JavaScript setTimeout fija un valor de timeout a 6.000 (1 minuto). Observe que el método  timeout, presentado 
a continuación, interrumpe la consulta cuando se alcanza el plazo de espera: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


/* Función timout */
function timeout(ajaxOBJ)
{
/* Interrupción del procesamiento */
ajaxOBJ.abort();
}

Esta función termina llamando a la función parserDOM como sigue: 

/*
Parseo y copia de la respuesta en la capa HTML resultado,
proporcionada por el servidor SOAP
*/
httpRequest.onreadystatechange=parserDOM;

Recordemos que el evento onreadystatechange permite ejecutar un procesamiento (la función  parserDOM en 
nuestro  caso)  en  cada  cambio  de  valor  del  indicador  readyState  asociado  al  objeto  httpRequest.  Para  que 
sirva como ejemplo, los valores de este indicador pueden ser: 

l 0: La consulta no se ha inicializado, 

l 1: La conexión con el servidor se ha establecido, 

l 2: La consulta se ha recibido por el servidor, 

l 3: El procesamiento está en curso en el servidor, 

l 4: La consulta ha terminado. 

Función parserDOM 

Esta función se llama por la función anterior (llamadaServidorRemoto). 

En  el  código  de  esta  función,  vamos  a  implementar  por  primera  vez  en  este  libro  una  instrucción  particular,  el 
try ... catch. 

El  try delimita un bloque de instrucciones que hay que comprobar, y en el bloque  catch se prevé una respuesta 


en caso de que se produzca una excepción (error) en el bloque try. 

El  bloque  try  (siempre  presente  por  definición)  puede  tener  muchas  instrucciones.  Para  el  procesamiento  de  las 
excepciones, puede haber varios catch consecutivos (incluso ninguno). También es posible prever, en último lugar, 
después  de  la  serie  catch,  un  último  bloque  llamado  finally,  en  el  que  se  integrarán  instrucciones 
sistemáticamente ejecutadas antes de la ejecución de las siguientes instrucciones del programa. 

Antes de pasar a estudiar detalladamente la función parserSOAP, veamos un ejemplo completo de la aplicación de 
try ... catch: 

Este  ejemplo  empieza  con  una  función  (comprobarDia)  que  devuelve  el  nombre  del  día,  correspondiente  a  un 
número de día, que se pasa como argumento (o un mensaje de error si el número no es válido): 

/* Definición de la función comprobarDia */


function comprobarDia(numeroDia)

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


{
/*
Decrementar el argumento que se ha pasado para tener en cuenta
que los valores de la tabla empiezan por 0
*/
numeroDia = numeroDia - 1;

/*
Declaración de una tabla de nombres de días de la semana
*/
var tablaDias = new Array("Lunes", "Martes", "Miércoles",
"Jueves", "Viernes", "Sábado", "Domingo");

/* Comprobación de la validez del argumento */


if (tablaDias[numeroDia] != null)
{
/* Valor de retorno (argumento válido) */
return tablaDias[numeroDia];
}
else
{
/* Valor de retorno (argumento inválido) */
return "Error en el número del día";
}
}

Ahora se llama a esta función como sigue: 

/* Visualización de la etiqueta del día de la semana */


var numDia = 8;
try
{
/* Recuperación de la etiqueta del día */
alert(comprobarDia(numDia));
alert(verificacionDia(numDia))
}
catch(error)
{
alert(error);
}

Se  declara  una  variable  numDia  y  se  inicializa  con  el  valor  8,  lo  que  nos  debería  dar  un  problema,  porque  solo 
existen 7 días en la semana. 

En el bloque try, se efectúan dos intentos de recuperación del nombre del día de la semana. 

En  el  primer  caso  (alert(comprobarDia(numDia));)  el  resultado  mostrará  el  mensaje  "  Error en el
número del día", previsto en el else de la función comprobarDia. 

En  el  segundo  caso,  se  ha  cometido  un  error  de  programación,  porque  se  llama  a  una  función  que  no  existe,  de 
nombre  verificacionDia.  Por  tanto,  el  catch  va  a  cumplir  su  función  y  mostrará  un  mensaje  de  error 
relacionado con esta anomalía (ReferenceError: verificacionDia is not defined).  

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Volvamos  ahora  a  la  función  parsearDOM,  que  va  a  integrar  un  try ... catch.  El  código  fuente  de  esta 
función se muestra completo, a continuación: 

/* Función parsearDOM */
function parsearDOM()
{
try
{
/* Prueba si la consulta ha terminado y satisfactoriamente */
if (httpRequest.readyState == 4)
{
/* Prueba estado OK para la consulta http */
if (httpRequest.status == 200)
{
/* Establece el timeout */
clearTimeout(valTimeout);
/* Recuperación de la respuesta */
var text = httpRequest.responseText;
// alert("texto: " + text);
/*
Elección del parser para descodificar el flujo XML enviado
por el servidor
*/
if (window.DOMParser)
{
/* Parser para IE7 y versiones posteriores,
Firefox,Chrome, Opera, Safari
*/
parsear = new DOMParser();
/* Recuperación del flujo a parsear */
xmlDoc = parsear.parseFromString(text, "text/xml");
}
else
{
/* Parsear para IE6 y versiones anteriores */
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
/*
La recuperación del flujo deberá ser completa antes
del inicio del parseo
*/
xmlDoc.async = "false";
/* Recuperación del flujo a parsear */
xmlDoc.loadXML(text);
}
/* Parseo
NB: El servidor SOAP envía los valores leídos en la
tabla MySQL coches en un flujo XML, con etiqueta
<item> ... </item>
*/
var html = "";
// alert("Número de campos en el flujo XML: "
// +xmlDoc.getElementsByTagNamed("item").length);
for (i=0; i<xmlDoc.getElementsByTagName("item")

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


.length; i++)
{
/*
NB: childNodes[0] designa el primer hijo
del elemento llamado item y nodeValue representa
el valor asociado
*/
if (i % 3 == 0)
{
html += "<br /><br />Código: " +
xmlDoc.getElementsByTagName("item")[i]
.childNodes[0].nodeValue;
}
if (i % 3 == 1)
{
html += "<br />Nombre: " +
xmlDoc.getElementsByTagName("item")[i]
.childNodes[0].nodeValue;
}
if (i % 3 == 2)
{
html += "<br />Velocidad máxima: " +
xmlDoc.getElementsByTagName("item")[i]
.childNodes[0].nodeValue;
}
}
/*
Ubicación del resultado del parseo
en la capa HTML resultado
*/
var capaResultado =
document.getElementById("resultado");
capaResultado.innerHTML = html;
}
}
}
catch(e)
{
/* Caso de error */
alert("Descripción del error: " + e.descripcion);
}
}

Pasemos rápidamente al mecanismo  try ... catch, que tiene por objetivo encontrar errores. El código empieza 


con dos comprobaciones anidadas (se podrían haber agrupado): 

l una primera verificación comprueba si la consulta ha terminado (httpRequest.readyState == 4), 
l una segunda prueba verifica el estado de la respuesta. 

El atributo readyState del objeto httpRequest puede tomar los siguientes valores: 

l 0: Consulta no inicializada, 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


l 1: Consulta cargándose, 

l 2: Consulta cargada, 

l 3: Consulta en proceso de interacción, 

l 4: Consulta terminada. 

Normalmente, solo se debe aceptar el valor 4 para el atributo readyState. 

La segunda comprobación se hace sobre el código de estado ( status) de la respuesta http proporcionada por el 
servidor. Los valores posibles de este código están en el sitio del W3C ( http://www.w3.org/Protocols/rfc2616/rfc2616­
sec10.html). En nuestro caso, solo se acepta el caso de un estado " 200 OK.". 

Posteriormente,  se  aplica  un  timeout  con  el  método  clearTimeout.  El  argumento  valTimeout  es  una 
variable declarada al inicio de script e inicializada a null: 

/* Establece el timeout */
clearTimeout(valTimeout);

La siguiente secuencia es la recuperación de la respuesta enviada por el servidor: 

/* Recuperación de la respuesta */
var text = httpRequest.responseText;

La  respuesta  se  almacena  en  una  variable  text  (declarada  para  la  ocasión)  para  recuperar  el  valor  del  atributo 
responseText del objeto httpRequest. 

Para  que  sirva  como  ejemplo  (por  supuesto,  depende  de  los  datos  almacenados  en  la  tabla  MySQL  coches), 
cuando se ejecuta, la respuesta del servidor es: 

<?xml versión="1.0" encoding="ISO-8859-1"?>


<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"><SOAP-ENV:Body>
<ns1:listarCochesResponse xmlns:ns1=
"http://angel.sanchez.online.es">
<return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[9]">
<item xsi:type ="xsd:string">V001</item>
<item xsi:type ="xsd:string">Porsche 930 Turbo</item>
<item xsi:type ="xsd:string">290</item>
<item xsi:type ="xsd:string">V002</item>
<item xsi:type ="xsd:string">Porsche 964 Turbo</item>
<item xsi:type ="xsd:string">300</item>
<item xsi:type="xsd:string">V003</item>
<item xsi:type="xsd:string">Ferrari 430</item>
<item xsi:type="xsd:string">320</item></return>
</ns1:listarCochesRespuesta></SOAP-ENV:Body></SOAP-ENV:Envelope>

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


En  este  flujo  XML  de  retorno  del  servidor  SOAP,  habrá  identificado  varios  grupos  de  etiquetas 
<item> ... </item> que delimitan a los valores extraídos de la tabla coches, en nuestro caso: 

l V001, Porsche 930 y 290 para el primer registro, 
l V002, Porsche 964 y 300 para el segundo registro, 
l V003, Ferrari 430 y 320 para el tercer registro. 

La elección del nombre de la etiqueta viene impuesta por la librería NuSOAP, de la que hablaremos más adelante. 

Por supuesto, sería posible encontrar, mediante un procesamiento de cadenas muy sofisticado, los valores de los 
campos.  No  obstante,  como  la  respuesta  del  servidor  SOAP  se  formaliza  en  un  flujo  XML,  va  a  ser  posible 
automatizar la recuperación de los valores de los campos con un dispositivo dedicado, que explota el modelo DOM 
de este flujo. 

Para esta operación de transformación, hay que tener en cuenta el navegador. Para los navegadores recientes y 
para Microsoft Internet Explorer versiones 7 y posteriores, será necesario recurrir al objeto  DOMParser, integrado 
de manera nativa. Para las versiones antiguas de Microsoft Internet Explorer, se deberá utilizar un objeto ActiveX 
Microsoft.XMLDOM. 

/* Elección del parser para descodificar el flujo XML enviado por


el servidor */
if (window.DOMParser)
{
/* Código para IE7+, Firefox, Chrome, Opera, Safari */
parser = new DOMParser();
/* Recuperación del flujo a parsear */
xmlDoc = parser.parseFromString(text, "text/xml");
}
else
{
/* Parseador para IE6 y versiones anteriores */
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
/* La recuperación del flujo deberá ser completo antes de iniciar
el proceso del parseo */
xmlDoc.async = "false";
/* Recuperación del flujo a parsear /*
xmlDoc.loadXML(text);
}

En cada caso, el flujo XML se almacena en un objeto llamado xmlDoc, que se deberá parsear. 

También hay una pequeña particularidad para los navegadores antiguos (IE6 y versiones anteriores). El parseo no 
debe empezar antes de que el flujo XML esté totalmente disponible ( xmlDoc.async = "false";). 

Llegamos a una etapa crucial del procesamiento, el parseo: 

/*
Parseo */
/* NB: El servidor SOAP envía los valores leídos

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


en la tabla MySQL coches en un flujo XML
con etiqueta <item> ... </item>
*/
var html = "";
// alert("número de campos integrados en el flujo XML: "
// +xmlDoc.getElementsByTagName("item").length);
for (i=0; i<xmlDoc.getElementsByTagName("item").length; i++)
{
/* NB: childNodes[0] designa el primer hijo
del elemento llamado item
y nodeValue representa el valor asociado */
if (i % 3 == 0)
{
html += "Código: "
+ xmlDoc.getElementsByTagName("item"[i]
.childNodes[0].nodeValue;
}
if (i % 3 == 1)
{
html += "<br />Nombre: "
+ xmlDoc.getElementsByTagName("item")[i]
.childNodes[0].nodeValue;
}
if (i % 3 == 2)
{
html += "<br />Velocidad máxima: "
+ xmlDoc.getElementsByTagName("item")[i]
.childNodes[0].nodeValue;
}
}

El  resultado  del  parseo  se  almacena  en  una  variable  llamada  html.  Un  bucle  for  recorre  el  flujo  y  genera 
progresivamente el resultado. 

En nuestro ejemplo, con tres coches caracterizados cada uno por tres campos ( codigo_coche, nombre_coche y 
velocidad_maxima), la instrucción: 

xmlDoc.getElementsByTagName("item").length

dará como resultado 9. 

El código: 

xmlDoc.getElementsByTagName("item")[i].childNodes[0].nodeValue

representa el valor del hijo directo de cada ítem. 

Una  comprobación  (con  una  operación  de  módulo)  permite  personalizar  cada  línea  integrada  en  la  variable  html. 
Concretamente, durante la primera vuelta del bucle for (i que vale 0), se utiliza "Código: " como prefijo. 

Posteriormente, este resultado (la variable html) se envía a pantalla dentro de una capa HTML como sigue: 

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Ubicación del resultado del parseo en la capa HTML resultado */
var capaResultado = document.getElementById("resultado");
capaResultado.innerHTML = html;

Esta capa de visualización está en la sección HTML <body> ... </body>: 

<!-- Capa de visualización del resultado en HTML -->


<div id="resultado"></div>

Teniendo en cuenta los datos integrados en el flujo XML, la visualización será la siguiente: 

Código: V001 
Nombre: Porsche 930 Turbo 
Velocidad máxima: 290 

Código: V002 
Nombre: Porsche 964 Turbo 
Velocidad máxima: 300 

Código: V003 
Nombre: Ferrari 430 
Velocidad máxima: 320 

Script PHP servidor_ws_01.php 

Solo  falta  estudiar  el  código  del  script  del  lado  servidor,  que  se  ocupa  de  recuperar  los  datos  en  una  tabla 
(coches),  alojada  en  una  base  de  datos  MySQL  y  que  transmite  un  flujo  XML  al  script  cliente_ws_01.htm, 
cuyo código acabamos de estudiar. 

Evidentemente,  con  este  script  no  se  pretende  formarle  en  el  desarrollo  de  aplicaciones  utilizando  el  lenguaje  de 
programación PHP, en el que está escrito. 

Sin  embargo,  se  ha  hecho  un  esfuerzo  particular,  fundamentalmente  introduciendo  comentarios,  para  que  este 
script sea comprensible por principiantes en PHP. Se resaltarán los puntos que necesitarán una modificación para su 
posterior reutilización en un proyecto personal. 

A continuación, ofrecemos la transcripción completa del código de este script. Más adelante, se darán explicaciones 
más detalladas. 

<?php
/*
NOMBRE DEL SCRIPT: server_ws_01.php
REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETO: Listado de coches de deporte con un WebService
(retorno de campos en formato XML)
*/

// Es necesaria la librería NuSOAP

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


require_once("nusoap.php");

// Creación de un objeto SOAP (instanciación)


$servidor_soap = new soap_server;

// Registro del método listarCoches en el objeto,


// para que esté disponible para los clientes de este objeto
$servidor_soap->register("listarCoches");

// Método listarCoches
function listarCoches()
{

// Definición de la consulta SQL a enviar


// a la base de datos MySQL
$consulta_sql = "select codigo_coche, nombre_coche,
velocidad_maxima
from coches
order by codigo_coche;";
// Argumentos SGBD MySQL
$servidor_mysql = "sql.esee.es";
$usuario_mysql = "angel.sanchez";
$contraseña _mysql = "********";
$bdd_mysql = "angel sanchez";

// Comprobación de conexión a MySQL


if (($conexion_mysql = @mysql_connect($servidor_mysql,
$usuario_mysql, $contraseña_mysql)) === FALSE)
{
// Mensaje de error enviado al cliente
return new soap_fault("Server", "MySQL", mysql_error());
}
else
{

// Comprobación del acceso a la base de datos


if ((@mysql_select_db($bdd_mysql, $conexion_mysql)) === FALSE)
{
// Mensaje de error enviado al cliente
return new soap_fault("Server", "MySQL", mysql_error());
}
else
{
// Envío de la consulta SQL al motor SQL de MySQL
$resultado_sql
= @mysql_query($consulta_sql, $conexion_mysql);
// Comprobación del número de registros seleccionados
if (@mysql_num_rows($resultado_sql)<1)
{
// Mensaje de error enviado al cliente
// si no hay registros
$respuesta[0] = "Tabla de coches vacía";
$respuesta[1] = "0";
return $respuesta;

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


}
else
{
// recorrido secuencial de la extracción (vista SQL)
$i = 0;
$num_elemento = 0;
while ($i < @mysql_num_rows($resultado_sql))
{
// Recuperación de los valores a mostrar
$codigo_coche
= mysql_result($resultado_sql, $i,
"codigo_coche");
$nombre_coche
= mysql_result($resultado_sql, $i,
"nombre_coche");
$velocidad_maxima
= mysql_result($resultado_sql, $i,
"velocidad_maxima");
// Preparación envío de los resultados
// al cliente
$respuesta[$num_element] = $codigo_coche;
$num_elemento = $num_element+1;
$respuesta[$num_element] = $nombre_coche;
$num_elemento = $num_element+1;
$respuesta[$num_element]
= $velocidad_maxima;
$num_elemento = $num_element+1;
// Paso al registro siguiente
$i++;
}
// Envío de la respuesta al cliente
return $respuesta;

}
}

// Cierre de la conexión MySQL


@mysql_close($conexion_mysql);
}
}

// Envío del valor de retorno al cliente


$servidor_soap->service($HTTP_RAW_POST_DATA);

// Fin de código PHP


?>

Seguramente, una primera lectura del script le habrá tranquilizado respecto a la sintaxis propia de PHP. Hay muchas 
similitudes  con  JavaScript,  fundamentalmente  a  nivel  de  las  estructuras  de  control  (while { ... },  if
(condición) { ... }, ...). 

Para la nomenclatura de las variables en memoria, observe algunas particularidades: 

l los nombres de las variables deben empezar por un $, 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


l el lenguaje es sensible a las diferencias entre mayúsculas/minúsculas, 

l no es necesario declarar (antes del uso) las variables. 

Debe  saber  también  que,  en  general,  el  código  PHP,  como  el  JavaScript,  se  inserta  en  las  secuencias  de  código 
HTML.  Para  pasar  alternativamente  de  un  código  HTML  a  un  código  PHP  dentro  de  un  mismo  script  (que  no  es  el 
caso en nuestro ejemplo), hay que utilizar: 

l <?php para indicar el inicio de una secuencia PHP, 
l ?> para indicar el final de una secuencia PHP (pasando a HTML o incluso a JavaScript). 

La  extensión  del  nombre  del  script  está  normalizada  (controlada  por  una  directiva  del  servidor  Apache)  y  es  en 
general .php e incluso .php, seguida del número de la versión de PHP utilizada (PHP 5, en nuestro caso). 

Para terminar, las reglas para incluir comentarios son comunes con JavaScript (/* ... */ o //). 

Revisemos las principales instrucciones de este script y, en particular, las modificaciones que debería realizar para 
reutilizarlo. 

La primera secuencia de código sirve para integrar en el script PHP la librería de funciones/métodos  nusoap.php 
(este script está en el mismo directorio que el script servidor_ws_01.php). 

// Es necesaria la librería NuSOAP


require_once("nusoap.php");

Posteriormente, se instancia un objeto de nombre $servidor_soap a partir de la clase NuSOAP soap_server. 

// Creación de un objeto SOAP (instanciación)


$servidor_soap = new soap_server;

La secuencia siguiente declara un método de nombre  listarCoches. Este método ya lo conocemos; lo habíamos 
visto en la construcción del mensaje SOAP en el script cliente_ws_01.htm. 

// Registro del método listarCoches en el objeto,


// para que esté disponible para los clientes de este objeto
$servidor_soap->register("listarCoches");

En el marco de la reutilización del código de este script servidor, el nombre de este método podría ser diferente. 

Pasemos ahora a la descripción del método listarCoches. 

Encontrará una sintaxis idéntica a la de JavaScript para describir las funciones, es decir: 

function nombreFunción(argumentos) {
contenido de la función
}

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


e incluso: 

function nombreFunción(argumentos)
{
contenido de la función
}

En  nuestro  caso  particular,  la  función  listarCoches  no  recibe  argumento(s)  del  script  cliente 
(cliente_ws_01.htm). 

A  continuación,  se  almacena  una  consulta  SQL  en  una  variable  en  memoria,  de  nombre  $consulta_sql.  Esta 
consulta se enviará naturalmente al motor SQL del SGBD MySQL más adelante. 

// Definición de la consulta SQL a enviar


// a la base de datos MySQL
$consulta_sql = "select codigo_coche, nombre_coche,
velocidad_maxima from coches order by codigo_coche;";

En el siguiente párrafo, los argumentos de conexión al servidor MySQL se graban en variables en memoria. Para una 
aplicación personal, en este script debe rellenar estas variables con los valores proporcionados por su host MySQL. 
En la reproducción del script, se ha ocultado el argumento $contraseña. 

// Argumentos SGBD MySQL


$servidor_mysql = "sql.esee.es";
$usuario_mysql = "angel.sanchez";
$contraseña_mysql = "********";
$bdd_mysql = "angel sanchez ";

La  siguiente  secuencia  es  relativa  a  la  conexión  con  el  sistema  de  gestión  de  base  de  datos  MySQL  (se  llama 
sql.esee.es  en  nuestro  caso,  que  es  el  nombre  del  calculador  MySQL  puesto  a  disposición  por  el  editor  Free 
para los host gratuitos).  

Evidentemente,  se  van  a  utilizar  los  argumentos  anteriores  ($servidor_mysql,  $usuario_mysql  y 


$contraseña_mysql): 

$conexion_mysql = @mysql_connect($servidor_mysql,
$usuario_mysql, $contraseña_mysql)

Si la conexión falla, se envía una respuesta al script cliente: 

return new soap_fault("Server", "MySQL", mysql_error());

En  caso  contrario,  solo  falta  conectarse  a  la  base  de  datos  (se  llama  angel sanchez,  en  nuestro  caso)  donde 
reside la tabla coches. Recordemos que la conexión anterior solo se dirige al SGBD; por tanto, falta la conexión a la 
base de datos como sigue: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


@mysql_select_db($bdd_mysql, $conexion_mysql)

Como para la conexión al SGBD, la conexión a la base se comprueba y se envía si es preciso un mensaje de error al 
script cliente: 

return new soap_fault("Server", "MySQL", mysql_error());

Habrá observado que el retorno de error está programado como el anterior. El servidor se encarga de gestionar la 
naturaleza del error con mysql_error(). 

La siguiente secuencia es la más interesante. Trata el caso de una conexión exitosa, al mismo tiempo, al SGBD y a la 
base de datos. 

En primer lugar, la consulta SQL se envía al motor SQL de MySQL: 

// Envío de la consulta SQL al motor SQL de MySQL


$resultado_sql = @mysql_query($consulta_sql, $conexion_mysql);

El  resultado  es  una  estructura  matricial  con  los  registros  en  filas  y  los  campos  en  columnas.  Se  almacena  en  una 
tabla de nombre $resultado_sql. 

Si no hay registros (@mysql_num_rows($resultado-_sql)<1), se debe indicarlo a la aplicación cliente. Esto 
se hace como sigue: 

// Mensaje de error enviado al cliente si no hay registros


$respuesta[0] = "Tabla de coches vacía";
$respuesta[1] = "0";
return $respuesta;

Falta tratar en el último else el caso más interesante: cuando se encuentran datos (uno o varios registros). 

Se implementa una estructura iterativa (while) para recorrer la estructura matricial $resultado_sql. El bucle se 
ejecuta mientras haya registros (@mysql_num_rows($resultado_sql)). 

Para  cada  registro,  hay  que  extraer  el  valor  para  cada  uno  de  los  campos  ( codigo_coche,  nombre_coche  y 
velocidad_maxima, en lo que nos afecta), como se hace, por ejemplo, para el código del coche: 

$codigo_coche = mysql_result($resultado_sql, $i, "codigo_coche");

En  esta  sintaxis,  $codigo_coche  es  una  variable  temporal  para  grabar  la  información;  mysql_result,  la 
función  de  extracción;  $resultado_sql, la matriz explorada;  $i, el número del registro tratado (la numeración 
empieza por 0), y para terminar "codigo_coche", que designa el nombre del campo implicado. 

Ahora falta ubicar estas diferentes variables ($codigo_coche,  $nombre_coche y  $velocidad_maxima) en 


una tabla llamada $respuesta. 

- 20 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Esta tabla de respuesta es una tabla monodimensional que tendrá, al final, n celdas (tres campos * el número de 
registros). 

Esta tabla $respuesta (caso del campo $codigo_coche), se alimenta como sigue: 

$respuesta[$num_element] = $codigo_coche;

Al final del procesamiento, la tabla $respuesta se reenvía a la aplicación cliente: 

return $respuesta;

Resultado de la ejecución 

Con  los  scripts  de  este  ejemplo  publicados  en  un  espacio  Web,  accesible  con  la  URL 
http://angel.sanchez.online.es/js_nusoap/, la visualización obtenida cuando se ejecuta el script cliente_ws_01.htm 
es la siguiente: 

2. Ejemplo 2: Acceso MySQL vía Ajax

La principal diferencia en este segundo ejemplo respecto al anterior es que la extracción de los datos desde la tabla 
MySQL  coches  no  se  efectúa  sobre  todos los  registros,  sino  sobre  un  registro  en  particular,  al  que  se  habrá 
enviado codigo_coche desde la aplicación cliente. 

Las piezas de Ajax empleadas son exactamente las mismas que en el ejemplo 1 (la respuesta siempre se enviará 
por el servidor como un flujo XML). 

Por  tanto,  el  ejemplo  es  la  ocasión  de  ver  cómo  pasar  un  argumento  (el  código  del  coche)  desde  una  aplicación 
cliente a una aplicación servidor. 

En el comentario de los scripts que forman este ejemplo, nos centraremos solo en los aspectos que no hemos visto 
en ejemplo anterior; por tanto, principalmente, el paso de argumento. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 21 -


Script nusoap.php 

Este script PHP (librería de funciones) ya se ha visto en el ejemplo 1. 

Script HTML cliente_ws_02.htm 

Este  script  cliente  escrito  en  HTML/JavaScript  es  estructuralmente  muy  parecido  al  script  cliente_ws_01.htm 
que hemos visto en el ejemplo anterior. 

Integra principalmente dos funciones JavaScript ya vistas en el ejemplo 1: 

l llamadaServidorRemoto 
l parserDOM 

Una  nueva  función,  controlarEleccionLista,  comprueba  la  entrada  realizada  del  código  del  coche,  cuyo 
datos asociados queremos buscar en la tabla MySQL  coches, desde una lista desplegable que finalmente ejecuta 
la búsqueda con una llamada a la función llamadaServidorRemoto. 

En la sección HTML  <body> ... </body>, se implementa un formulario que presenta una lista desplegable con 


los coches y una capa de visualización del resultado (como en el ejemplo 1): 

<!-- Formulario de entrada de datos del código del coche por el que pregunta -->
<form name="formulario">
<!-- Lista desplegable de opciones -->
Código del coche:
<select id="lista"
onchange="controlarEleccionLista(document.getElementById(’lista’),
’Seleccione un código’)">
<option value="CODIGO" selected>Código de coche</option>
<option value="V001">V001</option>
<option value="V002">V002</option>
<option value="V003">V003</option>
</select>
</form>

<!-- Capa de visualización del resultado en HTML -->


<div id="resultado"></div>

Cada  vez  que  cambia  el  código  de  coche  en  la  lista  desplegable  llamada 
lista,  se  ejecuta  la  función 
controlarEleccionLista. El argumento  getElementById(’lista’) se pasa a esta función, así como un 
mensaje que alerta al usuario de la necesidad de hacer una selección. 

Nuestra aplicación podría mejorarse integrando una lista desplegable de los códigos de los coches, alimentada por 
una  búsqueda  en  el  servidor  remoto.  Para  no  complicar  demasiado  la  explicación,  esta  elección  técnica  no  se  ha 
realizado. 

Hablemos también de algunas variables comunes a las funciones JavaScript dentro de la sección HTM  <head> ...


</head>: 

/* Variables globales a todas las funciones JavaScript */

- 22 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


var httpRequest = null;
var valTimeout = null;
var url =
"http://angel.sanchez.online.es/js_nusoap/servidor_ws_02.php";
var mensajeSOAP = null;

No hay sorpresas respecto a estas variables; son idénticas a las vistas en el ejemplo 1. La única diferencia está en 
el valor de la variable url; el script servidor que se va a solicitar es, esta vez, servidor_ws_02.php. 

Pasemos al estudio detallado de las funciones JavaScript que recuperan los datos y su procesamiento. 

Función controlarEleccionLista 

Esta función no estaba presente en el ejemplo 1. Por tanto, se reproduce íntegramente a continuación: 

/* Función que comprueba si se ha hecho una elección en la lista desplegable */


function controlarEleccionLista(lista, mensajeAviso)
{
if (lista.value == "CODIGO")
{
/* Visualización de un mensaje de alerta */
alert(mensajeAviso);
/* Foco en el campo de error */
lista.focus();
/* Valor de retorno */
return false;
}
else
{
/* Visualización de control */
// alert("El código del coche seleccionado es " +
// document.getElementById(’lista’).value);
// alert("El código del coche seleccionado es " + lista.value);
/* Llamada del servidor remoto */
llamadaServidorRemoto(lista.value);
/* Valor de retorno */
return true;
}
}

Se trata de un código sin muchas sorpresas. Se hace una comprobación para verificar que se haya seleccionado un 
dato de la lista desplegable, de identificador lista (el valor por defecto es el asociado al identificador CODIGO). Si 
no  se  ha  seleccionado  ningún  código  de  coche,  el  foco  se  sitúa  en  la  lista  y  se  muestra  un  mensaje  de  alerta 
(mensajeAviso).  En  caso  contrario,  se  realiza  la  llamada  al  servidor  remoto  con  la  función 
llamadaServidorRemoto pasando el código del coche seleccionado (lista.value). 

Función llamadaServidorRemoto 

El código es prácticamente idéntico al estudiado en el primer ejemplo. La única diferencia está en la construcción del 
mensaje  SOAP,  que  se  envía  al  servidor  remoto.  Esta  vez  debe  tener  un  argumento,  el  código  del  coche,  cuyos 
datos queremos buscar en la tabla MySQL coches. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 23 -


/* Mensaje SOAP que se va a enviar al servidor */
mensajeSOAP = ’<?xml versión="1.0" encoding="ISO-8859-1"?>’;
mensajeSOAP += ’<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"’;
mensajeSOAP += ’ xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"’;
mensajeSOAP += ’ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"’;
mensajeSOAP += ’ xmlns:SOAP-ENC=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd">’;
mensajeSOAP += ’<SOAP-ENV:Body>’;
mensajeSOAP += ’<ns1:buscarCoche
xmlns:ns1="http://angel.sanchez.online.es">’;
mensajeSOAP += ’<type xsi:type="xsd:string">’ + codigo_coche + ’</type>’;
mensajeSOAP += ’</ns1:buscarCoche>’;
mensajeSOAP += ’</SOAP-ENV:Body>’;
mensajeSOAP += ’</SOAP-ENV:Envelope>’;

Finalmente, las únicas líneas diferentes son: 

mensajeSOAP += ’<ns1:buscarCoche
xmlns:ns1="http://angel.sanchez.online.es">’;
mensajeSOAP += ’<type xsi:type="xsd:string">’ + codigo_coche + ’</type>’;
mensajeSOAP += ’</ns1:buscarCoche>’;

El método del script servidor que se va a solicitar se llama buscarCoche (listarCoches en el ejemplo 1). 

Observe también la integración en el mensaje SOAP del argumento codigo_coche: 

mensajeSOAP += ’<type xsi:type="xsd:string">’ + codigo_coche + ’</type>’;

Recuerde también que  codigo_coche es el argumento pasado por la función  controlarEleccionLista a la 


función llamadaServidorRemoto: 

/* Llamada del servidor remoto */


llamadaServidorRemoto(lista.value); /

* Función llamadaServidorRemoto */
function llamadaServidorRemoto(codigo_coche)

Funciones parserDOM y timeout 

En lo que respecta a estas funciones, no hay ningún cambio respecto a lo que se ha visto en el ejemplo 1. 

- 24 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Script PHP servidor_ws_02.php 

El script servidor escrito en PHP y que usa la librería de funciones NuSOAP no es muy diferente al visto en el ejemplo 
1. 

Por tanto, los comentarios se van a centrar en las diferencias. 

Se declara el método buscarCoche, pasando el argumento evidentemente: 

// Método buscarCoche
// Argumentos pasados por el cliente:
// - $codigo_coche: Código del coche de deporte
// del que se van a listar las características
function buscarCoche($codigo_coche)

A continuación, se hace una comprobación para verificar que se haya pasado un argumento correctamente (en caso 
de que no se haya pasado, se envía un mensaje de error a la aplicación cliente): 

// Comprobación del código del coche que envía el cliente


if (empty($codigo_coche))
{

// Mensaje de error enviado al cliente


return new soap_fault("Client", "Error coche",
"Código de coche no especificado");

}
else
{
// ...

En  realidad,  en  nuestra  aplicación,  esta  prueba  es  un  poco  inútil,  en  la  medida  en  que  la  elección  del  código  del 
coche se ha realizado en el script cliente, a través de una lista desplegable. 

La consulta SQL también se modifica un poco, integra el argumento $codigo_coche en la cláusula SQL where: 

// Definición de la consulta SQL que se envía


// a la base de datos MySQL
$consulta_sql = "select codigo_coche, nombre_coche, velocidad_maxima from coches where
codigo_coche=’$codigo_coche’;";

Está prácticamente terminado. Faltan algunas pequeñas diferencias a nivel de la preparación de la respuesta que 
se envía a la aplicación cliente. 

En caso (poco probable en nuestro ejemplo) de que el coche no se encuentre, tenemos: 

// Mensaje de error enviado al cliente si no hay registro


$respuesta[0] = "Coche no existe";
$respuesta[1] = "0";

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 25 -


return $respuesta;

y en caso favorable: 

// Envío del resultado al cliente


$respuesta[0]
= mysql_result($resultado_sql, 0,
"codigo_coche");
$respuesta[1]
= mysql_result($resultado_sql, 0,
"nombre_coche");
$respuesta[2]
= mysql_result($resultado_sql, 0,
"velocidad_maxima");
return $respuesta;

Resultado de la ejecución 

Con  los  scripts  de  este  ejemplo  publicados  en  un  espacio  Web  accesible  en  la  URL 
http://angel.sanchez.online.es/js_nusoap/, la visualización obtenida cuando se ejecuta el script cliente_ws_02.htm 
es la siguiente: 

- 26 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Presentación general de la solución

En  el  capítulo  anterior,  hemos  visto  cómo  implementar  una  solución  de  almacenamiento  remoto  basado  en  las 
siguientes tecnologías: 

l HTML/JavaScript. 

l Ajax  con  XMLHttpRequest  (objeto  JavaScript  o  ActiveX,  que  permite  recuperar  desde  un  servidor  remoto  los  datos  en 
formato XML, JSON, pero también HTML e incluso texto simple con consultas HTTP). 

l Protocolo SOAP, que encapsula un encabezado y los datos en formato XML. 

l PHP (lenguaje orientado a servidor) para consultar a la base de datos. 

l NuSOAP (librería PHP dedicada a la preparación de mensajes SOAP). 

l MySQL (servidor de dase de datos). 

l Parser DOM para descodificar el mensaje SOAP recibido del servidor. 

Las herramientas utilizadas son relativamente genéricas y se pueden extrapolar con facilidad utilizando, por ejemplo, 
otro  SGBD  en  el  servidor  (PosgreSQL, Microsoft  SQL  Server...)  u  otro  lenguaje  de  programación  (PHP,  Microsoft 
ASP.NET...). 

Sin duda, la principal dificultad sería encontrar, en nuestro caso, una alternativa a la librería NuSOAP. 

En este capítulo, vamos a desarrollar de nuevo el ejemplo del capítulo anterior, pero utilizando el formato de datos 
XML con otro formato: JSON (JavaScript Object Notation). 

JSON  es  un  formato  ligero  de  intercambio  de  datos.  Tiene  la  ventaja  de  ser  independiente  de  los  lenguajes  de 
programación y presenta la particularidad de ser reconocido de manera nativa por JavaScript. En las aplicaciones de 
intercambio de datos cliente­servidor, se utiliza de manera frecuente, como alternativa a XML. La ventaja es que la 
codificación del mensaje del lado servidor es fácil de realizar y el lado cliente no necesita recurrir a un parser DOM. 

Aunque vamos a descubrir JSON a través de varias miniaplicaciones en este capítulo, veamos de forma general este 
formato con un ejemplo. 

A continuación hay un mismo conjunto de datos, en formatos JSON y XML: 

Formato JSON: 

[
{
"menú": "Archivo",
"comandos":
[
{"nombre": "Nuevo", "accion":"crearDocumento"},
{"nombre": "Abrir", "accion": "abrirDocumento"},
{"nombre": "Cerrar", "accion": "cerrarDocumento"}
]
}
]

Formato XML: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


<?xml version="1.0" ?>
<barramenu>
<menu nombre="Archivo">
<comando etiqueta="Nuevo" accion ="crearDocumento" />
<comando etiqueta ="Abrir" accion ="abrirDocumento" />
<comando etiqueta="Cerrar" accion ="cerrarDocumento" />
</menu>
</barramenu>

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Implementación del almacenamiento remoto a través de ejemplos

Se van a presentar cinco ejemplos completos de aplicación. 

Para las necesidades de estos ejemplos, vamos a reutilizar la tabla MySQL  coches que hemos visto en el capítulo 
anterior. 

Recordemos simplemente la estructura de esta tabla: 

l codigo_coche, de cuatro caracteres (código del coche). 
l nombre_coche, de 20 caracteres (etiqueta del coche). 
l velocidad_maxima  es  un  número  entero  (velocidad  máxima  que  el  coche  puede  alcanzar,  en  un  circuito,  por 
supuesto). 

1. Ejemplo 1: Presentación del sistema de notación JSON

Comentario del script JSON_01.htm 

En este primer ejemplo, nos centramos en estudiar el sistema de notación propio de JSON y el modo de acceso a las 
propiedades de los objetos. 

Todo el código JavaScript comentado que se muestra a continuación se ha situado en la sección HTML <body> del 
script (llamado JSON_01.htm). Por tanto, este código está dentro de: 

<!-- Inicio script JavaScript -->


<script type="text/JavaScript">
/* Código JavaScript comentado a continuación */
</script>

El  script  empieza  definiendo  tres  objetos  (coche),  caracterizados  por  las  propiedades  habituales  (cf.  capítulo 
anterior): código, nombre y velocidad máxima:  

/* Definición de 3 objetos JSON */


var coche1 = {
codigo: "V001",
nombre: "Porsche 930 Turbo",
velocidad_maxima: 290
};
var coche2 = {
codigo: "V002",
nombre: "Porsche 964 Turbo",
velocidad_maxima: 300
};
var coche3 = {
codigo: "V003",
nombre: "Ferrari 430",
velocidad_maxima: 320
};

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Los valores de las propiedades de texto (nombre) están entre comillas. 

También  creamos  un  objeto  compuesto  (ensamblado  de  objetos)  de  nombre  alemanes,  que  agrupa  los  objetos 
coche1 y coche2, que efectivamente son coches alemanes, como sigue: 

/* Definición de un objeto compuesto */


var alemanes = {
aleman1: coche1,
aleman2: coche2
};

Veamos ahora cómo utilizar estos objetos para mostrar, por ejemplo, sus propiedades: 

/* Visualización de las propiedades de los objetos


coche1 y coche2 */
document.write("El " + coche1.nombre
+ " -> " + coche1.velocidad_maxima + "Km/h");
document.write("<hr />");
document.write("El " + coche2. nombre
+ " -> " + coche2.velocidad_maxima + "Km/h");

La notación no puede ser más simple. Es suficiente con indicar el nombre del objeto como prefijo y después indicar 
(tras un punto) la propiedad deseada como sufijo. 

La visualización en pantalla da el siguiente resultado: 

El Porsche 930 Turbo ­> 290Km/h 

El Porsche 964 Turbo ­> 300Km/h 

Modifiquemos ahora uno de los valores de las propiedades, la velocidad máxima del coche1 (290 inicialmente) para 
asignarle un valor más real (260) y mostremos el resultado: 

/* Modificación de la propiedad velocidad_maxima


del objeto coche1 */
coche1.velocidad_maxima = 260;

/* Visualización de propiedades del objeto coche1 */


document.write("<hr />");
document.write("El " + coche1.nombre
+ " -> " + coche1.velocidad_maxima + "Km/h");

La visualización es la siguiente: 

El Porsche 930 Turbo ­> 260Km/h 

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Hemos declarado un objeto compuesto alemanes; veamos cómo utilizarlo: 

/* Visualización de la propiedad velocidad_maxima del objeto


coche2 incluido en el objeto alemanes */
document.write("<hr />");
document.write("Mostrar el objeto alemanes:");
document.write("<br />");
document.write("El " + alemanes.aleman2.nombre + " -> " +
alemanes.aleman2.velocidad_maxima + "Km/h (sintaxis 1)");
document.write("<br />");
document.write("El " + alemanes["aleman2"]["nombre"] + " -> " +
alemanes["aleman2"]["velocidad_maxima"] + "Km/h (sintaxis 2)");

En nuestra secuencia de código, se proponen dos sintaxis de visualización para la propiedad velocidad_maxima 
del coche2: 

La sintaxis "objeto" (para el nombre): 

alemanes.aleman2.nombre

La sintaxis "tabla asociativa" (para el nombre): 

alemanes["aleman2"]["nombre"]

El resultado en pantalla es el siguiente: 

Mostrar el objeto alemanes: 
El Porsche 964 Turbo ­> 300Km/h (sintaxis 1) 
El Porsche 964 Turbo ­> 300Km/h (sintaxis 2) 

Terminemos nuestro ejemplo estudiando la posibilidad de construir objetos JSON a partir de tablas: 

/* Definición de 2 tablas (nombre y velocidad_maxima) */


var nombres = [ "Porsche 930 Turbo", "Porsche 964 Turbo", "Ferrari 430" ];
var velocidades_maximas = [ 290, 300, 320 ];

/* Definición de un objeto JSON basado en las tablas


nombres y velocidades_maximas */
var coches = {
nom:nombres,
vel:velocidades_maximas
};

En la secuencia de código, se crea una primera tabla nombres, con las tres etiquetas vistas anteriormente. 

Una segunda tabla  velocidades_maximas agrupa los tres valores de velocidad. Evidentemente, la información 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


se almacena en un orden concreto en estas dos tablas. 

Para  terminar,  tenemos  un  objeto  JSON  llamado  coches,  con  las  propiedades  nom  y  vel,  que  son  propiedades 
compuestas basadas en las dos tablas nombres y velocidades_maximas. 

Veamos ahora cómo se utiliza: 

/* Visualización (utilizando las tablas) de las propiedades del segundo coche */


document.write("<hr />");
document.write("Visualización (utilizando las tablas) de las propiedades
del segundo coche:");
document.write("<br />");
document.write(coches.nom[1] +" -> " + coches.vel[1] + " Km/h");

La  notación  también  es  muy  intuitiva.  Es  suficiente  con  indicar  el  nombre  del  objeto  JSON  como  un  prefijo  y, 
después, un punto que indique el nombre de la tabla implicada, con el rango del valor deseado entre []. 

Observe que, en las tablas, el primer elemento tiene el valor de rango 0. 

En nuestro caso, obtenemos la siguiente visualización: 

Visualización (utilizando las tablas) de las propiedades del segundo coche: 
Porsche 964 Turbo ­> 300 Km/h 

Resultado de la ejecución 

Se han indicado resultados parciales en el comentario del script  JSON_01.htm. Terminemos con el resultado de la 
ejecución, tal y como se presenta en nuestro navegador habitual (Chrome): 

2. Ejemplo 2: Lectura de un archivo JSON con XMLHttpRequest

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Comentario del script JSON_02.htm 

En  este  segundo  ejemplo,  vamos  a  ver  cómo  acceder  al  contenido  de  un  archivo  de  datos  JSON  desde  un  script 
JavaScript, y esto a través de un objeto XMLHttpRequest.  

Se ha utilizado el objeto XMLHttpRequest del capítulo anterior. 

Para  facilitar  la  comprensión  de  la  aplicación,  retomamos  nuestro  ejemplo  basado en  nuestros  tres  coches  de 
deporte: 

{
"coche1":{
"codigo":"V001",
"nombre":"Porsche 930 Turbo",
"velocidad_maxima":290
},
"coche2":{
"codigo":"V002",
"nombre":"Porsche 964 Turbo",
"velocidad_maxima":300
},
"coche3":{
"codigo":"V003",
"nombre":"Ferrari 430",
"velocidad_maxima":320
}
}

El nombre de este archivo, situado en el sitio Web en el mismo directorio que el script JavaScript, es coches.json. 

Estudiemos ahora paso a paso el script HTML/JavaScript. 

En la sección HTML <body>, encontramos principalmente esto: 

<!-- Capa de visualización del resultado -->


<div id="capaResultado"></div>

<!-- Llamada a la función JSON ajaxJSON -->


<script type="text/JavaScript">
ajaxJSON();
</script>

Se  crea  una  capa  HTML,  identificada  con  capaResultado,  para  recibir  los  datos  extraídos  del  archivo  JSON 
coches.json. 

A  continuación  se  invoca  a  una  función  llamada 


ajaxJSON.  El  código  se  podría  haber  situado  en  la  sección 
<body>. Sin embargo, se ha preferido colocar esta función en la sección HTML <head>. 

Pasemos ahora a lo fundamental, el estudio de la función ajaxJSON. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


El  código  empieza  asociando  una  variable  resultado  a  la  capa  de  visualización  capaResultado, mencionada 
anteriormente: 

/* Asociación de la variable resultado


a la capa de visualización capaResultado */
var resultado = document.getElementById("capaResultado");

Como en los ejemplos del capítulo anterior, se va a usar un objeto XMLHttpRequest: 

/* Instanciación de un objeto de tipo XMLHttpRequest


/* NB: XMLHttpRequest es un objeto ActiveX
o JavaScript, que permite obtener los datos
en formato XML, JSON, pero también HTML e incluso texto
plano, con consultas HTTP. */
if (window.XMLHttpRequest) {
// Código para IE7+, Firefox, Chrome, Opera, Safari
httpRequest = new XMLHttpRequest();
} else {
// Código para IE6, IE5
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

Para  las  versiones  antiguas  del  navegador  Microsoft  Internet  Explorer  (versiones  6  y  anteriores),  se  usa  un  objeto 
ActiveX en lugar de XMLHttpRequest.  

Pasemos ahora a la apertura del archivo coches.json y a la definición de su tipo: 

/* Apertura del archivo coches.json */


/* true: modo asíncrono -> el flujo debe estar
disponible completamente antes de su procesamiento */
httpRequest.open("GET", "coches.json", true);

/* Definición del tipo de flujo */


httpRequest.setRequestHeader("Content-Type", "application/json");

El argumento true del método  open sirve para indicar que el flujo debe estar totalmente disponible antes de que 
sea  tratado  por  la  aplicación  cliente.  Se  utiliza  el  método  GET porque la aplicación cliente no envía el argumento. 
Veremos más adelante un ejemplo de búsqueda de datos en una tabla MySQL, con una selección en el script cliente, 
donde utilizaremos el método POST. 

El método setRequestHeader indica que nuestro flujo de datos está en formato JSON. 

Ahora llegamos al procesamiento del flujo, cuando está totalmente disponible. La secuencia de código se presenta a 
continuación de manera íntegra, junto con una explicación detallada: 

/* Procesamiento realizado tan pronto como el flujo está disponible */


httpRequest.onreadystatechange = function() {

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Comprobación de si la consulta ha terminado y comprobación
del estado OK */
if (httpRequest.readyState == 4 && httpRequest.status == 200)
{

/* Visualización de control */
// alert("readystate: "+ httpRequest.readyState);
// alert("status: "+ httpRequest.status);
// alert("responseText: " + httpRequest.responseText);

/* Conversión del flujo JSON en objetos JavaScript */


var datosJSON = JSON.parse(httpRequest.responseText);

/* Inicialización de la variable resultado */


resultado.innerHTML = "";

/* Recorrido de los objetos JavaScript */


for (var obj in datosJSON)
{
/* Concatenación del resultado (una línea por
registro JSON) + un trazo de separación */
resultado.innerHTML += data[obj].nombre + " -> " +
data[obj].velocidad_maxima + " Km/h <hr />";
}

/* Sin envío de datos a través de la consulta XMLHttpRequest */


httpRequest.send(null);

/* Mensaje mostrado mientras se espera el procesamiento


del archivo coches.json */
results.innerHTML = "Espere el procesamiento JSON ...";

Como habíamos visto en el capítulo anterior, en el procesamiento de flujos XML, se hacen comprobaciones de las 
propiedades readyState y status del objeto XMLHttpRequest (llamado httpRequest en nuestro caso). 

Posteriormente,  hay  una  visualización  de  control  (comentada  en  el  script  anterior).  Para  que  sirva  de  ejemplo,  la 
instrucción: 

alert("responseText: " + httpRequest.responseText);

daría como resultado la siguiente visualización: 

responseText: {
"coche1":{
"codigo":"V001",
"nombre":"Porsche 930 Turbo",
"velocidad_maxima":290
},

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


"coche2":{
"codigo":"V002",
"nombre":"Porsche 964 Turbo",
"velocidad_maxima":300
},
"coche3":{
"codigo":"V003",
"nombre":"Ferrari 430",
"velocidad_maxima":320
}
}

Una vez que se ha recuperado el flujo JSON, hay que convertirlo en objetos JavaScript. Esta pesada operación se 
puede realizar con un método nativo de JavaScript, JSON.parse. Es suficiente con pasarlo como el flujo, es decir, 
httpRequest.responseText. 

/* Conversión del flujo JSON en objetos JavaScript */


var datosJSON = JSON.parse(httpRequest.responseText);

Ahora falta reiniciar (borrar) el contenido de la capa de visualización y explorar los objetos JavaScript con un bucle 
for: 

/* Inicialización de la variable resultado */


resultado.innerHTML = "";

/* Recorrido de los objetos JavaScript */


for (var objeto in datosJSON)
{
/* Concatenación del resultado */
/* NB: Una línea por registro JSON
+ un trazo de separación */
resultado.innerHTML += datosJSON[objeto].nombre + " -> "
+ datosJSON[objeto].velocidad_maxima + " Km/h <hr />";
}

El script de la función ajaxJSON termina con: 

/* Sin envío de argumentos en la consulta XMLHttpRequest */


httpRequest.send(null);

/* Mensaje mostrado en espera del procesamiento


del archivo coches.json */
results.innerHTML = "Espere el procesamiento JSON ...";

El  método  send  del  objeto  httpRequest  tiene  como  argumento  null,  lo  que  significa  que  el  cliente  no  ha 
transmitido ninguna información al servidor. Más adelante veremos un ejemplo de tipo POST con transmisión de un 
argumento. En nuestro caso (gestión del flujo JSON en modo asíncrono), el método  send se debe ubicar al final del 
script. 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La última línea del script es opcional. Permite hacer esperar al usuario de la aplicación durante el procesamiento del 
flujo JSON, que puede ser largo y complejo. 

Resultado de la ejecución 

La ejecución del script JSON_02.htm da el siguiente resultado en nuestro navegador habitual (Chrome): 

3. Ejemplo 3: Lectura de un archivo JSON con XMLHttpRequest y un script servidor en 
PHP

Comentario de los scripts JSON_03.htm y servidorJSON.php 

El tercer ejemplo presenta muchas similitudes con el ejemplo 2. 

El script cliente es casi idéntico. Simplemente se ha llamado JSON_03.htm. 

El archivo de datos JSON que contiene las descripciones de los coches también se reutiliza (sin cambiar el nombre). 

La diferencia en este nuevo ejemplo es que el flujo JSON se lee por una aplicación del lado servidor escrita en PHP. 

Veamos en detalle algunas modificaciones respecto a la aplicación anterior. 

En el script JSON_02.htm (ejemplo 2), teníamos esta apertura de archivo: 

/* Apertura del archivo coches.json */


/* true: modo asíncrono -> el flujo debe estar
disponible completamente antes de su procesamiento */
httpRequest.open("GET", "coches.json", true);

En el script JSON_03.htm, se hace referencia al script servidor PHP de nombre servidorJSON.php: 

/* Apertura del archivo coches.json


con el script PHP servidorJSON */
/* true: modo asíncrono -> el flujo debe estar
disponible completamente antes de su procesamiento */
httpRequest.open("GET", "servidorJSON.php", true);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Estudiemos, para terminar, el contenido del script servidor servidorJSON.php: 

<?php

// Tipo del flujo


header("Content-Type: application/json");

// Lectura del archivo JSON coches.json


$datosJSON = file_get_contents("coches.json");

// Envío del flujo JSON a la aplicación cliente


echo $datosJSON;

?>

Después de haber definido el tipo del flujo (configuración de tipo header), se lee el archivo JSON  coches.json y 
se asigna, sin transformación, a una variable de texto llamada datosJSON. 

Esta variable se envía finalmente a la aplicación cliente (JSON_03.htm). 

Hemos  visto  en  el  script  cliente  JSON_02.htm  (el  desarrollo  es  idéntico  para  JSON_03.htm)  cómo  se  tiene  en 
cuenta este contenido. 

A este nivel de la exposición de los ejemplos, se podría preguntar sobre el interés de encargar la lectura del archivo 
JSON  coches.json a un script servidor escrito en PHP. En los siguientes ejemplos vamos a ver (pero usted ya lo 
sabe  desde  el  capítulo  anterior)  cómo  utilizar  el  script  servidor  PHP  para  extraer  datos  desde  una  tabla  de  datos 
MySQL y aplicar a la extracción el formato JSON. 

Resultado de la ejecución 

Con  los  scripts  de  este  ejemplo  publicados  en  un  espacio  Web  accesible  con  la  URL 
http://angel.sanchez.online.es/js_json/JSON_03/,  la  visualización  obtenida  cuando  se  ejecuta  el  script 
JSON_03.htm es la siguiente: 

4. Ejemplo 4: Lectura de una tabla MySQL con XMLHttpRequest (servidor PHP y flujo 
JSON)

Comentario de los scripts JSON_04.htm y servidorJSON.php 

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Como habrá adivinado, el objetivo de este cuarto ejemplo va a ser recuperar los datos (tres coches) almacenados 
en una tabla MySQL (ya utilizada en el capítulo anterior). 

En el ejemplo 1 del capítulo anterior, habíamos dado prioridad a las tecnologías SOAP y XML, mientras que esta vez 
a los datos se les aplicará en formato JSON y serán trazados en consecuencia por el script cliente JSON_04.htm. 

Empecemos por descifrar el script de servidor escrito en PHP, llamado servidorJSON.php. 

Script servidor PHP servidorJSON.php 

El código fuente de este script es relativamente nuevo, aunque tiene algunas similitudes con el que hemos visto en 
el ejemplo 1 del capítulo anterior. A continuación se reproduce completamente y después se comentará en detalle: 

<?php

// Definición del header


header("Content-Type: application/json");

// Definición de la consulta SQL a enviar


// a la base de datos MySQL
$consulta_sql = "select
codigo_coche,
nombre_coche,
velocidad_maxima
from coches
order by codigo_coche;";
// return "Consulta SQL: $consulta_sql";

// Argumentos SGBD MySQL


$servidor_mysql = "localhost";
$usuario_mysql = "root";
$contraseña_mysql = "";
$bdd_mysql = "json";

// Comprobación de la conexión a MySQL


if (
(
$conexion_mysql = @mysql_connect(
$servidor_mysql,
$usuario_mysql,
$contraseña_mysql)
)
=== FALSE
)
{

// Mensaje de error enviado al cliente


echo "";

}
else
{

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


// Comprobación del acceso a la base de datos
if ((@mysql_select_db($bdd_mysql, $conexion_mysql)) === FALSE)
{

// Mensaje de error enviado al cliente


echo "";

}
else
{

// Envío de la consulta SQL al motor SQL de MySQL


$resultado_sql
= @mysql_query($consulta_sql, $conexion_mysql);

// Comprobación del número de registros seleccionados


if (@mysql_num_rows($resultado_sql) <1)
{

// Mensaje de error enviado al cliente


// si no hay registros
echo "";

}
else
{

while
($registro = mysql_fetch_assoc($resultado_sql))
{
// Inserción de los 3 campos (codigo_coche,
// nombre_coche y velocidad_maxima)
// del registro actual
// en la tabla $registros (que contendrá,
// al final, todos los datos)
$registros[] = $registro;
}

// Descodificación en formato JSON


de la tabla $registros
$datosJSON = json_encode($registros);

// Envío del resultado al cliente


echo $datosJSON;

// Cierre de la conexión MySQL


@mysql_close($conexion_mysql);

?>

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Al inicio del script aparece la configuración del header, ya vista en los ejemplos anteriores: 

// Definición del header


header("Content-Type: application/json");

La consulta SQL configurada posteriormente permitirá la extracción de los tres registros de la tabla MySQL coches, 
que se ordenarán utilizando los valores del campo codigo_coche: 

$consulta_sql = "select
codigo_coche,
nombre_coche,
velocidad_maxima
from coches
order by codigo_coche;";

Ahora vienen los argumentos de conexión al sistema de gestión de base de datos MySQL y a la base de datos de 
nombre  json.  Observe  que  nuestro  ejemplo  ha  sido  desplegado  en  un  servidor  local  (EasyPHP),  para  poder 
disponer de una versión del lenguaje PHP (5.2 mínimo) que soporte la función json_encode. Estos argumentos de 
conexión son: 

// Argumentos SGBD MySQL


$servidor_mysql = "localhost";
$usuario_mysql = "root";
$contraseña_mysql = "";
$bdd_mysql = "json";

Como en el ejemplo 1 del capítulo anterior, se realizan comprobaciones respecto a la conexión al SGBD y a la base 
de  datos.  En  nuestro  script  minimalista,  los  mensajes  de  error  que  se  envían  a  la  aplicación  cliente  no  se  han 
especificado, sino que solo se ejecuta un sencillo echo ""; en caso de error. 

Centrémonos en lo esencial, la recuperación de los datos de la tabla MySQL coches, la descodificación en un flujo 
JSON y el reenvío del flujo a la aplicación cliente: 

while
($registro = mysql_fetch_assoc($resultado_sql))
{
// Inserción de los 3 campos (codigo_coche,
// nombre_coche y velocidad_maxima)
// del registro actual
// en la tabla $registros (que contendrá,
// al final, todos los datos)
$registros[] = $registro;
}

// Descodificación en formato JSON de la tabla $registros


$datosJSON = json_encode($registros);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


// Envío del resultado al cliente
echo $datosJSON;

La  estructura  iterativa  while  recorre  el  conjunto  de  registros  correspondiente  a  la  consulta  SQL 
($consulta_sql).  Para  cada  registro  leído,  se  insertan  los  valores  de  los  campos  en  una  tabla  de  nombre 
$registro. Esta tabla se asigna, a su vez, a otra tabla (que se convierte de esta manera en una especie de tabla 
de dos dimensiones), de nombre $registros. 

Posteriormente,  con  la  función  PHP 


json_encode,  disponible  en  las  versiones  recientes  de  PHP,  la  tabla 
$registros se transforma en un flujo JSON. 

Para terminar, el flujo JSON se envía a la aplicación cliente. 

Script cliente HTML/JavaScript JSON_04.htm 

Este script es muy parecido al del ejemplo 3 de este mismo capítulo. Solo la visualización de los datos se modifica 
ligeramente: 

/* Recorrido de los objetos JavaScript */


for (var objeto in datosJSON)
{
/* Concatenación del resultado */
resultado.innerHTML += "Código del coche: "
+ datosJSON[objeto].codigo_coche + "<br />";
resultado.innerHTML += "Nombre: "
+ datosJSON[objeto].nombre_coche + "<br />";
resultado.innerHTML += "Velocidad máxima: "
+ datosJSON[objeto].velocidad_maxima + "<hr />";
}

Cuando se ejecuta este script, el flujo JSON recuperado es: 

[{"codigo_coche":"V001","nombre_coche":"Porsche 930 Turbo",


"velocidad_maxima":"290"},
{"codigo_coche":"V002","nombre_coche":"Porsche 964 Turbo",
"velocidad_maxima":"300"},
{"codigo_coche":"V003","nombre_coche":"Ferrari 430",
"velocidad_maxima":"320"}]

En  caso  de  que  el  módulo  PHP  de  su  servidor  Web  (Apache  en  la  mayoría  de  los  casos)  no  soporte  la  función 
json_encode, no todo está perdido. Tendrá que construir el flujo JSON con el código PHP. 

Resultado de la ejecución 

El host Free (utilizado para los ejemplos del capítulo anterior) no ofrece la función  json_encode, por lo que los 
scripts de este ejemplo se han desplegado en una intranet de tipo EasyPHP (versión 12.1). 

Con la URL http://122.1.0.0/js_json/JSON_04/JSON_04.htm, obtenemos: 

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Además de la instalación de EasyPHP, para ejecutar este ejemplo en su configuración personal, será necesario crear 
una base de datos MySQL de nombre json y desplegar en ella la tabla coches. 

5. Ejemplo 5: Recodificación del ejemplo 4 con una lista desplegable

Este  quinto  ejemplo  va  a  ser  muy  parecido  al  ejemplo  2  del  capítulo  anterior.  El  usuario  podrá,  usando  una  lista 
desplegable, elegir el coche de deporte cuyas características quiera obtener. 

Esta  posibilidad  tiene  algunos  impactos  tanto  en  el  script  cliente  (JSON_05.htm)  como  en  el  script  servidor 
(servidorJSON.php). 

Empecemos esta vez descifrando el script cliente. 

Script cliente HTML/JavaScript JSON_05.htm 

En la sección HTML <body> tenemos la lista desplegable y la capa de visualización del resultado: 

<!-- Formulario de entrada de datos del código del coche por el que se pregunta -->
<form name="formulario">
<!-- Lista desplegable de opciones -->
Código del coche:
<select
id="lista"
onchange="controlarEleccionLista(document.getElementById(’lista’),
’Por favor, seleccione un código’)">
<option value="CODIGO" selected> Código del coche </option>
<option value="V001"> V001 </option>
<option value="V002"> V002 </option>
<option value="V003"> V003 </option>
</select>
</form>

<!-- Capa de visualización del resultado -->


<div id="capaResultado"></div>

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


Además de la habitual función  ajaxJSON, la sección HTML  <head> también integra una función de gestión de la 
lista  desplegable,  controlarEleccionLista.  Esta  función  es  casi  idéntica  a  la  del  ejemplo  2  del  capítulo 
anterior: 

/* Función que comprueba si se ha hecho una selección


en la lista desplegable */
function controlarEleccionLista(lista, mensajeAviso) {
if (lista.value == "CODIGO") {
/* Visualización de un mensaje de alerta */
alert(mensajeAviso);
/* Foco en el campo con error */
lista.focus();
/* Valor de retorno */
return false;
} else {
/* Llamada a la función ajaxJSON */
ajaxJSON();
/* Valor de retorno */
return true;
}
}

La única diferencia es, evidentemente, el nombre de la función que se llama, es decir ajaxJSON: 

/* Llamada a la función ajaxJSON */


ajaxJSON();

Detengámonos también un poco en la función ajaxJSON. 

Hay algunas diferencias respecto al script del ejemplo 1 de este mismo capítulo: 

/* Apertura del archivo coches.json


con el script PHP servidorJSON.php*/
/* true: modo asíncrono -> el flujo debe estar
disponible completamente antes de su procesamiento */
httpRequest.open("POST", "servidorJSON.php", true);

El método  open se utiliza con el argumento POST (en lugar de GET) porque se va a pasar un argumento al script 
servidorJSON.php. 

Con el argumento POST, el envío de los argumentos se hace a través del cuerpo de la consulta, mientras que con el 
argumento  GET  el  envío  de  los  argumentos  se  hace  en  la  URL  en  sí  misma  (con  la  forma: 
http://misitio/miscriptservidor?argumento1=valor1&argumento2=valor2, por ejemplo). 

El tipo de flujo hacia el servidor también es diferente: 

/* Definición del tipo de flujo hacia el servidor */

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


httpRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");

Observe que application/x-www-form-urlencoded es el valor que es necesario conservar para el envío de 
argumentos  desde  un  formulario  HTML  (lista  desplegable  en  nuestro  caso).  Los  valores  de  argumentos  se 
codificarán (por ejemplo, sustitución de los espacios por %20). 

Encontrará  una  explicación  detallada  en  la  siguiente  dirección:  http://www.theasciicode.com.ar/ascii­control­


characters/escape­ascii­code­27.html  

Falta ver cómo enviar el argumento (código del coche) al servidor, con el método send del objeto httpRequest: 

/* Envío de datos a través de la consulta XMLHttpRequest


al script PHP servidorJSON.php */
var argumento = ’codigo=’;
argumento += document.getElementById(’lista’).value;
// alert("Argumento: " + argumento);
httpRequest.send(argumento);

Se inicializa una variable llamada  argumento con la secuencia  codigo=, seguida de la selección realizada en la 


lista desplegable ( document.getElementById(’lista’).value). A continuación, este argumento se envía 
al servidor con: 

httpRequest.send(argumento);

Script servidor PHP servidorJSON.php 

El script servidor es muy parecido al visto en el ejemplo 1. 

Veamos algunas modificaciones añadidas: 

// Recuperación del argumento pasado por la aplicación cliente


$codigo = $_POST["codigo"];

// Definición de la consulta SQL a enviar


// a la base de datos MySQL
$consulta_sql =
"select codigo_coche, nombre_coche, velocidad_maxima
from coches
where codigo_coche=’$codigo’;";

Una  variable  $codigo  recupera  el  valor  del  argumento  codigo,  que  se  pasa  por  el  script  cliente.  Los  valores 
posibles son, en nuestro caso, V001, V002 y V003. 

La consulta SQL se ha completado añadiendo una cláusula SQL de selección con este código: 

where codigo_coche=’$codigo’

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


Resultado de la ejecución 

Como  nuestro  host  habitual  (Free)  no  ofrece  la  función  json_encode,  los  scripts  de  este  ejemplo  se  han 
desplegado en una intranet de tipo EasyPHP (versión 12.1). 

Con la URL http://122.1.0.0/js_json/JSON_05/JSON_05.htm, obtenemos el siguiente resultado: 

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Principio de la geolocalización

El  API  HTML  5  de  geolocalización  ofrece  la  posibilidad  al  usuario  de  la  aplicación  de  conocer  su  posición  geográfica 
(latitud y longitud). 

Para realizar esta localización espacial, no es necesario recurrir a ninguna librería adicional porque esta funcionalidad 
es nativa y, por tanto, está integrada en los navegadores recientes, incluidos los smartphones (iPhone, Android...). 

Entre las principales aplicaciones que utilizan los mecanismos de geolocalización, encontramos Google Maps, Google 
Street e incluso Google Earth. En realidad, se trata de un API que puede utilizar en sus propios desarrollos. 

Los ejemplos que se presentan en la segunda parte de este capítulo usan justamente los API de Google. 

Por  tanto,  al  final  de  este  capítulo  sabrá  utilizar  un  mapa  de  Google  Maps  con  gran  precisión  (centrado,  zoom  y 
anotación,  pasando  por  los  diferentes  modos  de  visualización...)  y  podrá  desarrollar  aplicaciones  basadas  en  la 
geolocalización  (localización  de  puntos  de  interés  en  un  mapa,  trayectos,  distancias,  cálculo  de  velocidad, 
geomarketing,  aplicaciones  de  comunidad  basadas  en  la  geolocalización,  uso  de  overlays,  como,  por  ejemplo,  las 
indicaciones meteorológicas...). 

Para terminar, hay que observar que el uso de determinados API de Google no es gratuito. Además, Google, aunque 
tiene una presencia dominante, no goza del monopolio absoluto en materia de geolocalización. 

Para que sirva de ejemplo, el cliente Orange tiene su propio API de localización. Sin hacer una búsqueda exhaustiva, 
también podemos citar los siguientes API: 

l INSITEO: http://www.insiteo.com/joomla/index.php  

l MAXMIND: http://www.maxmind.com/es/home  

l HOSTIP.INFO: http://www.hostip.info/ 

l MICHELIN: http://dev.viamichelin.com/  

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Ejemplos de aplicaciones de geolocalización

1. Ejemplo 1: Visualización del mapa del centro de España

En este primer ejemplo vamos a implementar las funcionalidades básicas del API de geolocalización que se incluyen 
de manera nativa en HTML 5 y que, en consecuencia, son soportadas por los navegadores recientes (incluidos los 
smartphones). 

El objetivo va ser muy simple: mostrar en pantalla un mapa de Google Maps que presente la región correspondiente 
al centro de España, con un centrado del mapa en la ciudad de Madrid. 

Como se trata de nuestro primer ejemplo de cartografía, el script HTML/JavaScript se reproduce de forma íntegra (no 
se hará sistemáticamente en el resto de los ejemplos): 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">

<!--
NOMBRE DEL SCRIPT: GEO_01.htm
REALIZACIÓN INFORMÁTICA: Christian VIGOUROUX
FECHA DE CREACIÓN: 01/01/2014
FECHA DE ÚLTIMA MODIFICACIÓN: 01/01/2014
OBJETIVO: Gestión Google Map - Mapa del centro de España
(centrado en Madrid) -->

<!-- Inicio script HTML -->


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta http-equiv & content -->


<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<!-- Etiqueta meta que define la zona visualizable -->


<meta name="viewport" content="initial-scale=1.0, user-scalable=yes"/>
<!-- NB: El meta tag viewport indica al navegador el comportamiento
que debe adoptar para mostrar una página -->
<!-- initial-scale=1.0: Apertura de la página
con una escala del 100 % -->
<!-- user-scalable=yes: Funcionalidad
de zoom posible para el usuario -->

<!-- Hoja de estilos CSS -->


<style type=”text/css">

html, body, #mi Mapa


{
margin: 0;
padding: 0;
height: 80%;
}

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


</style>

<!-- Título del script HTML -->


<title>GEO_01</title>

<!-- Llamada al API Google Maps -->


<!-- NB: sensor=false significa que la aplicación
no ofrece localización GPS -->
<script type=”text/Javascript"
src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

<!-- Script JavaScript para implementar el mapa -->


<script type=”text/Javascript">

/* Función de inicialización del mapa */


function inicializarMapa()
{

/* Comprobación para saber si el navegador soporta el API de


geolocalización (W3C) */
if (!navigator.geolocation)
{
/* Mensaje de alerta */
alert("Su navegador no gestiona la geolocalización");
/* valor de retorno */
return false
}

/* Definición de la posición de centrado del mapa


(centrada en la ciudad de Madrid) */
var centreGoogleMap =
new google.maps.LatLng(40.416875, -3.703308);

/* Definición de las opciones del mapa */


var optionsGoogleMap =
{
/* Factor de zoom */
zoom: 8,
/* Punto de centrado */
center: centreGoogleMap,
/* Modo de visualización del mapa (vista mapa de carreteras) */
/* NB: google.maps.mapTypeId.ROADMAP ->
Visualización en modo Plan */
/* google.maps.mapTypeId.SATELLITE ->
Visualización en modo Satélite */
/* google.maps.mapTypeId.HYBRID ->
Visualización en modo Mixto (Plano/Satélite) */
/* google.maps.mapTypeId.TERRAIN ->
Visualización en modo Relieve */
mapTypeId: google.maps.MapTipoId.ROADMAP
}

/* Ubicación del mapa en la capa mi Mapa */


var mi Mapa =

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


new google.maps.Map(document.getElementById("mi Mapa"),
optionsGoogleMap);

</script>

</head>

<!-- Inicio sección body del script HTML -->


<body onload="inicializarMapa()">

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - GEO_01</h1>

<!-- Inicio script JavaScript -->


<script type=”text/Javascript">

/* Visualización del nombre del script */


alert("GEO_01");

</script>

<!-- Definición de la capa en la que se mostrará el mapa -->


<div id="mi Mapa" style="width:100%; height:100%"></div>

<!-- Mensaje a los usuarios con un navegador sin JavaScript -->


<noscript>
<p>Observación importante:</p>
<p>Para utilizar un mapa de tipo Google Maps,
JavaScript, tiene que estar activado en su navegador.</p>
</noscript>

<!-- Visualización del código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=’view-source:’ + window.location">
Código fuente
</a>
</center>

</body>

</html>

Sección HTML <body> 

Empezamos el comentario por la sección HTML <body>. 

Esta sección empieza con la ejecución de la función inicializarMapa: 

<!-- Inicio sección body del script HTML -->


<body onload="inicializarMapa()">

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Posteriormente, se define una capa identificada por mi Mapa. Esta capa recibirá el mapa. 

<!-- Definición de la capa en la que se mostrará el mapa-->


<div id="mi Mapa" style="width:100%; height:100%"></div>

No  nos  detenemos  en  el  resto  de  la  sección.  Observe  simplemente  un  conjunto  de  etiquetas  <noscript> ...
</noscript>, no muy útiles ahora, porque todos los navegadores soportan el JavaScript. 

Sección HTML <head> 

Esta sección empieza con la etiqueta meta habitual, que define el tipo de contenido y el conjunto de caracteres. 

A continuación, tenemos una segunda etiqueta meta específica de nuestro procesamiento: 

<!-- Etiqueta meta que define la zona visualizable -->


<meta name="viewport" content="initial-scale=1.0, user-scalable=yes"/>
<!-- NB: El meta tag viewport indica al navegador el comportamiento
que debe adoptar para mostrar una página -->
<!-- initial-scale=1.0: Apertura de la página
con una escala del 100 % -->
<!-- user-scalable=yes: Funcionalidad de zoom posible
para el usuario -->

Esta  etiqueta  indica  al  navegador  el  comportamiento  que  debe  tener  durante  la  visualización  de  la  página.  En 
nuestro caso, la página se mostrará al 100 % con el zoom autorizado. 

Posteriormente, se integra una hoja de estilos CSS, que sirve para definir el marging, el padding (margen adicional 
entre el contenido y el borde) y la altura para los elementos HTML html, body y #mi Mapa. 

<!-- Hoja de estilos CSS -->


<style type="text/css">

html, body, #mi Mapa


{
margin: 0;
padding: 0;
height: 80%;
}

Este  libro  no  explica  las  hojas  de  estilo  CSS,  aunque  haya  algunos  ejemplos  que  las  usen.  Se  puede  formar  de 
manera eficaz en CSS leyendo los libros XHTML y CSS  ­ Los nuevos estándares de código fuente [segunda edición] 
de  Luc  VAN  LANCKER,  o  HTML5,  CSS3  y  JavaScript  ­  Desarrolle  sites  para  terminales  móviles,  de  Olivier  HENEBELLE, 
publicados en Ediciones ENI. 

Estudiemos ahora la función JavaScript inicializarMapa. 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Antes hay que indicar el uso del API Google como sigue: 

<!-- Llamada al API Google Maps -->


<!-- NB: sensor=false significa que la aplicación no ofrece
localización GPS -->
<script type="text/Javascript"
src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

El argumento sensor="false" indica que la aplicación no usa la localización GPS (Global Positioning System). 

Fuente Wikipedia: el Global Positioning System (GPS) permite determinar en todo el mundo la posición de un objeto, 
una persona o un vehículo con una precisión hasta de centímetros (si se utiliza GPS diferencial), aunque lo habitual 
son unos pocos metros de precisión. El sistema fue desarrollado, instalado y empleado por el Departamento de Defensa 
de los Estados Unidos. El sistema GPS está constituido por 24 satélites y utiliza la triangulación para determinar en todo 
el globo la posición con una precisión de más o menos metros. 

Observe  que,  desde  la  versión  3  del  API  Google  Maps,  ya  no  es  necesario  pedir a  Google  un  código  para  poder 
utilizar  un  mapa  en  sus  aplicaciones  Web.  Puede  consultar  las  condiciones  de  uso  en  la  siguiente  dirección: 
https://developers.google.com/maps/documentation/javascript/tutorial?hl=es .  La  gestión  de  las  claves  de  Google  están 
fuera del ámbito de este libro. 

Aunque  los  navegadores  recientes  soportan  el  API  de  geolocalización,  puede  ser  interesante  comprobar  su 
disponibilidad: 

/* Comprobación para saber si el navegador soporta el API


de geolocalización (W3C) */
if (!navigator.geolocation)
{
/* Mensaje de alerta */
alert("Su navegador no gestiona la geolocalización");
/* valor de retorno */
return false
}

Pasemos ahora a la definición de la posición de centrado del mapa. Se ha decidido centrar el mapa alrededor de la 
ciudad de Madrid, que tiene la posición 40.416875 de latitud y ­3.703308 de longitud. 

/* Definición de la posición de centrado del mapa


(centrada en la ciudad de Madrid) */
var centreGoogleMap = new google.maps.LatLng(40.416875, -3.703308);

Hay muchos sitios Web que dan esta información para la gran mayoría de las ciudades españolas y del mundo. 

A continuación, se indica la información adicional (options) necesaria para la correcta visualización del mapa: 

/* Definición de las opciones del mapa */


var optionsGoogleMap =
{

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


/* Factor de zoom */
zoom: 8,
/* Punto de centrado */
center: centreGoogleMap,
/* Modo de visualización del mapa (vista mapa de carreteras) */
/* mapTypeID: google.maps.mapTypeId.ROADMAP ->
}

En nuestro caso, se elige un factor de zoom de 8; el mapa está evidentemente centrado en la posición de Madrid y 
la visualización es en modo ”mapa de carreteras” (ROADMAP). 

Hay otros modos de visualización disponibles: 

l google.maps.mapTypeId.SATELLITE: Modo Satélite 

l google.maps.mapTypeId.HYBRID: Modo Mixto (Plano/Satélite) 

l google.maps.mapTypeId.TERRAIN: Modo Relieve 

Terminamos asignando el mapa creado a la capa HTML prevista para su visualización: 

/* Ubicación del mapa en la capa mi Mapa */


var mi Mapa = new google.maps.Map(document.getElementById("mi Mapa"),
optionsGoogleMap);

Encontramos en esta instanciación la capa HTML mi Mapa y las opciones de visualización optionsGoogleMap. 

Observe  que,  con  este  script  minimalista,  el  mapa  se  muestra  con  un  determinado  número  de  dispositivos:  zoom 
aumentar/reducir, desplazamiento horizontal/vertical, icono de modo Google Street View. 

Fuente  Google:  Google  Maps  con  Street  View  permite  explorar  los  lugares  de  todo  el  mundo,  aprovechando  las 
imágenes  de  360  grados  de  sus  calles.  Puede  explorar  lugares  destacados,  descubrir  maravillas  de  la  naturaleza, 
seguir una ruta turística, entrar en restaurantes... 

Resultado de la ejecución 

La ejecución del script GEO_01.htm genera esta visualización: 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


2. Ejemplo 2: Visualización del mapa del centro de España (marcador)

Este segundo ejemplo es muy parecido al anterior. Su valor añadido va a ser la ubicación, en la posición geográfica 
de Madrid, de un marcador. 

Las explicaciones básicas de la implementación del mapa no se darán de nuevo. 

Una  marca  es  un  icono  (es  posible  modificar  la  imagen)  sobre  el  que  el  usuario  podrá  pulsar  para  obtener 
información contextual (como una ventana de tipo pop­up). 

Sección HTML <body> 

En la sección HTML <body>, encontraremos la capa de visualización mi Mapa, que ya hemos visto en el ejemplo 1. 

En cambio, respecto a la ejecución de la función  inicializarMapa, procedemos de manera diferente, a través 
del gestor de eventos de Google Maps. Volveremos a este punto más tarde. 

Sección HTML <head> 

Las etiquetas meta y la hoja de estilos CSS integrada son idénticas a las vistas en el ejemplo 1. 

También encontrará que la llamada al API Google Maps es idéntica. 

Pasemos al estudio de la función inicializarMapa. 

La definición de la posición de centrado, las opciones y la ubicación del mapa en la capa HTML  mi Mapa no cambian 
respecto al ejemplo anterior. 

Solo falta ver la gestión del marcador. El código íntegro de esta parte se reproduce a continuación: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


/* Ubicación de un marcador para encontrar la ciudad de Madrid */
/* NB1: posicion define la posición en latitud/longitud del marcador
map permite la asignación del marcador al mapa */
/* NB2: La ubicación del marcador debe seguir a la visualización
del mapa en la capa (y no a la inversa) */
var marcadorMadrid = new google.maps.Marker({
position: new google.maps.LatLng(40.416875, -3.703308),
map: mi Mapa,
title: "Madrid, capital de España "
});

/* Texto explicativo para la ciudad de Madrid */


var comentariosMadrid =
"<div>" +
"<h1>Madrid</h1>" +
"Es una ciudad con la categoría histórica de villa. <br />" +
"Es la capital de España y de la Comunidad de Madrid.<br />" +
"También conocida como la Villa y Corte, es la más poblada del Estado.<br />" +
"</div>";

/* Constructor de la ventana explicativa asociada a la ciudad de Madrid */


var ventanaMadrid = new google.maps.InfoWindow({
content: comentariosMadrid
});

/* Visualización de una ventana explicativa al hacer clic


en el marcador marcadorMadrid */
google.maps.event.addListener(marcadorMadrid, "click", function() {
ventanaMadrid.open(mi Mapa, marcadorMadrid);
});

Empecemos por la ubicación del marcador que indica la ciudad de Madrid: 

/* Ubicación de un marcador para encontrar la ciudad de Madrid */


/* NB1: posicion define la posición en latitud/longitud del marcador */
/* map permite la asignación del marcador al mapa */
/* NB2: La ubicación del marcador debe seguir a la visualización
del mapa en la capa (y no a la inversa) */
var marcadorMadrid = new google.maps.Marker({
position: new google.maps.LatLng(40.416875, -3.703308),
map: mi Mapa,
title: "Madrid, capital de España "
});

La marca se ubica con el objeto Marker del API Google Maps. 

El argumento de su constructor tiene una tabla de opciones: 

l position: posición de la marca en el mapa, 
l map: mapa en el que se mostrará la marca, 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


l title: texto que se mostrará al pasar el ratón. 

A continuación, hay un texto explicativo para una visualización posterior en una ventana pop­up: 

/* Texto explicativo para la ciudad de Madrid */


var comentariosMadrid =
"<div>" +
"<h1>Madrid</h1>" +
"Es una ciudad con la categoría histórica de villa. <br />" +
"Es la capital de España y de la Comunidad de Madrid.<br />" +
"También conocida como la Villa y Corte,
es la más poblada del Estado.<br />" +
"</div>";

Este texto se muestra en una ventana (llamada ventanaMadrid), que tiene como constructor: 

/* Constructor de la ventana explicativa asociada a la ciudad de Madrid */


var ventanaMadrid = new google.maps.InfoWindow({
content: comentariosMadrid
});

El  constructor  del  objeto  InfoWindow  tiene  como  argumento  el  comentario,  almacenado  en  la  variable 
comentariosMadrid. 

Una vez que se ha definido la ventana, hay que programar su visualización, que solo será efectiva si el usuario hace 
clic en el marcador. Esto se administra por el gestor de eventos de Google Maps: 

/* Visualización de una ventana explicativa al hacer clic


en el marcador marcadorMadrid */
google.maps.event.addListener(marcadorMadrid, "click", function() {
ventanaMadrid.open(mi Mapa, marcadorMadrid);
});

En  el  evento  click del marcador, se realiza la visualización de la ventana  ventanaMadrid, y esta, en la capa 


HTML mi Mapa. 

Un último punto relativo a este ejemplo es la llamada a la función inicializarMapa: 

/* Llamada a la función inicializarMapa por el gestor de eventos */


google.maps.event.addDomListener(window, "load", inicializarMapa)

Observe  que  esta  llamada  condicionada  a  un  evento  se  realiza  en  la  sección  HTML  <head>  después  de  la 
descripción de la función inicializarMapa. 

Se ha visto una alternativa en el ejemplo 1: <body onload="inicializarMapa()"> 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


Resultado de la ejecución 

La ejecución del script GEO_02.htm muestra lo siguiente: 

3. Ejemplo 3: Visualización del mapa del centro de España  (marcador y círculos de 
población)

En  este  nuevo  ejemplo,  retomamos  el  marco  de  los  dos  ejemplos  anteriores.  En  este  caso,  vamos  a  establecer 
círculos,  cuyo  radio  será  proporcional  a  la  población  que  vive  en  las  principales  ciudades  del  noroeste  de  la 
Comunidad de Madrid. Solo se comentará esta parte aquí. 

Sección HTML <body> 

Ninguna novedad respecto al ejemplo 2. 

Sección HTML <head> 

En la función  inicializarMapa, además de la ubicación de un marcador en la ciudad de Madrid, hay un segundo 
marcador en Las Rozas. Este marcador está personalizado por un cambio de icono. 

/* Establece una marca para ubicar la ciudad de Las Rozas */


/* NB1: posicion define la posición en Latitud/Longitud de la marca */
/* mapa permite la asignación de la marca al mapa */
/* NB2: La implantación de la marca debe seguir por la visualización

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


del mapa en la capa (y no a la inversa) */
var imagenMarcaLasRozas = "beachflag.png";
var marcaLasRozas = new google.maps.Marker({
posicion: new google.maps.LatLng(40.49, -3.87),
map: mi Mapa,
icon: imagenMarcaLasRozas
});

La ruta de acceso a la imagen que sirve de nuevo icono de marcado es lo primero que se define: 

var imagenMarcaLasRozas = "beachflag.png";

A continuación, se añade un argumento adicional (icon) en la instanciación del marcador: 

icon: imagenMarcaLasRozas

Pasemos  ahora  al  corazón  del  procesamiento,  la  implantación  de  círculos  que  representan  la  población  de  las 
ciudades de Madrid, Las Rozas, Pozuelo y Torrelodones.  

La secuencia empieza declarando una tabla en memoria (asociativa), en la que se almacena la posición geográfica 
de las cuatro ciudades, así como su población: 

/* Declaración de la tabla de ciudades */


var listaCiudades = {};

Para  que  sirva  de  ejemplo,  para  la  ciudad  de  Madrid,  los  datos  almacenados  en  la  tabla  asociativa 
listaCiudades son: 

/* Argumentos de Madrid */
listaCiudades[’Madrid’] = {
posicion: new google.maps.LatLng(40.416875, -3.703308),
poblacion: 207178
};

Falta recorrer la tabla listaCiudades para trazar un círculo, con radio proporcional a la población de cada una de 
las ciudades: 

/* Recorrido de la tabla listaCiudades para construir un círculo */


/* de tamaño proporcional a la población de cada ciudad */
for (var ciudad in listaCiudades)
{

/* Construcción de un círculo de radio calculado */


/* a partir de la población (división por 20) */
var opcionesCirculo = {
strokeColor: "#FF0000",

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: mi Mapa,
center: listaCiudades[ciudad].posicion,
radius: listaCiudades[ciudad].poblacion / 20
};
/* trazado del cículo */
circuloCiudad = new google.maps.Circle(opcionesCirculo);
}

opcionesCirculo es una tabla que agrupa todas las opciones que definen el círculo que se ha de trazar para 
cada ciudad. Las opciones definidas en nuestro ejemplo son: 

l el color del borde del círculo (strokecolor), 

l la opacidad del borde del círculo (strokeOpacity), 

l el grosor del trazo del borde del círculo (strokeWeight), 

l el color del interior del círculo (fillColor), 

l la opacidad del color del interior del círculo (fillOpacity), 

l el mapa en el que se ubica el círculo (map), 

l la posición del centro del círculo (center), 

l el radio del círculo (radius). 

Para terminar, el círculo se dibuja con las opciones definidas: 

/* Trazado del círculo */


circuloCiudad = new google.maps.Circle(opcionesCirculo);

Resultado de la ejecución 

La siguiente visualización se obtiene cuando se ejecuta el script GEO_03.htm: 

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


4. Ejemplo 4: Visualización del mapa del centro de España  (información meteorológica)

En  este  cuarto  ejemplo,  vamos  a  ver  cómo  añadir  a  un  mapa  una  capa  informativa  con  datos  meteorológicos,  en 
tiempo real en nuestro caso. 

Sección HTML <body> 

No  hay  ninguna  novedad  respecto  al  ejemplo  3;  por  tanto,  encontrará  la  capa  HTML  de  visualización  del  mapa 
llamada mi Mapa. 

Sección HTML <head> 

Esta  sección  empieza  definiendo  algunos  estilos  CSS  útiles  para  la  presentación  de  las  secciones  HTML  html  y 
body: 

<!-- Hoja de estilos CSS -->


<style>
/* Estilo CSS para las secciones html y body */
html, body
{
height: 80%;
margin: 0;
padding: 0;
}
</style>

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


A continuación encontramos la llamada habitual al API Google Maps: 

<!-- Llamada del API Google Maps -->


<!-- NB: sensor=false significa que la aplicación no ofrece
ubicación por GPS -->
<!-- libraries=weather es la librería específica de la gestión
del tiempo -->
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=
false&libraries=weather"></script>

En esta llamada no se indica la localización de la posición del usuario y con el argumento  libraries=weather 
indicamos el uso de la librería Google, que permitirá recuperar la información meteorológica. 

En la función  inicializarMapa que viene ahora, se establece el mapa Google Maps en la capa HTML mi Mapa 


como sigue: 

/* Establece del mapa en la capa mi Mapa */


var mi Mapa = new google.maps.Map(document.getElementById("mi Mapa"),
opcionesGoogleMap);

Vemos cómo integrar la capa de información (layer) mencionada. 

Empecemos  anunciando  las  temperaturas.  El  objeto  utilizado  es  WeatherLayer.  Es  suficiente  con  instanciar  un 
objeto y configurar la propiedad temperatureUnits como sigue: 

/* Definición de la capa (layer) de las temperaturas */


var capaTemperaturas = new google.maps.weather.WeatherLayer({
/* Unidad de temperatura: CELSIUS o FARENHEIT */
temperatureUnits: google.maps.weather.TemperatureUnit.CELSIUS
});

WeatherLayer  es  una  clase  de  la  librería  google.maps.weather.  La  elección  de  la  unidad  para  las 
temperaturas ha sido CELSIUS. 

A continuación, esta capa se debe ubicar en el mapa: 

/* Ubicación de la capa de las temperaturas en la mapa */


capaTemperaturas.setMap(mi Mapa);

En lo que respecta a la capa de visualización de las nubes y del sol, el desarrollo es prácticamente idéntico. 

Esta vez, el objeto utilizado es CloudLayer (sin argumentos): 

/* Definición de la capa (layer) de las nubes */


var capaNubes new google.maps.weather.CloudLayer();

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Para la colocación de los indicadores que representan las nubes en el mapa, se usa el método setMap: 

/* Ubicación de la capa de las nubes en el mapa */


capaNubes.setMap(mi Mapa);

Resultado de la ejecución  

La ejecución del script GEO_04.htm muestra lo siguiente: 

5. Ejemplo 5: Visualización del mapa de Madrid (capa panorámica)

En este nuevo ejemplo, vamos a estudiar una capa informativa particularmente interesante cuando visitamos, por 
ejemplo, una ciudad con nuestro smartphone favorito. Va a ser posible acceder a la información mostrada en una 
miniventana situada en los puntos de interés. 

Sección HTML <body> 

No hay ninguna novedad respecto al ejemplo 4. 

Sección HTML <head> 

Antes  de  descifrar  nuestra  habitual  función  inicializarMapa,  es  necesario  ver  el  contenido  de  una  hoja  de 
estilos CSS integrada: 

<!-- Hoja de estilos CSS -->

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 15 -


<style>
/* Estilo CSS para las secciones html y body */
html, body
{
height: 80%;
margin: 0;
padding: 0;
}

/* Estilo CSS para mostrar los marcos de foto */


#marcoFoto {
border: 1px solid #ccc;
width: 300px;
max-height: 300px;
background: #fff;
padding: 5px;
font-family: Arial;
font-size: 12px;
}
</style>

El estilo  #marcoFoto de esta hoja CSS sirve para formatear los marcos en los que se presentarán las fotos de los 
puntos de interés. 

La llamada al API Google Maps también es un poco diferente respecto a lo visto en los cuatro ejemplos anteriores: 

<!-- Llamada del API Google Maps -->


<!-- NB: sensor=false significa que la aplicación no ofrece
ubicación por GPS -->
<!-- libraries=panoramio es la librería específica para la gestión
de los lugares a visitar -->
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=
false&libraries=panoramio"></script>

El argumento  libraries=panoramio sirve para hacer referencia a una librería específica para la gestión de los 


lugares que se pueden visitar. 

La función  inicializarMapa empieza como de costumbre, definiendo la posición de centrado del mapa (siempre 
Madrid), las opciones de visualización y la ubicación del mapa en la capa HTML llamada mi Mapa. La única diferencia 
es el factor de zoom, fijado a 16 en este ejemplo. 

Como para las capas situadas en el mapa del ejemplo 4, aquí tenemos una capa llamada PanoramioLayer: 

/* Definición de la capa (layer) de los panoramas */


var capaPanoramas = new google.maps.panoramio.PanoramioLayer();

/* Ubicación de la capa de los panoramas en el mapa */


capaPanoramas.setMap(mi Mapa);

Este  no  está  totalmente  terminado;  falta  definir  el  marco  de  visualización  de  las  fotos  e  indicar  la  posición  de  las 
fotos en su marco; 

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* Definición del marco para mostrar las fotos */
var marcoFoto = document.getElementById("marcoFoto");

/* Posición de las fotos en los marcos */


map.controls[google.maps.ControlPosicion.RIGHT_TOP].push(marcoFoto);

El marco de las fotos se basa en el estilo  #marcoFoto descrito en la hoja de estilos CSS integrado. Las fotos se 
sitúan en la esquina superior derecha de estos marcos. 

Terminamos asociando una acción (visualización de la información adicional) al evento click en cada una de estas 
fotos: 

/* Evento clic para las fotos */


google.maps.event.addListener(panoramioLayer, "click", function(foto) {
/* Definición de un elemento div */
var div = document.createElement("div");
/* Definición del enlace hipertexto asociado a la foto */
var link = document.createElement("a");
// link.setAttribute("href", foto.featureDetails.url);
/* Establece el enlace hipertexto en la capa */
div.appendChild(link);
});

Sin entrar detalladamente, diremos que en esta secuencia: 

l se define una función que se ejecuta durante un clic en las fotos, 

l se crea una capa HTML llamada div, 

l se asocia un enlace hipertexto a la foto. 

El  argumento  foto  de  la  función  representa  la  foto  en  la  que  el  usuario  habrá  hecho  clic.  A  esta  foto  se  puede 
acceder desde el sitio Web Panoramio ( http://www.panoramio.com) con un enlace hipertexto. 

Resultado de la ejecución 

La visualización generada por el script GEO_05.htm da el siguiente resultado: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 17 -


6. Ejemplo 6: Visualización del mapa de Madrid (Street View)

Terminamos  aquí  nuestra  serie  de  ejemplos  sobre  geolocalización.  Podríamos  ir  incluso  más  lejos,  porque  Google 
Maps ofrece más posibilidades. 

En este sexto ejemplo, vamos a implementar Google Street View, que permite visitar virtualmente las calles de una 
ciudad a partir de un mapa Google Maps. 

Sección HTML <body> 

Una vez más, ninguna novedad respecto al ejemplo 4. 

Sección HTML <head> 

La sección empieza con etiquetas meta que ya conocemos: 

<!-- Etiqueta meta http-equiv & contenido -->


<meta http-equiv="Content-Type" contenido="text/html; charset=utf-8" />

<!-- Etiqueta meta que define la zona visible -->


<meta name="viewport" contenido="initial-scale=1.0, user-scalable=yes"/>
<!-- NB: initial-scale=1.0: Apertura de la página con
una escala del 100% -->
<!-- user-scalable=yes: Zoom posible para el usuario -->

- 18 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La hoja de estilos CSS utilizada va a ser idéntica a la del ejemplo 5. 

La llamada al API Google Maps también se ha visto como (ejemplos 1 a 4): 

<!-- Llamada del API Google Map -->


<!-- NB: sensor=false significa que la aplicación no ofrece
ubicación por GPS -->
<script
src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

La función inicializarMapa empieza configurando el centrado del mapa (en la ciudad de Madrid). 

Las opciones del mapa son las ya vistas: 

l un zoom a 16, 

l el centrado, 

l el modo de visualización ROADMAP. 

A continuación, el mapa se asigna a la capa HTML habitual, miMapa. 

Lo que sigue es el establecimiento del dispositivo Street View: 

/* Establece el mapa en la capa mi Mapa */


var mi Mapa = new google.maps.Map(document.getElementById("miMapa"),
opcionesGoogleMap);

/* Definición de las opciones Street View */


var streetViewOptions =
{
// position: mi Mapa,
pov: {heading: 34, pitch: 10}
};

/* Definición de la Street View */


var streetView =
new google.maps.StreetViewPanorama(document.getElementById("miMapa"),
panoramaOptions);

/* Establece la Street View en la capa mi Mapa */


miMapa.setStreetView(streetView);

En las opciones de Street View, encontramos  position para asociar el dispositivo al mapa y  pov (para punto of 


view ­ punto de vista). 

El argumento pov es una tabla de opciones con: 

l heading: ángulo de rotación de la cámara en grados (0 = posición Norte) en  el sentido de las agujas del reloj (90 
= posición Este); el valor por defecto es 0. 

l pitch: inclinación de la cámara (90 grados = inclinación hacia arriba, ­90 grados = inclinación hacia abajo); el valor 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 19 -


por defecto es 0. 

Resultado de la ejecución 

La ejecución del script GEO_06.htm genera esta visualización: 

- 20 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Presentación del API HTML 5 CANVAS
HTML 5 CANVAS (cf. etiqueta  <canvas>) es un API de diseño, que permite manipular dinámicamente las imágenes 
bitmap, con scripts escritos en JavaScript. Este API está soportado por la mayoría de las versiones recientes de los 
principales navegadores. 

<canvas>,  nuevo  elemento  en  HTML  5,  se  usa  para  realizar  gráficos  simples,  incluso  animaciones  (sin  alcanzar  el 
grado de sofisticación de Adobe Flash). 

Inicialmente,  <canvas>  fue  implementado  en  Apple  Mac  OS  X  (Dashboard);  después  se  soportó  en  el  navegador 
Safari y, para terminar, en Mozilla Firefox (Gecko 1.8). 

En  los  ejemplos  de  este  capítulo,  se  va  a  utilizar  el  elemento  <canvas>  en  el  diseño  de  un  conjunto  de  tipo 
TicTacToe (también llamado Morpion). 

La  serie  de  ejemplos  (basados  todos  en  el  TicTacToe),  le  permitirá  adquirir  conocimientos  básicos  sobre  lo  que  se 
puede hacer con <canvas>. 

En  la  red,  puede  encontrar  muchos  tutoriales  más  completos  sobre  <canvas>,  como  el  de  la  fundación  Mozilla 
(https://developer.mozilla.org/es/docs/Web/HTML/Canvas ). 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Ejemplos de aplicaciones del elemento <canvas>

1. Ejemplo 1: Dibujar un cuadrado sencillo

En este primer ejemplo, vamos a dibujar un cuadrado muy sencillo. Será la base de la futura matriz de TicTacToe. 

Sección HTML <head> 

Esta sección no tiene nada específico. Hay una simple etiqueta meta y el título del script. 

<!-- Inicio script HTML -->


<html>

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="Content-Type" contenido="text/html; charset=utf-8" />

<!-- Título del script HTML -->


<title>MORPION_01</title>

</head>

Sección HTML <body> 

El código de la sección <body> se reproduce completamente a continuación: 

<!-- Establece el elemento HTML canvas -->


<!-- NB: - Longitud del canvas: 1000 -->
<!-- - Altura del canvas: 800 -->
<canvas id="matrizMorpion" width="1000" height="800">
Atención, su navegador no soporta el elemento Canvas
</canvas>

<!-- Código Javascript asociado al canvas -->


<script type="text/javascript">

/* Definición de la ubicación del canvas */


var ubicacionCanvas = document.getElementById("matrizMorpion");

/* Definición del contexto del canvas (2D) */


var contextoCanvas = ubicacionCanvas.getContext("2d");

/*
Representación en el canvas
*/

/* Definición de las propiedades de los trazos */


contextoCanvas.strokeStyle = "black";

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


contextoCanvas.lineWidth = 1;

/* Inicio del recorrido de la línea punteada */


contextoCanvas.beginPath();

/* Punto de inicio del trazo (x, y) */


contextoCanvas.moveTo(10, 10);

/* Representación del trazo superior horizontal */


contextoCanvas.lineTo(110, 10);

/* Representación del trazo derecho vertical */


contextoCanvas.lineTo(110, 110);

/* Representación del trazo inferior horizontal */


contextoCanvas.lineTo(10, 110);

/* Representación del trazo izquierdo vertical */


contextoCanvas.lineTo(10, 10);

/* Fin de recorrido en línea punteada (opcional) */


contextoCanvas.closePath();

/* Representación efectiva */
contextoCanvas.stroke();

</script>

Estudiemos  ahora  las  diferentes  secuencias  de  este  script  (el  nivel  de  detalle  será  menor  en  los  siguientes 
ejemplos). 

El código de la sección <body> se reproduce completamente a continuación. 

El script empieza estableciendo el canvas: 

<!-- Establece el elemento HTML canvas -->


<!-- NB: - Longitud del canvas: 1000 -->
<!-- - Altura del canvas: 800 -->
<canvas id="matrizMorpion" width="1000" height="800">
Atención, su navegador no soporta el elemento Canvas
</canvas>

El  elemento  <canvas>  se  define  por  un  identificador  (id="matrizMorpion")  y  se  dimensiona  en  longitud 
(width="1000") y en altura (height="800"). Los valores se expresan en píxeles. 

El  texto  ("Atención, su navegador...")  presente  entre  la  etiqueta  <canvas> y la etiqueta  </canvas> 
se mostrará en caso de que el navegador no soporte el elemento <canvas>. 

La secuencia siguiente: 

/* Definición de la ubicación del canvas */

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


var ubicacionCanvas = document.getElementById("matrizMorpion");

define la ubicación ocupada por el  <canvas>, es decir, un rectángulo de 1.000 píxeles de longitud por 800 píxeles 
de altura. 

A continuación, se define el contexto del <canvas>: 

/* Definición del contexto del canvas (2D) */


var contextoCanvas = ubicacionCanvas.getContext("2d");

Recordemos  que  un  contexto  2D  proporciona  un  conjunto  de  objetos,  métodos  y  propiedades  que  permitirán  la 
manipulación de los diseños en 2D. 

Ahora podemos pasar a lo más importante. Se trata del dibujo de un simple rectángulo de color negro (sin relleno). 
Este cuadrado se replicará varias veces en el nuestro segundo ejemplo para construir una matriz de TicTacToe. 

Antes de dibujar una línea para nuestro cuadrado, es indispensable elegir un color ( black)  y  un  grosor  (1) para 


esta línea: 

/* Definición de las propiedades de los trazos */


contextoCanvas.strokeStyle = "black";
contextoCanvas.lineWidth = 1;

A continuación, es necesario indicar el inicio de una línea punteada: 

/* Inicio del recorrido de la línea punteada */


contextoCanvas.beginPath();

Lo que viene a continuación, exige un poco de paciencia. Se trata de la definición de las coordenadas de los cuatro 
lados de nuestro cuadrado: 

/* Punto de inicio del trazo (x, y) */


contextoCanvas.moveTo(10, 10);

/* Representación del trazo superior horizontal */


contextoCanvas.lineTo(110, 10);

/* Representación del trazo derecho vertical */


contextoCanvas.lineTo(110, 110);

/* Representación del trazo inferior horizontal */


contextoCanvas.lineTo(10, 110);

/* Representación del trazo izquierdo vertical */


contextoCanvas.lineTo(10, 10);

A partir de un punto de inicio (10, 10), se dibujan los cuatro lados. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


El cierre de la línea no es obligatorio: 

/* Fin de recorrido en línea punteada (opcional) */


contextoCanvas.closePath();

La representación efectiva del cuadrado se ejecuta por: 

/* Representación efectiva */
contextoCanvas.stroke();

Ejecución del script 

La ejecución del script MORPION_01.htm da la siguiente visualización: 

2. Ejemplo 2: Dibujar una matriz de TicTacToe

Ahora  hay  que  reproducir  el  procesamiento  visto  en  el  primer  ejemplo  para  obtener  una  verdadera  matriz  de 
TicTacToe. 

Sección HTML <body> 

Esta vez, empezamos la explicación estudiando la sección <body>. 

Después de la definición del  <canvas> (ya estudiado en el ejemplo anterior), el dibujo de la matriz (5 líneas * 5 
columnas) se obtiene como sigue: 

<!-- Code Javascript asociado al canvas -->


<script type=’text/javascript’>

/* Definición de la ubicación del canvas */


var ubicacionCanvas = document.getElementById("matrizMorpion");

/* Definición del contexto del canvas (2D) */

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


var contextoCanvas = ubicacionCanvas.getContext("2d");

/* Representación de la matriz */
/* NB: La función representarMatriz tiene 3 argumentos: */
/* - Argumento 1: xInicio */
/* - Argumento 2: yInicio */
/* - Argumento 3: longitudLado */
for (linea = 1; linea <= 5; linea++)
{
/* Representación de los 5 cuadrados
de la línea numeroLinea de la matriz */
for (columna = 1; columna <= 5; columna++)
{
representarMatriz(columna * 100, linea * 100, 100);
}
}
</script>

Hay dos bucles  for anidados para asegurar el dibujo de la matriz del TicTacToe. El primero gestiona las cinco líneas 
de la matriz, mientras que el segundo, el más interno, dibuja las cinco celdas de la línea actual. 

Se  llama  a  la  función  representarMatriz  para  asegurar  el  dibujo  efectivo  de  las  celdas.  A  esta  función  se  le 
pasan tres argumentos (expresados en píxeles): 

l argumento n.°1 (columna*100): coordenada x de la celda que se ha de dibujar, 

l argumento n.°2 (línea*100): coordenada y de la celda que se ha de dibujar, 

l argumento n.°3 (100): longitud del lado. 

Sección HTML <head> 

Esta sección contiene principalmente el código de la función representarMatriz: 

/* Función representarMatriz */
function representarMatriz(x, y, lado)
{

/*
Representación en el canvas
*/

/*
Definición de las propiedades de los trazos */
contextoCanvas.strokeStyle = "black";
contextoCanvas.lineWidth = 1;

/* Definición de las propiedades de la matriz */


var xInicio = x;
var yInicio = y;
var longitudLado = lado;

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


/* Inicio del recorrido de la línea punteada */
contextoCanvas.beginPath();

/* Punto de inicio del trazo (x, y) */


contextoCanvas.moveTo(xInicio, yInicio);

/* Representación del trazo superior horizontal */


contextoCanvas.lineTo(xInicio + longitudLado, yInicio);

/* Representación del trazo derecho vertical */


contextoCanvas.lineTo(xInicio + longitudLado, yInicio +
longitudLado);

/* Representación del trazo inferior horizontal */


contextoCanvas.lineTo(xInicio, yInicio + longitudLado);

/* Representación del trazo izquierdo vertical */


contextoCanvas.lineTo(xInicio, yInicio);

/* Fin de recorrido en línea punteada (opcional) */


contextoCanvas.closePath();

/* Representación efectiva */
contextoCanvas.stroke();

El código es similar al visto en el ejemplo 1. 

Se  declaran  las  tres  variables  xInicio,  yInicio  y  longitudLado  y  reciben  los  valores  que  se  pasan  como 
argumentos por el script que llama (cf. sección <body>). 

Ejecución del script 

Cuando se ejecuta el script MORPION_02.htm, da el siguiente resultado: 

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


3. Ejemplo 3: Colocación de dos marcas en la matriz del TicTacToe

El objetivo aquí es darle las bases técnicas para que pueda colocar las marcas en la matriz del TicTacToe. 

Sección HTML <body> 

Se ha elegido dibujar dos marcas en la matriz del TicTacToe: 

l un cuadrado verde en la línea 1, columna 2, para el jugador n.°1 ; 

l un círculo rojo en la línea 2, columna 2, para el jugador n.°2. 

El  código  situado  al  final  de  la  sección  <body>  es  el  más  sencillo  posible.  De  momento,  no  se  trata  del  conjunto 
definitivo, que permite a los dos jugadores actuar sucesivamente para situar sus marcas (damas) en la matriz con 
objeto de obtener cuatro marcas alineadas, por ejemplo. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


El código es el siguiente: 

/* Representación de una línea de color verde en línea 1 & columna 2 */


var x, y, lado;
contextoCanvas.fillStyle = "green";
linea = 1;
columna = 2;
x = (columna * 100) + 20;
y = (linea * 100) + 20;
lado = 60;
// alert("x = " + x);
// alert("y = " + y);
// alert("lado = " + lado);
contextoCanvas.fillRect(x, y, lado, lado);

/* Representación de un círculo de color rojo en línea 2 & columna 2 */


var xCentroCirculo, yCentroCirculo, radioCirculo;
contextoCanvas.fillStyle = "red";
linea = 2;
columna = 2;
xCentroCirculo = (columna * 100) + 50;
yCentroCirculo = (linea * 100) + 50;
radioCirculo = 30;
// alert("xCentroCirculo = " + xCentroCirculo);
// alert("yCentroCirculo = " + yCentroCirculo);
// alert("radioCirculo = " + radioCirculo);
contextoCanvas.beginPath();
contextoCanvas.arc(xCentroCirculo, yCentroCirculo, radioCirculo, 0, 2
* Math.PI, false);
contextoCanvas.fill();

Estudiemos este código paso a paso. 

Para dibujar el cuadrado verde (corresponde, por ejemplo, a la marca del jugador n.°1), se declaran tres variables 
locales: 

l x: posición horizontal (en píxeles) en el <canvas>, 
l y: posición vertical (en píxeles) en el <canvas>, 
l lado: longitud del lado, en píxeles, del cuadrado. 

No se le habrá escapado que los valores de x e  y se han determinado (para facilitar la colocación de las marcas) a 
partir de variables linea y columna, correspondientes a la posición deseada de la marca en la matriz. 

El método fillRect asegura el dibujo del cuadrado: 

contextoCanvas.fillRect(x, y, lado, lado);

en el color definido por: 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


contextoCanvas.fillStyle = "green";

Para  dibujar  el  círculo  rojo  (corresponde,  por  ejemplo,  a  la  marca  del  jugador  n.°2),  también  se  declaran  tres 
variables locales: 

l xCentroCirculo: posición horizontal (en píxeles) del centro del círculo en el <canvas>, 
l yCentroCirculo: posición vertical (en píxeles) del centro del círculo en el <canvas>, 
l radioCirculo: radio del círculo (en píxeles). 

El dibujo del círculo empieza por el método ya visto al dibujar la matriz del TicTacToe: 

contextoCanvas.beginPath();

El dibujo del círculo se hace a través del método arc como sigue: 

contextoCanvas.arc(xCentroCirculo, yCentroCirculo, radioCirculo,


0, 2 * Math.PI, false);

El relleno del círculo (en rojo), se hace como sigue: 

contextoCanvas.fillStyle = "red";
contextoCanvas.fill();

Ejecución del script 

La ejecución del script MORPION_03.htm da la siguiente visualización: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


4. Posibles mejoras en el conjunto del TicTacToe

El conjunto del TicTacToe no se ha programado completamente en este capítulo. En él (por qué no usted mismo) se 
pueden hacer muchas mejoras para obtener una buena aplicación, fundamentalmente: 

l la posibilidad para los jugadores de seleccionar las celdas validadas con el ratón, 

l un  algoritmo  que  permita  conceder  puntos,  por  ejemplo,  cuando  cuatro  marcas  idénticas  están  alineadas  vertical, 
horizontal o diagonalmente, 

l un sistema de contador de puntos, 

l la grabación de los marcadores, 

l la interrupción y el reinicio de una partida, 

l ... 

Estas  optimizaciones  se  pueden  llevar  a  cabo  fácilmente  y  sería  una  buena  ocasión  para  repasar  las  técnicas 
estudiadas en los capítulos anteriores de este libro (algoritmia, gestión de eventos, almacenamiento local o remoto 
en base de datos...). 

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Sin  duda,  tal  y  como  habrá  observado  a  través  de  los  tres  ejemplos  estudiados,  no  hemos  ido  muy  lejos  en  el 
estudio de muchas de las posibilidades de <canvas>.  

Es  recomendable  consultar  la  multitud  de  ejemplos  disponibles  en  Internet.  Con  ellos  aprenderá  a  utilizar  las 
funcionalidades avanzadas de <canvas>, en particular para gestionar: 

l los gráficos, paths, líneas y los estilos asociados, 

l las formas (cuadrados, rectángulos, arcos, círculos, curvas (incluida la curva de Bézier o de segundo grado)), 

l las imágenes, 

l los textos (fuentes, colores, alineaciones...), 

l los efectos (sombreado, degradado, transparencia, repetición...), 

y  encontrará  los  criterios  de  elección  de  un  framework  (librería)  para  facilitarle  el  trabajo  durante  sus 
implementaciones más ambiciosas. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


Diferentes soluciones de diseño de gráficos de gestión

Existen múltiples soluciones que permiten elaborar gráficos de gestión (histogramas, representaciones en sectores, 
nube de puntos...), disponibles en las páginas Web. 

Estas herramientas son a menudo librerías escritas en PHP e incluso en Java. Algunos ejemplos son: 

l JpGraph: http://jpgraph.net/  

l JFreeChart : http://www.jfree.org/jfreechart/ 

l GraphoViz: http://www.graphviz.org/ 

l Highcharts JS: http://www.highcharts.com/ 

Por su parte, Google ha desarrollado una serie de API que permiten diseñar, de manera sencilla, gráficos de gestión 
interesantes. Estos API se agrupan en la denominada Google Charts. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Ejemplos de uso de los API de Google Charts

No  se  pretende  reproducir  todos  los  ejemplos  propuestos  por  Google  para  ilustrar las  diferentes  y  abundantes 
posibilidades que ofrecen estos API. Nos conformamos aquí con proponer algunos ejemplos significativos. 

Los ejemplos ofrecidos por Google están disponibles en la dirección: https://developers.google.com/chart/?hl=es  

1. Ejemplo 1: Dibujar un histograma

El objetivo de este gráfico es sencillo. Se trata de asegurar la presentación como un histograma (barras verticales) 
de la producción de un producto LAMBDA (expresado en toneladas) en tres países (Italia, Francia y España), para 
los años 2010, 2011 y 2012. 

Sobre el histograma, se dibujará una "línea punteada" con la media de la producción por año. 

Sección HTML <body> 

El  código  situado  en  esta  sección  será  casi  idéntico  para  todos  los  ejemplos  de  este  capítulo.  Aquí  se  reproduce 
íntegramente: 

<!-- Inicio sección body del script HTML -->


<body>

<!-- Título del procesamiento -->


<h1>Ediciones ENI - JavaScript - COMBO</h1>

<!-- Inicio script JavaScript -->


<script type="text/javascript">

/* Visualización del nombre del script */


alert("COMBO");

</script>

<!-- Definición de la capa de visualización del gráfico -->


<div id="chart_div" style="width: 900px; height: 500px;"></div>

<!-- Visualización del código fuente -->


<br /><br /><br />
<center>
<a href="JavaScript:window.location=’view-source:’ +
window.location">
Código fuente
</a>
</center>

</body>

Se  diseña  una  capa  ( chart_div)  en  este  código  para  la  visualización  del  gráfico  (a  través  de  la  función 
dibujarGrafico, integrada en la sección <head>): 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


<!-- Definición de la capa de visualización del gráfico -->
<div id="chart_div" style="width: 900px; height: 500px;"></div>

Sección HTML <head> 

Como para la sección anterior, el código fuente de esta sección se reproduce completamente a continuación: 

<!-- Inicio encabezado script HTML -->


<head>

<!-- Etiqueta meta -->


<meta http-equiv="content-type" contenido="text/html; charset=utf-8" />

<!-- Título del script HTML -->


<title>COMBO</title>

<!-- Carga del API Google Chart -->


<script type="text/javascript"
src="https://www.google.com/jsapi"></script>

<!-- Carga del módulo visualization en versión 1


con la opción paquete corechart -->
<script type="text/javascript">
google.load(’visualization’, ’1’, {packages: [’corechart’] });
</script>

<!-- Definición del histograma -->


<script type="text/javascript">

/* Función dibujarGrafico */
function dibujarGrafico()
{

/* Datos a representar gráficamente */


var datos = google.visualization.arrayToDatosTabla([
[’Año’, ’España’, ’Francia’, ’Italia’, ’Media’],
[’2010’, 100, 110, 150, 120],
[’2011’, 120, 130, 200, 150],
[’2012’, 140, 120, 220, 160],
]);

/* Opciones de representación gráfica */


/* NB1: La cuarta serie (numeración de las series a partir de 0)
es una media representada por una línea */
/* NB2: Para el resto de las opciones, consulte
/* https://developers.google.com/chart/interactive/docs/
gallery/combochart */
var opciones =
{
title: ’Producción anual del producto LAMBDA por país’,

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


vAxis: {title: "Toneladas"},
hAxis: {title: "Años"},
seriesType: "bars",
series: {3: {type: "line"}}
};

/* Instanciación de la gráfica */
var chart = new google.visualization.
ComboChart(document.getElementById(’chart_div’));

/* Diseño de la gráfica */
chart.draw(datos, opciones);

/* Mostrar automáticamente la gráfica */


google.setOnLoadCallback(dibujarGrafico);

</script>

</head>

La primera secuencia específica de este ejemplo es la carga del API Google Charts: 

<!-- Carga del API Google Charts -->


<script type="text/javascript"
src="https://www.google.com/jsapi"></script>

Después  se  carga  el  módulo  visualization  (en  versión  1)  con  el  paquete  dedicado  a  los  gráficos  básicos, 
corechart: 

<!-- Carga del módulo visualization en versión 1


con la opción paquete corechart -->
<script type="text/javascript">
google.load(’visualization’, ’1’, {packages: [’corechart’]});
</script>

Pasemos ahora al estudio de la única función ( dibujarGrafico) encargada de dibujar el gráfico. 

La función empieza almacenando los datos que se han de representar gráficamente en una tabla en memoria: 

/* Datos a representar gráficamente */


var datos = google.visualization.arrayToDatosTabla([’Año’,
’España’, ’Francia’, ’Italia’, ’Media’],
[’2010’, 100, 110, 150, 120],
[’2011’, 120, 130, 200, 150],
[’2012’, 140, 120, 220, 160],
]);

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Esta  tabla  no  tiene  sorpresas.  El  primer  registro  indica  la  estructura  (Año  y  los  tres  países).  Los  siguientes 
corresponden a las líneas de datos. 

Los nombres de los países y las referencias a los años servirán naturalmente de leyenda. 

Hay opciones disponibles para afinar la presentación del gráfico. Puede encontrar el detalle de estas opciones en la 
dirección de internet mencionada en el script. 

Las opciones que se mantienen son: 

var opciones =
{
title: ’Producción anual del producto LAMBDA por país’,
vAxis: {title: "Toneladas"},
hAxis: {title: "Años"},
seriesType: "bars",
series: {3: {type: "line"}}
};

La opción  title servirá de título para el gráfico.  vAxis y  hAxis serán las leyendas de los ejes,  seriesType 


indica que se desea un gráfico de barras (histograma) y, para terminar, la opción series indica que la cuarta serie 
(la media) se debe mostrar como una "línea punteada". Observe que la numeración de las series empieza por cero. 

Puede  consultar  las  abundantes  opciones  en  la  siguiente  dirección: 


https://developers.google.com/chart/interactive/docs/gallery/combochart  

Solo  falta  instanciar  el  gráfico  y  garantizar  su  representación,  basándose  en  los  datos  almacenados  en  la  tabla 
datos y en opciones: 

/* Instanciación del gráfico */


var chart = new google.visualization.ComboChart(document
.getElementById(’chart_div’));

/* Diseño del gráfico */


chart.draw(datos, opciones);

La representación efectiva se ejecuta finalmente con la siguiente sentencia: 

/* Visualización automática del gráfico */


google.setOnLoadCallback(dibujarGrafico);

El  método  setOnLoadCallback  es  una  solución  más  eficaz  que  la  llamada  a  la  función  dibujarGrafico 
por un <body onload=’dibujarGrafico()’>. 

Ejecución del script 

Cuando se ejecuta el script COMBO.htm, obtenemos el siguiente resultado: 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


2. Ejemplo 2: Representación de un gráfico de sectores

Vamos a tomar como ejemplo un grupo de clasificación para el mundial que se jugó en Brasil en el año 2014. Como 
ejemplo,  supongamos  que  en  este  grupo  se  enfrentaron  los  equipos  nacionales  de  España,  Suiza,  Ecuador  y 
Honduras.  El  gráfico  de  sectores  desarrollado  muestra  la  probabilidad,  acordada  con  algunos  compañeros  de 
trabajo, de que cada uno de los equipos terminara primero de grupo. 

Sección HTML <body> 

El código fuente de esta sección no tiene ninguna particularidad y no se reproduce aquí. 

Sección HTML <head> 

Esta  sección  empieza  como  en  el  ejemplo  anterior,  con  la  carga  del  API  Google  Charts  y  del  módulo 
visualization (con el paquete corechart). 

Detengámonos ahora en el código de la función dibujarGrafico: 

/* Función dibujarGrafico */
function dibujarGrafico()
{

/* Datos a representar gráficamente */


var datos = google.visualization.arrayToDatosTabla([
[’País, ’Clasificación (%)’],
[’Suiza’, 30],
[’Ecuador’, 20],

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-


[’España’, 40],
[’Honduras , 10]
]);

/* Opciones de representación del gráfico */


/* NB: Para el resto de las opciones, consulte
/* https://developers.google.com/chart/interactive/
docs/gallery/piechart */
var opciones =
{
title: Porcentaje de probabilidad de ganar la clasificación
para el mundial de fútbol ’,
colors:[’Red’ , ’Green’, ’Blue’, ’Grey’],
slices: {
0: {offset: 0.01},
1: {offset: 0.01},
2: {offset: 0.20},
3: {offset: 0.01}
}
};

/* Instanciación del gráfico */


var chart = new google.visualization.PieChart(document
.getElementById(’chart_div’));

/* Representación del gráfico */


chart.draw(datos, opciones);

};

Los datos que se han de representar gráficamente se almacenan en una tabla llamada  datos. El primer campo es 
el nombre del país y el segundo, la probabilidad de terminar primero. 

Ahora vienen las opciones de visualización. 

En nuestro caso, se prevé la elección del color (colors) para cada uno de los sectores, el rojo para Suiza, el verde 
para Ecuador, etc. 

El argumento slices permite destacar los diferentes sectores del gráfico. Para que sirva de ejemplo, España, gran 
favorita del grupo, tiene un sector con un valor de offset más grande que sus rivales. 

Puede  consultar  las  abundantes  opciones  en  la  siguiente  dirección: 


https://developers.google.com/chart/interactive/docs/gallery/piechart  

La función termina como en el ejemplo 1, es decir, instanciando y representando el gráfico. 

La visualización del gráfico en la capa HTML  chart_div también se hace como en el ejemplo anterior, después del 
terminar la función dibujarGrafico como sigue: 

/* Visualización automática del gráfico */


google.setOnLoadCallback(dibujarGrafico);

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Ejecución del script 

Cuando se ejecuta el script PIE.htm, obtenemos el siguiente resultado: 

3. Ejemplo 3: Representación de un mapa

El objetivo de este ejemplo es representar en un mapa del mundo la posición geográfica de los cuatro países con 
los que hemos trabajado en ejemplo anterior. 

Sección HTML <body> 

Una vez más, el código fuente de esta sección no tiene ninguna particularidad. 

Sección HTML <head> 

Esta  sección  comienza  como  en  el  ejemplo  anterior,  es  decir,  cargando  el  API  Google  Charts  y  el  módulo 
visualization. Hay una pequeña modificación porque se sustituye el paquete corechart por geochart. 

<!-- Carga del módulo de visualización en versión 1


con la opción paquete geochart -->
<script type="text/javascript">
google.load(’visualization’, ’1’, {packages: [’geochart’]});
</script>

En  la  función  dibujarGrafico,  encontrará  el  almacenamiento  de  los  datos  que  se  han  de  representar 
gráficamente en una tabla: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 7-


/* Datos a representar gráficamente (Grupo E) */
var datos = google.visualization.arrayToDataTable([
[’País, ’Indicador’],
[’Switzerland’ , 500],
[’Ecuador’, 500],
[’Spain’, 500],
[’Honduras’ , 500]
]);

La primera columna representa el nombre del país. Observe que es obligatorio utilizar la nomenclatura internacional 
(ISO) a la hora asignar el nombre a los países; por tanto, Switzerland en lugar de Suiza, para que el país se puede 
localizar correctamente en el mapa. 

El valor de la segunda columna (llamada aquí  Indicador) define la densidad del color que representa cada país. 
La opción que se ha tomado ha sido seleccionar un valor común (500) para que los cuatro países se representen 
con el mismo color verde (el color por defecto). Jugar con el valor de esta segunda columna habría sido interesante, 
por ejemplo, si se hubiera querido comparar la población de cada país. 

Ahora vienen las opciones habituales: 

/* Opciones de representación gráfica */


/* NB: Para el resto de las abundantes opciones, consulte
/* https://developers.google.com/chart/interactive/docs/
gallery/geochart */
var opciones =
{
region: ’world’ ,
backgroundColor: ’LightBlue’,
fill: ’Green’,
datalessRegionColor: ’Yellow’,
legend: ’null’
};

El argumento  region sirve para indicar, en nuestro caso, que se quiere un mapa del mundo (también es posible 
una visualización por continente, por país...). 

El color de fondo (backgroundColor) del mapa es  LightBlue. Esto colorea lógicamente los mares y océanos 
en azul claro. 

La opción  fill da el color elegido (el verde) para identificar los países en el mapa. Los otros países aparecerán en 
amarillo (opción datalessRegion). 

Para terminar, no se ha previsto presentar una leyenda en el mapa. 

Puede  consultar  las  abundantes  opciones  en  la  siguiente  dirección: 


https://developers.google.com/chart/interactive/docs/gallery/geochart  

Ejecución del script 

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


El script GEOCHART.htm genera esta visualización: 

4. Ejemplo 4: Representación de un indicador

La presentación de eventos o indicadores es un gran clásico. En este ejemplo, vamos a mostrar la velocidad en un 
instante t de un coche en un gráfico de tipo contador de velocidad. 

Sección HTML <body> 

Una vez más, el código fuente de esta sección no tiene ninguna particularidad. 

Sección HTML <head> 

Esta  sección  empieza  como  en  el  ejemplo  anterior,  es  decir,  cargando  el  API  Google  Charts  y  el  módulo 
visualization (con el paquete gauge). 

<!-- Carga del API Google Chart -->


<script type="text/javascript"
src="https://www.google.com/jsapi"></script>

<!-- Carga del módulo de visualización en versión 1


con la opción el paquete gauge -->
<script type="text/javascript">
google.load(’visualization’, ’1’, {packages: [’gauge’]});
</script>

La  función  dibujarGrafico  empieza  como  de  costumbre,  con  el  almacenamiento  de  los  datos  que  se  han  de 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 9-


representar gráficamente en una tabla: 

/* Datos a representar gráficamente */


var datos = google.visualization.arrayToDataTable([
[’Nombre’ , ’Valor’],
[’Km/h’, 210]
]);

La tabla tiene dos campos (columnas), Nombre y Valor, con un único registro. 

La mención Km/h aparecerá en el contador de velocidad, así como la velocidad (210), por supuesto. 

Las opciones de visualización son muchas. En nuestro caso, hemos elegido las siguientes: 

/* Opciones de representación gráfica */


/* NB: Para el resto de las abundantes opciones, consulte
/* https://developers.google.com/chart/interactive/
docs/gallery/gauge */
var opciones =
{
width: 500, height: 500,
yellowFrom:160, yellowTo: 240,
redFrom: 240, redTo: 320,
majorTicks: [0, 40, 80, 120, 160, 200, 240, 280, 320],
minorTicks: 2,
min: 0,
max: 320
};

Los argumentos width y height (expresados en píxeles) definen la longitud y la altura del indicador (contador de 
velocidad). 

Una parte del marcador del contador tendrá una zona amarilla entre 160 (yellowFrom) y 240 (yellowTo) Km/h, 
y una segunda parte, una zona roja entre 240 ( redFrom) Km/h y 320 (redTo) Km/h. 

El contador estará graduado ( majorTicks) cada 40 Km/h, a partir de 40 Km/h. También hay una subgraduación 


cada 20 Km/h (minorTicks). 

Para terminar, el intervalo de la graduación del contador va de 0 Km/h (min) a 320 Km/h (max). 

Puede  consultar  las  abundantes  opciones  en  la  dirección: 


https://developers.google.com/chart/interactive/docs/gallery/gauge  

La función termina como en el ejemplo 1, instanciando y trazando el gráfico. 

La ejecución de la visualización del gráfico en la capa HTML  chart_div  también  se  hace  como  en  los  anteriores 


ejemplos, después de terminar la función dibujarGrafico. 

Ejecución del script 

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Cuando se ejecuta el script GAUGE.htm, obtenemos el siguiente resultado: 

5. Ejemplo 5: Representación de un timeline

La ubicación de eventos en un eje temporal (timeline) es una presentación gráfica muy habitual. 

Fijemos  como  objetivo  representar  gráficamente  en  un  timeline  los  primeros  presidentes  del  gobierno  español  en 
democracia  (Adolfo  Suárez  González,  Leopoldo  Calvo­Sotelo  y  Felipe  González  Márquez),  haciendo  referencia  a  la 
duración de su mandato. 

Sección HTML <body> 

El código fuente de esta sección no tiene ninguna particularidad respecto a los ejemplos anteriores. 

Sección HTML <head> 

Como en el ejemplo anterior, esta sección empieza cargando el API Google Charts y el módulo visualization. El 
paquete timeline sustituye al paquete gauge. 

<!-- Carga del API Google Chart -->


<script type="text/javascript"
src="https://www.google.com/jsapi"></script>

<!-- Carga del módulo de visualización en versión 1


con la opción package timeline -->
<script type="text/javascript">
google.load(’visualization’, ’1’, {packages: [’timeline’]});

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 11 -


</script>

La  definición  de  los  datos  que  se  han  de  representar  gráficamente  se  hace  en  dos  fases  en  la  función 
dibujarGrafico. 

Empecemos por la descripción de la estructura de la tabla de datos: 

/* Definición de la estructura de la tabla a representar gráficamente */


var datosTabla = new google.visualization.DatosTabla();
datosTabla.addColumn({
tipo: ’string’,
id: ’Presidente del gobierno español’
});
datosTabla.addColumn({
tipo: ’string’,
id: ’mandato’
});
datosTabla.addColumn({
tipo: ’date’,
id: ’Fecha de inicio’
});
datosTabla.addColumn({
tipo: ’date’,
id: ’Fecha de fin’
});

El primer campo de tipo string servirá para almacenar el nombre y el apellido del presidente del gobierno. 

El segundo campo, también de tipo string, permitirá almacenar la duración del mandato (los mandatos). 

Los campos 3 y 4 sirven para configurar la longitud de la barra horizontal correspondiente a cada presidente. 

Ahora mostramos los datos: 

/* Líneas de datos */
datosTabla.addRows([
[’Adolfo Suárez González’, ’(1977-1981)’, new Date(1977, 3, 30),
new Date(1981, 2, 25)],
[’Leopoldo Calvo-Sotelo’, ’(1981-1982)’, new Date(1981, 2, 25),
new Date(1982, 12, 2)],
[’Felipe González Márquez’, ’(1982-1996)’, new Date(1982, 12, 2),
new Date(1996, 4, 4)]
]);

Observe el formato particular para las fechas de inicio y fin del mandato (año, mes y día). 

Ahora vemos las opciones: 

/* Opciones de representación gráfica */


/* NB: Para el resto de las abundantes opciones consulte

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


/* https://developers.google.com/chart/interactive/
docs/gallery/timeline */
var opciones = {
colors: [’Blue’, ’Red’, ’Orange’]
};

La  opción  colors  indica  el  color  reservado  para  cada  presidente,  azul  (blue) para Adolfo Suárez González, por 
ejemplo. Los nombres de los colores se pueden sustituir por los códigos hexadecimales asociados. 

Puede  consultar  el  resto  de  las  abundantes  opciones  en  la  dirección: 
https://developers.google.com/chart/interactive/docs/gallery/gauge  

Como  en  todos  los  ejemplos  de  este  capítulo,  la  función  dibujarGrafico  termina  instanciando  y  trazando  el 
gráfico. 

La ejecución de la visualización del gráfico en la capa HTML  chart_div también se hace después del final de la 
función dibujarGrafico. 

Ejecución del script 

El script TIMELINE.htm muestra lo siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 13 -


Conceptos básicos

En  un  desarrollo  Web,  como  en  cualquier  aplicación  informática,  puede  ser  interesante  generar  sobre  la  marcha 
documentos  en  formato  PDF.  Esto  se  usará  mucho,  por  ejemplo,  en  un  sitio  web  de  compras,  en  el  que  el  usuario 
podrá recibir un factura, una confirmación de su pedido, etc. 

Este formato de archivo es muy compacto y susceptible de utilizarse como elemento adjunto en un mail. 

Para generar documentos en este formato, hay muchas soluciones, principalmente en JavaScript. Vamos a ver dos de 
ellas a través de ejemplos concretos. 

Debe  saber  que  las  librerías  dedicadas  en  PHP  también  existen,  principalmente  FPDF  (http://www.fpdf.org/)  y  son 
conocidas por su simplicidad de utilización y eficacia. 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


API de generación de archivos PDF

1. Solución pdf24.org

El  API  pdf24  (propuesto  en  el  sitio  web  http://es.pdf24.org/)  es  una  solución  relativamente  sencilla.  Es  más  que 
suficiente para la creación de documentos PDF sencillos. 

El API (librería que se debe instalar en su sitio web) está disponible para su descarga gratuita y se describe en la 
dirección http://es.pdf24.org/JavaScript­pdf­api.html. 

Estudiemos  en  detalle  un  script  JavaScript  de  ejemplo.  La  mayor  parte  del  código  útil  está  en  la  sección  HTML 
<body>. El código se reproduce íntegramente a continuación. Se aportan comentarios detallados. 

Sección HTML <head> 

Es necesario instalar en su sitio web la librería  pdf24.js. En la sección HTML <head>, esta librería se llama como 
sigue: 

<!—Integración de la librería JavaScript pdf24.js -->


<script type="text/Javascript" src="pdf24.js"></script>

Sección HTML <body> 

/*
Creación del archivo PDF y configuración básica
*/
/* Instanciación de un nuevo documento */
var archivoPDF = new PDF24Doc();
/* Definición del juego de caracteres */
archivoPDF.setCharset("UTF-8");
/* Nombre del archivo (con el sufijo pdf que añade el API) */
archivoPDF.setFilename("test");
/* Definición del formato de la página (A4 en formato vertical) */
archivoPDF.setPageSize(210, 297);

El  código  empieza  instanciando  un  nuevo  documento  PDF  llamado  archivoPDF  mediante  el  constructor 
PDF24Doc. 

El juego de caracteres UTF-8 se asigna posteriormente. 

El método setFilename del objeto archivoPDF permite asignarle un nombre. Observe que la extensión pdf se 
añade automáticamente. El método  setPageSize sirve para indicar el formato de la página (formato A4 en modo 
vertical en nuestro caso). 

Pasemos a la definición del contenido del documento en sí mismo: 

/*
Creación del contenido del documento PDF

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


*/
var contenidoPDF = new PDF24Element();
contenidoPDF.setTitle("Este es un documento creado por pdf24.js en PDF");
contenidoPDF.setUrl("http://www.pdf24.org");
contenidoPDF.setAuthor("Ángel Sánchez");
contenidoPDF.setDateTime("2010-04-15 8:00");
var texto ="";
texto = "El contenido del documento soporta el formato HTML con
las etiquetas habituales, como aquí la <b>negrita</b><br /><br />";
texto += "<table border=1>";
texto += "<tr><td><font color=blue>Código</font></td><td><font
color=blue>Nombre</font></td><td><font color=blue>Velocidad máxima
</font></td></tr>";
texto += "<tr><td>V001</td><td>Porsche 930 Turbo</td><td
align=right>290</td></tr>";
texto += "<tr><td>V002</td><td>Porsche 964 Turbo</td><td
align=right>300</td></tr>";
texto += "<tr><td>V003</td><td>Ferrari 430</td><td
align=right>320</td></tr>";
contenidoPDF.setBody(texto);

Instanciando un objeto PDF24Element, se crea el contenido del archivo, llamado contenidoPDF. 

Tiene a su disposición varios métodos para asignar el contenido a esta variable contenidoPDF, principalmente: 

l setTitle para definir un título al documento, 
l setURL para que podamos hacer clic en el título del documento y acceder a la URL que se pasa como argumento, 
l setAuthor para firmar el documento, 
l setDateTime para poner fecha al documento, 
l setBody para definir el contenido del documento. 

En el ejemplo habrá observado que es posible realizar formateos sofisticados, integrando en el texto etiquetas HTML. 

Falta asignar el elemento (es decir, la variable contenidoPDF) al objeto archivoPDF como sigue: 

/*
Añadir el contenido en el documento PDF
*/
archivoPDF.addElement(contenidoPDF);

Por supuesto, es posible asignar a un mismo objeto de la clase PDF24Doc diferentes contenidos consecutivamente. 

A  continuación,  aunque  no  es  obligatorio,  es  posible  programar  el  envío  del  archivo  PDF  (test.pdf  en  nuestro 
caso) usando mensajería electrónica a un destinatario dado. Esto se tiene en cuenta en nuestro script: 

/*
Configuración del envío del archivo PDF por mail

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


*/
archivoPDF.setEmailTo("[email protected]");
archivoPDF.setEmailFrom("[email protected]");
archivoPDF.setEmailSubject("Archivo creado por pdf24");
archivoPDF.setEmailBody("El archivo PDF se adjunta a este mensaje.
Cortesía de www.pdf24.org.");
archivoPDF.setEmailBodyType("texto");

Como  puede  observar,  esta  secuencia  de  código  no  presenta  ninguna  dificultad  particular;  los  nombres  de  los 
métodos utilizados por el desarrollador de este API son muy explícitos. 

En  nuestro  caso,  el  destinatario [email protected]  recibirá  un  mensaje  firmado  por 
[email protected]  con  el  texto  "Archivo creado por pdf24" como asunto y el texto 
" El archivo PDF se adjunta a este mensaje. Cortesía de www.pdf24.org.".  El  archivo 
test.pdf se envía como elemento adjunto en este mensaje. 

El envío del mensaje es una secuencia de código opcional. Si no está, el API generará en su navegador una nueva 
pestaña invitándole a: 

l descargar el archivo PDF, 

l enviar  el  archivo  PDF  a  un  destinatario,  usando  el  correo  electrónico  (se  le  pedirá  la  dirección  de  correo  del 
destinatario), 

l enviar el archivo PDF a un destinatario usando el fax (se le pedirá el número de fax del destinatario). 

El script termina creando el documento con el método create aplicado al objeto archivoPDF: 

/*
Creación del archivo PDF
*/
archivoPDF.create();

Ejecución del script 

El script PDF_01.htm muestra lo siguiente: 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


El archivo test.pdf generado se presenta como sigue: 

2. Soluciones alternativas

Existen muchos API que generan documentos PDF. Su estudio está fuera del objetivo de este libro. Sin embargo, 
puede considerar: 

l El API jsPDF (http://parall.ax/products/jspdf ), 

l El API de Adobe (http://www.adobe.com/devnet/acrobat/javascript.html ). 

El API JavaScript de Adobe Systems es muy completo. 

Recuerde que la empresa Adobe Systems es la creadora del formato de archivo PDF (Portable Document Format). 

Fuente Wikipedia : Portable Document Format, normalmente conocido como PDF, es un lenguaje descriptivo de 
páginas  creado  por  la  empresa  Adobe  Systems,  cuya  característica  principal  es  conservar  el  formato  de  un 
archivo ­tipos de letra, imágenes, objetos gráficos, etc.­ de una manera inalterada respecto al formato original 
establecido  por  el  autor  del  documento,  independientemente  del  software,  sistema  operativo  y  ordenador 
utilizados para imprimir o visualizar el documento. 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


Noción de código QR

El código QR (Quick Response) es un tipo de código de barras en dos dimensiones. Se compone de una yuxtaposición 
de cuadrados negros (sobre fondo blanco). 

Cada  vez  más,  los  códigos  QR  se  están  convirtiendo  en  verdaderas  herramientas  de  marketing  avanzadas  con 
integración del color o un logo. Es el caso de los siguientes ejemplos: 

Este tipo de código se puede leer por muchos dispositivos de lectura: 

l lector de código de barras compatible con códigos QR, 

l teléfonos móviles (con sistema operativo iOS, Android...), 

l webcam. 

La  lectura  de  un  código  QR,  fundamentalmente  a  través  de  aplicaciones  para  smartphones,  se  relaciona 
generalmente con: 

l un acceso a un sitio Web, usando una URL, 

l una consulta de un vídeo en línea (YouTube, Dailymotion...), 

l un acceso a un punto geográfico en un mapa Google Maps o incluso Bing Maps, 

l la adición de un mapa de visita virtual tipo vCard en una agenda electrónica, 

l la adición de un evento en una aplicación de tipo agenda electrónica, 

l una numeración telefónica, 

l la visualización de texto donde el código QR puede «abarcar» un contenido textual (de pequeño tamaño), 

l las aplicaciones de telepago (actualmente en fase experimental), 

l ... 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


Implementación del API JavaScript de creación de código QR

Como en el caso de los API de generación de documentos en formato PDF (véase el capítulo anterior), existen muchos 
API que permiten la creación de códigos QR. 

Vamos a ver, usando dos ejemplos, algunas de las posibilidades de los códigos QR: 

l Ejemplo 1: Código QR que guarda el número de teléfono correspondiente a una llamada telefónica, 

l Ejemplo 2: Código QR que guarda la URL de un sitio Web. 

1. Ejemplo 1: Código QR que incluye un número de teléfono

Comentario del script 

Para  este  primer  ejemplo,  vamos  a  utilizar  el  generador  de  códigos  QR  de  la  empresa  IWWWIT:  http://qr­code­
generator.iwwwit.com/generateur­qr­code.php 

El inconveniente de la solución es que hay que transmitir (publicar en el sentido HTML del término) los argumentos 
del código QR que se va a crear a un script PHP alojado por la empresa IWWWIT. Esto penaliza la integración de 
esta  solución  en  su  propio  desarrollo  Web.  Se  trata  de  la  elección  técnica  de  la  mayoría  de  las  empresas  que 
ofrecen este tipo de dispositivo. 

El código del script es muy simple. Es suficiente con transmitir, con un formulario dentro de la sección HTML <body>, 
un  conjunto  de  argumentos  con  destino  a  un  script  PHP  puesto  a  nuestra  disposición.  Una  vez  que  se  tiene  en 
cuenta la información por este script, genera el código QR en una página Web (es justamente esto lo que resulta un 
poco molesto desde el punto de vista de usabilidad). 

A continuación se muestra el código del formulario: 

<!-- Formulario que solicita la creación del código QR correspondiente


a un número de teléfono -->
<!-- NB: No modificar los atributos name de los diferentes input -->
<h2> QR code que permite lanzar una llamada telefónica </h2>
<form method="post"
action="http://qr-code-generator.iwwwit.com ">
Número de teléfono: <input type="text" name="tel-num" id="tel-num" />
<input type="hidden" name="colorf" class="colorf" value="#ffffff" />
<input type="hidden" name="colorp" class="colorp" value="#000000" />
<input type="hidden" name="err" class="err-l" value="L" />
<input type="hidden" name="qrsize" class="qrsize" value="300" />
<input type="submit" name="sub" value="Generación del código QR" />
</form>

Observe que la información (excepto el número de teléfono, que se le pedirá) se envía al script del servidor en modo 
oculto (type="hidden"). 

Los valores de los atributos name e id se fijan por el script del servidor. No cambie tampoco la cláusula  value del 
botón de envío. 

Ejecución del script 

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 1-


 

A continuación, como ejemplo, se muestra la interfaz de entrada de datos del número de teléfono: 

El resultado se proporciona sin retraso alguno por la aplicación servidor como sigue: 

2. Ejemplo 2: Código QR que incluye una URL

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


La  solución  que  se  mantiene  en  este  segundo  ejemplo  es  un  poco  más  clásica.  También  se  envían  al  API  Google 
argumentos técnicos relativos del código QR, fundamentalmente: 

l el tamaño del código QR (dimensión del cuadrado expresado en píxeles), 

l el texto de la URL. 

Los argumentos se envían al API a través de una URL (y no con un formulario, como en el ejemplo 1). 

La  ventaja  de  la  solución  Google  está  en  la  manera  en  que  se  presenta  el  resultado,  que  se  puede  devolver 
directamente a la página Web que ha servido para introducir los argumentos. 

Estudiemos rápidamente el código del script. 

Sección HTML <body> 

Principalmente,  esta  sección  incluye  el  formulario  de  entrada  de  datos  de  los  dos  argumentos  mencionados  con 
antelación: 

<!-- Formulario de entrada de datos de los argumentos del código QR -->


<form>
<table>
<tr>
<td>
Texto QR Code
</td>
<td>
<input type=”text" id="textoQRCode" size="50"
value="http://angel.sanchez.online.es">
</td>
</tr>
<tr>
<td>
Tamaño QR Code (Altura=Longitud)
</td>
<td>
<input type=”text" id="tamañoQRCode" size="5"
value="150">
</td>
</tr>
</table>
<br />
<input type="button" id="botonGeneracionQRCode"
value="Crear el QR Code" onclick="generarQRCode()">
</form>

El formulario se sigue por: 

<!-- Imagen QR Code -->


<img id="imagenQRCode">

© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 3-


Se trata de la posición de la imagen del código QR, que se genera por la función  generarQRCode que, a su vez, 
se llama por el botón botonGeneracionQRCode al final del formulario. 

Sección HTML <head> 

Después de la etiqueta meta habitual ( [<meta
HTTP-equiv="Content-Type"] [content="text/html;
charset=utf-8" />]) y del título de la página Web, esta sección contiene la función generarQRCode. 

/* Función generarQRCode */
function generarQRCode()
{

/* Preparación de la URL de creación del código QR */


/* Ejemplo URL:
https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=
Hello%20world&choe=UTF-8 */
var urlQRCode="https://chart.googleapis.com/chart?";
urlQRCode = urlQRCode + "&chs="
+ document.getElementById(’tamañoQRCode’).value + "x"
+ document.getElementById(’tamañoQRCode’).value;
urlQRCode = urlQRCode + "&cht=qr";
urlQRCode = urlQRCode + "&chl="
+ document.getElementById(’textoQRCode’).value;
urlQRCode = urlQRCode + "&choe=UTF-8";

/* Visualización de control de la URL */


// alert("URL del generación del código QR: " + urlQRCode);

/* Visualización del código QR */


document.getElementById(’imagenQRCode’).src = urlQRCode;
}

Tres de los cuatro argumentos que se envían con la URL al API Google son obligatorios: 

l el argumento chs, que indica el tamaño del código QR (longitud x altura), 

l el argumento cht, que indica que el API Google Charts debe generar un código QR (valor del argumento qr), 

l el argumento chl, que contiene la URL a la que el código QR dará acceso. 

El argumento  choe es opcional. Sirve para indicar la codificación de los datos en el código QR (valores que hay que 
elegir entre UTF-8 (valor por defecto), Shift_JIS e ISO-8859-1. 

El script de la función termina visualizando el código QR (véase la imagen anunciada en la sección HTML) como sigue: 

/* Visualización del código QR */


document.getElementById(’imagenQRCode’).src = urlQRCode;

Ejecución del script 

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack


© Editions ENI – Tous droits réservés – Copie personnelle de Jack Jack - 5-

También podría gustarte