What are you doing with Sylvester?

Apparently some people are actually using Sylvester. Which comes as something of a surprise to me because I’ve had nobody (until today) email me or comment here about it at any length. It initially came out seven or eight months ago, and while I intented it to be a full 3D rendering environment, my day job took over more and more of my time and it never got beyond being a maths framework. Truth be told, I knew pretty much nothing about 3D rendering when I started (and that largely remains true), but I’d seen other people write 3D engines in JavaScript and wanted to learn (and I wanted to write something that wasn’t riddled with dozens of global functions). And, though it’s so far not fulfilled the ambitions I initially had for it, writing it has taught me a great deal about JavaScript performance.

Recently though, there’s been signs of OpenGL-backed 3D environments coming to various browsers, and however good a job I make of writing a 3D engine, it will never perform as well as native browser code. I still think it’s worth fleshing out the maths capabilities of the framework, though — there are various features I was working on for version 0.2 that have never seen the light of day. Stuff like line segments, polygons, and various useful algorithms for dealing with them. I’d be interested to know whether people would be interested in me finishing these features, and whether I should still push for a 3D rendering engine. So if you’re using Sylvester for any project, large or small, do get in touch and let me know what you think of it and how it should be improved.

Using ChainCollector to respond to Ajax calls

Saq made a couple of comments on my ChainCollector article about how to queue up functions to respond to Ajax calls, and whether I could write something up to shed a bit of light on how this might be done. Today, I’m going to implement some methods that allow to GET from/POST to a URL, then do some basic things with the response using very sentence-like code. Specifically, I’m going to end up with:

Ajax.GET('/api').then.insertInto('#blog-excerpt').and.evalScripts()

(I hope you’re starting to see why I wrote ChainCollector: code clarity is something that’s very important to me, especially when you’re working in a team that covers the whole web software stack and many of them don’t know JavaScript.) I’m not sure if this exactly answers Saq’s problem, but I hope it will illustrate how you might begin using ChainCollector to solve issues like this.

Okay, the first thing we’re going to need is a new class that provides us with methods to use in the chain above. Let’s call it ChainableRequest. I’m using Prototype today, but hopefully non-Prototype users will be able to follow along.

Ajax.ChainableRequest = Class.create();

Object.extend(Ajax.ChainableRequest.prototype, {
  initialize: function(verb, url) {
    this.chain = new ChainCollector(this);
    this.request = new Ajax.Request(url, {
      method: verb,
      onComplete: function(transport) {
        this.response = transport;
        this.chain.fire(this);
      }.bind(this)
    });
  }
});

This class takes two arguments to initialize its instances: an HTTP verb (GET or POST) and a URL. It sets up a new ChainCollector (which will inherit any methods we add to ChainableRequest) and sets off an Ajax request to the URL. It registers a callback that tells the request to fire the chain when the request completes.

So, onto the methods that we want to add to the chain. We need a method that inserts the response into some elements on the page. I want this method to accept a CSS selector, an element reference, or an array of element references. For each element found, it strips any scripts out of the response and inserts the remainder into the element. Note how each method returns the ChainableRequest object for chaining purposes.

Object.extend(Ajax.ChainableRequest.prototype, {
  insertInto: function(elements) {
    if (!this.response) return this;
    if (typeof elements == 'string') elements = $$(elements);
    if (!(elements instanceof Array)) elements = [elements];
    elements.each(function(element) {
      element.innerHTML = this.response.responseText.stripScripts();
    }.bind(this));
    return this;
  }
});

And, we need a method to evaluate the scripts in the response. You’ll see that Prototype uses a setTimeout in some cases to do this, in case the document hasn’t finished updating the DOM in response to an innerHTML change.

Object.extend(Ajax.ChainableRequest.prototype, {
  evalScripts: function() {
    if (!this.response) return this;
    setTimeout(function() {
      this.response.responseText.evalScripts();
    }.bind(this), 10);
    return this;
  }
});

The final piece of the puzzle is to create methods for any HTTP verbs you want to use. Note that I’m using capitals because that’s the convention with HTTP verbs, and also because you might want to go on an implement PUT and DELETE (supported by YUI), and delete is a reserved word in JavaScript. Each verb method should create a new ChainableRequest, then return its chain property so you can chain methods into the onComplete callback.

$w('GET POST').each(function(verb) {
  Ajax[verb] = function(url) {
    var req = new Ajax.ChainableRequest(verb, url);
    return req.chain;
  };
});

// Remember to add the required methods to ChainCollector
ChainCollector.addMethods(Ajax.ChainableRequest);

And that just about wraps it up in terms of getting our initial code sentence working. You’d probably want something a lot more flexible than this in real life, but this covers some common uses for Ajax calls that can easily be turned into sentence structures. You can download the ChainableRequest JavaScript class to save yourself copy-pasting all the code from this article.

PackR, now with class methods

Quick note: at the suggestion of Aman Gupta, PackR now supports Packr.pack, Packr.minify and Packr.pack_file as class methods, so you don’t need to create an instance of PackR before doing anything. Originally, I wanted PackR’s design to mirror the JavaScript version to make maintainance easier, but these methods are a tiny addition so I’m happy to put them in.

Methodize and functionize

Though the API docs seem to make no mention of it, there is this little gem sitting in Prototype 1.6.0:

Function.prototype.methodize = function() {
  if (this._methodized) return this._methodized;
  var __method = this;
  return this._methodized = function() {
    return __method.apply(null, [this].concat($A(arguments)));
  };
};

What that does is it returns a new function that calls the original function with its first argument set to whatever the current meaning of this is. This is how they now bind element methods to DOM objects:

// This takes an element as an argument
Element.visible = function(element) {
  return $(element).style.display != 'none';
};

// Convert is so it can be called as a method on elements
HTMLElement.prototype.visible = Element.visible.methodize()

This bit of trickery means you can myDiv.visible() rather than Element.visible(myDiv). We can make this work in reverse as well…

Function.prototype.functionize = function() {
  if (this._functionized) return this._functionized;
  var __method = this;
  return this._functionized = function() {
    var args = $A(arguments);
    return __method.apply(args.shift(), args);
  };
};

You could, for example use this if you have a particular iterator you keep reusing…

// If I keep doing this...
var safe = strings.map(function(s) { return s.stripScripts(); });

// I could do this instead...
var stripScripts = "".stripScripts.functionize();
var safe = strings.map(stripScripts);

Eh voilá! Much more legible code. You could equally do the above in a similar way with Reiterate, but I digress. The point is that you can do some pretty tricksy stuff with functions in JavaScript, and I’d guess that many web devs (myself included) are mostly unaware of the possibilities. Hopefully the new Prototype release will help folks expand their JS knowledge ever so slightly.

Reiterate 1.3

Tiny update: after adding 16 characters (“this._object || “), Reiterate is now compatible with Prototype 1.6.0′s revised Hash API. Also, the gzipped copy is now even smaller, thanks to a different compression strategy. Essentially, when using Packer (or PackR for that matter), using ‘shrink variables’ plus gzip compression will result in the smallest an fastest-to-execute files. Base-62 is there in case you can’t use gzip for some reason: it creates smaller files than variable-shrinking on its own.

Where’s my inheritance?

Update: from what I can gather from going through the source code, $super in Prototype actually refers to the method in the parent class, rather than the old method in the current class. My point about the other libraries mentioned below stands, though. Also, my apologies to Dan, whom I cornered at @media Ajax and quizzed about Prototype’s stance on this issue.

There is one design decision in JS.Class that sets it aside from all the other inheritance libraries I looked at (Prototype, Base and Inheritance). With all those libraries, super means “the previous version of this method in this class”, rather than “the current version of this method in the parent class”. Now, if you’ve just built a class by inheriting from a parent class and then overwriting some of its methods, those two definitions amount to the same thing.

But JavaScript is a dynamic language, and I can add new methods to any class whenever I want. What if I want to replace a non-super-calling method with a method that does call super. More often than not, I don’t care how the method used to work (if I do, I can easily store a reference to it myself) but I do care about how the parent class’ method works. The aforementioned libraries leave you in the lurch here.

Now, consider the following inheritance situation:

var Car = JS.Class({});
var Ford = JS.Class(Car);
var ModelT = JS.Class(Ford);

Car.method('drive', function() {
    return 'Driving my Car';
});

ModelT.method('drive', function() {
    return this._super() + ', a Model T';
});

var a = new ModelT().drive();

Ford.method('drive', function() {
    return 'Driving my Ford';
});

var b = new ModelT().drive();

Car defines a drive method, which is inherited by Ford and ModelT through the prototype chain. Then ModelT defines its own drive function, which uses super. Clearly, this should refer to the drive method inherited from Car. But then, Ford defines a drive method. This will not be inherited by ModelT — it now has its own drive method — but the question arises about what super within ModelT#drive should refer to.

The prevailing wisdom with the libraries mentioned above is that it ought to refer to the current class’ previous implementation of the method, rather than the parent class’ current implementation. That is, super refers to the overridden method at the time the new method is defined, rather than the parent’s method at the time the new method is called.

Personally, I think this is madness. If I’m trying to debug some JavaScript and see the word this._super, the very first thing I’m going to do is inspect this.klass.superclass at that point in the code. I’m sure as hell not going to start wading through a large codebase (and if you need an inheritance model, I’m assuming you have a large codebase) trying to find out the order in which a particular method was overridden. Both semantically and practically, I think the “current method in superclass” method is superior to the “previous method in current class” one. In the above example, a contains "Driving my Car, a Model T" while b contains "Driving my Ford, a Model T".

It seems that a fair number of people disagree with this policy though, including the Ruby language (which JS.Class is modelled on), which actually inspects included Modules for super methods to use before working its way up through superclasses. I’d be really interested to know why this is, and whether there are compelling reasons not to do things my way. I might add support for the other libraries’ way of working if anyone can persuade me…

JS.Class updates

Yes, it only came out a couple days ago, but it’s a 0.9.x release, so it’s still being developed. If you downloaded JS.Class over the last couple days, I strongly recommend you upgrade to the latest version.

First off, it improves performance substantially over the initial release by inspecting method definitions to find out if they use this._super. If they don’t, they can be inserted straight into the class’ prototype without being wrapped in a _super-generating function. I believe Prototype and Base do something similar, though Inheritance seems not to.

Second, it fixes some subtle bugs to do with _super being reassigned when one _super-using function calls another _super-using function. This was a pretty basic oversight and was easily fixed.

Finally, it’s been much more thoroughly tested, the design has been tightened up, and instance method inheritance works better by using prototype chaining rather than brute-force method addition. That means you don’t have to use MyClass.method('name', func) if you don’t want to — you can just say MyClass.prototype.name = func and JavaScript’s own inheritance model will take care of the rest. (Although, if func uses this._super, you still need to add it using method.) Class method inheritance is still a bit of a pain, and you need to use MyClass.classMethod('name', func) if you want the method to be inherited.

Also, the docs have been augmented — I especially like the bit about module design and how closely you can mimic Ruby’s inheritance model using this library. As far as I know, this is the only JavaScript inheritance model in which you can use super without passing arguments back in, just like in Ruby.

Announcement: JS.Class

After mentioning Prototype’s inheritance model the other day, one rather important thing struck me about it. I was going to borrow their model for some of my own work when I realised that, if you use Prototype’s $super feature, your code will break if you compress it using a variable-shrinking algorithm (all the decent compressors do this). Prototype inspects the argument names of your functions and determines whether to use Function#wrap to pass in a reference to the overridden function.

So, what to do? We use YUI at work, but their inheritance model is so cumbersome as to be almost totally useless. I needed something better. Taking a few leaves out of Prototype’s model, and out of Alex Arnell’s Inheritance.js, I’ve come up with something that does just what I want. Basic features:

  • Simple, elegant single-inheritance model, including inheritance of class (static) methods
  • Clean, intuitive access to the class hierarchy from within instance methods, as well as through class interfaces
  • Automated inheritance: adding class/instance methods to a class after its initial definition instantly updates all its subclasses and their instances
  • Mixins, like in Ruby (this is essentially Ruby-ish syntax masking a trivial JavaScript feature)
  • super, with arguments optional
  • is_a support (JavaScript trivially supports has-a relationships itself)

Although this takes much of its syntax ideas from Ruby (that being the classical inheriting language I know best), it should be intelligeable to users of other classical OO languages such as Java (we are a Java shop where I work).

So, without further ado, go check out JS.Class.

Prototype’s Function#wrap

So Prototype 1.6 has finally hit the streets, and it looks to be a very nice piece of work. Though I’m no longer using Prototype at my day job (we use YUI, plus a layer of syntactic sugar that I’m in the process of writing), I’m interested to see what is possible with the JavaScript language. And, as it’s MIT-licensed, I can still borrow features from Prototype and weave them into my development toolkit.

A while back I wrote about how to intercept calls to JavaScript functions so you can alter their behaviour. Turns out that my method was unbelievably ugly and unnecessarily verbose: I was ignoring JavaScript’s functional capabilities and relying too much on copying techniques from Ruby. Let’s take a look at Prototype’s Function#wrap:

Function.prototype.wrap = function(wrapper) {
  var __method = this;
  return function() {
    return wrapper.apply(this,
        [__method.bind(this)].concat($A(arguments)));
  }
}

It’s quite simple really: it stores a reference to the function being wrapped (__method), and returns a new function (beginning at line 3), which I’ll refer to as foo. When foo is called, it creates a copy of __method bound to foo‘s scope (__method.bind(this)). It then calls wrapper in the scope of foo (wrapper.apply(this ...)), with the bound __method inserted as the first argument. It’s easier to see what’s going on here with some examples:

var add = function(a, b) { return a + b; };

There we have a very simple adding function with two arguments. Using wrap, we can overwrite this function and change its behaviour:

add = add.wrap(function(originalAdd, a, b) {
  return 2 * originalAdd(a, b);
});

add will still take two arguments, but wrap has inserted some magic behind the scenes to gives us a reference to originalAdd. After this wrapping operation, add(3, 5) returns 16 rather than 8. We could have done whatever we want with originalAdd inside our wrapper function to change the output of add — we could even choose not to call originalAdd at all and disable add for good.

Because of the way that wrap deals with execution scope, it works with object methods that use the this keyword:

var whizzBang = {
  name: 'Fizz buzz',
  
  say: function(thing) {
    alert(this.name + ' likes ' + thing);
  }
};

whizzBang.say('apples');
// --> alerts "Fizz buzz likes apples"

We can wrap whizzBang.say and all our uses of the this keyword will refer to the proper thing:

whizzBang.say = whizzBang.say.wrap(function(originalSay, stuff) {
  originalSay(stuff);
  if (!this.n) this.n = 0;
  alert(this.name + ' has ' + this.n + ' ' + stuff);
  this.n++;
});

whizzBang.say('oranges');
// --> alerts "Fizz buzz likes oranges", then "Fizz buzz has 0 oranges"


whizzBang.say('kiwis');
// --> alerts "Fizz buzz likes kiwis", then "Fizz buzz has 1 kiwis"

So this, both in originalSay and inside the wrapper function, refers to whizzBang, just as (I hope) you’d expect it to. This is really useful, and is actually how Prototype implements method inheritance with $super inside Class.create.