For the past eight(8) years Schalk Neethling has been working as a freelance developer under the pseudo of Volume4 and is now the president of Overt Strategy Consulting. During this period he has completed over 300 projects ranging from full web application development to complete branding. As president and lead developer of Overt Strategy Consulting, Schalk Neethling and his team has released a 100% Java standards based content management system called AlliedBridge and business document exchange and review system, called Doc-Central. Schalk Neethling is also actively involved on a daily basis in the open source, web standards and accessibility areas and is a current active member of the Web Standards Group. Schalk is also the co-founder and president of the non-profit The South Web Standards and Accessibility Group, which aims to actively educate and raise awareness of web standards and accessibility to both the developer society as well as business large and small. Schalk also has a long relationship with DZone and is currently zone leader for both the web builder, css.dzone.com, as well as the .NET zone, dotnet.dzone.com, and you can find a lot of his writing there as well as on his blog located at schalkneethling.alliedbridge.com. Schalk is constantly expanding on his knowledge of various aspects of technology and loves to stay in touch with the latest happenings. For Schalk web development and the internet is not just a job, it is a love, a passion and a life style. Schalk has posted 173 posts at DZone. View Full User Profile

How To - jMaki Events

05.18.2008
| 6583 views |
  • submit to reddit

The January 27, 2007 Tech Tip Introduction to jMaki introduced jMaki, a lightweight framework for creating Web 2.0 applications using standards-based technologies such as CSS, HTML, and JavaScript. Among its other features, the jMaki framework makes available widgets from popular JavaScript toolkits such as Dojo, Yahoo, Scriptaculous, and Google in a way that's familiar to Java technology, PHP, or Phobos developers. The tip briefly discussed the components in jMaki and showed some examples of using the framework to build Web 2.0 functionality into an application. It also briefly covered the framework's event mechanism and Glue, a key feature in the jMaki event mechanism.

The following tip expands the discussion of the event mechanism in jMaki. You'll learn more about the concepts that underlie the jMaki event mechanism and how to take advantage of it to easily interact with widgets. For example, consider an application in which a user clicks on the date in a calendar widget, and that event causes another widget such as a combobox to refresh or load different data. Or think of an application in which selecting a value in a combobox widget determines the values that are displayed in a table. Or perhaps an application where clicking on a widget loads a service, such as a blog, into another widget such as a table widget. Using the jMaki event mechanism makes these operations easy and straightforward.

Overview of jMaki Events

Events in jMaki are handled by something called Glue. jMaki Glue is a powerful feature that enables JavaScript components to talk to each other. You can use Glue in your web application to implement widget-to-widget communication. However, any JavaScript component can utilize the power of jMaki Glue.

Let's start with a simple example that uses Glue. Suppose you had an application that displays two buttons and two tables on a page as shown in Figure 1.

Figure 1. A Web Page That Displays Two Buttons and Two TablesFigure 1. A Web Page That Displays Two Buttons and Two Tables

The first button, labeled "select row 2", selects the second row of both tables, as shown in Figure 2, while the second button, labeled "yahoo table: select row 2", only selects the second row of the second table.

Figure 2. What Happens When You Click the select Row 2 ButtonFigure 2. What Happens When You Click the select Row 2 Button

Here's the code that enables the interaction:

<a:widget name="yahoo.button"
value="
{label : 'select row 2',
action : {topic : '/table/select', message: {targetId: 'bar'}}}"/>

<a:widget name="yahoo.button"
value="
{label : 'select row 2 in yahoo table',
action : {topic : '/mytable/select', message: {targetId: 'bar'}}}"/>

<a:widget name="dojo.table"
value="{columns : [
{ label : 'Title', id : 'title'},
{ label :'Author', id : 'author'},
{ label : 'ISBN', id : 'isbn'},
{ label : 'Description', id : 'description'}
],
rows : [
{ title : 'Book Title 1',
author : 'Author 1',
isbn: '4412',
description : 'A Some long description'},
{ id : 'bar',
title : 'Book Title 2',
author : 'Author 2',
isbn : '4412',
description : 'A Some long description'}
]
}" />

<a:widget name="yahoo.dataTable"
subscribe="['/table', '/mytable']"
value="{columns : [
{ label : 'Title', id : 'title'},
{ label :'Author', id : 'author'},
{ label : 'ISBN', id : 'isbn'},
{ label : 'Description', id : 'description'}
],
rows : [
{ title : 'Book Title 1',
author : 'Author 1',
isbn: '4412',
description : 'A Some long description'},
{ id : 'bar',
title : 'Book Title 2',
author : 'Author 2',
isbn : '4412',
description : 'A Some long description'}
]
}" />

Notice that there are ajax custom tags that wrap four widgets in the code example, two for Yahoo button widgets, one for a Dojo table widget, and one for a Yahoo table widget. Notice too that the tags for both of the button widgets include the action attribute:

action : {topic : '/table/select' ...

In jMaki, all table wrappers subscribe to the generic topic "/table" as well as to a topic that specifies the specific table (for example, "dojo/table"). Notice that the tag for the Dojo table widget includes the subscribe attribute:

subscribe="['/table', '/mytable']" ...

In both cases, the widgets subscribe to topics that are published by the button widgets. More specifically, one table widget subscribes to the generic topics ("/table" and "/dojo/table") and the other subscribes to a generic topic ("/table") and to a custom topic ("/mytopic") for that instance of the table.

This is all you have to write for these widgets to communicate. jMaki Glue handles the widget-to-widget communication without you having to write any additional JavaScript code.

Publish/Subscribe Mechanism

So what really is Glue? It's a programmatic approach to handling events in jMaki based on a publish/subscribe mechanism. Publish/subscribe mechanisms are used extensively in messaging systems. In jMaki there are producers of events (also called publishers) and consumers of events (also called subscribers). Widgets can be both producers and consumers. When an event occurs on a widget that is a producer, the widget publishes a notification of that event to a topic. A topic is a string or a name that associates the producer of an event to the consumers of that event and allows the producer and consumers to communicate in an asynchronous and decoupled way. Widgets that are interested in being notified of events published to that topic can register to become consumers of that topic. To do that, they subscribe to that topic.

Most widgets in jMaki publish events to topics based on some action. For example, a user selecting a row in a table, or clicking on a button, or expanding a tree node can result in the respective widget publishing a notification, that is, an event to a topic. Some widgets like the jMaki dcontainer, are consumers and expect to receive notification of events telling them to do something in response, such as load content from another page, update the rows in a table, or add a node to a tree. The notification includes data identifying the producer widget and any data in the widget that is useful to the consumer. Each consumer receives a notification of the event along with the published data. Using this mechanism, any producer widget can "talk" to any consumer widget (or set of consumer widgets) in a loosely coupled way.

Using Publish/Subscribe

There are two ways to use the jMaki publish/subscribe mechanism: (1) through actions, which represent a declarative approach, or (2) through programmatic events. Both approaches use the same implementation and therefore behave the same way.

Actions

Actions are a way of defining a producer of events in a declarative form. This approach is useful when the action is simple or straightforward. Consider the previous example. Recall that you want to select the second row of both tables when a user clicks on the "select row 2" button.

Here again is the tag for the button widget:

<a:widget name="yahoo.button"
value="
{label : 'select row 2',
action : {topic : '/table/select', message: {targetId: 'bar'}}}"/>

The button widget uses the action property to publish to the '/table' topic the command '/select' and the payload targetId: 'bar'.

Before continuing with the discussion of the action approach, let's briefly examine topic names, commands, and payloads.

  • Topic names. By default, topic names start with a slash followed by the name of the toolkit (such as jmaki, dojo, yahoo, and google), then a slash followed by the name of the widget (such as table, tree, or accordion). For example, the dojo table topic name defaults to "/dojo/table". See the jMaki widget documentation for the name of the topic to which a widget will publish by default. You can, however, override the default topic name, and because a topic name is a string, you can set it to any string. For the Yahoo button widget, the topic name is set to "table".
  • Commands. Many widgets are consumers of events and so also have event handler code in them. The event handlers in the widget code perform common operations on the widget. The set of operations supported are specified in the jMaki Data Event model pages. The jMaki documentation refers to the operations as commands. Commands are specific to the type of widget. The command name is appended to the end of the topic name, and by convention, it is the string that follows the last slash in the topic name. For the Yahoo button widget, the published command is "select", and it follows the slash after the topic name "table".
  • Payloads. When a widget publish to a topic it specifies the topic name and a payload. The payload is the data that the widget publishes to the topic. The Yahoo button widget publishes the payload targetId: 'bar'.

Here again is the tag for the Yahoo table widget:

<a:widget name="yahoo.dataTable"
subscribe="['/table', '/mytable']"
value="{columns : [
{ label : 'Title', id : 'title'},
{ label :'Author', id : 'author'},
{ label : 'ISBN', id : 'isbn'},
{ label : 'Description', id : 'description'}
],
rows : [
{ title : 'Book Title 1',
author : 'Author 1',
isbn: '4412',
description : 'A Some long description'},
{ id : 'bar',
title : 'Book Title 2',
author : 'Author 2',
isbn : '4412',
description : 'A Some long description'}
]
}" />

Actions rely on code that already exists in each widget. The underlying code sets up event handlers that can be used through the action property or directly. When a widget is initialized, the topic, such as /table/select, is associated by the underlying code with a function that is in the widget code.

If you examine the jMaki data models, you'll notice a set of properties that are common across the models. One of those properties is id. You use this property to identify an item such as a tab, table row, or tree node. Some of the other common properties are label, href, and action. Notice that the second row of the table has the id 'bar' (if no id property is present, jMaki generates an id for you) and recall that the payload published by the Yahoo button widget for a select event is targetId: 'bar'. This targets the second row of the Yahoo table when the Yahoo button is selected.

Programmatic Events

There are times when the action you want performed in response to an event is not as straightforward as highlighting a row in a table. For example, you might want the response action to get data from a database and then use the data to update a table. To do this you need to use the programmatic interface of Glue, which like the action approach, is based on the publish/subscribe mechanism. In fact, actions use Glue, but are transparent to you as an application developer. To use the programmatic events approach, you typically add some code to a JavaScript file named glue.js. The file is loaded by the jMaki framework by default. Placing the JavaScript code in the glue.js file makes it available to the entire application and promotes separation of JavaScript code from HTML, XML, and other markup in the application.

Let's use the Programmatic Events approach to extend the previous example. Specifically, let's add a button to the page and use the button to add a row to a table.

Here's the code for the new button:

<a:widget name="yahoo.button"
value="
{label : 'add row',
action : {topic : '/mytopic'}}"/>

You also need to add a listener to the topic '/mytopic', which will add the row of data to the table. Add the listener or handler to the glue.js file. The jMaki runtime will add this new handler to the internal hash map for topics when the page is loaded.

 jmaki.subscribe("/mytopic", function(args) {
jmaki.log("in mytopic");
var row = { id : 'new',
title : 'Book Title 3',
author : 'Author 3',
isbn : '4413',
description : 'A Some long description'};
jmaki.publish("/table/addRow",{value: row});
});

Here the row data is hard coded, but it can come from a database. The jmaki.publish API is used to send the data to the topic '/table'. Both tables in this example subscribe to that topic so both will add a row when the button is clicked.

Figure 3 shows what the page looks like after the new button, labeled "add row", is clicked.

Figure 3. A Button that Adds a Row to a TableFigure 3. A Button that Adds a Row to a Table

Chaining Events

Let's look at one last example. Suppose you wanted the new button in the previous example to add a row to the tables and also select the new row. To do that, you don't need to change the tags. Instead, you only need to update the handler in the glue.js file. Here's what the updated handler code looks like:

jmaki.subscribe("/mytopic", function(args) {
jmaki.log("in mytopic");
var row = { id : 'new',
title : 'Book Title 3',
author : 'Author 3',
isbn : '4413',
description : 'A Some long description'};
jmaki.publish("/table/addRow",{value: row});
jmaki.publish("/table/select", {targetId: 'new'});
});

This is an example of how to chain events in jMaki. You're chaining the publishing of two events: the event that results in a row being added to a table, and an event that selects the added row.

Figure 4 shows what the page looks like after the add row button is clicked.

Figure 4. A Button that Adds a Row to a Table and Selects the RowFigure 4. A Button that Adds a Row to a Table and Selects the Row

You can download the application that displays the page shown in Figure 4 and try it out yourself.

Further Reading

The jMaki sample getwidgetdata is a more complete example of using Glue in jMaki. That example demonstrates how to get data from the widget using a handler and how to pass the data to the server and on to another page in the application. The jMaki loadtable example shows how to use actions and Glue code to manipulate a table widget. Both examples are included in the standalone bundles, jmaki-java-1.1.zip and jmaki-php-1.1.zip, which you can download from the jMaki Downloads page.

For more information about the Publish/Subscribe mechanism see Handling jMaki Widget Events Using the Publish and Subscribe Mechanism.

Also see the blog Fun with jMaki: Using the Yahoo Geocoder service with the Dojo Combobox, which shows some of the potential of jMaki Glue to work as a controller.

About the Author

Carla Mott is a contributor on Project jMaki. She is also a Java Enterprise Community leader on java.net and a committer on Dojo, an open-source JavaScript toolkit. Previously, she was a project owner for Project GlassFish where she helped to open source Sun's application server and to build the GlassFish community.

 

References
Published at DZone with permission of its author, Schalk Neethling. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)