Some lessons from an open source project that never gained critical mass

I recently announced that I was halting development on QuickUI, and thought it would be a good idea to do a little post-mortem before moving on.

The good side: As a framework for web application UI development, QuickUI measured up to its design goals. It was useful for creating complex application UIs with a good separation of concerns between UI components. The core framework was highly reliable with a fairly tight abstraction and acceptable performance. QuickUI was used in some companies for real production apps with real users. The very small number of developers who actually used the framework said they liked it and were impressed by what it could do.

The bad side: As an open source project, QuickUI never achieved critical mass. QuickUI was my first attempt at kickstarting an open source project to help establish an ecosystem for component-based web user interfaces. I’d initially held the naive view that simply publishing something as open source (which I did in late 2009, two years into QuickUI’s development) would, on its own, generate community interest and participation. But the universe of open source development projects is vast, and simply making something free doesn’t make it popular. Free products still need to appeal to their audience and gain adoption through a good feature set, great distribution, and substantial luck.

Eventually, QuickUI was overtaken by open web component standards (which is a good thing), and it no longer made sense to continue investment in QuickUI. Before moving on, I wanted to write down some of the lessons the QuickUI project held for me.

  1. People care about the stack of technologies beneath your project. I used to think that all that mattered is whether a tool worked and was easy to use, but most developers make demands the construction of the tool itself: programming language, runtime platform, dependent libraries, etc. The most common reason someone will offer for this is that they may need to diagnose a bug in the code and fix it. That may also be true, but I think most people have less glorified reasons for considering the technology behind a tool.

    First, simply understanding the vocabulary associated with a given stack requires investment. Occasionally you come across a tool on GitHub whose Readme says the tool can be configured via a .foo file, where the location and syntax of a .foo file is completely obvious to current users of that tool’s stack. If you don’t already know what a .foo file is, you’re less likely to adopt that tool.

    Second, a developer toolchain is a creaky, cantankerous beast, and incorporating multiple stacks of tech is a pain. This is less about debugging than what Bruce Sterling refers to as the wrangling required to get things to work together.

    Third, you trust tools on stacks that have worked for you in the past, and are skeptical that tools on unfamiliar stacks will actually work as advertised. For example, I’ve hardly ever used Ruby, and rarely use Ruby gems. When I see a tool published via npm, I feel comfortable installing and using it, even if I never look at its source, because I’ve used many tools that way. If I see a tool that does the exact same thing published as a Ruby gem, I view its efficacy as black magic.

    Last, people implicitly trust other people who have selected the same technology stack. “If someone has made the same technology choices I have, they must be as enlightened as I am!” Conversely, people look askance at those who make different choices. A die-hard plain JavaScript coder may view the Clojure community are pot-smoking hippies, while the Clojure developer may view the original party as a latter-day COBOL dork lacking sufficient brainpower and awareness.

    In the case of QuickUI, when I started on it in late 2007 or so, I was most comfortable writing in C#, so when I needed to write a build-time compiler for UI markup, I wrote it in C#. Bad idea. Despite the fact that there was no run-time need for .NET, and that the compiler ran perfectly well on a Mac (under Mono), no one would take it seriously with the taint of .NET on it. I was eventually able drop the compiler altogether, and rely on a stack of tools which jQuery developers were already familiar, but that cost the project time and effort.

  2. Using anything other than native web technologies — plain HTML, plain JavaScript, and plain CSS — significantly constrains your audience. This is similar to the above point, but pertains to your project’s source code rather than the stack of technologies supporting that source. Again, part of the argument here is that they might theoretically need to dive into the runtime source to diagnose a problem, but I think the reaction is usually more instinctive than that.

    At one point in the development of QuickUI I discovered that working in CoffeeScript was much more productive for me than in plain JavaScript. In short order, I ported the QuickUI runtime to CoffeeScript. Switching to CoffeeScript was a huge productivity boost for me — but represented a huge reduction on the potential audience for QuickUI.

    For one thing, it seemed nearly impossible for me to get potential developers to ignore the presence of CoffeeScript. CoffeeScript compiles to plain JavaScript, but anyone who looked at the QuickUI source repo saw “CoffeeScript” listed as the primary language… and walked away. They might say, “Your project looks interesting, but I don’t know CoffeeScript.” I’d tell them they didn’t need to know CoffeeScript — that was an implementation detail — but they’d already decided they were uninterested.

    Over and over, the general feeling was, “I just don’t want to use something that uses something I don’t already know.” And then, of course, for most people who really did want to be able to grok the source, CoffeeScript was a non-starter.

    To build a community around a project, you probably want as many people as possible to be able to participate. Even if you hate JavaScript, it’s the web’s lingua franca. Using any other language for an open web project may not be an insurmountable obstacle, but at the very least it’s a significant handicap. As much as it pained me, when I started up the subsequent Quetzal web components experiments, I did so in plain JavaScript.

  3. Everyone will insist there is one thing you must do that will make your library more acceptable — and all those things are different, and all those things together are probably still insufficient. Over the course of the past few years, I have given many, many QuickUI demos, and received feedback on all aspects of the tool, the accompanying site at quickui.org, the learning process, etc. Very little of this feedback was consistent; everyone fixated on something different. I thought, if I just respond to all the feedback, surely at some point the barrier to adoption will be low enough that people will start adopting the tool.

    On the basis of such feedback, I spent a huge amount of time improving things. Early on, someone said I should move the source to GitHub, so I did. Someone said it needed better documentation, so I wrote a lot of documentation. As discussed above, numerous people suggested moving away from .NET, so I did. Someone suggested having live examples of UI components, so I built those. Someone thought a tutorial would be helpful, so I made an interactive tutorial. (Which many people complimented. Thank you!) One person’s key complaint with the entire framework was that the home page didn’t have icons; if the framework was to be successful, the home page needed little icons to indicate which browsers were supported by the framework. I did that. I received many, many other suggestions, and I incorporated almost all of them.

    None of it mattered. The feedback was actionable, and probably much of it was accurate, but even addressing (nearly) all of it wasn’t enough to make the project successful.

    The fact is that most people are unwilling to invest the time to understand, analyze, and articulate what’s really wrong with your project. Of the people who gave me feedback, few of them actually looked hard at it, very few had actually tried it beyond the online tutorial, and very, very few were willing to speak directly to their key concerns. This is all understandable — people are busy, spending time on a framework of unknown value is potentially wasted, and most people want to be nice to you — but feedback on a project should be accepted with these phenomena in mind.

  4. Paradigm shift is prohibitively expensive. Early on, one person told me that building UI in a component-oriented fashion represented a significant paradigm shift — and that represented a potentially insurmountable obstacle for QuickUI.

    The problem with a paradigm shift is that it’s hard to even have a conversation with someone whose conceptualization of the world doesn’t even allow them to recognize the problem they have. I spoke with many developers who viewed the undifferentiated pile of JavaScript generating their UI as the way things had to be done. They were more concerned with getting their UI to work across multiple browsers than to worry about componentization — even though a good component library is exactly the sort of thing that would have made cross-browser work more manageable. (The cross-browser hacks could have been folded into the components, allowing them to work at a higher level of abstraction, etc.) Interestingly, these same developers would carefully factor their code into classes or functions with clear lines of responsibility. They applied good factoring to every other thing they coded except their web UI.

    Over the past year or so, Google and others have been evangelizing a component-oriented paradigm for web development. At some point, we’ll go through some phase-change where that paradigm will suddenly become dominant. I’m betting that change will happen before late 2015. By then, it will be hard to find a good web UI developer who doesn’t think of their UI in terms of components.

  5. People are only interested in something if others are already using it. This is true for both seasoned developers and novice developers — but for different reasons. The novice teaches themself jQuery or Backbone or LESS because experienced people use those things, which means they’re probably interesting and useful. The seasoned developer picks up a new tool that others are using because the alternative — using something with a tiny user base — represents unacceptable risk.

    This last point was made to me by the most abrasive person I ever spoke with about QuickUI. In fact, I think it’s because they were untroubled by politeness that they could speak the truth. They said: “I would love to use this, but I can’t. If something were to happen to you, I would be stuck having to fix your bugs. I made a bet like this in the past, and was stuck supporting someone else’s framework. I won’t do that again. Come back when lots of other people are using this.”

    So this developer had, at some point, found a great piece of technology, developed by someone else, and they staked their own reputation on adopting this technology, only to have it completely fall apart when the other party went away (went bankrupt, was acquired, whatever). It’s probably safe to assume that most seasoned developers have had a similar experience. For every open library, there must exist some critical mass at which the library’s community becomes self-sustaining.

    At that point, if you find a bug in the library, someone else in the community has probably also found the bug, and maybe even fixed it. Enough other people are invested in the library that, even if the original developer disappears, the remaining investors will keep it going for as long as that makes technological sense.

    I’d be very interested if someone could pinpoint the size of that critical mass. I’m guessing the number is pretty small: perhaps 10 active contributors might be sufficient to create the perception the library is well-maintained and not going away. Whatever that size is, I couldn’t grow QuickUI to that size.

  6. Google could publish a JavaScript library for cloud-based ham sandwiches and a thousand people would immediately star the repo on GitHub. For much of my career, I focused my attention almost entirely on the value a product created, and gave very little thought to how a product would be distributed. Distribution is, in fact, at least as important, and maybe more important, than underlying value. That’s certainly true in the short term. And, over the long term, well, maybe technology changes quickly enough that the long term never comes into play.

    I’m not saying individuals can’t launch successful open source projects, but rather that doing so within the context of a company with name recognition and a developer outreach program makes it much, much easier. The people working within such a context may not realize it. I once heard someone describe people who work at big companies as “basketball players on the moon”. Those people can jump very high, but they may not realize the extent to which their performance depends on that context.

    I have deep respect for a person who can launch something entirely on their own, without relying on the backing of their company (or industry name recognition predicated on work they launched previously at some earlier company). If someone can make a disruptive technology successful entirely on its own merits, both that tech and that person are impressive indeed.

Ah, well, live and learn. I’m still looking forward to watching the web’s UI component ecosystem take shape, because we’ll all get to make awesome stuff together.

Advertisements

Polymer list box and combo box elements

The updated Quetzal home page shows off a handful of new elements ported from QuickUI:

  • A quetzal-list-box element that presents its children as items in a list. This makes it easy to give any collection of DOM elements the semantics of a single-selection list. The actual tracking of the selection is handled with Polymer’s own polymer-selector element. On top of this, the Quetzal list box adds keyboard navigation: the user can navigate the list using the Up/Down arrow keys, as well as Home/End and Page Up/Page Down. This keyboard navigation follows the Microsoft Windows model, in which navigation keys move the selection, which in turn forces the list’s scroll position to update to show the selected item. This makes it faster to select an item with the keyboard. (In Mac OS X, paging up and down does not update the selection.)
  • A quetzal-combo-box element ties together a text input element, a popup, and a button to invoke or dismiss the popup. See this post on the original QuickUI combo box for details on combo box behavior. Again, a key feature here is keyboard support: the Down key invokes the popup (if it’s not already open), and the Escape key dismisses it. Another feature (inherited from the popup-source element) is positioning the popup above or below the text area as room allows. This combo box element doesn’t provide a specific popup UI. Rather, it’s intended to be used as a base class for custom combo box elements.
  • A quetzal-list-combo-box element combines the two above elements to create a typical combo box which presents choices as a dropdown list box. This includes standard auto-complete behavior. In many situations, a combo box like this is often a better UI solution than a plain text box with auto-complete: the user has a clearly visible button which can be used to invoke the complete list of choices. This is more discoverable than requiring the user to begin typing to see what the possible choices are. The auto-complete behavior matches against the textContent of the elements’ children, so the list items can be any type of item that has meaningful textContent. The sample shown uses a custom element that shows a color swatch next to a color name; typing some text will auto-complete against the set of color names.

These elements still need more work. For example, the combo box needs a stock mobile variant in which the element can fill the screen when making a selection to provide bigger hit targets and maximize the number of visible list choices. Also, at the moment simply tapping a list box element causes the Android Chrome browser to crash. This makes it somewhat hard to debug. 😦 Nevertheless, I think these element demonstrate that a good set of UI base classes will make it much easier to create custom UI designs as web components take hold.

QuickUI breaks with CoffeeScript 1.5

Bad news: this week’s release of CoffeeScript 1.5 is incompatible with even the current QuickUI release, 0.9.3.

QuickUI goes through significant trouble to subclass jQuery because of jQuery’s complex constructor. jQuery depends on an unusual feature of JavaScript called an “other typed” constructor: a class constructor that returns something other than a plain instance of the class being instantiated. When the CoffeeScript project considered dropping support for such constructors, cases were made to keep that feature (see CoffeeScript issue #2359, but other people made similar cases on other issues). However, those arguments did not carry the day, and as of CoffeeScript 1.5, “other typed” constructors are rejected by the compiler. This effectively breaks the CoffeeScript source for QuickUI itself as well as for QuickUI Catalog.

Possible fixes are being investigated, but this issue runs very deep, and a number of straightforward workarounds have already been ruled out. A real fix will likely require a substantial change to the way QuickUI instantiates controls. For the time being, it is recommended that QuickUI developers use CoffeeScript 1.4.0.

Sample Contacts application using Backbone and QuickUI

Back in April, someone evaluating QuickUI made the completely reasonable request to see a complete sample application created in QuickUI. More specifically, they were interested in seeing a demonstration of how to use QuickUI as the View in an MVC (Model-View-Controller) application, ideally using the popular Backbone.js library. QuickUI is well suited to fill that role, and a sample application has now been created to show off how to do exactly that.

The result is a sample Contacts application built in QuickUI. The sample takes advantage of QuickUI’s support for CoffeeScript, which turns out to be an elegant language to express both Backbone and QuickUI classes.

Read the sample’s documentation for more details of its construction.

How jQuery instantiates objects as jQuery.fn.init, and what that means if you want to subclass jQuery

In order for the recent release of QuickUI 0.9.1 to support concise creation of control classes in CoffeeScript, it was necessary to go deep into the bowels of jQuery’s class constructor to determine how it worked. Those findings are documented here in case others have a similar need to subclass jQuery, or would like to address the same need that drove jQuery to its current implementation.

The jQuery class constructor can be found in core.js:

jQuery = function( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
}

But the comment doesn’t do much to explain why init exists, or how it works.

All jQuery developers are familiar with the form $(“div”), which is a shorthand for the longer jQuery(“div”). This, we are told, returns a new jQuery object. Actually, from the above constructor, we can see that what it really returns is an instance of the jQuery.fn.init class. (From here on out, we’ll just refer to that class as “init”.) The init constructor is defined like so:

jQuery.fn = jQuery.prototype = {
    init: function( selector, context, rootjQuery ) {
        ...
    }
}

Here, first note that jQuery.fn is just a synonym for jQuery.prototype. Given that, we see that the init class constructor hangs off the jQuery prototype. Stashing the init class on the jQuery class’ prototype allows the jQuery library to avoid polluting the JavaScript global namespace with an extra class. (Of course, init could easily have been defined inside the outer jquery.js function closure, which would avoid namespace pollution and prevent access to it from outside. The init class isn’t really referred to elsewhere in the jQuery source, so it’s not immediately clear why that wasn’t done. Perhaps the above approach makes for easier debugging.)

Further on, we see this init class defined as a subclass of the jQuery class:

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

Since jQuery.fn is just an abbreviation for jQuery.prototype, the above line is really:

jQuery.prototype.init.prototype = jQuery.prototype;

This ensures that any instance of init will also be a functional instance of jQuery. This can be confirmed in the debugger:

> $e = $("div")
> $e instanceof jQuery
true
> $e instanceof jQuery.fn.init
true

So all those times when you create an instance of jQuery you are actually working with an instance of a jQuery subclass.

Okay, but why bother? One reason is that jQuery wants to support a static constructor form: one you can invoke with needing to specify “new”. Regardless of whether you invoke the jQuery() constructor with “new” or not, it’s always going to return an instance of the init class. And, because init is a subclass of jQuery, you’ll end up with an instance of jQuery, which is what you wanted.

// The following lines are all equal.
var $e = new jQuery("div");
var $e = jQuery("div");
var $e = new $("div");
var $e = $("div");

So at least one reason init exists is that it serves as a helper class to let you write shorter jQuery code. The thing is, supporting instantiation without “new” doesn’t require defining a separate helper class.

The jQuery constructor above is relying upon an oddity in the JavaScript language: a constructor can return an object that’s an instance of a class other than the class defined by the constructor. The jQuery class could more easily use the simpler factory constructor pattern to check to see whether it’s been invoked without “new” (in which case “this” will be the window) and, if so, just return a new instance of itself. That is, in fact, how jQuery worked back in jQuery 1.1:

var jQuery = function(a,c) {
    // If the context is global, return a new object
    if ( window == this )
        return new jQuery(a,c);
    ...
};

By jQuery 1.2, however, the jQuery constructor was using the technique shown above. It’s hard to tell from the code exactly why the init helper class was introduced. One possibility is that init has that extra rootjQuery parameter which is for internal use only. Burying that parameter in a helper class avoids having to expose the parameter in the jQuery API, where it might confuse jQuery developers or, worse, encourage them to create code that depends upon that parameter.

Subclassing jQuery

One cost of jQuery’s class scheme is that it makes it much harder for you to subclass jQuery. One reason you might want to do this is to provide scoping for your own jQuery plugins. If you want to add a lot of plugins to jQuery’s prototype (which, as indicated above, is what you’re doing when you add something to jQuery.fn), you could potentially pollute the jQuery namespace and run into conflicts with other plugins. By subclassing jQuery, and working strictly with instances of your subclass, you hide all your plugins from anyone who’s directly instantiating the plain jQuery class.

Unfortunately, because of this init helper class, the normal JavaScript prototype-based subclassing scheme won’t work with jQuery. To make your subclass jQuery-like, you end up needing to replicate jQuery’s complex helper class arrangement: create a subclass of jQuery and a companion init helper class, derive your helper class from your actual jQuery subclass, and ensure your subclass’s constructor actually returns an instance of your init class.

The mind-breaking pain of all that is presumably what led to the creation of a jQuery function called $.sub(). That function does exactly what’s described above: it defines a new subclass of jQuery and a companion init helper class.

The $.sub() plugin doesn’t seem to be used much, perhaps because its benefits and reason for existence aren’t well-documented. The announced plan is that $.sub() will be removed from the core jQuery library in version 1.8, and transition to become an official plugin. As a result, $.sub() is deprecated as a native jQuery feature, but $.sub() and its technique will continue to be useful, so it’s still worth understanding and considering it.

QuickUI relies upon the $.sub() technique to make its base Control a subclass of jQuery. This is what lets you use any jQuery feature with QuickUI controls directly: you can bind events to them with $.on(), you can style them with $.css(), and so on. That’s because your control class derives from Control, and so ultimately derives from jQuery.

You can create a new QuickUI control class in JavaScript by invoking Control.sub(). And, with QuickUI 0.9.1, you can now create subclasses of Control (and, therefore, jQuery ) using CoffeeScript’s built-in class syntax, which is concise and highly legible. In either language, you can easily create your own reusable web user interface components that have direct access to all the power of jQuery.

Some observations on porting the QuickUI runtime from plain JavaScript to CoffeeScript

This post shares some highlights of the experience porting a non-trivial library from plain JavaScript to CoffeeScript in case other parties are considering a similar transition.

Yesterday’s announcement of QuickUI 0.9 mentioned that the framework source code has now been ported to CoffeeScript. The QuickUI framework is intended for plain JavaScript development as well; nothing in the change of source language changes that. But experimentation with the CoffeeScript language suggested there were enough advantages to the language that, going forward, it would be worth porting the runtime from plain JavaScript to CoffeeScript.

Overall, the port from plain to JavaScript to CoffeeScript went rather smoothly, and the bulk of it took about two days. The QuickUI runtime, quickui.js, is a reasonably complex JavaScript library, which is to say that it’s not a toy or trivial sample application. The last plain JavaScript version of the QuickUI runtime, quickui-0.8.9.js, was about 7700 lines of plain JavaScript (including comments), or about 60K, developed over the course of four and a half years.

Automatic translation with js2Coffee

The handy js2coffee conversion tool was used to kickstart the port. Kudos to Rico Sta. Cruz for this great tool.

  • The automatically translated CoffeeScript immediately passed 97% of the QuickUI unit test suite. The remaining 4 broken tests were do to a single issue related to translation of the “instanceof” keyword, which was easy enough to work around.
  • The one thing js2coffee doesn’t translate (yet) are comments, so these had to be copied over by hand. Tedious, but straightforward.
  • Similarly, the js2coffee output sometimes produced long lines that needed to be hand-broken for legibility. Again, a bit tedious but straightforward.
  • Once all unit tests passed, the unit tests themselves were ported to CoffeeScript by the same process.

After about a morning of work, a CoffeeScript-based quickui.js was functional. It passed all unit tests, and could actually be used to drive a non-trivial QuickUI-based body of code like the QuickUI Catalog.

Towards idiomatic CoffeeScript

After the mechanical port with js2coffee, various CoffeeScript idioms were applied incrementally to replace the standard JavaScript idioms with their more concise CoffeeScript versions. This took another day and half or so.

  • There was occasion to use pretty much all of CoffeeScript’s syntactic sugar. References to Foo.prototype.bar() were replaced with the more concise Foo::bar(). Closure variables to hold “this” for use in an event handler were replaced with CoffeeScript’s “=>” syntax. Etc., etc.
  • Because CoffeeScript can wrap a body of code in a single function closure, this no longer needed to be done by hand. A wrapping closure like that can complicate the management of a pile of plain JavaScript files. The closure will typically have to be created through a build process that includes a JavaScript fragment (to start the closure) before the real JavaScript files, and another fragment (to end the closure) afterwards. (The jQuery Makefile does this, for example.) CoffeeScript’s built-in support for a closure that spans multiple files finally made it easy enough to break up the quickui.js runtime from a single monolithic JavaScript file into a much saner and more manageable collection of CoffeeScript files. That is, while the same degree of manageability could have been achieved in plain JavaScript, CoffeeScript made it simple enough that it actually got done.
  • The QuickUI runtime itself doesn’t create many classes, but in some cases (e.g., the unit test suite), classes could be created via CoffeeScript’s concise class syntax. This took advantages of QuickUI’s new support for creating web user interface controls using CoffeeScript class syntax.
  • JavaScript “for” loops were replaced with CoffeeScript list comprehensions.

Idiomatic CoffeeScript iteration over jQuery objects

Speaking of “for” loops, it turns out that a good deal of the QuickUI runtime deals with looping over jQuery objects. QuickUI controls are a subclass of jQuery object, and when looping over them in plain JavaScript, it’s often convenient to use jQuery’s $.each() function. For example, this function invokes foo(), a jQuery method or plugin, on each element in a jQuery object:
var $elements = $(".someClass");
$elements.each( function( index, element ) {
    $( element ).foo();
});
Note that $.each() gives the callback the plain DOM element, so you have to wrap that element with $(element) to get a jQuery object you can then manipulate. To simplify that, QuickUI’s runtime has long had a helper function called eachControl() that gives the callback the element as a wrapped jQuery object. (In QuickUI’s case, it also ensures the control’s particular subclass of jQuery is used, so that you can directly manipulate the control with that control’s own specific API.) E.g.:
var $buttons = $(".BasicButton");
$buttons.eachControl( function( index, $button ) {
    $button.foo();
});
To take best advantage of CoffeeScript’s supports for looping constructs, a simple jQuery plugin was created to create an array that can directly be used by CoffeeScript’s “for” loop and list comprehensions. This plugin, called Control.segments(), converts a jQuery object that holds a number of elements into an array of jQuery objects that each hold a single (wrapped) element. The definition of segments() in CoffeeScript is trivial:
Control::segments = ->
  ( @constructor element for element in @ )
QuickUI defines segments() on the Control class so as not to pollute the general jQuery plugin namespace, but the above definition could just as easily be done as jQuery::segments to create a plugin that worked with any jQuery object. In any event, the result of applying segments() to a jQuery object is an array that can be directly iterated over, while at the same time preserving type information.
$button.foo() for $button in Control(".BasicButton").segments()
Here, the looping variable $button ends up holding an instanceof BasicButton (which is also an instanceof jQuery), so $button.foo() invokes BasicButton.prototype.foo().
This “for” loop feels more direct and idiomatic in CoffeeScript than the standard $.each() approach. (In fact, it’d be nice if $.each() were extended so that, if invoked without arguments, it returned an array just like segments() does here.) This segments() call can also be used in CoffeeScript list comprehensions, thereby replacing many situations in which $.map() is currently used. A jsperf experiment suggests the segments() approach performs roughly as well as the standard $.each(). The generated JavaScript for segments() does build a temporary array of results, but it avoids the need for the callback function and the accompanying closure.

Impressions

The new, CoffeeScript-based QuickUI source code gets compiled to a plain JavaScript file that’s essentially the same size as the handwritten JavaScript (61K vs 60K). The new runtime appears to perform and function just as well as the earlier plain JavaScript one, so QuickUI developers shouldn’t notice any difference. At the same time, the new CoffeeScript source code feels a lot tighter and easier to read and maintain.
This ability to write tighter code has already invited the successful implementation of a number of long-planned improvements to the runtime. It’s hard to say how many of those improvements were easier to tackle because of advantages in the CoffeeScript language itself, and how many were tackled just because CoffeeScript is a shiny, new tool. But as a general rule, it seems that CoffeeScript permits a programmer to more directly express their intention than one can do in JavaScript — and any language that can do that is a step forward.
Best of all, using any language like CoffeeScript that compiles to plain JavaScript enables a developer to finally break a hard dependence between language choice and the user’s browser. Now that QuickUI itself is written in CoffeeScript, it can take immediate advantage of improvements in CoffeeScript the day they appear, instead of waiting years for incremental JavaScript improvements to make their way through committee, into browsers, and into users’ hands.

QuickUI now lets you create user interface controls in CoffeeScript

QuickUI now supports the use and creation of web user interface controls in CoffeeScript, a language that adds many useful features to the JavaScript language. Through its compiler, CoffeeScript can be easily used as a replacement for JavaScript in many web projects.

QuickUI turns out to be a natural fit for CoffeeScript. One of the nice features in CoffeeScript is that you can create classes with the language’s built-in “class” syntax. You can take advantage of that syntax to create new QuickUI control classes, simply by extending the base Control class or any other control class:

# A simple button class in CoffeeScript
class window.HelloButton extends BasicButton
  constructor: -> return Control.coffee()
  inherited:
    content: "Hello, world!"
  genericSupport: true

QuickUI control classes are subclasses of jQuery, so one of the key features in QuickUI’s new support for CoffeeScript is actually being able to create jQuery subclasses in CoffeeScript. CoffeeScript generates a prototype-based class that is similar to the classes produced by jQuery’s $.sub() feature (a core part of jQuery that will be moved to a plugin in jQuery 1.8), but jQuery’s classes require a rather Byzantine construction sequence. This is handled through the boilerplate constructor shown above. When Control.coffee() is called, it fixes up the CoffeeScript class so that it conforms to jQuery’s notion of how its class constructors should work.

With this in place, it’s now possible to create QuickUI controls in CoffeeScript with significantly less source code than the equivalent plain JavaScript. This is an overall win for web UI developers. If your team hasn’t already taken a look at CoffeeScript, now might be a good time.

Creating QuickUI controls in CoffeeScript currently requires a plugin, but the plan is to fold CoffeeScript support directly into the quickui.js runtime. Read the documentation for QuickUI support of CoffeeScript for more details.