Click here to Skip to main content
Click here to Skip to main content

Current Tree-Node Opener

, 23 May 2003
Rate this:
Please Sign up or sign in to vote.
Simple DOM exploiting code to display the currently selected node in a HTML list tree

Introduction

This article describes a simple method of using JavaScript and the DOM to display the selected node in a HTML tree list. Most methods rely on the tree constructor to "follow the path" down the node tree to the selected item, setting each parent node to a visible mode.

This method however does the reverse; The current node is tagged and the path from it up to the root node is followed making each parent visible on the way. This method is more efficient as no searches or iterations on node collections are needed to find the next node to make visible.

This is not an article on how to make HTML tree lists, I assume you already know how to do this. You can of course view the sample code which includes HTML tree lists. That topic has been covered very well in other articles here on Code Project.

Requirements

Knowledge of HTML, CSS and JavaScript are essential. Knowledge of the Document Object Model (DOM) will help you as well.

No server-side environments, ASP/PHP/etc., are required to run the examples or use this  method. It is all client-side.

The Problem

You have this...
Sample screenshot
and you want this on-load of your page:
Sample screenshot

What you have here is a HTML tree list coded like this:

<ul id="menu">
    <li><a href="">Section 1</a></li>
    <li><a href="">Section 2</a>
        <ul>
            <li><a href="">Section 2.1</a></li>
            <li><a href="">Section 2.2</a></li>
            <li><a href="">Section 2.3</a>
                <ul>
                    <li><a href="">Section 2.3.1</a></li>
                    <li><a href="">Section 2.3.2</a></li>
                </ul>
            </li>
            <li><a href="">Section 2.4</a></li>
        </ul>
    </li>
    <li><a href="">Section 3</a></li>
</ul>

Each UL within a LI will have it's display style attribute set to none in a CSS file. e.g. ul#menu li ul { display:none; }. This is a great setup allowing simple JavaScript to open and close nodes as the user needs.

However when it comes to loading a page and having a sub-node displayed in a visible/open mode by default this structure makes it less than easy. You cannot very well expect users to click back down through the tree structure every time they visit a new page. The tree structure should remain open to the node they clicked on.

The conventional way of sorting this problem out is with code like so:

<ul id="menu">
    <li><a href="">Section 1</a></li>
    <li><a href="">Section 2</a>
        <ul class="open">
            <li><a href="">Section 2.1</a></li>
            <li><a href="">Section 2.2</a></li>
            <li><a href="">Section 2.3</a>
                <ul class="open">
                    <li><a href="">Section 2.3.1</a></li>
                    <li><a href="">Section 2.3.2</a></li>
                </ul>
            </li>
            <li><a href="">Section 2.4</a></li>
        </ul>
    </li>
    <li><a href="">Section 3</a></li>
</ul>

Each parent of the node you want to display needs an assigned class of open. In your CSS you then have ul#menu li ul.open { display: block }.

It works but the main problem is that you have to concoct code which assigns that class to each node that needs it. Not only is the code for this not easy but it is also inefficient. Another really big problem is that you cannot easily cache your tree code as with each navigation event the code changes. It basically becomes per-user code, rendering caching a bit pointless. There are ways around that but the method I will explain below needs none of this.

Looking Up, Another Way

The DOM element property of parentElement is the key. Basically ever element excluding HTML must have a parent element. The tree view code of above is especially dependant on this child/parent structure.

To kick this off here is what I propose; Walk up the tree. Start with the selected node and then using parentElement you walk up the tree to the "root" node of the menu. Everytime you hit a UL element you simply assign block to it's display style attribute. Damned simple IMO. No looping through other elements on the same level is required. You don't need to check if the node is on the right path because it automatically is, by virtue of it being a parent of the node you have walked up from.

Since you are all code-heads you will probably understand the code better than that explanation:

function showCurrentSection()
{        
    var objCurrentSection = document.getElementById("navcurrentsection");        
    if (objCurrentSection != null)
    {
        objCurrentSection.style.display = "block";            
        objCurrentSection.parentElement.childNodes[0].className = "open";
        if (objCurrentSection.parentElement.parentElement.nodeName == "UL")
            showSection(objCurrentSection.parentElement.parentElement);        
    }
}

function showSection(objSection)
{    
    objSection.style.display = "block";
    objSection.parentElement.childNodes[0].className = "open";    
    if (objSection.parentElement.parentElement != null && objSection.parentElement.parentElement.nodeName == "UL")
        showSection(objSection.parentElement.parentElement);
}

You have two functions. showCurrentSection is kicked off normally by an onload event e.g. <body onload="showCurrentSection();">. showCurrentSection calls showSection which calls itself until no more valid parent elements are found.

showCurrentSection starts with the line document.getElementById("navcurrentsection"). There is one modification to the HTML tree list code you need to make:

<ul id="menu">
    <li><a href="">Section 1</a></li>
    <li><a href="">Section 2</a>
        <ul>
            <li><a href="">Section 2.1</a></li>
            <li><a href="">Section 2.2</a></li>
            <li><a href="">Section 2.3</a>
                <ul id="navcurrentsection" >
                    <li><a href="">Section 2.3.1</a></li>
                    <li><a href="">Section 2.3.2</a></li>
                </ul>
            </li>
            <li><a href="">Section 2.4</a></li>
        </ul>
    </li>
    <li><a href="">Section 3</a></li>
</ul>

You need to tag the section so that the walker can find where it should start from. document.getElementById("navcurrentsection") returns an object reference to whatever UL element has that specific ID.

The if (objCurrentSection != null) is just there to ensure that indeed a section is currently selected. For instance on the home page of your website probably no node will be selected, in which case the walker should not run.

Next we just set the navcurrentsection node to be displayed. We then change the classname of the node so that any visualisation of an open node are applied, e.g. an open folder graphic. Next the code checks wether the element two levels up is a UL. Remember that a sub node is a UL contained within a LI element i.e. The parent is actually a LI not a UL. You don't want to touch the LI, so two levels up you go.

If it is a UL then we call the showSection function and pass that parent-parent element to it.

showSection does the actual walking as it calls itself until objSection.parentElement.parentElement != null && objSection.parentElement.parentElement.nodeName == "UL" is false. i.e. Until no more parent-parent elements correspond to a UL element. nodeName returns the name of the element. e.g. A for <a href=""></a>, DIV for <div></div>, UL for <UL></UL> etc.

This obviously means that your HTML tree list code needs to be well coded, valid in otherwords.

Conclusion

All in all quite simple really. Certainly improvements can be made in the JavaScript code, but the idea is there and it works quite well. The main thing I like about this method is that you just output your HTML tree list code, bang in a tag and run the script. You do not have to change the code which generates your HTML tree list. It also gives a taste of the power of the DOM.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Paul Watson
Web Developer TSSG
Ireland Ireland
Paul is an internet developer living in Dublin, Ireland though home is still South Africa.
 
He believes in self-taught programming skills, standards based thinking and in the power of the common man.
 
Oh, and he loves photography. Make sure you don't get caught in the corner of a party when he has that photographic gleam in his eye. And if you were wondering about that bed-head photograph, wonder no longer...
Follow on   Twitter

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 24 May 2003
Article Copyright 2003 by Paul Watson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid