 | Level: Intermediate Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
11 Mar 2008 One strong suit of Asynchronous JavaScript™ + XML (Ajax) is presenting data from the server to users in a dynamic fashion. Discover several techniques that use Ajax for dynamic data display using tables, tabs, and gliders.
When people think of Ajax and Web 2.0, they mostly remember the
visual elements of the user experience. It's the feel of working in-place, without
the page refresh, that gives Ajax its distinctive appeal. It's not completely hype:
The page refresh of traditional HTML applications does cause a blink and a reload
that even on the fastest connections presents a visual context change.
 |
Frequently used acronyms
- DHTML: Dynamic HTML
- HTML: Hypertext Markup Language
- XSLT: Extensible Stylesheet Language Transformation
|
|
In this article, I show several techniques—both with Ajax and without—that
demonstrate this context change-free approach to user experience design. I start with
the simplest example of Ajax user experience, the tabbed window.
Tabbed windows
Tabs present the easiest way to put a lot of data in a relatively small amount of
real estate. And the fantastic Prototype.js JavaScript library makes building
Ajax-enabled tabbed windows in Dynamic HTML (DHTML) ridiculously easy, as shown in
Listing 1. To learn more about the Prototype library and download
a copy of it for your use, see Resources.
Listing 1. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<a href="javascript:void loadTab( 'tab1.html' )">Tab 1</a> |
<a href="javascript:void loadTab( 'tab2.html' )">Tab 2</a> |
<a href="javascript:void loadTab( 'tab3.html' )">Tab 3</a>
<div id="content" style="padding:5px;border:2px solid black;">
</div>
<script>
function loadTab( tab ) {
new Ajax.Updater( 'content', tab, { method: 'get' } );
}
loadTab( 'tab1.html' );
</script>
</body>
</html>
|
At the top of the file, I include the Prototype.js library, which handles all the
Ajax work. Then, you see a list of links to the various pages, each of which calls
loadTab to update the content area of the page. The
content area is a <div> with the ID
content. The loadTab function
calls the Ajax.Updater to update the content
<div> with the specified HTML file.
Listing 2 shows the first tab HTML file. All the other
files are similar to this one.
Listing 2. tab1.html
When I navigate to the file in my browser, I see something like
Figure 1.
Figure 1. The starting tab page
Then, when I click the second tab, I see the content shown in
Figure 2.
Figure 2. After clicking the second tab
You can achieve this functionality by using hidden <div>
tags with the content, then switching out their visibility. The advantage of the
Ajax approach is that the content is created and loaded only when necessary. So,
the compute time to build the content is reduced or eliminated if users choose
not to see the content.
The next three examples are all ways to deal with tables using Ajax techniques (or
something that looks like Ajax).
Basic tables with Ajax
My first demonstration of building tables with Ajax is through the use of an XML
request to the server over Ajax. The value of this technique is two-fold. First,
it loads the data on demand and can be updated in place, which makes for a pleasant
user experience. Second, the technique requires an XML data source, which is
valuable not just for the Ajax code but for any client looking to consume your
data through XML.
Listing 3 shows the XML-driven table example code.
Listing 3. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<table id="books">
</table>
<script>
new Ajax.Request( 'books.xml', {
method: 'get',
onSuccess: function( transport ) {
var bookTags = transport.responseXML.getElementsByTagName( 'book' );
for( var b = 0; b < bookTags.length; b++ ) {
var author = bookTags[b].getElementsByTagName('author')[0].firstChild.nodeValue;
var title = bookTags[b].getElementsByTagName('title')[0].firstChild.nodeValue;
var publisher =
bookTags[b].getElementsByTagName('publisher')[0].firstChild.nodeValue;
var elTR = $('books').insertRow( -1 );
var elTD1 = elTR.insertCell( -1 );
elTD1.innerHTML = author;
var elTD2 = elTR.insertCell( -1 );
elTD2.innerHTML = title;
var elTD3 = elTR.insertCell( -1 );
elTD3.innerHTML = publisher;
}
}
} );
</script>
</body>
</html>
|
 | |
The onSuccess handler of the
Ajax.Request call breaks up the XML data by first
getting each book element. Then, it gets the author,
title, and publisher values
from the nested tags. Finally, it adds the data to the table using
insertRow and insertCell for
each book.
Listing 4 shows the XML code for this example.
Listing 4. books.xml
<books>
<book>
<author>Jack Herrington</author>
<title>Code Generation In Action</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
|
Figure 3 shows the resulting DHTML file.
Figure 3. The XML-driven table page
This example is fine for small result sets, but what about for something larger?
Paged tables with Ajax
To create paged tables with Ajax, I show a slightly different technique. Not because
I necessarily need to—I can easily extend the XML technique shown
above—but I want the examples in this article to show a variety of
techniques from which you can pick and choose to suit the needs of your application.
In this case, I use a PHP data source that provides blocks of HTML code for the
various pages of a paged table. The HTML code starts in
Listing 5.
Listing 5. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<div>
<a href="javascript:void updateTable(0);">1</a> |
<a href="javascript:void updateTable(1);">2</a> |
<a href="javascript:void updateTable(2);">3</a> |
<a href="javascript:void updateTable(3);">4</a> |
<a href="javascript:void updateTable(4);">5</a> |
<a href="javascript:void updateTable(5);">6</a>
</div>
<div id="states">
</div>
<script>
function updateTable( start ) {
new Ajax.Updater( 'states', 'stats.php?start='+(start*10)+'&count=10',
{ method: 'get' } );
}
updateTable( 0 );
</script>
</body>
</html>
|
The majority of the page is in the links to the various pages of the table. Then,
the states <div> tag receives the content of the
table from the stats.php page.
To run a multi-paged example, I need a larger data set, so I found some United
States population statistics and created a PHP function called
getdata, which returns an array of states and their
populations over the years. Listing 6 shows an excerpt of the function.
Listing 6. data.php
<?php
function getdata()
{
$population = array();
$population []=
array( 'Alabama',4447100,4527166,4596330,4663111,4728915,4800092,4874243 );
$population []= array( 'Alaska',626932,661110,694109,732544,774421,820881,867674 );
...
$population []= array( 'Wyoming',493782,507268,519886,528005,530948,529031,522979 );
return $population;
}
?>
|
Now, to get various portions of the data, I create a stats.php page that, given a
start and end index, returns an HTML table with just that portion of the data.
Listing 7 shows this file.
Listing 7. stats.php
<table>
<?php
require 'data.php';
$data = getdata();
$start = 0;
$count = count( $data );
if ( array_key_exists( 'start', $_GET ) ) $start = $_GET['start'];
if ( array_key_exists( 'count', $_GET ) ) $count = $_GET['count'];
$index = 0;
foreach( $data as $state ) {
if ( $index >= $start && $index < $start + $count ) {
?>
<tr>
<?php
foreach( $state as $item ) {
?>
<td><?php echo($item); ?></td>
<?php
}
?>
</tr>
<?php
}
$index += 1;
}
?>
</table>
|
When I bring up the page in my browser, as in Figure 4, it
loads the first page automatically.
Figure 4. The paged table display
As I click the various sections of the table, the table from stats.php loads
dynamically. Figure 5 shows what happens when I click the
second page of the data.
Figure 5. The second page of the paged
table display
This technique is similar to the one I used with the tabs. Passing HTML over Ajax is
often as effective as XML. And it's a bit easier on the browser, because the XML
doesn't need to be parsed and converted back into HTML again.
The third table-building technique I show is the easiest non-Ajax way to build a
table dynamically.
Hidden paged tables
The page in Listing 8 shows a simple technique to create
paged tables without Ajax for the back end.
Listing 8. index.php
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<div>
<?php
require( 'data.php' );
$data = getdata();
$states = count( $data ) / 10;
for( $s = 0; $s < $states; $s++ ) {
?>
<?php echo( ( ( $s == 0 ) ? '' : '| ' ) ); ?>
<a href="javascript:void updateTable(<?php echo( $s ) ?>);">
<?php echo( $s + 1 ) ?>
</a>
<?php
}
?>
</div>
<?php
$index = 0;
foreach( $data as $state ) {
?>
<?php
if ( $index % 10 == 0 ) {
?>
<?php if ( $index > 0 ) { ?></table></div><?php } ?>
<div id="states<?php echo( $index / 10 ) ?>" style="display:none;">
<table>
<?php
}
?>
<tr>
<?php
foreach( $state as $item ) {
?>
<td><?php echo($item); ?></td>
<?php
}
?>
</tr>
<?php
$index += 1;
}
?>
</table>
</div>
<script>
function updateTable( id )
{
var elStateDivs = [];
<?php
for( $s = 0; $s < $states; $s++ ) {
?>
elStateDivs.push( $( 'states<?php echo( $s ) ?>' ) );
<?php
}
?>
for( var i = 0; i < elStateDivs.length; i++ ) {
if ( i == id ) elStateDivs[i].show();
else elStateDivs[i].hide();
}
}
updateTable( 0 );
</script>
</body>
</html>
|
In this case, I use the PHP code to create a series of <div>
tags—one for each page in the table. The first one is shown by default,
while the rest are hidden. The updateTable function
shows or hides the various portions of the table depending on which page is
selected.
Notice that I still include the Prototype.js library—not because of the
Ajax support. I want to make it easier to get a hold on each
<div> element using the $()
method and the show and hide
methods, all of which the library implements.
Figure 6 shows the page.
Figure 6. The mock paged table display
My last Ajax example shows a glider control. A glider is a new form of
display that provides a dynamic left/right motion as the pages of the display
change.
Gliders
To enable the glider effect, I need a few more libraries. The first library is the
Scriptaculous library, which is built on Prototype.js. It provides the effects that
the glider uses. The second library is the Glider library.
Listing 9 shows an example of the glider.
Listing 9. index.html
<html><head>
<link rel="stylesheet" href="stylesheets/glider.css" type="text/css">
<script src="javascripts/prototype.js"></script>
<script src="javascripts/effects.js"></script>
<script src="javascripts/glider.js"></script>
</head><body>
<div id="glider"><div class="controls">
<a href="#tab1">Tab 1</a> |
<a href="#tab2">Tab 2</a> |
<a href="#tab3">Tab 3</a> |
<a href="#tab4">Tab 4</a></div>
<div class="scroller"><div class="content">
<div class="section" id="tab1">Tab 1</div>
<div class="section" id="tab2">Tab 2</div>
<div class="section" id="tab3">Tab 3</div>
<div class="section" id="tab4">Tab 4</div>
</div></div></div>
<script>
new Glider( 'glider', { duration:0.5 } );
</script>
</body></html>
|
 | |
At the top of the file are the inclusions of the various script libraries. Then,
there is the glider <div>, which contains first a
<div> called controls that has anchor tags
to get to each tab, then another <div> called
scroller that contains the content for each tab. The script at the bottom
creates a Glider object with the ID of the glider <div>
element.
When I open the page in my browser, I see something like Figure 7.
Figure 7. The tabs example done with
a glider
When I click another tab, the content literally glides to it.
Conclusion
I've shown just a few of the different types of interface elements that you can
build with Ajax, PHP, and the Prototype.js library. Hopefully, you can take some
of these ideas and use them in your own Web application. They are certainly easy
enough, and the Prototype.js library really makes Ajax a snap. If you have a
success story you'd like to share, please join the
developerWorks
Ajax forum: We would be happy to hear from you.
Resources Learn
Get products and technologies
-
IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
Discuss
About the author
Rate this page
|  |