asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Advanced UI Design Using XML and XSL - Part 1: Folder Tree Creation
By Joe Slovinski
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    Welcome to Advanced UI Design Using XML and XSL. Each article in my series will demonstrate the creation of a specific user interface (UI) component using eXtensible Markup Language (XML) and eXtensible Stylesheet Language (XSL). This article explains how to create a folder tree of unlimited depth by using XML and XSL, the style-sheet language for XML. The folder tree discussed in this article functions by taking an XML feed of a specific format and applying an XSL style sheet to it. The resulting transformation is then printed to the client. The client handles all requests to expand, collapse, maximize or minimize entities within the tree, or the whole tree itself. The client used in this article is Internet Explorer 5.5+.

    The actual folder tree demonstrated is available for download at the end of this article.

    Folder -Tree-Specific Architecture

    Like most Web page objects, there are several ways to build them. When developing your specific folder tree, you should keep in mind some architectural decisions adherent to a folder tree such as:

    1. Nesting
    2. Lines

    Nesting


        Figure 1. No nesting within the browser

        Figure 2. Nesting within the browser

    In Both Figures 1 and 2 borders were temporarily applied to the tree so that one can more easily see the relationships and nesting of objects within the Document Object Model (DOM).

    Lines

    Lines within your tree can provide a greater visual effect and make larger tree structures easier to read. The negative effect on having lines within your tree is performance. A tree with 100 items may use about 300 images just to display the relationship between entities. Caching and preloading images can help, but they still exist as individual objects within the DOM. Without lines, simple indenting can show the relationship between parent and child. In this article I will demonstrate the creation of a tree without lines.

    XML Structure

    All corporations' requirements differ from one another. Odds are the requirements I have for my tree are much different than the requirements you may have for yours. XML provides us with the perfect interface to describe our unique tree entities. The format you choose will have a direct effect on your XSL style sheets and your client operations. The format I have chosen is good for a recursive XSL style sheet, which satisfies the requirement within this article for a folder tree of unlimited depth.

    The XML document I have constructed contains a root element named "tree" that can contain only "entity" elements. The structure of your tree is implicitly defined here by nesting entity elements within the "contents" element of other entity elements. Below is a listing of all elements or attributes that belong to the "entity" element.

    NameTypeDescription
    idAttributeUnique string or integer used to identify the individual entity
    descriptionElementDescription of individual entity. This is the text displayed to the user.
    onClickElementName of the client-side function fired upon the onClick event
    imageElementImage displayed when entity is closed or not selected
    imageOpenElementImage displayed when entity is open
    contentsElementContains entity elements. The content element is used to determine whether or not an entity has children.

    Within your individual trees, use the entity element to append specific data about each object in your tree. This could be the ID of a record in a database that the entity is representing. In upcoming articles I will demonstrate how to create an entity-specific context menu that is implemented by the addition of an "oncontextmenu" element to our entity element.

    The following XML is the XML we will be using in this article. For illustration purposes I have created a static XML document instead of implementing a dynamic XML database query.

    
    <?xml version="1.0"?>
    <tree>
      <entity id="e1">
        <description>Customers</description>
        <oncontextmenu></oncontextmenu>
        <image>images/book.gif</image>
        <imageOpen>images/bookOpen.gif</imageOpen>
        <contents>
          <entity id="e2">
            <description>Microsoft</description>
            <image>images/book.gif</image>
            <imageOpen>images/bookOpen.gif</imageOpen>
            <onClick>displayCustomer(12345)</onClick>
            <contents>
              <entity id="e3">
                <description>Orders</description>
                <image>images/book.gif</image>
                <imageOpen>images/bookOpen.gif</imageOpen>
                <onClick></onClick>
                <contents/>
              </entity>
            </contents>
          </entity>
          <entity id="e4">
            <description>IBM</description>
            <image>images/book.gif</image>
            <imageOpen>images/bookOpen.gif</imageOpen>
            <onClick>displayCustomer(12346)</onClick>
            <contents>
              <entity id="e5">
                <description>Orders</description>
                <image>images/book.gif</image>
                <imageOpen>images/bookOpen.gif</imageOpen>
                <onClick></onClick>
                <contents/>
              </entity>
            </contents>
          </entity>
          <entity id="e6">
            <description>Sun Microsystems</description>
            <image>images/book.gif</image>
            <imageOpen>images/bookOpen.gif</imageOpen>
            <onClick>displayCustomer(12347)</onClick>
            <contents>
              <entity id="e7">
                <description>Orders</description>
                <image>images/book.gif</image>
                <imageOpen>images/bookOpen.gif</imageOpen>
                <onClick></onClick>
                <contents>
                  <entity id="e8">
                    <description>#12345</description>
                    <image>images/paper.gif</image>
                    <imageOpen>images/paper.gif</imageOpen>
                    <onClick></onClick>
                    <contents/>
                  </entity>
                  <entity id="e9">
                    <description>#12346</description>
                    <image>images/paper.gif</image>
                    <imageOpen>images/paper.gif</imageOpen>
                    <onClick></onClick>
                    <contents/>
                  </entity>
                </contents>
              </entity>
            </contents>
          </entity>
          <entity id="e10">
            <description>Oracle</description>
            <image>images/book.gif</image>
            <imageOpen>images/bookOpen.gif</imageOpen>
            <onClick>displayCustomer(12348)</onClick>
            <contents>
              <entity id="e11">
                <description>Orders</description>
                <image>images/book.gif</image>
                <imageOpen>images/bookOpen.gif</imageOpen>
                <onClick></onClick>
                <contents/>
              </entity>
            </contents>
          </entity>
        </contents>
      </entity>
      <entity id="e12">
        <description>Reports</description>
        <oncontextmenu></oncontextmenu>
        <image>images/book.gif</image>
        <imageOpen>images/bookOpen.gif</imageOpen>
        <contents>
          <entity id="e13">
            <description>Income</description>
            <oncontextmenu></oncontextmenu>
            <image>images/paper.gif</image>
            <imageOpen>images/paper.gif</imageOpen>
            <contents>
            </contents>
          </entity>
          <entity id="e14">
            <description>Expenses</description>
            <oncontextmenu></oncontextmenu>
            <image>images/paper.gif</image>
            <imageOpen>images/paper.gif</imageOpen>
            <contents>
            </contents>
          </entity>
        </contents>
      </entity>
    </tree>
    
    
    The above XML file is named "tree.xml" and is available for download at the end of this article.

    XSL Style Sheet

    Both Figures 1 and 2 were the result of transformations with our XML document and separate XSL style sheets. Below is the standard XSL style sheet that is applied to our XML document(s).

    
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" language="JavaScript">
    
    <xsl:template match="tree">
      <xsl:apply-templates select="entity"/>
    </xsl:template>
    
    <xsl:template match="entity">
      <div onclick="window.event.cancelBubble = true;clickOnEntity(this);" onselectstart="return false" ondragstart="return false">
      <xsl:attribute name="image"><xsl:value-of select="image"/></xsl:attribute>
      <xsl:attribute name="imageOpen"><xsl:value-of select="imageOpen"/></xsl:attribute>
      <xsl:attribute name="open">false</xsl:attribute>
      <xsl:attribute name="id">f<xsl:value-of select="@id"/></xsl:attribute>
      <xsl:attribute name="open">false</xsl:attribute>
      <xsl:attribute name="STYLE">
        padding-left: 20px;
        cursor: hand;
        <xsl:if expr="depth(this) > 2">
          display: none;
        </xsl:if>
      </xsl:attribute>
        <table border="0" cellspacing="0" cellpadding="0">
          <tr>
            <td valign="middle">
              <img border="0" id="image">
                <xsl:attribute name="SRC">
                  <xsl:value-of select="image"/>
                </xsl:attribute>
              </img>
            </td>
            <td valign="middle" nowrap="true">
            <xsl:attribute name="STYLE">
              padding-left: 7px;
              font-family: Verdana;
              font-size: 11px;
              font-color: black;
            </xsl:attribute>
            <xsl:value-of select="description"/></td>
          </tr>
        </table>
      <xsl:apply-templates select="contents/entity"/>
      </div>
    </xsl:template>
    
    </xsl:stylesheet>
    
    
    Figure 3 (below) displays the folder tree that is created using the above XSL style sheet.


    Figure 3. XSL transformation

    Client Operations

    In order for our folder tree to function, we require the following client-side operations:

    1. Initialize
    2. Expand
    3. Collapse
    4. Expand All (Maximize)
    5. Collapse All (Minimize)
    Below is the code that performs these five operations. This code can be found within the "tree.js" file included with this article.
    
    function initialize() {
      var xmlDoc
      var xslDoc
    
      xmlDoc = new ActiveXObject('Microsoft.XMLDOM')
      xmlDoc.async = false;
    
      xslDoc = new ActiveXObject('Microsoft.XMLDOM')
      xslDoc.async = false;
    
      xmlDoc.load("tree/tree.xml")
      xslDoc.load("tree/tree.xsl")
    
      folderTree.innerHTML = xmlDoc.documentElement.transformNode(xslDoc)
    }
    
    function clickOnEntity(entity) {
      if(entity.open == "false") {
        expand(entity, true)
      }
      else {
        collapse(entity)
      }
      window.event.cancelBubble = true
    }
    
    function expand(entity) {
      var oImage
    
      oImage = entity.childNodes(0).all["image"]
      oImage.src = entity.imageOpen
    
      for(i=0; i < entity.childNodes.length; i++) {
        if(entity.childNodes(i).tagName == "DIV") {
          entity.childNodes(i).style.display = "block"
        }
      }
      entity.open = "true"
    }
    
    function collapse(entity) {
      var oImage
      var i
    
      oImage = entity.childNodes(0).all["image"]
      oImage.src = entity.image
    
      // collapse and hide children
      for(i=0; i < entity.childNodes.length; i++) {
          if(entity.childNodes(i).tagName == "DIV") {
            if(entity.id != "folderTree") entity.childNodes(i).style.display = "none"
            collapse(entity.childNodes(i))
          }
        }
      entity.open = "false"
    }
    
    function expandAll(entity) {
      var oImage
      var i
    
      expand(entity, false)
    
      // expand children
      for(i=0; i < entity.childNodes.length; i++) {
        if(entity.childNodes(i).tagName == "DIV") {
          expandAll(entity.childNodes(i))
        }
      }
    }
    
    

    Future of Web-Based Folder Trees

    As Web technologies grow, they allow us to maintain state within our Web applications. This increases the complexity of our interfaces as more operations are moved from server to client. This is a blessing that will increase the usability of our interfaces and the performance of our applications by taking the load off of our servers.

    In future articles I may expand on the tree discussed in this article by explaining how to create an API to dynamically insert, remove, rename, and refresh objects within your trees.

    Closing

    I hope the contents of this article will help increase the quality of your Web applications interface. If you have any questions, comments, or suggestions, please feel free to email me at the address listed in the author section.

    On a side note, I would like to thank Lee McGraw for helping me proofread and validate this document.

    The second article in this series addresses custom context menu creation.

    Download

    Download the example.zip file that contains the files that make up the tree, including tree.xsl, tree.xml, tree.js, tree.css, common.js, and images.

    Other Articles in This Series

    Advanced UI Design

    Part 2 -- Custom Context Menu Creation
    http://www.15seconds.com/issue/010927.htm

    Part 3 -- Folder Tree Administration
    http://www.15seconds.com/issue/011113.htm

    Part 4 - Folder Tree Drag and Drop
    http://www.15seconds.com/issue/011129.htm

    Part 5 - Progress Indicator Creation
    http://www.15seconds.com/issue/011212.htm

    Part 6 -- Progress Indicator Usage
    http://www.15seconds.com/issue/020109.htm

    Part 7 -- Relational Folder Tree Lines
    http://www.15seconds.com/issue/020424.htm

    About the Author

    Joe Slovinski has been programming Web applications since 1993. For more information on the code in this article, contact the Joe Slovinski.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Supporting Products/Tools
    Stonebroom.ASP2XML
    Stonebroom.ASP2XML(c) is an interface component designed to make building applications that transport data in XML format much easier. It can be used to automatically pass updates back to the original data source.
    [Top]
    Other Articles
    Sep 22, 2005 - Implementing Remote Calling Without Using AJAX
    Right now the latest buzzword around town is AJAX. AJAX is an acronym for Asynchronous JavaScript and XML and is a method used to implement remote calling. The problem is that AJAX is only implemented in ASP.NET 2.0. This article will show you one way to implement remote calling without using AJAX or the XMLHttpRequest object. The technique outlined can even be used from classic ASP and is sufficient for most remote calling needs.
    [Read This Article]  [Top]
    Aug 18, 2005 - SQL Server 2005 XQuery and XML-DML - Part 3
    This article is the third and final installment of Alex Homer's series covering the new XML support in Microsoft SQL Server 2005. In it he covers updating the contents of xml columns, comparing traditional XML update techniques with XQuery, and using XQuery in a managed code stored procedure.
    [Read This Article]  [Top]
    Aug 11, 2005 - SQL Server 2005 XQuery and XML-DML - Part 2
    In the second part of his series on SQL Server 2005's new XML support, Alex Homer looks at extracting data from XML columns, comparing traditional XML data access approaches with XQuery, and combining XQuery and XSL-T.
    [Read This Article]  [Top]
    Aug 3, 2005 - SQL Server 2005 XQuery and XML-DML - Part 1
    Microsoft SQL Server 2005 now offers great support for and close integration with XML as a data persistence format. In the first article of his series examining this new support, Alex Homer offers an overview of how SQL Server 2005 stores XML documents and schemas, examines how it supports querying and manipulating XML documents, and provides a simple test application that allows you to experiment with XQuery.
    [Read This Article]  [Top]
    Jun 30, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 3, Cont'd
    In the final article of his series on reading and writing XML in .NET 2.0, Alex Homer looks at how the updated XML document store objects XmlDocument, XmlDataDocument and PathDocument can be used to read, persist and write XML documents and fragments more easily and more efficiently than in .NET 1.x.
    [Read This Article]  [Top]
    Jun 29, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 3
    In the final article of his series on reading and writing XML in .NET 2.0, Alex Homer looks at how the updated XML document store objects XmlDocument, XmlDataDocument and PathDocument can be used to read, persist and write XML documents and fragments more easily and more efficiently than in .NET 1.x.
    [Read This Article]  [Top]
    Jun 16, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 2, Cont'd
    Alex Homer continues his series on reading and writing XML in .NET 2.0. In part one, we focused on the reading side of things, examining the XmlReader and XmlReaderSettings classes. In this article, we move on to look at the XmlWriter and XmlWriterSettings classes, and how they can be used to write XML documents and fragments more easily and more efficiently than in version 1.x of .NET.
    [Read This Article]  [Top]
    Jun 15, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 2
    Alex Homer continues his series on reading and writing XML in .NET 2.0. In part one, we focused on the reading side of things, examining the XmlReader and XmlReaderSettings classes. In this article, we move on to look at the XmlWriter and XmlWriterSettings classes, and how they can be used to write XML documents and fragments more easily and more efficiently than in version 1.x of .NET.
    [Read This Article]  [Top]
    Jun 2, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 1, Cont'd
    In the first part of his series on reading and writing XML in .NET 2.0, Alex Homer discusses the XmlReader and XmlReaderSettings classes. The XmlReader exposes several useful new features and the all new XmlReaderSettings class makes it easy to generate single or multiple instances of an XmlReader with a range of useful properties.
    [Read This Article]  [Top]
    Jun 1, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 1
    In the first part of his series on reading and writing XML in .NET 2.0, Alex Homer discusses the XmlReader and XmlReaderSettings classes. The XmlReader exposes several useful new features and the all new XmlReaderSettings class makes it easy to generate single or multiple instances of an XmlReader with a range of useful properties.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers