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}`;
}
});
}