Welcome to mirror list, hosted at ThFree Co, Russian Federation.

WORKFLOW.md « web - github.com/lavabit/magma.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6a75e479bfb6dab3b23f83ea074cd16fb8d66010 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# 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](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);
        }
    };