Christian Heilmann

You are currently browsing the Christian Heilmann blog archives for April, 2007.

Archive for April, 2007

My Highland Fling talk about Progressive Enhancement with JavaScript

Thursday, April 5th, 2007

I just finished my talk at the Highland Fling conference in Edinburgh. It seems that it went quite well, and as I was asked about the slides, here they are:

I won\’t go naked this year!

Wednesday, April 4th, 2007

There, I said it. I won’t remove my style sheets of this here blog to participate in the CSS naked day. But why oh why wouldn’t I? After all, the other cool kids do it and it promotes web standards and meaningful markup doesn’t it?

Oh look, generated code!

Well, IMHO it doesn’t. Most of the participating sites are blogs, some of them with out-of-the-box templates that weren’t even developed by the authors. I wonder for example how a PHPBB forum without styles counts as markup to be proud of.

You can organise have a fashion show of very healthy bodies for an obese audience, but without telling the audience what went into achieving this body and why their bodies will be a problem in the future it is just showing off.

Missing the target audience

I also fail to see the relevance of the whole thing when it isn’t accompanied by tutorials as to what markup you can see and why it made sense to use this kind of element for that kind of job. The argument that it will shake the world and make some visitors wonder why the site looks different and have an epiphany that it all works correctly and immediately get hooked onto web standards is rather moot. This could work if every world portal or large ecommerce companies were to participate, but just a couple of blogs or small web design agencies will not have an impact.

I am not saying that the participating sites are pointless, I am saying that whoever gets there is already interested in web development and frankly if you still haven’t grasped the benefit of semantic markup, please change your job.

Missing the target market

The feel-good factor of the whole thing is great and in its wake last year you heard a lot of people mentioning that we won the web standards war, everything works and wahey. Reality check: go and work with a enterprise level CMS or framework, work on B2B applications, financial or local government sites. When was the last time you have used a company intranet, meeting room booking system, expense system or vacation planner that was not terrible, terrible markup?

I just came back from giving a workshop in Singapore and many of the people in the course were completely amazed with what you can do with CSS and JS when your HTML makes sense. There is a lot of bad code, bad ideas and misinformation out there, IMHO our job is still to get to these people, and not show off and get the Google juice up for a day pointing to our blogs.

Ok, you can call me a grumpy old bastard and spoilsport now, but I really don’t see a point.

Come to think of it, I might turn the CSS table gallery naked for the day, making it working but pointless.

Ready for Highland Fling

Tuesday, April 3rd, 2007

I just finished my slides for the Highland Fling conference and ordered a mini cab to get me to the airport in the morning.

I am looking forward to this a lot, for several reasons:

  • I am taking a plane but I don’t have to brace myself for jetlag
  • Alan (the organizer) is a lovely lovely chap and it is great to be part of something new happening (HF could become big next year)
  • The lineup of speakers is quite brilliant and the different topics do quite nicely lead from one to the other.

Whilst I had to get the graveyard shift right after lunch I hope I’ll keep people entertained, awake and that they get something from my presentation.

See you there. I will also stay over the weekend in Edinburgh to see how pretty (or not) the city is.

The only for loop you will ever need °

Monday, April 2nd, 2007

° main contain hyperbole to take the mickey out of other blog posts

I am a very lazy person when it comes to typing. As I am doing so much of it I’d rather not type something I really don’t need. This is why I had an issue with “for” loops as you need to type them so often.

The classic way of looping through an array for example is a for loop with an iterator:

var arr = [1,2,3,4,5];
for( var i=0; i<arr.length; i++ ){
  alert( arr[i] );
}

This is however not a good plan for large arrays (like DOM trees) as the length attribute is read out every time the loop executes. You can avoid this in two ways. If it is for example irrelevant in which order you loop through the array you can use a reverse loop:

var arr = [1,2,3,4,5];
for( var i=arr.length - 1; i>-1; i-- ) {
  alert( arr[i] );
}

Or using while:

var arr = [1,2,3,4,5];
var i = arr.length;
while( i-- ) {
  alert( arr[i] );
}

If you really need to go through the array in the normal order then you need to use another variable to store the length and compare with that one.

var arr = [1,2,3,4,5];
for( var i=0,j=arr.length; i<j ; i++ ){
  alert( arr[i] );
}

The for loop also allows you to use the in keyword to make it easier:

for(i in arr ){
  alert(arr[i]);
}

However, there is also another trick if you don’t want to do this (for example if you don’t want to iterate through all but use a step of 2). The comparison inside the loop does not need to be the iterator but could be any comparison. As long as it is true, the loop gets executed, when it becomes false the loop ends. This allows you to simply check for the array element inside the loop itself which means you don’t need to read the length attribute at all:

var arr = [1,2,3,4,5];
for(var i=0; arr[i]; i++ ){
  alert( arr[i] );
}

There is however the issue of the truthy and falsy and type casting in JavaScript which means that if your array has null or 0 elements the loop would end, too:

var arr = [1,2,0,4,5];
for(var i=0; arr[i]; i++ ){
  alert( arr[i] );
}

You can avoid this by testing properly:

var arr = [1,2,0,4,5];
for(var i=0; arr[i]!==undefined; i++ ){
  alert( arr[i] );
}

There is also another problem this kind of loop avoids: if you manipulate the array during execution of the loop (for example by removing or moving DOM nodes) you need to change the iterator, too. This example will be an endless loop and lock your browser:

var u = document.getElementsByTagName('ul')[0];
var lis = u.getElementsByTagName('li');
for( var i=0; i&lt;lis.length; i++ ){
  u.removeChild(lis[i]);
}

With the other kind of loop that is not a problem. You can for example remove all list items from a UL with:

var u = document.getElementsByTagName('ul')[0];
var lis = u.getElementsByTagName('li');
for( var i=0; lis[0]; i++ ){
  u.removeChild( lis[0] );
}

Did I miss something obviously bad about this idea? If so, please tell me, but also consider the other benefits of this for loop to end all for loops:

  • a lot smaller than the YUI, Dojo or Prototype
  • unobtrusive and accessible (if the array is not there nothing happens)
  • may have rounded corners (but they are invisible)
  • cross-browser
  • easy to read
  • heals sick animals when you don’t look

If you wonder about the speed implications of the different styles, check out the speed comparison of for loops test page.

Q&A: Linking a whole DIV

Monday, April 2nd, 2007

Q: I have a DIV with some text, an image and a link and I was asked by our designer to make the whole thing a link. I cannot use an image, so I tried nesting all in a link and making the real link text a SPAN with a style that makes it look like a link, which seemed dirty and I used a link around a DIV which is invalid HTML. How can you link a whole DIV?

A: This is a classic example where a small JavaScript makes a lot more sense than trying to misuse HTML or make non-semantic HTML mimic the proper element with CSS. If your construct is something like

... foo

you can write a JavaScript that assigns a click handler on every DIV that changes the document location to the href attribute of the first link:


window.onload = function(){
var divs = document.getElementsByTagName(‘div’);
for(var i=0,j=divs.length;i if(divs[i].className === ‘clickbox’){
divs[i].onclick = function(){
window.location = this.getElementsByTagName(‘a’)[0].href;
}

}
}

}

This is a rather obtrusive example when it comes to event handling, but it should get you on your way.