| By Sean McMullan | Article Rating: |
|
| April 18, 2002 12:00 AM EDT | Reads: |
29,103 |
If a user wants to change the order of the rows, another call to the server must be made to get the data from a database in a different order, and the HTML table with data must be sent to the browser again, which isn't very efficient. Another problem is that if there are many rows of data, the user must scroll the window, thus losing sight of the column headings.
If you're developing a spreadsheet application or an application in which the user is trying to find a specific row of data quickly, then the static table isn't very user-friendly. The addition of an XML parser to a Web browser, such as Microsoft's XML3 parser in Internet Explorer 6.0, allows developers to leverage the power of XSLT transformations in the browser to quickly re-sort and display rows of data without going back to the server. I'll show you how to make sortable tables using this technique, as well as a few other tricks to build full-featured data grids.
Browser-Side Transformations
The trick to browser-side transformations is to get both the
XML data and XSLT presentation logic into the browser where it can be
transformed via JavaScript. By using XML data islands, you can cache
both the data and the presentation on the client machine. Since XSLT
is well-formed XML, we can put the presentation logic on the client
by placing the stylesheet between <XML> tags. Once that's done, the
structure can be accessed as an XML DOM object in JavaScript by using
the XMLDocument property of the tag ID. Listing 1 shows an example
reference as:
document.all.tableXSL.XMLDocument
To do a transformation you need two XML data islands: one that contains the data, another that contains the XSLT that will create an HTML table from the data. You can then use JavaScript to access both XML DOM objects and do the transformation with the transformNode method.
newHTML = oXMLDOM
.transformNode(oXSLDOM)
The HTML that results from the transform can be placed on a page by using the innerHTML property of a DIV tag.
In Figure 1 there are actually two tables that make up the grid. The top one contains the column headings; the bottom one, the rows of data. The column headings are in a separate table so just the rows of data scroll and the column headings are always visible at the top of the grid - a nice feature if you have lots of rows and your columns aren't self-explanatory. The table with the data rows is placed within a
Creating Tables with XSLT
We want to sort the rows in the XML by some default field
when the table is first displayed.
The value of the select attribute is a valid XPath statement
that tells the parser how to sort the data. In this case we're
sorting on an attribute (as indicated by the "@" character) within
the current ROW element named "AcctNo". The valid values for the
order attribute are "ascending" or "descending." The datatype
attribute tells the parser to do either a number or text sort, which
can be tricky if you want to sort on something like date, but I'll
touch on this later.
Now create cells for each field you want to display in your
table and add
Sorting
After the changes are made to the sort tag, we can
retransform the XSLT stylesheet with the data in the XML data island
and insert the new HTML table into the scrollable <DIV>. This all
happens within the browser - there's no need to go to the server
every time the user changes the sort order. To change the attributes
on the sort tag, we'll use the API for the XML DOM to select the
<xsl:sort/> using XPath and then update the attributes. In Listing 3
notice that the onClick event on the table headers calls the sort
function in Listing 1, passing it the name of the attribute and
datatype to sort on. The sort function uses the selectSingleNode
method on the XML DOM object to get a reference to the select
attribute within the xsl:sort node.
The select attribute is then set to the new attribute from
the XML we want to sort on. Next we check the current sort order and
change it to the opposite order. Finally, we set the datatype
attribute.
Another attribute you can add to the xsl:sort that isn't
shown in the source is the "case-order" attribute, which can be set
to either "upper-first" or "lower-first". If you don't include this
attribute, the default will be the former - for example, "VanStueben"
would come before "vanStueben."
The XSLT engine can sort by text or number by setting the
datatype attribute. If all your columns have strings or numbers, you
won't run into any problems. One of the biggest shortfalls is that
you can't sort by date very easily, which is often a requirement of a
data grid. Like most problems, there are a couple of workarounds. The
first requires you to change the way you display dates. Most
applications designed for the U.S. market display their dates in
mm/dd/yyyy format - if you try to sort columns by text or number,
08/01/2001 will come before 08/31/2000. But if you change the date
format to most significant to least significant, that is, yyyy/mm/dd,
your date sorting will work fine as long as you display months and
days that are less than 10 as 01, 02, and so on.
Another trick is to have an attribute within your XML that
has the date in the yyyy/mm/dd format that isn't displayed in the
table. Sort on it, but display the data in the traditional
mm/dd/yyyy. So your XML might look like:
The column would show the birthday, but the onClick event in
the TH tag would look like:
Selecting Rows
Where to Go from Here
You could also add drag-and-drop features to the table
headers so users could change the order of the column headers,
similar to a spreadsheet. When the user drags one column and drops it
onto another, you could manipulate the order of the column nodes in
the XSLT and then retransform it with the XML. Remove the dragged
node from the XSLT by using the removeChild method, then insert it
before the dropped TR tag by using the insertBefore method. For
example, to move the AcctNo column before the LastName column execute:
Now do the transformation again and replace the old HTML
table with the new HTML table.
These are just a few ideas to take your HTML tables to the
next level. Because of the power of XSLT transformations and the
MSXML3 parser, you can really build full-featured data grids that
your users will enjoy.
The algorithm for creating HTML tables with XSLT is fairly
simple: for every row of data in the XML, create one row in the HTML
table. If you look at Listing 2, you'll see that the stylesheet
starts with the obligatory document element <xsl:stylesheet> tag. The
result of the transformation will be HTML, so you need the
<xsl:output> tag with the method attribute set to "html". Then add
the <TABLE> tag. Now use the
<xsl:for-each select="//ROW">
<xsl:sort select="@/AcctNo" order=
"ascending" datatype="number"/>
After the table is displayed, we want to enable the user to
click on a column heading and have the table re-sort on that column.
The sorting of the rows is handled by the <xsl:sort/> tag within the
XSLT. When a user clicks on a column heading, we want to (1) change
the value of the select attribute to the attribute in the XML (see
Listing 4) that matches this column, and (2) set the order attribute
to "ascending". If the user clicks on the column again, we need to
change the order attribute to "descending".
var objSelect = XSLIsland
.selectSingleNode
("//xsl:sort/@select")
<row birthday="08/15/1954" sortdate=
"1954/08/15"/>
sort('./@sortdate','number')
You might also want to allow your users to select a row
within the grid and have all the data from that row passed to another
Web page. Most grid controls in rich-client applications allow the
user to press the up and down arrows to highlight a row and then
press the enter key or double-click the mouse to select the row.
Listing 1 shows how the arrows are captured from the keyboard and how
we keep the current selected row highlighted with the keyCheck and
selectRow functions. In the sample code, for a selected row, we want
to return all the data to the server as an XML string for processing.
We'll do this by taking the value from the hidden key column and
using XPath to select the data row from the XML data island and
return it to the server. If you look at the XSLT in Listing 2, you'll
see that the first column of the table contains an ID that isn't
displayed to the user. When a user chooses a row, we'll get the ID by
grabbing the innerText of this table cell and passing it to the
selectSingleNode method on the data XML DOM object to get a reference
to the node the user selected. We can then send the XML string of
that node to the server by placing it into a FORM element and
submitting it to the server via the POST method. In the function
selectCurrentRow (see Listing 1) I just alert the XML string, so I'll
leave it to you to create the FORM.
There are some other features you might consider adding to
make the table more like a spreadsheet. You could add an indicator in
the column heading that shows which column the table is sorted by and
in what order. Modify the sort function so that it shows the proper
icon within the TH tag.
dragNode = XSLIsland.selectSingleNode
("//TD[@id='accountCol']")
dropNode = XSLIsland.selectSingleNode
("//TD[@id='lastnameCol']")
trNode = XSLIsland.selectSingleNode
("//TR[@id='trnode']")
trNode.insertBefore
(trNode.removeChild
(dragNode),dropNode)
Published April 18, 2002 Reads 29,103
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Sean McMullan
Sean McMullan is a Web application developer with ALLTEL Information
Services, Inc. He received his bachelor's degree in computer science
from Siena Col
![]() |
David Anderson 12/03/02 04:33:00 AM EST | |||
- Publishing Synergy: Blog, Twitter and Ulitzer
- Will PR Firms Survive The New Media Avalanche?
- Typhoon Ondoy (Ketsana) Hits the Philippines (Part 2)
- Confessions of a Ulitzer Addict
- Cloud Computing Expo 2010 East to Attract More Than 5,000 Delegates in New York City
- Cloud Computing Journal Continues To Publish World's Best Cloud Analysts
- CIA Falls for Cloud Computing in a Big Way
- Are You Comfortable With Where Your Data Sleeps at Night?
- Dr. Leslie Lenert of CDC Speaks on Healthcare IT
- Game-Changing Innovations and the Evolving SOA Appliance
- What Happened To SOA?
- Instant Professionalism Online Despite Yourself...with Ulitzer
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Publishing Synergy: Blog, Twitter and Ulitzer
- Will PR Firms Survive The New Media Avalanche?
- Typhoon Ondoy (Ketsana) Hits the Philippines (Part 2)
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Combining the Cloud with the Computing: Application Delivery Networks
- Cloud Computing Expo 2010 East to Attract More Than 5,000 Delegates in New York City
- Ulitzer vs. Ning
- Cloud Computing Journal Continues To Publish World's Best Cloud Analysts
- CIA Falls for Cloud Computing in a Big Way
- Are You Comfortable With Where Your Data Sleeps at Night?
- Where Are RIA Technologies Headed in 2008?
- AJAX World RIA Conference & Expo Kicks Off in New York City
- JSON vs XML - A Jason vs Freddie Sequel
- Processing XML with C# and .NET
- Has the Technology Bounceback Begun?
- BPEL Processes and Human Workflow
- The Top 250 Players in the Cloud Computing Ecosystem
- Open Source Database Special Feature: An Introduction to Berkeley DB XML
- "HP's Problem Ain't the SAP Install," Says Sun's Schwartz
- eXist - An Introduction To Open Source Native XML Database
- Digitizing the Planet: Google Earth vs MSN Virtual Earth vs MapQuest
- Generating XML from Relational Database Tables



































