Adam Greenfield recently mentioned this:

“The ability to ‘read’ a medium means you can access materials and tools created by others. The ability to ‘write’ in a medium means you can generate materials and tools for others. You must have both to be literate.”

That neatly taps into a lot of what I’m thinking about (and failing to write about here) at the moment. Things like this, and mixing your own paint, and programming-as-act-in-its-own-right versus programming-as-necessary-evil, and a whole host of other questions (such as what it is I actually do).

Things are slowly coalescing. This quotation coalesced a great deal, and deserved more than a mere del.icio.us link…

It’s fairly common practice in jQuery to bind events to a quick anonymous function that performs the action you desire. But how do you bind an event to a non-anonymous function – something that you’ve already extracted into a function so as to avoid reptition? I learned this one the hard way, and thought it was worth sharing.

I was working on some jQuery to apply to some legacy HTML at work, and was fiddling around to see if our goal was possible.

I was working on a “springy” archive menu. There are some headers and some lists; the lists are hidden on pageload, and when you click on a header, the subsequent list (ie the archive for that year) opens. Many lists can be open or closed at once. In addition, we toggle a class on the header (rather than the header link, which is there purely out of legacy code for now) to change an image, indicating that it’s open.

Here’s my proof of concept code – my first working version to demonstrate how this functionality would work.

$(document).ready(function() {
	var headlinks = $("div.container h3 a");

	for (var i=0; i < headlinks.length; i++) {
		$(headlinks[i]).bind("click", function() {
			$(this).parent().next().toggle();
			$(this).parent().toggleClass("open");
		});              
		$(headlinks[i]).parent().next().toggle();
		$(headlinks[i]).parent().toggleClass("open");
	};

	toggleArchiveLinks(headlinks[0]);
	$(headlinks[0]).parent().next().toggle();
	$(headlinks[0]).parent().toggleClass("open");
});

Now we've got the code working, it's time to refactor. There's a lot of repetition going on - three instances of that "toggle visibility and toggle class" behaviour, so let's pull that out into a function:

function toggleArchiveLinks(element) {
	$(element).parent().next().toggle();
	$(element).parent().toggleClass("open");
	return false;
}

Much better. Unfortunately, we can't replace our anonymous function within that bind directive with this. I initially thought you could bind "click" to toggleArchiveLinks(this). But that doesn't work, because in the context of events, what gets passed out to another function is the event object itself. (I think it works fine in the anonymous object due to the way things are scoped).

But it's a bit ugly to refactor some, but not all of the code. After looking at the jQuery docs for bind, it turns out that there's a third parameter you can pass in: a data object. This is made available to a handler function. So that means we can pass information about the element we want to toggle to a handler event. We write our new bind directive like this:

$(headlinks[i]).bind("click", {element: headlinks[i]}, handleToggleEvent);

That object in the middle will be made available to a new function handleToggleEvent. (We could, of course, pass as many key/value pairs as we wanted to to the function). We also need to write handleToggleEvent. That function looks like this:

function handleToggleEvent(event) {
	toggleArchiveLinks(event.data.element);
	event.preventDefault();
}

The function accepts an event as a parameter, and the object/hash from our bind statement is available as event.data. We're then free to call toggleArchiveLinks on the element of our choosing. Finally, we have to call event.preventDefault in order to stop the event propagating any further. If we don't do this, the bound behaviour will happen, and then the link will click through as normal. return false; won't work here, because we're actually dealing with the event itself, not just an anonymous function.

So we've now managed to refactor some repetitive code and call it from a bind statement. Our final jQuery script looks like this:

$(document).ready(function() {
	var headlinks = $("div.container h3 a");

	for (var i=0; i < headlinks.length; i++) {
		$(headlinks[i]).bind("click", {element: headlinks[i]}, handleToggleEvent);                
		toggleArchiveLinks(headlinks[i]);
	};
	toggleArchiveLinks(headlinks[0]);
});

function toggleArchiveLinks(element) {
	$(element).parent().next().toggle();
	$(element).parent().toggleClass("open");
	return false;
}

function handleToggleEvent(event) {
	toggleArchiveLinks(event.data.element);
	event.preventDefault();
}

Which is much better, I think.

There comes a point in every developer’s life when your realise the problem isn’t your work, but the tools you’ve got to hand. Toolsmithery is an important part of the job, and so I spent a few hours yesterday crafting a tool useful to any front-end developer.

The result is the CSS Redundancy Checker.

When you’re writing HTML, over time, your CSS files begin to fill up a lot. If you’re working on a large project, you might even end up with several people contributing to the CSS file, not to mention refactoring each other’s work. The result is a directory full of HTML files, and a very large CSS file.

What tends to happen is that not ever selector in the CSS file actually applies to your HTML; many are rendered redundant by refactoring, or by changes in HTML. But when you’ve got a 70k+ CSS file, it’s not easy to check precisely which selectors aren’t in use any more.

Enter the CSS Redundancy Checker. It’s a very simple tool, really. You pass in a single css file, and either a directory of HTML files, or a .txt file listing URLs (one to a line). It then proceeds to look at each file in turn, and at the end, list all the selectors in your css file that aren’t used by any of the HTML files.

That’s it. I’m pretty sure it’s accurate, and it should work with most CSS files. Most of the magic isn’t down to me, but down to _why the lucky stiff‘s marvelous Hpricot HTML parser. The script itself is about 50 lines of reasonably tidy Ruby. You’ll need Ruby, and Hpricot, in order to run it. There’s more full documentation over at the Google Code site where I’m hosting it. Please add any issues there, or get in touch if you want to contribute.

Things it doesn’t do: listing line numbers of where the selectors are. I wrote that functionality on the train this morning, but I can’t find a way to make it 100% accurate, so thought it best to leave it out – inaccurate line numbers are of no use to anyone. If you can come up with a way that works, let me know. Also, at some point I might turn it into a Textmate command. All in good time, though.

The need for the tool came out of a large project we’re working on at NPG, but I felt it would be useful to pretty much any HTML developer. So I’ve released it to the world. Let me know what you think, and do spread the word. You can get it via svn checkout, for now:

svn checkout http://css-redundancy-checker.googlecode.com/svn/trunk/ css-redundancy-checker