Comprendo la facilidad que ofrece el uso de jQuery en el proyecto para seleccionar elementos del DOM; pero, creo que hubiera estado más acorde con la onda EcmaSript-ProgramaciónFuncional, si en lugar de jQuery, se hubiera usado JavaScript vanilla: document.querySelector('#id-selector') …
¡Aún así, el curso va muy bien!
Seguimos.
Agregando a esto recuerdo que se puede usar la propiedad textContent de JavaScript para lograr cambiar el texto quedando algo así: document.querySelector('#id-selector').textContent = 'value'
¡Coincido, muy buen curso!
También podría quedar de la siguiente manera:
let descripcion =document.getElementById('descripcion')descripcion.value='texto'
Si les parece mas rápido y sencillo utilizar la nomenclatura de jQuery $('#element') para acceder a los elementos del dom, pueden hacer uso de esta sin necesidad de cargar la librería con la siguiente función:
//probando en la home de platzi (https://platzi.com/) desde la consolaconst$=element=>document.querySelector(element)const spanNumber =$('#home-v4 > div > div.HeroContent > div > div.HeroContent-content > div.HeroContent-stats > div > div:nth-child(1) > span:nth-child(1)')console.log(spanNumber)// nos mostrara un elemento span
++AVISO++: de esta forma no podrás usar los métodos de jQuery como val() o text() ,pero tendrás disponibles todos los métodos nativos de los elementos HTML como .innerText o .textContent entre muchísimos mas claro.
Veo esto y veo Vue y recuerdo por qué amo Vue jaja, con Vue solo tienes que actualizar el valor y ya Vue se encarga de actualizar todo el en DOM xD
let updateTotals = () => {
let scal = items.reduce((acum,item) => acum +=parseInt(item.cal) ,0)
let scarb = items.reduce((acum,item) => acum +=parseInt(item.carb) ,0)
let sprote = items.reduce((acum,item) => acum +=parseInt(item.prote) ,0)
}
Ejemplo utlizando JS puro o lo que tambien se conoce como vanilla
constcompose=(...functions)=>data=> functions.reduceRight((value, func)=>func(value), data);// Se utiliza $ para identificar que una variable o constante hace referencia// a elementos del DOMconst $DESCRIPTION=document.getElementById("description");const $CALORIAS=document.getElementById("calorias");const $CARBOIDRATOS=document.getElementById("carboidratos");const $PROTEINAS=document.getElementById("proteinas");constERROR_CLASS="is-invalid";constSUCCESS_CLASS="is-valid";// Arreglo de elementosconstLIST=[];// consiguiendo los atributes para las etiquetas HTMLconstattributesToString=(obj ={})=>{constENTRIES=Object.entries(obj);constATTRS=[];for(let i =0; i <ENTRIES.length; i +=1){constAUX=ENTRIES[i];constATTR=AUX[0];constVALUE=AUX[1];ATTRS.push(`${ATTR}="${VALUE}"`);}returnATTRS.join("");};// Creando etiquetas html con atributosconstcreateTagAttr=obj=>(content ="")=>{const{ tag, attr }= obj;return` <${tag}${attr ?`${attributesToString(attr)}`:""}>
${content} </${tag}>`;};// Generando tag de maner dinamicaconstcreateTag=(tag)=>{constTAG=(typeof tag ==="string")?createTagAttr({ tag }):createTagAttr(tag);returnTAG;};// Asignacion de evntos siempre que se desea asignar un evento aun elemento del DOM// es necesario utilizar addEventListener$DESCRIPTION.addEventListener("keypress",()=> $DESCRIPTION.classList.remove(ERROR_CLASS));$CALORIAS.addEventListener("keypress",()=> $CALORIAS.classList.remove(ERROR_CLASS));$CARBOIDRATOS.addEventListener("keypress",()=> $CARBOIDRATOS.classList.remove(ERROR_CLASS));$PROTEINAS.addEventListener("keypress",()=> $PROTEINAS.classList.remove(ERROR_CLASS));// Limpiando inputsconstcleanInputs=()=>{ $DESCRIPTION.classList.remove(SUCCESS_CLASS); $DESCRIPTION.value=""; $CALORIAS.classList.remove(SUCCESS_CLASS); $CALORIAS.value=""; $CARBOIDRATOS.classList.remove(SUCCESS_CLASS); $CARBOIDRATOS.value=""; $PROTEINAS.classList.remove(SUCCESS_CLASS); $PROTEINAS.value="";};constupdateTotals=()=>{let carboidratos =0;let proteinas =0;let calorias =0;// Por buenas praxticas se utiliza un forEach y cumple la mism funcion que se busca// practicamente una funcion de alto orden, no utiizo el map por que map siempre regresa// algo y de momento no importa capturar lo que regresa la iteracion que realizamos.LIST.forEach((item)=>{ carboidratos += item.carboidratos; proteinas += item.proteinas; calorias += item.calorias;});document.querySelector("#totalCalorias").textContent= calorias;document.querySelector("#totalCarboidratos").textContent= carboidratos;document.querySelector("#totalProteinas").textContent= proteinas;};// Agregar elementos en la listaconstaddElement=()=>{const newItem ={description: $DESCRIPTION.value,calorias:parseInt($CALORIAS.value,10),carboidratos:parseInt($CARBOIDRATOS.value,10),proteinas:parseInt($PROTEINAS.value,10),};LIST.push(newItem);cleanInputs();updateTotals();};// funcion para validar los inputsconstvalidateInputs=()=>{// Por cuestion de buenas practicas el resultado de una condición// Ternaria tiene que ser asignada a una variable o constanteconstDESCRIPTION_CLASS=(($DESCRIPTION.value)?SUCCESS_CLASS:ERROR_CLASS); $DESCRIPTION.classList.add(DESCRIPTION_CLASS);constCALORIAS_CLASS=(($CALORIAS.value)?SUCCESS_CLASS:ERROR_CLASS); $CALORIAS.classList.add(CALORIAS_CLASS);constCARBOIDRATOS_CLASS=(($CARBOIDRATOS.value)?SUCCESS_CLASS:ERROR_CLASS); $CARBOIDRATOS.classList.add(CARBOIDRATOS_CLASS);constPROTEINAS_CLASS=(($PROTEINAS.value)?SUCCESS_CLASS:ERROR_CLASS); $PROTEINAS.classList.add(PROTEINAS_CLASS);if($DESCRIPTION.value&& $CALORIAS.value&& $CARBOIDRATOS.value&& $PROTEINAS.value){addElement();}};
Este es mi código para la parte de updateTotals, utilize textContent, ya que innerHTML no me convence mucho para este caso
//Las puse a parte por si se usan en otro momento, si no simplemente se pasan a la funciónconst totalCalories =document.getElementById('totalCalories')const totalCarbs =document.getElementById('totalCarbs')const totalProteins =document.getElementById('totalProteins')constupdateTotals=()=>{let calories =0, carbs =0, protein=0 list.map(item=>{ calories += item.calories, carbs += item.carbs, protein += item.protein})console.log(calories) totalCalories.textContent= calories
totalCarbs.textContent= carbs
totalProteins.textContent= protein
}
// update total inputsfunctionupdateTotals(){let calories =0, carbs =0, protein =0;List.map(item=>{ calories += item.calories; carbs += item.carbs; protein += item.protein;})document.querySelector('#totalCalories').innerHTML= calories;document.querySelector('#totalCarbs').innerHTML= carbs;document.querySelector('#totalProtein').innerHTML= protein;}```
Para evitar escribir tantas veces document.getElementById podemos crear una función, este caso le llamé nodeId, recibe como parámetro el id del elemento html que deseamos obtener. Esto lo aprendí de otro estudiante en el curso de profesional de asincronismo con Juan DC.
constnodeId=(node)=>document.getElementById(node);//Función que actualiza los valores totalesconstupdateTotals=()=>{let calories =0, carbs =0, protein =0; list.forEach(item=>{ calories += item.calories; carbs += item.carbs; protein += item.protein;});nodeId("totalCalories").textContent= calories;nodeId("totalCarbs").textContent= carbs;nodeId("totalProtein").textContent= protein;console.log(calories, carbs, protein)}
Mi versión de la función updateTotals() usando reduce:
Desde mi personal punto de vista, yo hubiera hecho la función con un .forEach, ya que el este método hace casi lo que hace un ciclo for, lo que vendría siendo el recorrer todo el arreglo y ya, sin regresar ningún tipo de array nuevo, como en el caso de .map
Mi función con parseFloat porque me estaba concatenando!
const updateTotals =()=>{let cal =0, carb =0, prot =0; list.map(item =>{ cal +=parseFloat(item.calories), carb +=parseFloat(item.carbs), prot +=parseFloat(item.protein)})document.getElementById('totalCalories').textContent= cal;document.getElementById('totalCarbs').textContent= carb;document.getElementById('totalProtein').textContent= prot;}```
Para los que validaron anteriormente como yo lo hice, en esta clase les arrojará un error, hay que agregar una línea de código en la siguiente función.