Enhancing the Dynamic Tree Menu System, Part 3By Sam M. Reynoso
In Part 2 we looked at how to support loading the tree content data from a database table. In this part we'll look at how to conditionally load data (that is, only load data when the user clicks the menu item) and how to implement folder memory in a way that each folder can remember its previous state.
Conditional Data Loading
On a similar note, many developers reported that they were dealing with navigation trees containing hundreds of items and requested a way to load folder data a bit at a time. Since our navigation tree was put together using data loaded from a database instead of a static XML file, we have more control over how the folders get populated.
In the sample code, Conditional Data Loading has been applied to the last folder in the tree ("History"). To demonstrate that no data is initially being loaded for this item, take a look at the HTML source immediately after loading the page. This will reveal that there are no items underneath the history folder. However, clicking the plus sign on the history folder fires off a chain of events that cause it to load its contents.
menu.asp page to be submitted when that folder is opened:
After the page is submitted, the ASP code queries the database for the tree data like before, but this time it also loads data corresponding to the clicked folder. The newly populated XML document object now includes the data for the clicked folder's items, and the new HTML page reflects this.
Let's take a closer look at what happens when a user clicks a folder configured
for Conditional Data Loading. First, loading additional data requires a trip
to the server in order to retrieve the data. To make a submit possible, it is
necessary to encapsulate the entire tree between a set of HTML
A submit will occur any time a user opens a folder that is configured for Conditional
doChangeTree() makes this determination by
checking the name of the clicked folder's
<img> tag. If the name is
then the navigation tree is submitted.
On the server side, the ASP code determines if Conditional Data Loading
is required by checking if the form was submitted or not. If it was,
the XML loader function
fnLoadXMLData() rebuilds the XML document object
to include the data for the history folder.
The second parameter of
fnLoadXMLData() is a boolean that indicates whether or not
the history folder data should be loaded. This value is
a form has been submitted.
For the sake of simplicity, this example applies Conditional Data Loading only to a
single folder. However, it would be easy to modify the code to apply
similar functionality to other folders in the tree.
The final enhancement, Folder Memory, goes hand-in-hand with Conditional Data Loading discussed above. It would make no sense to have a feature like Conditional Data Loading if all the folders in the tree defaulted back to their original closed state each time the tree was rebuilt. The Folder Memory feature gives the navigation tree the ability to "remember" the open/closed state of each of its folders. Note that this memory only works when the menu is submitted, not when it is reloaded.
To "remember" the state of its folders, the tree must record each time a folder is
open or closed. If the folder is opened,
fnAddItem() is called to
append the ID of the clicked folder to a comma-delimited list stored in a
hidden HTML input control (
hdnOpenFolders). If the folder
fnRemoveItem() takes care of removing the appropriate ID
from the same hidden control. These functions are shown below:
hdnOpenFolders contains the IDs of folders that are open.
As long as this list is properly maintained, we can feel confident that it
accurately reflects the current state of the folders in our navigation menu.
The IDs in
hdnOpenFolders are used by the ASP routine
DisplayNode() as it builds the HTML for the menu.
After the XML document object is loaded with data, the ASP subroutine
DisplayNode() is called recursively to build the navigation menu.
Each time it examines a new node of XML data, it compares the list of open folder
IDs to the ID it is going to assign to the current node. If they match, the folder
is displayed as open, otherwise it is displayed closed. The ASP function
fnGetFolderStatus() performs this simple check using the following lines of code:
The result of this evaluation is then sent as a parameter to the the
function which returns the name of the appropriate
.gif to use for the folder.
This feature is the best example of how we can use HTML
<form> tags, hidden
submit() method to pass
feature would not be possible without this level of interaction.
There is one last modification that needs mentioning. In the original sample code, the dynamic HTML generated for the navigation tree was formatted using tabs and spaces to be easily readable. This works fine for small menus but presented problems when menus contained hundreds of items. The problem was that larger menus required more HTML code which in turn had to be transmitted downstream to the browser, resulting in slower download times.
To get around this problem, the current version of the sample code has been redesigned
to contain a minimum of characters. The rendered HTML page is now smaller in bytes,
but more difficult to read. Examining the source code will reveal a block of code sandwiched
between open and close
<form> tags. This is because all carriage returns,
blank lines, unnecessary spaces, tabs, quotes, etc. were removed. The visitor will appreciate the
quick download, but it may present problems for a developer attempting to debug his/her
There have been many other minor modifications to the original sample code. In some
to be more modular. Instead of putting everything in one file, separate
.asp files were created.
The basic underlying mechanism for rendering the HTML navigation tree from an XML document object, however, has remained relatively unchanged from the original article. Thanks again to the readers for their valuable feedback. Feel free to send more suggestions, requests, or complaints. :-)
Wisebits Digital Solutions, Inc.