# Workflow Examples
## Adding HTML Blocks
HTML blocks are located in `dev/blocks`. Block hierarchy is indicated by the filename. The hierarchy shows which files will be embedded into each other.
Blocks can indicate where other blocks can be embedded with the `` comment. Only one embed statement is allowed per block.
## Compiling Blocks Into States
State files located in `static/states` and `js/states` are used to compile blocks into sets of HTML code. Embedding is indicated with white space (4 spaces, not tabs). For example, with the blocks named:
container
container.list
container.list.item
A state file that embeds the item into the list and list into the container would be:
container
list
item
Also, if you wanted a block with just the list and embedded item (usefull for javascript blocks which only need snippets of html, not complete html files), you would do the following:
container.list
item
Running `dev/build/build-html.php` compiles all the states into blocks. (You will need to run `dev/build/build-js.php` following compiling html to update the blocks stored in `dev/js/scripts/blocks.js` for javascript access).
## Views
Views are responsible for creating html containers and managing user interactions. The `getBlock` method lets you grab an html block by name (the name of the state file). For example, if you create a state called list.state:
container.list
item
Then run `build-html.php` then `build-js.php` to complile the blocks into an html string and insert them `dev/js/scripts/blocks.js`, you can access the block with the following:
var list = getBlock('list');
Which returns the jQuery object of the list.html block.
Views will also grab data from models and fill templates. Templates are located in `dev/js/templates/`. See [jQuery templates API](http://api.jquery.com/category/plugins/templates/) for syntax details. Running `dev/build/build-js.php` inserts templates into `dev/js/scripts/tmpl.js`. Use the tmpl model to fill templates.
Model data is accessed by observing the events that provide it. For example, with template named `listItems`, the following snippet fills the template on the `loaded` event:
listModel.addObserver('loaded', function(data) {
var tmplModel = magma.model.tmpl();
tmplModel.observeOnce('completed', function(list) {
// do stuff with list jquery object
});
tmplModel.fillTmpl('listItems', data);
});
Views select specific elements to bind actions to or delegate events to handle the user interactions:
list.delegate('.item', 'click', function() {
alert($(this).text());
});
Finally, the root element is returned to interface with the bootstrap explained below:
return {
root: list
};
Putting it together:
magma.view = {
list: function(listModel) {
var list = getBlock('list');
list.delegate('.item', 'click', function() {
alert($(this).text());
});
listModel.addObserver('loaded', function(data) {
var tmplModel = magma.model.tmpl();
tmplModel.observeOnce('completed', function(items) {
list.append(items);
});
tmplModel.fillTmpl('listItems', data);
});
listModel.loadItems(10);
return {
root: list
};
}
};
## Models
Models can communicate with views with events passed through the observable object. Events are typically listed when the observerable is created:
var observable = newObservable(['loaded']);
This creates an observable with two events that can be subscribed to. In some cases, the `listEvents` helper is used to create a set of events:
var observable = newObservable(listEvents(['loaded']));
`listEvents` expands the array to `['loaded', 'loadedError', 'loadedFailed']` for convenience since server methods will either be successfull, return an error, or fail.
Models also access server data via the JSON interface. `getData` is used to make an AJAX request to server:
var load = function(amount) {
getData('list.items', {items: amount}, {
success: function(data) {
observable.notifyObservers('loaded', data);
},
error: function(error) {
observable.notifyObservers('loadedError', error);
},
failure: function() {
observable.notifyObservers('loadedFailed');
}
});
};
Any views that subscribe to the `loaded` event will be notified when the data is finished loading and have access to the data object.
All models return on object containing interface methods and subscription methods:
return {
loadItems: load,
addObserver: observable.addObserver,
observeOnce: observable.observeOnce,
removeObserver: observable.removeObserver
};
Putting things together:
magma.model = {
list: functions() {
var observable = newObservable(listEvents(['loaded']));
var load = function(amount) {
getData('list.items', {items: amount}, {
success: function(data) {
observable.notifyObservers('loaded', data);
},
error: function(error) {
observable.notifyObservers('loadedError', error);
},
failure: function() {
observable.notifyObservers('loadedFailed');
}
});
};
return {
loadItems: load,
addObserver: observable.addObserver,
observeOnce: observable.observeOnce,
removeObserver: observable.removeObserver
};
}
};
## Bootstrap
The bootstrap methods located in `dev/js/scripts/bootstrap.js` are used to launch tabs or workspaces. These functions glue together specific models and views and add the views to the page.
`login`, `locked`, `logout`, and the `loading` bootstraps are for startup
`main` sets up the chrome and workspace container
`inbox`, `read`, `compose`, `search`, and `scrape` are examples of creating a tabbed workspace
`mail`, `contacts`, `options`, and `help` are global navigation that hide or show the tabs.
For example, a bootstrap method for the list view and model above would look like the following:
magma.bootstrap = {
list: function() {
var listModel = magma.model.list();
magma.view.list(listModel).root.appendTo(document.body);
}
};