Announcing Bluff, plus a few other project updates

I put out a few new software releases over the last few days, and thought I’d gather them into one post rather than lots of little ones. Let’s start with the biggest.

Update: for those wishing to contribute bug reports (as failing test cases) and patches, Bluff is hosted on Github.

In what can only be described as a colossal case of wheel reinvention, I’ve ported Geoffrey Grosenbach’s Gruff graphing library to JavaScript and called it Bluff. My major gripe with current JavaScript graphing libraries is that they either have too large a dependency requirement (i.e. they depend on one of the large JS frameworks or on Flash), or they are large themselves and kinda unwieldy to use. Bluff only requires a copy of JS.Class to work, and that’s only 2kb on the wire. Bluff itself is 8kb, plus 4kb for ExCanvas if you want your graphs to work in IE. I actually went to the trouble of writing a compiler that would take JS.Class-based code and generate ‘raw’ JavaScript from it, but the output from that ended up being twice the size of the JS.Class version and didn’t run fast enough to make up the difference so I’m keeping the JS.Class requirement for now.

Why did I do this? About a year ago I wrote an app called DesalData for my then employer, and it has a section that lets you search for water plants from a database of ~15,000 entries using a stack of filters and graph data from them in real time, and it lets you save those graphs to your machine (you can’t see it without a login, sorry). I was doing the site in Rails so I figured I’d use Gruff, but we started it off on shared hosting, so I didn’t want the server to deal with generating all those images on top of the database load. So, I had to generate graphs on the client but keep the ability to generate identical graphs on the server for download if required. So, I stuck with Gruff and reimplemented it on the client – the client’s machine handles most of the rendering so the server’s workload is a little lighter and the app is more responsive.

(Yes, 15,000 entries doesn’t sound like much but the data model for this thing involves some very wide tables and lots of joins. Getting this to perform decently involved patching Rails to support multiple SQL calculations on one query, but that’s another story.)

Anyway, this release is a complete rewrite (my original version for DesalData is closed-source and incomplete), and is pretty much equivalent to Gruff 0.3.4, the current release. A few graph types (the ones that use images) are missing, but they’re kinda niche and I’d rather keep this lightweight. Give it a whirl and let me know what you think.

The second announcement concerns JS.Class, in that version 2.0.1 is out. It’s a very minor bug fix release and should be a drop-in replacement for 2.0.0, so go ahead and upgrade straight away. The fixes include use of strict equality (=== rather than ==) throughout, and a fix in Module#include that fixes this very rare edge case:

M = new JS.Module({
  extend: {
    included: function(base) {
      // Redefine include() on the including class
      base.extend({ include: function() { /* ... */ } });
    }
  }
});

C = new JS.Class({
  include: M,
  foo: function() { /* ... */ }
});

2.0.1 makes sure that the M.included hook’s redefinition of base.include takes effect before the class’ own methods are added to it – like I said, edge case but I ran into it recently to now it’s fixed.

My final announcements are a couple of new Ruby gems that I’m using to build my JavaScript projects these days. oyster is a really simple commandline option parser, inspired by Trollop but with some subtle differences, and jake is an automated build tool that merges and compresses JavaScript files using PackR and lets you use ERB snippets and helper functions in source files. I won’t say much about either, as I’m only really releasing them so my colleagues can build my projects on their own machines, but do feel free to consult their READMEs and gem install either to have a play around. Any bug reports are, as always, gratefully received.