When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
Message Board
Related Web Technologies
User Tips!
Coding Tips

Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Stump the SQL Guru!
XML Info
Author an Article
ASP ASP.NET ASP FAQs Message Board Feedback
Print this page.
Published: Wednesday, July 25, 2001

A Dynamic Tree Menu System, Part 2

By Sam Reynoso

  • Read Part 1

  • In Part 1 we looked at the need for a tree-like navigational tool for Web sites. We examined existing solutions and discussed how to create a custom solution using an XML file as a data source for the tree structure. In this part, we'll take a high-level view at the HTML, ASP, and client-side JavaScript code we'll need to accomplish this.

    - continued -

    ASP for HTML Code Generation
    One of the advantages of the tree navigation system is the ability to view the resulting HTML code by selecting View/Source in the browser. This is made possible by a core ASP subroutine that is called recursively to traverse the XML tree. The HTML for displaying folders and documents is generated with each call to the subroutine. When the last node of the XML tree has been processed, the ASP code will have returned a complete HTML page containing the entire structure of the navigation menu. When rendered by the browser, some elements will be collapsed by default until the user clicks to expand them. Viewing the source would reveal all the nodes used in the tree menu and the javascript necessary to control the expansion and collapse of menu items.

    The javascript consists of two functions that support toggling menu items open and closed. The functions read from two arrays to determine which menu items to manipulate. The first array contains integers that represent the IDs of all the expandable nodes on the tree. The second array contains integers that represent the IDs of all expandable/collapsible menu items. Since the code has to be able to generate any menu structure defined in the XML file, we can't know the size of these arrays at design time. To get around this problem, we embed ASP into the Javascript dynamically declare the arrays on the server side at run-time. This is discussed in more detail below.

    Introducing the Code
    All the code necessary to generate the tree menu (except the XML) is stored in a single file called menu.asp. At the top of the file we insert a basic style definition to control the look of the text used in the menu items. We encapsulate our style into a single class called node which we apply later on. The style definition is presented below:

    <STYLE TYPE="text/css">
       .node { color: black;
          font-family : "Helvetica", "Arial", "MS Sans Serif", sans-serif;
          font-size : 9pt;}
       .node A:link { color: black; text-decoration: none; }
       .node A:visited { color: black; text-decoration: none; }
       .node A:active { color: black; text-decoration: none; }
       .node A:hover { color: black; text-decoration: none; }

    Next, we load our XML file into the MSXML parser. We check for errors that can occur along the way. The subroutine sbShowXMLParseError() displays a detailed explanation of the parse error, if it is encountered, and helps pinpoint the exact location of the error.

    sXMLSourceFile = "menuitems.xml"
    'Create instance of XML document object that we can manipulate
    Set objDocument = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
    if objDocument is nothing then
       Response.Write "objDocument object not created<br>"
       If Err Then 
          Response.Write "XML DomDocument Object Creation Error - <BR>"
          Response.write Err.Description
          'Load up the XML document into the XML object
          objDocument.async = false
          bLoaded = objDocument.load(Server.MapPath(sXMLSourceFile))
          if (bLoaded = False) then
             sbShowXMLParseError objDocument 

    Just before we begin drawing the tree menu, we give the developer an opportunity to specify what folders should be expanded by default. This is done by putting values into an array. When the menu is generated, the array is probed for elements that match the current node. If a match is found, the folder is displayed as expanded.

            'Set some folders to open by default.
            dim arArray(3)
            'Root value in our tree should be open by default
            arArray(0) = objDocument.firstChild.getAttribute("value") 
            arArray(1) = "History"

    Now we make our first call to the subroutine that will actually generate the HTML for our navigation tree. The parameter iTotal is passed in by reference and keeps track of the total number of elements in our tree. It will be used in the Javascript portion of our page. The subroutine continues to call itself recursively until all nodes of the objDocument object have been visited.

    DisplayNode objDocument.childNodes, iTotal, sLeftIndent, arArray

    Once DisplayNode has completed execution, we get to the javascript portion of our ASP page. ASP code is embedded in the javascript array declaration. This permits us to be flexible in the number of elements used in the tree menu. A For loop uses the value of iTotal to iterate through a cycle equivalent to the number of nodes in the menu. When the loop is complete, the page will contain a javascript array definition that exactly matches the number of elements in the tree menu.

    var arClickedElementID = new Array(<% for i = 1 to iTotal %> "<%=i%>"<%if i < iTotal then%>,<%end if%> <%next%>);
    var arAffectedMenuItemID = new Array(<% for i = 1 to iTotal %> "<%=i+1%>"<%if i < iTotal then%>,<%end if%> <%next%>);

    Once the ASP file has finished executing, the browser will receive a fully-formed HTML page that displays a tree navigation menu. Viewing the sourcecode will reveal only Javascript and HTML code. The content that was stored in the XML file has been processed and is now a part of the HTML document.

    Now that we've examined the purpose and general code for menu.asp from a very high-level perspective, it's time that we drill into the guts of the page - the DisplayNode() function. In Part 3 we'll tackle this task. (Do note, though, at any time you may view a live demo of the dynamic tree navigation.)

  • Read Part 3!

  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article