All the original javascript for colr.org was home-brewed, and some of it was pretty sketchy. I learned a lot since then, and it was time to plow the old field under and replant. Also, several very nice js libraries have recently been fighting for supremacy. The fierce competition has generated some very handy and powerful frameworks.
So, the basic goals were (1) use a js library to (2) ditch as much of the old code as possible.
Things got more specific along the way, and a few tangents were introduced. Below are some specifics.
Colr was written shortly after I learned it was possible to do OO javascript. I got a little class-happy, creating storage classes for things like colors and color schemes.
Turns out, that's a bit of overkill. You can represent storage classes just fine with arrays and hashes. Which makes it possible to:
It's kind of funny - the server originally sent straight JS to the client (never XML). But it wasn't JSON, it was a crappy frankenstein of data mixed with commands. The JSON api was added later, for other folks to use. With the move to primitives to represent data, JSON became a natural fit for the main colr site. The frankenstein JS API is gone and good riddance.
This was most of the effort of the overhaul. The interface logic was an ugly tangle of various attributes like:
onclick="if(x) {do(y)}"
It got very very tough to add functionality without breaking other things.
The main problem is the cohabitation of view-generating code
<div id="x">and controller-managing code:
"onclick="do_something()"
It wasn't as bad as this horror story, but it wasn't good.
Before getting into the dirty business of how this stuff was split up, I want to make clear that the payoff was huge - even better than I dared hope.
The credit for this goes to MochiKit's sophisticated event-management model. It makes calling partial functions easy. This means that functions no longer rely on global or upper-level variables to preserve state information. Funky-smelling code like this:
function add_tag_back_to_scheme() {
var url = base_url+'js/scheme/'+action_target.scheme_id+'/addtag/';
var data = 'tags='+action_target.tag;
Now looks like this:
function add_tag_back_to_scheme(scheme_id, tag, evt) {
var url = base_url+'js/scheme/'+scheme_id+'/addtag/';
var data = 'tags='+tag;
Much cleaner! The function now accepts the arguments it cares about, like a good function should. But the key is that those arguments can be valued at either event fire time or function bind time. If you don't understand that, read it again. It's important.
One minor speedbump was managing references to elements that need events hooked to them. Does each element need its own id? That would be a pain.
DOM selection functions avoid such pain. Most javascript libraries have pretty good DOM munging support, and MochiKit is no different:
getElementsByTagAndClassName(tagName, className, parent=document) getFirstElementByTagAndClassName(tagName, className, parent=document)
YeahTheFunctionNamesAreVeryVeryLong, oh well :)
Several things that were previously bunches of functions are now full-on widget classes. These are:
DropDownMenu can also be used as a straight menu or a context (right-click) menu.
It also does a neat thing that I have not seen elsewhere. If a menuitem has the "confirm" property set, selecting the menuitem flashes an "are you sure?" message *as part of the menuitem itself.* I like that a lot better than a browser pop-up. It felt like a million bucks to get the mouse events hooked up to make this work without massive hackery (the menuitem component is 161 lines). Again, massive props to MochiKit's event model.
All the user interface code is javascript. The server-side code used to care about roughly 10% of the user interface. Now it's flat nothing. A side benefit of this is being able to experiment with new code by using a different .js file and still hitting the main site. No need for a totally separate development copy of the site.
New features can be added much more easily (without breaking existing stuff). Which is good, because there's a long list of new things to add.
The colr.js file is down to 93K - a shrinkage of 28%! How about them apples? (a net increase in total bytes, because MochiKit is 190K). But a lot less code for me to support.
MochiKit rocks the block. I heart it.
It should be noted that colr.org uses a packed version of the latest bleeding-edge development version of MochiKit. If you'd like to start playing with MochiKit, you can download it straight from colr.org. On the mochikit download site, only the stable 1.3.1 version is available as a packed file. The latest code is only available from the subversion repository (it comes with a handy python utility for rolling your own packed version).
Feedback is appreciated. You can leave comments here. Or email me.