Sunday, March 24, 2013

Leveraging the jQuery UI Sortable Widget in a Backbone-based Data List

Creating a sortable list of items is a common user interface pattern. The jQuery UI Sortable interaction widget makes it very easy to enable this feature in your page. If your list is based on a set of data represented by a Backbone collection, you'll need to find a way to bind the state of the sorted list into the collection's models so they can be saved. Most likely, you'll have an attribute in the model that records the order and configure the collection to sort on that attribute. The goal is to bind to that column and use it to control the sorting and update it when the user interacts with the Sortable widget.

Let's say you have the following simple model/collection defined:


var ThingModel = Backbone.Model.extend({

defaults: {
order: 0,
title: ''
}

});

var ThingCollection = Backbone.Collection.extend({

model: ThingModel,
comparator: 'order'

});


Using that simple collection, I'm going to recreate the basic Sortable demo using Backbone views driven from the data in the above collection/model definitions. Since we're working with a list of things, it makes sense to use a list/item view pattern to render our data source. The item view will represent each LI element in our list. Since our model only contains one other attribute other than the order column, this view is relatively simple:



var ThingItem = Backbone.View.extend({

template: null,

tagName: 'li',
className: 'ui-state-default',

render: function () {

this.$el.html( this.model.get('title') );

return this;
}

});


Now we can begin building the list view which will contain the bulk of the logic required to manage the sorting of the list. This view will render a UL element which will then contain the LI elements rendered by the item view above:



var ThingList = Backbone.View.extend({

tagName: 'ul',

itemView: ThingItem,

_listItems: null,
_listIsSyncing: false,

orderAttr: 'order',

render: function () {

this._listItems = {};

this.listenTo( this.collection, 'sync reset', this.listSync );

this.listSync();

return this;
},



This sets up the basic entry point of the view - initialize an object to hold the item view references, start listening to events from the collection, and draw anything that is currently in the collection.

The listSync() function is designed to handle rebuilding the whole list. It cleans up any existing item views and then passes the new set of models through to the listAdd() function to actually instantiate the item view:



listSync: function () {

var list = this.collection.models

this._listIsSyncing = true;

_.invoke( this._listItems, 'remove' );
this._listItems = {};

for ( var m in list )
this.listAdd( list[m] );

this._listIsSyncing = false;

this.listSetup();

},



Before looking at the add/remove functions, the listSetup() function is the place where the Sortable is actually attached, configured, and bound to enable moving items around. The function seems pretty empty because this is generally where I put any other UI configuration code. Its called anytime the list changes its contents to allow the supporting UI elements to change in response. In this example, there are none so its pretty light:


listSetup: function () {

this.$el.sortable({ containment: 'parent', tolerance: 'pointer' });

},

events: {
'sortupdate' : 'handleSortComplete'
},

handleSortComplete: function () {

var oatr = this.orderAttr;

_.each( this._listItems, function ( v ) {
v.model.set(oatr, v.$el.index());
});

this.collection.sort({silent: true});
this.listSetup();

this.trigger('sorted');
},



The handleSortComplete() function actually responds to the completion of a drag event representing an item being moved in the list. Since the Sortable widget has already updated the DOM, it simply iterates over all the item views and determines their position in the DOM to update their model's ordering attribute to the same value. I found that doing this was not enough to cause the collection to sort the items - an explicit sort was required to achieve the final result.

The final pieces in the example handle the individual add/remove functions of the list


listAdd: function ( model ) {

var v;

if ( !this._listItems[model.cid] ) {
v = this._listItems[model.cid] = new this.itemView({ model: model });
this.$el.append(v.render().$el);
}

if ( !this._listIsSyncing )
this.listSetup();
},

listRemove: function ( model ) {

if ( this._listItems[model.cid] ) {
this._listItems[model.cid].remove();
delete this._listItems[model.cid];
}

if ( !this._listIsSyncing )
this.listSetup();

},


You may have noticed there was no provision to enable the user to add/remove elements. The list view might not directly support the functionality to add and remove but can be designed to respond to the collection changing by listening to the add/remove events:


render: function () {

this._listItems = {};

this.listenTo( this.collection, 'sync reset', this.listSync );
this.listenTo( this.collection, 'add', this.listAdd );
this.listenTo( this.collection, 'remove', this.listRemove );

this.listSync();

return this;
},


Now, if you use add/delete buttons, drag/drop, or some other means of changing the list, the view can respond to it accordingly. Additionally, there's no provision in the listAdd() function to add to anywhere other than the end. It does not check the order attribute of the model and insert in the correct location in the DOM. If you were building a UI that allowed for items to be added anywhere in the list, that would have to be accounted for in that function.

The final step is to actually use the collection and view in a page. Below, I created a simple set of items, bound the collection to a new list view, rendered it into the page, and added an event handler to echo the current contents of the collection to the page for illustrative purposes:



function prettyPrintData(data) {
$('#json').text( JSON.stringify(data.toJSON()).replace(/{/g, '\n\t{').slice(0, -1)+'\n]' );
}

$(function() {

var things = new ThingCollection([
{ order: 0, title: 'Item 1' },
{ order: 1, title: 'Item 2' },
{ order: 2, title: 'Item 3' },
{ order: 3, title: 'Item 4' },
{ order: 4, title: 'Item 5' },
{ order: 5, title: 'Item 6' },
{ order: 6, title: 'Item 7' }
]);

var list = new ThingList({ collection: things });

$('.wrapper').append( list.render().$el );

list.on('sorted', function () {
prettyPrintData(things);
});

prettyPrintData(things);
});



The full demo and source is on my sandbox. This provides a basic concept to harnessing the power of the both the interaction available in the jQuery UI Sortable widget and data management of the Backbone framework.

Tuesday, March 19, 2013

Finishing the jQuery UI AutoComplete ComboBox Demo

jqueryui-select-combobox
If you worked with the jQuery UI Autocomplete, you may have noticed the demo for the combobox which replaces a HTML select box with a autocomplete/button widget that looks like a select box but provides type ahead features. The data source for the autocomplete is the select box. You're just enhancing the user experience with the type ahead. However, there is a note on the demo indicating it is not complete. It also provides a link with more details about the implementation that also states its not complete. Well, I really needed a complete version so took the time to package it up and figured I'd share what I built in case you're in the same place I was.

The demos are not exceptionally far from complete. The biggest change I made was to remove setting the value of the combobox from the _create() function and moving it to a value() function so that it could be used to get/set the combobox after it was initialized. I also added a change trigger in the autocomplete change callback. Finally, I put a wrapper element around the whole thing and added a few classes to enable better control of the styling.

You might ask why I moved transferring the value from the select box to the widget when it is initialized. I have several arguments which may not be applicable to other use cases (or you just feel differently). Either way, here they are:


  1. Unlike other input fields, the select box will pick the first entry even if you don't explicitly set it. You generally have to add a empty item or explicitly set selectedIndex to -1 to prevent this behavior. I want to only have the list of valid choices in the box and did not want the combobox to initialize with the first item in the list (nothing selected is implicitly null/blank/empty).

  2. I want to interact with the widget not the select box so using the value() function makes sense and is consistent with other jQuery UI widgets (spinner, slider, etc).

  3. The widget will most likely be bound to something I plan to get/set in a database so the initial value of the select box is irrelevant and will be overridden shortly after initializing the widget.



  4. The third point is really my biggest reason for having the value() function and skipping setting it during the creation phase. If your working with an MVC library like Backbone, Knockout, etc, then you'll be binding the widget to some data source that will get/set it via some kind of event triggering mechanism. Anything that is there when you create the widget won't be there shortly after creating it because the binding will set it to something useful.

    I have the current source on my GitHub jQuery UI extension repository (JS/CSS). You can also view the demos for examples. The pertinent one shows how the value function is used to get/set the combobox after its been initialized.

Tuesday, March 12, 2013

Navigating the Mysterious World of Javascript Inheritance

If you've used Javascript for any amount of time, you've probably run across the term "prototypal inheritance". Maybe you've scratched your head and moved on because any library you're using neatly tucks the details of this feature of Javascript away and makes things just work. However, perhaps your now trying to figure out how those libraries work or want to extend them. This is where understanding the finer points of the language will enable you to figure out what all that code is actually trying to accomplish. In this post, I will attempt to summarize the basic concept of inheritance in Javascript and how can be be leveraged to build reusable components. The code samples are fairly simple and I encourage you to copy them into a page and try out different permutation yourself to visualize the mechanics of the language. My main goal is to determine the absolute essential pieces required to define objects and how instances of those objects behave. I'll start by examining a simple base object and its instances. Next I'll build on that concept to construct a parent/child definition and related instance objects. Finally, I'll explore how to add several convenience functions to manage creating object definitions and their related inheritance chains. I'll compare this against how existing libraries today implement these concepts to provide similar capabilities.

The Two Sides of Function



Before diving in, we need to know what our building blocks are and what they mean and can do for us. First, everything is an object in Javascript (this page has a nice summary of the concepts). As such, a Function is also an object with special powers. What gets confusing is that a function can serve two purposes - to do some processing like a traditional function would do or to define an instance of an object that contains certain properties and more functions. To illustrate, lets define a simple function, sum() and see how it can be used in either context:


var sum = function(x, y) { return x + y };

// Outputs 6
console.log(sum(2,4));

// Outputs {Object}
console.log(new sum(2, 4));


In the first case, we use it as a normal function to add 2 and 4 together to get 6. In the second case, we use the new keyword to create an instance of an Object. So what's the difference? The second usage is calling sum() as a constructor to create a new object based on the prototype property associated with the function. What's a prototype property? Just an object that is used to create the new object when you use the "new" keyword to call a function. By default, this object will contain one key - "constructor" which is the sum() function. When you use new, you'll get an object with "constructor" as the properties in the new object. You know this because you can call it directly just like sum():



// Outputs 6
console.log(sum.prototype.constructor(2,4));

// This is true
console.log(sum.prototype.constructor === sum);

// Outputs 6 too
console.log((new sum(2, 4)).constructor(2,4));


What's in a Prototype



Alright, so a basically empty object that simply has the original function reference in it is not all that useful. Let's add some more to our object:



// Empty constructor
var Calc = function () {};

// Add 2 properties and a function to the prototype object
Calc.prototype.x = 2;
Calc.prototype.y = 4;
Calc.prototype.sum = function () {
return this.x + this.y;
};

Now, two different instances:
var c1 = new Calc();
var c2 = new Calc();

// Outputs 6
console.log(c1.sum());
// Outputs 6
console.log(c2.sum());

c1.x = 5;
// Outputs 9
console.log(c1.sum());
// Outputs 6
console.log(c2.sum());


c2.x = 7;
// Outputs 9
console.log(c1.sum());
// Outputs 11
console.log(c2.sum());

// Both false - different objects like expected
console.log(c1 === Calc.prototype);
console.log(c2 === Calc.prototype);

// However,
Calc.prototype.x = 10;
Calc.prototype.y = 12;

// Outputs 17
console.log(c1.sum());
// Outputs 19
console.log(c2.sum());


That last part where I changed the prototype after creating the instances c1 and c2 caused "y" to change in both but not "x". But a few lines up we confirmed that neither c1 nor c2 where the same as Calc.prototype so how did that happen - aren't they completely different objects? Well, yes and no, this is the part where you can cause yourself hours of debugging trying to find something that you don't expect to happen (this page has some good material on the subject). This feature of prototypes is meant to save memory by not completely copying all the object properties from the prototype to the instance. When you access a property, you'll get the current version in the prototype unless you overwrite it in the instance. So, in this example, "x" was set to 5 and 7 so the change to the prototype had no effect. However, "y" was never touched so the change will be seen by both instances. If either c1 or c2 had set "y" prior to that change, the local value would override the prototype. This is the basic inheritance pattern in Javascript. Each instance knows what properties it "owns" and what prototype it inherited from. If it can't find it locally, it will search the prototype. In the example above, we have created a prototype in Calc where the constructor(), sum(), x, and y are defined. This is what is called the prototype chain and enables us to organize our code into reusable objects by inheriting common parts through the prototype. At this point, we have only created one level - the instance object (c1 and c2) inherited from the object definition (Calc). The next step is to create another layer by building another object definition based on a parent/base object.

Creating the Chain



Inheriting a base object's properties and methods is remarkably simple. It is the same pattern as creating an instance from the object definition. The only difference is, instead of defining a variable to receive the instance, we'll assign it to the prototype of the child object:



// Create the constructor function
var A = function () {
console.log('A.constructor');
}

// Add a function. Our new child object will
// inherit this functionality automatically
A.prototype.foo = function () {
console.log('A.foo');
}

// Now create the subclass constructor
var B = function () {
console.log('B.constructor');
}

// Inherit all the parents features
// This is the magic part
B.prototype = new A;

// Add a function unique to the child
B.prototype.bar = function () {
console.log('B.bar');
}



Now B has both a foo and a bar function. The B.prototype = new A line is the bare essentials required to establish the prototype chain. However, there is a small issue using the above convention. new A will cause A's constructor function to execute (just like it does for any new instance). Meaning, if you look at your console, the following message would appear:


> A.constructor


At this point, we haven't even created an instance of A or B that we intend to use. We've just setting up the inheritance between objects. So how do we prevent this from happening? Well, we could say that no constructor can do anything and then the above code would work fine. However, that is rather inflexible. Another approach is to add an intermediary object between the parent and child objects. This object will have an empty constructor. This will work around that problem and allow anything to be in the parent constructor and it won't run when setting up the inheritance:


// Instead of B.prototype = new A,
// use this method.

// Create an empty intermediate function
var I = function () { };

// Assign the parent's prototype to the intermediate's prototype.
// "I" will now inherit from "A".
I.prototype = A.prototype;

// Now create the new "I" which is "A" but without the constructor
// function that contains code that needs to execute.
B.prototype = new I;


Now, the A constructor will not run when creating the chain. Now that we have our inheritance setup, let's try to create and instance and use it:


b = new B();
b.foo();


This will cause the following output in the console:

> B.constructor
> A.foo


So the next questions is - what happened to A's constructor? Only the constructor for B ran and then the inherited function foo() ran as expected. The issue here is anything defined in B with the same name will override A causing not to run. The same behavior would occur if we also added a foo() function to B:



B.prototype.foo = function () {
console.log('B.foo');
}

b = new B();
b.foo();


Now the console will show only the B implementation of constructor and foo:


> B.constructor
> B.foo


This is the same behavior exhibited earlier when we would read from the property and it would return the value from the prototype but once we wrote to it, it was set in the instance and was no longer connected to the prototype. So the same pattern occurred here: a new instance of B will first check if there is an instance variable set, then the B prototype, and then the A prototype. Since the constructor for B is found first, it is run and that's it. The same thing happens when you add a foo() function to B - it overrides the foo() implementation in A. It is possible to cause the overridden functions from A to execute, however, it must be called explicitly:



B = function () {
// Run parent constructor first
A.prototype.constructor.apply(this, arguments);
console.log('B.constructor');
}

B.prototype.foo = function () {
console.log('B.foo');

// Run parent last
A.prototype.foo.apply(this, arguments);
}

b = new B();
b.foo();


Now, the console will output the following:


> A.constructor
> B.constructor
> B.foo
> A.foo


At this point, this all you need to start creating your own library of reusable objects. However, you might be wondering why libraries like Backbone, Prototype, and jQuery UI have these various extend methods that are suppose to make this all easier. Well, they do wrap up the above logic into a convenient function. Additionally, they all, in some fashion, add some extra functionality into the mix either to make it easier to develop or to ensure anything you build with them is consistent (and works) with the rest of the library.

The Missing Link



So far, we've accessed the parent functionality via the prototype on the parent's definition directly. This not the only way to get there:


B.prototype.foo = function () {
console.log('B.foo');

// Run parent last
A.prototype.foo.apply(this, arguments);

// These will also do the same thing:
//B.prototype.constructor.prototype.foo.apply(this, arguments);
//this.constructor.prototype.foo.apply(this, arguments);
//arguments.callee.prototype.foo.apply(this, arguments);

}


Notice we can eliminate the reference to the object definition completely (A or B) and just work with the current scope (this or arguments.callee) which keeps the code somewhat more generic and decoupled. However, we can shorten up the reference a little by setting a class property to the parent's prototype while defining the inheritance:



...
var I = function () { };
I.prototype = A.prototype;
B.prototype = new I;

// Replaces the "prototype.constructor"
// required above
B.__super__ = A.prototype;

B.prototype.foo = function () {
console.log('B.foo');
B.__super__.foo.apply(this, arguments);
}


Now its a little more explicit what were trying to do here. However, this still requires "B" in the call to foo() since __super__ is defined on the object definition not the instance. You could modify the constructor so that each time an instance is created it sets up a reference to the parent's prototype:



B = function () {
this.__super__ = this.constructor.prototype;
this.__super__.constructor();
console.log('B.constructor');
}

B.prototype.foo = function () {
console.log('B.foo');

// Run parent constructor last
// Don't need to use apply() if we know the
// arguments to send. foo() will run in the
// scope of "this"
this.__super__.foo();
}


Now we can just use this.__super__ to access anything in the parent prototype we might need. In general, we're going to do this when we override a parent's function (constructor(), foo(), etc) and would like to reuse the parent's implementation of the function. This is probably the most common reason to want this access, so wouldn't it be nice if we could just call this.__super__() inside the overridden function and the parents version of the same function would execute? Well, this is possible, but not without digging into our bag of Javascript tools and using anonymous functions and closures to build the illusion that the __super__() function actually exists:



// Define B.foo()
B.prototype.foo = function () {
console.log('B.foo');

// We're counting on that fact that something will
// wrap this function so the parent's version of
// foo() will be called when __super__() is called
this.__super__();
}

// Now, proxy the new function inside a closure that
// will become the actual foo function. This function
// will setup the reference to the parent's version of
// the function so its available inside B.foo()
B.prototype.foo = (function (_base, _call) {

var __super__ = function () { _base.apply(this, arguments); };

return function () {

var ___super___ = this.__super__,
_ret;

this.__super__ = __super__;

_ret = _call.apply(this, arguments);

this.__super__ = ___super___;

return _ret;
}

})(A.prototype.foo, B.prototype.foo);

var b = new B();
b.foo();


This example might seem a little over done for what it does, but its a simplified version of what jQuery UI is actually doing when you extend from the widget base object (or any other existing widget using the $.widget() function):



// Inherit from the base Spinner widget
$.widget( "ui.myspinner", $.ui.spinner, {

...
// Override _create ...
_create: function() {

this.options.min = this.options.min || 0;
this.options.max = this.options.max || 100;

if ( this.options.alignment != 'vertical' &&
this.options.alignment != 'horizontal' ) {
this.options.alignment = 'vertical';
}

// Call the base Spinner's version of _create here:
this._super();

this._value( this.element.val() );
this.uiSlider.slider( 'value', this.value() | 0 );
},
...


One of the side-effects of doing this is that there will be an undefined instance variable __super__ in "b". If you inspect it in Firebug, you'll see it there. Of course, the same thing happens in jQuery UI:


var s = $('#slider').slider().data('ui-slider');


If you create the slider on an element and then grab a reference to the actual slider instance object and inspect it in Firebug, you'll see the _super and _superApply properties lingering as undefined on the object. You also have the added layer of complexity because several anonymous functions are making it harder to debug issues in your code. I do like the convenience and simplicity of the notation, however, its not part of the language nor is it necessary for inheritance to work.

Putting It All Together



Now that we know what is and is not built into the base Javascript inheritance model, we can create some helper utilities to extend objects and add any special features we might want to have available. Here's a simple extend function which will take a parent object, a child constructor, and a prototype object for the child and return the child with the prototype chain setup and the desired prototype object attached. As part of the processing, it will proxy function collisions to add a _super() function so the parent's implementation can be optionally invoke inside the child's implementation:



function extend(parent, child, props) {

var subr = function () { };

// Setup the prototype chain
subr.prototype = parent.prototype;
child.prototype = new subr;

// Proxy collisions so _super() is available
// to conveniently invoke parent's function.
for ( var p in props ) {

if ( parent.prototype[p] ) {

// There is a collision - wrap up the methods in a proxy to
// add chaining via super()
if ( typeof(props[p]) == 'function' ) {

// Break the shared scope and lock in the current method
// by wrapping in another function to create a new parent scope
child.prototype[p] = (function (_base, _call) {

var _super = function () { _base.apply(this, arguments); }

var _proxy = function () {

var _ret, __ret,
__super = this._super

this._super = _super;
var _ret = _call.apply(this, arguments);

this._super = __super;

return _ret;
}

return _proxy;

})(parent.prototype[p], props[p]);

} else {

// Non-function collisions - child wins...
child.prototype[p] = props[p];

}

} else {

// No collisions detected. Copy it all across.
child.prototype[p] = props[p];

}
}

return child;
}


Its not a perfect version since it does not handle setting up the _super() function on the constructors. I wanted to keep the code simple here. The goal was to consolidate everything together to see how it fit together. Refer to the end of the post for a link to a more robust version and other options. Using the above function looks something like this:



// Create the constructor function
var A = function () {
console.log('A.constructor');
}

// Give it a function
A.prototype.foo = function () {
console.log('A.foo');
}

// Create the child constructor
B = function () {
console.log('B.constructor');
}

// Now extend A with B adding the following
// to the prototype. Any function collisions will be
// proxied so the _super() function is available to
// call the parent's implementation.

B = extend(A, B, {
bar: function () {
console.log('B.bar');
},
foo: function () {
console.log('B.foo');

this._super();
}
});

// Try it out ...
var b = new B();
b.foo();
b.bar();



Alright, so you want to have some of these capabilities available in your own library, isn't there something already available or do I need to figure out how to make my own? Yes, there are several options depending on what you need. Prototype has a Class object that you can use to setup object definitions and wrap up various helpers including a $super argument to child functions. If you're not interested in all the extra library goodies Prototype comes with, you can check out Base by Dean Edwards which focuses only on creating a consistent interface for defining and extending object classes. Finally, I created a simple base class implementation which pulls ideas from jQuery UI, Prototype, and other libraries I've encountered to establish consistency and useful tools for defining objects in Javascript.

In the end, whether you build your own or utilize another library, understanding the capabilities of Javascript inheritance will undoubtedly help you when writing your next web app.