Christian Heilmann

You are currently browsing the Christian Heilmann blog archives for November, 2011.

Archive for November, 2011

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

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

In Yesterday’s tutorial I went up to making the advent calendar use Ajax to load the different content, now for extra effect I made the entries move to where you clicked the calendar. There is not much more to it and you can see the whole thing in action here.

Step 4: Moving overlays

Now, first of all, instead of showing the entry above the calendar we now cover it, which means we should give the end users a way to get rid of them. this means adding a close link to the entry. As the entry is assembled in the API, this needs to happen there:

<?php
  $data = '';
  $day = 0;
  $day = +$_GET['day'];
  if (+date('m') < 12 || $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>';
  }
 
  $data .= '<p><a href="index.php" id="close">close</a></p>';
 
  if (isset($_GET['ajax'])) { echo $data; }
?>

The link also points back to the page, so if there is no JavaScript available, the page just reloads.

Now, in order to hide and show the entry, I positioned it absolutely and gave it a higher z-index:

article {
  z-index: 10;
  position: absolute;
  top: -400px;
  width: 700px;
  background: #d3caff;
}

This, of course needs to be un-done when there is a day selected. In the case of a no JavaScript version, this needs to be done in the PHP itself. To override the original, I defined a class:

article.show {
  top: 200px;
}

And in the PHP I write out this class when a valid day was sent in:

<article <?php if($day) {echo ' class="show"';} ?>>
   <?php if($day) {echo $data;} ?>
</article>

In order to move the entry to the right height, you need to capture the mouse position when the user clicks one of the links. For this, I modified the event delegation handler to read the y position of the mouse and send it through to the ajax loader:

list.addEventListener('click', function(ev) {
  var t = ev.target;
  if (t.tagName ==='A') {
    var y = ev.clientY + document.body.scrollTop +
            document.documentElement.scrollTop;
    load(+t.innerHTML, y);
  }
  ev.preventDefault();
}, false);

The loading function then does not only change the content of the article element but it also adds the class of “show” to it and modifies its top position to the y parameter it received.

function load(day, y) {
  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;
        output.className = 'show';
        output.style.top = y + 'px';
      } else {
        document.location = 'index.php?day=' + day;
      }
    }
  };
  request.open('get', 'simpleapi-closing.php?ajax=1&day='+day, true);
  request.setRequestHeader('If-Modified-Since',
                           'Wed, 05 Apr 2006 00:00:00 GMT');
  request.send(null);  
}

To make this smooth, all we need to do is add a CSS transition to the element – isn’t it wonderful to work with browsers that don’t suck?

article {
  z-index: 10;
  position: absolute;
  top: -400px;
  width: 700px;
  background: #d3caff;
  -moz-transition: top 1s;
  -webkit-transition: top 1s;
  -ms-transition: top 1s;
  -o-transition: top 1s;
  transition: top 1s;
}

To hide the element again we need to re-set the position and remove the “show” class. This happens in two cases: when the user clicks the close link (we gave it an ID of “close”) and when the user hits the ESC key on the keyboard. For the former we use event delegation on the article element (as its content keeps getting re-written), for the latter a keyboard handler on the document:

output.addEventListener('click',function(ev){
  var t = ev.target;
  if(t.tagName === 'A' && t.id === 'close') {
    output.style.top = '-400px';
    output.className = '';
    ev.preventDefault();
  }
},false);
 
document.addEventListener( 'keydown', function(key) {
   if ( key.keyCode === 27 ) {
     if( output.className === 'show' ) {
       output.style.top = '-400px';
       output.className = '';
     }
   }
 }, false );

That’s it! Smooth entries moving up and down when you click different links.

Step 5: Adding the real content

The final change to make this work was to find a way for people to send me links to show. For this, all I needed to do was create a Google spreadsheet and send it around.

You can publish your spreadsheets on the web using File > Publish to the web > Start Publishing. I chose CSV as the format and then changed the API accordingly.

I load the document in using cURL and then split it into an associative array using the csv_to_array() method by M. Bunge found on the PHP docs for str_getcsv().

I then check if there is an entry for the day and if there isn’t I just give back a “not yet” string. Otherwise I get the data from the associative array and assemble the real string.

<?php
$now = '';
$day = 0;
$data = '';
 
if (isset($_GET['day'])) {
  $day = +($_GET['day']);
  if ($day > 24) { $day = 24; }
  if (+date('m') < 12 || $day > +date('d')) {
    $day = 0;
  }
 
  $url = 'https://docs.google.com/spreadsheet/pub?'.
         'key=0AhphLklK1Ve4dEp5X2tBNHFPM0hQSHpZQnBjYl9NLUE&output=csv';
  $ch = curl_init(); 
  curl_setopt($ch, CURLOPT_URL, $url); 
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  $output = curl_exec($ch); 
  curl_close($ch);
 
  $csvdata = csv_to_array($output);
  $now = $csvdata[($day-1)];
  if ($now) {
    $data .= '<h1><a href="'.$now[0].'">'.$now[1].'</a></h1>'.
             '<p>'.$now[2].'</p>';
    if ($now[3] !== '') {
      $data .= '<p>You can also <a href="'.$now[3].
               '">see it in action here</a>.</p>';
    }
  } else {
    $data .= '<h1><a href="http://developer.mozilla.com">Not yet!</a></h1>'.
             '<p>You have to wait, like all the others.</p>';
  }
}
 
$data .= '<a id="close" href="index.php">x</a>';
 
if (isset($_GET['ajax'])) { echo $data; }
 
function csv_to_array($input, $delimiter=',') {
  $header = null;
  $data = array();
  $csvData = str_getcsv($input, "\n");
  foreach($csvData as $csvLine) {
    if (is_null($header)) {
      $header = explode($delimiter, $csvLine); 
    } else {
      $items = explode($delimiter, $csvLine);
      for($n = 0, $m = count($header); $n < $m; $n++){
        $prepareData[$n] = $items[$n];
      }
      $data[] = $prepareData;
    }
  }
  return $data;
}
?>

And that is that – a simple advent calendar in PHP progressively enhanced with JavaScript and CSS.

See the final functional demo in action at:
http://isithackday.com/calendar-tutorial/realcontent.php

Final tweaks

In the final version I will of course add some caching instead of hitting Google Docs live and I added a lot more CSS to make it look the way I wanted to. But this should get you going.

The Final Build folder has a cleaned up version, with external CSS and JavaScript and a nice (function(){}()); around the JS to stop those global variables.

You can also get the whole project on GitHub

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

Tuesday, November 29th, 2011
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:

All our work should be like Calvin and Hobbes

Saturday, November 26th, 2011

You may not know it, but I am a huge Calvin and Hobbes fan. Not as big as this guy, but big:

Calvin and Hobbes tattoo

The reason to me is that Calvin and Hobbes is full of features that I consider the ingredients of great quality work, and something we should strive to emulate:

  • Simplicity – none of the comics are very complex, there is no depth in the paintings, no 3D shadings with metal effects. A few black and white lines arranged in the right way make the effect
  • Staying in the boundaries – the comic never deviated from the normal format of a few panels with the exception of the Sunday specials which were in colour and full-page or some Christmas specials. This is OK and I never expected it to do anything like that. Staying within standardised boundaries and being beautiful at the same time is harder than breaking the mould all the time.
  • Beautiful details – what makes C&H lovable is the little details – Calvin’s shoes that look like bread rolls, the jumping TV set, Hobbes’ fuzzy belly. All of which are a few lines that are not like you expect them but make you see the effort that went in
  • Delivery vs. money focus – there was never any official Calvin and Hobbes merchandise other than the books. Bill Watterson wanted to deliver a great product on paper and that is it. No animated series, no real actor movie, just books. I sincerely hope it stays that way.
  • Syndication brings fame – Calvin and Hobbes is printed in newspapers, it uses an existing channel to reach as many people as possible. This is a tough place to get to, but you reach everybody and not just a chosen few.
  • Good messages – beyond the funny pictures, Calvin and Hobbes covers a lot of important topics. From environmental issues to philosophy, you find good messages without any religious overtones found for example in Peanuts. Through the mouth of a very excited kid bad things come across in a very powerful way when he is bummed out about something.
  • Rules can be bent or broken – Calvinball has no rules, but seems to be a lot of fun. Science is fascinating but can be bent if you want to have a transmogrifier to turn you into a pterodactyl if you want to.
  • Relationships keep things interesting – Calvin and Susie Derkins or Calvin and his dad remind me a lot of times about the tensions and relationships I have with people I work with in a less destructive way that Dilbert does. Yes, there is animosity, yes there are misunderstandings, but all in all we care about each other.
  • The source matter is not important if your imagination is good – Calvin building his snowmen of horror or assembling junk dug out from the ground into a dinosaur skeleton are great examples of that.
  • Summon your alter egos – when Calvin escapes his dilemma of having to do homework by becoming “stupendous man” or “spaceman spiff” I think of how I look at my work from the angle of an end user or person with a disability. Going out of your normal frame of mind can be immensely powerful.
  • Be passionate and up for it – Calvin is always 110% (it might be the sugar in the breakfast cereal) and so should we. Passion is the most important part that drives creativity. Passion can lead to controversy and misunderstandings. This is good, and it is sad to see that we live in a society were people with strong opinions are labeled destructive and negative. They may not be, they are just up for it and want to change things and experience new things all the time. If we stop that we deliver mediocrity
  • Be warm and don’t fear to show your emotions – the most wonderful moments are in Calvin and Hobbes when emotion comes through, beyond all logic. When Calvin forgets Hobbes in the garden and his parents seek him in the dark (in his stuffed toy form) and Calvin’s mom catches herself shouting his name, we know that the characters care for each other a lot. When Calvin cuddles up with his parents every time something bugs him you want to be part of it. Emotions are good, we should not hide behind a mask of awesome or professionalism

I might be rambling here, but I think it is important that we give our best when we create. It is a magical world out there and we all have some little magic to bring into it. When Calvin gets moody about autumn arriving and the summer being over and Hobbes explains that the leaves with their different colours look like fireworks of mother nature, I knew that even bleak moments can become magical when we allow them to.

And if you can not deliver this every time you do something, that is not a problem either. Some days are bad, so bad that even your lucky rocketship underpants don’t help. All we can do is deal with them and move on.

Breaking barriers at Beyond Tellerand (talk, audio and impressions)

Friday, November 25th, 2011

A few days ago I was fortunate enough to attend the Beyond Tellerand conference in Dusseldorf/Germany.

The conference was organised by an old friend of mine, Marc Thiele and it showed once again that the success of a conference is very much dependent on the passion of the organiser. As it were, Beyond Tellerand was amazing and had a very cozy vibe to it. This could be because of the location, an old-school theatre for variety shows, complete with small tables with lamps on each (no telephones to order champagne though).

I was kicking off the day with my “Breaking the barriers – moving browsers and the web forward” talk. The slides and audio are available here:


(navigate slides with cursor left and right, go through bullet points with up and down and toggle notes with “n”)

I will publish a more detailed post on Mozilla about the content of the slides. Here, let me quickly go through the other talks I attended and was able to follow (I had a cold and felt awful).

(Some of) the talks

  • Aaron Gustafson’s “Crafting Rich Experiences with Progressive Enhancement” was a nice reminder on how to create rock-solid sites and apps by layering complexity instead of throwing the kitchen sink at the browser and wondering when things break. His book on Adaptive Web Design covers the same topics in a very understandable fashion. I have had lots of work together with Aaron but we met for the first time IRL, which is very cool.
  • Naomi Atkinson’s “Going Beyond” was a talk about self-promotion and how to get known online. It was not a seedy SEO talk but more about the irony that we spend days making our products look amazing but fail at doing the same about ourselves. That she managed to use three celebrities as examples that I heartily despise and still keep me interested shows that it was a talk worth your while.
  • Heiko Behrens’ “Mobile Apps with JavaScript – There’s More Than Web” was a whirlwind tour of all the different options we have to build mobile applications using JavaScript. He covered Appcelerator, PhoneGap and many other tools and live coded the examples to show us how you can use emulators to get going. A bit packed as a talk, but I managed to follow and enjoy it.
  • Vitaly Friedman’s “The Invisible Side of Design” showed a lot of shiny web site examples but reminded us that the real value of design is not in its visual representation but in the effects it has on the visitors and the benefits it brings for site owners. A nice reminder not to chase the shiny but use effects in moderation and where they reap benefits.
  • Seb Lee-Delisle’s “CreativeJS – Beauty in the Browser” was a live coding session showing some particles in Canvas and creating 3D animated snow. Much like the stuff he keeps making people create in his great workshops. Pretty unfair to show people how easy it is to create beautiful things and then end with “but don’t do that” :)
  • Yves Peter’ “Trajan in movie posters: the rise and fall of the Roman Empire” sounded really far-fetched but actually was a very entertaining research into how many movie posters used the font “Trajan” which is known as the “make it an Oscar movie” font. Whilst one can argue with the analytics methodology (amount of movies vs. percentage of movies released in the year, which, IMHO, would be a more interesting number) I thoroughly enjoyed the journey into the OCD world of a typography enthusiast. And, no, simply using Trajan does not automatically get the movie an oscar.
  • Simon Collinson’s “Notes from the Edge” gave us a good reminder that building things with design tools and software is a craft and that we should put pride into what we do instead of complaining about lack of resources or response from the outside world.
  • Tomas Casper’s “How to sneak Accessibility into your project without anybody noticing it” showed a lot of expertise and ideas of how to sell accessibility to large organisations where the “it is the right thing to do” doesn’t quite cut it. Lots of good info there, but IMHO far too much packed into a single talk. This could be a kick-ass workshop
  • Dan Rubin’s “Hands-on Prototyping with HTML & CSS” told the tale of user testing the changes in a huge old-school web site by showing HTML and CSS mockups (done with image map-like positioned elements to click and enter data). Very good information on how to make user testing much more agile and get faster results
  • Jake Archibald’s “Reusable Code, for good or for awesome!” told the tale of historical phalluses and had some info about code. Seriously, it is a kick-ass talk about building reusable JavaScript solutions.
  • Jon Tan’s “Welcome to the brave new world of web type” was a very inspiring talk on using the right font-faces on the web and common mistakes being made. Instead of just talking about the aesthetics of different fonts Jon also talked a lot about usability issues and quality concerns in rendering. All in all, a kick-ass talk about a subject I know zilch about but made me interested in doing more.

All in all Beyond Tellerand was well worth my time and the organisation was great. The format of having 15 minute breaks between speakers worked very well and took the rush out of the conference. The lack of stable or working wireless was annoying but actually meant that I listened to the other talks more than usual (no distraction with company emails).

I especially enjoyed that while being very specialist topics, none of the talks was elitist or left people not “in the know” confused and lost (or bored). I wouldn’t know Arial from Helvetica to save my life (funnily enough I am good at Cheese or Font though) but I was really inspired and interested in the typography talks as they talked about real issues and solutions for them. Being in Germany was weird for me, as I am so used to speaking in English as the first language in conversations but helping other people (and buying cold medicine for Jake) was fun to do.

All in all I had a great time, I hope I inspired a few people to have a go at modern and bleeding edge technology and I can safely say that is a great place to go.

On SOPA and PIPA and online creativity

Thursday, November 17th, 2011

If you’ve been here yesterday you’ve seen the modular popup telling you that this site might be censored. This was a script by American Censorship making people aware of the issue of the Censorship and filtering attempts of the US government as an answer to copyright infringement.
The Stop Online Piracy Act (SOPA) and PROTECT IP Act of 2011 (PIPA) (Greek people can snigger now, you are welcome) are scary. Check out the following video or check the infographic to learn more:

PROTECT IP Act Breaks The Internet from Fight for the Future on Vimeo.

Now, earlier I was asked to give a statement for a publication here in the UK and for the sake of full disclosure, here’s what I sent:

The concept of SOPA becoming a reality frightens me. The internet is an incredibly powerful communication tool that keeps people connected when they are not close and gives those a voice who can’t get out via official communication channels. It also allows people to be creative and be found by showing their talents in videos, music and animations.

Allowing the government to take down web sites on perceived copyright infringements is a scary thought that will not only censor the internet but also stem the flow of creativity that made it the success it is. We point at countries like China, Iran and Syria for censoring the free speech of their citizens and at the same time are ready to frighten ours into not speaking up on the grounds of lost income in the entertainment history.

If you have comments on your site, if you host user generated content, if you have a slightly vulnerable install of WordPress (for example) and spammers manage to inject links to copyrighted material you will be taken down and blocked. Seeing that anything related to government communication is not the speediest of issues this also means that wrong accusations can mean that you will be blocked and offline for quite a while, losing the trust of your users.

The most annoying part about this bill is not that it is about illegal, political or dangerous content, it is about showing a video or using a soundtrack that doesn’t belong to you. It is not about protecting citizens or upholding the peace or bring order to the internet, it is driven by greed and backed by a total failure to understand how the web works. If the entertainment industry embraced the web as a distribution platform rather than selling me DVDs I can not play in another country with 5 trailers I can’t skip and a 2 minute intro that I should not download illegal copies none of this would be necessary.

In essence, the proposed way of stopping piracy will not affect the piracy scene at all which can work with IPs instead of domain names, go back to old-school distribution channels like FTP and newsgroups and set up relay servers in other countries. The entertainment industry could learn from the pirates how to effectively distribute media on the web rather than making an attempt to block them and hurt the whole web as a platform in the process.