Skip to content

HTTPS clone URL

Subversion checkout URL

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