The Atom protocol pair lets online providers of resources such as news, community Web sites, and blogs to syndicate their content through the Web. In a typical use of Atom, content providers syndicate a file, or a Web feed, and make it available over the Web. The feed, whose representation is defined in the Atom Syndication Format, provides a summary of recently added resources. Published feeds can then be used by Atom client software, such as blog readers, which leverage the Atom Publishing Protocol to discover newly added content and present it.
This article will add to your Ajax knowledge by demonstrating how to start to develop an Ajax- and Atom-based blog reader (in this installment you will develop the view and controller components of the reader). You'll use the Dojo toolkit to develop the application, which will communicate with back-end Atom feeds using the Atom Publishing Protocol. You'll also use the Dojo storage package to keep feed subscription data.
Dojo — our Ajax toolkit of choice
This blog reader application is based on the Dojo toolkit, and you might wonder why we selected Dojo and not some of the other toolkits out there. The Book of Dojo (see Resources) suggests several reasons, but for the purposes of this exercise, we cite two simple reasons that drove us to use Dojo:
- Vertical integration and completeness: compared to other open source Ajax toolkits, Dojo offers the most complete and integrated library of components.
- Black box reuse: the Dojo widget mechanism allows developers to compose new applications from widgets without knowing their internals. This makes it relatively easy to create sophisticated Ajax applications.
Vertical integration and completeness
Dojo has a layered architecture, where each layer adds a progressively more advanced functionality:
- The Dojo core layer includes the fundamental Ajax features that are present in many toolkits (such as IO and DnD), cross-browser compatibility, basic DOM manipulations, and so on.
- On top of the Dojo core, the DIJIT layer provides the widget system as well as many widgets.
- The last layer, DOJOX, includes various extensions such as offline storage and cross-browser vector graphics.
Collectively, the various layers of the Dojo architecture produce a comprehensive integrated toolkit that addresses most development needs.
Dojo widgets are Ajax-based UI components that can be reused with a single line of HTML code. For example, Listing 1 shows how an expandable title pane widget can be instantiated in an HTML page:
Listing 1. Title pane widget instantiation in an HTML page
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" src="../../dojo/dojo.js"
djConfig="parseOnLoad: true, isDebug: true"></script>
<script language="JavaScript" type="text/javascript">
dojo.require("dijit.TitlePane");
dojo.require("dojo.parser");
</script>
<style type="text/css">
@import "../../dojo/resources/dojo.css";
@import "../themes/tundra/tundra.css";
</style>
</head>
<body class="tundra">
<div dojoType="dijit.TitlePane"
title="This is the title" style="width: 300px;">
And this is the content, clicking the title
will expand/collapse me.
</div>
</body>
</html>
|
As you can see, the page starts by importing the core Dojo library. Once the Dojo
core is loaded, we can use dojo.require() to load the
TitlePane widget, which we then reference inside the body tag.
Figure 1 shows the TitlePane widget in action, the outcome of the code fragment shown in Listing 1:
Figure 1. TitlePane widget in action
InformationBox — developing a simple Dojo widget
Widgets are implemented by a Dojo JavaScript class that provides the widget's functionality. For widgets with a complex UI, you can also provide an HTML fragment to function as the widget UI template. To dispel the magic behind widgets, let's develop a very simple widget that displays informational messages. The widget will allow users to title an information fragment and provide outcomes similar to the illustration in Figure 2:
Figure 2. InformationBox widget in action
Listing 2 presents dwsample.Info, our informational
message widget:
Listing 2. InformationBox widget implementation
if(!dojo._hasResource["dwsample.Info"]) {
dojo._hasResource["dwsample.Info"] = true;
dojo.provide("dwsample.Info");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare(
"dwsample.Info",
[dijit._Widget, dijit._Templated],
{
title: "",
// The widget content template
templateString: [
"<div id='${id}' class='dijitTitlePaneTitle'>",
" <div>",
" <span dojoAttachPoint='titleNode' style='font-size:1.1em; margin:
1em;'></span>",
" </div>",
" <div dojoAttachPoint='containerNode' class='dijitTitlePaneContent'></div>",
"</div>"
].join('\n'),
postCreate: function(){
this.setTitle(this.title);
},
setTitle: function(/*String*/ title){
this.titleNode.innerHTML = title;
}
});
}
|
As shown in Listing 2, the widget implementation really starts with the dojo.declare() function.
This function receives the widget's definition in JSON format and initializes a new widget.
An important aspect of this new widget is the templateString. It provides an HTML fragment that serves as a template to the HTML content generated by the widget. The template is scattered with dojoAttachPoint
attributes instructing Dojo to attach the marked DOM element as a member of the
generated template. This allows widgets direct access to the DOM nodes without DOM
manipulations (as seen in the method setTitle). A special
attach point, containerNode, signals a special DOM node where
the widget body should be appended.
Using the new widget is simple, as demonstrated in Listing 3:
Listing 3. InformationBox widget usage
<div dojoType="dwsample.Info"
title="Do not panic, here is what you need to do"
style="width: 500px;">
At first, developing a Dojo widget looks like a chore, but it is
not! Here is what you should do:
<ol>
<li>Create a JavaScript file with the name of the widget and in
a directory structure known by Dojo</li>
<li>Extend the Dojo widget base classes</li>
<li>...</li>
</ol>
</div>
|
While the informational message is a very simple widget — it does not use events or expose new methods — it should give you enough of an idea of how widgets operate.
Now that you have a basic knowledge of Dojo, let's take a look at Atom and its use in our blog reader.
The term Atom refers to a pair of standards that define a feed format (for representing) and a protocol (for editing) Web resources such as Weblogs, online journals, Wikis, and similar content:
- The Atom Syndication Format (ASF) was standardized in RFC 4287 and specifies the representation format of Atom resources.
- The Atom Publishing Protocol (APP) is still in its draft form and specifies how to use REST to manage Atom resources.
Note that while Atom started with blogging in mind, it has a more general use in that it allows for CRUDing Web resources (CRUD is an acronym for create/read/update/delete).
The Atom Syndication Format (ASF)
The ASF specifies the XML representation for resources carrying information on syndicated item collections (also known as feeds) and the items they contain (known as entries):
- A feed is a uniquely identified, titled, and time-stamped collection of syndicated resource entries. Blogs are normally represented by one or more feeds.
- An entry is a uniquely identified, time-stamped resource with metadata such as title, summary, and categories. The entry's resource content can be anything from inline text to binary base64 encoded blob to out-of-line content specified by URI. Blog entries are normally represented by an entry in the blog feed.
To make the ASF more concrete, let's take a look at a short, single-entry Atom feed document in Listing 4:
Listing 4. Sample Atom feed
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>My Blog</title>
<link href="http://example.org/myblog/"/>
<updated>2005-11-13T16:25:05Z</updated>
<author>
<name>John Smith</name>
</author>
<id>urn:uuid:50a70c74-d399-11d9-b93C-0004545e0af6</id>
<entry>
<title>What is Atom?</title>
<link rel="alternate" href="http://example.org/myblog/1"/>
<id>urn:uuid:1234c670-cfb8-4ebb-aaaa-80da352efa6a</id>
<updated>2005-11-13T16:25:05Z</updated>
<summary> The term Atom refers to a pair of standards</summary>
<content type="text/html">
The term Atom refers to a pair of
standards which are primarily used in the context of Web
content syndication. The emergence of Atom was motivated ...
</content>
</entry>
</feed>
|
As you can see, the feed representation carries with it some feed-specific information, followed by any number of entries.
The Atom feed information includes a few mandatory elements as well as recommended and optional elements. The mandatory feed elements include:
- Title: Provides a human-readable title for the feed. Typically, it is the same as the title of the associated Web site.
- Updated: Indicates the most recent time when the feed was modified, in a format the publisher considers significant.
- ID: Conveys a permanent, universally unique identifier for the feed.
The Link element, a recommended Atom feed element, can be used to link to various other resources that are related to the feed (including links back to the Atom feed resource).
The Atom entry element is similar to the feed element in that it also must contain the title, updated, and ID sub-elements. In reality, however, the entry does not serve its purpose without additional elements, such as:
- Link: Links to a resource that is related to the entry. The relation type is
defined by the
relattribute; for example, the valuealternatesignifies that the link provides an alternate representation of the resource described by the entry element. - Content: Contains either the actual resource representation or links to the representation.
- Summary: Provides a short excerpt of the entry.
If no entry content is provided, there must be at least one alternate link pointing to the content.
Atom Publishing Protocol (APP)
The APP is a REST-based protocol for publishing and editing Web resources. This means that APP applies not only to Atom resources, but also to other Web-related resources, such as images, e-mail content, and more. As RESTful protocols go, APP leverages the HTTP protocol (including methods, headers, and status codes, among others) to CRUD the resources. APP will be used by your blog reader to interact with ATOM feeds and entries.
APP introduces the concept of collections, which are sets of resources that can be retrieved in whole or in part. In the Atom syndication realm, these collections and resources are mapped to Atom feed and entry resources, whose representation is encoded according to the ASF. In addition to collections and resources, the APP also defines workspaces and services that can be used to discover collections (however, this is beyond the scope of this article).
Now, having covered plenty of background, you're ready to start building your blog reader!
Implementing a blog reader with Atom
Our blog reader application (shown in Figure 3) manages a list of blog feeds (and their URIs) which are of interest to the user:
Figure 3. Blog reader application
Feeds can be added to and removed from the list. In our application, users subscribe to a specific feed of interest by entering its title and URI into the dialog box (as shown in Figure 4):
Figure 4. Adding a feed
When a user wants to see content in a certain feed, he or she simply selects it in the feeds combo-box. Behind the scenes, the blog reader application follows the APP and sends an HTTP GET request to the feed URI. The reader then checks the returned HTTP status code and in case of success (status code is 200), it retrieves the resulted Atom entry collection from the HTTP response payload. At this point, the reader inspects the returned entries and presents them to the user. First, the entries are listed together at the left side of the application, with the entry title representing the entry in the list (see Figure 5):
Figure 5. Listing the entries
At this point, the user can select an entry from the list by clicking it and the reader does its best to present the content of the entry using the following algorithm:
- If the entry includes a
contentelement with actual resource representation, it is used. - Otherwise, if a
summaryelement is available, it is used. - If both content and summary elements are missing, a link to the content is presented.
If the original article link could not be detected either, the link to the alternate
entry resource representation is given, as specified in the
linkelement withrelattribute havingalternatevalue. When the user follows the link, a new browser window is opened with the link.
The reader application follows the model view control (MVC) design pattern. Upcoming sections cover the implementation of the reader view and control components. (The model and the technology used for implementation will be covered in a future article.) Note that in our MVC implementation, a practical approach was taken that preferred simplicity over design purity. Therefore, the view and control are coupled more than may be optimal.
The blog reader view is implemented as a single HTML file that leverages Dojo. The view includes three main sections as sketched in the (skeletal) Listing 5:
Listing 5. View component implementation
<html>
<head>
<!-- Section 1, Dojo and application imports -->
</head>
<body class="tundra">
<!-- Section 2, Blog Reader UI -->
<fieldset class="feed-definition-area">
Select Feed:
...
</fieldset>
<hr>
<div class="feed-area">
<div dojoType="dijit.layout.SplitContainer"
...
</div>
</div>
<!-- Section 3, dialog box definitions -->
<div dojoType="dijit.Dialog"
id="add-feed-dlg"
...
</div>
<!-- Progress dialog -->
<div dojoType="dijit.Dialog"
id="progress-dlg"
title="">
...
</div>
<div dojoType="dijit.Dialog"
id="error-msg-dlg"
...
</div>
</body>
</html>
|
- The first section imports the various JavaScript, CSS, and widgets used throughout the application.
- The second section constructs the main reader UI.
- The third section defines all the various dialog boxes used throughout the reader implementation.
Let's take a more detailed look into the various sections of the application.
Take a look at Listing 6, which presents the full Imports section of the application:
Listing 6. Imports section
<head>
<title>Blog Reader</title>
<script type="text/javascript"
src="./reset-styles.js"></script>
<style type="text/css">
@import "../dojoAjax/dojo/resources/dojo.css";
@import "../dojoAjax/dijit/themes/tundra/tundra.css";
@import "css/blogreader.css";
</style>
<script type="text/javascript"
src="../dojoAjax/dojo/dojo.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dijit.Dialog");
dojo.require("dijit.util.manager");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.Textbox");
dojo.require("dijit.layout.SplitContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dojo.parser");
</script>
<script type="text/javascript" src="blog-reader.js"></script>
</head>
|
The Imports section starts by importing the JavaScript file
reset-styles.js, which resets the CSS
properties of the various tags to well-known defaults. Following the style reset, the various CSS files that set the look and feel of the application are imported. We first import the Dojo CSS files (and especially tundra.css that sets the look and feel of the
various Dojo widgets) and then add to them several blog reader-specific styles.
The next step is to import the Dojo library. In this case, Dojo is located in the
dojoAjax directory and the core dojo.js is imported. The various
required Dojo widgets are also imported using the dojo.require() method
(provided by the Dojo core).
As a last step, the blog reader logic held inside the file
blog-reader.js is imported (you will explore
blog-reader.js later in this article).
Section 2: Reader UI construction
Now that the various CSS and JavaScript files are included, we can start building the application using HTML tags and Dojo widgets, shown in Listing 7:
Listing 7. Blog reader UI implementation
<body class="tundra">
<fieldset class="feed-definition-area">
Select Feed:
<select dojoType="blogreader.FeedsCombo" id="feed-combo" comboClass="feedsCombo">
</select>
<button dojoType="dijit.form.Button" id="add-feed-btn" iconClass="addIcon">
Add Feed
</button>
<button dojoType="dijit.form.Button" id="clear-feed-btn" iconClass="cancelIcon">
Clean Feeds
</button>
</fieldset>
<hr>
<div class="feed-area">
<div dojoType="dijit.layout.SplitContainer"
orientation="horizontal"
sizerWidth="7"
activeSizing="false"
class="article-splitter">
<div dojoType="dijit.layout.ContentPane"
sizeShare="30"
sizeMin="20"
style="overflow:auto">
<div id="articles-table-wrapper"
style="visibility: hidden; width:96%">
<div dojoType="blogreader.ArticleList"
id="article-list"
listClass="articles-list"
titleClass="articles-list-title"></div>
</div>
</div>
</div>
<div dojoType="dijit.layout.ContentPane"
sizeShare="70"
style="overflow:auto">
<div id="article-content-pane" class="article-content-pane">
<div id="article-title-id" class="article-title">
</div>
<div id="article-content" class="article-content">
</div>
</div>
</div>
</div>
|
The first noticeable Dojo dependency in this section is the use of the tundra class
inside the body. Dojo implements visual themes using CSS. Setting the body class
to tundra kicks in the use of the Dojo tundra theme.
The first UI element we create is the feed selection control located at the top-most portion of the application's UI. The feed selection control is created by assembling together an HTML select control and two Dojo buttons. A few things to note in this section:
- We implemented a Dojo widget to wrap the select control. Wrapping the select with our own widget allows us to put all the presentation logic related to the feed selection (adding and removing feeds) in a single place.
- We do not set callbacks from the view to the controller directly in the markup. Later on we will bind the controller JavaScript methods and control event handlers programmatically.
- We decorate the buttons with icons (determined from a CSS class).
Next we construct the main area where the selected feed is presented. The goals for the feed presentation area are:
- If a feed is selected, present a list of entries at the left.
- If a certain entry is clicked, present its contents at the right. However, if the user did not select an entry, do not present anything.
We implement these goals using the Dojo split container, which allows us to take over
the browser space and split it into two areas, each populated by
ContentPane. The
ContentPanes are separated by a sizer control that allows users to resize the
ContentPanes. Each of the ContentPanes contains a div HTML element that wraps the
content (entry list/entry content). Using these div elements, we can easily show and
hide their content (using the display CSS style).
The entry list is once again implemented as a home-grown Dojo widget.
The third and last view section instantiates the dialog boxes used within the reader. In a perfect world, each of the dialog boxes would have been implemented as a widget. However, to keep things short, we embed the dialog boxes into our main UI and handle their events in the controller.
Take a look at Figure 6, which presents the Add Feed dialog box, which is the most complex of the various dialog boxes:
Figure 6. Add Feed dialog box
Listing 8 presents the implementation of the Add Feed dialog box:
Listing 8. Add Feed dialog box implementation
<div dojoType="dijit.Dialog"
id="add-feed-dlg"
title="Add Feed"
closeNode="cancel-add-feed-btn"
style="width: 400px;">
<form onsubmit="return false;">
<table class="table-no-border">
<tr>
<td>
<label for="feed-name">Title: </label>
</td>
<td width="100%">
<div dojoType="dijit.form.TextBox"
id="feed-name"
type="text"
required="true"
value=""
trim="true"
autocomplete="on"
classPrefix="noColors"
class="text-box"></div>
</td>
</tr>
<tr>
<td>
<label for="feed-url">URL: </label>
</td>
<td width="100%">
<div dojoType="dijit.form.TextBox"
id="feed-url"
type="test"
required="true"
value=""
trim="true"
classPrefix="noColors"
class="text-box"></div>
</td>
</tr>
</table>
<fieldset>
<button dojoType="dijit.form.Button" id="ok-add-feed-btn">
OK
</button>
<button dojoType="dijit.form.Button" id="cancel-add-feed-btn">
Cancel
</button>
</fieldset>
</form>
</div>
|
An interesting thing to note about the Add Feed dialog box is how easy it is to implement it out of widgets and HTML markup, as follows:
- By using the
dijit.Dialogwidget, we immediately gain the ability to open a simple and lightweight dialog box in the context of the existing browser window. - By populating
dijit.Dialogwith HTML markup and widgets, we determine how the body of the dialog box is going to look. - The cancel action can be easily implemented by using the
closeNodeattribute. This way, we do not need to implement the handler to the Cancel button. - The rest of the implementation is delegated to Dojo, which provides APIs that let us show and hide the dialog box including its content.
Our blog reader controller listens to events flowing from the view components and reacts to them by operating on the model. In general, the UI events are:
- New feed selection: The controller needs to load and present the newly selected feed.
- New entry selection: The controller needs to present the newly selected entry.
- Add feed button activation: The controller needs to pop up the Add Feed dialog box.
- Clean feeds button activation: The controller needs to erase the feed list.
- The OK button was pressed in the Add Feed dialog box: The controller should take the entered title and URL and add a feed using them.
The controller interaction with the model has an interesting twist to developers new to Ajax — it is asynchronous. In general, the JavaScript code running inside the browser is single threaded. This means that if you want to keep the UI alive and responsive while the model communicates over the network, you should work in asynchronous mode. For this reason, the controller also listens to the following model events:
-
feedDataArrived: Fired by the model when it is done reading a feed. Upon receiving this event, the controller knows that the feed data is cached in the model object and can be presented in the view. -
feedReadFailed: Fired by the model when the communication fails. Upon receiving this event, the controller knows that the model failed to communicate with the ATOM feed and an error message needs to be displayed
The upcoming sections walk you through the controller implementation and show how to connect to the view components and respond to various events using Dojo.
Binding to the UI and Model components
Listing 9 shows the general structure of the controller and focuses on the
initialize() method and the two tasks it performs:
- Locating the UI components through their IDs
- Assigning listeners to various events in the model and the UI
Listing 9. Binding to the UI and Model components
var BlogController = {
mHideProgressFunction: null,
mFeedsCombo: null,
mAddFeedDlg: null,
mFeedURLTextbox: null,
mFeedTitleTextbox: null,
mArticleWrapper: null,
mProgressDlg: null,
mProgressDlgMsg: null,
mContentDiv: null,
mContentTitle: null,
mContentPane: null,
mErrDlgContent: null,
mErrDlg: null,
mArticleList: null,
// Initialize the page
initialize: function() {
this.mFeedsCombo = dijit.byId("feed-combo");
this.mArticleList = dijit.byId("article-list");
this.mAddFeedDlg = dijit.byId("add-feed-dlg");
this.mFeedURLTextbox = dijit.byId("feed-url");
this.mFeedTitleTextbox = dijit.byId("feed-name");
this.mArticleWrapper = dojo.byId("articles-table-wrapper");
this.mProgressDlg = dijit.byId("progress-dlg");
this.mProgressDlgMsg = dojo.byId("progress-msg");
this.mContentDiv = dojo.byId("article-content");
this.mContentTitle = dojo.byId("article-title-id");
this.mContentPane = dojo.byId("article-content-pane");
this.mErrDlgContent = dojo.byId("error-msg-content");
this.mErrDlg = dijit.byId("error-msg-dlg");
dojo.connect(BlogModel,
"feedDataArrived",
this,
this.feedDataArrived);
dojo.connect(BlogModel,
"feedReadFailed",
this,
function(errMsg) {
this.hideProgressDlg();
this.cleanFeedUI();
this.showErrorMsgDlg(errMsg);
this.mFeedsCombo.setValue("");
this.mArticleWrapper.style.visibility = "hidden";
});
BlogModel.initialize(this);
this.populateFeedsCombo();
// connect add feed/clean feeds to functions
dojo.connect(dojo.byId("add-feed-btn"),
"onclick",
this,
function() {
this.mAddFeedDlg.show();
this.mFeedTitleTextbox.focus();
});
dojo.connect(dojo.byId("clear-feed-btn"),
"onclick",
this,
this.cleanFeeds);
// dialog box callbacks
dojo.connect(dojo.byId("ok-add-feed-btn"),
"onclick",
this,
this.createFeed);
// Listen to combo box selection changes
dojo.connect(this.mFeedsCombo,
"onSelectionChanged",
this,
function() {
this.readFeed(this.mFeedsCombo.getSelectedValue());
});
// List selection changes
dojo.connect(this.mArticleList,
"onSelectionChanged",
this,
this.updateArticleContent);
},
createFeed: function(event) {
// Create a new feed reference, add it to the model and
// to the feeds combo
},
cleanFeeds: function() {
// erase all feed references from both the model and the view
},
// Updates the page content according the feed xml
feedDataArrived: function() {
// Feed was read. Update the reader with the new information
},
updateArticleContent: function() {
// The selection in the articles list changed, update the article pane
},
// Utility methods
populateFeedsCombo: function() {
// Populate the feeds combo box with the feeds registered in the model
},
readFeed: function(url) {
// Cleans the feed presentation UI and initiates fetching a new feed
},
// Clean feed content
cleanFeedUI: function() {
// Zero the Feed presentation UI
},
showErrorMsgDlg: function(errorMsgContent) {
// Pops up an error dialog box with a specific message
},
showProgressDlg: function(msg) {
// Pops up the progress dialog box with a specific message
}
};
|
The initialize() method shows how Dojo programs locate and
reference UI components (HTML elements and widgets) using their component IDs and two
methods:
-
dojo.byId(id): Looks up an HTML element using its ID as a parameter. The method returns the DOM object. -
dijit.byId(id): Looks up a Dojo widget using its ID as a parameter. The method returns the JavaScript object instance representing the widget.
If you follow our use of the byId() methods in the controller,
you will notice that we use them in the initialize() method
and cache the returned results in member variables. This is not just for performance
reasons, but more for maintainability. The IDs used in the view can change frequently
during the development phase, so looking them up once (and in a well-known location)
makes it easier to maintain the code.
Our controller uses dojo.connect to listen to events in the
view and the model. dojo.connect allows Dojo applications to
attach functions to method invocations in other objects. For example, the following code
fragment attaches the function foo to the
method bar in the object obj:
Listing 10. Listening to events
dojo.connect(obj, "bar", expectedThis, foo);
|
The third parameter of dojo.connect is the object reference to
be used as this in the called method. This can turn out to be
useful if you want to use a template function on different objects.
Note that because JavaScript treats functions as data, it is possible to pass function objects as parameters without declaring them specifically, as presented in the following code fragment:
Listing 11. Attaching function object
dojo.connect(this.mFeedsCombo,
"onSelectionChanged",
this,
function() {
this.readFeed(this.mFeedsCombo.getSelectedValue());
});
|
This feature comes in handy if you have many short functions (say, 2 - 3 lines) that are not used by anything but the connect method. In such a case, declaring the function at its place of use lets you improve the readability of your code.
Calling back on the Dojo widgets
As seen before, the Dojo widgets drive controller using events. However, how
can the event handlers call back on the Dojo widgets? The answer is simple: Dojo
widgets are simply JavaScript objects with public methods, and all you need to do is
call these methods. Similarly, HTML elements and their attributes get exposed as
DOM objects. As a result, the function showProgressDlg(msg)
presented in the following code fragment can easily set a message into the progress
dialog box and pop it up:
Listing 12. Event handler calling back on the Dojo widgets
initialize: function() {
// setup references to Dojo widgets and DOM elements
this.mProgressDlg = dijit.byId("progress-dlg");
this.mProgressDlgMsg = dojo.byId("progress-msg");
...
}
...
showProgressDlg: function(msg) {
// Use the methods exposed by DOM and the widget
this.mProgressDlgMsg.innerHTML = msg;
this.mProgressDlg.show();
},
...
|
(For more information about the methods exposed by Dojo and DOM objects, refer to the DOM and Dojo references listed in the Resources section).
At this point, you want to initialize the controller when the page finishes
loading and the Dojo widgets are ready for interaction. In this blog reader case, this
means calling to BlogController.initialize.
Dojo helps you accomplish the initialization tasks by providing a simple on-load
hook mechanism through dojo.addOnLoad. For example, in our controller example, we are using the
following code fragment to kickstart BlogController.initialize:
Listing 13. Controller initialization
dojo.addOnLoad(BlogController, BlogController.initialize);
|
dojo.addOnLoad can accept either one or two parameters:
- When a single parameter is used, Dojo expects it to be the function to execute when Dojo is loaded.
- With two parameters, it is expecting the first parameter to serve as
thisand the second parameter to be the function to execute when Dojo is loaded.
Note that as a developer, you can also try other approaches. For example,
you could use dojo.connect and bind to one of the dojo object
life cycle methods in a manner similar to the following code fragment. (However, note that this approach is not recommended because the life cycle methods can change in the future):
Listing 14. Another way for Controller initialization
dojo.connect(dojo,
"loaded",
BlogController,
BlogController.initialize);
|
You have learned about the essentials of blogging architecture and looked at two Atom standards and how they can be exploited by blog reader applications. You examined how the view and controller of a simple, yet functioning, Dojo-based reader can be implemented. The next article of the series will walk you through the implementation of the model. Stay tuned!
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample blog application | wa-aj-basics2.zip | 18KB | HTTP |
Information about download methods
- Read the
Atom Syndication Format specification
for the details on this XML-based feed format.
- Take a look at
The Book of Dojo.
- Consult the
Atom Publishing Protocol draft specification
for a better understanding of the application-level protocol for publishing and editing
Web resources.
-
The developerWorks Ajax resource center is packed with tools, code, and information to get you started developing slick Ajax applications today.
- With Web 2.0 being a hot area within development
circles, you'll find an ever-growing collection of resources in the Web development zone.
- Read James Snell's great developerWorks articles
"An overview of the
Atom 1.0 Syndication Format" and
"Create and edit Web resources with the
Atom Publishing Protocol" to quickly get on board with these two standards.
- Take a look at the DOM reference.
- Get more information on the Dojo reference.
Gal Shachor is an IBM Senior Technical Staff Member and researcher working at the IBM Haifa Research Lab, on various topics related to middleware and rich Internet applications. Gal is the author of the book JSP Tag Libraries and several technical articles.
Ksenya Kveler holds a B.Sc. in Computer Science from the Technion - Israel Institute of Technology. For the last five years, she has been working as a software engineer in the IBM Haifa Research Lab, mostly in the fields of distributed systems, simplified application development tools and, currently, medical informatics. Her main interests are Java and Web technologies.
Maya Barnea holds a B.Sc. in Mathematics and Computer Science from the Haifa University. For the last five years, she has been working as a software engineer in the IBM Haifa Research Lab, mostly in the fields of visual application development tools and complex event processing. Her main interests are Java and Web technologies, event processing, simplified programming, and usability.
Comments (Undergoing maintenance)





