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.

Advertisements

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.

QuickUI 0.9.1 released

QuickUI 0.9.1 contains two changes:

First, it’s now even easier to create web user interface components in CoffeeScript. When CoffeeScript support in QuickUI was first announced a month ago, you had to include a boilerplate constructor. This was required to work around a limitation in CoffeeScript, in which CoffeeScript’s default constructor for a class didn’t return a value. (See a good summary of the issue here.) That issue has now been fixed in CoffeeScript 1.3.3. With a considerable degree of rework in the base Control class, you can now create a new user interface control in a single line of CoffeeScript:

control window.MyButton extends BasicButton

The QuickUI documentation for creating controls in CoffeeScript has been updated to reflect this.

Second, QuickUI 0.9.1 has a simplified model for generic styling. The QuickUI Catalog controls define generic styles that allow them to function without you needing to provide styling for them. You can easily turn off a base class’ generic style by setting the subclass’ generic() property to false.

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 0.9: a significant update

QuickUI 0.9 has been released. This is a major update which includes a number of changes that make it easier than ever to create reusable, extensible web user interface components.

  • The means by which classes are defined has been substantially simplified, which means that QuickUI is doing a lot less work when a class is defined. One result is that the previous Control.subclass() method has been replaced with a simple jQuery.sub() call. An overload still permits one to pass in a JavaScript object defining the class, but now everything in that object is simply copied over to the new class’ prototype. A new “inherited:” key now holds the Control JSON used to render the control; see the docs for more details.
  • The way you refer to an element within a control’s DOM has changed. Previously, you set an ID on an element in Control JSON using an “id:” key. Under the covers, this set an ID on the HTML element. As of QuickUI 0.9, to refer to an element in code, the Control JSON should include a “ref:” key. (See the tutorial example.) Under the covers, this will set a CSS class on the element. As before, this also implicitly creates an element reference function you can use to get that element through code: e.g., setting ref: “foo” on an element lets you get back to that element with the element reference function $foo().
  • A control’s initialize() method now implicitly invokes the initialize() methods of its base classes. Previously, you had to remember to have initialize() invoke this._super(), which was error prone. Failure to invoke this._super() would often mean that a base class’ event handlers didn’t get wired up, which could lead to bugs which were difficult to track down.
  • CoffeeScript support, announced earlier, has been folded into the core quickui.js runtime.

While the above work was underway, the QuickUI source code was substantially overhauled:

  • The aforementioned support for creating QuickUI controls in CoffeeScript has gone so well that QuickUI’s own runtime has now itself been ported to CoffeeScript. This does not mean that QuickUI developers need to use CoffeeScript; QuickUI supports plain JavaScript development and CoffeeScript development equally well. For people using QuickUI, this simply means that a number of planned improvements to QuickUI (including those listed above) could more easily be tackled.
  • The quickui.js runtime file itself is now built with Ben Alman’s handy Grunt build tool.
  • The optional QuickUI markup compiler has been moved into a separate GitHub repo, quickui-markup.

Please take a look!

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.

How QuickUI controls use code to specialize the handling of their content (in ways that might not be supported by Web Components)

As indicated in the earlier overview comparing QuickUI and Web Components, one significant difference between the two frameworks is that QuickUI allows code to run when a control’s content() property is set, while the Web Components spec does not currently allow for this. This post will attempt to begin making the case for the need for this feature, starting with an analysis of how that feature is used in QuickUI controls today.

The largest public body of QuickUI controls is QuickUI Catalog, which as of this writing includes 76 open source controls that handle a variety of common user interface tasks or serve as demonstrations of how to achieve common behaviors in controls. Of the 76 published controls:

  • 32 controls include code that runs when their content() property is set. Since the base Control class already provides a default content() property, these controls are overriding that base implementation. (In some cases, like PopupSource, the class’ content() property override is itself overridden by a subclass like ComboBox.)
  • Of the above 32 controls, 23 use their content() property override to delegate content to a sub-element. This is the standard approach in QuickUI for a control to incorporate content from its host. (For a working example, see this jsFiddle, in which a UserTile control delegates its content to a span inside the control. This topic is also covered in the second portion of the QuickUI JavaScript tutorial.) This is roughly analogous to what Web Components spec accomplishes with the proposed <content> element.
  • 12 controls (of the 76 in the catalog) are text box variations that delegate their content() property to a text box: either an <input> element of type “text” or a <textarea>. For example, the content() of a ListComboBox will be placed inside an <input>. Historically, HTML input fields have insisted on handling the field’s value through a string “value” property, whereas an element’s content is a DOM subtree. Despite the difference in data type, in many cases the distinction between “value” and “content” feels somewhat arbitrary. The convenience of a content property is just as interesting to a control that wants to render that content in a text box. For example, if a combo box is going to hold a list of animal names, it’s nice to be able to set the default content of that combo box in markup as:<ListComboBox>Dog</ListComboBox>. Naturally, this translation is lossy: if one passes a DOM subtree into such a control’s content() property, it’s to be expected that it will only preserve the subtree’s text. Nevertheless, it is highly useful to be able to define controls that render their primary content in text boxes.
  • 20 of the controls override their content() property to perform work whenever the content changes. The following table summarizes these 20 cases:
Control When content() property is set, the control…
AutoSizeTextBox Recalculates its own height to match that of the content.
ColorSwatchButton Transforms a string color name/value into a color.
ColorSwatchTextBox Transforms a string color name/value into a color.
HighlightEffects Recalculates its height/width.
HintTextBox Shows hint text if the content is empty.
Menu Recalculates the width of a subelement (a “shield” element that must be exactly as wide as the content to achieve a particular visual effect).
PackedColumns Recalculates its layout.
PanelWithOverflow Recalculates its layout.
PersistentPanel Checks to see whether the panel should be docked or not.
PopupButton Adjusts its layout if the content is not empty.
Repeater Copies the content into the array of repeated sub-controls.
SearchBox Enables its search icon if the content is not empty.
SlidingPages Recalculates its height/width.
SlidingPagesWithDots Updates the number of page buttons to match the number of pages (i.e., child nodes) in the content.
Switch Determines which child should be visible.
Tab Lets the parent tab set know the tab’s size may have changed.
TabSet Creates a tab button for each tab page.
TextBox Generates a programmatic “change” event.
TextCondenser Determines whether the text should appear condensed to help it fit.
ValidatingTextBox Validates the contents.

To summarize, these controls are doing the following types of work when their content changes:

  • Adjust its dimensions or the dimensions of some subelements (e.g., AutoSizeTextBox, Menu).
  • Layout contents to achieve results not directly supported in HTML and CSS (e.g., PackedColumns, PanelWithOverflow).
  • Transform or manipulate the content before rendering it (e.g., Repeater, ColorSwatch).
  • Update its own subelements based on the content (e.g., TabSet, SlidingPagesWithDots).
  • Validating content (e.g., ValidatingTextBox, and its subclasses like DateTextBox).

Such controls represent a significant percentage of the QuickUI Catalog — approximately 25% — and it’s very likely that similar results would be found in other QuickUI-based projects. And in addition to the scenarios listed above, other scenarios likely exist in which a control wants to perform work when its content changes.

Overall, this pass through the QuickUI Catalog suggests that many interesting user interface components have a need to perform work when their content is set — to do something more than passively hold the content they’re passed. At this point, it’s not exactly whether the aforementioned QuickUI controls could be successfully ported to Web Components as the spec currently stands, which would be unfortunate. (As stated in the previous post, a long-term vision for the QuickUI framework is that controls created in QuickUI can be transitioned to a Web Components foundation in the future.)

It’s possible that a component could use forthcoming support for DOM mutation observers could be used to track changes to its own content, but whether this would work, or work well, is not yet known. A control could also force its host to invoke some method on the control whenever the host changes the control’s content, but that would be unfortunate; it would place extra work on the developer, and a host’s failure to properly notify the control that its contents have changed could lead to subtle bugs.