DANA
DANA

Reputation: 11

setInterval doesn’t work with onmouseover

I'm using luxon to get some different timezones' information.

When mouse is over on a content div, it has to show the present time of a city and when onmouseout is called, show the city's name again.

But somehow setInterval doesn’t work with onmouseover function, just it stays with stopped time information.

What I want to make is real time clocks that can run when I mouse over on each city name. How can I make it work?

Code Sample:

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>

Upvotes: 1

Views: 222

Answers (1)

Nico Kr&#228;tschmer
Nico Kr&#228;tschmer

Reputation: 156

This calls updateTimes upon execution and sets what it returns as its callback function.

const time = setInterval(updateTimes(), 1000);

This is the first error. You want to pass it like this:

const time = setInterval(updateTimes, 1000);

So you don't execute the function and pass what it returns, but pass the function itself.

clearInterval doesn't take a function but an interval id. setInterval returns that id so to clear the interval you have to save the interval id and use that as the first argument like so:

const time = setInterval(updateTimes, 1000);
clearInterval(time);

It also only has one input parameter.

But you don't want to clear the interval right away because then it wouldn't be called at all.

So let's look at the updateTimes function and see what it does. It sets a new event listener for the mouseover event. This should work but instead you should try to keep the logic in the event listener.

This is my solution:

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>

Upvotes: 2

Related Questions