Tubthumping

A place to rant.

Wednesday, October 17, 2007

Javascript, without the misery

I was trying to convince a friend of mine to implement a new widget in Javascript. Of course, he was reluctant. Who can blame him? Who likes to deal with "silent errors" and "browser incompatibilities"?

Indeed, the first ten minutes of writing Javascript will make you want to punch yourself in the face to stop the pain. After all, javascript errors do often pass by silently by default (or else they show useless modal dialogs). And some operations really are very different across browsers. Moreover, Javascript's dynamic typing allows you to do all kinds of illegal things without finding out until the program blows up at run-time, at which point it's hard to observe what's happened.

Two things can make Javascript development more comfortable: good programming practices and good tools.

Programming tips
  • Make errors a Big Deal. You don't have to use a modal dialog, but maybe write exceptions with stack traces to the bottom of your page when they come up. At the very least, use the Firefox error console to observe the problems that occur.
  • Seek cross-browser solutions. There aren't that many operations that are really different across browsers. Adding event handlers is a classic one that you just can't avoid because IE used to use attachEvent(), and Firefox uses addEventListener().
  • When you do need to write code that depends on the browser, try to use semantic tests to distinguish among browsers. That is, instead of checking for IE, check for the presence of attachEvent(). Browser detection is tough to do completely correctly, and needing to know which browsers use which methods makes code more brittle and likely to break when new browsers or versions are released.
  • Isolate browser-specific code into utility functions. This one should be obvious. Browser-detection code is probably among the most brittle of any web application. At least if it's isolated to a small section of code, it can be maintained, tested, and updated more easily when things change.
  • Don't end lists with commas. My advice has suddenly become much more concrete. But this is a problem I've run into several times and spent an incredible amount of time debugging. IE versions before 7 choke when given Javascript lists that end with commas. For example:

    var array = [ 1, 3, 5, ]; /* note comma after 5 */

    This construction is really useful for lists of more complex items when the list's contents might change and each item takes up nearly a whole line. But it will bring IE6 to its knees in a completely silent, unhelpful way, because it can't even parse your file. If you're getting a bizarre error before any of your code seems to be run, check for this issue.

    For the curious, this is technically correct behavior: the ECMA standard IE is implementing doesn't allow that comma, but every other language does, and other browsers deal with it alright.
Tools and references
  • Look up methods and properties on w3schools.com. Their HTML, DOM, and CSS references are invaluable.
  • Check out the Venkman debugger. It's slow and somewhat buggy, but it gives you more observability into Javascript than you'd have thought possible if you haven't sought out good tools before. You can set breakpoints and watches, evaluate arbitrary expressions, view call stacks, etc.
  • Use the Firefox web developer toolbar. Among the great features of this add-on are in-line CSS editing (without reloading the page), outlining arbitrary DOM elements, and displaying other relationships between DOM elements. Great for debugging everything from cookies to DIV positioning.
  • Here's a useful list of Javascript gotchas.
There's one thing left to know about: layout problems are often undebuggable. This isn't a tip - it's an admission that web development with Javascript isn't all rosy. Before you start messing with padding and margins, learn about the Box model. Then learn about the peculiar ways in which every browser manage to implement it incorrectly.