Home > Software engineering >  How to avoid overwriting variables value through new execution by setInterval
How to avoid overwriting variables value through new execution by setInterval

Time:09-08

I am coding a digital clock. The seconds in the clock should be hideable witch clicking on button if the user wants this. When I am clicking on the button seconds will be hide but only until the next second is in turn. If the next second is elapsed the users preferences are unintentionally setted to default.

let currentDate = new Date();
//assigning function above to a variable
let formattedDate = displayTime(currentDate);

//new time will be displayed every second
setInterval(() => {
  currentDate = new Date();
  formattedDate = displayTime(currentDate);

  formattedDate;
}, 1000);

function displayTime(dataObject) {
  const disDate = document.getElementById("date-elements");
  const disTime = document.getElementById("time-elements");

  //time-objects
  const parts = {
    //date elements:
    weekday: dataObject.getDay(),
    daysNumber: dataObject.getDate(),
    month: dataObject.getMonth()   1,
    year: dataObject.getFullYear(),
    //time elements:
    hours: dataObject.getHours(),
    minutes: dataObject.getMinutes(),
    seconds: dataObject.getSeconds(),
  };

  //adding "PM" or "AM" respectively depending on days time
  const formatAMPM = parts.hours >= 12 ? "PM" : "AM";
  const dayState = formatAMPM;
  parts.hours = parts.hours % 12;
  parts.hours ? parts.hours : 12;

  //appending zero if smaller than 10
  const dysNmbr =
    parts.daysNumber < 10 ? "0"   parts.daysNumber : parts.daysNumber;
  const mnth = parts.month < 10 ? "0"   parts.month : parts.month;

  const hrs = parts.hours < 10 ? "0"   parts.hours : parts.hours;
  const mins = parts.minutes < 10 ? "0"   parts.minutes : parts.minutes;
  const secs = parts.seconds < 10 ? "0"   parts.seconds : parts.seconds;

  //array of weekdays names
  const days = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];

  //determine the weekday
  const currentDayName = days[parts.weekday];

  //displayed elements
  disDate.innerHTML = `${currentDayName}, ${dysNmbr}/${mnth}/${parts.year}`;
  disTime.innerHTML = `${hrs} : ${mins} : ${secs} ${dayState}`;

  //hide and show seconds depending on users preferences
  let i = true;
  const btn = document.getElementById("btn");
  //if button is clicked
  btn.addEventListener("click", () => {
    if (i) {
      //hiding seconds
      disTime.innerHTML = `${hrs} : ${mins} ${dayState}`;
      btn.innerHTML = "Display Seconds";
      i = false;
    } else {
      //displaying seconds
      disTime.innerHTML = `${hrs} : ${mins} : ${secs} ${dayState}`;
      btn.innerHTML = "Hide Seconds";
      i = true;
    }
  });
}
<div id="date-elements"></div>
<div id="time-elements"></div>
<button id="btn">Hide seconds</button>

CodePudding user response:

Putting btn.addEventListener("click"... inside the displayTime function causes the event listener handler to be added each time setInterval fires, therefore resetting the time display to its default state, which is displaying the seconds.

You're also writing the date and time information to the page twice each time the button is clicked. Does not contribute to the error but is unnecessary.

There are number of ways to make this work. In this case the seconds display is wrapped in a span tag:

`${hrs} : ${mins} <span ": "hideme"}">: ${secs}</span> ${dayState}`

...and the (now global) i variable is used to include (or not) a CSS selector that hides the seconds:

${(i)? "": "hideme"}

This is the Javascript ternary operator—it's a short way to write an if..else statement.

//hide and show seconds depending on users preferences
let i = true;
const btn = document.getElementById("btn");
//if button is clicked
btn.addEventListener("click", () => {
  if (i) {
    btn.innerHTML = "Display Seconds";
    i = false;
  } else {
    btn.innerHTML = "Hide Seconds";
    i = true;
  }
});

let currentDate = new Date();
//assigning function above to a variable
let formattedDate = displayTime(currentDate);

//new time will be displayed every second
setInterval(() => {
  currentDate = new Date();
  formattedDate = displayTime(currentDate);
}, 10);


function displayTime(dataObject) {
  const disDate = document.getElementById("date-elements");
  disTime = document.getElementById("time-elements");

  //time-objects
  parts = {
    //date elements:
    weekday: dataObject.getDay(),
    daysNumber: dataObject.getDate(),
    month: dataObject.getMonth()   1,
    year: dataObject.getFullYear(),
    //time elements:
    hours: dataObject.getHours(),
    minutes: dataObject.getMinutes(),
    seconds: dataObject.getSeconds(),
  };

  //adding "PM" or "AM" respectively depending on days time
  formatAMPM = parts.hours >= 12 ? "PM" : "AM";
  dayState = formatAMPM;
  parts.hours = parts.hours % 12;
  parts.hours ? parts.hours : 12;

  //appending zero if smaller than 10
  dysNmbr = parts.daysNumber < 10 ? "0"   parts.daysNumber : parts.daysNumber;
  mnth = parts.month < 10 ? "0"   parts.month : parts.month;

  hrs = parts.hours < 10 ? "0"   parts.hours : parts.hours;
  mins = parts.minutes < 10 ? "0"   parts.minutes : parts.minutes;
  secs = parts.seconds < 10 ? "0"   parts.seconds : parts.seconds;

  //array of weekdays names
  days = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];

  //determine the weekday
  currentDayName = days[parts.weekday];

  //displayed elements
  disDate.innerHTML = `${currentDayName}, ${dysNmbr}/${mnth}/${parts.year}`;
  disTime.innerHTML = `${hrs} : ${mins} <span ": "hideme"}">: ${secs}</span> ${dayState}`;
}
.hideme {
  display: none;
}
<div id="date-elements"></div>
<div id="time-elements"></div>
<button id="btn">Hide seconds</button>

CodePudding user response:

I think i found your problem...

  //displayed elements
  disDate.innerHTML = `${currentDayName}, ${dysNmbr}/${mnth}${parts.year}`;
  disTime.innerHTML = `${hrs} : ${mins} : ${secs} ${dayState}`;

here.

You are setting the innerHtml to display the default format with second, and since displayTime() is called every second it just overwrites the innerHtml set in

  //hiding seconds
  disTime.innerHTML = `${hrs} : ${mins} ${dayState}`;

You could do something like this:

let currentDate = new Date();
// declare hide-seconds preference flag outside of the loop.
let hideSeconds = false;
//assigning function above to a variable
let formattedDate = displayTime(currentDate);

//new time will be displayed every second
setInterval(() => {
  currentDate = new Date();
  formattedDate = displayTime(currentDate);

  formattedDate;
}, 1000);

//The main clock loop
function displayTime(dataObject) {
  const disDate = document.getElementById("date-elements");
  const disTime = document.getElementById("time-elements");

 //...

  //displayed elements depending on user preferences
  disDate.innerHTML = `${currentDayName}, ${dysNmbr}/${mnth}${parts.year}`;
  if(hideSeconds) {
    disTime.innerHTML = `${hrs} : ${mins} ${dayState}`;
  }else {
    disTime.innerHTML = `${hrs} : ${mins} : ${secs} ${dayState}`;
  }
  

  //set the hideSeconds flag depending on users preferences
  const btn = document.getElementById("btn");
  //if button is clicked
  btn.addEventListener("click", () => {
    if (!hideSeconds) {
      //hiding seconds
      btn.innerHTML = "Display Seconds";
      hideSeconds = true;
      disTime.innerHTML = `${hrs} : ${mins} ${dayState}`;
    } else {
      //displaying seconds
      btn.innerHTML = "Hide Seconds";
      hideSeconds = false;
      disTime.innerHTML = `${hrs} : ${mins} : ${secs} ${dayState}`;
    }
  });
}
  • Related