Countdown timer

Paul, I am sorry if I said something that upset you; if I had only known, I could have sent you …
image

On a more serious note, that last bit of code did the trick.

Please know that I value your expertise and truly appreciate your efforts and that you came back to the table.

Thanks!

4 Likes

Paul,

Thank you again!


return {
  total: total,
  minutes: minutes,
  seconds: seconds
}

Paul,

@rpg_digital got this to work in IE11 and when you did your last version, it now is not working in IE11. Was hoping there is an easy fix for this.

Thanks

In the code we have

const [match, minutes, seconds] = time.match(/(\d+).*?(\d+)/);
const countdown = Number(minutes) * 60 + Number(seconds);

It’s a nice feature of ES6+ called destructuring.

time.match returns an array something like

[
  0: full match
  1: minutes captured
  2: seconds captured
]

For it to work in IE11 we need to go back to using indexes

const match = time.match(/(\d+).*?(\d+)/)
const countdown = Number(match[1]) * 60 + Number(match[2])

So if you want it to work in IE11 the full JS should be

function getTimeRemaining (endtime) {
  const total = Date.parse(endtime) - Date.parse(new Date())
  const seconds = Math.floor((total / 1000) % 60)
  const minutes = Math.floor((total / 1000 / 60) % 60)

  return {
    total: total,
    minutes: minutes,
    seconds: seconds
  }
}

function toggleClock () {
  document.querySelector('#clockdiv').classList.add('hide')
  document.querySelector('#clocklink').classList.remove('hide')
}

function initializeClock (id, endtime) {
  const clock = document.getElementById(id)
  const minutesSpan = clock.querySelector('.minutes')
  const secondsSpan = clock.querySelector('.seconds')

  function updateClock () {
    const t = getTimeRemaining(endtime)
    minutesSpan.innerHTML = ('0' + t.minutes).slice(-2)
    secondsSpan.innerHTML = ('0' + t.seconds).slice(-2)

    if (t.total <= 0) {
      clearInterval(timeinterval)
      toggleClock()
    }
  }
  updateClock()
  const timeinterval = setInterval(updateClock, 1000)
}

// const time = "<%=countdown%>";
const time = '11 minutes - 24 seconds'
const match = time.match(/(\d+).*?(\d+)/)
const countdown = Number(match[1]) * 60 + Number(match[2])


document.querySelector('#clocklink').classList.add('hide')
const deadline = new Date(Date.parse(new Date()) + countdown * 1000)
initializeClock('clockdiv', deadline)
2 Likes

Very impressive, thank you so much! For me, and perhaps for others, it’s nice to still have code work for IE11 because it’s still used, although fading away slowly. Habits of using a particular browser for users can be hard to break.

Thanks for providing that to me, I really appreciate it. And again, thanks for @Paul_Wilkins help too. Both of you have impressive skills that I wish I had.

Take care!

1 Like

I have updated the codePen code accordingly, so that it forms a good solid base if any further work needs to occur.

2 Likes

Got it figured out - disregard, got the problem that I was having solve,thanks

Paul,

Will the countdown timer continue to work if in the background on a mobile device?

Thank you.

You wouldn’t be able to store the amount of time remaining in a long-term variable. You would need to calculate the amount of remaining time each second of the loop instead, as is done in post #44

That’s very interesting, I am going to evaluate that. And by the way, I have used the timer and like it very much and I really appreciate your efforts on this as well as @rpg_digital. Both very helpful.

Still a little confused on some of my research on mobile devices and if JS can run in background. I read some that say yes and many saying no. Can you clarify if in fact you can effectively run JS in the background and/or when the screen is off (perhaps that’s the same thing)?

Thank you.

1 Like

No, there is no guarantee that it runs in the background.

So if let’s say you have a secure bank site and want to auto logoff after x mins, there is no guarantee that will 100% work in the background?

Also, if you can’t guarantee that it will work in the background, can you guarantee if coded probably, it won’t work? Meaning you don’t want it to continue running once it’s not an active screen?

The client browser is not in charge of that, because you should never trust security to the client browser.

There is no guarantee of that either.

1 Like

Here is a useful article among many about client browser security.

1 Like

Thank you for the informative information. So I suppose you have to program your code in your specific language to accommodate that. Thanks

Is it possible, that at the end of the countdown (00:00), it could trigger an AJAX response so I can send that information to the database? Using something like I do with links clicked, like this:

<script>
    function loadXMLDoc(elementId, endpoint) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                document.getElementById(elementId).innerHTML =
      this.responseText;
            }
        };
        xhttp.open("GET", endpoint, true);
        xhttp.send();
    }
</script>
<h1>Countdown Clock</h1>
<div id="clockdiv">
  <div>
    <span class="minutes"></span>
    <div class="smalltext">Minutes</div>
  </div>
  <div>
    <span class="seconds"></span>
    <div class="smalltext">Seconds</div>
  </div>
</div>
<div id="clocklink">
  <p>Follow <a href="https://www.google.com">this link</a>.</p>
</div>
<div id="clocklink">
  <p>Follow <a href="https://www.google.com">this link</a>.</p>
</div>

With the clocklink, how can you limit this link, once drawn to the page, to x amount of time? Meaning, after that time, it becomes unclickable.

  document.addEventListener('DOMContentLoaded', function(event) {

    window.setTimeout(function(event){
      const clocklink = document.querySelector('#clocklink a')

      // replace the surrounding anchor tag and content e.g. <a>text content</a> 
      // with just the text content
      clocklink.outerHTML = clocklink.textContent
    }, 2000 /* delay here in ms */)
  })

or maybe add a class as well to indicate it has been disabled?

css

.disabled-link {
  text-decoration: line-through;
}

javascript

document.addEventListener('DOMContentLoaded', function(event) {

  window.setTimeout(function(event){
    const clocklink = document.querySelector('#clocklink a')

    clocklink.outerHTML = '<span class="disabled-link">' + clocklink.textContent + '</span>'
  }, 2000 /* delay here in ms */)
})

Another option hide the whole line?

css

.hide {
  animation: hide .5s ease forwards;
}

@keyframes hide {
  from{
    opacity: 1;
    visibility: visible;
  }

  to{
    opacity: 0;
    visibility: hidden;
  }
}

javascript

document.addEventListener('DOMContentLoaded', function(event) {

  window.setTimeout(function(event){
    // this time selected the whole clocklink
    const clocklink = document.querySelector('#clocklink')

    clocklink.classList.add('hide')
  }, 2000 /* delay here in ms */)
})

Thank you for that, now trying to put it together. Not sure which is the best option.

On that code, do I just add it to the existing JS and replace it with this:

document.querySelector('#clocklink').classList.add('hide')

Meaning that line is not needed?

Not sure where you are with your code, but this at the end of your code should do the trick

window.setTimeout(function(event){
  document.querySelector("#clocklink").classList.add("hide");
}, 2000 /* time to disable ms */)
1 Like