Coding with Jesse

Replace text with an image using CSS

Let's say you want to have a logo on a page, but you'd really like to use an <h1> with some text for the header in the HTML. Or maybe you like to use images for all your titles, but would still like to have plain text inside header tags in your HTML.

There are a number of reasons for wanting to do this, namely accessibility and search engine optimization. I talk more about this in my post Writing Semantic HTML.

The problem is: How do you hide the text? I think the most popular technique is to wrap the text with a <span> inside the header tag, then use some CSS to 1) hide the text, and 2) use the header tag as an image. Something like this:

<style type="text/css">
h1 {
    width: 500px;
    height: 100px;
    background: url(my_header_image.gif);
}

h1 span {
    display: none;
}
</style>

<h1><span>My Great Header</span></h1>

Unfortunately, this technique makes us add an extra tag to our markup, and we all know that every time we use an unnecessary tag, a puppy dies. Either that, or we end up with ugly, unnecessarily bloated HTML.

Well here's another technique which hides the text just by using CSS. The text will still be readable by screenreaders and search engine spiders, but will disappear like magic for everyone else:

<style type="text/css">
h1 {
    width: 500px;
    height: 100px;
    background: url(my_header_image.gif);
    overflow: hidden;
    line-height: 500px;
}
</style>

<h1>My Great Header</h1>

This technique works by pushing the text down inside the header with a rather large line-height (it must be at least twice the height). Then the overflow: hidden hides the text since it's overflowing.

Now isn't that better? No puppies were harmed, and we end up with slightly cleaner and shorter markup.

Published on November 7th, 2006. © Jesse Skinner

The Ajax Experience Wrap-up

I had a really great time at The Ajax Experience, and got to meet a lot of really cool fellow JavaScript hackers. The sessions were all very interesting, but what really stuck with me was the difference that a good JavaScript library can really make in your development.

John Resig's talk on Choosing a JavaScript Library showed how much cleaner and faster development can be when a library offers elegant solutions to very common problems. And I assume John used some kind of Jedi mind trick because his talk made me choose his own library, jQuery. I even rewrote my talk's examples in jQuery to make them shorter. I'm sure I'll be writing a lot about jQuery on here in the future.

My "Unobtrusive Ajax" talk went pretty well, I thought. I realised afterwards that I hadn't pointed people at my examples for download. So if you attended and want to take a second look, or if you didn't attend but still want to see what it was all about, go check out the downloads below:

And please, contact me if you have any questions or comments about any of this stuff.

Published on October 26th, 2006. © Jesse Skinner

Carnival of the Web is on hiatus

Unfortunately, there will be no Carnival of the Web this month. I'll be putting it on hiatus indefinitely. Now that I'm freelancing, I simply don't have the time to read through blogs and pick the best posts. Perhaps it will come back some time in the future. I apologize to everyone who had submitted articles for the fifth edition.

Published on October 21st, 2006. © Jesse Skinner

Defining functions in a loop

Do you ever try to define a function in a loop, like an event handler for example, and find that it's always the last variable in the array that is pointed at by every event handler? It can take a while to debug this stuff. Let's say you do something like this:

var links = document.getElementsByTagName('a');
for (var i=0;i < links.length;i++) {
    var link = links.item(i);
    link.onclick = function() {
        alert(link.href);
        return false;
    };   
}

(Stupid example, I know). Well if you run this on a page, you would expect that everytime you click a link, you will get an alert with the href of that link. Well that's wrong! You actually get the href of the last link on the page every time!

This happens because of closures in JavaScript. You would expect that the link variable has the same value inside the onclick function as it does outside. But in fact, every time the loop comes around, link gets a new value, and actually the link variable in all those other onclick functions changes. So when the loop finishes, every onclick function will alert the href of the last link.

So to avoid this, you can do a few things. You can make a separate function that attaches the event like so:

function attachLinkEvent(link) {
    link.onclick = function() {
        alert(link.href);
        return false;
    };   
}

var links = document.getElementsByTagName('a');
for (var i=0;i < links.length;i++) {
    var link = links.item(i);
    attachLinkEvent(link);
}

This works because inside the attachLinkEvent function, the value of link points at the argument, which is a copy of the link in the loop. This way it doesn't change when the original link changes. Confusing? You bet.

Rather than use this workaround, you can just avoid using the link variable altogether in the onclick function, and replace it with this. Inside an event handler like onclick, this will point at the element that the event handler is attached to. In this case, this points at the link:

var links = document.getElementsByTagName('a');
for (var i=0;i < links.length;i++) {
    var link = links.item(i);
    link.onclick = function() {
        alert(this.href);
        return false;
    };   
}

Of course, real life examples are a bit more complicated. There are also different workarounds to fix the problem. But typically, one of these two solutions will fix things.

For way more information on closures than you will ever need, read Richard Cornford's essay JavaScript Closures

Published on October 19th, 2006. © Jesse Skinner

Unobtrusive Ajax at The Ajax Experience

I'll be presenting at The Ajax Experience. This is an Ajax conference taking place in Boston from October 23-25, 2006.

My topic will be "Unobtrusive Ajax", which I've described as so:

Learn how the separation of content, presentation and behavior can not only make your web applications more accessible, but also easier to develop and maintain. See how to implement modern web interfaces so that they are enhanced by JavaScript and still work fine without JavaScript.

Jesse will walk you through lots of examples and show you solutions for some common problems in Unobtrusive Ajax development. Although some of the examples will use a bit of PHP, Jesse will focus on the JavaScript and HTML, so you'll be able to apply the lessons learned to any server platform.

I'll mostly be talking about the practical benefits of separating JavaScript, CSS and HTML, as well as why you shouldn't assume people have JavaScript, and how to design (or re-design) some common Ajax interfaces to avoid this assumption.

I'm a bit worried I'll be the party pooper at the conference.. everyone'll be so excited about using JavaScript, nobody will want to be reminded about the minority that doesn't have JavaScript. But I think the presentation will be a lot of fun and I'll hopefully show people that it's not a big deal to support non-JavaScript users, and it may even make your code more stable and easier to manage.

If you'll be attending, please, let me know. I'd love to meet some fellow Ajax hackers.

Update Oct. 26, 2006: Click here for a write-up and links to my slides and examples.

Published on October 10th, 2006. © Jesse Skinner
<< older posts newer posts >> All posts