A Brief Introduction
MooTools (over jQuery)
In my opinion, MooTools has taken just the right path encapsulating and abstracting altering operations on the DOM with support across all major browsers. I prefer its object-oriented approach over jQuery’s function-centric approach. If you’re interested, I recommend reading jQuery vs MooTools for a side-by-side comparison.
1 2 3 4 5 6 7 8 9 10 11 12 13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Since this is not intended to be an introduction to Coffeescript, knowledge of the basic syntax of Coffeescript and its inherent features is recommended for the rest of this article. If you aren’t familiar with it yet, I absolutely recommend reading The Little Book on Coffeescript. It’s free!
Composer.js is a new MVC framework building on the shoulders of the MooTools core. It borrows features from Backbone and Spine and combines them in a very lightweight approach, making absolutely no assumptions about the communication of the frontend and backend of your application. This means you have to implement the data-syncing yourself, but as we will see, this is not a big deal. Composer.js consists of:
- Models: Models are simply objects that encapsulate the data of an entity, so just like models in a classical MVC way. They can be synced with the server, included in collections and handled by controllers.
- Collections: Collections are just sets of models. Like models, they can be synced with the server. A model can be included in several collections, but the collection priority dictates which collection is consulted when syncing the model with the server.
- Controllers: Controllers are the glue between models, collections and the DOM. Every controller needs to be tied to an element in the DOM. Further elements which are children of the main element can also be referenced within the controller.
No views, huh? Actually, this is also a cool thing about Composer.js – it makes no assumptions about the data-syncing and it also leaves the choice of a templating engine up to you. Every controller provides a
render method, so this is where the view invocation should be situated. And as denoted in the abstract, we will use …
Mooml, which is short for MooTools Markup Language, is a MooTools port of the jQuery-based Jaml templating engine. It eliminates the need of the write-intensive creation of new elements with
new Element. Furthermore it simplifies the process of injecting new elements in the DOM by providing easy mechanisms for nesting.
Using Coffeescript, Mooml almost feels like it’s server-side companion Haml. Additionally, the code is slimmer as we can almost solely rely on the indentation when nesting elements. For example, consider creating a simple table:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
The templates have been registered in the Mooml namespace, so when you now want to render the template from a controller with an arbitrary result object, you just have to invoke
Mooml.render with a template name and an object:
1 2 3 4 5 6 7
Resulting in the following (valid X)HTML code to be injected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Isn’t that just nice? We can now easily create tables from anywhere we want with only two lines of code and almost arbitrary result objects. If we extend our result objects to include options, we can pass them in the template e.g. for setting CSS classes.
Building a Simple MVC Skeleton
After this short introduction, we will build a simple skeleton for a frontend MVC application. Using Coffeescript we setup the necessary bootstrapping, write models and collections and create controllers as well as views.
Before we can begin using Composer.js with Coffeescript, we have to do a little bit of bootstrapping. I suggest the following directory structure, which is perfect if you use Ruby on Rails as a backend, because from Rails 3.1 on, you can use the asset pipeline for automatic compilation and compression:
1 2 3 4 5 6 7 8 9
application.js situtated in
The necessary compatibility code for bootstrapping Composer.js together with Coffeescript can be found in the file
bootstrap.coffee. Furthermore, the file contains a reference implementation of the
Composer.sync method, which assumes your backend to behave in a RESTful way. This is necessary in order to make the CRUD (Create Read Update Delete) operations work, as Composer.js uses the CRUD paradigm to sync its data with the server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
For example, if you have a model called
User, Composer.js assumes that it is modelled as a server-side resource and all CRUD actions live in
Models and Collections
Let’s assume we have a list of users which we want to display. In our world, every user has an id, a name, a certain age and an email-address. Since users are considered entities, we write a simple model for them. Note that the model is registered in a global namespace which was defined in the
1 2 3 4 5 6
Initializing a new user, you can pass all attributes to the constructor - Composer.js does the rest for you. No explicit fields must be defined. However, if you need to process the data passed to the constructor before it is assigned to the model, you should overwrite the
parse method. See the documentation for more information.
Now we add a simple collection in
1 2 3 4 5 6
When you now invoke
fetch on a new collection, the collection invokes
Composer.sync to fetch the correponding models from the server with
GET /users/. The models are then initialized with the data returned and appended to the collection.
Controllers and Views
Next we can write the necessary controller code and implement the views. Controllers are the glue between models, collections and the DOM. Tied to a DOM element, they can register as event listeners on specific events. Those events can also be triggered on child-nodes. Let’s assume we have a section referenced by the ID
#contents within which we want to render a user table with the data obtained by our user collection. When the child node referenced by
#button is clicked, an alert box should appear with the result of the
introduction method of the user model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
Since we’re adding new elements to the DOM for which we are registering event listeners, we have to refresh the element references after the injection.
The only thing missing is the view. I suggest to locate them in the
application/views folder in thematically grouped files. We already described a view called
items-list which we will use to render a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
The only drawback might be some (mostly neglectable) performance loss, since the creation and handling of objects isn’t as cheap as setting a HTML string via
innerHTML. However, this is an inherent problem of all abstractions.
This is the current approach I am undertaking to build maintainable and complex web frontends. I hope you find it helpful, at least to know how to couple Composer.js and Coffeescript, since this was a point that took me some time.
Mooml is a nice templating engine but others can be used, since Composer.js is agnostic when it comes to the templating engine and data-syncing procedure. MVC doesn’t have backend in its name, so the next time you build a web frontend from the ground up - think in MVC. You’ll love it.
You can download the whole source code here.