Ya mencionamos que en Javascript y en muchos lenguajes dirigidos a manipular clases son los objetos quienes agrupan métodos -acciones– y propiedades con valores. Por lo que al modificar elementos HTML accederemos a los objetos de la API DOM.
SELECCIONAR ELEMENTOS HTML DESDE EL DOM
Los selectores querySelector() y querySelectorAll son dos métodos comunes para seleccionar elementos HTML a partir de su clase o id.
ESTRUCTURA PARA EJEMPLOS
Si bien el objeto DOM contiene la estructura de los elementos HTML presentes en toda página web, usaré los lenguajes JS y HTML para acceder a esos elementos. Recomiendo conocer el lenguaje HTML al detalle mediante tutoriales o bibliografía técnica en caso de seguir con el estudio del DOM. La base del código es la siguiente:
<!doctype html>
<html>
<head>
<!-- Permite mostrar caracteres tildados -->
<meta charset="UTF-8">
<script>
// Aquí el código JS que accede a los elementos HTML
</script>
</head>
<body>
<!-- Aquí los elementos HTML -->
</body>
</html>
Selector querySelector()
Apunta a un elemento HTML según su nombre de etiqueta (por ejemplo "h1", "p"), o su id, o class.
RECORDAR
Para apuntar a un elemento HTML según su CLASE o ID sólo es necesario el selector document.querySelector("...")
. Lo que sí cambia es el signo de etiqueta: id ("#nombre") o class (".nombre")
/* La función querySelector()... */
let variable = document.querySelector( ___ );
/* Puede apuntar desde su parámetro () a: */
/*... al elemento ID */
".identificadorId"
/*... al elemento CLASS */
"#identificadorClass"
/*... al un elemento HTML */
"h1", "p"...
Sin embargo, cuando cada uno de estos selectores es conectado con el objeto, entonces se convierten en métodos que devolverán un resultado. Ojo en la sintaxis para apuntar al elemento html: 'document.querySelector ("elemento");'
En HTML
<h1 class="titulo"> Aquí va el titulo </h1>
En Javascript
/* Obtener el primer elemento "h1".
Se guarda ese puntero en la variable 'elem' */
let elem = document.querySelector("h1");
/* En consola se invoca la variable
que guarda el elemento apuntado */
console.dir(elem);
// En consola se muestra: h1.titulo
Desde la función console() ambos códigos devolverán dos valores: el nombre de la etiqueta apuntada -'h1'- y el nombre de la clase a la que apunta esa etiqueta: "titulo".
De igual forma, se puede acceder a un elemento HTML que contenga un identificador ID. Ojo en la sintaxis para apuntar al elemento con ID: 'document.querySelector ("#nombreElementoId");'
En HTML
<h3 class="nada"> ... </h3>
<h3 class="nada"> ... </h3>
<h3 id="subtitulo"> Elemento ID</h3>
Javascript
/* Obtener el elemento con ID. Se aloja lo apuntado
en una variable */
let elem = document.querySelector("#subtitulo");
console.dir(elem);
// En consola: h3#subtitulo
En otro ejemplo seleccionamos los elementos según el nombre identificador id o la clase.
En HTML
<h3 class="cosaClase"> ... </h3>
<h3 id="cosaIdentificador"> ... </h3>
Javascript
/* Alojamos el elemento de la CLASE apuntada en una variable */
let elem = document.querySelector(".cosaClase");
console.dir(elem);
// Consola muestra h3.cosaClase
/* Alojamos el elemento del ID apuntado en una variable */
let elem2 = document.querySelector("#cosaIdentificador");
console.dir(elem2);
// Consola muestra:
// h3#cosaIdentificador
RECORDAR
Cada identificador en los querySelector() va agrupado en paréntesis y comillas ("..."). Ejemplo:
...querySelector ("#identificadorClase");
...querySelector (".identificadorId");
Selector querySelectorAll()
Selecciona todos los elementos según el identificador de la clase de esos elementos:
En HTML
<h3 class="titulo"> Aquí va primer titulo </h3>
<h3 class="titulo"> Aquí va segundo titulo </h3>
<h3 class="titulo"> Aquí va tercer titulo </h3>
Javascript
/* Alojar en una variable el conjunto
de clases que se está apuntando desde
el identificador "titulo" */
let elem = document.querySelectorAll(".titulo");
/* Invocar la variable */
console.dir(elem);
/* En consola se muestra:
0:h3.titulo
1:h3.titulo
2:h3.titulo
length:3
*/
Hasta aquí nada extraordinario sucede. En HTML se nombran a los elementos como (class="...")
o (id="...")
y se los apunta mediante document. querySelector();
o document. querySelectorAll().
Por lo tanto, como se demostrará en las siguientes secciones, es a partir de esa selección que podremos alterarlos y manipularlos.
MANIPULAR ELEMENTOS USANDO EL DOM
Manipular elementos HTML desde el DOM significa explorarlos, seleccionarlos, añadirles estilo e interacción junto con nuevos atributos entre otros.
PROPIEDAD BODY
Para Lars Svekis y van Putten [5] la propiedad body
contiene todo lo que se halla dentro de los tags <body> ... </body> del documento HTML:
- Recordar: Siempre que deseemos acceder a los métodos del DOM, debemos iniciar con el objeto
document.
, luego con el método útil para obtener y manipular los elementos del DOM y finalmente con el identidicador del elemento a apuntar. - Por ejemplo:
document .querySelector("h1");
Javascript
/* Escribiendo en consola */
console.dir(document.body);
/* El Inspector mostrará docenas
de propiedades y valores del objeto body
:
body
aLink:""
accessKey:""
ariaAtomic:null
ariaAutoComplete:null...
*/
/* Otro ejemplo en una variable */
var seleccion = querySelection(document.body);
UBICAR ELEMENTOS HIJO CON LA PROPIEDAD CHILDREN
Obtiene elementos HTML anidados uno dentro de otros. El primer padre es document.body
y luego, cada propiedad children
apuntará al elemento inmediato (el hijo) de cada padre. Ejemplo:
En HTML
<!-- Padre -->
<div id="Padre1"> ...
<!-- Hijo y padre -->
<div id="hijo1">
<!-- Hijo y padre -->
<div id="Padre2">
<!-- Solo hijos -->
<div id="Hijo2A">..</div>
<div id="Hijo2B">..</div>
</div>
</div>
</div>
Javascript
/* Selecciona SOLO el hijo1 */
console.dir(document.body
.children.Padre1
.children.hijo1);
// -> Muestra en consola: div#hijo1
/* Selecciona SOLO el padre1 */
console.dir(document.body
.children.Padre1);
// -> Muestra en consola: div#Padre1
/* Selecciona SOLO el hijo2A */
console.dir(document.body
.children.Padre1
.children.hijo1
.children.Padre2
.children.Hijo2A);
// -> Muestra en consola: div#Hijo2A
- La secuencia es:
...body.padre. children.hijo
- Un elemento padre es cada identificador que agrupa otro elemento.
- Cada
childnode
debe inicia con un padre... - ...y luego de eso apunta al hijo.
- Recordar: muchas veces un hijo también es padre de otro elemento.
APUNTAR ELEMENTOS CON LA PROPIEDAD CHILDNODES
Permite en breve determinar un arreglo (array) cuyo índice dado apuntará al elemento HTML a seleccionar.
- Recordar: para ejecutar estos ejercicios, copia el código HTML en un archivo 'nombre.html'. Luego, abre el archivo en un navegador. Después, ejecuta el modo inspector (en computadores de escritorio es con click derecho + elegir Inspector en el menú). Finalmente, elige la pestaña de 'console' e inserta en esa ventana sólo el código de JS. El resultado se mostrará en una sola línea.
En HTML
<!-- OJO CON ESTO: El espacio de arriba es un nodo [0] #text.
Este comentario es un nodo [1] #comment y el espacio
siguiente antes del div es otro nodo [2] #text -->
<div id="Padre1"> ... </div>
Javascript
/* Seleccionar Padre1.
Según los elementos de arriba, el nodo con id 'Padre1'
corresponde al índice [3] */
console.dir(document.body
// Muestra div#Padre1 pero no muestra el contenido
.childNodes[3]);
//-> Muestra div#Padre1
//-> Muestra #comment
.childNodes[1]);
//-> #comment
Solo en caso de que se eliminen los espacios vacíos y los comentarios, el nodo [0] sería entonces el elemento Padre1.
IMPORTANTE DIFERENCIA
La propiedad childNodes
devuelve un objeto nodeList
, accedido mediante índice numérico [..]. Este objeto puede ser un espacio de caracter vacio, los comentarios del código o la etiqueta HTML y su clase o Id. En otras palabras, todos esos elementos (los comentarios, las etiquetas HTML y sus clases o IDs) son nodos que apuntan a un índice.
Por otro lado, la propiedad children
solo devuelve elementos HTML (no toma en cuenta espacios vacios y comentarios).
Para mostrar el índice de los nodos y su cantidad:
En HTML
<div id="Afuera">
<div id="dentro"></div>
</div>
Javascript
let todoEldiv = document.getElementById("Afuera");
let mostrar = todoEldiv.childNodes;
console.dir(mostrar);
//-> Cantidad de nodos
/* NodeList(3)
0: text
1: div#dentro
2: text
length: 3
[[Prototype]]: NodeList */
Para mostrar las etiquetas y los elementos nodos de un body
en tiempo real:
En HTML
<!-- Cada salto de linea es un nodo #text -->
<h1> </h1>
<h2> </h2>
<p> </p>
<p>Los elementos son:</p>
<p id="demo"></p>
Javascript
/* Se aloja en una variable
todos los nodos hijo presentes
en el documento abierto en el navegador */
const listaNodos = document.body.childNodes;
// Para guardar todo lo hallado
let loHallado = "";
// Iteración: Recorre todos los nodos mediante indice
for (let i = 0; i < listaNodos.length; i++) {
/* --El atributo nodeName muestra el nombre de cada nodo.
--loHallado alojará su propio contenido + el recorrido
de los nodos gracias al atributo nodename */
loHallado = loHallado + listaNodos[i].nodeName + "
";
}
/* Apunta a obtener el contenido interno del id=demo.
Ojo con esta igualdad: desde el llamado de
un elemento del DOM que tendrá el valor
del recorrido de la iteración. */
document.getElementById("demo").innerHTML = loHallado;
/* En la pantalla se muestra:
Los elementos son:
#text, #comment, #text, #comment, #text,
H1, #text, H2, #text, P,
#text, P, #text, P, #text, SCRIPT */
- Propiedad '.innerHTML': Añade o remueve el contenido de un elemento HTML que será mostrado en la página del navegador. Ojo: manipular una gran cantidad de nodos con '.innerHTML' podría cargar al navegador.
- En el ejemplo de abajo (y desde un archivo .html) se agrega y se muestra desde JS un elemento HTML que aún no existe.
En HTML
<body> <!-- Inicialmente aquí no hay nada --> </body>
En Javascript
/* La propiedad 'createElement' crea un elemento HTML
según la etiqueta dada */
var frase = document.createElement("p");
// Pedimos que dentro de 'frase' se inserte "Para envolverte...
frase.innerHTML = "Para envolverte en besos...";
/* El método appendChild() adjunta o inserta al final
de un nodo padre un elemento asignado desde el argumento,
y muestra el elemento adjuntado en el navegador. */
document.body.appendChild(frase);
/* En el navegador se mostrará la frase:
Para envolverte en besos quisiera ser el viento */
Tener en cuenta algo interesante en el penúltimo ejemplo antes del recuadro celeste: se creó una igualdad desde el llamado de un elemento del DOM y una variable. Similar al ejemplo de abajo: se pide que el llamado a un nodo DOM sea igual (o lo que es lo mismo) que inserte en ese llamado el contenido de la variable. Por lo tanto, en este contexto la igualdad significa 'inserte aquí'.
En HTML
<!-- Elemento id declarado pero vacío de contenido -->
<div id="demo"> </div>
En Javascript
// Aloja string
var myText = "Eres perla que surgiste...";
// Obtiene el contenido interno del id 'demo' = ...
// E inserta el contenido de la variable myText
document.getElementById("demo").innerHTML = myText;
// Se muestra en el Navegador
// 'Eres perla que surgiste...'
INSERTAR ESTILOS CSS A LOS ELEMENTOS HIJOS SEGÚN CHILDNODES[..] y CHILDREN[..], Y MOSTRARLOS
Dos propiedades similares permiten acceder y manipular los elementos hijos a partir de un elemento padre y a partir de un número índice: .childNodes[]
y .children[]
.
.childNodes[]
accede en toda la colección o lista de elementos nodos al igual que espacios en blanco y etiquetas; y también a los no-nodos como los textos dentro de las etiquetas y comentarios de código. En este ejemplo, los elementos <p>
están ubicados en una sola línea de código. Esto evita confusiones en el conteo de los nodos y no-nodos. Es decir, se los organizó sin espacios de la siguiente forma: <p>texto</p><p>texto</p><p>texto</p>. Por lo tanto, al haber 3 nodos se puede apuntar a uno de los 3 mediante .childNodes[...]
. En este caso se apuntó solo al nodo índice 1 -ver el código en consola-.
Nodo índice Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Nodo índice 2 Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam
Nodo índice 3 Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur
Por otro lado, .children[]
devuelve únicamente el elemento nodo hijo de un padre. Sin embargo, ¿por qué contamos esta vez desde el índice 0 en adelante? Puesto que .children[]
solo apunta a los nodos hijos del padre, solo contaremos los índices desde el cero en adelante. .children[]
no lee los no/nodos, como los texto o comentarios. Incluso, de haberlos, solo detectará los nodos o etiquetas de elementos.
Nodo índice 0 Lorem ipsum dolor sit amet
Nodo índice 1 Sed ut perspiciatis unde omnis iste natus error
Nodo índice 2 Nemo enim ipsam voluptatem quia voluptas
Por otro lado, una forma de apuntar a un nodo que anteceda a otro es mediante la propiedad previousElementSibling
. Solo a manera de concepto: entre dos elementos A y B, .children[B]. previousElementSibling;
apuntará a su elemento anterior (al elemento A). Pero si no está explícito uno de los dos nodos, el mensaje dará un mensaje de 'undefined'.
Nodo 0 Lorem ipsum dolor sit amet
Nodo 1 sed do eiusmod tempor
Nodo 2 Ut enim ad minim veniam
Nodo 3 sed do eiusmod tempor
SELECCIONAR Y CAMBIAR LAS PROPIEDADES DE LOS ELEMENTOS NODO
En HTML
<h1> aaa </h1>
<p id="saludos"> bbb </p>
Javascript
/* Solo apunta a todos los elementos hijos de body,
tengan o no identificador id o class. Nada nuevo aún. */
document.body.children.saludos;
PROPIEDAD INNERTEXT
Inserta un contenido dado explícito y lo prepara para ser mostrado. En este caso, se usarán dos tags con identificadores id="..."
que inicialmente están vacíos. La propiedad 'innerText' les añadió contenido:
.
.
En otro ejemplo se insertará contenido mediante .innerText
hacia los hijos del documento <body>
En HTML
<!-- Las etiquetas h1 y p están vacías -->
<body>
<h1 id="saludos"></h1>
<p id="textito"></p>
</body>
Javascript
/* h1 mostrará 'hola' */
document.body.children.saludos.innerText = "hola!!";
/* p mostrará 'amigos' */
document.body.children.textito.innerText = "amigos";
/* Luego de eso ambas etiquetas mostrarán
las nuevas palabras en el nevegador */
PROPIEDAD INNERHTML
La propiedad innerHTML
obtiene y altera contenido dentro de un elemento HTML -ver código en consola-.
Este texto esta primero
Abajo, otro ejemplo más interactivo en el uso de .innerHtml
. Un click al botón ejecuta la acción
Eres perla...
ACCEDER A ELEMENTOS DESDE EL ID
El método getElementById()
devuelve un elemento apuntando a un id único –no se repite en ningún lado de ese documento–.
En HTML
<h1> Ejemplo </h1>
<div id="uno" class="ejemplo"> aaa </div>
<div id="dos" class="ejemplo"> bbb </div>
<div id="tres" class="algo"> ccc </div>
Javascript
console.dir( document.getElementById("two") );
//-> div#dos.ejemplo
En el ejemplo de abajo: Se alojará el ID apuntado en una variable creada. Luego se creará otra variable para alojar un nuevo elemento 'h2' en el cual se mostrará el contenido seleccionado. La propiedad .innerText se usará para 'insertar' lo seleccionado dentro del nuevo h2 creado. Finalmente se usará document.querySelector("") para apuntar al contenedor padre donde queremos se ubique el elemento seleccionado. Y se usará .appendChild() para concretar esa inserción. (Revisar código en consola).
Se elije:
- Usar
document. body. appendChild(nodoElegido)
hubiera mostrado el nodo elegido 'Eres perla..' al final de esta página web. Ya que se deseaba ubicar el resultado dentro del padre div, se necesitó usar alojar en una variable adocument. querySelector(".padre");
y luego, adjuntar el resultado elegido mediantepadreVar. appendChild(elegido);
.
ACCEDER A ELEMENTOS DESDE EL NOMBRE DEL TAG (tag name)
Propiedad no sensible al nombre de las etiquetas a la que apunta. Es decir, getElementsByTagName ("div")
apuntará a ese elemento así sea ("DIV") o ("dIV"). Esa propiedad apuntará a un elemento HTML por su nombre de tag. Sin embargo, podría dar como resultado un tipo de dato arreglo o una lista de nodos (pueden haber más de un elemento con el mismo nombre de tag, como el tag <div>...</div>
) como en el siguiente ejemplo:
Javascript con el mismo bloque HTML dado arriba
// Apunta a todos los elementos de tag 'div'
// Ojo con ElementS –termina en 's'-
console.dir(document.getElementsByTagName("div"));
// La consola muestra:
/* HTMLCollection(3)
0: div#uno.ejemplo
1: div#dos.ejemplo
2: div#tres.algo
dos: div#dos.ejemplo
tres: div#tres.algo
uno: div#uno.ejemplo
length: 3 */
Por eso es útil apuntar a elementos ID únicos, y no a nombres de tag (que pueden ser cientos de elementos).
APUNTAR A ELEMENTOS SEGÚN SU TAG Y SU INDICE
Mediante el método getElementsByTagName
–OJO, es ElementS– y mediante el métodos item()
.
Los elementos son:
El script resulta en:
En otro ejemplo, se escoge un elemento según el índice:
En HTML
<div id="a" class="letra"> aaa </div>
<div id="b" class="letra"> bbb </div>
<p id="num" class="numero"> 222 </div>
<p id="num1" class="numero"> 333 </div>
Javascript
/* Ubicar el 'div' con indice cero */
console.dir(
document.getElementsByTagName("div").item(0)
);
// -> div#a.letra
/* Ubicar el 'p' con indice cero */
console.dir(document.getElementsByTagName("p").item(1));
// -> p#num1.numero
Para apuntar a un elemento con el ID dado, usar también namedItem("..")
. Por ejemplo:
En HTML
<p id="xx" class="numero"> 222 </div>
<p id="yy" class="numero"> 333 </div>
Javascript
/* Ubicar el 'div' con el ID 'num' */
console.dir(
document.getElementsByTagName("p").
namedItem("identificador_ID"));
// p#num.numero
/* Cuando se invoca con console.log(); */
console.log(
document.getElementsByTagName("p").namedItem("xx"));
/* -> <p id="xx" class="numero"> 222 </p> */
Para apuntar a todos los elementos de un mismo tipo (por ejemplo, solo elementos <p>) se usa como argumento de getElementsByTagName("...")
el nombre de la etiqueta a apuntar. El resultado será un HTMLCollection
de todos los elementos <p> sea cual fuere su ID o su CLASS:
- ERROR (Omitir la S):
getElementByTagName ("...")
- CORRECTO (Con la S):
getElementsByTagName ("...")
En HTML
<!-- Todos son elementos <p>-->
<!--Sin ID o CLASS-->
<p> .. </div>
<!-- Sin CLASS-->
<p id="bb"> .. </div>
<!-- Sin ID-->
<p class="numero"> .. </div>
Javascript
/* Apuntar a todos los elementos <p>*/
console.log(
document.getElementsByTagName("p"));
/* HTMLCollection(3)
0: p#aa.numero
1: p#bb.numero
2: p#cc.numero
aa: p#aa.numero
bb: p#bb.numero
cc: p#cc.numero
len
APUNTAR A ELEMENTOS POR EL NOMBRE DE CLASE (CLASS NAME)
En HTML
<!-- Elementos con igual clase -->
<p class="xx" id="holi"> .. </div>
<p class="xx" id="lali"> .. </div>
<p class="zz"> .. </div>
Javascript
/* Apuntar a elementos de clase 'xx' */
console.log(
document.getElementsByClassName("xx"));
/* -> HTMLCollection(2)
0: p#holi.xx
1: p#lali.xx
holi: p#holi.xx
lali: p#lali.xx
length:2
* Notar que el elemento 'p' de clase 'zz' no es mostrado. */