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.