Christian Heilmann

Building an advent calendar for Mozilla in PHP/JS/CSS (part 1)

Tuesday, November 29th, 2011 at 12:27 am
Note: the server is defunct at the moment but you can get the source code of the calendar on GitHub: code and zip

Yesterday morning I got inspired to have a go at building an advent calendar for the Mozilla Developer Network where we are going to have a daily link for you. Here’s my work log on how I did it. Maybe it is inspirational for you, maybe not. Let’s just have a go.

Step 1: Distributing the 24 “doors” on a massive logo

This was simple. I put the logo as a background into an element with the right dimensions and positioned that one relative. I then wrote a wee script to position 24 list items with the correct links randomly on the “canvas”:

<?php 
echo '<ol>';
$width = 700;
$height = 800;
for ($i=0;$i<24;$i++) {
  $x = rand(10,$width-10);
  $y = rand(10,$width-10);
  echo '<li style="left:'.$x.'px;top:'.$y.'px">'.
          '<a href="index.php?day='.($i+1).'">'.($i+1).'</a>'.
       '</li>';
}
echo '</ol>';
?>

I gave the list items a size and positioned them absolutely and then looked at the results. I reloaded until not many overlapped, moved those by hand, grabbed the innerHTML of the list in Firebug and I had my awesome calendar layout. :)

See it here: http://isithackday.com/calendar-tutorial/random.php

Step 2: Build the API

The next step was to build the API to display the when you click on one of the links. This I build as a dummy, too. It is pretty simple, really.

<?php
  $data = '';
  $day = 0;
  $day = +$_GET['day'];
  if ($day > 24) { $day = 24; }
 
  if ($day) {
    $data .= '<h1><a href="#">Title '.$day.'</a></h1>'.
             '<p>Description</p>'.
             '<p>See it in action <a href="#">here</a></p>';
  }
?>

I cast the day URL parameter to an integer and make sure that it can’t be more than 24. If there was a valid number sent in, I assemble a string of HTML with the output data to show for the day. As $day is preset as 0 and will be 0 when the data sent in is not a valid number, $data will be empty.

In the page I then create an element and conditionally write the content out:

All I need to make this work as an advent calendar later on is add a date validation in there.

<?php 
if (+date('m') < 12 || $day > +date('d')) {
  $day = 0;
}
?>

For now, I commented that out, though.

See it in action here: http://isithackday.com/calendar-tutorial/dummyapi.php

Step 3: Ajaxify

This all works now, but to make it slicker, let’s load the content via Ajax when possible. The first step there was to define the article element as the output container and use event delegation to find out which list element was clicked:

var list = document.querySelector('ol'),
    output = document.querySelector('article');
 
list.addEventListener('click', function(ev) {
  var t = ev.target;
  if (t.tagName ==='A') {
    load(+t.innerHTML);
  }
  ev.preventDefault();
}, false);
 
function load(day) {
  alert(day);
}

I then moved the dummy api out to an own file (simpleapi) and added a check for another parameter:

<?php
  $data = '';
  $day = 0;
  $day = +$_GET['day'];
  if ($day > +date('d')) {
    $day = 0;
  }
  if ($day > 24) { $day = 24; }
 
  if ($day) {
    $data .= '<h1><a href="#">Title '.$day.'</a></h1>'.
             '<p>Description</p>'.
             '<p>See it in action <a href="#">here</a></p>';
  }
  if (isset($_GET['ajax'])) { echo $data; }
?>

That way I only had to do a classic Ajax call adding a new parameter to the url to trigger the echo in the PHP:

function load(day) {
  var httpstats = /200|304/;
  var request = new XMLHttpRequest();
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      if (request.status && httpstats.test(request.status)) {
        output.innerHTML = request.responseText;
      } else {
        document.location = 'index.php?day=' + day;
      }
    }
  };
  request.open('get', 'simpleapi.php?ajax=1&day='+day, true);
  request.setRequestHeader('If-Modified-Since',
                           'Wed, 05 Apr 2006 00:00:00 GMT');
  request.send(null);  
}

If you wonder about the date in the request header, yes I did indeed rip my own code from my 2006 Ajax book. :)

http://isithackday.com/calendar-tutorial/ajax.php

That’s all for today

That is the main functionality, really. In part 2 I will then show you how to pull the real data off the web and make this look much sexier, as shown here:

Tags: ,

Share on Mastodon (needs instance)

Share on Twitter

My other work: