Skip to content

Latest commit

 

History

History
184 lines (127 loc) · 6.64 KB

WORKFLOW.md

File metadata and controls

184 lines (127 loc) · 6.64 KB

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 <!-- [BLOCK] --> 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 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);
    }
};