This example shows how to bind events to a mojit, configure code to run
on the client, and make AJAX calls to the YQL Web service. The application
listens for events and then makes AJAX calls to YQL to get Flickr photo
information.

Mojito lets you configure applications to run on either the server or client
side. This example uses binders that are deployed to the client, so we need
to configure Mojito to deploy the application to the client, where it will
be executed by the browser.

To configure Mojito to run on the client, you simply set the "deploy"
property to true in application.json as seen below.

This code example uses the flickr.photos.search table to get information
for photos that have a title, description, or tags containing a string. For
example, the YQL statement below returns Flickr photo information for those
photos that have a title, description, or tags containing the string “Manhattan”.

Copy the query below into the YQL Console,
replace {your_flickr_api_key} with your own Flickr API key, and then click TEST
to see the returned XML response.

The returned response contains photo information in the photo element. You extract the
farm, server, id, and secret attributes from each photo element to create
the photo URI as seen here:

http://farm+{farm}+static.flickr.com/+{server}+/+{id}+_+{secret}+.jpg

In the model.server.js of PagerMojit shown below, the YQL function uses the YQL
statement above to get photo data, then parses the returned response to create the photo
URIs. The model then wraps the photo information in an object and stores those objects in
the images array that is sent to the controller through the callback function.

A mojit may have zero, one, or many binders within the binders directory. Each binder
will be deployed to the browser along with the rest of the mojit code, where the
client-side Mojito runtime will call it appropriately. On the client, the binder has a
proxy object (mojitProxy) for interacting with the mojit it represents as well as
with other mojits on the page. Methods can be called from the mojitProxy object
that allow binders to listen for and fire events.

The binder consists of a constructor, an initializer, and a bind function. The following
describes each component and indicates when the mojitProxy object can be used.

constructor - creates the namespace for your binder that wraps the initialization
code and binder.

initializer - is passed the mojitProxy where it can be stored and used to listen
and fire events with other binders. The mojitProxy is the only gateway back into the
Mojito framework for your binder.

bind - is a function that is passed a Y.Node instance that wraps the DOM node
representing this mojit instance. The DOM event handlers for capturing user interactions
should be attached in this function.

The skeleton of the binders/index.js file below illustrates the basic structure of the
binder. For more information, see Mojito Binders.

This code example uses the binder PageMojitBinder to perform the following:

attach onClick handlers to prev and next links

invoke the index method of the controller through the mojitProxy object

create an overlay with Flickr photo information received from YQL

The binders/index.js for this code example is long and fairly involved, so we will
dissect and analyze the code. Let’s begin by looking at the bind function of
index.js, which allows mojits to attach DOM event handlers.

In this code snippet of binders/index.js, the bind function contains the nested
updateDOM function that updates node content and attaches event handlers. Using the
mojitProxy object, the nested flipper function calls the index function of
the controller. The callback updateDOM is passed to index to update the content.

...bind:function(node){varthatNode=node;// Define the action when user click on prev/next.varflipper=function(event){vartarget=event.target;// Get the link to the page.varpage=parsePage(target.get('href'));varupdateDOM=function(markup){thatNode.set('innerHTML',markup);thatNode.all('#nav a').on('click',flipper,this);thatNode.all('#master ul li a').on('mouseover',showOverlay,this);thatNode.all('#master ul li a').on('mouseout',showOverlay,this);};this.mojitProxy.invoke('index',{params:{page:page},},updateDOM);};...

The event handler for mouseovers and mouseouts are handled by the showOverlay
function, which creates the overlay containing photo information. In the code snippet
below, showOverlay makes an AJAX call to YQL to get photo data that is placed in an
unordered list for the overlay.

Thus far, we’ve looked at the event handlers, but not the actual binding of the handlers
to nodes. At the end of the bind function, you’ll see three important lines
(shown below) that bind the flipper and showOutlay functions to handle click and
mouseover events.

After a little analysis, the full binders/index.js below should be easier to
understand. The binder attaches event handlers to nodes, invokes a function in the
controller, and updates the content in the template. The binder also has a couple of
helper functions for parsing and requires the IO and YQL modules, which are specified in
the requires array.

The paging for this code example relies on the application configuration to set route
paths and the controller to create links to access previous and next pages.

The routes.json file below configures two route paths for HTTP GET calls made on the
root path. The perpage configuration, however, requires a query string with the
page parameter, which is used for paging. The page parameter has the value
:page, which is a variable that is assigned a value by the controller that we’re
going to look shortly.

The Params addon allows you to access variables
from the query string parameters, the POST request bodies, or the routing systems URLs.
In this code example, you use the getFromMerged method, which merges the parameters
from the query string, POST request body, and the routing system URLs to give you access
to all of the parameters. In the code snippet taken from controller.server.js below,
the getFromMerged method is used to get the value for the page parameter and then
calculate the index of the first photo to display:

...index:function(actionContext){varpage=actionContext.params.getFromMerged('page');varstart;page=parseInt(page)||1;if((!page)||(page<1)){page=1;}// Page param is 1 based, but the model is 0 basedstart=(page-1)*PAGE_SIZE;...}...

To get the photo data, the controller depends on the model to call YQL to query the
Flickr API. Using actionContext.get({model_name}) lets you get a reference to the
model. The file naming convention for models is {model_name}.{affinity}.{selector}.js.
The {affinity} can have the values server, client, or common. The {selector}
is defined by the selector property in application.json, but does not need to be defined.
The {model_name} is an arbitrary string defined by the user. So, for example,
our model in this example is model.server.js, so {model_file_name} is model.

The example controller below calls the getData from the model
with actionContext.models.get('model').getData, which
will get the returned data from YQL in the callback function. To use methods from models,
you need to require the model in the requires array of the controller.

...index:function(actionContext){...// Data is an array of imagesactionContext.models.get('model').getData('mojito',start,PAGE_SIZE,function(data){Y.log('DATA: '+Y.dump(data));vartheData={data:data,// imageshasLink:false,prev:{title:"prev"// opportunity to localize},next:{link:createLink(actionContext,{page:page+1}),title:"next"},query:'mojito'};if(page>1){theData.prev.link=createLink(actionContext,{page:page-1});theData.hasLink=true;}actionContext.done(theData);});}...};},'0.0.1',{requires:['mojito','mojito-models-addon','mojito-url-addon','mojito-params-addon','PagerMojitModel','dump']});

The URLs for the prev and next links are created by passing the mojit instance,
the method, and the query string parameters to the make method from the Url addon.
The code snippet below creates the query string parameters with the
YUI QueryString module.
If the query string created by Y.QueryString.stringify is “page=2” ,
actionContext.url.make would return the URL {domain_name}:8666/?page=2.

Stitching the above code snippets together, we have the controller.server.js below.
The index function relies on the model for data and the createLink function to
create URLs for the next and prev links.

To create the binder for click events and invoke the index function of the
controller, replace the code in binders/index.js with the code below. Again,
Be sure to replace the '{your_flickr_api_key}' with your own Flickr API key.