My latest countdown program

I frequently find myself needing to set a 'countdown timer'-type of thing on my computer. A typical use for it is to remind myself that I need to stop working and go do something - otherwise I'll be too focused to notice the passage of time.

So, I've written short programs for myself to set up reminders. Many times. I've written them in Visual C++, Borland Delphi, C# with WinForms, C# with WPF. And those are the ones I can bring to mind right now - functionality is very simple, so I often don't mind writing one in 10' if I don't have it on the machine on which I'm working.

My latest version, however, was written at home, before I installed Visual Studio. What could I possibly use, you might ask? Well if you don't know about HTML Applications (HTAs for short), you're in for a treat.

Just save this to a file with a ".hta" extension, using notepad if you want, double-click, and enjoy! (minimal error handling on this version, though)

<html>
<head>
<HTA:APPLICATION
    INNERBORDER='no'
    />
<title>Countdown</title>
<style>
body {
    font-family: Verdana;
    font-size: 10pt;
}

h1 {
    font-family: Trebuchet;
    font-size: 14pt;
}

input {
    font-family: Consolas;
    font-size: 10pt;
}
</style>
<script>

var countdownTimerId = 0;
var countdownRunning = false;
var countdownTimeTargetMs = 0;

function TimeStringToSeconds(text) {
  var segments = text.split(":");
  var result = 0;
  result += new Number(segments[segments.length-1]);
  if (segments.length > 1) {
    result += 60 * new Number(segments[segments.length-2]);
    if (segments.length > 2) {
      result += 60 * 60 * new Number(segments[segments.length-3]);
    }
  }
  return result;
}

function SecondsToTimeString(seconds) {
  var minutes = Math.floor(seconds / 60);
  seconds -= minutes * 60;
  var hours = Math.floor(minutes / 60);
  minutes -= hours * 60;
  return hours + ":" + minutes + ":" + seconds;
}

function Say(text) {
  var voice = new ActiveXObject("SAPI.SpVoice");
  try {
    voice.Speak(text);
  }
  catch (e) {
    // See https://msdn2.microsoft.com/en-us/library/ms717306.aspx for error codes.
    // SPERR_DEVICE_BUSY 0x80045006 -2147201018
    if (e.number == -2147201018) {
      alert("The wave device is busy - Happens sometimes over Terminal Services.");
    }
  }
}

function TimerClick() {
  var currentTimeMs = new Date().valueOf();
  var remainingMs = countdownTimeTargetMs - currentTimeMs;
  if (remainingMs <= 0) {
    CountdownFinished();
    SetStatusHtml("Countdown complete.");
    Say("Countdown complete");
  } else {
    var remainingSeconds = Math.round(remainingMs / 1000);
    SetStatusHtml("Time left: " + SecondsToTimeString(remainingSeconds));
  }
}

function SetStatusHtml(htmlText) {
  document.getElementById("statusDiv").innerHTML = htmlText;
}

function CountdownFinished() {
  window.clearInterval(countdownTimerId);
  countdownTimerId = 0;
  countdownRunning = false;
  countdownTimeTargetMs = 0;
  SetButtonCaption("Start");
}

function SetButtonCaption(text) {
  var button = document.getElementById("startButton");
  button.value = text;
}

function StartClicked() {
  if (countdownRunning) {
    CountdownFinished();
    SetStatusHtml("Countdown stopped.");
  } else {
    var text = document.getElementById("CountdownTimeBox").value;
    var secondsDelta;
    try {
      secondsDelta = TimeStringToSeconds(text);
    } catch (err) {
      alert(err.message);
      return;
    }
      
    SetButtonCaption("Stop");
    countdownTimeTargetMs = new Date().valueOf() + secondsDelta * 1000;
    countdownTimerId = window.setInterval(TimerClick, 1000);
    countdownRunning = true;
    TimerClick();
  }
}

// Startup size.
window.resizeTo(300, 200);

</script>
</head>
<body>
<h1>Countdown</h1>
<div>Enter the countdown time.</div>
<div>
<input type='text' name='CountdownTimeBox' value='00:00:05' />
<input type='button' name='StartButton' value='Start'
 onclick='StartClicked()' style='width: 40pt;'/>
</div>
<div id='statusDiv'></div>
</body>
</html>

Enjoy!

PS: oh, I had written something like this using JavaScript as well, for my Windows Vista Sidebar. Just remembered as I was finishing this post.