Ciencias de la Computación · Ceibal · Parte 1 de 2: Fundamentos
🌳 El DOM
Sección 1 de 6

Todo en una página es un árbol

El navegador no ve tu HTML como texto: lo convierte en una estructura de nodos conectados entre sí, el DOM, que JavaScript puede leer y modificar. Entender esa estructura es el primer paso para todo lo que sigue.

📘 Este es el Recurso 1 de 2 sobre JavaScript y el DOM: acá vemos los fundamentos (el DOM, seleccionar, leer y escribir contenido, crear elementos). El Recurso 2 sigue con eventos, condicionales y la función de corrección automática que vas a necesitar para tu actividad de Sprint 3.

🧠 Todo es un árbol

Cuando el navegador carga una página, la convierte en una estructura de nodos llamada DOM (Document Object Model). Cada etiqueta se transforma en un objeto con el que JavaScript puede hablar: leerlo, cambiarlo, borrarlo o crear otros nuevos.

Esa estructura tiene forma de árbol genealógico: hay un nodo raíz (<html>), que tiene hijos (<head> y <body>), esos hijos tienen sus propios hijos, y así sucesivamente.

Todos estos nodos son accesibles desde JavaScript a través de un objeto global: en una página real, ese objeto es document (por ejemplo, document.body es el nodo que representa la etiqueta <body>). En los simuladores de este recurso vas a usar contenedor en lugar de document — es la misma idea, pero apuntando solo a tu casilla de práctica, no a toda la página.

Además, cuando el navegador convierte una etiqueta en nodo, en realidad genera dos tipos distintos: un nodo Elemento (la etiqueta en sí) y, adentro de él, un nodo Texto (el texto que esa etiqueta encierra).

🔍 <p>Esta página es <strong>muy sencilla</strong></p> se convierte en:
• nodo Elemento <p>
  ↳ nodo Texto: "Esta página es"
  ↳ nodo Elemento <strong>
    ↳ nodo Texto: "muy sencilla"
<html>
<head>
<body>
<header>
<h1>
<main>
<article>
<h2>
<p>
<aside>
<footer>
Toca cualquier etiqueta del árbol para ver su información acá (de qué se trata, cuál es su padre, cuántos hijos directos tiene).
🧩 Pruébalo tú: nodo Elemento vs nodo Texto

Con el mismo ejemplo (<p>Esta página es <strong>muy sencilla</strong></p>), selecciona el nodo Elemento <p> y el nodo Elemento <strong>, e imprime con console.log el tagName de cada uno y el textContent del nodo Texto que tiene adentro <strong>.

JS script.js

                  
                

🧩 Padres, hijos y hermanos

Un nodo puede tener un padre (el que lo contiene directamente), varios hijos (los que están directamente dentro de él) y hermanos (nodos que comparten el mismo padre).

Estas palabras no son solo vocabulario: JavaScript tiene propiedades que usan exactamente estos nombres, como elemento.parentElement y elemento.children, que vas a usar todo el tiempo para moverte por la página.

🌳 <body> es padre de <header>, <main> y <footer> — y esos tres son hermanos entre sí, porque comparten el mismo padre.
🧩 ¿Lo entendiste? · Repaso rápido

🗂️ Tipos de nodo y el objeto document

No todos los nodos del árbol son iguales: el navegador clasifica cada uno en un tipo distinto, según lo que representa. El punto de entrada a todo el árbol es un nodo especial de tipo Document: en una página real es el objeto document, y desde ahí accedes a todo lo demás (document.head, document.body).

🔎 En Chrome puedes ver este árbol tal cual, en vivo: clic derecho sobre cualquier parte de una página → "Inspeccionar" → pestaña Elements. Ahí puedes editar el HTML a mano y ver el resultado al instante (el cambio se pierde al recargar).
Tipo de nodoQué representaEjemplo
DocumentEl documento completo: la raíz desde la que se accede a tododocument
ElementUna etiqueta HTML<div>, <p>, <strong>
AttrUn atributo de una etiquetaid="app", class="paises"
TextEl texto encerrado dentro de una etiqueta"Hola Mundo"
CommentUn comentario escrito en el HTML<!-- nota -->

Para explorar cualquiera de estos nodos, el navegador ofrece console.dir(): a diferencia de console.log(), muestra el nodo como un objeto navegable, con todas sus propiedades para abrir una por una en la consola.

console.dir(document);       // el documento completo
console.dir(document.head);  // la sección <head>
console.dir(document.body);  // la sección <body>
💡 Pruébalo en cualquier página real: clic derecho → Inspeccionar → pestaña Console → escribe console.dir(document.body) y presiona Enter.

Elegir elementos con selectores CSS

Un problema clásico: tienes una lista de frutas en pantalla y quieres mostrar el nombre de la primera, o armaste una pequeña encuesta con checkboxes y necesitas contar cuántas personas marcaron "sí". Para hacer cualquiera de las dos cosas, antes que nada el programa necesita encontrar esos elementos dentro de la página — del mismo modo en que tú los encontrarías con la vista. querySelector y querySelectorAll son las herramientas para eso, usando los mismos selectores que ya conoces de CSS.

🔑 getElementById y los métodos clásicos

Antes de que existiera querySelector, la clase Document ya tenía formas de encontrar elementos. Son más viejas y menos flexibles, pero las vas a seguir viendo todo el tiempo en código ajeno, así que conviene reconocerlas.

HTML de referencia

<div id="app">
  <p id="parrafo1">Hola Mundo</p>
</div>

JavaScript

let div = document.getElementById("app");
let parrafo = document.getElementById("parrafo1");
console.log(div.innerHTML);
console.log(parrafo.innerHTML);
MétodoQué devuelveEjemplo
getElementById("id")Un único elemento, el que tenga ese id (sin el #)document.getElementById("parrafo1")
getElementsByClassName("clase")Todos los que tengan esa clase, como un Array de elementosdocument.getElementsByClassName("paises")
getElementsByTagName("etiqueta")Todos los que tengan esa etiqueta — la menos específica, porque las etiquetas se repiten muchodocument.getElementsByTagName("div")

Estos tres métodos siempre devuelven lo mismo que pidas en singular o en grupo: getElementById te da un solo elemento, los otros dos te dan un grupo recorrible con for...of (igual que harías con un Array). Mira paso a paso cómo se arma:

0 / 3

            
🧩 ¿Lo entendiste? · Practica

Usa contenedor.getElementById('fruta1') para encontrar la primera fruta, y contenedor.getElementsByClassName('fruta-clasica') para contar cuántas hay en total.

JS script.js

                  
                

🔎 querySelector y querySelectorAll

Para resolver el problema de la lista de frutas, primero hay que decirle a JavaScript cuál elemento (o elementos) queremos tocar. Eso es justamente lo que hacen estos dos métodos — buscan, no modifican todavía nada.

A diferencia de getElementById/getElementsByClassName/getElementsByTagName que acabas de ver, querySelector acepta cualquier selector de CSS (id, clase, etiqueta, combinaciones, pseudo-clases) con una única sintaxis — por eso es la forma más usada hoy en día.

const primero = document.querySelector('.fruta');
const todas = document.querySelectorAll('.fruta');

// todas es recorrible con forEach
todas.forEach(function (el) {
  console.log(el.textContent);
});
MétodoQué devuelveEjemplo
querySelector("sel")El primer elemento que coincide con el selector (o null si no hay ninguno)document.querySelector('.fruta')
querySelectorAll("sel")Todos los que coinciden, en una lista recorrible con forEachdocument.querySelectorAll('.fruta')
🧩 ¿Lo entendiste? · Completa el código
Completar espacios

Completa con el método correcto en cada espacio.

document.('#resultado');
document.('.fruta');

✅ La pseudo-clase :checked

Ahora el problema de la encuesta: necesitas contar solo los checkboxes que la persona marcó, no todos los que existen en la página. Para eso, los selectores CSS incluyen pseudo-clases, como :checked, que filtra por un estado del elemento en este momento (marcado o no).

Mira primero, paso a paso, cómo se resuelve el problema completo (nombre de la primera fruta + cantidad marcada). Después te toca practicarlo tú en la pestaña siguiente.

SelectorQué selecciona
.gustaTodos los checkboxes con clase "gusta", estén marcados o no
.gusta:checkedSolo los que están marcados en este momento
0 / 3

          

✍️ Ahora practica tú

Es el mismo problema que acabas de ver resuelto paso a paso. Ahora te toca escribirlo tú: usa querySelector para el nombre de la fruta, y querySelectorAll('.gusta:checked') para contar los marcados.

JS script.js

              
            

Leer, escribir y decorar contenido

Otro problema clásico: corregir una actividad y avisarle a la persona si acertó, mostrando un mensaje ("¡Correcto!" o "Intenta de nuevo") pintado de verde o de rojo según el resultado. Ya sabes encontrar el elemento; ahora falta poder cambiar su contenido (textContent, innerHTML) y cambiar su apariencia con clases (classList).

📝 textContent vs innerHTML

Para avisarle a la persona si acertó, hay que escribir un mensaje dentro de un elemento que ya existe. Estas son las dos formas de hacerlo:

⚠️ Si el texto que insertas con innerHTML viene de otra persona (algo que escribió un usuario) y no lo revisaste, podría meter una etiqueta <script> peligrosa. Regla: texto plano → textContent; HTML que tú controlas → innerHTML.

Mira la diferencia con un mensaje de corrección más real, con varias etiquetas adentro — no solo una palabra en negrita:

PropiedadQué haceEjemplo
textContentLee o escribe texto plano. Si le asignas etiquetas HTML, NO se interpretan: aparecen tal cualelemento.textContent = "¡Correcto!"
innerHTMLLee o escribe interpretando el HTML realelemento.innerHTML = "<strong>Correcto</strong>"
elemento.textContent = "…"
<strong>¡Correcto!</strong> Revisa la <em>ortografía</em> antes de entregar — <mark>+10 pts</mark>
elemento.innerHTML = "…"
¡Correcto! Revisa la ortografía antes de entregar — +10 pts
🧩 ¿Lo entendiste? · Practica
JS script.js

                  
                

🎨 classList: add y remove

Ya tienes el mensaje escrito. Para pintarlo de verde o de rojo, no le cambias el color directamente: le agregas o sacas una clase CSS, y es el CSS el que define cómo se ve esa clase. Cada elemento tiene una propiedad classList para manejar sus clases.

Esta es la técnica central para dar feedback visual — exactamente lo que vas a usar para corregir actividades en el Recurso 2.

MétodoQué haceEjemplo
add("clase")Agrega la clase si no la tienecaja.classList.add('correcto')
remove("clase")Quita la clase si la tienecaja.classList.remove('incorrecto')
toggle("clase")La agrega si no está, la saca si estácaja.classList.toggle('activa')
contains("clase")Devuelve true o false según si la tienecaja.classList.contains('correcto')
🧩 ¿Lo entendiste? · Practica
JS script.js

                  
                

Crear elementos y armar texto

Hasta ahora trabajaste con elementos que ya existían. Ahora vas a crear elementos nuevos desde código, y a armar los textos que les pones adentro de una forma más prolija.

🧱 createElement, appendChild y remove

document.createElement("li") crea un elemento nuevo en memoria (todavía no se ve en la página). Le puedes poner texto con textContent antes de mostrarlo.

padre.appendChild(elemento) lo agrega como último hijo de "padre", y ahí aparece en pantalla. elemento.remove() lo saca del DOM directamente.

const nuevo = document.createElement('li');
nuevo.textContent = 'Nueva tarea';
lista.appendChild(nuevo);

tareaVieja.remove();
🧩 ¿Lo entendiste? · Practica
JS script.js

                  
                

🧩 Template literals (backticks)

Un template literal se escribe con comillas invertidas (`) en vez de comillas simples o dobles. Dentro, insertas el valor de una variable con ${variable}.

También puedes poner expresiones dentro de ${ }, no solo variables sueltas: por ejemplo `Doble: ${puntos * 2}`.

`Hola ${nombre}, tienes ${puntos} pts`
Con +Con template literal
"Hola " + nombre + "!"`Hola ${nombre}!`
"Puntos: " + (p*2)`Puntos: ${p * 2}`
🧩 ¿Lo entendiste? · Practica
JS script.js

                  
                

👪 Juego: Buscando parientes

Un problema clásico: cada vez que una familia suma un integrante nuevo, alguien tiene que anotar quién es su padre o madre, y esa persona nueva debe aparecer colgando de esa rama en el árbol genealógico.

El HTML no puede traer ya escritas a todas las personas que todavía no existen — así que el árbol tiene que crecer con código, cada vez que alguien aprieta "Agregar". Esto combina las tres cosas que acabas de aprender:

Fíjate que el árbol crece en capas: si agregas a "Carlos" como hijo de "Rosa", y después agregas a "Ana" como hija de "Carlos", el <li> de Ana queda anidado dentro del de Carlos, que a su vez está anidado dentro del de Rosa.

Paso del juegoLo resuelve
Encontrar al padre o madre en el árbolquerySelector
Crear a la persona nueva y colgarla ahícreateElement + appendChild
Armar el texto "👤 nombre"template literal
🧩 ¿Lo entendiste? · Practica
JS script.js

                  
                

📋 De inputs y arrays a elementos en pantalla

Los datos de un formulario HTML se leen o se escriben a través de la propiedad value de cada input seleccionado.

HTML de referencia

<input id="nombre" type="text">
<input id="edad" type="number">

JavaScript

document.getElementById("nombre").value = "HOMERO";
document.getElementById("edad").value = 39;

Y la misma propiedad funciona al revés: si el usuario ya escribió algo en el input, input.value te devuelve ese texto para que lo uses en tu código.

Ese valor casi siempre se combina con lo que ya sabes de createElement y for...of: recorres un Array de datos y, por cada uno, creas y agregas un elemento nuevo. Es exactamente el mismo patrón que usaste en el juego de parientes:

let padre = document.getElementById("personas");
let personas = ["HOMERO", "MARGE", "BART", "LISA", "MAGGIE"];

for (const persona of personas) {
  let li = document.createElement("li");
  li.innerHTML = persona;
  padre.appendChild(li);
}

Si en vez de nombres sueltos tienes objetos (con varias propiedades cada uno), un template literal te permite armar de una sola vez todo el HTML interno de cada tarjeta:

const productos = [
  { id: 1, nombre: "Arroz", precio: 125 },
  { id: 2, nombre: "Fideo", precio: 70 },
  { id: 3, nombre: "Pan",   precio: 50 },
  { id: 4, nombre: "Flan",  precio: 100 }
];

for (const producto of productos) {
  let tarjeta = document.createElement("div");
  tarjeta.innerHTML = `<h3>ID: ${producto.id}</h3>
    <p>Producto: ${producto.nombre}</p>
    <b>$ ${producto.precio}</b>`;
  document.body.appendChild(tarjeta);
}
🧩 ¿Lo entendiste? · Practica

Lee el valor del input con .value, crea un <li> con ese texto y agrégalo a la lista con appendChild.

JS script.js

                  
                

Práctica integrada

Una misión chica que combina todo lo de este recurso: seleccionar, leer/escribir contenido, clases y crear elementos con template literals.

🎯 Misión: tarjeta de perfil interactiva

Tienes una tarjeta de estudiante con un botón para agregar una habilidad y un botón para marcarla como favorita. Completa el código para que funcione de punta a punta.

  • Leer el nombre y el puntaje con querySelector y armar el saludo con un template literal.
  • Agregar una nueva habilidad a la lista con createElement + appendChild.
  • Marcar la tarjeta como favorita con classList cuando se hace clic en la estrella.
JS script.js

      
    

Glosario

Todos los términos de este recurso, para repasar. Toca una tarjeta para girarla y ver la definición.

🔍
Sección 1 de 6