Automatically Set Your CSS Clock with Javascript

PR0 Challenge 7.4 [60pts]

Adapted from CSS Animation at cssanimation.rocks


So, you’ve got a clock from the previous challenge. That’s awesome, but does it tick? The first step towards animation will be automatically setting the clock hand angles.

In this challenge we’ll automatically set the clock using javascript, the coding language behind all the mechanics of the web.


STEP 1: Find Your Clock Thimble

Start by finding your Thimble Project from the previous challenge. If you did not complete the "Assemble a CSS Clock" challenge, make sure to do that firs. To find your project:

Visit thimble.mozilla.org
Log in to Webmaker (top-right corner)
Click on your username (top-right) to reveal a drop-down menu, select:     Your Projects  
Find the project you named "Your Name's CSS Clock" from the list;

Your clock should look like this:



You should also have these basic files in your Thimble project:

  1. index.html
  2. style.css
  3. ios_clock.svg

We'll be spending most of our time in this challenge hacking style.css.

STEP 2: Add a Javascript File

Begin by creating a new Javascript (JS) file in Thimble; click the "+" button on the top-left of the screen. Rename your JS file to be set-hr.js. We will use this first file to set the hour hand!

Delete all of the the current, auto-generated code that is in your set-hr.js file and replace it with the following code:

/*
 * Starts any clocks using the user's local time
 * From: cssanimation.rocks/clocks
 * Modified by: http://hackshop.org
 */
function setHr() {
  // Get the local time using JS
  var date = new Date;
  var seconds = date.getSeconds();
  var minutes = date.getMinutes();
  var hours = date.getHours();

  // Create variable with hour hand angle in degrees
  var angle = 30 * ( (hours) + (minutes / 60) + (seconds / 360) );

  // set the angle of hour hand element
  var elements = document.querySelectorAll('.hours');
  for (var k = 0; k < elements.length; k++) {
    elements[k].style.webkitTransform = 'rotateZ('+ angle +'deg)';
    elements[k].style.transform = 'rotateZ('+ angle +'deg)';
  }
}

Lets take a quick look at this code's most important lines in the next step.

STEP 3: The setHr Function

The set-hr.js file we created in the last step does some important work for our clock, so let's take a closer look at it.

The first important line of code in the file is function setHr() {...} that wraps up all the other code (i.e. the ...). This line defines a new function "setHr" which we will be using in the next step.

Next we have this block of code:

  var date = new Date;
  var seconds = date.getSeconds();
  var minutes = date.getMinutes();
  var hours = date.getHours();

This piece of the code does a couple of things. First, it defines new variables using the var command; these variables are date, seconds, minutes, and hours. Next, it sets date to be new Date;, which uses some javascript to retrieve the current date from the server where this code is running. It's a clock we can trust! Finally, it pulls out the specific parts of the date we need using getSeconds(); and the equivalent for minutes and hours.

Great, now we have the current date broken up into pieces. Why? Because we're going to use those pieces to calculate the decimal time and convert it into an angle! Remember that? So then, does this line of math look familiar to you?

  var angle = 30 * ( (hours) + (minutes / 60) + (seconds / 360) );

It should because it's the h-angle from the previous challenge. OK then, wrapping things up, we've got a bit of a mess left:

  var elements = document.querySelectorAll('.hours');
  for (var k = 0; k < elements.length; k++) {
    elements[k].style.webkitTransform = 'rotateZ('+ angle +'deg)';
    elements[k].style.transform = 'rotateZ('+ angle +'deg)';
  }

You can see some more familiar stuff here. Do you notice the .hours bit in there? What about the 'rotateZ('+ angle +'deg)';, remember that? Basically, this section is modifying the CSS code from your style sheet. It finds the .hours class you created and changes the value of the rotateZ() function to change the angle of the hour hand using the angle variable that we calculated here.

So the setHr() function sets the h-angle for the current hour! That's hand dandy, isn't it?

STEP 4: Use the setHr Function

Creating the JS file does not automatically execute the JS functions within it. In order to actually use the code, you need to call the functions somewhere in your webpage. You can make a function run when a button is clicked in your page, when something is entered into a field, or even just simply when the page is first loaded. We're going to do that for simplicity.

The first step is to make sure that the set-hr.js file is included in your clock page. We need to add the following line to the <head> section of the page:

  <script src="set-hr.js"></script>

this line can go right after the line that loads your style sheet, for example:

  <link rel="stylesheet" href="style.css">
  <script src="set-hr.js"></script>

That tells the page to find the JS file and use whatever is in it, but again, only when you tell it to. In order to make sure that the function setHr is used, we'll need to call it "onload". Find the <body> section of your clock page and add the attribute onload="setHr()" to the opening tag. It should look like this:

  <body onload="setHr()">

Did you notice anything happen when you did that? Try refreshing the web page preview. Where is the hour hand? Is it in the correct position?

STEP 5: Set Minutes and Hours too

Got the hang of it? Let's practice by creating two new functions to set the seconds and minutes too. Here's what you'll need to do:

  1. Create two new JS files: set-min.js and set-sec.js;
  2. Copy/paste the set-hr.js code into these new files;
  3. Rename these functions to be setMin() and setSec()
  4. Change the angle calculation in each JS file to be correct for minutes and seconds, not hours;
  5. Replace '.hours' class in the document.querySelectorAll('.hours'); to be '.minutes' or '.seconds'
  6. Make sure to include the new JS files in the <head> of your clock page using <script>

Once you've done all that, the last step is to add those functions to the onload attribute in <body>. NOTE that the functions should be separated by commas and it should look like this:

  <body onload="setHr(), setMin(), setSec()">

Make sure to refresh your clock preview in order to see the functions go to work! Keep clicking refresh to see the second hand move around too.