Skip to main content

Ajax and XML: Five cool Ajax widgets

Use Ajax and XML with new graphic tools to enhance your site

Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Summary:  With the Web 2.0 wave came a whole new emphasis on the user experience. Part of that experience is the development novel ways to interact with and present information to users. Often, these new interfaces are called widgets and use Asynchronous JavaScript + XML (Ajax) to communicate with the server. Discover five widgets that you can use to enhance the interactivity of your site.

View more content in this series

Date:  16 Jan 2007
Level:  Intermediate
Activity:  9302 views

The Web 2.0 revolution emphasizes unique and novel ways to interact with customers on your Web site. A lot of these new, innovative techniques revolve around using graphics and widgets that communicate with the server to retrieve data for display. In this article, I introduce you to five such widgets -- some open source, some licensed – that communicate with the server through Ajax and XML:

  • carousel: This widget is a rolling image viewer that customers can use to scroll through a list of items, each portrayed by a small graphic. What you do when a user clicks an item is up to you. Examples of carousels in the wild include the Flikr site and the iTunes interface from Apple. This carousel is available at no cost and is based on the popular jQuery JavaScript framework.
  • SWF/Charts: This Adobe Flash-based control reads XML located on the server for its charting data and styling options, then displays a chart based on the data. The interface is elegant, and the XML data is so easy to create that it's a snap to add dynamic graphing to your page.
  • SWF/Gauge: A cousin to SWF/Charts, this Flash widget uses XML located on the server to build a completely customizable gauge display. The gauge can look like something from an airplane or a car or something more trendy. The choice is up to you.
  • In-place editing: While not strictly a widget, an in-place editing control is an intuitive, interactive, and lightweight way to get information from users when they have it. In-place editing functionality comes with the Scriptaculous framework, which sits on top of the prototype.js library.
  • DHTML windows: The DHTML window provides a mechanism for putting a modeless floating window on top of your page content. Users can move the window around, resize it, or dismiss it. The content of the window can either be specified by JavaScript code on the page or read through Ajax from the server. This type of window is ideal for use as an alert mechanism or for bringing up small forms that don't deserve an entire page reload.

I start the show off with the SWF/Charts widget, because I think it's one of the easiest widgets to deploy. It also provides the biggest return for the effort.

The SWF/Charts widget

It's hard to argue with the old saying, "A picture is worth a thousand words," particularly where graphs are concerned. But graphing on the Web has always been a problem. Most Web frameworks lack a graphing tool right out of the box, although some include the graphics primitives for building images. This lack of functionality leaves you stuck building graphs on your own.

Wouldn't it be great if there were a widget that would just graph XML-encoded data? Turns out, there is one: SWF/Charts. To start using this widget, I download the SWF file from the site along with the extra SWF files that the widget uses. Then, I installed the files on my site and added a link to the SWF widget on the HTML page, as shown in Listing 1.


Listing 1. Chart_page.html
	
<html><body>

<object
  classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  codebase="http://download.macromedia.com/pub.../swflash.cab#version=6,0,0,0" 
  width="400" height="250">
<param name="movie"
  value="charts.swf?xml_source=chart_data.xml&library_path=charts_library">

<embed
  src="charts.swf?xml_source=chart_data.xml&library_path=charts_library" 
  width="400" height="250" 
  type="application/x-shockwave-flash" 
  pluginspace="http://www.macromedia.com/go/getflashplayer">
</embed>
</object>

</body></html>

Charts.swf takes two parameters: the location of its libraries directory and the URL of the XML data. The XML data format is ridiculously easy. Listing 2 shows a simple example.


Listing 2. Chart_data.xml
	
<chart>
  <chart_type>bar</chart_type>
  <chart_data>
    <row>
      <null/>
      <string>2005</string>
      <string>2006</string>
    </row>
    <row>
      <string>Projected</string>
      <number>500</number>
      <number>700</number>
    </row>
    <row>
      <string>Actual</string>
      <number>600</number>
      <number>900</number>
    </row>
  </chart_data>
</chart>

This file is primarily the data for the chart, along with some optional visual information. In this case, I'm specifying the chart type as a bar chart. The site from which I downloaded the SWF file has a lot more on the options you can set and the types of graphs that are available.

When I browse to the file in my Firefox browser, I see the graph shown in Figure 1.


Figure 1. The Chart Widget in action
The Chart Widget in action

As you can see, the default color scheme and the look of the chart is really slick. And the graph does the right thing of rounding up the axis values nicely. The overall effect is great with little effort on my part.

Obviously, you could replace the graph_data.xml file with a dynamic Web page: As long as the returned data is in the correct format, the graph control cares less. This is the case with all the examples in this article. In fact, you can run all the examples in a Web browser on local files without using a Web server (such as Apache Tomcat or IBM® WebSphere® Application Server) or Web programming language (for example, PHP, Microsoft® ASP.NET, Java™ 2 Enterprise Edition [Java EE]).


The SWF/Gauge widget

Another attractive way to present data is as a gauge. Personally, I'm not much on the gauge idea, because it takes up a lot of space to present just a little information. But gauges are a key feature of executive dashboards, so the ability to create them quickly is convenient.

But if the Web doesn't do simple bar charts very well, it certainly doesn't do circular gauges well. So, I went back to the same company that created XML/Graph, and wouldn't you know it? They also have a solution for gauges: XML/Gauge.

I'll start with the HTML page that embeds the SWF/Gauge widget, as shown in Listing 3.


Listing 3. Gauge_page.html
	
<html><body>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  codebase="http://download.macromedia.com/.../swflash.cab#version=6,0,0,0"
  width="110" height="55">
<param name=movie VALUE="gauge.swf?xml_source=gauge_data.xml">
<embed src="gauge.swf?xml_source=gauge_data.xml"
  width="110" height="55" type="application/x-shockwave-flash"
  pluginspace="http://www.macromedia.com/go/getflashplayer">

</embed></object>

</body></html>	

That gauge.swf movie takes a single argument: the location of the data. In this case, the location is gauge_data.xml, which is shown in Listing 4.


Listing 4. Gauge_data.xml
	
<gauge>

<circle fill_color="888888" start="275" fill_alpha="100"
  line_color="555555" line_thickness="3" line_alpha="90"
  radius="50" x="55" end="445" y="55"/>
<circle fill_color="99bbff" start="280" fill_alpha="90"
  line_thickness="4" line_alpha="20" radius="45" x="55"
  end="440" y="55"/>
<circle fill_color="666666" start="317" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="322" y="55"/>
<circle fill_color="666666" start="337" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="342" y="55"/>
<circle fill_color="666666" start="357" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="362" y="55"/>
<circle fill_color="666666" start="377" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="382" y="55"/>
<circle fill_color="666666" start="397" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="402" y="55"/>
<circle fill_color="666666" start="417" fill_alpha="100"
  line_color="333333" line_alpha="0" radius="44" x="55"
  end="422" y="55"/>
<circle fill_color="99bbff" start="280" fill_alpha="100"
  radius="40" x="55" end="440" y="55"/>
<circle fill_color="FF4400" start="280" fill_alpha="100"
  radius="44" x="55" end="310" y="55"/>
<circle fill_color="44FF00" start="50" fill_alpha="100"
  radius="44" x="55" end="80" y="55"/>
<circle fill_color="99bbff" start="280" fill_alpha="80"
  radius="40" x="55" end="440" y="55"/>
<circle fill_color="333333" start="270" fill_alpha="100"
  line_alpha="0" radius="20" x="55" end="450" y="55"/>

<rotate start="280" shake_span="2" shadow_alpha="15"
  step="1" x="55" span="0" y="55" shake_frequency="20">
  <rect fill_color="ffff00" fill_alpha="90" line_alpha="0"
    height="40" x="53" width="4" y="13"/>
</rotate>

<circle fill_color="111111" start="270" fill_alpha="100"
  line_thickness="5" line_alpha="50" radius="15" x="55"
  end="450" y="55"/>

</gauge>

As you can see, SWF took a different approach with this widget. Instead of specifying the data for the gauge (or graph), I actually build the gauge out of graphics primitives such as circles, arcs, and rectangles.

Honestly, I prefer a set of canned gauges with which I can just supply the data. But this method works, and it allows me almost infinite room for tweaking -- although I would have appreciated a few more canned examples that I could work from.

When I go to the page in my browser, I see the gauge shown in Figure 2.


Figure 2. The Gauge Widget in Action
The Gauge Widget in Action

You might think that with the specification of the graphics primitives, there isn't a lot to be gained on this widget. Not so. The primitives also include simple animation techniques so that you can bounce the needle around as well as sound and the ability to create hot-linking zones that navigate the browser when the user clicks them. In addition, you can think out of the box with this control, not just using it for gauges but using its simple graphics primitive language to build any type of image and simple animation.


In-place editing

Users now expect in-place editing from desktop applications, but this functionality is something rarely found on the Web, until now. With Web 2.0, interactivity becomes paramount, so techniques such as in-place editing are also more commonplace.

To implement in-place editing, you can either write it yourself or use one of the JavaScript frameworks to do the heavy lifting for you. One of the most popular toolkits is the Scriptaculous framework, which is built on top of the prototype.js library. The Scriptaculous library makes building an in-place edited control quite easy.

A simple HTML test file for in-place editing is shown in Listing 5.


Listing 5. Inplace.html
	
<html><head>
<script src="prototype.js"></script>
<script src="effects.js"></script>
<script src="controls.js"></script>
<script src="scriptaculous.js"></script>
</head><body>
<table width="100%">
<tr><th width="10%">Name</th>
<td width="90%"><p id="name">Candy bar</p></td>
</tr></table>
<script>
new Ajax.InPlaceEditor('name', 'submitted.html' );
</script>
</body>
</html>

To start, Inplace.html includes all the necessary JavaScript source files. Then, I put together a simple table with a paragraph containing the in-place editable data. At the end of the file, I insert a small bit of script that creates an InPlaceEditor object for the paragraph.

That InPlaceEditor constructor takes as arguments the ID of the paragraph as well as the URL of the page that will handle the submission after I'm done editing. In this case, that page is submitted.html; but in reality, it would be an ASP.NET, Java EE, or PHP page or some other dynamic Web technology.

Listing 6 shows the simple submitted.html file.


Listing 6. Submitted.html
	
<p>Name changed!</p>

Now to test it. I first open my browser to the HTML file. There, I see the original text. As I mouse over the text, it turns yellow, as shown in Figure 3.


Figure 3. The starting point of in-place editing
The starting point of in-place editing

This yellow highlighting is a visual indicator to users that they can edit the field by clicking it. So, I click the field and get the Name field, an ok button, and a cancel link, as shown in Figure 4.


Figure 4. Editing the text after clicking it
Editing the text after clicking it

I then change the text and click ok, which posts the data to the server (or the submitted.html page, in this case). The server then returns the HTML page that should replace the original text. In this case, I send back Name changed! (as shown in Figure 5); in reality, it would probably be the new value of the data.


Figure 5. The new content after clicking ok
The new content after clicking ok

Simple interface upgrades like these can make a world of difference in the usability of your application. Waiting for page loads -- especially from slow servers -- gives the impression of a clunky, old-style interface. Using simple tools such as this in-place editor can really spruce up your application with very little in terms of implementation complexity.


DHTML windows

It's probably a good thing that browsers make it difficult to build modal windows into Web pages. But sometimes, small windows can be a good thing. They are handy to display alerts or to bring up small forms. They're also a great way to launch annoying ads that cover the content of the page. Oh, wait: Scrap that last one.

Anyway, as I said, it's not easy to build windows for Dynamic HTML (DHTML) pages. So I was happy when I found this extremely robust window package based on the popular Protoype.js library. Not only was it easy to use, but the interface was skinnable and works well on every browser. Listing 7 shows the window.html page.


Listing 7. Window.html
	
<html>
<head>
<link href="default.css" rel="stylesheet" type="text/css" />
<script src="prototype.js"></script>
<script src="window.js"></script>
</head>
<body>
<script>
var win = new Window( 'myPopup', {
   title: "Terms and Conditions",
   top:70, left:100, width:300, height:200,
   resizable: true, url: "terms.html",
   showEffectOptions: { duration: 3 }
  } 
);
win.show();
</script>
</body>
</html>

I first bring the prototype.js and window.js source files into the header. Then, I build the pop object with the parameters I like, including the size, the location, the title, and the URL of the page from which the widget should get its content. Loading the content from a page through Ajax is just one way of getting the contents, though; you can also set them dynamically through JavaScript code or wrap the window around an existing <div> tag on the page.

In this case, I reference the terms.html file shown in Listing 8.


Listing 8. Terms.html
	
<html><body bgcolor="white">
<h1>Terms and Conditions</h1>
<p>In order to use this site you must comply
with the following conditions...</p>
</body></html>

When I launch the page in my browser, I see the window shown in Figure 6.


Figure 6. The initial window
The initial window

No, that’s not just two Mac windows on top of each other. That's a Mac-looking fake DHTML window inside a real Firefox browser window. But it looks and feels the same anyway.

I can stretch and move the window around, as shown in Figure 7.


Figure 7. The window after moving and resizing it
The window after moving and resizing it

I looked at several DHTML window libraries, both for this article and for my own work, and I can tell you with some confidence that this one has the best feel to me. Other window packages had rendering problems, rendered in segments, or behaved badly when I resized them. This one feels very much like a real window that's just trapped inside the browser.


The carousel widget

Anyone who has done a significant amount of user interface (UI) work can tell you that screen real estate is critical. It's important to squeeze as much data as you can into a given space without it feeling compressed. So, I was pretty impressed when I first saw a carousel control in Apple iTunes.

A carousel control shows several images in a fixed block of space. To the left and right of the block of images are left and right arrows. If you click the arrows, the images shift to the left or right and are replaced with a new set of images. In iTunes, the images were album covers, and there was a carousel control for each genre.

The space savings are significant: You can put 30 album covers in the space of three and still show each at a reasonable size. And the control is intuitive. It's like a simplified scrollbar.

The downside is that carousels aren't easy to implement, especially because part of the allure is the animation of the images moving to the left or the right. So I was happy to see an open source carousel called carousel built on the jQuery JavaScript framework.

I implemented a simple carousel widget on the Web page shown in Listing 9.


Listing 9. Carousel.html
	
<html>
<head>
<script type="text/javascript" src="js/jquery-1.0.3.js"></script>
<script type="text/javascript" src="js/jcarousel.js"></script>
<style type="text/css">
#mycarousel { display: none; }
.jcarousel-scope {  position: relative; width: 255px;
  -moz-border-radius: 10px; background: #D4D0C8;
  border: 1px solid #808080; padding: 20px 45px; }
.jcarousel-list li { width: 81px; height: 81px;
  margin-right: 7px; }
.jcarousel-list li img { border: 1px solid #808080; }
.jcarousel-list li a { display:block;  outline: none;
  border: 2px solid #D4D0C8; -moz-outline:none; }
.jcarousel-list li a:hover { border: 2px solid #808080; }
.jcarousel-next {  position: absolute; top: 45px;
  right: 5px; cursor: pointer; }
.jcarousel-next-disabled { cursor: default; }
.jcarousel-prev { position: absolute; top: 45px;
  left: 5px; cursor: pointer; }
.jcarousel-prev-disabled { cursor: default; }
.loading { position: absolute; top: 0px;
  right: 0px; display: none; }
</style>
<script type="text/javascript">
function loadItemHandler( carousel, start, last, available ) {
  if (available) { carousel.loaded(); return; }
  var cr = carousel;
  jQuery.get("data.xml", function(data) { appendItemCallback(cr, start, last, data); });
};

function appendItemCallback( carousel, start, last, data ) {
  var items = data.match( /(\<img .*?\>)/g );

  for (i = start; i <= last; i++) {
    if ( items[ i - 1 ] == undefined ) break;
    var item = carousel.add( i, getItemHTML( items[i-1]) );
    item.each(function() {
      jQuery("a.thickbox", this).click(function() {
        var t = this.title || this.name || null;
        var g = this.rel || false;
        TB_show(t,this.href,g);
        this.blur();
        return false;
      });
    });
  }
  carousel.loaded();
};

function getItemHTML( item ) {
  var found = item.match( /href=\"(.*?)\"/ );
  var url   = jQuery.trim(found[1]);
  var title = jQuery.trim(found[1]);
  var url_m = url.replace(/_s.jpg/g, '_m.jpg');
  return '<a href="' + url_m +
	'" title="' + title +
	'" class="thickbox"><img src="' + url +
	'" width="' + 75 + '" height="' + 75 +
	'" alt="' + title + '" /></a>';
};

var nextOver = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/next-over.gif"); };

var nextOut = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/next.gif"); };

var nextDown = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/next-down.gif"); };

function nextButtonStateHandler(carousel, button, enabling) {
  if (enabling) {
    jQuery(button).attr("src", "img/horizontal-ie7/next.gif")
      .mouseover(nextOver).mouseout(nextOut).mousedown(nextDown);
  } else {
    jQuery(button).attr("src", "img/horizontal-ie7/next-disabled.gif")
      .unmouseover(nextOver).unmouseout(nextOut).unmousedown(nextDown);
  }
}

var prevOver = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/prev-over.gif"); };

var prevOut = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/prev.gif"); };

var prevDown = function() {
  jQuery(this).attr("src", "img/horizontal-ie7/prev-down.gif"); };

function prevButtonStateHandler(carousel, button, enabling) {
  if (enabling) {
    jQuery(button).attr("src", "img/horizontal-ie7/prev.gif")
      .mouseover(prevOver).mouseout(prevOut).mousedown(prevDown);
  } else {
    jQuery(button).attr("src", "img/horizontal-ie7/prev-disabled.gif")
      .unmouseover(prevOver).unmouseout(prevOut).unmousedown(prevDown);
  }
}

jQuery(document).ready(function() {
  jQuery().ajaxStart(function() { jQuery(".loading").show(); });
  jQuery().ajaxStop(function() { jQuery(".loading").hide(); });
  jQuery("#mycarousel").jcarousel({
    itemVisible: 3, itemScroll: 2, wrap: true,
    loadItemHandler: loadItemHandler,
    nextButtonStateHandler: nextButtonStateHandler,
    prevButtonStateHandler: prevButtonStateHandler
  });
});
</script></head><body><div id="mycarousel">
<div class="loading">
<img src="img/loading.gif" width="16" height="16" border="0" />Loading...</div>
<img src="img/horizontal-ie7/prev.gif" border="0" class="jcarousel-prev" />
<img src="img/horizontal-ie7/next.gif" border="0" class="jcarousel-next" />
<ul></ul>
</div></body></html>

Yes, there is a lot more to it than in the previous examples. But most of the code is setting up the graphics and interpreting the Ajax data returned from the server. In fact, most of the code for this article is based on one of the examples provided with the download. So, I didn't have to learn much or read any documentation to use the control.

The data for the carousel is shown in Listing 10.


Listing 10. Data.xml
	
<images>
<img href="pics/image1.jpg" />
<img href="pics/image2.jpg" />
<img href="pics/image3.jpg" />
<img href="pics/image4.jpg" />
</images>

In this case, the file is just in a simple XML format that has an <images> tag with a set of <img> tags in it that hold the URL for each image. You can use whatever format you like, because the control is not natively an Ajax widget. I'm writing the code that interprets the XML and creates each slide element in the carousel. The end result is shown in Figure 8.


Figure 8. The image carousel on the page
The image carousel on the page

I can click the image and go to the page with the image (or to any URL I specify). Or, I can click the right or left arrow to scroll around the carousel to see more images. The effect is really quite impressive.


Conclusion

I showed you just a handful of the widgets and tools available on the Web both commercially and at no cost. Many of the tools I looked at while I researched this article didn't use Ajax and as such didn't fit into the topic. However, they were noteworthy on their own. In particular, I was impressed by the number of high-quality, open source WYSIWYG editors available for download. I often have customers frustrated when they have to use HTML in text boxes to get content onto their sites with bold, italics, links, images, and so on. These editors hide all the HTML and give users an editing feel that's similar to a word processing application.

In addition to the WYSIWYG editors, you can find solutions for progress bars, tabbed dialog boxes, accordion controls, clocks, date pickers, RSS and Outline Processor Markup Language (OPML) readers -- even interactive terminal windows. Certainly, before you build your own DHTML or Flash controls, you should look at what's available (often at no cost) on the Internet. With widgets such as these, you can add a lot of interactivity to your site without a lot of effort.


Resources

Learn

Get products and technologies

Discuss

About the author

Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source, Web development
ArticleID=187703
ArticleTitle=Ajax and XML: Five cool Ajax widgets
publish-date=01162007
author1-email=jherr@pobox.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers