Colofón

Escrito por Camilo Castro y colaboradores [1]. Para Ninjas.cl[2].

Licencia Creative Commons

A menos que se especifique explícitamente, el código fuente esta bajo una licencia BSD-2[4].

Este libro puede ser gratuitamente leido en:

Edición de Junio del 2024

Dedicatoria

Este texto está dedicado a Victor Manuel Arjona Cabrera y a todo el equipo de la revista Club Nintendo por escribir la guía inicial de Club Net en 1997, la cual me abrió las puertas a la informática.

Capítulo 1. HTML

Para empezar, HTML (Lenguaje de Marcas de Hipertexto, del inglés HyperText Markup Language) [5]. Es el lenguaje de elaboración de páginas para el Web. También es muy importante decir que el concepto que muchos tienen sobre Internet es sólo el de las páginas creadas para el WWW (World Wide Web o Red mundial en español) [6], pero esto sólo es la parte "bonita" de Internet y la que vamos a ver en esta ocasión. Para que puedas llevar a cabo lo que aquí aprenderás, necesitas un editor de texto para poder escribir tu página (escribe tu página y guárdala como texto plano poniéndole la extensión html)[7] (Recomendamos Doom Emacs), un navegador (de preferencia Firefox) para poder ver el resultado de lo que hiciste y haber entrado al menos un par de veces a la red para que sepas de qué hablamos cuando hagamos referencias a enlaces y a direcciones de correo electrónico (mejor conocido como email).

En el pasado también se usaba la extensión htm, pero era por compatibilidad con sistemas operativos (FAT) [8] que no permitían extensiones de más de 3 letras. Hoy siempre es recomendable usar html como extensión.

Al nombrar los archivos recomendamos no usar espacios ni caracteres con acentos, de preferencia siempre en minúsculas. Esto es para simplificar la URL [9].

Cuando hablemos de browser (navegador) nos referimos a Firefox[10], Edge, Safari o Chrome y similares.

Como una herramienta de apoyo puedes ir a JSBin[11] y la página de Documentación de Mozilla[12] para aprender y practicar los códigos rápidamente.

1.1. Comenzando

Todo programa de HTML esta formado de etiquetas o "tags" que son algo así como los comandos del lenguaje. Estos tags van a ir encerrados entre corchetes angulares ó < y >, Entonces, tu página en HTML debe comenzar así:

Código de HTML
<!DOCTYPE html>
<html>
    <!-- El código de tu página -->
</html>

La primera y segunda línea de código indica que se trata de una página en HTML.[13].

El único propósito de <!DOCTYPE html> es declarar el uso de HTML moderno, omitirla da compatibilidad con hasta Internet Explorer 5.

La tercera línea es un "comentario" el cual no va a ser tomado en cuenta por el browser y que sirve para que tú no te enredes con tu código. Para entenderle mejor, todo lo que esté entre <!— y —> no va a aparecer en el browser.

Si bien no se mostrarán los comentarios HTML, si estarán presentes en la página si vemos su código fuente. Por lo que aumentarán el tamaño del documento. Procura no escribir mensajes con información delicada.

La cuarta línea indica el final de tu código. Si te fijas bien, este tag tiene un "slash" o / después del corchete angular. Cuando veas tags con el slash, quiere decir que se está cerrando algún tag, en este caso el de <html> (Para aquéllos que hayan programado en C o similares, es como el curly braces {} o fin de bloque).

Por cierto, al browser le da igual si escribes <HTML> ó <html> ó <HtMl>. Tampoco le importa si pones todo tu programa en una sola línea, pero si lo haces asi te podrías enredar tú solo.

El uso de minúsculas se estandarizó en el año 2000.

Ahora, todo programa de HTML tiene una cabeza (<head>) y un cuerpo (<body>) (como un muñeco de nieve):

Estructura de Página HTML
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <!-- El código de tu página -->
    </body>
</html>

1.1.1. Etiqueta <title>

Dentro de la cabeza pueden ir comentarios (de hecho, estos pueden ir donde sea) y el tag <title>, este tag va a poner un título hasta arriba del browser. Veamos un ejemplo:

Etiqueta <title>
<!DOCTYPE html>
<html>
    <head>
        <title>Esta es una prueba</title>
    </head>
    <body>
        <!-- El código de tu página -->
    </body>
</html>

Uso de Etiqueta title

Cómo ves sólo aparece el título en la pestaña del browser y el comentario no aparece.

1.2. CSS

Ántes de entrar al contenido de una página, hay que decir que dentro del tag <body> [14] (y que conste que es muy diferente a decir dentro de <body>) pueden ir parámetros para cambiar el color del fondo, de los enlaces y del texto. Lo que se conoce como atributos. En específico podemos utilizar el atributo style [15].

Si al código de arriba le cambias la etiqueta <body> por:

<body>
<body style="color: #999999; background-color: #000;">
Estilos en <body>
<!DOCTYPE html>
<html>
    <head>
        <title>Esta es una prueba</title>
    </head>
    <body style="color: #999999; background-color: #000;">
        <!-- El código de tu página -->
    </body>
</html>

El resultado es que verás en tu browser que la parte donde iría la página se puso negra. Esto es por que la propiedad background-color (color de fondo) le pusimos color negro. La propiedad color sirve para indicar el color del texto que aparecerá en tu página.

Esto se conoce como estilos CSS (hojas de estilo en cascada o en inglés Cascading Style Sheets). El CSS es un lenguaje de marcado que se encarga de la apariencia de las páginas web. Controla los colores, las fuentes y el diseño de los elementos de tu sitio web.

Este lenguaje de hojas de estilo también te permite añadir efectos o animaciones. Sin CSS, tu sitio web se verá como una página básica HTML muy aburrida y desabrida.

Anteriormente utilizamos lo que se conoce como un estilo inline (misma línea). Lo que nos da la posibilidad de dar estilos a un elemento en específico. Pero la recomendación es utilizar la etiqueta <style> dentro de la etiqueta <head> (la cabecera) para así dar estilos a todos los elementos de la página en un único lugar (mejorando el órden y legibilidad del código).

Estilos en <style>
<!DOCTYPE html>
<html>
    <head>
        <title>Esta es una prueba</title>
        <style text="text/css">
            /* Este es un comentario en CSS */
            body {
                color: #999999;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        <!-- El código de tu página -->
    </body>
</html>

Al igual que HTML, CSS cuenta con un comentario especial que va desde /* a */. Todo lo que este escrito dentro de esos dos símbolos, será omitido por el navegador.

1.2.1. CSS Externo

Adicionalmente a la etiqueta <style> tenemos la opción de obtener un CSS desde una ubicación, puede ser localmente o remotamente.

<link rel="stylesheet" type="text/css" href="miestilo.css">

Usar estilos dentro de la página (etiqueta style) es bueno para hacer pruebas y correcciones rápidas. Usar un CSS externo es recomendable cuando la página ya este completa y disponible públicamente. Definir cual usar depende del contexto, pero usar CSS externo es lo más recomendable en la mayoría de los casos.

1.2.2. Colores

Aquí es bueno explicar algo acerca de los colores.[16] Si te fijas bien, cada parámetro va seguido de 6 dígitos. Los dos primeros indican la cantidad de rojo que quieres, los 2 siguientes indican la cantidad de verde y los 2 últimos indican cuánto de azul. Esto es porque se está trabajando en RGB (Red, Green, Blue). Para obtener los diferentes colores, hay que mezclar diferentes cantidades en los tres componentes. Por ejemplo:

  • El blanco se hace con 100% de Red, 100% de Green y 100% de Blue.

  • El morado se hace con 100% de Red, 0% de Green y 100% de Blue.

  • El negro se hace con 0% de Red, 0% de Green y 0% de Blue.

  • El amarillo con 100% de Red, 100% de Green y 0% de Blue.

¡Hey! Un momento. Cuando tenía 5 años me enseñaron que si juntas amarillo y azul te da verde. ¿Por qué ahora me dicen que rojo y verde te da amarillo? Ambas cosas son ciertas. Lo que pasa es que RGB [17] es diferente a CMYK [18] (en este último indica el color verde no es color primario).

Notar que el color negro #000 usó solamente 3 números. Esto es una ayuda de CSS. Cuando se escriben tres números iguales, los otros tres restantes serán automáticamente añadidos.

Los atributos de color van a tomar valores "hexadecimales", o sea que en vez de ir de 0 a 9 como en base 10 (diez valores posibles), van a ir de O a 15 (16 valores posibles), por lo tanto, lo dígitos hexadecimales son: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, donde A vale 10, B vale 11, C vale 12, etc. Así logras tener un total de 16777216 colores (16.7 millones de colores). Entonces, un Rojo al 100% sería FF (El número 255). Puedes identificar que es un número hexadecimal por que el valor comienza con un hashtag #.

Además de hexadecimal CSS soporta otras formas de expresar los colores como rgb, rgba (con transparencia), hsl, hsla, entre otros.

1.2.3. Unidades de medida

Existen diversas unidades de medida [19] dependiendo de lo que queramos representar. La más común es px (pixeles).

La cantidad debe estar pegada a la unidad de medida, por ejemplo margin-left: 20px. Notar que es 20px y no 20 px.

Entre los más comunes se pueden encontrar [20]:

  • px: Valor absoluto pixel.

  • %: Valor relativo al porcentaje basado en el valor del elemento padre.

  • em: Valor relativo al tamaño de letra del elemento padre.

  • rem: Valor relativo al tamaño de letra del elemento raíz.

  • lvh: Valor relativo al tamaño del viewport del dispositivo.

1.2.4. Selectores en CSS

Hay diversas formas de seleccionar un elemento para otorgarle estilos en CSS. Por tipo, por clase y por ID [21].

Por Tipo

El elemento está presente en el documento, por ejemplo el elemento <body> que ya hemos dado estilos. Se aplican los estilos a todos los elementos del mismo tipo presentes en el documento.

Ejemplo de Selección por Tipo
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        <h1>Mi Título</h1>
        <p>Mi Contenido</p>
        <p>Único</p>
    </body>
</html>
Por Clase

El elemento indica que utiliza una o más clases de estilos en su atributo class. Se aplican los estilos a todos los elementos que declaran pertenecer a la clase dentro del documento.

En CSS se puede usar una clase con el prefijo de punto. Ejemplo .verde.

Ejemplo de Selección por Clase
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }

            .rojo {
                color: red;
            }

            .verde {
                color: green;
            }

            .grande {
                font-size: 40px;
            }
        </style>
    </head>
    <body>
        <h1 class="verde grande">Mi Título</h1>
        <p class="rojo">Mi Contenido</p>
        <p class="verde">Único</p>
    </body>
</html>

En el ejemplo los elementos con la clase .verde serán de color verde y los elementos de clase .rojo serán de color rojo. Además la clase .grande aumentará la fuente a 40 pixeles.

Selector por Clase en CSS

Por ID

El elemento utiliza un identificador único y está asociado a solo un elemento en el atributo id. Se puede identificar utilizando un hashtag # antes del nombre ejemplo #unico.

Ejemplo de Selección por ID
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }

            .rojo {
                color: red;
            }

            .verde {
                color: green;
            }

            .grande {
                font-size: 40px;
            }

            #unico {
                color: yellow;
            }
        </style>
    </head>
    <body>
        <h1 class="verde grande">Mi Título</h1>
        <p class="rojo">Mi Contenido</p>
        <p class="verde" id="unico">Único</p>
    </body>
</html>

Selector CSS por ID

Como se puede ver el selector #unico sobreescribe el color verde por un color amarillo.

CSS aplica los cambios en forma de cascada, es decir, que el último cambio realizado es el que se muestra como resultado final. Por esta razón a pesar de ser verde originalmente cambió a amarillo.

Especificidad

Un tema especial es la especificidad [22] de los selectores CSS. No entraremos muy en detalle, pero significa la forma en que podemos determinar cuál será el estilo que se está aplicando al elemento. Es responder a la pregunta ¿Cuán específico es mi selector?.

Ejemplo de especificidad en CSS
div.outer p {
  color: orange;
}
div:not(.outer) p {
  color: lime;
}

1.3. Texto y Contenido

Ya con estos conocimientos vamos a pasar a lo bueno, el contenido de la página.

Contenido
<!DOCTYPE html>
<html>
    <head>
        <title>Esta es una prueba</title>
        <style text="text/css">
            body {
                color: #999999;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        ?Que' tal como esta'n?
        Ojala que le este'n entendiendo.
    </body>
</html>

Página con fondo negro

1.3.1. Caracteres especiales

Observa bien y fijate como las dos líneas de texto salen juntas, es decir, el browser no respetó el "Enter" que diste. También existe el pequeño problema de los acentos y del signo de interrogación.

Los acentos y caracteres raros como la ñ los puedes poner usando algo parecido a código ASCII [23]. Los códigos los pones después de &:

  • La á es con 225 (&#225).

  • La é es con 232 (&#232).

  • La í es con 237 (&#237).

  • La ó es con 243 (&#243).

  • La ú es con 250 (&#250).

  • La ¿ es con 191 (&#191).

  • La ñ es con 241 (&#241).

Uno de los más comunes es &nbsp; usados para dar un espacio sin un salto de línea.

Estos códigos se conocen como entidades de caracteres HTML[24] y tienen distintos símbolos que se pueden expresar con números y letras.

Sin embargo, es sumanente complicado escribir en castellano de esta forma. Por lo que se debe añadir una nueva etiqueta <meta> [25] en la cabecera.

Las etiquetas <meta> dan información adicional sobre nuestra página web, información que no está destinada a las personas, más bien al navegador y robots de internet.

Por ejemplo usaremos <meta charset="utf-8"> dentro de <head> para indicar al navegador que nos permita utilizar todo el abanico de caracteres disponibles en cualquier idioma humano, lo que se conoce como UTF-8 [26] (incluyendo emojis [27] twemoji).

Uso de <meta>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Esta es una prueba</title>
        <style text="text/css">
            body {
                color: #999999;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        ¿Qué tal como están?
        Ojalá que le estén entendiendo.
    </body>
</html>

Otra etiqueta <meta> muy usada es la <meta name="viewport" content="width=device-width, initial-scale=1"> [28], la cual nos permite tener compatibilidad con pantallas pequeñas como en los teléfonos móviles.

1.3.2. Etiqueta <p>

Para dar un espacio utilizaremos la etiqueta <p>, la cual quiere decir párrafo [29]. También existe la etiqueta <br> la cual significa "salto de página" [30], pero no es muy usada y se recomienda más <p>.

Etiqueta <p>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Esta es una prueba</title>
        <style text="text/css">
            body {
                color: #999999;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        <p>
            ¿Qué tal como están?
        </p>
        <p>
            Ojalá que le estén entendiendo.
        </p>
    </body>
</html>

Página con fondo negro y utf8

1.3.3. Otras Etiquetas

Otros tags que están involucrados con texto son:

  • Títulos como <h1>, <h2>, <h3>, <h4>, <h5>, <h6> (mientras más grande el número más pequeño es el tamaño) [31].

  • Listas numeradas con <ol> [32],

  • Listas sin numerar con <ul> [33] o <menu> [34].

  • Elemento dentro de una lista con <li> [35].

  • Elemento de lista de definiciones <dl>, <dt> y <dd> [36].

  • Elemento <span> nos permite agrupar una porción de texto para darle estilos por separado. [37].

  • Elemento <sup> nos permite elevar el texto (superíndice). [38].

  • Element <sub> nos permite bajar el text (subíndice). [39].

  • Elemento <strong> o <b> [40] permiten usar negritas. [41]

  • Elemento <em> permite dar énfasis a un texto. [42].

  • Elemento <code> permite escribir código fuente. [43].

  • Elemento <kbd> permite mostrar pulsaciones de teclado. [44].

  • Elemento <var> permite mostrar variables de programas. [45].

  • Elemento <cite> permite citar un texto. [46].

  • Elemento <dfn> permite marcar un término a definir. [47].

  • Elemento <samp> permite mostrar un resultado de un programa como ejemplo. [48].

  • Elemento <i> permite utilizar cursivas. [49].

  • Elemento <tt> permite usar texto con ancho fijo. [50].

  • Elemento <article> información de contenido. [51].

  • Elemento <address> información de contacto. [52].

  • Elemento <pre> texto que respetará los espacios y párrafos. [53].

Mas Tags de Texto
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        <h1>Bienvenidos</h1>
        <h2>Menú</h2>
        <menu>
            <li>Opción A</li>
            <li>Opción B</li>
            <li>Opción C</li>
            <li>Opción D</li>
            <li>Opción E</li>
            <li>Opción F</li>
        </menu>
        <h2> Menú 2</h2>
        <ol>
            <li>Opción A</li>
            <li>Opción B</li>
            <li>Opción C</li>
        </ol>
        <h3><span style="color:#ff0000">Advertencia</span> No leas esto</h3>
        <dl>
            <dt>Palabra</dt>
            <dd>Definición</dd>

            <dt>Palabra 2</dt>
            <dt>Palabra 3</dt>
            <dd>Otra Definición</dd>
        </dl>
    </body>
</html>

Elementos de Texto

1.4. Tablas

Imagínate que organizaste un concurso y necesitas poner a los ganadores en tu página. ¿A poco no se vería mejor tenerlos bien ordenaditos en una tabla?. [54].

Ejemplo de Tabla
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }
        </style>
    </head>
    <body>
        <h1>TOPS</h1>
        <table>
            <thead>
                <tr>
                    <th>Rango</th>
                    <th>Nombre</th>
                    <th>Pista</th>
                    <th>Tiempo</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>Toad</td>
                    <td>Luigi Raceway</td>
                    <td>1' 51'' 10</td>
                </tr>
                <tr>
                    <td>2</td>
                    <td>Mario</td>
                    <td>Luigi Raceway</td>
                    <td>1' 51'' 11</td>
                </tr>
                <tr>
                    <td>3</td>
                    <td>Luigi</td>
                    <td>Luigi Raceway</td>
                    <td>1' 51'' 12</td>
                </tr>
                <tr>
                    <td>4</td>
                    <td>Wario</td>
                    <td>Luigi Raceway</td>
                    <td>1' 51'' 13</td>
                </tr>
                <tr>
                    <td>5</td>
                    <td>Bowser</td>
                    <td>Luigi Raceway</td>
                    <td>1' 51'' 14</td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

Las tablas al igual que nuestro documento tienen una estructura de cabeceras <thead> y cuerpo <tbody>. Una tabla se compone de filas y columnas. El elemento para una columna es <tr> y los elementos para filas son <th> en la cabecera y <td> para el cuerpo.

En realidad no es difícil usar tablas, sólo se necesita tener el "esqueleto" de una de ellas y cuando quieras usar una, únicamente hay que insertar el texto o incluso imágenes u otro contenido.

Tabla sin Estilos

Si mostramos nuestra página vemos que los datos quedan ordenaditos, pero falta que se vea bonito. Para esto usaremos la característica de CSS de clases e ids. (class y id).

1.4.1. Tabla con CSS

Ahora aplicaremos CSS para mejorar el aspecto visual de nuestra tabla.

Ejemplo de Tabla con CSS
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo Tabla con CSS</title>
        <style text="text/css">
            body {
                color: #fff;
                background-color: #000;
            }

            table {
            	width: 100%;
            	border-style: solid;
                border-width: thin;
                border-collapse: collapse;
            }

            th, td {
            	width: 25%;
            	border-style: solid;
                border-width: thin;
                padding: 8px;
            }

            .color-red {
            	color: #ff0000;
            }

            .background-gray {
            	background-color: #303030;
            }

            .center {
            	text-align: center;
            }

            .left {
            	text-align: left;
            }

            .right {
            	text-align: right;
            }
        </style>
    </head>
    <body>
        <h1 class="center color-red">TOPS</h1>
        <table>
            <thead>
                <tr>
                    <th class="center">Rango</th>
                    <th class="left">Nombre</th>
                    <th class="center">Pista</th>
                    <th class="right">Tiempo</th>
                </tr>
            </thead>
            <tbody>
                <tr class="background-gray">
                    <td class="center">1</td>
                    <td class="left">Toad</td>
                    <td class="center">Luigi Raceway</td>
                    <td class="right">1' 51'' 10</td>
                </tr>
                <tr>
                    <td class="center">2</td>
                    <td class="left">Mario</td>
                    <td class="center">Luigi Raceway</td>
                    <td class="right">1' 51'' 11</td>
                </tr>
                <tr>
                    <td class="center">3</td>
                    <td class="left">Luigi</td>
                    <td class="center">Luigi Raceway</td>
                    <td class="right">1' 51'' 12</td>
                </tr>
                <tr>
                    <td class="center">4</td>
                    <td class="left">Wario</td>
                    <td class="center">Luigi Raceway</td>
                    <td class="right">1' 51'' 13</td>
                </tr>
                <tr>
                    <td class="center">5</td>
                    <td class="left">Bowser</td>
                    <td class="center">Luigi Raceway</td>
                    <td class="right">1' 51'' 14</td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

Tabla con CSS aplicado

Algunas propiedades de CSS usadas son:

  • width nos permite decir que la tabla ocupe todo el ancho de la pantalla, el 100%.

  • text-align nos permite alinear el texto al centro, izquierda o derecha.

  • padding nos permite dar un espacio superior, inferior, izquierdo y derecho de 8 pixeles para cada elemento th y td.

  • border-style y border-width nos permiten declarar el estilo del border y su ancho. border-collapse nos permite declarar que el borde no tenga separaciones entre cada elemento (este comprimido).

1.5. Imágenes

Para utilizar imágenes en nuestro documento html debemos usar la etiqueta <img> [55] y se debe poner la ruta de la imagen en su atributo src de la siguiente forma:

Ejemplo de Imagen
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Esta es una prueba de imagen</title>
         <style text="text/css">
          body {
            color: #fff;
            background-color: #000;
          }

          img {
          	width: 100%;
            height: auto;
          }
        </style>
    </head>
    <body>
        <h1>Este es un ejemplo de cómo poner una imagen</h1>
        <img src="waverace64.png"
            title="Wave Race 64"
            alt="Gameplay del juego Wave Race 64, para Nintendo 64."
        >
    </body>
</html>

Página con Imágenes

La línea <img src="waverace64.png"> indica al browser que coloque una imagen la cual se llama waverace64.png y está en el mismo directorio donde está tu archivo de HTML. Aquí es importante hacer un alto para remarcar algunos aspectos:

  1. Hay varios formatos de imágenes disponibles para usar, los más comunes son JPG [56] para fotos y PNG [57] para ilustraciones con transparencias. Antes se usaba GIF [58] para animaciones pequeñas con transparencia, pero fue desplazado debido a su limitaciones técnicas. Actualmente también se puede usar formatos como WebP [59], AVIF [60] y SVG [61].

  2. Para videos se puede usar MP4 [62] en el elemento <video> [63] y audios con el elemento <audio> [64].

  3. Adicionalmente le damos un título a nuestra imagen con el atributo title y una descripción en el atributo alt. Esto es útil para las personas no videntes que pueden visitar nuestra página y obtener una descripción de la imagen.

  4. Dentro del CSS le añadimos un ancho (width) del 100% y un alto (height) automáticamente calculado, para que mantenga la proporción de la imagen. Aunque siempre es recomendable utilizar las imágenes con su tamaño ya procesado anteriormente y comprimidas para disminuir su peso.

1.5.1. Posicionando Imágenes

Para poder dar la posición de izquierda, derecha o centro debemos usar una propiedad de CSS llamada float [65].

Ejemplo de Posicionado de Imágenes
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Otra prueba de imágenes</title>
         <style text="text/css">
          body {
            color: #fff;
            background-color: #000;
          }

          img {
          	width: 50%;
            height: auto;
          }

          img.left {
            float: left;
            margin-right: 15px;
          }

          img.right {
            float: right;
            margin-left: 15px;
          }

          img.center {
            float: center;
          }

          br {
          	clear: both;
          }
        </style>
    </head>
    <body>
        <h1>Imágenes en distintas posiciones</h1>
        <img
            class="left"
            src="mario64.png"
            title="Super Mario 64"
            alt="Gameplay del juego Super Mario 64, para Nintendo 64."
        >
        <p>
            Acá puede ir un texto grande o pequeño. Puede ir el texto que más quieras.
        </p>

        <br>
        <img
            class="right"
            src="mario64.png"
            title="Super Mario 64"
            alt="Gameplay del juego Super Mario 64, para Nintendo 64."
        >
        <p>
            Acá puede ir un texto grande o pequeño. Puede ir el texto que más quieras.
        </p>

        <br>
        <img
            class="center"
            src="mario64.png"
            title="Super Mario 64"
            alt="Gameplay del juego Super Mario 64, para Nintendo 64."
        >
        <p>
            Acá puede ir un texto grande o pequeño. Puede ir el texto que más quieras.
        </p>
    </body>
</html>

Posición de Imágenes con Float

Como se puede ver utilizamos la propiedad float para permitir que el texto este a la izquierda (float left), derecha (float right) y centro (float center). La propiedad especial clear: both que aplicamos a la etiqueta <br> nos permite crear un salto de página y limpiar cualquier elemento con float anterior. Finalmente la propiedades margin-left y margin-right nos permiten dar un pequeño espacio de separación entre la imagen y el texto, si no los usamos el texto estaría pegado a la imagen.

1.5.2. Imágenes de Fondo

Para poner una imagen de fondo utilizamos las propiedades background-image [66], background-repeat [67] y background-size [68] podemos definir las características de una imagen de fondo dentro de la etiqueta body.

Ejemplo de Imagen de Fondo
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Imagen de Fondo</title>
         <style text="text/css">
          body {
            color: #fff;
            background-color: #000;
            background-image: url("mariokart64.jpg");
            background-repeat: repeat;
            background-size: 320px auto;
          }
        </style>
    </head>
    <body>
        <!-- Contenido -->
    </body>
</html>

Imagen de Fondo de Mario Kart 64

1.5.3. Rutas relativas y absolutas

Hay dos formas de establecer rutas. Una relativa y una absoluta. La relativa toma la ruta donde está el documento html como ruta inicial. La absoluta debe establecer la ruta completa.

Ejemplo de Rutas
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Rutas Relativas y Absolutas</title>
    </head>
    <body>
        <img src="imagen.jpg">
        <img src="fotos/fondo.jpg">
        <img src="../animacion.gif">
        <img src="/Users/camilo/imagen.jpg">
        <img src="https://ejemplo.com/imagen.jpg">
    </body>
</html>
  • "imagen.jpg": Le estamos indicando al navegador que la imagen se encuentra en el mismo directorio en donde está el documento que la manda llamar.

  • "fotos/fondo.jpg": Aquí le indicamos al navegador que la imagen está en un directorio llamado "fotos" y que este directorio es relativo (en el mismo lugar) donde está el documento.

  • "../animacion.gif": Ahora, la imagen está un directorio atrás de donde está nuestro documento. Dos puntos (..) significa directorio anterior y un punto (.) directorio actual. Podemos llegar a tener rutas complejas como "../../.././animacion.gif".

  • "/Users/camilo/imagen.jpg": Esta es una ruta absoluta que no depende de la ubicación del documento HTML para encontrar el archivo. La podemos identificar por que el primer caracter es un slash (/).

  • "https://ejemplo.com/imagen.jpg": Esta es una url remota, tampoco dependerá de la ubicación del html para encontrar el archivo.

Existe una URL especial llamada data-uri [69] que nos permite incrustar la imagen dentro del documento. Esto hará más pesado el documento HTML, pero no será necesario incluir las imágenes separadas ni se harán llamadas a servicios externos. Todo estará incluido dentro del documento.

1.6. Enlaces

Toda buena página debe tener enlaces utilizando el elemento ancla [70], ya sea a otras partes de la misma página, archivos o a otros lugares en el internet. Si no se les da estilo en CSS aparecen subrayadas y de color azul, al posicionar nuestro puntero del ratón sobre ellas, el ícono cambiará a una mano.

Ejemplo de Elemento ancla
<a href="ruta">Lo que quieras</a>

La parte de "Lo que quieras" puedes poner texto, imágenes u otro contenido y cuando alguien le dé click a esta parte, el navegador les desplegará el contenido dentro de la ruta. En general, sólo se debe utilizar una ancla para navegación utilizando una URL adecuada. Para otros casos es mejor utilizar el elemento <button> [71].

Podemos cambiar los estilos con CSS: a, a:link [72], a:visited [73], a:hover [74] y a:active [75].

Ejemplo de Elemento Ancla con CSS
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Elemento Ancla</title>
         <style text="text/css">
          a {
            text-decoration: none;
            color: #999;
          }

          a:hover {
            color: #ff0000;
          }
        </style>
    </head>
    <body>
        <a href="#">Mi Contenido</a>
    </body>
</html>

1.6.1. Componentes de una URI y URL

Una URI o identificador uniforme de recursos es una cadena de caracteres que generalmente identifica cualquier recurso web mediante un nombre, una ubicación o ambos. Un localizador uniforme de recursos (URL) y un nombre uniforme de recursos (URN) son los dos tipos de URI.

esquema:[//autoridad]ruta[?query][#fragmento]

Ejemplos

Una URL o localizador universal de recursos, por su siglas en inglés, es una dirección completa de un sitio web que lleva a los usuarios a una página específica dentro de ese website.

  • esquema (http, https, ftp)

  • subdominio (www, blog)

  • dominio segundo nivel (Second-level domain, google, ninjas, youtube)

  • dominio primer nivel (Top-level domain, .com, .cl, .net)

  • puerto (port 80, 8000, 8080)

  • ruta (path)

  • consulta (query)

  • parámetros

  • fragmento

En síntesis, se trata de la dirección web que tiene cada uno de los recursos en Internet que les permite ser encontrados por los navegadores e identificados por diferentes herramientas.

Cada elemento que hace parte del WWW, sin importar su formato o propósito, debe tener una dirección URL específica donde está guardada.

En cuanto al puerto, es el número específico que identifica qué servicio web estás solicitando en un servidor web. Por ejemplo, el número de puerto predeterminado para la URL HTTP es 80 y para la URL HTTPS es 443. Sin embargo, si el servidor web utiliza un protocolo estándar como HTTP o HTTPS, el puerto suele omitirse en la URL.

1.6.2. index.html

Si llamamos a nuestra página index.html (index significa índice) automáticamente el navegador la cargará si llamamos a una URL. Ejemplo al llamar http://ejemplo.com es lo mismo que escribir http://ejemplo.com/index.html. Es importante que esté todo en minúsculas.

1.6.3. Hashtag

Para la ruta que dirige al ancla a una sección dentro de un documento se utiliza un hashtag (#). Si no se escribe nada despues del símbolo hashtag, se volverá al inicio. Si se escribe un texto, el navegador buscará un elemento cuyo atributo id sea el ingresado.

Ejemplo de Elemento Ancla con CSS
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Elemento Ancla en Mismo Documento</title>
    </head>
    <body>
        <h1 id="titulo">Mi Título</h1>
        <p>Contenido de Ejemplo</p>

        <h2 id="titulo2"> Segundo Título</h2>

        <a href="#titulo2">Mi Contenido</a>
    </body>
</html>

Al hacer click en "Mi Contenido" el navegador irá a la posición de <h2 id="titulo2">.

1.6.4. Enlaces a protocolos

Hay una forma de gatillar eventos especiales en el navegador como abrir el correo, marcar un teléfono, y otros. Esto es por que en ves de utilizar el protocolo común que es http o https se utiliza otro [76].

Ejemplo de protocolos en un ancla
<a href="mailto:correo@ejemplo.com">Esto abrirá el gestor de correos</a>
<a href="tel:+491570156">Esto abrirá la aplicación para llamar por teléfono</a>

http es una versión simple y no segura de la página, mientras que https es una versión donde la comunicación esta protegida. Siempre recomendamos usar https para navegar por internet.

target

Permite especificar dónde se abrirá el vínculo [77]. Si no es definido se abrirá en la misma página.

  • _self: El vínculo se abrirá en la misma página (predeterminado).

  • _blank: El vínculo se abrirá en una nueva pestaña.

  • _parent: El vínculo se abrirá en la página padre (si está en un iframe).

  • _top: El vínculo se abrirá en la primera página en el árbol de jerarquía.

  • nombre El vínculo se abrirá en un iframe específico con el atributo name.

<a href="/" target="_blank">Nueva página</a>

Usar target="_blank" no es muy recomendado por que puede causar algunos inconvenientes si el navegador es móvil. Evaluar si realmente es necesario antes de usarlo.

1.7. Mapas de Imágenes

Ahora que sabemos como usar una imagen y un enlace, podemos utilizar otra herramienta de HTML que utiliza ambos conceptos. Los mapas de imágenes [78].

Por ejemplo tomemos la siguiente imagen

Mario Kart 64 Player Select Screen

Lo que queremos hacer es que en sectores definidos de la imagen podamos hacer click y realizar una acción distinta.

Para esto hay que abrir la imagen en un editor de imágenes, hay varios como: Gimp [79], Paint.net [80] u otros que te darán las coordenadas exactas de cada pixel en la imagen.

Vamos a crear tres zonas distintas para hacer click.

  1. La imagen de Mario.

  2. La nariz de Yoshi.

  3. Todo lo demás.

Si vemos la imagen en un editor, podemos definir los lugares para hacer click.

Mario Kart 64 Player Select Screen en Editor de Imágenes

Como se puede ver las coordenadas comienzan en (x = 0, y = 0) en la esquina superior izquierda. Si se va hacia la derecha aumenta el eje x (eje abscisas) y si se va hacia abajo aumenta el eje y (eje ordenadas).

La imagen de Mario es una figura rectangular, lo que significa que necesitamos dos distintas coordenadas para formar la figura, es decir, las coordenadas de la esquina superior izquierda y la coordenada de la esquina inferior derecha.

El editor de imágenes nos brinda las siguientes coordenadas:

  • (x = 93, y = 178)

  • (x = 385, y = 457)

Ahora para la imagen de Yoshi es una figura ovalada, la cual solamente necesita la coordenada central y el radio necesario. Según el editor la coordenada es:

  • (x = 199, y = 611)

Existen cuatro posibles valores para un área dentro de un mapa [81]:

  • rect: Una figura rectangular, necesita de dos coordenadas.

  • circle: Una figura circular, necesita de una coordenada del punto central y el radio.

  • poly: Una figura compuesta por distintas coordenadas, normalmente usada para formas más complejas.

  • default: Un valor para abarcar cualquier area no especificada anteriormente.

Ejemplo de Mapa
<map name="mariokart64">
  <area
    shape="rect"
    coords="93,178,385,457"
    href="https://developer.mozilla.org/docs/Web/JavaScript"
    target="_blank"
    alt="JavaScript">

  <area
    shape="circle"
    coords="199,611,75"
    href="https://developer.mozilla.org/docs/Web/CSS"
    target="_blank"
    alt="CSS">

    <area shape="default" nohref>
</map>

Si no queremos una url, podemos usar la propiedad nohref.

La prioridad es de arriba hacia abajo. Por lo que shape=default siempre debe ir al final del mapa, si no abarcará por sobre las demás formas.

Hemos creado nuestro mapa y ahora lo debemos asociar a una imagen. El mapa fue llamado como mariokart64, lo que esta definido en el atributo name.

Para asociarlo a una imagen simplemente utilizamos el atributo usemap y asociamos con el nombre del mapa usando #. En este caso sería #mariokart64.

Ejemplo de Mapa asociado a una Imagen
<img src="mariokart64-ps-2.png" usemap="#mariokart64">
Ejemplo de Mapa con Imagen
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ejemplo de Mapa</title>
    </head>
    <body>
        <map name="mariokart64">
            <area
                shape="rect"
                coords="93,178,385,457"
                href="https://developer.mozilla.org/docs/Web/JavaScript"
                target="_blank"
                alt="JavaScript">

            <area
                shape="circle"
                coords="199,611,75"
                href="https://developer.mozilla.org/docs/Web/CSS"
                target="_blank"
                alt="CSS">

            <area shape="default" nohref>
        </map>

        <img src="mariokart64-ps-2.png" usemap="#mariokart64">
    </body>
</html>

1.8. Etiqueta <iframe>

En el pasado existían lo que se llaman <frameset> [82] y <frame> [83], usados comunmente para crear un menú y cargar distintas secciones en la página, pero fueron marcados como obsoletos. Hoy en día se utiliza el elemento <iframe> [84]. Muy usado para incrustar elementos externos dentro de nuestra página, por ejemplo videos de Youtube.

Ejemplo de <iframe>
<iframe
    width="560"
    height="315"
    src="https://www.youtube.com/embed/LeYLP5uerGQ?si=MtJKC6wNLMlF7m5O"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
</iframe>

Es importante notar que cada elemento <iframe> carga una página completamente y está separada de la página principal, por lo que utilizar muchos <iframe> puede usar muchos recursos y hacer nuestra página más lenta. Se deben usar apropiadamente y sin abusar de ellos.

1.9. Divisores de Contenido

Veremos un poco sobre las etiquetas de divisón o secciones de página. Una forma de agrupar nuestro contenido para facilitar el contexto tanto para CSS como para otras herramientas que analizan la página web.

Existen diversos y su uso simplemente varía en el contexto de la división. A continuación se mostrarán las etiquetas divisoras más comunes.

  • <div> [85]: Es una separación genérica, la más común.

  • <section> [86]: Similar a <div>, pero requiere de un título que le siga (h1, h2, h3, etc).

  • <main> [87]: Es la separación que tiene el contenido principal de nuestra web.

  • <header> [88]: Es la separación que normalmente está usada para los elementos iniciales (menus, logos, etc). No confundir con <head>.

  • <nav> [89]: Permite almacenar un menú de navegación.

  • <footer> [90]: Donde irá la información más abajo de la página. Normalmente un mensaje de copyright o similar.

Ejemplo de etiqueta divisora
<div class="warning">
  <p>Cuidado, piso resbaloso</p>
</div>

Capítulo 2. JavaScript

Hoy en día, JavaScript [91] es uno de los lenguajes de programación más populares y no solamente está limitado al ambiente de páginas web. Sin embargo únicamente veremos una pequeña pincelada de este lenguaje en el caso de uso de la Web.

2.1. Etiquetas

Hay dos formas de incluir JavaScript en nuestra página HTML.

La primera nos permite escribir el código directamente en la página HTML.

<script type="text/JavaScript">
    /* Mi script JavaScript */
</script>

La segunda forma nos permite obtener remotamente un archivo JavaScript e incluir su código en nuestra página.

<script src="miscript.js"></script>

Además de usarlos dentro de <head>, también es válido usarlo dentro de <body>, sobre todo al final de la página (</body>) para asegurar que se haya cargado todo el HTML y CSS antes del JavaScript.

2.2. Tipos de Datos

JavaScript cuenta con diversos tipos de datos. Pero solamente nombraremos a los más comunes:

  • Number (números) [92]: Tipo de dato que permite representar y manipular valores numéricos como 42 o -9.8.

  • String (texto) [93]: Tipo de dato que representa datos textuales (cadenas de caracteres).

  • Boolean (booleano) [94]: Tipo de dato que representa un valor lógico (booleano) y puede tener dos valores true o false.

  • Undefined (sin definir) [95]: Tipo de dato que representa cuando no se ha definido una variable o valor (no existe).

  • Null (nulo) [96]: Tipo de dato que representa el valor nulo o vacío (existe pero está vacío).

  • Object (objeto) [97]: Tipo de dato que representa una colección de datos definida y es la base para otros tipos de datos más complejos.

  • Function (función) [98]: Tipo de dato que representa un elemento con la capacidad de ser invocado con parámetros y retornar un resultado.

  • Array (arreglos) [99]: Tipo de dato que permite almacenar una cantidad de elementos en una lista.

2.3. Comentarios y Console

JavaScript permite comentarios de una línea (//) y comentarios de múltiples líneas (/*, */). Para poder mostrar mensajes en la consola utilizamos la herramienta console.log() [100]

// Comentario de una línea
/*
    Comentario de
    más línas
*/

console.log("Hola Mundo");

2.4. Variables

Existen varias formas para almacenar datos en los programas. En JavaScript se usan principalmente dos: let y const.

  • let: Usado cuando deseas permitir que la variable sea modificada.

  • const: Cuando quieres evitar que la variable se modifique despúes de ser asignada. La palabra const que significa "constante".

const numero = 10;
let numero_variable = 5;

// Error
numero = numero + 1

// Permitido
numero_variable = numero_variable + 1

Recomendamos usar const en la mayoría de los casos y let cuando se deba almacenar un dato que se desee modificar en el futuro.

2.5. Strings

Las cadenas de caracteres se pueden representar de diversas formas en JavaScript utilizando comillas dobles ("mi texto"), simples ('mi texto') y comillas invertidas (`) (backticks).

La recomendación es usar comillas invertidas por sobre las comillas dobles o simples, debido a que las comillas invertidas tienen dos ventajas:

  1. Permiten múltiples líneas.

  2. Permiten la interpolación, es decir usar código JavaScript dentro del texto.

const nombre = "Luigi"; // Comillas dobles
const apellido = 'Mario'; // Comillas simples
const nombre_completo = `${nombre} ${apellido}`; // Comillas invertidas e interpolación
const nombre_apellido = nombre + " " + apellido; // Sin interpolación solo podemos concatenar

Como se puede ver la interpolación se usa con ${} dentro de un texto con comillas ivertidas. Lo que nos permite escribir cualquier instrucción de JavaScript válida que será ejecutada y utilizada como valor para el texto. Sin interpolación podemos concatenar el texto con el operador de suma (+).

2.5.1. length

Para saber el largo de una cadena de caracteres podemos usar la propiedad length [101].

// 5
"Luigi".length;

2.6. Funciones

Una función es una forma de escribir una serie de operaciones que puede ser invocada pasando parámetros.

La siguiente función incrementa el valor de un número. Es decir si le entregamos como parámetro 1, retornará 2 como resultado.

function incrementar(numero) {
    return numero + 1;
}

// Invocación con parámetro 1
incrementar(1);

También podríamos escribirla de forma más compacta utilizando const.

const incrementar = (numero) => {
    return numero + 1;
}

// Invocación con parámetro 1
incrementar(1);

Cuando usamos la sintaxis () ⇒ {} se conoce como función anónima o lambda. Las funciones también podemos para pasarlas como parámetro a otras funciones (si no utilizamos los paréntesis). Ejemplo utilizamos incrementar para pasarla como parámetro e incrementar() para invocarla.

2.7. Condicionales

Cuando deseamos si seguir un camino o no, nos enfrentamos a una condicional [102] . Nos permiten separar la ejecución de nuestro programa según una condición. Ésta condición debe ser verdadera (true) o falsa (false).

if (condicion) {
  // código a ejecutar si la condición es verdadera
} else {
  // ejecuta este otro código si la condición es falsa
}

Para elaborar nuestra condición podemos usar los siguientes operadores:

  • === y !==: Prueba si un valor es exactamente igual a otro, o sino es indentico a otro valor.

  • < >: Prueba si un valor es menor o mayor que otro.

  • y >=: Prueba si un valor es menor e igual o mayor e igual que otro.

  • && (operador AND): Permite encadenar dos o más expresiones para que todas ellas se tengan que evaluar individualmente true para que expresión entera retorne true.

  • || (operador OR): Permite encadenar dos o más expresiones para que una o más de ellas se tengan que evaluar individualmente true para que expresión entera retorne true.

Ejemplo de Condicional
const vidas = 10;

if (vidas <= 0) {
  console.log("Game Over");
}

Ahora una condicional un poco más elaborado

Ejemplo de Condicional Más elaborado
if (personaje === "Mario" && vuelta > 2) {
    console.log("Ganador");
} else {
    console.log("Siguiente Vuelta");
}

2.8. Arreglos

Un arreglo permite almacenar una cadena de valores enumerables, es decir, que pueden ser contados.

const personajes = ["Mario", "Luigi", "Peach"];
// 3
personajes.length;

Además tiene una serie de funciones que permiten facilitar el trabajar con ellos.

2.8.1. Función map

Podemos generar una nuevo arreglo a partir de uno anterior con la función map [103].

// Mario N64, Luigi N64, Peach N64
const personajes = ["Mario", "Luigi", "Peach"].map((nombre) => {
    return nombre + " N64";
});

2.8.2. Función sort

También podemos ordenar la lista de elementos dentro de un arreglo con la función sort [104].

// ["Luigi", "Mario", "Peach"]
const personajes = ["Mario", "Luigi", "Peach"].sort((personaje_anterior, personaje_siguiente) => {
    	return personaje_anterior > personaje_siguiente;
});

2.8.3. Función filter

Se puede filtrar usando la función filter [105]. Elementos según un criterio específico y obtener un nuevo arreglo solamente con los elementos que cumplan el filtro.

// ["Toad"]
const personajes = ["Mario", "Luigi", "Peach", "Toad"].filter((personaje) => {
    return personaje.length < 5;
});

2.8.4. Función reduce

La función reduce [106] permite reducir el arreglo a solamente un valor final. Útil para procesar los elementos y retornar un resultado según operaciones específicas.

// "MarioLuigiPeachToad"
const personajes = ["Mario", "Luigi", "Peach", "Toad"].reduce((acumulador, personaje) => {
    return acumulador + personaje;
});

2.8.5. Función join

La función join [107] es similar a la función reduce solo que une a todos los elementos sin ninguna otra transformación. Puede ser pasado un parámetro para especificar el caracter de separación. Predeterminado es la coma ,.

// "Mario,Luigi,Peach,Toad"
["Mario", "Luigi", "Peach", "Toad"].join()

// "Mario-Luigi-Peach-Toad"
["Mario", "Luigi", "Peach", "Toad"].join("-")

// "MarioLuigiPeachToad"
"Mario", "Luigi", "Peach", "Toad"].join("")

2.8.6. Composición

Podemos encadenar distintas funciones y utilizar el valor del resultado anterior. Creando una cascada o pipeline (tubería) donde nuestro parámetro (acumulador) se transformará hasta llegar a un valor final.

Una buena estrategia es separar nuestras funciones en tres categorías:

  • Creadores: Funciones que crean un dato, le dan su valor inicial.

  • Reductoras o Procesadoras: Funciones que procesan el dato y lo reducen para ser utilizado por la siguiente operación.

  • Conversoras o Transformadoras: Funciones que toman el dato al final de todo el pipeline y lo transforman a un formato final que puede ser usado en otro pipeline o mostrado al usuario final.

Esta estrategia se conoce como CRC (Create (Crear), Reduce (Reducir), Convert (Convertir)).

// ["Mario N64"]
const personajes = ["Mario", "Luigi", "Peach"].map((nombre) => {
    return nombre + " N64";
}).filter((nombre) => {
    return nombre.startsWith("M");
});

2.9. Objetos

Un objeto nos permite almacenar datos en un único lugar. Estos pueden ser números, arreglos, strings, booleanos, funciones u otros objetos.

const mario = {
    nombre: "Mario",
    apellido: "Mario",
    direccion: {
        calle: "Honguito",
        numero: 1981,
        ciudad: "Mushroom Kingdom"
    }
};

// Mushroom Kingdom
console.log(mario.direccion.ciudad);

2.9.1. JSON

JSON [108] es una forma de convertir a texto los objetos y viceversa, siguiendo una estructura que puede ser enviada o recibida por cualquier otro sistema (implementado en cualquier otro lenguaje de programación). Es una buena herramienta para obtener y enviar datos.

const mario = {
    nombre: "Mario",
    apellido: "Mario"
};
// {"nombre":"Mario","apellido":"Mario"}
JSON.stringify(mario);

// Luigi
const luigi = JSON.parse(`{"nombre":"Luigi","apellido":"Mario"}`);
console.log(luigi.nombre);

2.10. Spread Operator

El spread operator (operador de propagación) [109] nos permite acceder elementos dentro de un arreglo o un objeto. Se utiliza con tres puntos (…​). Lo que hace es separar los elementos uno a uno y permite asignar los valores a variables separadas.

const [mario, ...xs] = ["Mario", "Luigi", "Peach", "Toad"];

// Mario
console.log(mario);

// ["Luigi", "Peach", "Toad"]
console.log(xs);

También nos permite combinar distintos elementos en uno solo

const hermanos = ["Mario", "Luigi"];
const realeza = ["Peach", "Toad"];
const todos = [...hermanos, ...realeza];

// ["Mario", "Luigi", "Peach", "Toad"]
console.log(todos);
const mario_nombre = {
    nombre: "Mario",
    apellido: "Mario",
};

const mario_direccion = {
    direccion: {
        calle: "Honguito",
        numero: 1981,
        ciudad: "Mushroom Kingdom"
    }
};

const mario = {...mario_nombre, ...mario_direccion};

// Mushroom Kingdom
console.log(mario.direccion.ciudad);

Finalmente permite pasar parámetros a funciones

function sumar_vidas(jugador, cantidad) {
    return jugador.vidas + cantidad;
}

const juego = [{nombre: "Mario", vidas: 1}, 2];

// 3
console.log(sumar_vidas(...juego));

Capítulo 3. DOM

En los capítulos anteriores vimos una pincelada de HTML, CSS y JavaScript. Pero falta profundizar un poco en lo que es el DOM (Modelo de Objetos del Documento o en inglés Document Object Model) [110] y CSSOM (Modelo de Objetos de CSS o en inglés CSS Object Model) [111].

Ambos son árboles generados por el navegador y que permiten seleccionar los nodos (hojas) y realizar operaciones en ellas. El contenido de la página es almacenado en DOM y el acceso y la manipulación se hace vía JavaScript, aunque cualquier otro lenguaje de programación podría ser capaz de crear un lector y manipulador del DOM.

El siguiente código HTML

<!DOCTYPE html>
<html>
    <head>
        <title>My title</title>
    </head>
    <body>
        <h1>My header</h1>
        <a href="#">My link</a>
    </body>
</html>

Generará un árbol DOM como la siguiente imagen:

Árbol de DOM [112]

Árbol del DOM

3.1. Critical Rendering Path

Para generar estos árboles el navegador realiza un proceso llamado Critical Rendering Path (Ruta de Renderizado Crítica) [113] el cual consiste en los siguientes pasos:

  1. El navegador recibe una solicitud por parte del usuario y envía una petición HTTP al servidor.

  2. El servidor responde con un documento HTML.

  3. El navegador comienza a procesar el documento, generando un árbol DOM inicial.

  4. El navegador solicita todos los recursos externos encontrados como: hojas de estilo, scripts o imágenes. En algunas peticiones el navegador esperará hasta que finalicen, bloqueando las otras peticiones.

  5. El navegador seguirá procesando el árbol DOM hasta terminar. Luego continuará generando el CSSOM.

  6. Al tener listos el DOM y CSSOM comenzará el proceso de generar el árbol final para renderizar o "pintar" la página web al usuario. Acá se computan los estilos para todo el contenido visible.

  7. Luego se define la ubicación y tamaño de todos los elementos del árbol de renderizado.

  8. Finalmente al tener el árbol de renderizado con los estilos, tamaño y ubicación de cada elemento, es renderizado y "pintado" los pixeles en la pantalla visible al usuario.

El árbol de renderizado tiene solamente los nodos que serán mostrados. Por ejemplo si se aplica display:none el elemento o sus hijos no estarán en el árbol y no serán mostrados.

Mientras más nodos tenga un DOM más lento será su renderizado. Por lo que procura no realizar operaciones en el DOM innecesarias o aumentar mucho la cantidad de nodos.

3.2. Diferencias entre DOM y CSSOM

La principal diferencia es que el DOM es creado de forma incremental, procesando cada elemento HTML encontrado. El documento podría solicitar o realizar llamadas JavaScript que pueden alterar el DOM.

En cambio CSSOM bloqueará el renderizado hasta que este totalmente finalizado su procesamiento. Esto es por que CSS puede sobre escribir los estilos en cascada, lo que obliga a procesar todos los estilos antes de poder ser renderizado.

3.3. Objetos document y window

Los objetos document [114] y window [115] son de vital importancia para manipular el DOM con JavaScript.

  • window: Contiene la información de la "ventana" del navegador y a muchos otros objetos útiles, como document. Usado para obtener información del entorno y parámetros que darán más contexto a los scripts JavaScript.

  • document: Contiene todo los nodos DOM y es usado para realizar consultas y manipular el DOM.

3.4. Selección de Nodos DOM

Para poder seleccionar elementos, el navegador dispone de diversas funciones. Algunas funciones retornan HTMLCollection [116] y otras NodeList [117]. Por lo que es recomendable estandarizarlas a un arreglo para poder usar los métodos filter, map, reduce entre otros. Estas funciones pueden ser usadas en el objeto document o cualquier otro elemento válido.

El siguiente código de ejemplo utiliza el operador de propagación (…​).

const nodos = document.querySelectorAll("<selector>");
const lista = [...nodos];

3.4.1. getElementById()

La función getElementById() [118] Permite obtener un elemento [119] buscando por su id.

<p id="mario">Super Mario Brothers</p>
Ejemplo de obtener un elemento por su id
const mario = document.getElementById("mario");

3.4.2. getElementsByTagName()

La función getElementsByTagName() [120] Devuelve una lista de elementos, buscando por su tipo o "tag". Devuelve un HTMLCollection.

<table id="tops">
    <thead>
        <tr>
            <th>Rango</th>
            <th>Nombre</th>
            <th>Pista</th>
            <th>Tiempo</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>Toad</td>
            <td>Luigi Raceway</td>
            <td>1' 51'' 10</td>
        </tr>
    </tbody>
</table>
Ejemplo de Obtención de todas las filas de la tabla
const tabla = document.getElementById("tops");
const filas = tabla.getElementsByTagName("td");

3.4.3. getElementsByClassName()

La función getElementsByClassName() [121] Permite obtener una lista de elementos por su clase. Devuelve un HTMLCollection.

<th class="center">Rango</th>
<th class="left">Nombre</th>
<th class="center">Pista</th>
<th class="right">Tiempo</th>
Ejemplo de obtener solamente los elementos con clase "center"
const center_list = document.getElementsByClassName("center");

3.4.4. querySelector()

La función querySelector() [122] Permite obtener un elemento buscando por su Selector CSS [123].

<p id="mario">Super Mario Brothers</p>
Ejemplo de obtener el elemento con id = mario
const mario = document.querySelector("#mario");

3.4.5. querySelectorAll()

La función querySelectorAll() [124] Obtiene una lista de elementos utilizando Selectores CSS. Devuelve un NodeList.

<div class="rojo">
    Mario
</p>
<div class="verde">
    Luigi
</div>
Ejemplo de obtener los elementos div con clase rojo o verde
const personajes = document.querySelectorAll("div.rojo, div.verde");

3.5. Crear Nodos

Para poder crear nodos se puede usar createElement [125] (para elementos HTML) y createTextNode [126] (para elementos de texto).

Ejemplo de createElement
const bowser = document.createElement("h1");
Ejemplo de createTextNode
const juego = document.createTextNode("Super Mario 64");

La función setAttribute [127] nos permite añadir distintos atributos al nodo creado.

const wario = document.createElement("div");
wario.setAttribute("id", "wario");
wario.append("Wario");

Solamente creamos el elemento, pero se debe añadir al DOM para ser procesado por el navegador.

3.6. Añadir Nodos al DOM

Existen diversas formas de añadir un elemento al DOM. Puede ser directamente en el objeto document o también en cualquier elemento, debido a que cada elemento guarda un árbol de sus hijos.

La forma más común es utilizar append [128]. La cual permite añadir uno o varios nodos o textos.

const juego = document.createElement("div");
juego.append("Wave Race 64");

// Wave Race 64
console.log(juego.textContent);

Otras funciones similares son appendChild [129], insertBefore [130] y insertAdjacentElement [131].

3.6.1. innerHTML

Una forma simple de añadir hijos es usando el texto HTML directamente.

También sirve para leer el HTML de los hijos del elemento como texto. ejemplo: <div id="wario">Wario</div>

const juego = document.createElement("div");
juego.innerHTML = "<span>Mario Kart 64</span>";

// 1
console.log(juego.children.length);

Como se puede ver el elemento div ahora tiene un nuevo hijo <span>.

3.6.2. outerHTML

Es similar a innerHTML, con la diferencia de que considera no solamente a los hijos del elemento, si no también al elemento mismo. También sirve para leer el HTML del elemento como texto. ejemplo: <div id="personajes"><div id="wario">Wario</div></div>.

Es una buena práctica crear los nodos con la función createElement más que recurrir a innerHTML y outerHTML.

const juegos = document.createElement("div");

const mk64 = document.createElement("span");

mk64.append("Mario Kart 64");

juegos.append(mk64);

console.log(juegos.outerHTML);

innerHTML y outerHTML convierten el texto a elementos HTML, por lo que la procedencia del texto debe ser sanitizada para evitar ataques XSS [132] (permiten un ataque de ejecución de código peligroso) y otros problemas de seguridad. Usarlos con cautela.

3.7. Eliminar Nodos

Existen tres formas para eliminar nodos dentro del DOM, remove, removeChild y replaceChild.

3.7.1. remove

La función remove [133] nos permite eliminar un elemento específico del árbol DOM.

<div id="mario">Mario</div>
<div id="luigi">Luigi</div>
<div id="peach">Peach</div>
Ejemplo de remove
const peach = document.getElementById("peach");
peach.remove();

3.7.2. removeChild

La función removeChild [134] nos permite eliminar un hijos desde un padre.

<div id="personajes">
    <div id="mario">Mario</div>
    <div id="luigi">Luigi</div>
    <div id="peach">Peach</div>
</div>
Ejemplo de removeChild
const personajes = document.getElementById("personajes");
const luigi = personajes.getElementById("luigi");
personajes.removeChild(luigi);

3.7.3. replaceChild

La función replaceChild [135] nos permite reemplazar un nodo hijo por otro.

<div id="personajes">
    <div id="mario">Mario</div>
    <div id="luigi">Luigi</div>
    <div id="peach">Peach</div>
</div>
Ejemplo de replaceChild
const personajes = document.getElementById("personajes");
const luigi = personajes.getElementById("luigi");

const wario = document.createElement("div");
wario.setAttribute("id", "wario");
wario.append("Wario");

// Reemplazo de luigi por wario
personajes.replaceChild(wario, luigi);

3.8. Rendimiento

Cada vez que modificamos el DOM directamente se paga un costo de rendimiento. Mientras menos operaciones se realicen (como escribir y eliminar nodos), más rápido será el sitio web.

El siguiente código es lento e ineficiente, por que crea cien nodos llamando a la función append cien veces. (Usamos Array.from [136] para crear nuestra lista de 100 elementos).

Ejemplo de modificar el DOM 100 veces
Array.from({length: 100}, (_, indice) => {
    const node = document.createTextNode(indice);
    document.body.append(node);
});

Se puede implementar de una mejor forma, solamente llamando a la función append una vez con cien elementos.

Ejemplo de modificar el DOM una vez con 100 elementos
const nodes = Array.from({length: 100}, (_, indice) => {
    return document.createTextNode(indice);
});

document.body.append(...nodes);

3.9. Eventos

El navegador llamará a distintos eventos que suceden dependiendo de las interacciones que realiza el usuario con el sitio web y su ciclo de vida. Por ejemplo cuando la página se ha cargado completamente, se hace click en un botón, o se envía un formulario, entre otros eventos.

Utilizando JavaScript podemos asociar funciones que serán invocadas al momento de que el navegador detecte un evento.

3.9.1. Atributos de HTML

Un elemento HTML puede tener un atributo que este asociado a una función de JavaScript, lo que se conoce como atributos de gestión de eventos [137].

Debido a que se mezcla HTML y JavaScript usar estos atributos no es recomendable. Puede generar sistemas difíciles de mantener. En algunos sistemas incluso pueden ser bloqueados por seguridad.

<button onclick="console.log('Its a me, Mario!')">
    Saluda Mario
</button>

3.9.2. Propiedades de Evento en Elemento

Un elemento también permite asociar eventos a una propiedad [138]. Esta es una forma menos flexible de añadir eventos, pero es la que tiene mayor compatibilidad con navegadores viejos.

<button id="mario">
    Saluda Mario
</button>

<script type="text/JavaScript">
    const button = document.querySelector("#mario");
    button.onclick = () => {
        console.log("It's a me, Mario!");
    };
</script>

3.9.3. Función addEventListener()

La función addEventListener() [139] nos permite escuchar un evento. Es recomendable usar addEventListener() por sobre las propiedades de evento debido a que podemos crear varios manejadores distintos para el mismo evento.

<button id="mario">
    Saluda Mario
</button>

<script type="text/JavaScript">
    const button = document.querySelector("#mario");
    button.addEventListener("click", (elemento) => {
        console.log(elemento);
        console.log("It's a me, Mario!");
    });
</script>

Adicionalmente si se desea eliminar un manejador de eventos se puede usar la función removeEventListener() [140].

3.9.4. Eventos Más Comunes

Entre los eventos más comunes podemos encontrar:

  • Evento window.load [141]: La página y sus recursos se cargó completamente.

  • Evento DomContentLoaded [142]: El DOM se ha cargado, pero todavía no sus recursos externos.

  • Evento click [143]: Se ha hecho click en un elemento.

  • Evento submit [144]: Permite detectar que se ha enviado un formulario.

Ejemplo de evento load
window.addEventListener("load", (event) => {
  console.log("La página se cargó completamente");
});

Capítulo 4. Formularios

Los formularios son parte de HTML y están en un capítulo separado debido a su relevancia y a la necesidad de aprender un poco sobre JavaScript y DOM antes de ver este tema. Ahora después de ver los capítulos anteriores podemos profundizar un poco más sobre los formularios.

4.1. ¿Para qué sirven?

Los formularios son muy útiles cuando se necesita obtener información por parte del usuario. Si se es diestro se pueden crear algunos juegos solamente con formularios y JavaScript (Como del tipo elige tu propia aventura o cuestionarios entretenidos para averiguar que personaje de Super Mario eres).

4.2. El elemento <form>

El elemento <form> [145] es la base para cualquier formulario y nos permite organizar todos nuestros elementos en un grupo.

Todos los elementos que estén dentro de <form> serán enviados cuando se gatille el evento submit del formulario.

Ejemplo de formulario
<form>
    <!-- elementos de formulario -->
</form>

4.2.1. Atributo name

El atributo name [146] nos permite identificar nuestro formulario dentro de los formularios disponibles en document.forms. De esta forma podemos tener múltiples formularios en una misma página.

Ejemplo de formulario con nombre
<form name="personajes">
    <!-- elementos de formulario -->
</form>
const personajes = document.forms["personajes"];

4.2.2. Atributo action

El atributo action [147] es opcional. Es la acción que ejecutará el formulario al ser enviado. Normalmente se llama a una URI [148] que permite llamar a otro sistema (backend) escrito en algún lenguaje de programación como PHP, Elixir, Ruby, Java, Golang o incluso C (cgi-bin). Si no está incluido se tomará la URL del documento como base.

Ejemplo de formulario con action
<form name="personajes" action="enviar.php">
    <!-- elementos de formulario -->
</form>

4.2.3. Atributo method

El atributo method [149] nos permite seleccionar el método con el cual llamaremos al action. Existen diversos métodos pero los formularios solamente soportan dos: GET [150] y POST [151]. Si no se incluye se llamará por el método GET.

Ejemplo de formulario con method
<form name="personajes" action="enviar.php" method="post">
    <!-- elementos de formulario -->
</form>
GET

Los datos enviados por el formulario se adjuntarán a la url como parámetros. Ejemplo enviar.php?nombre=Toad&color=red.

POST

Los datos enviados por el formulario se enviarán en el cuerpo de la llamada al servidor.

Otros Métodos

Existen otros métodos que son usados para realizar llamadas HTTP, aunque no se puedan usar directamente en el formulario, si se desea pueden ser incluidos como parámetro dentro del formulario y dejar que el servidor determine que hacer.

  • GET: Obtiene la información de un recurso.

  • POST: Crea un nuevo recurso.

  • PUT: Reemplaza completamente un recurso existente.

  • PATCH: Reemplaza una parte de un recurso existente.

  • DELETE: Elimina un recurso existente.

Existen algunos otros más que pueden ser estudiados en el RFC 9110 [152].

Detallar más es un tema sumamente bueno y necesario, pero escapa un poco del alcance de este libro. Recomendamos aprender como crear APIs REST [153] con alguna tecnología (como Elixir).

4.3. El elemento <fieldset>

El elemento <fieldset> [154] permite agrupar distintos elementos, por ejemplo que tengan un contexto en común.

4.3.1. El elemento <legend>

El elemento <legend> [155] permite dar un título al <fieldset>.

 <fieldset>
  <legend>Edad</legend>
  <label>
    <input type="checkbox" tabindex="20" name="edad" value="20-39">
    20-39
  </label>
  <label>
  <input type="checkbox" tabindex="21" name="edad" value="40-59">
    40-59
  </label>
</fieldset>

4.4. El elemento <label>

El elemento <label> [156] permite dar una etiqueta a un control específico. Puede contener al elemento o puuede referenciarlo con el atributo for.

Formato Anidado
<label>
<input type="checkbox" tabindex="21" name="edad" value="40-59">
    40-59
</label>
Formato no Anidado (Referencia)
<input type="checkbox" tabindex="21" name="edad" value="40-59">
<label for="edad">
    40-59
</label>

4.5. El elemento <input>

El elemento <input> [157] permite obtener información por parte del usuario, tiene diversos tipos de entrada pero solamente nombraremos los más comunes.

  • hidden: El elemento no será mostrado, pero es usado para enviar información oculta al servidor. Por ejemplo un código de protección CSRF [158].

  • text: Es un elemento de texto, solamente una línea.

  • password: Es un elemento de texto, pero cuyos caracteres son ocultados al escribirlos.

  • email: Es un elemento de texto, pero se validará que el formato sea un email válido.

4.5.1. Atributos Especiales

Los elementos soportan algunos atributos especiales, acá una pequeña lista.

  • name: El nombre del elemento para ser almacenado en el formulario.

  • maxlength: Limita la cantidad máxima de caracteres.

  • minlength: Limita la cantidad mínima de caracteres.

  • placeholder: Muestra un texto de ejemplo que será borrado al ingresar un texto por parte del usuario.

  • required: El formulario no será enviado a menos que el elemento tenga un valor.

  • autofocus: El elemento será seleccionado automáticamente por el navegador.

  • tabindex: El orden del elemento al pulsar la tecla TAB.

  • checked: El valor será seleccionado automáticamente (para checkbox y radio).

  • value: El valor inicial que tendrá el elemento. Normalmente usado para rellenar automáticamente al cargar un formulario.

<input type="text" name="nombre" placeholder="Toadstool Peach" maxlength="40">

4.5.2. El tipo checkbox

Una selección múltiple. Los elementos deben compartir el mismo atributo name.

<label>
  <input type="checkbox" name="consola_favorita" checked value="Nintendo 64"> Nintendo 64
</label>
<label>
  <input type="checkbox" name="consola_favorita" value="Super Nintendo">
  Super Nintendo
</label>
<label>
<input type="checkbox" name="consola_favorita" value="Virtual Boy">
  Virtual Boy
</label>
<label>
<input type="checkbox" name="consola_favorita" value="Game Boy">
  Game Boy
</label>
<label>
<input type="checkbox" name="consola_favorita" value="Nintendo">
  Nintendo
</label>
Ejemplo de checkbox

Checkbox Input

4.5.3. El tipo radio

Una selección simple. Los elementos deben compartir el mismo atributo name.

<label>
  <input type="radio" name="consola_favorita" checked value="Nintendo 64"> Nintendo 64
</label>
<label>
  <input type="radio" name="consola_favorita" value="Super Nintendo">
  Super Nintendo
</label>
<label>
<input type="radio" name="consola_favorita" value="Virtual Boy">
  Virtual Boy
</label>
<label>
<input type="radio" name="consola_favorita" value="Game Boy">
  Game Boy
</label>
<label>
<input type="radio" name="consola_favorita" value="Nintendo">
  Nintendo
</label>
Ejemplo de radio

Radio Input

4.5.4. El elemento <output>

El elemento <output> [159] es un complemento de <input>. Normalmente usado para mostrar el resultado de alguna operación luego de enviar el formulario.

<output name="resultado" for="a b">60</output>

4.6. El elemento <select>

Otra forma de mostrar una lista de elementos es usando el elemento <select> [160].

<select name="consola_favorita">
  <label>
    <option checked value="Nintendo 64">
    Nintendo 64
  </label>
  <label>
    <option value="Super Nintendo">
    Super Nintendo
  </label>
  <label>
  <option value="Virtual Boy">
    Virtual Boy
  </label>
  <label>
  <option value="Game Boy">
    Game Boy
  </label>
  <label>
  <option value="Nintendo">
    Nintendo
  </label>
</select>
Ejemplo de select

Select Input

Si se le da el atributo size permite mostrar la lista con un número de elementos específico.

<select name="consola_favorita" size="2">

Además se puede usar el atributo multiple para permitir selección múltiple.

<select name="consola_favorita" size="2" multiple>

4.6.1. El elemento <optgroup>

Si se desea agrupar distintas opciones por una categoría específica se puede usar el elemento <optgroup> [161].

<select name="consola_favorita">
  <optgroup label="64 bits">
    <label>
      <option checked value="Nintendo 64">
      Nintendo 64
    </label>
  </optgroup>
  <optgroup label="32 bits">
    <label>
      <option value="Virtual Boy">
      Virtual Boy
    </label>
  </optgroup>
  <optgroup label="16 bits">
    <label>
      <option value="Super Nintendo">
      Super Nintendo
    </label>
  </optgroup>
  <optgroup label="8 bits">
    <label>
      <option value="Game Boy">
      Game Boy
    </label>
    <label>
      <option value="Nintendo">
      Nintendo
    </label>
  </optgroup>
</select>
Ejemplo de optgroup

Optgroup

4.7. El elemento <textarea>

Para ingresar un texto más largo, se puede usar <textarea> [162]. Mantiene los mismos atributos que un <input>, adicionalmente tiene rows y cols que dan las filas y columnas soportadas.

<textarea name="historia" rows="10" cols="50">
Escribe tu historia acá
</textarea>

4.8. El elemento <button>

El elemento <button> [163] es un botón que puede ser usado para enviar, reiniciar el formulario o simplemente gatillar eventos "click" en JavaScript.

<button type="submit">Enviar Formulario</button>
<button type="reset">Reiniciar Formulario</button>
<button>Botón Genérico</button>

4.9. Validar Formularios

Validar un formulario es sumamente importante debido a que permite asegurar que los datos enviados son correctos. Pero siempre hay que recordar que nunca se debe confiar en los datos enviados por el usuario, ya que aún realizando validaciones siempre las puede modificar. Por lo que esto permitirá tener un primer filtro de los datos y luego el servidor debe validar adecuadamente.

4.9.1. Validación por atributo onsubmit

La primera forma de validar es utilizando el atributo onsubmit del formulario.

<form onsubmit="return validar()">
</form>
function validar() {
  return false;
}

Si el evento onsubmit devuelve el valor true, el formulario se enviará normalmente. Si el evento onsubmit devuelve false, el formulario no se envíará.

No se recomienda utilizar el atributo onsubmit debido a que se mezcla HTML y JS. Es mejor usar solamente JavaScript para validar el formulario.

4.9.2. Validación con JavaScript

Ésta es una validación usando un manejador de eventos de click y el método preventDefault() [164] que permite evitar que se envíe el formulario si no pasa las validaciones.

<form name="contacto">
  <input id="nombre" type="text" name="nombre">
  <input id="email" type="email" name="email">
  <button id="btn-enviar" type="submit">Enviar</button>
</form>
const enviar = document.getElementById("btn-enviar");

enviar.addEventListener("click", (event) => {

  const nombre = document.forms["contacto"]["nombre"].value;
  const email = document.forms["contacto"]["email"].value;

  if(nombre === "") {
    console.log("Nombre vacío");
    document.getElementById("nombre").focus();
    event.preventDefault();
    return false;
  }

  if(email === "") {
    console.log("Email vacío");
    document.getElementById("email").focus();
    event.preventDefault();
    return false;
  }

  // Validación correcta
  // Continuar con enviar el formulario
  return true;
});

Capítulo 5. Proyecto

Ahora haremos un pequeño proyecto para poner en práctica los conocimientos y habilidades adquiridas en este librito.

5.1. Simulador de Mario Kart 64

Este es un pequeño juego utilizando formularios y un poquitín de JavaScript. Consiste en seleccionar un personaje y se mostrará los resultados de cada vuelta. Si tu personaje es el ganador mostrará su imagen y la frase ¡GANASTE!.

Ejemplo de Ejecución

Simulador de Mario Kart 64

5.1.1. Requerimientos Funcionales

El juego consiste en un formulario que muestra la opción de seleccionar un personaje a la vez.

  • Mario

  • Luigi

  • Peach

  • Toad

  • Yoshi

  • Donkey Kong

  • Wario

  • Bowser

Debe tener un botón con el texto "Comenzar Carrera". Al momento de precionarlo se mostrará tres listas (vueltas) numeradas con los nombres ordenados aleatoriamente.

Si en la tercera lista el nombre del primer elemento es igual al personaje seleccionado. Mostrar la imagen del personaje y el texto "¡Ganaste <nombre>!".

5.1.2. Requerimientos No Funcionales

El proyecto debe estar limpio, ordenado, bonito y ambientado en la temática de Mario Kart 64.

Puedes obtener imágenes del juego en Spriters Resource [165].

5.1.3. Requerimiento Opcional

Agregar un contador de las veces que ha ganado tu personaje.

5.1.4. Esqueleto Base

Usa el siguiente esqueleto HTML como base para obtener un resultado similar a la imagen anterior. Puedes tener libertad de diseño usando todos las herramientas disponibles en HTML, CSS y JavaScript aprendidas en este libro.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Simulador de Mario Kart 64</title>

        <style type="text/css">
        </style>

        <script type="text/JavaScript">
            function iniciar() {
                const personaje = document.forms["personaje"]["nombre"].value;
                return false;
            }
        </script>
    </head>
    <body>
        <h1>Simulador de Mario Kart 64</h1>
        <h2>Escoge a un personaje</h2>

        <form name="personaje" onsubmit="return iniciar();">
        </form>
    </body>
</html>

5.1.5. Solución

La siguiente es una posible solución, pero no es la única forma de obtener el resultado. Si necesitas ayuda puedes revisarla, pero la recomendación es verla solo después de solucionar el proyecto por tu cuenta.

Se han usado eventos (onsubmit) en atributos de HTML. ¿Cómo se podría mejorar?.

Se ha usado innerHTML. ¿Cómo se podría mejorar?.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Simulador de Mario Kart 64</title>

    <style type="text/css">
        body {
            background-image: url("bg.png");
            background-repeat: repeat;
            background-size: 600px auto;
        }
        .left {
            float: left;
        }
        .clear {
            clear: both;
        }
    </style>

    <script type="text/JavaScript">

        function personajes() {
            return [
                "Mario", "Luigi", "Peach",
                "Toad", "Yoshi", "DK",
                "Wario", "Bowser"
            ];
        }

        function personajes_aleatorios() {
            return personajes().sort(() => Math.random() - 0.5);
        }

        function es_ganador(personaje, resultado) {
            return personaje == resultado[0];
        }

        function mostrar_ganador(personaje, resultado) {
            if (es_ganador(personaje, resultado)) {
                return `
                    <h3 class="clear">
                        ¡Ganaste ${personaje}!
                    </h3>
                    <img src="${personaje}.png" alt="${personaje}">
                    `;
            }
            return "";
        }

        function mostrar_resultado(vuelta, resultados) {
            return `
                <div class="left">
                    <h3>Vuelta ${vuelta}</h3>
                    <ol>
                        ${resultados
                            .map(nombre => `<li>${nombre}</li>`)
                            .join("")}
                    </ol>
                </div>
            `;
        }

        function iniciar() {
            const personaje = document.forms["personaje"]["nombre"].value;
            const resultado_vuelta3 = personajes_aleatorios();

            document.getElementById("resultados").innerHTML =
                mostrar_resultado(1, personajes_aleatorios()) +
                mostrar_resultado(2, personajes_aleatorios()) +
                mostrar_resultado(3, resultado_vuelta3) +
                mostrar_ganador(personaje, resultado_vuelta3);

            return false;
        }
    </script>
</head>
<body>
    <h1>Simulador de Mario Kart 64</h1>
    <h2>Escoge a un personaje</h2>

    <form name="personaje" onsubmit="return iniciar();">
        <input type="radio" name="nombre" value="Mario" checked="true">
        <label for="Mario">Mario</label>

        <input type="radio" name="nombre" value="Luigi">
        <label for="Luigi">Luigi</label>

        <input type="radio" name="nombre" value="Peach">
        <label for="Peach">Peach</label>

        <br>

        <input type="radio" name="nombre" value="Toad">
        <label for="Toad">Toad</label>

        <input type="radio" name="nombre" value="Yoshi">
        <label for="Yoshi">Yoshi</label>

        <input type="radio" name="nombre" value="DK">
        <label for="DK">Donkey Kong</label>

        <br>

        <input type="radio" name="nombre" value="Wario">
        <label for="Wario">Wario</label>

        <input type="radio" name="nombre" value="Bowser">
        <label for="Bowser">Bowser</label>

        <br>
        <button type="submit">Comenzar Carrera</button>
    </form>

    <div id="resultados"></div>

</body>
</html>

Capítulo 6. Siguientes Pasos

Ahora que se ha mostrado los componentes básicos de HTML, CSS y JavaScript queda un mundo por descubrir. En este capítulo mencionaremos brevemente las tecnologías que puedes ahondar.

6.1. Tecnologías Legadas

Por tecnologías legadas se denomina a las herramientas que fueron muy usadas en el pasado, pero que hoy en día no son tan relevantes. jQuery, Bootstrap y Sass son tecnologías que poco a poco han perdido popularidad, sin embargo muchos sitios web y sistemas todavía los usan por lo que no estaría mal conocerlas.

6.1.1. jQuery

Es una tecnología que permite estandarizar muchas funciones entre distintos navegadores, fue muy usada en la década del 2010. Con el tiempo los navegadores fueron adoptando el estándar actual de JavaScript, añadiendo funcionalidades y facilitando algunas operaciones que antes eran muy engorrosas, haciendo el uso de jQuery menos necesario. Hoy en día no se recomienda usar jQuery para sistemas nuevos, pero se recomienda aprenderlo para cuando sea necesario mantener sistemas más viejos.

Ejemplo de jQuery
const hiddenBox = $("#banner-message");
$("#button-container button").on( "click", function(event) {
  hiddenBox.show();
});

6.1.2. Bootstrap CSS

Bootstrap, al igual que jQuery, nació por la necesidad de facilitar ciertas operaciones engorrosas de hacer. En este caso, crear sitios web ordenados y fáciles de diseñar usando CSS. Han surgido numerosos "Framework CSS" en el transcurso de los años, pero Bootstrap es uno de los más populares. No recomendamos usarlo para sitios nuevos, pero es importante aprenderlo para cuando sea necesario mantener un sistema viejo.

Ejemplo de formulario con Bootstrap CSS
<form>
  <div class="mb-3">
    <label for="exampleInputEmail1" class="form-label">Email</label>
    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
  </div>
  <div class="mb-3">
    <label for="exampleInputPassword1" class="form-label">Password</label>
    <input type="password" class="form-control" id="exampleInputPassword1">
  </div>
  <button type="submit" class="btn btn-primary">Enviar</button>
</form>

6.1.3. Preprocesadores CSS

En los inicios CSS tenía características no tan avanzadas, por ejemplo no permitía almacenar variables para los colores. Es por esto que se crearon los preprocesadores que añadían algunas características convenientes. Hoy debido a las herramientas disponibles tanto en CSS como el ecosistema, estos preprocesadores han sido desplazados. De todas formas es bueno conocerlos por si están usados en sistemas más viejos.

El siguiente es un ejemplo en SASS.

Ejemplo de código Sass
$font-stack: Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}
Ejemplo del código Sass al compilar a CSS
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

6.2. Tailwind CSS

A diferencia de Bootstrap, Tailwind promueve la granularidad de los estilos. Bootstrap proporciona una clase btn, la cual tenía estilos predeterminados, mientras que en Tailwind debemos poner un estilo para cada propiedad.

Ejemplo de botón en Tailwind
<button class="bg-blue-500 hover:bg-blue-700 text-white
            font-bold py-2 px-4 rounded">
  Button
</button>

Recomendamos usar Tailwind para nuevos sistemas debido a que permite mayor personalización de los componentes que Bootstrap.

6.3. CSS Avanzado

En este libro nos concentramos en CSS básico, hay muchas más técnicas de CSS que pueden ser útiles en sistemas más complejos. Recomendamos estudiar flexbox [166] y grid [167] entre otras herramientas disponibles.

6.4. Wordpress y CMS

Wordpress es un CMS (Sistema Manejador de Contenidos o en inglés Content Management System) que es muy popular y usado actualmente, se pueden hacer muchos sitios web con ésta tecnología. Además de conocer HTML, CSS y JavaScript te recomendamos aprender un poco de PHP.

Los CMS son buenos para muchas cosas, pero cuando se crean sistemas más complejos se requiere ir al siguiente nivel que son los frameworks para aplicaciones web.

6.5. Frameworks para Aplicaciones Web

Hoy existen diversos frameworks creados para organizar la creación de aplicaciones web. Muchas veces al utilizar una mezcla de jQuery y PHP se podían tener sistemas muy difíciles de modificar y mejorar, por lo que dio el origen a numerosas soluciones. Entre los primeros podemos mencionar a Knockout.js [168] y Ember.js [169]. El tiempo y avance tecnológico permitió que otras soluciones nacieran como React.js [170], Vue.js [171], Svelte.js [172] y Solid.js [173], entre otros. Entrar a detallar las características y propuestas de cada framework escapa del alcance del libro, pero podemos hacer una pequeña lista de recomendaciones:

Elegir un framework de frontend no es obligación para todos los proyectos, puede que simplemente usando HTML, CSS y JavaScript tradicional sea suficiente para cumplir los objetivos. Todo depende del contexto de cada proyecto y las habilidades de quienes participan en este.

6.6. Palabras Finales

Saber elegir entre todas estas alternativas no es algo sencillo, pero te recomendamos seleccionar una y dedicarle un tiempo razonable hasta dominarla muy bien y luego cambiar a otra si deseas. Recordar que si bien JavaScript permite abordar múltiples casos de uso, no es la única tecnología disponible ni la más adecuada para todos los casos. Te invitamos a investigar por tu cuenta y probar nuevas alternativas y soluciones. Te recomendamos Elixir [174] si deseas aprender algo novedoso y con muchos proyectos entretenidos.

Anexo A: Hospedajes y Dominios

¿Donde alojar tu sitio web?. Hay distintas opciones tanto gratuitas, de pago y de elaboración propia.

Lo ideal es tener un dominio y servidor propio. Puedes empezar con el servicio de Neocities que te dará un dominio gratuito y espacio de hasta 1 GB para almacenar páginas, CSS, imagenes y JavaScript.

A.1. Proveedores de Dominio

Un dominio nos permite acceder facilmente a un sitio web (ejemplo.com) y pueden ser adquiridos en proveedores autorizados. Acá se da una lista pequeña de distintos proveedores actuales.

A.2. Proveedores de Hospedaje

Dependiendo de tus necesidades puedes tener algo propio en una computadora vieja, un celular no usado, Raspberry PI [175], o adquirir un servidor. La siguiente es una lista no ordenada de distintas opciones.

Nuestra recomendación es partir con un servidor propio o gratuito y luego invertir en uno de pago.

A.3. Servidores

Si deseas hospedar en tu propio computador puedes usar un software llamado servidor y existen muchos disponibles. Todos pueden cumplir la función de permitir a otros ver tu página web a través de la red. Elegir un servidor dependerá de tus necesidades y las capacidades de cada servidor, pero si quieres servir solamente HTML, cualquiera es buena opción.

Nuestra recomendación es Caddy y Yaws.

Anexo B: Generador de Sitios Estáticos

Al momento de crear un sitio web, sobre todo si tiene mucho contenido, puede ser engorroso y tedioso armar una por una cada página web. Es por esto que existen lo que se conoce como generador de sitios estáticos.

Los generadores de sitios estáticos son programas que toman archivos de texto plano y configuraciones, transformándolas en archivos html, css y js que podemos usar para subir a un hospedaje. Lo que ahorra mucho tiempo y permite crear sitios complejos con mayor facilidad.

Se llaman estáticos por que generan archivos finales. A diferencia de un servidor dinámico que generaría los archivos al vuelo.

Lo ideal es usar uno elaborado con la tecnología que más te guste, hay diversas opciones y para todos los gustos. También si eres más diestro en los lenguajes de programación puedes intentar crear uno propio. Te recomendamos el lenguaje de programación Elixir [176].

Acá una selección pequeña:

B.1. Preprocesador C

Si usas el lenguaje C por ejemplo puedes usar su preprocesador para generar archivos [177].

El siguiente código es un ejemplo de cómo generar un archivo index.html a partir de una plantilla usando el programa cpp.

header.html
<head>
    <meta charset="utf-8">
    <title>Mi Página</title>
</head>
index.template.html
<!DOCTYPE html>
<html>
    #include "header.html"
    <body>
        <p>Hola Mundo</p>
    </body>
</html>
compilar
cpp -P index.template.html index.html

B.2. Libre Office

Otra opción es exportar desde un editor de texto como Libre Office [178] el cual nos permite generar un archivo HTML a partir de un documento docx u odt.

Archivo > Enviar > Crear documento HTML

B.3. Lenguajes de Marcado

Existen programas especiales que toman texto plano y pueden generar archivos HTML, CSS y JavaScript. Pero adicionalmente documentos docx [179], pdf [180] o epub [181].

Estos programas pueden utilizar un lenguaje de marcado [182] especial para definir las reglas y cómo se debe ver el texto.

Existen varios populares entre ellos:

  • Asciidoc [183] (Usado para escribir este libro).

  • Markdown [184].

  • Latex [185].

Una herramienta muy buena que permite convertir entre diferentes formatos es Pandoc [186].

Ejemplo de Asciidoc
= Título del Libro

Este es un libro muy bonito

== Ejemplo de Capítulo

// Comentario
https://github.com/powerman/asciidoc-cheatsheet[Enlace]

.Lista

- *Negrita*
- _Cursiva_
- `destacado`

image:foto.jpg[Foto de Mario 64]

Anexo C: Firefox Developer y User Scripts

Hay dos herramientas muy buenas para poder desarrollar y hacer experimentos con sitios web. Firefox Developer y UserScripts.

C.1. Firefox Developer

Cualquier navegador servirá para desarrollar y ver los sitios web, sin embargo recomendamos Firefox Developer Edition [187] debido a que tiene herramientas adicionales que mejorarán la calidad de vida al momento de desarrollar páginas web. En este pequeño anexo se tendrá vistazo general de las herramientas proporcionadas por Firefox Developer.

Para abrir el panel de desarrollo debemos ir a Herramientas del Navegador y buscar "Herramientas de Desarrollo Web". Como alternativa se puede hacer click derecho y seleccionar "Inspeccionar".

C.1.1. Inspector

El inspector [188] permite seleccionar elementos HTML y editarlos, junto a sus estilos CSS. Muy útil para hacer pruebas y ver los cambios de diseño en tiempo real sin necesidad de refrescar la página. Cualquier cambio no será almacenado en la página web y debe ser transportado al documento original manualmente. Además cualquier cambio se perderá si se recarga la página.

Inspector

C.1.2. Consola

La consola [189] nos permite ejecutar JavaScript e inspeccionar todas las funciones que se han implementado en la página. Muy útil para realizar pruebas de concepto y evaluar fácilmente scripts.

Consola

Para hacer pruebas se recomienda utilizar la función auto ejecutable (() ⇒ {})();. Lo que nos da la posibilidad de no polucionar el ambiente y evitar conflictos con variables o funciones definidas previamente.

Ejemplo de función auto ejecutable
(() => {
    // Código de JavaScript en función auto ejecutable.
})();

Todos los cambios se perderán al momento de recargar la página.

C.1.3. Red

La pestaña de Red (Network) [190] nos permite ver los recursos que han sido obtenidos por la página web, como imágenes, scripts e incluso cualquier solicitud HTTP realizada por el sitio web.

Además nos permite modificar los parámetros enviados y reintentar las solicitudes.

Esta pestaña es útil para averiguar el peso de nuestro sitio web, sobre todo para detectar imágenes muy pesadas que podemos comprimir y hacer más liviana la página.

Network

C.2. UserScript

Los scripts de usuario (UserScript) son archivos JavaScript cargados automáticamente por un gestor de scripts. Estos scripts pueden modificar la página web con adiciones creadas por el usuario, ya sea modificaciones estéticas o incluso agregar nuevas funcionalidades.

Se pueden encontrar diversos scripts disponibles en los siguientes sitios web:

Los gestores de UserScript recomendados son Violent Monkey y Grease Monkey:

Te animamos a crear tus propios UserScript para modificar tus sitios web favoritos y personalizarlos. Por ejemplo si tienes que hacer un prototipo web puedes modificar una web existente y agilizar el definir ideas y posibles caminos a tomar.

Ejemplo de UserScript
// ==UserScript==
// @name        New script
// @namespace   Violentmonkey Scripts
// @match       *://example.org/*
// @grant       none
// @version     1.0
// @author      -
// @description 21/6/2024, 23:08:50
// ==/UserScript==

Bibliografía

Una lista de recursos complementarios y referenciales.

Revistas

1. https://codeberg.org/ninjas/superclubnet
2. https://ninjas.cl
3. http://creativecommons.org/licenses/by-nc-sa/4.0/
4. https://opensource.org/licenses/BSD-2-Clause
5. https://developer.mozilla.org/es/docs/Web/HTML
6. https://es.wikipedia.org/wiki/World_Wide_Web
7. https://doomemacs.org
8. https://www.quora.com/Why-are-all-file-extensions-of-three-letters-only
9. https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding
10. https://www.mozilla.org/es-CL/firefox/
11. https://jsbin.com/
12. https://developer.mozilla.org/es/docs/
13. https://developer.mozilla.org/es/docs/Glossary/Doctype
14. https://developer.mozilla.org/es/docs/Web/HTML/Element/body
15. https://developer.mozilla.org/es/docs/Web/HTML/Element/style
16. https://developer.mozilla.org/es/docs/Web/CSS/color
17. https://es.wikipedia.org/wiki/RGB
18. https://es.wikipedia.org/wiki/Modelo_de_color_CMYK
19. https://developer.mozilla.org/es/docs/Learn/CSS/Building_blocks/Values_and_units
20. https://www.w3.org/TR/css-values-4/
21. https://developer.mozilla.org/es/docs/Web/CSS/Specificity
22. https://developer.mozilla.org/es/docs/Web/CSS/Specificity
23. https://developer.mozilla.org/es/docs/Glossary/ASCII
24. https://es.wikipedia.org/wiki/Anexo:Referencias_a_entidades_de_caracteres_XML_y_HTML
25. https://developer.mozilla.org/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML
26. https://developer.mozilla.org/es/docs/Glossary/UTF-8
27. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Regular_expressions/Unicode_character_class_escape
28. https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag
29. https://developer.mozilla.org/es/docs/Web/HTML/Element/p
30. https://developer.mozilla.org/es/docs/Web/HTML/Element/br
31. https://developer.mozilla.org/es/docs/Web/HTML/Element/Heading_Elements
32. https://developer.mozilla.org/es/docs/Web/HTML/Element/ol
33. https://developer.mozilla.org/es/docs/Web/HTML/Element/ul
34. https://developer.mozilla.org/es/docs/Web/HTML/Element/menu
35. https://developer.mozilla.org/es/docs/Web/HTML/Element/li
36. https://developer.mozilla.org/es/docs/Web/HTML/Element/dl
37. https://developer.mozilla.org/es/docs/Web/HTML/Element/span
38. https://developer.mozilla.org/es/docs/Web/HTML/Element/sup
39. https://developer.mozilla.org/es/docs/Web/HTML/Element/sub
40. https://developer.mozilla.org/es/docs/Web/HTML/Element/b
41. https://developer.mozilla.org/es/docs/Web/HTML/Element/strong
42. https://developer.mozilla.org/es/docs/Web/HTML/Element/em
43. https://developer.mozilla.org/es/docs/Web/HTML/Element/code
44. https://developer.mozilla.org/es/docs/Web/HTML/Element/kbd
45. https://developer.mozilla.org/es/docs/Web/HTML/Element/var
46. https://developer.mozilla.org/es/docs/Web/HTML/Element/cite
47. https://developer.mozilla.org/es/docs/Web/HTML/Element/dfn
48. https://developer.mozilla.org/es/docs/Web/HTML/Element/samp
49. https://developer.mozilla.org/es/docs/Web/HTML/Element/i
50. https://developer.mozilla.org/es/docs/Web/HTML/Element/tt
51. https://developer.mozilla.org/es/docs/Web/HTML/Element/article
52. https://developer.mozilla.org/es/docs/Web/HTML/Element/address
53. https://developer.mozilla.org/es/docs/Web/HTML/Element/pre
54. https://developer.mozilla.org/es/docs/Web/API/HTMLTableElement
55. https://developer.mozilla.org/es/docs/Web/HTML/Element/img
56. https://es.wikipedia.org/wiki/Joint_Photographic_Experts_Group
57. https://es.wikipedia.org/wiki/Portable_Network_Graphics
58. https://es.wikipedia.org/wiki/Graphics_Interchange_Format
59. https://es.wikipedia.org/wiki/WebP
60. https://es.wikipedia.org/wiki/AVIF
61. https://es.wikipedia.org/wiki/Gr%C3%A1ficos_vectoriales_escalables
62. https://es.wikipedia.org/wiki/MPEG-4_Parte_14
63. https://developer.mozilla.org/es/docs/Web/HTML/Element/video
64. https://developer.mozilla.org/es/docs/Web/HTML/Element/audio
65. https://developer.mozilla.org/es/docs/Web/CSS/float
66. https://developer.mozilla.org/es/docs/Web/CSS/background-image
67. https://developer.mozilla.org/es/docs/Web/CSS/background-repeat
68. https://developer.mozilla.org/es/docs/Web/CSS/background-size
69. https://developer.mozilla.org/es/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
70. https://developer.mozilla.org/es/docs/Web/HTML/Element/a
71. https://developer.mozilla.org/es/docs/Web/HTML/Element/button
72. https://developer.mozilla.org/es/docs/Web/CSS/:link
73. https://developer.mozilla.org/es/docs/Web/CSS/:visited
74. https://developer.mozilla.org/es/docs/Web/CSS/:hover
75. https://developer.mozilla.org/es/docs/Web/CSS/:active
76. https://developer.mozilla.org/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks
77. https://developer.mozilla.org/es/docs/Web/HTML/Element/a#target
78. https://developer.mozilla.org/es/docs/Web/HTML/Element/map
79. https://www.gimp.org/
80. https://www.getpaint.net/
81. https://developer.mozilla.org/es/docs/Web/HTML/Element/area
82. https://developer.mozilla.org/es/docs/Web/HTML/Element/frameset
83. https://developer.mozilla.org/es/docs/Web/HTML/Element/frame
84. https://developer.mozilla.org/es/docs/Web/HTML/Element/iframe
85. https://developer.mozilla.org/es/docs/Web/HTML/Element/div
86. https://developer.mozilla.org/es/docs/Web/HTML/Element/section
87. https://developer.mozilla.org/es/docs/Web/HTML/Element/main
88. https://developer.mozilla.org/es/docs/Web/HTML/Element/header
89. https://developer.mozilla.org/es/docs/Web/HTML/Element/nav
90. https://developer.mozilla.org/es/docs/Web/HTML/Element/footer
91. https://developer.mozilla.org/es/docs/Web/JavaScript
92. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Number
93. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String
94. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Boolean
95. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/undefined
96. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/null
97. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/object
98. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/function
99. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array
100. https://developer.mozilla.org/es/docs/Web/API/console/log_static
101. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String/length
102. https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/conditionals
103. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map
104. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
105. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
106. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
107. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/join
108. https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/JSON
109. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Spread_syntax
110. https://developer.mozilla.org/es/docs/Glossary/DOM
111. https://developer.mozilla.org/es/docs/Web/API/CSS_Object_Model
112. https://www.w3schools.com/js/js_htmldom.asp
113. https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path
114. https://developer.mozilla.org/es/docs/Web/API/Document
115. https://developer.mozilla.org/es/docs/Web/API/Window
116. https://developer.mozilla.org/es/docs/Web/API/HTMLCollection
117. https://developer.mozilla.org/es/docs/Web/API/NodeList
118. https://developer.mozilla.org/es/docs/Web/API/Document/getElementById
119. https://developer.mozilla.org/es/docs/Web/API/Element
120. https://developer.mozilla.org/es/docs/Web/API/Element/getElementsByTagName
121. https://developer.mozilla.org/es/docs/Web/API/Document/getElementsByClassName
122. https://developer.mozilla.org/es/docs/Web/API/Document/querySelector
123. https://developer.mozilla.org/es/docs/Learn/CSS/Building_blocks/Selectors
124. https://developer.mozilla.org/es/docs/Web/API/Document/querySelectorAll
125. https://developer.mozilla.org/es/docs/Web/API/Document/createElement
126. https://developer.mozilla.org/es/docs/Web/API/Document/createTextNode
127. https://developer.mozilla.org/es/docs/Web/API/Element/setAttribute
128. https://developer.mozilla.org/es/docs/Web/API/Element/append
129. https://developer.mozilla.org/es/docs/Web/API/Node/appendChild
130. https://developer.mozilla.org/es/docs/Web/API/Node/insertBefore
131. https://developer.mozilla.org/es/docs/Web/API/Element/insertAdjacentElement
132. https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting
133. https://developer.mozilla.org/es/docs/Web/API/Element/remove
134. https://developer.mozilla.org/es/docs/Web/API/Node/removeChild
135. https://developer.mozilla.org/es/docs/Web/API/Node/replaceChild
136. https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/from
137. https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#event_handler_attributes
138. https://developer.mozilla.org/es/docs/Web/API/EventTarget/addEventListener#older_way_to_register_event_listeners
139. https://developer.mozilla.org/es/docs/Web/API/EventTarget/addEventListener
140. https://developer.mozilla.org/es/docs/Web/API/EventTarget/removeEventListener
141. https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
142. https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event
143. https://developer.mozilla.org/es/docs/Web/API/Element/click_event
144. https://developer.mozilla.org/es/docs/Web/API/HTMLFormElement/submit_event
145. https://developer.mozilla.org/es/docs/Web/HTML/Element/form
146. https://developer.mozilla.org/es/docs/Web/HTML/Element/form#name
147. https://developer.mozilla.org/es/docs/Web/HTML/Element/form#action
148. https://developer.mozilla.org/es/docs/Glossary/URI
149. https://developer.mozilla.org/es/docs/Web/HTML/Element/form#method
150. https://www.rfc-editor.org/rfc/rfc9110.html#name-get
151. https://www.rfc-editor.org/rfc/rfc9110.html#name-post
152. https://www.rfc-editor.org/rfc/rfc9110.html#name-method-definitions
153. https://blog.logrocket.com/build-rest-api-elixir-phoenix/
154. https://developer.mozilla.org/es/docs/Web/HTML/Element/fieldset
155. https://developer.mozilla.org/es/docs/Web/HTML/Element/legend
156. https://developer.mozilla.org/es/docs/Web/HTML/Element/label
157. https://developer.mozilla.org/es/docs/Web/HTML/Element/input
158. https://developer.mozilla.org/es/docs/Glossary/CSRF
159. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output
160. https://developer.mozilla.org/es/docs/Web/HTML/Element/select
161. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup
162. https://developer.mozilla.org/es/docs/Web/HTML/Element/textarea
163. https://developer.mozilla.org/es/docs/Web/HTML/Element/button
164. https://developer.mozilla.org/es/docs/Web/API/Event/preventDefault
165. https://www.spriters-resource.com/nintendo_64/mariokart64/
166. https://developer.mozilla.org/es/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox
167. https://developer.mozilla.org/es/docs/Web/CSS/CSS_grid_layout
168. https://github.com/knockout/knockout
169. https://github.com/emberjs/ember.js
170. https://react.dev/
171. https://vuejs.org/
172. https://svelte.dev/
173. https://www.solidjs.com/
174. https://elixir-lang.org/
175. https://www.raspberrypi.org/
176. https://elixir-lang.org/
177. https://github.com/cedric-h/c-website
178. https://help.libreoffice.org/latest/es/text/swriter/guide/send2html.html
179. https://es.wikipedia.org/wiki/Office_Open_XML
180. https://es.wikipedia.org/wiki/PDF
181. https://es.wikipedia.org/wiki/EPUB
182. https://es.wikipedia.org/wiki/Lenguaje_de_marcado
183. https://es.wikipedia.org/wiki/AsciiDoc
184. https://es.wikipedia.org/wiki/Markdown
185. https://es.wikipedia.org/wiki/TeX
186. https://es.wikipedia.org/wiki/Pandoc
187. https://www.mozilla.org/es-CL/firefox/developer/
188. https://firefox-source-docs.mozilla.org/devtools-user/page_inspector/how_to/open_the_inspector/index.html
189. https://firefox-source-docs.mozilla.org/devtools-user/web_console/ui_tour/index.html
190. https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/