Linux Professional Institute Learning Logo.
Pasar al contenido principal
  • Inicio
    • Todos los recursos
    • LPI Learning Materials
    • Conviértete en colaborador
    • Publishing Partners
    • Conviértase en un Publishing Partner
    • Acerca de nosotros
    • FAQ
    • Colaboradores
    • Roadmap
    • Contáctenos
  • LPI.org
034.4 Lección 1
Tema 031: Desarrollo de Software y Tecnologías Web
031.1 Conceptos básicos de desarrollo de software
  • 031.1 Lección 1
031.2 Arquitectura de aplicaciones web
  • 031.2 Lección 1
031.3 Conceptos básicos de HTTP
  • 031.3 Lección 1
Tema 032: Marcado de documentos HTML
032.1 Anatomía del documento HTML
  • 032.1 Lección 1
032.2 HTML Semántica HTML y jerarquía de documentos
  • 032.2 Lección 1
032.3 Referencias HTML y recursos incrustados
  • 032.3 Lección 1
032.4 Formularios HTML
  • 032.4 Lección 1
Tema 033: Estilo de contenido CSS
033.1 Conceptos básicos de CSS
  • 033.1 Lección 1
033.2 Selectores CSS y aplicación de estilo
  • 033.2 Lección 1
033.3 Estilo CSS
  • 033.3 Lección 1
033.4 Modelo y diseño CSS
  • 033.4 Lección 1
Tema 034: Programación JavaScript
034.1 Ejecución y sintaxis de JavaScript
  • 034.1 Lección 1
034.2 Estructuras de datos en JavaScript
  • 034.2 Lección 1
034.3 Funciones y estructuras de control de JavaScript
  • 034.3 Lección 1
  • 034.3 Lección 2
034.4 Manipulación JavaScript del contenido y estilo del sitio web
  • 034.4 Lección 1
Tema 035: Programación NodeJS server
035.1 Conceptos básicos de Node.js
  • 035.1 Lección 1
035.2 Conceptos básicos de NodeJS Express
  • 035.2 Lección 1
  • 035.2 Lección 2
035.3 Conceptos básicos de SQL
  • 035.3 Lección 1
How to get certified
  1. Tema 034: Programación JavaScript
  2. 034.4 Manipulación JavaScript del contenido y estilo del sitio web
  3. 034.4 Lección 1

034.4 Lección 1

Certificación:

Conceptos básicos de desarrollo web

Versión:

1.0

Tema:

034 Programación JavaScript

Objetivo:

034.4 Manipulación JavaScript del contenido y estilo del sitio web

Lección:

1 de 1

Introducción

HTML, CSS y JavaScript son tres tecnologías distintas que se unen en la Web. Para crear páginas verdaderamente dinámicas e interactivas, el programador de JavaScript debe combinar componentes de HTML y CSS en tiempo de ejecución, una tarea que se facilita enormemente mediante el uso del Document Object Model (DOM).

Interactuar con el DOM

El DOM es una estructura de datos que funciona como una interfaz de programación para el documento, donde cada aspecto del documento se representa como un nodo en el DOM y cada cambio realizado en el DOM repercutirá inmediatamente en el documento. Para mostrar cómo usar DOM en JavaScript, guarde el siguiente código HTML en un archivo llamado example.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>HTML Manipulation with JavaScript</title>
</head>
<body>

<div class="content" id="content_first">
<p>The dynamic content goes here</p>
</div><!-- #content_first -->

<div class="content" id="content_second" hidden>
<p>Second section</p>
</div><!-- #content_second -->

</body>
</html>

El DOM estará disponible solo después de que se cargue el HTML, así que escriba el siguiente código JavaScript al final del cuerpo de la página (antes de la etiqueta final </body>):

<script>
let body = document.getElementsByTagName("body")[0];
console.log(body.innerHTML);
</script>

El objeto document es el elemento DOM superior, todos los demás elementos se derivan de él. El método getElementsByTagName() lista todos los elementos que descienden de document que tienen el nombre de etiqueta dado. Aunque la etiqueta body se usa solo una vez en el documento, el método getElementsByTagName() siempre devuelve una colección similar a un arreglo de elementos encontrados, de ahí el uso del índice [0] para devolver el primero (y único) elemento encontrado.

Contenido HTML

Como se muestra en el ejemplo anterior, el elemento DOM devuelto por document.getElementsByTagName("body")[0] se asignó a la variable body. La variable body se puede usar para manipular el elemento del cuerpo de la página, ya que hereda todos los métodos y atributos DOM de ese elemento. Por ejemplo, la propiedad innerHTML contiene el código de marcado HTML completo escrito dentro del elemento correspondiente, por lo que puede usarse para leer el marcado interno. Nuestra llamada console.log(body.innerHTML) imprime el contenido dentro de <body></body> en la consola web. La variable también se puede usar para reemplazar ese contenido, como en body.innerHTML = "<p>Contenido borrado</p>".

En lugar de cambiar porciones enteras del marcado HTML, es más práctico mantener inalterada la estructura del documento y simplemente interactuar con sus elementos. Una vez que el navegador representa el documento, todos los elementos son accesibles mediante métodos DOM. Es posible, por ejemplo, listar y acceder a todos los elementos HTML usando la cadena especial * en el método getElementsByTagName() del objeto document:

let elements = document.getElementsByTagName("*");
for ( element of elements )
{
  if ( element.id == "content_first" )
  {
    element.innerHTML = "<p>New content</p>";
  }
}

Este código colocará todos los elementos que se encuentran en document en la variable elements. La variable elements es un objeto similar a un arreglo, por lo que podemos iterar a través de cada uno de sus elementos con un ciclo for. Si la página HTML donde se ejecuta este código tiene un elemento con un atributo id establecido en content_first (consulte la página HTML de muestra que se muestra al comienzo de la lección), la declaración if coincide con ese elemento y su contenido de marcado se cambia a <p>New content</p>. Tenga en cuenta que se puede acceder a los atributos de un elemento HTML en el DOM utilizando la notación dot de las propiedades del objeto JavaScript: por lo tanto, element.id se refiere al atributo id del elemento actual del bucle for. El método getAttribute() también podría usarse, como en element.getAttribute("id").

No es necesario recorrer todos los elementos si desea inspeccionar solo un subconjunto de ellos. Por ejemplo, el método document.getElementsByClassName() limita los elementos coincidentes a aquellos que tienen una clase específica:

let elements = document.getElementsByClassName("content");
for ( element of elements )
{
  if ( element.id == "content_first" )
  {
    element.innerHTML = "<p>New content</p>";
  }
}

Sin embargo, iterar a través de muchos elementos del documento usando un bucle no es la mejor estrategia cuando tiene que cambiar un elemento específico en la página.

Seleccionar elementos específicos

JavaScript proporciona métodos optimizados para seleccionar el elemento exacto en el que desea trabajar. El ciclo anterior podría ser reemplazado por completo por el método document.getElementById():

let element = document.getElementById("content_first");
element.innerHTML = "<p>New content</p>";

Cada atributo id en el documento debe ser único, por lo que el método document.getElementById() devuelve solo un objeto DOM. Incluso la declaración de la variable element se puede omitir, porque JavaScript nos permite encadenar métodos directamente:

document.getElementById("content_first").innerHTML = "<p>New content</p>";

El método getElementById() es el método preferible para localizar elementos en el DOM, porque su rendimiento es mucho mejor que los métodos iterativos cuando se trabaja con documentos complejos. Sin embargo, no todos los elementos tienen un ID explícito, y el método devuelve un valor null si ningún elemento coincide con el ID proporcionado (esto también evita el uso de funciones o atributos encadenados, como el innerHTML utilizado en el ejemplo anterior). Además, es más práctico asignar atributos de ID solo a los componentes principales de la página y luego usar selectores CSS para ubicar sus elementos secundarios.

Los selectores, presentados en una lección anterior sobre CSS, son patrones que coinciden con elementos del DOM. El método querySelector() devuelve el primer elemento coincidente en el árbol del DOM, mientras que querySelectorAll() devuelve todos los elementos que coinciden con el selector especificado.

En el ejemplo anterior, el método getElementById() selecciona el elemento que lleva el ID content_first. El método querySelector() puede realizar la misma tarea:

document.querySelector("#content_first").innerHTML = "<p>New content</p>";

Debido a que el método querySelector() usa la sintaxis del selector, la ID proporcionada debe comenzar con un caracter hash. Si no se encuentra ningún elemento coincidente, el método querySelector() devuelve null.

En el ejemplo anterior, todo el contenido del div content_first se reemplaza por la cadena de texto proporcionada. La cadena contiene código HTML, lo que no se considera una práctica recomendada. Debe tener cuidado al agregar marcado HTML codificado de forma rígida al código JavaScript, ya que los elementos de seguimiento pueden resultar difíciles cuando se requieren cambios en la estructura general del documento.

Los selectores no están restringidos al ID del elemento. El elemento interno p se puede direccionar directamente:

document.querySelector("#content_first p").innerHTML = "New content";

El selector #content_first p coincidirá solo con el primer elemento p dentro del div #content_first. Funciona bien si queremos manipular el primer elemento. Sin embargo, es posible que deseemos cambiar el segundo párrafo:

<div class="content" id="content_first">
<p>Don't change this paragraph.</p>
<p>The dynamic content goes here.</p>
</div><!-- #content_first -->

En este caso, podemos usar la pseudoclase :nth-child(2) para que coincida con el segundo elemento p:

document.querySelector("#content_first p:nth-child(2)").innerHTML = "New content";

El número 2 en p:nth-child(2) indica el segundo párrafo que coincide con el selector. Vea la lección de selectores CSS para saber más sobre los selectores y cómo usarlos.

Trabajar con atributos

La capacidad de JavaScript para interactuar con DOM no se limita a la manipulación de contenido. De hecho, el uso más generalizado de JavaScript en el navegador es modificar los atributos de los elementos HTML existentes.

Digamos que nuestra página de ejemplo HTML original ahora tiene tres secciones de contenido:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>HTML Manipulation with JavaScript</title>
</head>
<body>

<div class="content" id="content_first" hidden>
<p>First section.</p>
</div><!-- #content_first -->

<div class="content" id="content_second" hidden>
<p>Second section.</p>
</div><!-- #content_second -->

<div class="content" id="content_third" hidden>
<p>Third section.</p>
</div><!-- #content_third -->

</body>
</html>

Es posible que desee hacer que solo uno de ellos sea visible a la vez, de ahí el atributo hidden en todas las etiquetas div. Esto es útil, por ejemplo, para mostrar solo una imagen de una galería de imágenes. Para que uno de ellos sea visible cuando se cargue la página, agregue el siguiente código JavaScript a la página:

// Which content to show
let content_visible;

switch ( Math.floor(Math.random() * 3) )
{
  case 0:
    content_visible = "#content_first";
  break;
  case 1:
    content_visible = "#content_second";
  break;
  case 2:
    content_visible = "#content_third";
  break;
}

document.querySelector(content_visible).removeAttribute("hidden");

La expresión evaluada por la declaración switch devuelve aleatoriamente el número 0, 1 o 2. El selector de ID correspondiente se asigna a la variable content_visible, que utiliza el método querySelector(content_visible). La llamada encadenada removeAttribute("hidden") elimina el atributo hidden del elemento.

El enfoque opuesto también es posible: todas las secciones podrían ser inicialmente visibles (sin el atributo hidden) y el programa JavaScript puede asignar el atributo hidden a cada sección excepto a la de content_visible. Para hacerlo, debe iterar a través de todos los elementos div de contenido que son diferentes del elegido, lo cual se puede hacer usando el método querySelectorAll():

// Which content to show
let content_visible;

switch ( Math.floor(Math.random() * 3) )
{
  case 0:
    content_visible = "#content_first";
  break;
  case 1:
    content_visible = "#content_second";
  break;
  case 2:
    content_visible = "#content_third";
  break;
}

// Hide all content divs, except content_visible
for ( element of document.querySelectorAll(".content:not("+content_visible+")") )
{
  // Hidden is a boolean attribute, so any value will enable it
  element.setAttribute("hidden", "");
}

Si la variable content_visible se estableció en #content_first, el selector será .content:not(#content_first), que se lee como todos los elementos que tienen la clase content excepto los que tienen el ID content_first. El método setAttribute() agrega o cambia atributos de elementos HTML. Su primer parámetro es el nombre del atributo y el segundo es el valor del atributo.

Sin embargo, la forma correcta de cambiar la apariencia de los elementos es con CSS. En este caso, podemos establecer la propiedad CSS display en hidden y luego cambiarla a block usando JavaScript:

<style>
div.content { display: none }
</style>

<div class="content" id="content_first">
<p>First section.</p>
</div><!-- #content_first -->

<div class="content" id="content_second">
<p>Second section.</p>
</div><!-- #content_second -->

<div class="content" id="content_third">
<p>Third section.</p>
</div><!-- #content_third -->

<script>
// Which content to show
let content_visible;

switch ( Math.floor(Math.random() * 3) )
{
  case 0:
    content_visible = "#content_first";
  break;
  case 1:
    content_visible = "#content_second";
  break;
  case 2:
    content_visible = "#content_third";
  break;
}
document.querySelector(content_visible).style.display = "block";
</script>

Las mismas buenas prácticas que se aplican a la mezcla de etiquetas HTML con JavaScript se aplican también a CSS. Por lo tanto, no se recomienda escribir propiedades CSS directamente en código JavaScript. La forma correcta de alternar el estilo visual es seleccionar una clase CSS predefinida para el elemento.

Trabajar con clases

Los elementos pueden tener más de una clase asociada, lo que facilita la escritura de estilos que se pueden agregar o eliminar cuando sea necesario. Sería agotador cambiar muchos atributos CSS directamente en JavaScript, por lo que puede crear una nueva clase CSS con esos atributos y luego agregar la clase al elemento. Los elementos DOM tienen la propiedad classList, que se puede usar para ver y manipular las clases asignadas al elemento correspondiente.

Por ejemplo, en lugar de cambiar la visibilidad del elemento, podemos crear una clase CSS adicional para resaltar nuestro div content:

div.content {
  border: 1px solid black;
  opacity: 0.25;
}
div.content.highlight {
  border: 1px solid red;
  opacity: 1;
}

Esta hoja de estilo agregará un borde negro delgado y semitransparencia a todos los elementos que tengan la clase content. Solo los elementos que también tienen la clase highlight serán completamente opacos y tendrán el borde rojo fino. Entonces, en lugar de cambiar las propiedades CSS directamente como lo hicimos antes, podemos usar el método classList.add("highlight") en el elemento seleccionado:

// Which content to highlight
let content_highlight;

switch ( Math.floor(Math.random() * 3) )
{
  case 0:
    content_highlight = "#content_first";
  break;
  case 1:
    content_highlight = "#content_second";
  break;
  case 2:
    content_highlight = "#content_third";
  break;
}

// Highlight the selected div
document.querySelector(content_highlight).classList.add("highlight");

Todas las técnicas y ejemplos que hemos visto hasta ahora se realizaron al final del proceso de carga de la página, pero no se limitan a esta etapa. De hecho, lo que hace que JavaScript sea tan útil para los desarrolladores web es su capacidad para reaccionar a los eventos en la página, que veremos a continuación.

Controladores de eventos

Todos los elementos visibles de la página son susceptibles a eventos interactivos, como el clic o el movimiento del mouse. Podemos asociar acciones personalizadas a estos eventos, lo que amplía enormemente lo que puede hacer un documento HTML.

Probablemente el elemento HTML más obvio que se beneficia de una acción asociada es el elemento button. Para mostrar cómo funciona, agregue tres botones sobre el primer elemento div de la página de ejemplo:

<p>
<button>First</button>
<button>Second</button>
<button>Third</button>
</p>

<div class="content" id="content_first">
<p>First section.</p>
</div><!-- #content_first -->

<div class="content" id="content_second">
<p>Second section.</p>
</div><!-- #content_second -->

<div class="content" id="content_third">
<p>Third section.</p>
</div><!-- #content_third -->

Los botones no hacen nada por sí mismos, pero suponga que desea resaltar el div correspondiente al botón presionado. Podemos usar el atributo onClick para asociar una acción a cada botón:

<p>
<button onClick="document.getElementById('content_first').classList.toggle('highlight')">First</button>
<button onClick="document.getElementById('content_second').classList.toggle('highlight')">Second</button>
<button onClick="document.getElementById('content_third').classList.toggle('highlight')">Third</button>
</p>

El método classList.toggle() agrega la clase especificada al elemento si no está presente, y elimina esa clase si ya está presente. Si ejecuta el ejemplo, notará que se puede resaltar más de un div al mismo tiempo. Para resaltar solo el div correspondiente al botón presionado, es necesario eliminar la clase highlight de los otros elementos div. No obstante, si la acción personalizada es demasiado larga o involucra más de una línea de código, es más práctico escribir una función aparte de la etiqueta del elemento:

function highlight(id)
{
  // Remove the "highlight" class from all content elements
  for ( element of document.querySelectorAll(".content") )
  {
    element.classList.remove('highlight');
  }

  // Add the "highlight" class to the corresponding element
  document.getElementById(id).classList.add('highlight');
}

Como en los ejemplos anteriores, esta función se puede colocar dentro de una etiqueta <script> o en un archivo JavaScript externo asociado con el documento. La función highlight primero elimina la clase highlight de todos los elementos div asociados con la clase content, luego agrega la clase highlight al elemento elegido. Cada botón debería llamar a esta función desde su atributo onClick, usando el ID correspondiente como argumento de la función:

<p>
<button onClick="highlight('content_first')">First</button>
<button onClick="highlight('content_second')">Second</button>
<button onClick="highlight('content_third')">Third</button>
</p>

Además del atributo onClick, podríamos usar el atributo onMouseOver (que se activa cuando el dispositivo señalador se usa para mover el cursor sobre el elemento), el atributo onMouseOut (que se activa cuando el dispositivo señalador ya no está contenido en el elemento), etc. Además, los controladores de eventos no están restringidos a botones, por lo que puede asignar acciones personalizadas a estos controladores de eventos para todos los elementos HTML visibles.

Ejercicios guiados

  1. Usando el método document.getElementById(), ¿cómo podría insertar la frase “Dynamic content” en el contenido interno del elemento cuyo ID es message?

  2. ¿Cuál es la diferencia entre hacer referencia a un elemento por su ID usando el método document.querySelector() y hacerlo a través del método document.getElementById()?

  3. ¿Cuál es el propósito del método classList.remove()?

  4. ¿Cuál es el resultado de usar el método myelement.classList.toggle("active") si myelement no tiene la clase active asignada?

Ejercicios de exploración

  1. ¿Qué argumento del método document.querySelectorAll() hará que imite el método document.getElementsByTagName("input")?

  2. ¿Cómo se puede utilizar la propiedad classList para listar todas las clases asociadas con un elemento dado?

Resumen

Esta lección cubre cómo usar JavaScript para cambiar el contenido HTML y sus propiedades CSS usando DOM (Modelo de objetos de documento). Estos cambios pueden ser provocados por eventos de usuario, lo cual es útil para crear interfaces dinámicas. La lección abarca los siguientes conceptos y procedimientos:

  • Cómo inspeccionar la estructura del documento usando métodos como document.getElementById(), document.getElementsByClassName(), document.getElementsByTagName(), document.querySelector() y document.querySelectorAll().

  • Cómo cambiar el contenido del documento con la propiedad innerHTML.

  • Cómo agregar y modificar los atributos de los elementos de la página con los métodos setAttribute() y removeAttribute().

  • La forma correcta de manipular las clases de elementos usando la propiedad classList y su relación con los estilos CSS.

  • Cómo vincular funciones a eventos del mouse en elementos específicos.

Respuestas a los ejercicios guiados

  1. Usando el método document.getElementById(), ¿cómo podría insertar la frase “Dynamic content” en el contenido interno del elemento cuyo ID es message?

    Se puede hacer con la propiedad innerHTML:

    document.getElementById("message").innerHTML = "Dynamic content"
  2. ¿Cuál es la diferencia entre hacer referencia a un elemento por su ID usando el método document.querySelector() y hacerlo a través del método document.getElementById()?

    La ID debe ir acompañada del caracter hash en las funciones que utilizan selectores, como document.querySelector().

  3. ¿Cuál es el propósito del método classList.remove()?

    Elimina la clase (cuyo nombre se da como argumento de la función) del atributo class del elemento correspondiente.

  4. ¿Cuál es el resultado de usar el método myelement.classList.toggle("active") si myelement no tiene la clase active asignada?

    El método asignará la clase active a myelement.

Respuestas a los ejercicios de exploración

  1. ¿Qué argumento del método document.querySelectorAll() hará que imite el método document.getElementsByTagName("input")?

    El uso de document.querySelectorAll("input") coincidirá con todos los elementos input de la página, al igual que document.getElementsByTagName("input").

  2. ¿Cómo se puede utilizar la propiedad classList para listar todas las clases asociadas con un elemento dado?

    La propiedad classList es un objeto similar a un arreglo, por lo que se puede usar un bucle for para recorrer todas las clases que contiene.

Linux Professional Insitute Inc. Todos los derechos reservados. Visite el sitio web de Learning Materials: https://learning.lpi.org
Este trabajo está registrado bajo la Licencia Internacional Creative Commons Attribution-NonCommercial-NoDerivatives 4.0

Siguiente lección

035.1 Conceptos básicos de Node.js (035.1 Lección 1)

Leer la próxima lección

Linux Professional Insitute Inc. Todos los derechos reservados. Visite el sitio web de Learning Materials: https://learning.lpi.org
Este trabajo está registrado bajo la Licencia Internacional Creative Commons Attribution-NonCommercial-NoDerivatives 4.0

LPI es una organización sin fines de lucro.

© 2023 Linux Professional Institute (LPI) es la organización global de certificación y apoyo académico para profesionales de código abierto. Con más de 200,000 titulares de certificación, es el primer y más grande organismo de certificación no comercial del mundo para Linux y Open Source. LPI cuenta con profesionales certificados en más de 180 países, realiza exámenes en varios idiomas y tiene cientos de socios de capacitación.

Nuestro propósito es hacer que las oportunidades económicas y creativas estén disponibles para todos, haciendo que el conocimiento de código abierto y la certificación sea universalmente accesible.

  • LinkedIn
  • flogo-RGB-HEX-Blk-58 Facebook
  • Twitter
  • Contáctenos
  • Política de privacidad y cookies

¿Detecta un error o desea ayudar a mejorar esta página? Por favor háznoslo saber.

© 1999–2023 The Linux Professional Institute Inc. Todos los derechos reservados.