0

I created a page with a combination of analog clock and digital clock using JavaScript. I created a button to toggle between the two clocks. I have it so the analog clock works well. When I switch to the digital clock, however, it displays for a second before disappearing. There is no error in the console, and I cannot figure out where I am going wrong.

NOTE: In the code, I have the digital clock hidden when the analog clock displays. I had to do this, because I couldn't get the page to display properly by having the digital clock display first.

Code for my clock is here:

setInterval(setClock, 1000); //Run every 1000 milliseconds = 1 second

const hourHand = document.querySelector("[data-hour-hand]");
const minuteHand = document.querySelector("[data-minute-hand]");
const secondHand = document.querySelector("[data-second-hand]");

function setClock() {
  var currentDate = new Date(); //Gets current date and time
  var secondsRatio = currentDate.getSeconds() / 60;
  // Move minute and hour hands gradually according to seconds and minutes
  var minutesRatio = (secondsRatio + currentDate.getMinutes()) / 60;
  var hoursRatio = (minutesRatio + currentDate.getHours()) / 12;
  setRotation(secondHand, secondsRatio);
  setRotation(minuteHand, minutesRatio);
  setRotation(hourHand, hoursRatio);
  // Setting digital clock to be hidden on page load
  document.getElementById("digital-clock").style.display = "none";
}

function setRotation(element, rotationRatio) {
  // Sets property of element to rotation variable in CSS
  element.style.setProperty("--rotation", rotationRatio * 360);
}

function displayDigitalTime() {
  var currentDate = new Date();
  var hrs = currentDate.getHours();
  var min = currentDate.getMinutes();
  var sec = currentDate.getSeconds();
  var session = document.getElementById("session");

  if (hrs >= 12) {
    session.innerHTML = "PM";
  } else {
    session.innerHTML = "AM";
  }

  // Changes format from 24 hour clock to 12 hour clock
  if (hrs > 12) {
    hrs = hrs - 12;
  }

  // Because minutes and seconds were not getting a padded 0 if the number
  // was less than 10, I have to use an extra if statement for minutes and
  // seconds. I found my answer here:
  // https://www.tutorialspoint.com/How-to-pad-a-number-with-leading-zeros-in-JavaScript

  if (min < 10) {
    let paddedMin = min.toString().padStart(2, "0");
    min = paddedMin;
  }

  if (sec < 10) {
    var paddedSec = sec.toString().padStart(2, "0");
    sec = paddedSec;
  }

  document.getElementById("hours").innerHTML = hrs;
  document.getElementById("minutes").innerHTML = min;
  document.getElementById("seconds").innerHTML = sec;
}

//https://stackoverflow.com/questions/10687479/javascript-replace-div-on-each-click
function toggleClock() {
  var analog = document.getElementById("analog-clock");
  var digital = document.getElementById("digital-clock");
  // If analog clock is not displayed, display it in place of digital clock.
  if (analog.style.display === "none") {
    analog.style.display = "block";
    digital.style.display = "none";
    //https://www.w3schools.com/jsref/prop_html_innerhtml.asp
    document.getElementById("btn").innerHTML =
      "Click me to display digital clock";
  } else {
    // If digital clock is not displayed, display it in place of analog clock.
    analog.style.display = "none";
    digital.style.display = "block";
    setInterval(displayDigitalTime, 10);
    document.getElementById("btn").innerHTML =
      "Click me to display analog clock";
  }
}

setClock(); //Sets clock to current time as soon as page is loaded.
*,
*::before,
*::after {
  box-sizing: border-box;
  font-family: Gotham Rounded, sans-serif;
}

body {
  padding: 0;
  margin: 0;
  /* Originally was background: linear-gradient(to right #00aaff, #00ff6c
    This was not working in Chrome, so I found a solution here: 
    https://stackoverflow.com/questions/26318988/linear-gradient-not-working-in-chrome */
  background: -webkit-gradient(
    linear,
    left top,
    right top,
    /* Colors found in https://flatuicolors.com/palette/nl*/
      color-stop(0%, #f79f1f),
    color-stop(100%, #d980fa)
  );
  /* Move clock to middle of page */
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  /* Remove scrollbar from side */
  overflow: hidden;
}

.clock {
  width: 300px;
  height: 300px;
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 50%; /* Makes square space into circle */
  border: 2px solid black;
  position: relative;
  margin-top: 10px;
}

.clock .number {
  --rotation: 0; /* Variable to be used in transform below */
  position: absolute;
  width: 100%;
  height: 100%;
  text-align: center;
  transform: rotate(var(--rotation)); /* Rotates number according to variable */
  font-size: 1.5rem;
}

.clock .number1 {
  --rotation: 30deg;
}

.clock .number2 {
  --rotation: 60deg;
}

.clock .number3 {
  --rotation: 90deg;
}

.clock .number4 {
  --rotation: 120deg;
}

.clock .number5 {
  --rotation: 150deg;
}

.clock .number6 {
  --rotation: 180deg;
}

.clock .number7 {
  --rotation: 210deg;
}

.clock .number8 {
  --rotation: 240deg;
}

.clock .number9 {
  --rotation: 270deg;
}

.clock .number10 {
  --rotation: 300deg;
}

.clock .number11 {
  --rotation: 330deg;
}

.clock .hand {
  --rotation: 0; /* This will be updated by JavaScript */
  position: absolute;
  bottom: 50%;
  left: 50%;
  border: 1px solid white;
  /* These will transform top of hand to look rounded */
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  background-color: black;
  /* takes rotation from bottom of hand, keeping it in center */
  transform-origin: bottom;
  /* translateX moves the hand back 50%, making it straight with the 12*/
  transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
  /* Making sure hands are always above numbers */
  z-index: 10;
}

.clock::after {
  /* Creates 'pseduo content', which can be styled here in CSS*/
  content: "";
  position: absolute;
  background-color: black;
  /* Ensure that this circle will be above hands on clock */
  z-index: 11;
  width: 15px;
  height: 15px;
  /* Keep this center of clock */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* Make square into circle */
  border-radius: 50%;
}

.clock .hand.second {
  width: 3px;
  height: 45%;
  background-color: red;
}

.clock .hand.minute {
  width: 7px;
  height: 40%;
  background-color: black;
}

.clock .hand.hour {
  width: 10px;
  height: 35%;
  background-color: black;
}

.digital-container {
  font-family: Arial, Helvetica, sans-serif;
  color: blue;
  font-weight: bold;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 70px;
}

/* https://getcssscan.com/css-buttons-examples */
.button-3 {
  appearance: none;
  background-color: #2ea44f;
  border: 1px solid rgba(27, 31, 35, 0.15);
  border-radius: 6px;
  box-shadow: rgba(27, 31, 35, 0.1) 0 1px 0;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  display: inline-block;
  font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial,
    sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  padding: 6px 16px;
  position: absolute;
  top: 15%;
  margin-bottom: 25px;
  text-align: center;
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  vertical-align: middle;
  white-space: nowrap;
}

.button-3:focus:not(:focus-visible):not(.focus-visible) {
  box-shadow: none;
  outline: none;
}

.button-3:hover {
  background-color: #2c974b;
}

.button-3:focus {
  box-shadow: rgba(46, 164, 79, 0.4) 0 0 0 3px;
  outline: none;
}

.button-3:disabled {
  background-color: #94d3a2;
  border-color: rgba(27, 31, 35, 0.1);
  color: rgba(255, 255, 255, 0.8);
  cursor: default;
}

.button-3:active {
  background-color: #298e46;
  box-shadow: rgba(20, 70, 32, 0.2) 0 1px 0 inset;
}
<body>
  <!--<button onclick="hideAnalog()">Click Here</button>-->
  <div class="clock" id="analog-clock">
    <div class="hand hour" data-hour-hand></div>
    <div class="hand minute" data-minute-hand></div>
    <div class="hand second" data-second-hand></div>
    <!-- div.number.number$*12{$}*12 - Shortcut to add this 12 times-->
    <div class="number number1">1</div>
    <div class="number number2">2</div>
    <div class="number number3">3</div>
    <div class="number number4">4</div>
    <div class="number number5">5</div>
    <div class="number number6">6</div>
    <div class="number number7">7</div>
    <div class="number number8">8</div>
    <div class="number number9">9</div>
    <div class="number number10">10</div>
    <div class="number number11">11</div>
    <div class="number number12">12</div>
  </div>
  <div class="digital-container" id="digital-clock">
    <span id="hours"></span>
    <span>:</span>
    <span id="minutes"></span>
    <span>:</span>
    <!-- NOTE: Have to look up 
        https://stackoverflow.com/questions/1267283/how-can-i-pad-a-value-with-leading-zeros 
        for adding a padding zero if seconds is less than 10 -->
    <span id="seconds"></span>
    <span id="session"></span>
  </div>
  <button type="button" class="button-3" id="btn" onclick="toggleClock()">Click me to display digital clock</button>
</body>

</html>

I tried adding the function that calls the digital clock at different parts of my JavaScript code, but nothing I have done changes the fact that the digital clock displays for a second and then disappears.

Wongjn
  • 8,544
  • 2
  • 8
  • 24

1 Answers1

0

It is due to

// Setting digital clock to be hidden on page load
document.getElementById("digital-clock").style.display = "none";

within the setClock() function. The setclock() function runs every second because of the setInterval(setClock, 1000); call. Instead, you could set the digital clock to display: none to have it hidden initially:

#digital-clock {
  display: none;
}

setInterval(setClock, 1000); //Run every 1000 milliseconds = 1 second

const hourHand = document.querySelector("[data-hour-hand]");
const minuteHand = document.querySelector("[data-minute-hand]");
const secondHand = document.querySelector("[data-second-hand]");

function setClock() {
  var currentDate = new Date(); //Gets current date and time
  var secondsRatio = currentDate.getSeconds() / 60;
  // Move minute and hour hands gradually according to seconds and minutes
  var minutesRatio = (secondsRatio + currentDate.getMinutes()) / 60;
  var hoursRatio = (minutesRatio + currentDate.getHours()) / 12;
  setRotation(secondHand, secondsRatio);
  setRotation(minuteHand, minutesRatio);
  setRotation(hourHand, hoursRatio);
}

function setRotation(element, rotationRatio) {
  // Sets property of element to rotation variable in CSS
  element.style.setProperty("--rotation", rotationRatio * 360);
}

function displayDigitalTime() {
  var currentDate = new Date();
  var hrs = currentDate.getHours();
  var min = currentDate.getMinutes();
  var sec = currentDate.getSeconds();
  var session = document.getElementById("session");

  if (hrs >= 12) {
    session.innerHTML = "PM";
  } else {
    session.innerHTML = "AM";
  }

  // Changes format from 24 hour clock to 12 hour clock
  if (hrs > 12) {
    hrs = hrs - 12;
  }

  // Because minutes and seconds were not getting a padded 0 if the number
  // was less than 10, I have to use an extra if statement for minutes and
  // seconds. I found my answer here:
  // https://www.tutorialspoint.com/How-to-pad-a-number-with-leading-zeros-in-JavaScript

  if (min < 10) {
    let paddedMin = min.toString().padStart(2, "0");
    min = paddedMin;
  }

  if (sec < 10) {
    var paddedSec = sec.toString().padStart(2, "0");
    sec = paddedSec;
  }

  document.getElementById("hours").innerHTML = hrs;
  document.getElementById("minutes").innerHTML = min;
  document.getElementById("seconds").innerHTML = sec;
}

//https://stackoverflow.com/questions/10687479/javascript-replace-div-on-each-click
function toggleClock() {
  var analog = document.getElementById("analog-clock");
  var digital = document.getElementById("digital-clock");
  // If analog clock is not displayed, display it in place of digital clock.
  if (analog.style.display === "none") {
    analog.style.display = "block";
    digital.style.display = "none";
    //https://www.w3schools.com/jsref/prop_html_innerhtml.asp
    document.getElementById("btn").innerHTML =
      "Click me to display digital clock";
  } else {
    // If digital clock is not displayed, display it in place of analog clock.
    analog.style.display = "none";
    digital.style.display = "block";
    setInterval(displayDigitalTime, 10);
    document.getElementById("btn").innerHTML =
      "Click me to display analog clock";
  }
}

setClock(); //Sets clock to current time as soon as page is loaded.
*,
*::before,
*::after {
  box-sizing: border-box;
  font-family: Gotham Rounded, sans-serif;
}

body {
  padding: 0;
  margin: 0;
  /* Originally was background: linear-gradient(to right #00aaff, #00ff6c
    This was not working in Chrome, so I found a solution here: 
    https://stackoverflow.com/questions/26318988/linear-gradient-not-working-in-chrome */
  background: -webkit-gradient(
    linear,
    left top,
    right top,
    /* Colors found in https://flatuicolors.com/palette/nl*/
      color-stop(0%, #f79f1f),
    color-stop(100%, #d980fa)
  );
  /* Move clock to middle of page */
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  /* Remove scrollbar from side */
  overflow: hidden;
}

.clock {
  width: 300px;
  height: 300px;
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 50%; /* Makes square space into circle */
  border: 2px solid black;
  position: relative;
  margin-top: 10px;
}

.clock .number {
  --rotation: 0; /* Variable to be used in transform below */
  position: absolute;
  width: 100%;
  height: 100%;
  text-align: center;
  transform: rotate(var(--rotation)); /* Rotates number according to variable */
  font-size: 1.5rem;
}

.clock .number1 {
  --rotation: 30deg;
}

.clock .number2 {
  --rotation: 60deg;
}

.clock .number3 {
  --rotation: 90deg;
}

.clock .number4 {
  --rotation: 120deg;
}

.clock .number5 {
  --rotation: 150deg;
}

.clock .number6 {
  --rotation: 180deg;
}

.clock .number7 {
  --rotation: 210deg;
}

.clock .number8 {
  --rotation: 240deg;
}

.clock .number9 {
  --rotation: 270deg;
}

.clock .number10 {
  --rotation: 300deg;
}

.clock .number11 {
  --rotation: 330deg;
}

.clock .hand {
  --rotation: 0; /* This will be updated by JavaScript */
  position: absolute;
  bottom: 50%;
  left: 50%;
  border: 1px solid white;
  /* These will transform top of hand to look rounded */
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  background-color: black;
  /* takes rotation from bottom of hand, keeping it in center */
  transform-origin: bottom;
  /* translateX moves the hand back 50%, making it straight with the 12*/
  transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
  /* Making sure hands are always above numbers */
  z-index: 10;
}

.clock::after {
  /* Creates 'pseduo content', which can be styled here in CSS*/
  content: "";
  position: absolute;
  background-color: black;
  /* Ensure that this circle will be above hands on clock */
  z-index: 11;
  width: 15px;
  height: 15px;
  /* Keep this center of clock */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* Make square into circle */
  border-radius: 50%;
}

.clock .hand.second {
  width: 3px;
  height: 45%;
  background-color: red;
}

.clock .hand.minute {
  width: 7px;
  height: 40%;
  background-color: black;
}

.clock .hand.hour {
  width: 10px;
  height: 35%;
  background-color: black;
}

.digital-container {
  font-family: Arial, Helvetica, sans-serif;
  color: blue;
  font-weight: bold;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 70px;
}

/* https://getcssscan.com/css-buttons-examples */
.button-3 {
  appearance: none;
  background-color: #2ea44f;
  border: 1px solid rgba(27, 31, 35, 0.15);
  border-radius: 6px;
  box-shadow: rgba(27, 31, 35, 0.1) 0 1px 0;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  display: inline-block;
  font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial,
    sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  padding: 6px 16px;
  position: absolute;
  top: 15%;
  margin-bottom: 25px;
  text-align: center;
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  vertical-align: middle;
  white-space: nowrap;
}

.button-3:focus:not(:focus-visible):not(.focus-visible) {
  box-shadow: none;
  outline: none;
}

.button-3:hover {
  background-color: #2c974b;
}

.button-3:focus {
  box-shadow: rgba(46, 164, 79, 0.4) 0 0 0 3px;
  outline: none;
}

.button-3:disabled {
  background-color: #94d3a2;
  border-color: rgba(27, 31, 35, 0.1);
  color: rgba(255, 255, 255, 0.8);
  cursor: default;
}

.button-3:active {
  background-color: #298e46;
  box-shadow: rgba(20, 70, 32, 0.2) 0 1px 0 inset;
}

#digital-clock {
  display: none;
}
<body>
  <!--<button onclick="hideAnalog()">Click Here</button>-->
  <div class="clock" id="analog-clock">
    <div class="hand hour" data-hour-hand></div>
    <div class="hand minute" data-minute-hand></div>
    <div class="hand second" data-second-hand></div>
    <!-- div.number.number$*12{$}*12 - Shortcut to add this 12 times-->
    <div class="number number1">1</div>
    <div class="number number2">2</div>
    <div class="number number3">3</div>
    <div class="number number4">4</div>
    <div class="number number5">5</div>
    <div class="number number6">6</div>
    <div class="number number7">7</div>
    <div class="number number8">8</div>
    <div class="number number9">9</div>
    <div class="number number10">10</div>
    <div class="number number11">11</div>
    <div class="number number12">12</div>
  </div>
  <div class="digital-container" id="digital-clock">
    <span id="hours"></span>
    <span>:</span>
    <span id="minutes"></span>
    <span>:</span>
    <!-- NOTE: Have to look up 
        https://stackoverflow.com/questions/1267283/how-can-i-pad-a-value-with-leading-zeros 
        for adding a padding zero if seconds is less than 10 -->
    <span id="seconds"></span>
    <span id="session"></span>
  </div>
  <button type="button" class="button-3" id="btn" onclick="toggleClock()">Click me to display digital clock</button>
</body>

</html>
Wongjn
  • 8,544
  • 2
  • 8
  • 24