Estoy trabajando en un proyecto de JS en el que creo un programador diario y cada hora debe tener un código de colores en función de si es pasada, presente o futura.
El horario va de 9am a 5pm. Actualmente está aplicando la clase para el futuro a cada bloque, por lo que cada fila se muestra en verde. En su lugar, digamos que si fueran las 11 a. m., la fila de las 11 a. m. se resaltaría en rojo para la hora actual, las filas de las horas anteriores a las 11 a. m. serían grises o transparentes y las horas futuras serían verdes.
He configurado identificadores para cada uno de mis bloques de horas para analizar y comparar con la hora actual, pero por alguna razón no funciona. Ya tengo configuradas las clases en mi CSS para pasado, presente y futuro.
var blocks = document.getElementsByClassName("description"); var hourBlock = parseInt(moment().format('H')); Array.from(blocks).forEach(description => { let idString = description.id, rowHour; if (idString) { rowHour = parseInt(idString); } if (rowHour) { if (hourBlock === rowHour) { $(".description").addClass("present") } else if (hourBlock < rowHour) { $(".description").addClass("past") } else { $(".description").addClass("future"); } } });
El problema es que en su bucle está actualizando las clases de todos los elementos .description
, no el del bucle forEach
.
Para solucionar el problema y hacer que su código sea mucho más breve, puede pasar una función al método addClass()
de jQuery que se evaluará individualmente con cada elemento de la colección. En esta función, puede verificar la id
del elemento con respecto a la hora actual (para la cual no necesita MomentJS) y establecer la clase adecuada. Prueba esto:
// let nowHour = (new Date()).getHours(); let nowHour = 13; // hard-coding value for this demo $('.description').addClass(function() { return +this.id === nowHour ? 'present' : +this.id < nowHour ? 'past' : 'future'; });
.present { background-color: #C00; } .past { background-color: #CCC; } .future { background-color: #0C0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <div class="description" id="9">9am</div> <div class="description" id="10">10am</div> <div class="description" id="11">11am</div> <div class="description" id="12">12pm</div> <div class="description" id="13">1pm</div> <div class="description" id="14">2pm</div> <div class="description" id="15">3pm</div> <div class="description" id="16">4pm</div> <div class="description" id="17">5pm</div>
Cada vez que llamas a un código como este:
$(".description").addClass("past");
... consultará TODOS los elementos con la clase 'descripción' como establece la clase en el pasado. Lo que desea hacer es solo establecer la clase del elemento que se examina en el ciclo.
Como está usando jquery, no necesitamos getElementsByClassName('description') porque esto se puede traducir como $('.description').
// using jquery's each to loop through the collection $('.description').each((idx, elt) => { $(elt).removeClass(); // no params to clear ALL classes from element // put whatever logic you want to analyze the element (elt) $(elt).addClass("whateverClassYouWant"); // add the description back on, or don't remove it and instead removeClass('specificClass') for each past/present/future $(elt).addClass("description"); });
En tu código, nunca eliminas las clases, solo sigues agregándolas. Es plausible que haya asignado las clases correctas a sus elementos, pero dado que nunca eliminó las clases incorrectas (¡o todos los elementos tienen todas las clases!), CSS tuvo que elegir qué color anula las otras bases en prioridad interna.
No desea ninguna ambigüedad: cada elemento debe tener solo la clase 1 que necesita, por lo que la llamada .removeClass() sin parámetro eliminará todas las clases antes de que vuelva a agregar la deseada.
El HTML no se publicó, así que utilicé las etiquetas más apropiadas: <table>
y sus etiquetas para niños. Simplemente reúna todos los <th>
en una matriz, luego itere a través de ellos y la devolución de llamada es solo una declaración de control de flujo if/if else
para determinar la asignación de className
. La hora estaba determinada por el tiempo real.
let t = new Date() let hour = t.getHours(); const cols = [...document.querySelectorAll('th')]; cols.forEach(h => h.className = ''); cols.forEach((h, i) => { if (i + 9 < hour) { h.className = 'past'; } else if (i + 9 > hour) { h.className = 'future'; } else { h.className = 'present'; } });
.past { background: grey } .future { background: green } .present { background: red }
<table> <thead> <tr> <th>9AM</th> <th>10AM</th> <th>11AM</th> <th>12PM</th> <th>1PM</th> <th>2PM</th> <th>3PM</th> <th>4PM</th> <th>5PM</th> </tr> </thead> <tbody> <tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table>