Ajax and XML: Ajax for tables

摘自: IBM developerWorks Worldwide  被阅读次数: 50


yangyi 于 2008-03-24 21:56:02 提供


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="http://www.ibm.com/developerworks/xml/library/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
                
Tab 1

When I navigate to the file in my browser, I see something like Figure 1.


Figure 1. The starting tab page
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
After clicking the second tab
Live demo of tabbed windows

To see the tabbed window example in a live environment, Open link to view live demo of tabbed windows in new window view this online demo.

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).



Back to top


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="http://www.ibm.com/developerworks/xml/library/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>

Live demo of basic tables with Ajax

To see the basic tables example in a live environment, Open link to view live demo of basic tables in new window view this online demo.

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
The XML-driven table page

This example is fine for small result sets, but what about for something larger?



Back to top


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="http://www.ibm.com/developerworks/xml/library/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
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
The second page
Live demo of paged tables with Ajax

To see the paged tables example in a live environment, Open link to view live demo of paged tables in new window view this online demo.

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.



Back to top


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="http://www.ibm.com/developerworks/xml/library/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.

Live demo of hidden paged tables

To see the hidden paged tables example in a live environment, Open link to view live demo of hidden paged tables in new window view this online demo.

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
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.



Back to top


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="http://www.ibm.com/developerworks/xml/library/javascripts/prototype.js"></script>
<script src="http://www.ibm.com/developerworks/xml/library/javascripts/effects.js"></script>
<script src="http://www.ibm.com/developerworks/xml/library/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>

Live demo of glider effect

To see a glider example in a live environment, Open link to view live demo of glider in new window view this online demo.

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
The tabs example done with a glider

When I click another tab, the content literally glides to it.



Back to top


Conclusion

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!

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

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.




Original link: http://www.ibm.com/developerwork...