Javascript contextual clock

Contextual clock screenshot

Another experiment I did way back to create a contextual clock in html/css/js, originally in jQuery but now updated to vanilla javascript. Source available on Github.

The clock itself is a table of cells containing a single character, each with its own ID. Rows have letters and columns numbers.

<table>  
  <tr>
    <td id='a1'>I</td>
    <td id='a2'>T</td>
    ...

With this we can create the words and numbers as strings of IDs separated by commas. Because arrays are zero indexed I'm explicitly setting the hours so the array key matches the hour (eg. [1] = one):

var itis = "a1,a2,a4,a5";  
var a = "a7";  
var ten = "a9,a10,a11";  
...

var hourwords = new Array();  
hourwords[1] = "d1,d2,d3";  
hourwords[2] = "d4,d5,d6";  
...

Before we update the time it's important to clear the board. To do this we loop through all the <td> elements, ensure each has a numeric key and remove the CSS class 'alight':

function clearBoard(){  
  var alltds = document.getElementsByTagName('td');
  for (var index in alltds) {
    if(!isNaN(parseInt(index, 10)) && alltds[index].classList.contains('alight')){
      alltds[index].classList.remove("alight");
    }
  }
}

To determine which words to light up we create an empty array to hold the words, then use an instance of the Date object to get numerical representations of the hour and the minutes:

var words = new Array();  
var now = new Date();  
var hour = now.getHours();  
var mins = now.getMinutes();  

The following is a little bit of a hacky approach but it avoids complicated if statements. Each case tests which five minute bracket the current minutes falls in and adds the relevant words to our array:

  switch(true){
    case (mins >= 55): words = [five, to]; hour++; break;
    case (mins >= 50): words = [ten, to]; hour++; break;
    case (mins >= 45): words = [quarter, to]; hour++; break;
    case (mins >= 40): words = [twenty, to]; hour++; break;
    case (mins >= 35): words = [twenty, five, to]; hour++; break;
    case (mins >= 30): words = [half, past]; break;
    case (mins >= 25): words = [twenty, five, past]; break;
    case (mins >= 20): words = [twenty, past]; break;
    case (mins >= 15): words = [a, quarter, past]; break;
    case (mins >= 10): words = [ten, past]; break;
    case (mins >= 5):  words = [five, past]; break;
    case (mins < 5):   words = [oclock]; break;
  }

Because Javascript's Date object returns hours in twenty-four hour format we have to do a little maths to change things to twelve hour format.

if(hour > 12){  
  hour = hour - 12;
} else if(hour < 1){ 
  hour = 12; 
}

Now it's just a case of pushing the words 'it is' and the current hour to our words array. Looping through each word then splitting each word by the comma to get each cell ID. With this we can set the class to 'alight'.

words.push(itis, hourwords[hour]); 

words.forEach((word) => {  
  word.split(',').forEach((letter) => {
 document.getElementById(letter).classList.add("alight");
  });
});

To get this all running we fire the showClock() function. To update it we run a function every five seconds to see if the current minutes is a multiple of five and if so, run the showClock() function again.

(function() {
  showClock();
  setInterval(() => {
    if(new Date().getMinutes() % 5 == 0){ 
      showClock();
    }
  }, 5000);
})();

To make the letters glow apply a text-shadow with a light colour against a dark background:

.alight { 
  text-shadow: 0px 0px 12px #ccc; 
  color:       #fff; 
}