Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 947 lines (825 sloc) 34.211 kB
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
1 ==============
2 Binding Events
3 ==============
4
5 **Time Estimate:** 20 minutes
6
7 **Difficulty Level:** Advanced
8
c5dacc0 @isao get back joe's docs changes:
isao authored
9 .. _code_exs_events-summary:
10
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
11 Summary
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
12 =======
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
13
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
14 This example shows how to bind events to a mojit, configure code to run
15 on the client, and make AJAX calls to the YQL Web service. The application
16 listens for events and then makes AJAX calls to YQL to get Flickr photo
17 information.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
18
19 The following topics will be covered:
20
21 - configuring the application to run on the client
22 - getting Flickr data from the model with YQL
23 - binding events through the ``mojitProxy`` object
24 - making AJAX calls to YQL from the binder
25
c5dacc0 @isao get back joe's docs changes:
isao authored
26 .. _events_summary-req:
27
28 Requirements
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
29 ------------
30
31 You will need to `get a Flickr API key <http://www.flickr.com/services/api/keys/apply/>`_
32 to run this example.
33
c5dacc0 @isao get back joe's docs changes:
isao authored
34 .. _code_exs_events-notes:
35
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
36 Implementation Notes
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
37 ====================
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
38
c5dacc0 @isao get back joe's docs changes:
isao authored
39 .. _events_notes-client:
40
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
41 Configuring the Application to Run on the Client
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
42 ------------------------------------------------
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
43
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
44 Mojito lets you configure applications to run on either the server or client
45 side. This example uses binders that are deployed to the client, so we need
46 to configure Mojito to deploy the application to the client, where it will
47 be executed by the browser.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
48
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
49 To configure Mojito to run on the client, you simply set the ``"deploy"``
50 property to ``true`` in ``application.json`` as seen below.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
51
52 .. code-block:: javascript
53
54 [
55 {
56 "settings": [ "master" ],
57 "specs": {
58 "frame": {
59 "type": "HTMLFrameMojit",
60 "config": {
61 "deploy": true,
62 "child": {
63 "type": "PagerMojit"
64 }
65 }
66 }
67 }
68 }
69 ]
70
c5dacc0 @isao get back joe's docs changes:
isao authored
71 .. _events_notes-data:
72
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
73 Getting Data with YQL in the Model
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
74 ----------------------------------
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
75
c5dacc0 @isao get back joe's docs changes:
isao authored
76 In the mojit model, the `YUI YQL Query Utility <http://developer.yahoo.com/yui/3/yql/>`_
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
77 is used to get Flickr photo information. To access the utility in your model,
78 specify ``'yql'`` in the ``requires`` array as seen in the code snippet below:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
79
80 .. code-block:: javascript
81
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
82 YUI.add('PagerMojitModel', function(Y, NAME) {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
83 ...
84 /* Code for PagerMojitModel */
85 ...
86 }, '0.0.1', {requires: ['yql']});
87
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
88 This code example uses the ``flickr.photos.search`` table to get information
89 for photos that have a title, description, or tags containing a string. For
90 example, the YQL statement below returns Flickr photo information for those
91 photos that have a title, description, or tags containing the string "Manhattan".
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
92
0ef19a4 @zhouyaoji Fixed typos.
zhouyaoji authored
93 Copy the query below into the `YQL Console <http://developer.yahoo.com/yql/console/>`_,
94 replace ``{your_flickr_api_key}`` with your own Flickr API key, and then click **TEST**
95 to see the returned XML response.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
96
0ef19a4 @zhouyaoji Fixed typos.
zhouyaoji authored
97 ``select * from flickr.photos.search where text="Manhattan" and api_key="{your_flickr_api_key}"``
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
98
c5dacc0 @isao get back joe's docs changes:
isao authored
99 The returned response contains photo information in the ``photo`` element. You extract the
100 ``farm``, ``server``, ``id``, and ``secret`` attributes from each photo element to create
101 the photo URI as seen here:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
102
103 ``http://farm + {farm} + static.flickr.com/ + {server} + / + {id} + _ + {secret} + .jpg``
104
df58c4f @zhouyaoji Merge branch 'docs_remove_init_controllers' into HEAD
zhouyaoji authored
105
c5dacc0 @isao get back joe's docs changes:
isao authored
106 In the ``model.server.js`` of ``PagerMojit`` shown below, the ``YQL`` function uses the YQL
107 statement above to get photo data, then parses the returned response to create the photo
108 URIs. The model then wraps the photo information in an object and stores those objects in
109 the ``images`` array that is sent to the controller through the ``callback`` function.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
110
111
112 .. code-block:: javascript
113
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
114 YUI.add('PagerMojitModel', function(Y, NAME) {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
115 /**
116 * The PagerMojitModel module.
117 * @module PagerMojitModel
118 */
119 /**
120 * Constructor for the Model class.
121 * @class Model
122 * @constructor
de93f81 @zhouyaoji Fixed formatting of code examples; removed any last remnants of view …
zhouyaoji authored
123 **/
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
124 Y.namespace('mojito.models')[NAME] = {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
125 init: function(config) {
126 this.config = config;
127 },
128 getData: function(query, start, count, callback) {
129 var q = null;
130 // Get Flickr API key: http://www.flickr.com/services/api/keys/apply/
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
131 var API_KEY = "{your_flickr_api_key}";
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
132 start = parseInt(start) || 0;
133 count = parseInt(count) || 10;
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
134 q = 'select * from flickr.photos.search(' + start + ',' + count + ') where text="%' + query + '%" and api_key="' + API_KEY + '"';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
135 Y.YQL(q, function(rawData) {
136 if (!rawData.query.results) {
137 callback([]);
138 return;
139 }
140 var rawImages = rawData.query.results.photo, rawImage = null,images = [], image = null, i = 0;
141 for (; i<rawImages.length; i++) {
142 rawImage = rawImages[i];
143 image = {
144 title: rawImage.title,
145 location: 'http://farm' + rawImage.farm + '.static.flickr.com/' + rawImage.server + '/' + rawImage.id + '_' + rawImage.secret + '.jpg',
146 farm: rawImage.farm,
147 server: rawImage.server,
148 image_id: rawImage.id,
149 secret: rawImage.secret
150 };
151 if (!image.title) {
152 image.title = "Generic Title: " + query;
153 }
154 images.push(image);
155 }
156 callback(images);
157 });
158 }
159 };
160 }, '0.0.1', {requires: [ 'yql']});
161
de93f81 @zhouyaoji Fixed formatting of code examples; removed any last remnants of view …
zhouyaoji authored
162
c5dacc0 @isao get back joe's docs changes:
isao authored
163 For a more detailed explanation about how to use YQL in your Mojito application, see
164 `Calling YQL from a Mojit <calling_yql.html>`_. For more information about YQL, see the
de93f81 @zhouyaoji Fixed formatting of code examples; removed any last remnants of view …
zhouyaoji authored
165 `YQL Guide <http://developer.yahoo.com/yql/guide>`_.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
166
c5dacc0 @isao get back joe's docs changes:
isao authored
167 .. _events_notes-bind_events:
168
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
169 Binding Events
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
170 --------------
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
171
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
172 This section will discuss the basics of binding events in Mojito and then look at the
173 binder used in this code example.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
174
c5dacc0 @isao get back joe's docs changes:
isao authored
175 .. _bind_events-basics:
176
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
177 Binder Basics
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
178 #############
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
179
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
180 A mojit may have zero, one, or many binders within the ``binders`` directory. Each binder
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
181 will be deployed to the browser along with the rest of the mojit code, where the
182 client-side Mojito runtime will call it appropriately. On the client, the binder has a
183 proxy object (``mojitProxy``) for interacting with the mojit it represents as well as
184 with other mojits on the page. Methods can be called from the ``mojitProxy`` object
185 that allow binders to listen for and fire events.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
186
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
187 The binder consists of a constructor, an initializer, and a bind function. The following
188 describes each component and indicates when the ``mojitProxy`` object can be used.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
189
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
190 - **constructor** - creates the namespace for your binder that wraps the initialization
191 code and binder.
192 - **initializer** - is passed the ``mojitProxy`` where it can be stored and used to listen
193 and fire events with other binders. The ``mojitProxy`` is the only gateway back into the
194 Mojito framework for your binder.
195 - **bind** - is a function that is passed a ``Y.Node`` instance that wraps the DOM node
196 representing this mojit instance. The DOM event handlers for capturing user interactions
197 should be attached in this function.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
198
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
199 The skeleton of the ``binders/index.js`` file below illustrates the basic structure of the
200 binder. For more information, see `Mojito Binders <../intro/mojito_binders.html>`_.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
201
202 .. code-block:: javascript
203
204 YUI.add('AwesomeMojitBinder', function(Y, NAME) {
205 // Binder constructor
206 Y.namespace('mojito.binders')[NAME] = {
207 init: function(mojitProxy) {
208 this.mojitProxy = mojitProxy;
209 },
210 // The bind function
211 bind: function(node) {
212 var thatNode = node;
213 }
214 };
215 Y.mojito.registerEventBinder('AwesomeMojit', Binder);
216 }, '0.0.1', {requires: ['mojito']});
217
c5dacc0 @isao get back joe's docs changes:
isao authored
218 .. _bind_events-pagemojitbinder:
219
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
220 Examining the PageMojitBinder
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
221 #############################
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
222
223 This code example uses the binder ``PageMojitBinder`` to perform the following:
224
225 - attach ``onClick`` handlers to ``prev`` and ``next`` links
226 - invoke the ``index`` method of the controller through the ``mojitProxy`` object
227 - create an overlay with Flickr photo information received from YQL
228
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
229 The ``binders/index.js`` for this code example is long and fairly involved, so we will
230 dissect and analyze the code. Let's begin by looking at the ``bind`` function of
231 ``index.js``, which allows mojits to attach DOM event handlers.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
232
de93f81 @zhouyaoji Fixed formatting of code examples; removed any last remnants of view …
zhouyaoji authored
233 In this code snippet of ``binders/index.js``, the ``bind`` function contains the nested
234 ``updateDOM`` function that updates node content and attaches event handlers. Using the
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
235 ``mojitProxy`` object, the nested ``flipper`` function calls the ``index`` function of
236 the controller. The callback ``updateDOM`` is passed to ``index`` to update the content.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
237
238 .. code-block:: javascript
239
240 ...
241 bind: function(node) {
242 var thatNode = node;
243 // Define the action when user click on prev/next.
244 var flipper = function(event) {
245 var target = event.target;
246 // Get the link to the page.
247 var page = parsePage(target.get('href'));
248 var updateDOM = function(markup) {
249 thatNode.set('innerHTML', markup);
250 thatNode.all('#nav a').on('click', flipper, this);
251 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
252 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
253 };
254 this.mojitProxy.invoke('index',
255 {
256 params: {page: page},
257 }, updateDOM
258 );
259 };
260 ...
261
262
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
263 The event handler for mouseovers and mouseouts are handled by the ``showOverlay``
264 function, which creates the overlay containing photo information. In the code snippet
265 below, ``showOverlay`` makes an AJAX call to YQL to get photo data that is placed in an
266 unordered list for the overlay.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
267
268 .. code-block:: javascript
269
270 ...
271 bind: function(node) {
272 ...
273 var showOverlay = function(event) {
274 var target = event.target;
275 var href = target.get('href');
276 var imageId = parseImageId(href);
277 if (target.hasClass('overlayed')) {
278 target.removeClass('overlayed');
279 thatNode.one('#display').setContent('');
280 } else {
281 Y.log('HREF: ' + href);
282 Y.log('IMAGE ID: ' + imageId);
283 target.addClass('overlayed');
284 // Query for the image metadata
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
285 var query = 'select * from flickr.photos.info where photo_id="' + imageId + '" and api_key="' + {your_flickr_api_key} + '"';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
286 thatNode.one('#display').setContent('Loading ...');
287 Y.YQL(query, function(raw) {
288 if (!raw.query.results.photo) {
289 Y.log('No results found for photoId: ' + imageId);
290 return;
291 }
292 var props = raw.query.results.photo;
293 var snippet = '<ul style="list-style-type: square;">';
294 for (var key in props) {
295 if (typeof(props[key]) == 'object') {
296 continue;
297 }
298 snippet += '<li>' + key + ': ' + props[key] + '</li>';
299 }
300 snippet += '</ul>';
301 thatNode.one('#display').setContent(snippet);
302 });
303 }
304 };
305 ...
306 }
307 ...
308
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
309 Thus far, we've looked at the event handlers, but not the actual binding of the handlers
310 to nodes. At the end of the ``bind`` function, you'll see three important lines
311 (shown below) that bind the ``flipper`` and ``showOutlay`` functions to handle click and
312 mouseover events.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
313
314 .. code-block:: javascript
315
316 ...
317 bind: function(node) {
318 ...
319 // Bind all the image links to showOverlay
320 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
321 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
322 // Bind the prev + next links to flipper
323 thatNode.all('#nav a').on('click', flipper, this);
324 }
325 ...
326
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
327 After a little analysis, the full ``binders/index.js`` below should be easier to
328 understand. The binder attaches event handlers to nodes, invokes a function in the
329 controller, and updates the content in the template. The binder also has a couple of
330 helper functions for parsing and requires the IO and YQL modules, which are specified in
331 the ``requires`` array.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
332
333 .. code-block:: javascript
334
335 YUI.add('PagerMojitBinder', function(Y, NAME) {
0ef19a4 @zhouyaoji Fixed typos.
zhouyaoji authored
336 var API_KEY = '{your_flickr_api_key}';
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
337 function parseImageId(link) {
338 var matches = link.match(/com\/(\d+)\/(\d+)_([0-9a-z]+)\.jpg$/);
339 return matches[2];
340 }
341 function parsePage(link) {
342 var matches = link.match(/page=(\d+)/);
343 return matches[1];
344 }
345
346 /**
347 * The PagerMojitBinder module.
348 * @module PagerMojitBinder
349 */
350 /**
351 * Constructor for the Binder class.
352 *
353 * @param mojitProxy {Object} The proxy to allow
354 * the binder to interact with its owning mojit.
355 * @class Binder
356 * @constructor
357 */
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
358 Y.namespace('mojito.binders')[NAME] = {
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
359 /**
360 * Binder initialization method, invoked
361 * after all binders on the page have
362 * been constructed.
363 */
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
364 init: function(mojitProxy) {
365 this.mojitProxy = mojitProxy;
366 },
367 /**
368 * The binder method, invoked to allow the mojit
369 * to attach DOM event handlers.
370 * @param node {Node} The DOM node to which this
371 * mojit is attached.
372 */
373 bind: function(node) {
374 var thatNode = node;
375 Y.log('NODE: ' + Y.dump(this.node));
376 // define the action when user click on prev/next
377 var flipper = function(event) {
378 var target = event.target;
379 // get the link to the page
380 var page = parsePage(target.get('href'));
381 Y.log('PAGE: ' + page);
382 var updateDOM = function(markup) {
383 thatNode.set('innerHTML', markup);
384 thatNode.all('#nav a').on('click', flipper, this);
385 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
386 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
387 };
388 this.mojitProxy.invoke('index',
389 {
390 params: {page: page}
391 }, updateDOM
392 );
393 };
394 var showOverlay = function(event) {
395 var target = event.target;
396 var href = target.get('href');
397 var imageId = parseImageId(href);
398 if (target.hasClass('overlayed')) {
399 target.removeClass('overlayed');
400 thatNode.one('#display').setContent('');
401 } else {
402 Y.log('HREF: ' + href);
403 Y.log('IMAGE ID: ' + imageId);
404 target.addClass('overlayed');
405 // Query for the image metadata
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
406 var query = 'select * from flickr.photos.info where photo_id="' + imageId + '" and api_key="' + API_KEY + '"';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
407 thatNode.one('#display').setContent('Loading ...');
408 Y.YQL(query, function(raw) {
409 if (!raw.query.results.photo) {
410 Y.log('No results found for photoId: ' + imageId);
411 return;
412 }
413 var props = raw.query.results.photo;
414 var snippet = '<ul style="list-style-type: square;">';
415 for (var key in props) {
416 if (typeof(props[key]) == 'object') {
417 continue;
418 }
419 snippet += '<li>' + key + ': ' + props[key] + '</li>';
420 }
421 snippet += '</ul>';
422 thatNode.one('#display').setContent(snippet);
423 });
424 }
425 };
426 // Bind all the image links to showOverlay
427 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
428 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
429 // Bind the prev + next links to flipper
430 thatNode.all('#nav a').on('click', flipper, this);
431 }
432 };
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
433 }, '0.0.1', {requires: ['yql', 'io', 'dump']});
c5dacc0 @isao get back joe's docs changes:
isao authored
434
df58c4f @zhouyaoji Merge branch 'docs_remove_init_controllers' into HEAD
zhouyaoji authored
435
c5dacc0 @isao get back joe's docs changes:
isao authored
436 .. _events_notes-paging:
437
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
438 Using Paging
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
439 ------------
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
440
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
441 The paging for this code example relies on the application configuration to set route
442 paths and the controller to create links to access previous and next pages.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
443
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
444 The ``routes.json`` file below configures two route paths for HTTP GET calls made on the
445 root path. The ``perpage`` configuration, however, requires a query string with the
446 ``page`` parameter, which is used for paging. The ``page`` parameter has the value
447 ``:page``, which is a variable that is assigned a value by the controller that we're
448 going to look shortly.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
449
450 .. code-block:: javascript
451
452 [
453 {
454 "settings": ["master"],
455 "root": {
456 "verbs": ["get"],
457 "path": "/",
458 "call": "frame.index"
459 },
460 "perpage": {
461 "verbs": ["get"],
462 "path": "/?page=:page",
463 "call": "frame.index"
464 }
465 }
466 ]
467
468 The controller for ``PagerMojit`` performs several functions:
469
470 - uses the ``Params`` addon to get the ``page`` parameter from the query string
471 - calculates the index of the first photo on the page
472 - calls the ``getData`` function in the model to get photo data
473 - creates URLs for the **next** and **prev** links
474
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
475 The `Params addon <../../api/classes/Params.common.html>`_ allows you to access variables
476 from the query string parameters, the POST request bodies, or the routing systems URLs.
477 In this code example, you use the ``getFromMerged`` method, which merges the parameters
478 from the query string, POST request body, and the routing system URLs to give you access
479 to all of the parameters. In the code snippet taken from ``controller.server.js`` below,
480 the ``getFromMerged`` method is used to get the value for the ``page`` parameter and then
481 calculate the index of the first photo to display:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
482
483 .. code-block:: javascript
484
485 ...
486 index: function(actionContext) {
487 var page = actionContext.params.getFromMerged('page');
488 var start;
489 page = parseInt(page) || 1;
490 if ((!page) || (page<1)) {
491 page = 1;
492 }
493 // Page param is 1 based, but the model is 0 based
494 start = (page - 1) * PAGE_SIZE;
495 ...
496 }
497 ...
498
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
499 To get the photo data, the controller depends on the model to call YQL to query the
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
500 Flickr API. Using ``actionContext.get({model_name})`` lets you get a reference to the
501 model. The example controller below calls the ``getData`` from the model
502 ``PagerMojitModel`` with ``actionContext.models.get('PagerMojitModel').getData`, which
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
503 will get the returned data from YQL in the callback function. To use methods from models,
504 you need to require the model in the ``requires`` array of the controller.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
505
506 .. code-block:: javascript
507
508 ...
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
509 index: function(actionContext) {
510 ...
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
511 // Data is an array of images
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
512 actionContext.models.get('PagerMojitModel').getData('mojito', start, PAGE_SIZE, function(data) {
513 Y.log('DATA: ' + Y.dump(data));
514 var theData = {
515 data: data, // images
516 hasLink: false,
517 prev: {
518 title: "prev" // opportunity to localize
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
519 },
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
520 next: {
521 link: createLink(actionContext, {page: page+1}),
522 title: "next"
523 },
524 query: 'mojito'
525 };
526 if (page > 1) {
527 theData.prev.link = createLink(actionContext, {page: page-1});
528 theData.hasLink = true;
529 }
530 actionContext.done(theData);
531 });
532 }
533 ...
534 };
535 }, '0.0.1', {requires: ['dump', 'mojito-url-addon', 'mojito-params-addon', 'PagerMojitModel']});
536
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
537
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
538 The URLs for the **prev** and **next** links are created by passing the mojit instance,
539 the method, and the query string parameters to the ``make`` method from the ``Url`` addon.
540 The code snippet below creates the query string parameters with the
541 `YUI QueryString module <http://yuilibrary.com/yui/docs/api/modules/querystring.html>`_.
542 If the query string created by ``Y.QueryString.stringify`` is "page=2" ,
543 ``actionContext.url.make`` would return the URL ``{domain_name}:8666/?page=2``.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
544
545 .. code-block:: javascript
546
547 ...
548 function createLink(actionContext, params) {
549 var mergedParams = Y.mojito.util.copy(actionContext.params.getFromMerged());
550 for (var k in params) {
551 mergedParams[k] = params[k];
552 }
553 return actionContext.url.make('frame', 'index', Y.QueryString.stringify(mergedParams));
554 }
555 ...
556
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
557 Stitching the above code snippets together, we have the ``controller.server.js`` below.
558 The ``index`` function relies on the model for data and the ``createLink`` function to
559 create URLs for the **next** and **prev** links.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
560
561 .. code-block:: javascript
562
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
563 YUI.add('PagerMojit', function(Y, NAME) {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
564 /**
565 * The PagerMojit module.
566 * @module PagerMojit */
567 var PAGE_SIZE = 10;
568 /**
569 * Constructor for the Controller class.
570 * @class Controller
571 * @constructor
572 */
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
573 Y.namespace('mojito.controllers')[NAME] = {
9275476 @zhouyaoji Removed the init methods from controolers. Still many more to go.
zhouyaoji authored
574
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
575 index: function(actionContext) {
576 var page = actionContext.params.getFromMerged('page');
577 var start;
578 page = parseInt(page) || 1;
579 if ((!page) || (page<1)) {
580 page = 1;
581 }
582 // Page param is 1 based, but the model is 0 based
583 start = (page - 1) * PAGE_SIZE;
584 // Data is an array of images
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
585 actionContext.models.get('PagerMojitModel').getData('mojito', start, PAGE_SIZE, function(data) {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
586 Y.log('DATA: ' + Y.dump(data));
587 var theData = {
588 data: data, // images
589 hasLink: false,
590 prev: {
591 title: "prev" // opportunity to localize
592 },
593 next: {
594 link: createLink(actionContext, {page: page+1}),
595 title: "next"
596 },
597 query: 'mojito'
598 };
599 if (page > 1) {
600 theData.prev.link = createLink(actionContext, {page: page-1});
601 theData.hasLink = true;
602 }
603 actionContext.done(theData);
604 });
605 }
606 };
607 // generate the link to the next page based on:
608 // - mojit id
609 // - action
610 // - params
611 function createLink(actionContext, params) {
612 var mergedParams = Y.mojito.util.copy(actionContext.params.getFromMerged());
613 for (var k in params) {
614 mergedParams[k] = params[k];
615 }
616 return actionContext.url.make('frame', 'index', Y.QueryString.stringify(mergedParams));
617 }
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
618 }, '0.0.1', {requires: ['dump', 'mojito-url-addon', 'mojito-params-addon', 'PagerMojitModel']});
c5dacc0 @isao get back joe's docs changes:
isao authored
619
620 .. _code_exs_events-setup:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
621
622 Setting Up this Example
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
623 =======================
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
624
625 To set up and run ``binding_events``:
626
627 #. Create your application.
628
629 ``$ mojito create app binding_events``
630 #. Change to the application directory.
631 #. Create your mojit.
632
633 ``$ mojito create mojit PagerMojit``
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
634 #. To configure you application to run on the client and use ``HTMLFrameMojit``, replace
635 the code in ``application.json`` with the following:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
636
637 .. code-block:: javascript
638
639 [
640 {
641 "settings": [ "master" ],
642 "specs": {
643 "frame": {
644 "type": "HTMLFrameMojit",
645 "config": {
646 "deploy": true,
647 "child": {
648 "type": "PagerMojit"
649 }
650 }
651 }
652 }
653 }
654 ]
655
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
656 #. To configure routing to call the ``index`` action from the instance of the
657 ``HTMLFrameMojit``, replace the code in ``routes.json`` with the following:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
658
659 .. code-block:: javascript
660
661 [
662 {
663 "settings": ["master"],
664 "root": {
665 "verbs": ["get"],
666 "path": "/",
667 "call": "frame.index"
668 },
669 "perpage": {
670 "verbs": ["get"],
671 "path": "/?page=:page",
672 "call": "frame.index"
673 }
674 }
675 ]
676
677 #. Change to ``mojits/PageMojit``.
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
678 #. To have the controller get data from the model and create links for paging, replace the
679 code in ``controller.server.js`` with the following:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
680
681 .. code-block:: javascript
682
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
683 YUI.add('PagerMojit', function(Y, NAME) {
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
684 var PAGE_SIZE = 10;
685 /**
686 * Constructor for the Controller class.
687 * @class Controller
688 * @constructor
689 */
df58c4f @zhouyaoji Merge branch 'docs_remove_init_controllers' into HEAD
zhouyaoji authored
690 Y.namespace('mojito.controllers')[NAME] = {
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
691
692 index: function(actionContext) {
693 var page = actionContext.params.getFromMerged('page');
694 var start;
695 page = parseInt(page) || 1;
696 if ((!page) || (page<1)) {
697 page = 1;
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
698 }
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
699 // Page param is 1 based, but the model is 0 based
700 start = (page - 1) * PAGE_SIZE;
701 // Data is an array of images
2785d93 @zhouyaoji Added new syntax for calling models from controllers and changed 'fra…
zhouyaoji authored
702 actionContext.models.get('PagerMojitModel').getData('mojito', start, PAGE_SIZE, function(data) {
f3e9641 @zhouyaoji Continuing to work on init function.
zhouyaoji authored
703 Y.log('DATA: ' + Y.dump(data));
704 var theData = {
705 data: data, // images
706 hasLink: false,
707 prev: {
708 title: "prev" // opportunity to localize
709 },
710 next: {
711 link: createLink(actionContext, {page: page+1}),
712 title: "next"
713 },
714 query: 'mojito'
715 };
716 if (page > 1) {
717 theData.prev.link = createLink(actionContext, {page: page-1});
718 theData.hasLink = true;
719 }
720 actionContext.done(theData);
721 });
722 }
723 };
724 // Generate the link to the next page based on:
725 // - mojit id
726 // - action
727 // - params
728 function createLink(actionContext, params) {
729 var mergedParams = Y.mojito.util.copy(actionContext.params.getFromMerged());
730 for (var k in params) {
731 mergedParams[k] = params[k];
732 }
733 return actionContext.url.make('frame', 'index', Y.QueryString.stringify(mergedParams));
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
734 }
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
735 }, '0.0.1', {requires: ['dump', 'mojito-url-addon', 'mojito-params-addon', 'mojito-models-addon', 'PagerMojitModel']});
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
736
df58c4f @zhouyaoji Merge branch 'docs_remove_init_controllers' into HEAD
zhouyaoji authored
737
0e6a846 @zhouyaoji Copy edited the developer guide documentation.
zhouyaoji authored
738 #. To get Flickr photo information using YQL, create the file ``models/model.server.js``
739 with the code below. Be sure to replace the ``'{your_flickr_api_key}'`` with your own
c5dacc0 @isao get back joe's docs changes:
isao authored
740 Flickr API key.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
741
742 .. code-block:: javascript
743
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
744 YUI.add('PagerMojitModel', function(Y, NAME) {
0ef19a4 @zhouyaoji Fixed typos.
zhouyaoji authored
745 var API_KEY = '{your_flickr_api_key}';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
746 /**
747 * The PagerMojitModel module.
748 * @module PagerMojitModel
749 */
750 /**
751 * Constructor for the Model class.
752 * @class Model
753 * @constructor
754 */
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
755 Y.namespace('mojito.models')[NAME] = {
9275476 @zhouyaoji Removed the init methods from controolers. Still many more to go.
zhouyaoji authored
756
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
757 getData: function(query, start, count, callback) {
758 var q = null;
759 // Get Flickr API key: http://www.flickr.com/services/api/keys/apply/
760 var API_KEY = "{your_api_key}";
761 start = parseInt(start) || 0;
762 count = parseInt(count) || 10;
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
763 q = 'select * from flickr.photos.search(' + start + ',' + count + ') where text="%' + query + '%" and api_key="' + API_KEY+ '"';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
764 Y.YQL(q, function(rawData) {
765 if (!rawData.query.results) {
766 callback([]);
767 return;
768 }
769 var rawImages = rawData.query.results.photo, rawImage = null,images = [], image = null, i = 0;
770 for (; i<rawImages.length; i++) {
771 rawImage = rawImages[i];
772 image = {
773 title: rawImage.title,
774 location: 'http://farm' + rawImage.farm + '.static.flickr.com/' + rawImage.server + '/' + rawImage.id + '_' + rawImage.secret + '.jpg',
775 farm: rawImage.farm,
776 server: rawImage.server,
777 image_id: rawImage.id,
778 secret: rawImage.secret
779 };
780 if (!image.title) {
781 image.title = "Generic Title: " + query;
782 }
783 images.push(image);
784 }
785 callback(images);
786 });
787 }
788 };
789 }, '0.0.1', {requires: ['yql']});
790
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
791 #. To create the binder for click events and invoke the ``index`` function of the
c5dacc0 @isao get back joe's docs changes:
isao authored
792 controller, replace the code in ``binders/index.js`` with the code below. Again,
793 Be sure to replace the ``'{your_flickr_api_key}'`` with your own Flickr API key.
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
794
795 .. code-block:: javascript
796
797 YUI.add('PagerMojitBinder', function(Y, NAME) {
0ef19a4 @zhouyaoji Fixed typos.
zhouyaoji authored
798 var API_KEY = '{your_flickr_api_key}';
3c5bb67 @zhouyaoji Added a placeholder for the API key and modified query.
zhouyaoji authored
799 function parseImageId(link) {
800 var matches = link.match(/com\/(\d+)\/(\d+)_([0-9a-z]+)\.jpg$/);
801 return matches[2];
802 }
803 function parsePage(link) {
804 var matches = link.match(/page=(\d+)/);
805 return matches[1];
806 }
807
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
808 /**
809 * The PagerMojitBinder module.
810 * @module PagerMojitBinder
811 */
812 /**
813 * Constructor for the Binder class.
814 *
815 * @param mojitProxy {Object} The proxy to allow
816 * the binder to interact with its owning mojit.
817 * @class Binder
818 * @constructor
819 */
820 Y.namespace('mojito.binders')[NAME] = {
821 /**
822 * Binder initialization method, invoked
823 * after all binders on the page have
824 * been constructed.
825 */
826 init: function(mojitProxy) {
827 this.mojitProxy = mojitProxy;
828 },
829 /**
830 * The binder method, invoked to allow the mojit
831 * to attach DOM event handlers.
832 * @param node {Node} The DOM node to which this
833 * mojit is attached.
834 */
835 bind: function(node) {
836 var thatNode = node;
837 Y.log('NODE: ' + Y.dump(this.node));
838 // define the action when user click on prev/next
839 var flipper = function(event) {
840 var target = event.target;
841 // get the link to the page
842 var page = parsePage(target.get('href'));
843 Y.log('PAGE: ' + page);
844 var updateDOM = function(markup) {
845 thatNode.set('innerHTML', markup);
846 thatNode.all('#nav a').on('click', flipper, this);
847 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
848 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
849 };
850 this.mojitProxy.invoke('index',
851 {
852 params: {page: page}
853 }, updateDOM
854 );
855 };
856 var showOverlay = function(event) {
857 var target = event.target;
858 var href = target.get('href');
859 var imageId = parseImageId(href);
860 if (target.hasClass('overlayed')) {
861 target.removeClass('overlayed');
862 thatNode.one('#display').setContent('');
863 } else {
864 Y.log('HREF: ' + href);
865 Y.log('IMAGE ID: ' + imageId);
866 target.addClass('overlayed');
867 // Query for the image metadata
f0af949 @zhouyaoji Updated query.
zhouyaoji authored
868 var query = 'select * from flickr.photos.info where photo_id="' + imageId + '" and api_key="' + API_KEY + '"';
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
869 thatNode.one('#display').setContent('Loading ...');
870 Y.YQL(query, function(raw) {
871 if (!raw.query.results.photo) {
872 Y.log('No results found for photoId: ' + imageId);
873 return;
874 }
875 var props = raw.query.results.photo;
876 var snippet = '<ul style="list-style-type: square;">';
877 for (var key in props) {
878 if (typeof(props[key]) == 'object') {
879 continue;
880 }
881 snippet += '<li>' + key + ': ' + props[key] + '</li>';
882 }
883 snippet += '</ul>';
884 thatNode.one('#display').setContent(snippet);
885 });
886 }
887 };
888 // Bind all the image links to showOverlay
889 thatNode.all('#master ul li a').on('mouseover', showOverlay, this);
890 thatNode.all('#master ul li a').on('mouseout', showOverlay, this);
891 // Bind the prev + next links to flipper
892 thatNode.all('#nav a').on('click', flipper, this);
893 }
894 };
895 }, '0.0.1', {requires: ['yql', 'io', 'dump']});
896
351e25f @zhouyaoji Added a prereq for doing the code example, added a link to get Flickr…
zhouyaoji authored
897 #. To display links to photos and associated photo data in the rendered template, replace
898 the code in ``views/index.hb.html`` with the following:
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
899
900 .. code-block:: html
901
902 <div id="{{mojit_view_id}}" class="mojit" style="position: relative; width: 960px">
903 <h3>Query Term: {{query}}</h3>
904 <div id="nav" style="clear: both;">
905 {{#hasLink}}
906 {{#prev}}
907 <a href="{{{link}}}">{{title}}</a>
908 {{/prev}}
909 {{/hasLink}}
910 {{^hasLink}}
911 {{#prev}}{{title}}{{/prev}}
912 {{/hasLink}}
913 {{#next}}
914 <a href="{{{link}}}">{{title}}</a>
915 {{/next}}
916 </div>
917 <div id="master" style="width: 30%; float: left;">
918 <ul>
919 {{#data}}
920 <li><a href="{{location}}" data-id="{{image_id}}">{{title}}</a></li>
921 {{/data}}
922 </ul>
923 </div>
924 <div style="width: 50%; float: right">
925 <!-- load image here dynamically -->
926 <div id="display" style="margin: 0 auto;">
927 &nbsp;
928 </div>
929 </div>
930 </div>
931
932 #. From the application directory, run the server.
933
934 ``$ mojito start``
935 #. To view your application, go to the URL:
936
937 http://localhost:8666
938
c5dacc0 @isao get back joe's docs changes:
isao authored
939 .. _code_exs_events-src:
940
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
941 Source Code
b5ece1a @zhouyaoji Fixed steps, replaced 'view template' with 'template', fixed syntax f…
zhouyaoji authored
942 ===========
4b30716 @zhouyaoji Adding the reST documentation to the Mojito project.
zhouyaoji authored
943
944 - `Application Configuration <http://github.com/yahoo/mojito/tree/master/examples/developer-guide/binding_events/application.json>`_
945 - `Mojit Binder <http://github.com/yahoo/mojito/tree/master/examples/developer-guide/binding_events/mojits/PagerMojit/binders/index.js>`_
74b3d8a @zhouyaoji Fixed syntax for namespacing controllers/models in docs/examples.
zhouyaoji authored
946 - `Binding Events Application <http://github.com/yahoo/mojito/tree/master/examples/developer-guide/binding_events/>`_
Something went wrong with that request. Please try again.