duduromeroa.com

Javascript | DOM | API

Programación para web con Javascript: estudio del Document Object Model (DOM) 2


Contenido

querySelector(), querySelectorAll(), document.body, document.body.children, childNodes, innerText, getElementsByTagName(), getElementsByClassName





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 en su estructura los elementos HTML, usaré JS para accederlos. En adelante lo combinaré con la sintaxis HTML solo para demostración. Recomiendo conocer la sintaxis HTML al detalle –y cómo vincular archivos HTML y JS– mediante tutoriales audiovisuales o con bibliografía técnica en caso de seguir con el estudio del DOM.



<!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()

Ambos selectores 'controlan' un elemento HTML al ubicarlo según su nombre de etiqueta (por ejemplo "h1", "p"), su <id=""> o su <class="">

Sin embargo, cuando cada uno de estos selectores es conectado con el objeto, entonces se convierten en métodos que devolverán un resultado.

En HTML

<h1 class="titulo"> Aquí va el titulo </h1>

En Javascript

// Obtener el primer elemento "h1"
	let elem = document.querySelector("h1");
	console.dir(elem);
// h1.titulo

Ambos códigos devolverán –solo en consola– dos valores: la etiqueta 'h1'; y el nombre de la clase "titulo".

De igual forma, se puede acceder a un elemento HTML que contenga un identificador ID.

En HTML

<h3 class="nada"> ... </h3>
	<h3 class="nada"> ... </h3>
	<h3 id="subtitulo"> Elemento ID</h3> 

Javascript

 /* Obtener el elemento con ID  */
	let elem = document.querySelector("#subtitulo");
	console.dir(elem);
// 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

let elem = document.querySelector(".cosaClase");
console.dir(elem);
// Consola muestra:
// h3.cosaClase

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

/* Obtener todos los elementos con 
el identificador de clase "titulo" */
let elem = document.querySelectorAll(".titulo");
console.dir(elem);

/* 
0:h3.titulo
1:h3.titulo
2:h3.titulo
length:3
*/

Como se demostrará en las siguientes secciones, es a partir de la selección de los elementos HTML desde la API DOM que podremos alterarlos y manipularlos.

MANIPULAR ELEMENTOS USANDO EL DOM

Manipular elementos HTML desde el DOM significa explorarlos, seleccionarlos, añadir nuevos elementos, añadirles estilo, acciones interactivas y nuevos atributos junto con sus valores, 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:

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);

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 div#hijo1

/* Selecciona SOLO el padre1 */
console.dir(document.body
.children.Padre1);
// -> Muestra div#Padre1

/* Selecciona SOLO el hijo2A */
console.dir(document.body
.children.Padre1
.children.hijo1
.children.Padre2
.children.Hijo2A);
// -> Muestra 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.

PROPIEDAD CHILDNODES

Permite en breve determinar un arreglo (array) cuyo índice dado apuntará al elemento HTML a seleccionar.

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
.childNodes[3]);
//-> Muestra div#Padre1

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, comentarios y los propios elementos. En otras palabras, todos esos nodos contemplan 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);
//->
/* 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 comentario es un nodo #comment -->
<!-- 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 llama a todos los nodos
const listaNodos = document.body.childNodes;

// Para guardar todo lo hallado
let loHallado = "";

// Recorre todos los nodos mediante indice
for (let i = 0; i < listaNodos.length; i++) {
/* Ojo con el atributo nodeName. 
Este muestra el nombre del nodo en tiempo real */
  loHallado = loHallado + listaNodos[i].nodeName + "
"; } // Muestra 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 */

Para dar estilo a un elemento seleccionado según su índice:

En HTML

<div id="agrupador"><!-- [0]-->
			<p>Soy [1]</p>
			<!--   [2]-->
			<p>soy [3]</p>
	</div>

Javascript

document.getElementById("agrupador")
.childNodes[3].style.backgroundColor = "yellow";
// Solo 'soy [3]' se muestra con fondo amarillo

Para determinar lo que está antes de un elemento apuntado:

En HTML

<div id="agrupador"><!-- [0]-->
			<p>Soy [1]</p>
			<!--   [2]-->
			<p>soy [3]</p>
	</div>

Javascript

var elem = document.getElementById('holiSpan')
.previousElementSibling;

document.write('

Lo que esta arriba de span:

'); /* Mientras que 'elem' sea true. O sea, mientras tenga un dato válido como mínimo */ while (elem) { /* Recordar nodeName: permite mostrar la etiqueta de cada elemento apuntado */ document.write('
  • ' + elem.nodeName + '
  • '); elem = elem.previousElementSibling; } document.write(''); /* En la pantalla se muestra: div, div, p Lo que esta arriba de span: DIV, H4 */

    SELECCIONAR Y CAMBIAR PROPIEDADES DE ELEMENTOS COMO OBJETOS

    Para manipular elementos HTML desde el API DOM en JS, se direcciona un elemento de la siguiente forma:

    En HTML

    <h1> aaa </h1>
    <p id="saludos"> bbb </p>
    

    Javascript

    /* Solo apunta al contenido agrupado 
    entre los signos de apertura y cierre 
    del elemento HTML. Aún no hay cambios. */
    document.body.children.saludos;
    

    PROPIEDAD INNERTEXT

    Apunta a todo el contenido únicamente textual que está agrupado entre los tags de apertura y cierre de un elemento HTML. Así mismo, mostrará cualquier cambio que sea en un texto.

    El siguiente ejemplo apunta solo a un elemento de texto y al cambio –también textual– a ejecutar en él:

    En HTML

    <!-- La etiqueta H1 con el id 'saludos' tiene un contenido -->
    <h1 id="saludos"> ... </h1>
    <p id="textito"> ... </p>
    

    Javascript

    /* Ahora la etiqueta H1 con el id 'saludos' 
    mostrará la palabra Holi!! */
    document.body.children.saludos.innerText = "Holi!!";
    // + + + 
    /* Ahora la etiqueta p con el id "textito" muestra la palabra
     Holi!! */
    document.body.children.textito.innerText = "Holi!!";
    

    PROPIEDAD INNERHTML

    La propiedad innerHTML altera textos y elementos HTML –con sus tags–. Así, para reemplazar un elemento HTML por otro nuevo elemento HTML con nuevos tags (en este caso, con tags <h1></h1>y <i>...</i>) :

    Javascript

    /* Un nuevo elemento con nuevos tags HTML se agrega 
    en reemplazo al elemento con el ID "textito" */
    document.body.children.textito.innerHTML= 
    "<h1><i>Nuevo titulo</i></h1>";
    

    ACCEDER A ELEMENTOS DESDE EL ID

    El método getElementById() devuelve un elemento apuntando a un id único –no se repite en en ningún lado del mismo 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
    

    ACCEDER A ELEMENTOS DESDE EL NOMBRE DEL TAG (tag name)

    Apuntar a un elemento HTML por su nombre de tag 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().

    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. */
    


    BIBLIOGRAFÍA:
      3ra edición. 2018. Marijn Haverbeke. No starch press.
      Mozilla Foundation.
      David Flanagan (2020). Editorial O'Reilly.
      Ved Antani, Stoyan Stefanov (2017). Packt Publishing.
      Editorial Packt.
      Information and Computation. Elsevier.
      ACM SIGCSE BulletinVolume 19Issue 1Feb. 1987 pp 98–102https://doi.org/10.1145/31726.31742.