Estoy usando luxon para obtener información de diferentes zonas horarias.
Cuando el mouse está sobre un div de contenido, debe mostrar la hora actual de una ciudad y cuando se llama onmouseout, mostrar el nombre de la ciudad nuevamente.
Pero de alguna manera setInterval no funciona con la función onmouseover, solo permanece con la información de tiempo detenido.
Lo que quiero hacer son relojes en tiempo real que puedan ejecutarse cuando paso el mouse sobre el nombre de cada ciudad. ¿Cómo puedo hacer que funcione?
Ejemplo de código:
const one = document.querySelector(".div1 div div"); const timezone = one.getAttribute("data-timezone"); const now = luxon.DateTime.now().setZone(timezone); const city = one.getAttribute("data-city"); const time = setInterval(updateTimes(), 1000); function updateTimes() { one.onmouseover = function() { one.innerHTML = now.toFormat("LLL dd HH:mm:ss"); }; } const stoptime = clearInterval(stopTimes(), 1000); function stopTimes() { one.onmouseout = function() { one.innerHTML = city; }; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.3.2/luxon.min.js"></script> <div class="div1 content"> <div class="wrap"> <div data-city="New York" data-timezone="America/New_Yrok">New York</div> </div> </div>
Esto llama a updateTimes
tras la ejecución y establece lo que devuelve como su callback function
de llamada.
const time = setInterval(updateTimes(), 1000);
Este es el primer error. Quieres pasarlo así:
const time = setInterval(updateTimes, 1000);
Por lo tanto, no ejecuta la función y pasa lo que devuelve, sino que pasa la función en sí.
clearInterval
no toma una función sino una identificación de intervalo. setInterval
devuelve esa identificación, por lo que para borrar el intervalo debe guardar la identificación del intervalo y usarla como el primer argumento de la siguiente manera:
const time = setInterval(updateTimes, 1000); clearInterval(time);
También solo tiene un parámetro de entrada.
Pero no desea borrar el intervalo de inmediato porque entonces no se llamaría en absoluto.
Así que echemos un vistazo a la función updateTimes y veamos qué hace. Establece un nuevo detector de eventos para el evento mouseover. Esto debería funcionar, pero en su lugar debe intentar mantener la lógica en el detector de eventos.
Esta es mi solución:
const one = document.querySelector(".div1 div div"); const timezone = one.getAttribute("data-timezone"); let now = luxon.DateTime.now().setZone(timezone); const city = one.getAttribute("data-city"); let interval = null; // we set the interval here if it is already set we clear the previous interval // mouseenter is only called once when we enter mouseover gets called everytime we move our mouse and it is inside the element one.addEventListener("mouseenter", () => { if (interval) clearInterval(interval); // we save the interval id to clear it later interval = setInterval(() => { // Here we update the time and text now = luxon.DateTime.now().setZone(timezone); one.innerHTML = now.toFormat("LLL dd HH:mm:ss"); }, 1000); // we do it again once so we don't have to wait for one second the first time now = luxon.DateTime.now().setZone(timezone); one.innerHTML = now.toFormat("LLL dd HH:mm:ss"); }); // Here we clear the interval // mouseleave so we only ever clear when the mouse moves out of the element one.addEventListener("mouseleave", () => { // when we leave and the inteval is set we clear it if (interval) { clearInterval(interval); interval = null; } // and reset the text one.innerHTML = city; });
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.3.2/luxon.min.js"></script> <div class="div1 content"> <div class="wrap"> <!-- There was a typo in data-timezone="America/New_Yrok" --> <div data-city="New York" data-timezone="America/New_York">New York</div> </div> </div>