Although we’ve created client-side code by deploying controllers, models, framework
code, and templates to the client, we have written client code that works with the
DOM. Mojito has a special way for you to write code specifically for DOM binding
and manipulation called binders. Mojits can have one or more binders that are
deployed to the client (they cannot run on the server). We’re going to create
some binders to allow users to update data and hide content.

In the screenshot, you can see that we now have a full dashboard with data
from GitHub, Twitter, the YUI blog, YouTube, and YUI Gallery. You can also see
the icon ⟲, which uses binders to refresh data when clicked.

In the last module, we covered writing unit and functional tests for Mojito.
We looked at both the YUI Test and Arrow testing frameworks and also fleshed
out our dashboard application. In summary, we looked at the following:

Client-side code for Mojito are placed in files called binders. 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. The view used to generate
output determines which binder is used. Thus, if the simple view is used, the
binder simple.js is used. This can be overridden by setting view.binder in the meta
argument to ac.done. If no binder matches the view, then no binder is used.

To use binders, your application must be using
HTMLFrameMojit or your own frame
mojit and be configured to deploy code to the client with the
deploy property in application.json. See Configuring
Applications to Be Deployed to Client
for more information. Also, the template files (e.g., index.hb.html) must have
containers (div elements) that have the id attribute assigned the value
{{mojit_view_id}} because the attribute value
{{mojit_view_id}} allows binders to attach themselves to the DOM.
For example: <divid={{mojit_view_id}}>. Mojito generates the value for
{{mojit_view_id}} at runtime.

Like controllers and models, binders register a module name with YUI.add and their own
namespace. Binders have the two essential functions init and bind. The init
function initializes the binder and contains the mojitProxy object, which we will discuss
in detail soon. The bind function, as you might imagine, allows the binder code to be
attached to the DOM.

The binder index.js will be created whenever the index function of the controller
is executed. and its corresponding DOM node is attached to a client page. Mojito will
select that DOM node and pass it into the bind function. This allows you to write
code to capture UI events and interact with Mojito or other mojit binders.

The init method is called with an instance of a mojit proxy specific for this mojit
binder instance. The mojitProxy instance can be used at this point to listen for events.
It is typical to store the mojitProxy for later use as well. The mojitProxy object
is the only gateway back into the Mojito framework for your binder.

The bind method is passed a Y.Node instance that wraps the DOM node representing
this mojit instance within the DOM. It will be called after all other binders on the page
have been constructed and their init methods have been called. The mojitProxy can
be used at this point to broadcast events. Users should attach DOM event handlers in bind
to capture user interactions.

Each binder, when constructed by Mojito on the client, is given a proxy object for interactions
with the mojit it represents as well as with other mojits on the page. This mojitProxy
should be saved with this for use in the other parts of the binder.

children - the children of the mojit, which are defined in application.json.

data - the data model that allows your binder to share and access data through a tunnel
that data can pass between the client and server.

type - the name of the mojit that attached the binder to the DOM.

From the mojitProxy, you can access properties that use the interface and provides the
information below:

YUI.add('githubModel',function(Y,NAME){// The namespace for the model that passes the// name.Y.mojito.models[NAME]={init:function(config){this.config=config;},getData:function(params,callback){// Model function to get data...},...};},'0.0.1',{requires:['yql']});

In addition to the properties of the mojitProxy object, you can also use the methods
of the MojitProxy class,
so that the binder can interact with the controller and other mojits. We’re going to focus
on a core set of the available methods and recommend you look at the API documentation to
complete the picture.

In the next few sections, we’ll give you an overview of binder features and
the relevant MojitProxy methods and then look at how to implement the features.

refreshView - Refreshes the current DOM view for this binder without recreating the
binder instance. Will call the binder’s onRefreshView function when complete with
the new Y.Node and HTMLElement objects.

render - This method renders the data provided into the specified view. The “view”
must have the name of one of the files in the current mojits views directories.
Returns using the callback.

The invoke method is critical because it allows user-driven events to trigger the
execution of controller functions. In the binder snippet below, the invoke
method calls the controller function show with parameters. The returned value is
used to update the DOM. This is the typical use of the invoke method. The controller
may need to get data from the model, so the flow would be
binder->controller->model->controller->binder. We’ll be using the invoke method
in our application to refresh the data for our Twitter and Github mojits.

If the controller has not been deployed to the client, the binder sends a request to the
server through a special path called the tunnel that Mojito creates to allow the client to
make HTTP requests from the client to the server. The default path is http://domain:8666/tunnel,
but you can configure the name of the path.

Often all you want your binder to do is to refresh its associated view. From the
mojitProxy object, you can call the refreshView method to render a new DOM node
for the current mojit and its children, as well as reattach all of the existing
binders to their new nodes within the new markup. Because all binder instances
are retained, state can be stored within a binder’s scope.

After you have copied the application that you made in the last module
(see Setting Up), change into the application
07_binders.

Let’s create our last two mojits Blog and Gallery for the dashboard. The Blog
mojit will display posts from the YUI Blog, and the
Gallery mojit will display the latest modules pushed to the YUI Gallery.

$mojitocreatemojitBlog

$mojitocreatemojitGallery

Create mojit instances for our new mojits in application.json and make them
children of the body instance as shown below. Also, be sure to update the
path to the CSS assets.

For the binders, the first one we’ll change is that of the PageLayout mojit
(mojits/PageLayout/binders/index.js). We’re just to use the YUI Node Class
to select a node and then add a class so that users can hide content, so we won’t need
to use the mojitProxy object. Update the bind function with the following, which
will select a node by the class, handle a click event, and then either add or remove
a class to allow the user to hide or show a widget.

The next binder modification will be for the Twitter mojit. We want the binder
to allow users to update the Twitter feed by clicking on a button. The binder code
below cleans up the Twitter feed, handles click events on , and then calls the
controller method index on the server. After the index method is executed, the
rendered index.hb.html template is attached to the DOM. The
communication between the client and server is through the mojitProxy object:

We want to let users to be able to update the GitHub activity as well. Before we start
working on the binders of the Github mojit, let’s refine the controller, model, and
update the tests. First, in the controller, update the index method and add the
method githubMap outside the controller namespace to format the returned response
with the code below. We’re using a YQL table that’s in the
YQL hosted storage
now (store://gpgSGZAwQ3vaDaalPQZ44u)

Go ahead and start your application. You’ll see that we now have two widgets per
column. The GitHub and Twitter feeds should have the refresh icon.

Open a developer console or Firebug and then click on the refresh icon for the GitHub
widget. You will probably not see any new content, but in the developer console, you’ll
see the following indicating that the controller index method was invoked through
the RPC tunnel and that a new binder was created for the returned content.

Congratulations, you have basically finished the dashboard application. The last few
modules will add Mojito information, but focus mostly on enhancing your application
through configuration, adding specialized templates for different devices, and
adding localization.

If you open the developer console, click the refresh button for either the Github
or Twitter mojit, you should see the logs from the binder code that indicate that the
mojits are creating new nodes and attaching content to the DOM. If you see no log messages
and there are no errors on the server, there is a good chance that you have not configured
the application to deploy to the client. In application.json, confirm that deploy
is set to true:

If you see log messages on the client that indicate binders are being created,
but nothing happens when you click on the Refresh button to update the GitHub
or Twitter data, you might have forgotten to add {{mojit_view_id}} to the
id attribute of the div container in that mojit’s template. For example,
the first line in the template index.hb.html for the Github mojit should be
the following: <divid="{{mojit_view_id}}"class="mojit">

Can the controller update Handelbars expressions without rendering the template and
sending it to the client?

Yes, binder code can invoke a controller method that uses ac.pageData.set to
update a Handlebars expression. For example, if the template for a mojit has the
Handlebars expression {{rss_feed}} that contains RSS feeds. That mojit’s binder
could invoke a controller method that would call
ac.pageData.set('rss_feed'{rss:<some_data>}) to update the Handlebars expression.

Can the server broadcast events to the client-side binders?

Not directly, but when a controller method is executed on the server, the binder is
created and attached to the DOM, so the binder can then broadcast events to other
binders on the page. The controller does not have a way to directly broadcast events
though.

Have the binder of the Github mojit broadcast a updated event that the
binder for the PageLayout mojit listens for and invokes a controller method that
simply logs a message that the page has refreshed data.

Instead of having the controller of the PageLayout mojit render one of its children,
have the controller use the Data addon to pass data to the templates.