Creating a countdown timer clock is a fairly common task, and often used in timed promotions. There’s a lot of solutions on the internet and even on these forums. I wanted to try creating one that would give content creators a lot of flexibility with the goal being able to use your own styling on the various time components.
Here’s my solution for a flexible countdown timer. You can see it in action with this document:
FlexibleCountdownTimer.hype.zip (65.8 KB)
First, copy this code to the Head HTML:
<script>
// replace the string value with the end date you want for the countdown timer
// this is an ISO 8601 string, like: YYYY-MM-DD(T)HH:MM:SS(+/-)TZD
var countDownDateString = "2017-05-15T00:00:00-08:00";
function updateCountdownClocks() {
// some code from:
// https://www.w3schools.com/howto/howto_js_countdown.asp
// http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
var targetTimeInterval = new Date(countDownDateString).getTime();
var currentTimeInterval = new Date().getTime();
var deltaTimeInterval = targetTimeInterval - currentTimeInterval;
if(deltaTimeInterval < 0) {
// do special handling when timer is expired; default is to just set it to 0
deltaTimeInterval = 0;
}
var timeComponents = {
"days" : Math.floor(deltaTimeInterval / (1000 * 60 * 60 * 24)),
"hours" : Math.floor((deltaTimeInterval % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
"minutes" : Math.floor((deltaTimeInterval % (1000 * 60 * 60)) / (1000 * 60)),
"seconds" : Math.floor((deltaTimeInterval % (1000 * 60)) / 1000),
};
// utility function to add leading 0's
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
// utility function that gets the requested padding of zeros from a class name
// of the format countdown_format_N where 'N' is an integer for the
// total width (ie 3 would be 088 008 888 8888)
function determinePadding(element) {
var matches = element.className.match(/countdown\_format\_([\d]+)/);
if(matches == null || matches.length != 2) {
return 0;
}
return Math.max(0, parseInt(matches[1]));
}
// for each component, try to find a matching class name that wants to be filled in
for(var timeComponentKey in timeComponents) {
if(timeComponents.hasOwnProperty(timeComponentKey) == false) {
continue;
}
var timeValue = timeComponents[timeComponentKey];
var timeElements = document.getElementsByClassName("countdown_" + timeComponentKey);
for(var i = 0; i < timeElements.length; i++) {
var timeElement = timeElements[i];
var padding = determinePadding(timeElement);
timeElement.innerHTML = pad(timeValue, padding);
}
}
// repeat every second
window.setTimeout(updateCountdownClocks, 1000);
}
// start after document has loaded (without use of handlers)
window.setTimeout(updateCountdownClocks, 0);
// use a Hype scene load handler to start:
if("HYPE_eventListeners" in window === false) {
window.HYPE_eventListeners = Array();
}
window.HYPE_eventListeners.push({"type":"HypeSceneLoad", "callback":updateCountdownClocks});
</script>
In the above paste, you’ll want to change this line to reflect the date you are counting down to:
var countDownDateString = "2017-05-15T00:00:00-08:00";
You don’t need to modify anything else in the JavaScript code.
The way the countdown timer works is that it will replace the inner HTML of elements with these class names to their various values: countdown_days
, countdown_hours
, countdown_minutes
, and countdown_seconds
. So what you can do is make text elements in Hype and set the Class Name value in the Identity Inspector to each of these.
A common formatting problem with time is whether or not to display leading zeros. If you append another class name of countdown_format_2
then the value will always display two or more digits (in fact, you can use any number as the class name, so you could use countdown_format_3
for something like the countdown_days
if you wanted). So a full Class Name might look like:
Because this just operates on class names, you don’t necessarily need to break out each component into a separate Hype element. It can also look into the inner HTML of a single element. So if you wanted to construct a timer that looked like “0d 0h 00m 00s”, you would set the Inner HTML of the element to this code:
<span class="countdown_days">0</span>d
<span class="countdown_hours">0</span>h
<span class="countdown_minutes countdown_format_2">00</span>m
<span class="countdown_seconds countdown_format_2">00</span>s
The code itself doesn’t really have any Hype dependencies, so you could even use it on non-Hype projects if you wanted, but hopefully the way this was put together will be useful when using Hype for countdown timers!
P.S. There are some items this countdown timer doesn’t handle:
- When the countdown is done, the value is simply 0
- There’s no way to represent other date values, like weeks or months
- While you can have as many different views on the countdown date as you want, there can only be one date per document/html page.