Tuesday, May 29, 2012

(ab)using labels in javascript

Something that always felt a bit messy in unobtrusive javascript coding was how we normally use class names for both styling and binding functionality to an element. For example:

<-- HTML -->
<a class="expander" href="javascript:void(0)"></a>

/* CSS */
.expander {/* some arrow styles */}

/* javascript */
$(".expander").click(toggleAccordion)

There are two problems with this:

  1. If I have another type of expander button somewhere else that needs to do something different (e.g. maybe somewhere I need to ajax content in first), then I need to clutter the code with more stuff in order to allows the different buttons to do different things
  2. I have no indication of what said button does by inspecting it w/ Firebug/dev tools, let alone by just looking at it. I have to slog through the code to figure out what code might get attached to this element

Stepping back for a moment

As it turns out, there's a third, minor issue: the href attribute of the element doesn't serve any purpose. It doesn't even tell the user where clicking on the element might go. It's just a clunky way of telling the browser to not do its default action when you click on the element. It's a code smell that can be refactored to something like the this:

$(".expander").click(false)

As it also turns out, browsers as old as IE8 support document.querySelectorAll, so finding elements by href nowadays is not particularly slower than searching by class name. So why not repurpose that useless href back to identifying what a user should expect when clicking on the element?

What's javascript:void(0) anyways?

javascript:void(0) is an antique from a decade ago that most people just blindly use without really thinking about what it might mean. All this line does is run some javascript that returns undefined. Returning undefined in this context is equivalent to e.preventDefault(), which in this case means "prevent going to a URL".

There are many ways of returning undefined, the shortest of which is to simply... do nothing.

<a href="javascript:;"></a>

But we can do better: do nothing in a descriptive way, by using javascript labels:

<a class="expander" href="javascript:expand:;"></a>

And we can target that via jQuery:

$("[href='javascript:expand:;']").click(toggleAccordion)

We can attach different behaviors to different ".expander" elements simply by using a different href:

<a class="expander" href="javascript:expandData:;"></a>

$("[href='javascript:expandData:;']").click(ajaxAccordion)

So now we have a clean way of separating styling from behavior on an element, while making "javascript:void(0)" more informative for users and future maintainer selves.

Wednesday, May 16, 2012

On learning how to code, or whose life is it anyways?

So this drama started by Jeff Atwood about whether people should learn how to code or not still hasn't died.

The trigger for his post seems to be that some mayor somewhere ought to be spending his time doing mayor work and not learning things that don't necessarily help w/ his day job.

The thing is, even if he gets paid by tax payers to do his job, it doesn't mean he must do it at all times of the day. Lots of coders go home after work to learn about things like photography or martial arts. And not because they are actually trying to get photos published in a magazine, or actually going into real combat.

Some are advocating everyone should learn how to code, but that's a bit like saying everyone should learn English or Mandarin under the logic that it opens up a whole lot of business opportunities because of the whole global economy thing. Sure, there are many things that are probably worth pursuing if we had infinite time, but since we don't, just let people pursue whatever the heck they want to.