Count down timer

Hello ! I coded a timer custom widget , the problem is when ever I change the step the timer reset and stop , I want the timer to be visible for the user and the user also can set the amount of time and be able to pause it ,stop it and If the user did not stop it it will continue counting.
The timer that already with Tulip does not stop when it reach Zero , is there any solution for that !

Hi @abeer.garman,
did you try putting your Widget to the Base Layout of the app?
On steps where you dont want so see the Timer (but want it to still count) you can drag it out of the viewport.

I’m curious if that would work…

@abeer.garman, in addition to @thorsten.langner’s suggestion to put the widget on the base layout, if you’re comfortable sharing the code someone may be able to help you debug

Hmm , but the time value is from inside the widget , and all the other options

const startBtn       = document.getElementById('start');
const pauseBtn       = document.getElementById('pause');
const stopBtn        = document.getElementById('stop');
const timerValue     = document.getElementById('timerValue');
const thresholdValue = document.getElementById('thresholdValue');
 

const countdownContainer = document.getElementById('countdown');
const hours = document.getElementById('hours');
const mins  = document.getElementById('mins');
const secs  = document.getElementById('secs');
 
let THRESHOLD = 0;
 

let COUNTDOWN = 0;
let startTime = 0;
let timeElapsed = 0;  // keep track of time elapsed before pause
let timerFn = null;
 

stopBtn.onclick = function(e) {
    e.preventDefault();
    stopTimer();
}
 

startBtn.onclick = function(e) {
    e.preventDefault();
 
   
    COUNTDOWN = parseInt(timerValue.value);
    THRESHOLD = parseInt(thresholdValue.value);
    if (COUNTDOWN > 0) {
        startTime = Math.ceil(Date.now() / 1000) - timeElapsed;  // subtract time elapsed before pause
        timerFn   = setInterval(updateTimer, 1000);
    }
}

pauseBtn.onclick = function(e) {
    e.preventDefault();
    pauseTimer();
}
 
function stopTimer() {
    clearInterval(timerFn);
    timeElapsed = 0;  // reset time elapsed
    setThreshold();
    timerFn = null;
}

function pauseTimer() {
    clearInterval(timerFn);
    timeElapsed = Math.ceil(Date.now() / 1000) - startTime;  // calculate time elapsed before pause
    setThreshold();
    timerFn = null;
}
 
function setThreshold(status) {
    if (status) {
        countdownContainer.classList.add("threshold");
    } else {
        countdownContainer.classList.remove("threshold");
    }
}

function updateTimer() {
  const current = Math.ceil(Date.now() / 1000);
 
  const remaining = COUNTDOWN - current + startTime;
  const timerValues = getTimeValues(remaining);
 
  // ... WITH LEADING 0's
  hours.innerHTML = ('00' + timerValues.hours).substr(-2);
  mins.innerHTML = ('00' + timerValues.mins).substr(-2);
  secs.innerHTML = ('00' + timerValues.secs).substr(-2);
 
  if (remaining <= THRESHOLD) {
      setThreshold(true);
  }
  // CHECK FOR TIMEOUT
  if (remaining <= 0) {
    fireEvent('TIMES UP');
    stopTimer();
  }
}
 
// SECONDS TO TIME VALUES H:M:S
function getTimeValues(referenceTime) {
  const hours = parseInt(referenceTime / 3600);
  const mins = parseInt((referenceTime - hours * 3600) / 60);
  const secs = referenceTime - hours * 3600 - mins * 60;
 
  return {hours, mins, secs};
}

this is the code I used for the timer, any suggestion will be more than welcomed !

@abeer.garman Local variables in a custom widget (eg startTime, endTime) are reset whenever the widget has to be re-rendered, which includes navigating between steps. It would also get reset if the page was refreshed, or the user closed and re-opened the player.

Take a look at how the Stopwatch widget in our library works – we save the current time elapsed in the “Duration” variable so it persists across refreshes.

1 Like