|
Articles Index
Project jMaki
gives you a simple way to include Ajax-enabled widgets in your web
applications. (Ajax
is a technology that includes but is not limited to Asynchronous
JavaScript and XML.) The jMaki technology does this by allowing you to
wrap widgets in a JavaServer
Pages (JSP) technology tag handler or a JavaServer
Faces component. By wrapping a widget in this way, you can
encapsulate it in a modular unit and also give it the benefits of any
JSP tag handler or JavaServer Faces component.
The primary benefit is that you can easily include wrapped widgets
into any JSP or JavaServer Faces technology-based application in the
same way that you would include any other custom JSP tag or JavaServer
Faces component tag. By wrapping the widget in a JavaServer Faces
component, you can give the widget all the functionality of any other
JavaServer Faces component, including access to data conversion and
validation capabilities. What's more, jMaki does all the work of
creating the custom tag handler or custom JavaServer Faces component
for you. You won't need to write another tag handler, component class,
or component renderer by hand.
What makes the technology so flexible is that jMaki does not limit
you to any particular kind of widget from any particular vendor. You
can grab one of the widgets from Dojo, Script.aculo.us, or wherever you like and create a
jMaki wrapper for it with minimal effort. With so many cool widgets
available out there, this is a huge benefit: You don't have to reinvent
the wheel. Still, if you don't find a widget that meets your needs, you
can create one using jMaki and wrap it in a JSP technology tag handler
or a JavaServer Faces component, as you would with any other widget.
The following sections give you a short introduction to using jMaki.
First, you'll see how easy it is to include a jMaki component in a
page. After that, you'll find out what's included in a typical jMaki
widget. Then you'll learn how to wrap the components of a prebuilt,
third-party widget and use it in a page. Finally, you will see how to
create your own jMaki widget from scratch and add it to your
application.
The modular nature of a jMaki widget makes life easier for page
authors. You don't need to know any JavaScript
technology to use the widgets, and you can reuse them in multiple pages
with minimal effort.
Once you download and unpack the jMaki
zip file, adding jMaki widgets to applications is quite easy. It
just takes some simple steps:
- Find the
jMaki.war file in your unpacked jMaki zip
file.
- Copy the
jmaki.js file from the resources
directory of jMaki.war to your application's web
directory.
- Copy the
ajax-wrapper-comp.jar file from the WEB-INF/lib
directory of jMaki.war to your application's web/WEB-INF/lib
directory.
- Copy the widget's resources to your application's
web/resources
directory. For example, the Dojo inline edit widget is located in
the resources/dojo/inlineedit directory of jMaki.war.
- Add any scripts supplied by the third party that produced the
original widget to the
web/resources/libs directory. For
example,
the Dojo scripts are located in the /resources/libs/dojo
directory of the jMaki distribution.
For details on how to get started, see one of the two tutorials
listed in the For More Information
section.
Once you perform the preceding steps, you can decide whether to use
a widget in a JSP technology tag handler or a JavaServer Faces
component by adding one of the two tag libraries that come with Project
jMaki:
<%@ taglib prefix="a" uri="http://java.sun.com/jmaki-jsf" %> <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>
|
After adding one of these to the page, include the
widget using the ajax custom tag:
<a:ajax name="dojo.inlineedit"/>
|
The name attribute refers to the widget's name. In this case, it specifies
the inline edit widget, a jMaki widget wrapped from the Dojo toolkit's InlineEditBox widget. This is one of the widgets included in the jMaki distribution. The inline edit widget allows users to edit a text string by clicking on it, editing the text string, and clicking a button, as shown in Figure 1.
Figure 1: Screen Capture of the Inline Edit Widget
|
There are other attributes besides the name attribute on the ajax
tag. Different widgets might require you to use different attributes. See Using
jMaki Widgets for a description of the other attributes.
The next section describes what a typical jMaki widget includes.
After that, you'll find out how the jMaki development team wrapped the inline edit widget
using jMaki.
A jMaki widget is composed of the following simple pieces:
- A
component.js file: A JavaScript technology file
that contains all the client-side logic that handles any
user-initiated events and interacts with the Ajax mechanism.
- A
component.htm file: An HTML file that the
rendering mechanism will use as a template to render the widgets to the
client.
- A
component.css file: A CSS stylesheet that
controls the appearance of the widget, such as the style of fonts it
might use. This file is optional.
As described in the previous section, when you package the widget in
your web application, you must also add the following files:
- The
jmaki.js file
- The
ajax-wrapper-comp.jar file
- Any extra script libraries that the widget requires
Figure 2 shows where the basic resources of a Dojo jMaki
widget are located in a web application.
Figure 2: Example Locations of Resource Files in an Application
|
A widget might also require a service component, which can be a
servlet, a JSP technology page, or a managed bean. This component has
access to the request parameters and can perform some extra processing
when the widget is activated. For example, if you have a widget that
allows you to add items to a list, the service performs the logic that
initializes the List object and invokes its add
method with the new item to add.
The next section describes how to wrap these components into a jMaki
widget.
Before you get started learning how to wrap a prebuilt widget, you
should know that you might not even need to do so. Project jMaki
comes with many common widgets already wrapped, including several from
the Dojo toolkit
and Script.aculo.us.
Just follow the simple instructions in the section Using a jMaki Widget to use those
existing widgets.
To show you how easy it is to wrap a widget with jMaki, this article
will now describe how the jMaki development team wrapped the Dojo InlineEditBox widget,
included in the jMaki.war file as the inline editor jMaki
widget. First, the jMaki development team downloaded the widget code from the Dojo toolkit web
site. The code for all the Dojo widgets is already available in
the jMaki distribution.
To wrap the Dojo inline editor widget with jMaki, the jMaki development team followed these steps:
- Set up the widget's directory structure.
- Create three files:
component.js
component.htm
component.css
The first step is to create the inlineedit directory
for the widget. What you name the directory is significant because this
is how the jMaki wrapper and rendering mechanism will refer to the
widget. You can find this directory in the resources/dojo directory of
your jMaki.war file. Inside the inlineedit directory, add
the three templating files: component.htm, component.js,
and component.css.
The component.htm file is the HTML template file in
which you can customize how the widget will be used on the page. In
this case, the component.htm file includes the following information:
<h1 id="${uuid}" dojoType="inlineEditBox"> Edit me - I will trigger a custom onSave Handler</h1>
|
These lines tell the jMaki rendering mechanism to render a Dojo
InlineEditBox widget with a heading 1 and give it a
generated ID. Because you can put any number of these widgets on a
page, jMaki will replace the parameterized ID ${uuid}
with a generated ID, which it constructs with the name of the
widget, concatenated with an integer representing the instance of
the widget in the page.
The component.js
file includes the JavaScript technology code that will import the
code that came with the prebuilt widget and bootstrap it so that it
works with your application:
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.InlineEditBox");
dojo.require("dojo.event.*");
var w = dojo.widget.createWidget(widget.uuid);
w.getValue = function() {
return w.textValue;
}
// Save the state.
if (typeof widget.valueCallback != 'undefined') {
w.onSave = function(newValue, oldValue) {
var url = widget.valueCallback;
dojo.io.bind({
url: url + "?cmd=update",
method: "post",
content: { "value" : newValue },
load: function (type, data, evt) {
}
});
}
}
w.saveState = w.onSave;
jmaki.attributes.put(widget.uuid, w);
|
As
this code shows, you must import the appropriate Dojo packages and
call the createWidget function to create the widget.
Then you provide a function that gets the widget's current value,
which is whatever the user entered into the text field.
The
next several lines of code provide support for saving the state of
the widget to a managed bean, for those who want to use a widget as
a JavaServer Faces component. These lines will be essentially the
same for any Dojo widget wrapped as a jMaki widget.
Finally,
you add the widget ID to a special properties map using the
jmaki.attributes.put function. This saves the widget
for later use, in case you have components that need to interact
with each other.
At this point, you have a jMaki widget. Now
you can decide whether to wrap this widget in a JSP technology tag
handler or a JavaServer Faces component by using one of the two tag
libraries that come with Project jMaki, as shown in the section Using a jMaki Widget.
After
adding one of these to the page, you can include the widget by using
the ajax custom tag:
<a:ajax type="dojo"
name="dojo.inlineedit"/>
|
The name
attribute refers to the name of the directory in which you created
the widget.
Before you begin creating a new widget, browse through the
widgets included with jMaki to see whether one of those fits your
needs. If you don't find what you need there, check out Dojo and
other widget repositories to see whether you can use one from there
and wrap it with jMaki. The process of creating a brand-new
jMaki widget is almost the same as the process of wrapping an
existing widget, except that you must provide the JavaScript
technology code that implements the widget. Here are the steps:
- Create a new directory for the widget.
- Create the
component.htm file.
- Create the
component.css file.
- Create the
component.js file.
- Create a separate service in the form of a JSP technology page or JavaServer Faces technology
managed bean to perform any necessary logic other than that used to
handle Ajax requests.
- Include the necessary jMaki
bootstrap JavaScript technology file and tag libraries.
- Include the widget in a page.
The list
widget, which is part of the jMaki distribution, was created from
scratch -- that is, it is not just a wrapper around a pre-existing
widget. This widget allows the user to add items to a list and
display the list on the page. It also allows the user to click an
item in the list to remove it. Figure 3 shows a screen capture of a
page using the list widget.
Figure 3: Screen Capture of List Widget |
Let's take a look at the different pieces of the list widget to get
a sense of how you can create new jMaki widgets. First, go to the widgets/list
directory of the jMaki distribution. In the src/resources
directory, you'll find the component.js, component.htm,
and component.css files.
The component.htm File
The component.htm file includes the following:
<div id="${uuid}" class="listContainer"> <form onsubmit="jmaki.attributes.get('${uuid}').submitData(); return false;"> <input id="${uuid}_entryField" type="text" size="20" value="Enter new Value"> <input type="button" onclick="jmaki.attributes.get('${uuid}').submitData(); return false;" value="Add to List"> </form>
<div id="${uuid}_list" class="listDiv"></div> </div>
|
Notice that there are two div tags, one inside the
other. A JavaScript technology function looks for a tag in a page by
using the unique IDs of div tags. The outer div
tag wraps the form component, which includes the field in which you
enter an item, the button to add the item to the list, and the inner div
tag. The inner div tag identifies the component that
displays the list on the page.
When the user clicks the button, jMaki gets the ID of the entire
list widget and invokes the widget's submitData method,
defined in the component.js file. After the application
displays the list, the user can remove an item from the list by
clicking on the item.
The component.css File
The component.css file defines a few simple styles
that help give feedback to the user. For example, the application must
indicate to the user that clicking on an item in the list will remove it.
When the user passes the mouses over an item, the following style is
applied to it:
.over { color: white; height:25; font-size:18px; font-weight: bold; font-family: Arial; background: blue; cursor: pointer; }
|
As you can see, at the mouseover event, the background changes to
blue, the text changes to white, and the cursor turns into a pointer,
indicating that clicking on the item will have an effect. You'll see
how this style is used in a later discussion about the service listService.jsp,
which interacts with component.js file to manipulate the
contents of the list.
The Interaction of the component.js File and the listService.jsp
File
The component.js file contains the mostly boilerplate
code you've seen before to implement the Ajax mechanism. It contains
two functions: submitData and removeItem.
These functions interact with the listService.jsp
service. This service does the work of adding an item to the list or
removing an item from the list using common java.awt.List
operations. In this section, you will see how the component.js
and listService.jsp files work together to manipulate the
list's contents.
Here are the submitData and removeItem
functions from the component.js file:
this.submitData = function() { var list = document.getElementById(uuid + "_list"); var req = getXHR(service); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { list.innerHTML = req.responseText; } } }; req.open("POST", service, true); var entryField = document.getElementById(uuid + "_entryField"); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("command=add&entry=" + entryField.value + "&uuid=" + uuid); }
this.removeItem = function(index) { var list = document.getElementById(uuid + "_list"); var req = getXHR(service); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { list.innerHTML = req.responseText; } } }; req.open("POST", service, true); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("command=remove&index=" + index + "&uuid=" + uuid); }
|
This submitData function does the following:
- Passes the
listService.jsp service to the XMLHttpRequest
object
- Gets the
list element and the entryField
element from the HTML DOM
- Gets the value that the user entered into the
entryField
- Passes to the service these three items:
| |
- The value - The list - The command to add the value to the list
|
The removeItem function accomplishes the following tasks:
- Passes the
listService.jsp service to the XMLHttpRequest
object
- Gets the list widget from the HTML DOM
- Passes to the service these three items:
| |
- The list - The index of the item to remove - The command to remove the item from the list |
The listService.jsp service receives the ID of the
list widget and the command -- add or remove
-- from the request parameters. When the service renders the list, it
renders the following div tag to the page for each item
in the list:
<div class=\"plain\" onmouseover=\"this.className ='over';\" onmouseout=\"this.className ='plain';\" onclick=\"jmaki.attributes.get('" + uuid + "'). removeItem('" + counter++ + "')\">" + it.next() + "</div>
|
This div tag contains some script that allows the user
to select an item in the list to remove it. This action invokes the removeItem
method in component.js, which in turn will send to the
service the remove command, the widget ID, and the index
of the item to be removed.
Notice that the service in this case is a JSP technology page. You
can implement the service code in a different kind of component, such
as a servlet or a JavaServer Faces technology managed bean.
Packaging and Using the List Widget
Now that you have created all the files you need, you must package
them, along with some files that jMaki provides, as described in Using a jMaki Widget.
That's it. Now you can use the list widget as shown here:
<a:ajax name="list" service="listService.jsp" />
|
Conclusion
Project jMaki makes it easier to add Ajax to both pure JSP and
JavaServer Faces technology-based applications. jMaki simplifies the
page author's work because the widget is encapsulated in a modular,
portable unit, thereby shielding the page author from JavaScript
technology code and facilitating reuse of the widgets.
It's also easier for developers for many reasons. They can reuse
most widgets they already created. And they get the benefit of a JSP
technology tag handler or JavaServer Faces component without having to
write the extra code that is associated with creating these modules.
For More Information
About the Author
Jennifer Ball is a staff writer at Sun. She writes about web application technologies that are part of the Java EE platform.
|