Wyatt
brings mustache into your Titanium application
Introduction
Since Titanium helps us writing complex mobile applications in Javascript, the pain has always been to describe views. Alloy had to solve this problem with the brand new XML approach plus its TSS style definition. For me as for many other Titanium developers, it was quite something and I was prepared to migrate all my former code to Alloy.
The Alloy concept has been a bit frustrating for me. I'm an anti-precompiler. I think precompiling is a fail in a compilation process. I couldn't stand it in C, I don't like CoffeeScript, so I wasn't happy to see that Alloy came with its precompilation system behind a big MVC machine.
Wyatt is not meant to replace Alloy.
In fact, the development pattern is completely different : Alloy is a framwork, Wyatt is a simple template&query engine, that's it. The rest of the application : your MVC choice if you want MVC, your libs, your db manager ... I won't code your application, you're the boss here.
Getting Started
Write your index.yat file
{
"el": "window",
"options": {
"fullscreen": true,
"backgroundColor": "white"
},
"tree": [
{
"el": "label",
"options": {
"text": "{{message}}"
}
}
]
}
Then render it in your app.js file
var wyatt = require('wyatt');
// Generates the UI
var yat = wyatt.render('index.yat', {message: 'Hello World !'})
// Finds and open the window
yat.first({el: "window"}).open();
Wyatt API
wyatt.render(path, context)
Returns a YAT Document from a template path and a given context.
wyatt.yat(description)
Returns a YAT Document from a given description (Javascript Object).
wyatt.el(name)
Returns an Element constructor from its name (eg: 'view', 'button' ...).
wyatt.register(name, constructor)
Registers a constructor with the given name. The new name can be used next in a YAT Document.
YAT Document
Wyatt read YAT Documents to render the element tree.
Syntax
YAT syntax is basicaly JSON with some specials keys.
- el : the name of the element (e.g.: 'view', 'button', 'window' ...).
- options : an object to pass at the UI factory (Ti.UI.createWhatever)
- tree : the whole tree to append into the current UI
Mustache basics
Mustache is the template processor used to generate the element tree from a given context.
The logic-less system is fast to process and very adapted for mobile development.
In a nutshell :
- {{foobar}} is replaced by the foobar value in the given context.
- {{#titans}} {{name}} {{/titans}} iters into the titans array to retrieve 'name' for each iteration.
As the processor used is Handlebars (like was Wyatt Earp mustache),
You can learn more here : handlebarsjs.com
Making Queries
When a document is rendered, the first thing you'll need to do is retrieve the elements to manipulate them.
Queries are made for that.
The methods listed here are callable from a YAT Document Object Model (generated by wyatt.render)
yat.where(query)
Retrieve the list of elements in the document where the query match.
The query parameter is an object using like a filter.
The keys in the filter can be "el" (to filter by element name) or anything defined in the YAT Document.
query-example.yat :
{
"el": "view",
"tree": [
{
{{#persons}}
{
"el": "label",
"job": "{{job}}",
"options": {
"text": "{{name}}"
}
}
{{/persons}}
}
]
}
app.js :
var wyatt = require('wyatt');
// Generates the UI
var yat = wyatt.render('query-example.yat', {
persons: [
{name: "John Smith", job: "developer"},
{name: "Stewart McKay", job: "developer"},
{name: "Bob White", job: "manager"},
]
});
// Finds all the developers and change their color
yat.where({el: "label", job: "developer"}).forEach(function (el) {
el.attr('color': 'red');
});
yat.first(query)
Same as above but return only the first element.
Sub Queries
Elements have their own YAT Document Object Model for their own tree.
So they can be used as query proxies.
subquery-example.yat :
[
{
"el": "view",
"food": "fruits",
"tree": [
{{#fruits}}
{
"el": "label",
"options": {
"text": "{{name}}"
}
}
{{/fruits}}
]
},
{
"el": "view",
"food": "vegetables",
"tree": [
{{#vegetables}}
{
"el": "label",
"options": {
"text": "{{name}}"
}
}
{{/vegetables}}
]
}
]
app.js :
var wyatt = require('wyatt');
// Generates the UI
var yat = wyatt.render('subquery-example.yat', {
fruits: [
{name: "Peach"},
{name: "Apple"},
{name: "Cherry"},
],
vegetables: [
{name: "Endive"},
{name: "Letuce"}
]
});
// Finds all the vegetables and change their color
yat.first({id: "vegetables"}).where({el: "label"}).forEach(function (el) {
el.attr('color': 'green');
});
Element
Elements (or view elements) are Titanium UI wrappers. This pattern is inspired by jQuery.
You'll get an element instead of the direct UI, but Why ?
An element will have a bunch of shorcuts and useful methods to helps you manipulating UI attributes and events.
However, elements keep the UI intact and you can still retrieve it with el.ui attribute
.ui
ui attribute is a access to the original Titanium UI object (eg Ti.UI.View)
.attr(key, value)
A single way to set parameters. Looks first for a setter (eg: 'color' -> ui.setColor). If the setter doesn't exist, use a simple patch
Can be chained. Example :
yat
.first({id: 'something'})
.attr('color', 'white')
.attr('width', '50px')
.attr('opacity', 0.5)
.trigger(event, data)
A proxy method to ui.fireEvent
.on(event, callback)
A proxy method to ui.addEventListener
.off(event, callback)
A proxy method to ui.removeEventListener
Custom Element
Any element can be extended and used in the YAT document
The process : retrieve the element by its name, extend it, override the create method.
Example :
var wyatt = require('wyatt');
wyatt.register('redbutton', wyatt.el('button').extend({
create: function (options) {
options.backgroundColor = 'red';
wyatt.el('button').prototype.create.apply(this, [options]);
}
}));
// Now 'redbutton' can be used in a YAT Document.