There were a lot of buzz recently about Sproutcore and Objective-C, a desktop architecture and language from the Apple platform that are adapted (or ported) to the JavaScript world. There is one great idea in Cocoa (built using Objective-C): yes it’s MVC but I want to talk about the Key-Value Observer. It offers a great abstraction for creating RIA from my point of view, but let’s start at the beginning.
aHtmlElement.onclick = function() { }
formerly DOM level 0 is how you can handle native events in a very simple manner. I reminds me the C# delegate
s (that are using the +=
operator thus). Very simple and useful (but only one at the time, so very restrictive).
DOM level 1 introduces the addEventListener
(or attachEvent
for MSIE). I’m sure that the Java-guys will reminds the java.util.EventListener
that you are using everywhere in any AWT/Swing application. The main difference is that JavaScript works at the function level and not object one. Java is not a functional languae.
Then some JavaScript framework/libraries offers a different kind of handling events. YUI, Dojo or jQuery have interesting ones. The great advantages of messages passing over function calls is that you separate the producer from the consumer (decoupling) and become more robust; if no one care about a message, it’s simply lost, but if something linke ten differents processes cares about it, they will for sure get it.
If you made a little bit of Qt®, Dojo have the connect method: dojo.connect(myObject, "onclick", function() {});
It’s still DOM level 0 method overloading, not very clean but simple. It has the advantage to works with non-native events (or with any functions call in that particular case).
YUI pandora box contains the CustomEvent, a very simple implementation of the Gang of Four (GoF) Observer pattern. It’s used in more or less in every single YUI widget.
var event = new YAHOO.util.CustomEvent("my type"); event.subscribe(function(type, data){ alert(type + ": " +data) }); event.fire("Hello World!");
jQuery has also a custom event handling system included. It’s very powerful and kind of no so documented. It reminds me the GObject signal used by GTK.
$(document). bind("my-type", function(event, data) { alert(event.type + ": " + data); }). triggerHandler("my-type", ["Hello World!"]);
I’d like to see a centralized system for messaging passing. I toke example on how Bayeux is made, some XMPP parts too, and wrote a pubsub class. It has the advantage that you don’t have to keep track of the object that manages the events and can subscribe to meta-channels (using the star *
).
new pubsub(). subscribe("/test/first", function(data) { alert("first got: "+data); }). subscribe("/test/second", function(data) { alert("second got:" + data); }). subscribe("/test/*", function(data) { alert("a message has been sent: "+data); }). publish("/test/first", [1]). publish("/test/second", [2]). publish("/test/third", [3]);
Now, what are offering Sproutcore or Objective-J to JavaScript? Key-Value Observer. That means you aren’t creating specific custom events, or channels but will observe objects’ values directly. It’s a very simple to do, the only trade off is to access them with getters and setters only (which sucks).
var label = function(name, value) { this.name = name||""; this.value = value||""; }; // label inherits from observable label.prototype = new observable(); label.constructor = label; // you can also chain the followings. var my_label = new label("my label"); my_label.observe("value", function(value) { alert(this.name + " is: " + value); }); my_label.set("value", "Hello World!");
With all those tools, it’s very easy to imagine a complex rich internet application made of independent modules. Those modules don’t know each other directly, gets notified when something they are looking for happens. You can transform it into a MVC-like architecture with one kind of module for each type; displaying with HTML/CSS, reacting to HTML events, reacting to asynchronous events like XHR, storing data information.
All those issues have been handled by desktop software for years. I think it’s time to learn from it and get the best in terms of simplicity, reliability and strength. It’s also a lot easier to unit test small modules or to create brilliant mash-ups upon them. Being unobtrusive is maybe still the first step that many JavaScript applications have to face (with event delegation all over the place), the second one could be to not act as spaghetti code with as few cross references as possible. Rich internet application is becoming serious, so make sure it’s also as kind as possible to everyone, with ARIA for example.