miércoles, 31 de julio de 2019

JavaScript manejando el DOM con las clases

Este artículo forma parte de una serie que trata sobre el DOM (Document Object Model) y su manejo desde JavaScript.
  1. JavaScript manejo del DOM
  2. Manejar el DOM en JavaScript
  3. Cambiar color usando el DOM en JavaScript
  4. JavaScript manejando el DOM por sus etiquetas
  5. JavaScript manejando el DOM con las clases
  6. JavaScript manejando el DOM
En esta ocasión veremos como trabajar con las clases (class).


HTML

En el documento HTML tenemos una sección con id="seccionLunas" y unos cuantos li para crear una lista identificados por su clase (class).

 <!DOCTYPE html>  
 <html>  
  <head>  
   <meta charset="utf-8">  
   <title>modifica el DOM</title>  
  </head>  
  <body>  
   <section id="seccionLunas">  
    <h1>Satélites naturales</h1>  
   <ul>  
    <li class="marte">Phobos es la luna interior y la que más rápido gira.</li>  
    <li class="marte">Deimos es la luna exterior y la de giro más lento.</li>  
    <li class="marte">Phobos tiene una masa casi 5 veces mayor que Deimos.</li>  
    <li class="tierra">La Luna es el único satélite de la Tierra.</li>  
    <li class="jupiter">Ganímedes es la mayor luna de Júpiter.</li>  
    <li class="jupiter">Io es una luna de Júpiter.</li>  
    <li class="jupiter">Europa es unaluna de Júpiter.</li>  
    <li class="jupiter">Calisto es la mayor luna de Júpiter.</li>  
    <li class="saturno">Titán es la mayor luna de Saturno.</li>  
   </ul>  
   </section>  
   <!--scripts-->  
   <script src="dom4.js"></script>  
  </body>  
 </html>  

JavaScript

 'use strict'  
 //TRABAJAR EN EL DOM CON ELEMENTOS POR SU CLASE  
 console.log(("▼ 1 ").repeat(20));  
 var liMarte=document.getElementsByClassName('marte');  
 console.log(liMarte);  
 for(var i in liMarte){  
   if(liMarte[i].className=="marte"){  
     liMarte[i].style.backgroundColor="beige";  
   }  
 }  
 console.log("");  
   
 console.log(("▼ 2 ").repeat(20));  
 var liTierra=document.getElementsByClassName('tierra');  
 console.log(liTierra);  
 //si hacemos el siguiente for no es necesario un if  
 for(var i=0;i<liTierra.length;i++){  
   liTierra[i].style.fontStyle="italic";  
   liTierra[i].style.fontWeight="bold";  
   liTierra[i].style.backgroundColor="#00FF00";//verde  
 }  
 console.log("");  
   
 console.log(("▼ 3 ").repeat(20));  
   
 //con QUERYSELECTOR  
 var id=document.querySelector("#seccionLunas"); //con # actuamos sobre los id  
 console.log(id);  
 console.log("");  
   
 console.log(("▼ 4 ").repeat(20));  
 var claseMarte=document.querySelector(".marte");//con . actuamos sobre las clases  
 console.log(claseMarte); //muestra solo el primer elemento  
 console.log("");  
   
 console.log(("▼ 5 ").repeat(20));  
 var a=document.querySelectorAll(".marte"); //con querySelectorAll pillamos todos  
 console.log(a);  
 console.log("");  
   
 function toArray(domElements){  
  return Array.from(domElements);  
 }  
   
 console.log(("▼ 6 ").repeat(20));  
 console.log("usando HTMLCOLLECTION - FOREACH");  
 //seleccionamos con getElementById, getElementsByClassName, ...  
 var htmlcollection = document.getElementsByTagName('li');   
   
 /*  
 //esto no funciona, da erro, dice  
 //TypeError: htmlcollection.forEach is not a function  
 console.log(htmlcollection);//vemos que es una htmlcollection  
 htmlcollection.forEach((value, key) => {  
  console.log(key + " => " + value);  
 });  
 */  
 console.log("");  
   
 console.log(("▼ 7 ").repeat(20));  
 var htmlcollection_array = toArray(htmlcollection); // Convertimos en array convencional  
 htmlcollection_array.forEach((value, key) => { // Ya funciona  
  console.log(key + " => " + value.textContent);  
 });  
 console.log("");  
   
 console.log(("▼ 8 ").repeat(20));  
   
 console.log("Usando NODELIST - FOREACH");  
 //usamos una función de selección de tipo querySelector, querySelectorAll.  
 var nodelist = document.querySelectorAll("li");  
 console.log("");  
   
 console.log(("▼ 9 ").repeat(20));  
 console.log(nodelist); //comprobamos que es una nodelist  
 console.log("");  
   
 console.log(("▼ 10 ").repeat(16));  
 nodelist.forEach((value, key) => {  
  console.log(key + " => " + value.textContent);  
 });  
 console.log("");  
   
 console.log(("▼ 11 ").repeat(16));  
 console.log("usando AMBOS - FOR(..IN...)");  
   
 //para evitar usar if dentro del bucle tanto para htmlcollection como para nodelist  
 //deben ser pasados a arrays  
 //para htmlcollection ya tenemos htmlcollection_array  
   
 var nodelist_array = toArray(nodelist);  
 for(let key in nodelist_array){ //funciona bien sin if  
  console.log(key, nodelist_array[key].textContent);  
 }  
 console.log("");  
   
 console.log(("▼ 12 ").repeat(16));  
   
 for(let key in htmlcollection_array){ //funciona bien sin if  
  console.log(key, htmlcollection_array[key].textContent);  
 }  
 console.log("");  
   
 console.log(("▼ 13 ").repeat(16));  
   
 console.log("usando FOR(..OF...) ponemos fondo azul");  
 //Otra forma que no necesita if es FOR(...OF...)  
 var jovianos = document.getElementsByClassName("jupiter"); //satélites jovianos  
 for(let joviano of jovianos){  
  joviano.style.background = "cyan";  
 }  
 console.log("");  
   
 console.log(("▼ 14 ").repeat(16));  
   
 //usando FOR(...IN...) pero es necesario un IF  
 //si necesitamos poner el if con un FOR(...IN...)  
 var rediv=document.getElementsByClassName("marte");  
 for(var value in rediv){  
  if(typeof rediv[value]=="HTMLLIElement"){  
   rediv[value].style.color="blue";//tinta azul  
  }  
  console.log("este es de marte: "+rediv[value]);  
 }  
 //si no hubieramos puesto el if si funcionaría la tinta azul pero  
 //la consola daría un error porque intenta poner azul elementos  
 //que no son texto y que van en la colección.  

Las colecciones del tipo HTMLcollection no aceptan bucles forEach para ser recorridas y así poder sacar sus elementos. Lanzan un error diciendo:

TypeError: htmlcollection.forEach is not a function

Un posible solución es emplear un bucle for del tipo for(...in...) pero en este caso al pedir con style que los elementos del HTMLcollection tomen determinado atributo, como por ejemplo, un color, se hace necesario añadir un condicional if para evitar que el código intente añadir un color a los elementos finales de la colección que ya no son puro texto.

En el código se presentan otras formas de establecer bucles para que no sea necesario usar ese condicional if y que sin embargo podamos añadir ciertos estilos (style) como por ejemplo el color, únicamente a los elementos que son de puro texto.
  • Un sistema consiste en convertir la colección en un array con toArray() y así luego ya podamos aplicar un forEach
  • Un sistema que funciona estupendamente es hacer un for(...of...)

Para iterar elementos del DOM es más interesante usar for(...of...). A diferencia del "for in" la variable "div" no toma los índices, toma los valores de cada índice que es lo que habitualmente queremos. Con "for in" obtienes indices y con "for of" obtienes valores.

Si usamos funciones del tipo querySelectorAll, que son similares a JQuery, si podremos usar un forEach sin problemas ya que lo que devuelven es un objeto del tipo NodeList.



No hay comentarios:

Publicar un comentario