Developer

Build cross-browser XML paging code

If scrolling through a long XML table is not an optimal experience for your browser app, why not implement pagination? Presenting data in page-length chunks can help your users find the data they need. See how to build fast, cross-browser XML pagination.


My manager doesn't like scrolling through page after page of tabular information when using a browser-based application. And the delay he experiences while waiting for the next page to load provides him the opportunity to exercise his vast knowledge of the more interesting parts of the English language. He does have a point—it's easy to miss one row when presented with several hundred rows on a page.

In essence, what he wants is fast multipage tabular data. The more I thought about the problem, the more I kept coming back to the concept of using XML data islands. Although this solution works with both Mozilla and Internet Explorer, it doesn't permit paging. Once an XML data island is bound to a table, all of the rows are rendered. Having a bound XML data island with a subset of information and unloading/reloading each page would kill anything that remotely resembles speed. The solution I came up with lay somewhere between the two ideas: two XML data islands. The first would contain the full tabular information and the second bound data island would contain a specific window to the first.

Getting started
Step one was to create two XML data islands, as shown in Listing A. (You can download the listing from TechRepublic.) The first data island, xmlFull, contains the complete XML that can be displayed in the page. The second data island, xmlWindow, is bound to a table. Because of the binding, each datafld represented in xmlWindow will be rendered.

The method you use to create the actual XML data islands depends quite a bit on the origin of the information. For example, if it's an ADO Recordset, you can use the save method to store the XML. You can then use XSLT on the "saved" recordset to transform the XML into something a little easier to bind to HTML. Another method, although not nearly as elegant, is to use the XML DOM interface to build the XML node by node.

Because flexibility makes code reuse easier, I decided to code the paging JavaScript function as an object constructor. The reasoning behind this decision is that in addition to promoting code reuse, it will make the invoking of the various methods clearer. The constructor's properties and methods are outlined in Table A and Table B.
 
Table A
Property Description
bound The bound "window" XML Data Island.
full The unbound "full" XML Data Island.
table The bound HTML table.
Object constructor properties
 
Table B
Method Description
length Retrieve or modify the number of rows to be displayed in the bound table.
page Returns the current logical page number.
pagecount Returns the total number of logical pages based upon the length and the record count.
recordcount The number of records (rows) in the "full" XML Data Island.
showPage Redisplays the current logical page based upon the absolute position in the "full" XML Data Island.
showFirst Sets the absolute position to zero and invokes the showPage method.
showLast Sets the absolute position to the first row of the last logical page and invokes the showPage method.
showNext Sets the absolute position to the first row of the next page (if applicable) and invokes the showPage method.
showPrevious Sets the absolute position to the first row of the previous page (if applicable) and invokes the showPage method.
Object constructor methods

Internally, the object constructor contains very little browser-specific coding. With Mozilla, because XML data island support is accomplished through the use of JavaScript, a data island is only an unknown type of HTML node. Therefore, cloning XML nodes from the "full" data island to the "bound" data island is really only cloning HTML, which is a relatively easy task, as this single line of code shows:
objRoot.appendChild(this.full.getElementsByTagName(objCommonAncestor).item(i).cloneNode(true));

Microsoft Internet Explorer, on the other hand, supports XML data islands directly, so you'd think that the code would be just as easy as the Mozilla code; unfortunately, this wasn't the case. Because Internet Explorer recognizes XML and HTML as two entirely different and unique document types, it gets really cranky when treating one as the other. The solution to this is to use ActiveX to build an XML document just to create the right type of node to append to the bound XML data island. Here's the equivalent to Mozilla's one line of code:
if(i == intAbsolutePosition) {
 objXML = new ActiveXObject('MSXML.DOMDocument');
 objRoot = objXML.createElement('root');
}
objRoot.appendChild(this.full.XMLDocument.getElementsByTagName(objCommonAncestor).item(i).cloneNode(true));

Now, all that's left is to create an instance of the object as shown below and then bring up the page and press the buttons:
objPage = new xmlPage();                    //  Create instance
 
                                            // Establish relationships
objPage.bound = document.getElementById('xmlWindow');
objPage.full = document.getElementById('xmlFull');
objPage.table = document.getElementById('boundTable');
 
objPage.length(10);                         //  Set page length
objPage.showPage();                         //  Show first page

Figure A shows what the page looks like in Mozilla, while Figure B shows the same page in Microsoft Internet Explorer. Easy as that.

Figure A
XML paging in Mozilla


Figure B
XML paging in Internet Explorer

Editor's Picks