Rococo

Javascript Microframework

Download .zip Download .tar.gz View on GitHub

Welcome

Rococo is a Micro Framework to create elegant and robust Javascript Applications.

Perfection is achieved, 
not when there is nothing more to add, 
but when there is nothing left to take away.
    -- Antoine de Saint-Exupery

Rococo works with a strict subset of Javascript (informally we call this BlackScript). BlackScript is like Javascript but has no:

  • new keyword
  • prototypes
  • this keyword
  • native constructors
  • __proto__
  • object.create
  • labels
  • with keyword

We choose to work with BlackScript instead of Javascript because:

  • we prefer a small, clean language without half-baked features
  • a language that works in all browsers even the oldest ones (unlike object.create or proto)

Object Oriented Programming in BlackScript

To understand Rococo, you need to understand BlackScript first. Object oriented programming in BlackScript is really simple. We only use literals.

A class is a literal object that produces other objects and is defined in a class namespace like this:

 UI.classes.Machine {
       createNew: function(bundle) {
             var protect = bundle || {};
             //protected property
             protect.coin = false;
             var obj = {};
             obj.insertCoin = function(coin) {
                  protect.coin = true;
             }
             return obj;
       }
 }

 UI.classes.CoffeeMachine = {
       createNew: function(bundle) {
             var protect = bundle || {};
             //inherit from machine
             var obj = UI.classes.Machine.createNew(protect); 
             obj.makeCoffee = function() {
                  if (!protect.coin) return 'insert coin!';
                  protect.coin = false;
                  return 'espresso';
             }
             return obj;
       }
 }

You can use this class like this:

 var c = UI.classes.CoffeeMachine.createNew();
 c.insertCoin(1);
 c.makeCoffee(); //returns 'espresso'

Using Rococo

Rococo helps you to structure your BlackScript application. A Rococo application consists of three parts: HTML, components and delegates or helpers.

  • HTML is where you store the markup
  • Components is where you store reusable code
  • Delegates and helpers are where you store custom behaviour

Rococo separates these three and re-connects them to form an application.

Your first component

Rococo thinks in components. You write a Rococo application by defining (or reusing) components. A component manages an HTML snippet. For instance consider the following button:

 <button class="awake" data-post="/store" data-awake="ActionButton" >SAVE DOCUMENT</button>

Here we have the HTML for a save button. We would like to have a general button that performs a server call and updates the label afterwards. This is our 'generic' component. We can define this component like this:

 UI.components.ActionButton = {
        createNew: function() {
               var obj = {};
               obj.init = function() {
                     obj.onclick = function(e){
                          e.preventDefault();
                          var url = obj.node.getAttribute('data-post');
                          var data = serializeForm();
                          myAjaxPostFunction(url, data, function(){
                               obj.node.innerHTML = 'SAVED!';
                          });
                     });
               }
               return obj;
        }
 }

Delegates

While this button will work just fine, it would be nice if we could change the default behaviour of the button after posting the data. This would allow us to use this buttons in projects that require slightly different ActionButton behaviour. To do so, we add a delegate like this:

<button class="awake" data-post="/store" data-awake="ActionButton" data-delegate="controller" >SAVE DOCUMENT</button>

And we define our delegate:

 UI.classes.Controller = {
        createNew: function() {
               var obj = {};
               obj.serverDidRespond = function(resp) {
                    return JSON.parse(resp).message;
               }
               return obj;
        }
 }

 UI.instances.controller = UI.classes.Controller.createNew();

And we change the component to:

  myAjaxPostFunction(url, data, function(){
       obj.node.innerHTML = obj.delegate.serverDidRespond();
  });

Now we can specify any behaviour for our ActionButton! But even better the connection between the component and delegate has been specified in the HTML, the classes are loosely coupled and easy to test.

Connecting nodes

Most of the time, a component consists of a single DOM node containing several child nodes. Together these nodes form the component DOM available in your component object property obj.$node.

Sometimes however you may have several DOM nodes forming a component together. For instance if you have a sortable table component and a list of filters in the sidebar, or a video component with a separate remote control formed by a set of additional DOM nodes. Rococo allows you to easily connect these nodes.

<div class="awakable" id="cinema" data-awake="VideoPlayer"></div>
<div class="connected" data-belongsto="cinema"><a>PLAY</a></div>

In this example we connect a player control to its component. Note that we use a class 'connected' to mark the DOM node as being connected to another DOM node. Then, we specify the owning DOM node by its ID in the data-belongsto property.

Both DOM nodes will now be available in obj.$nodes

Factories

Instead of using a delegate object you can also specify a delegate class. Using the

 data-factory="MyDelegateClass"

You can specify which delegate class should be used to create the delegate instance. Rococo will now function as a factory and create an instance of MyDelegateClass and connect this delegate object to your component instance.

jQuery

You can use Rococo with jQuery. After including rococo.js, also include rococo.jquery.js. Now you can use $node and $nodes beside node and nodes in your Rococo components - these will be the jQuery nodes. Also this plugin will allow you to pass jQuery nodes to the awake() method.