Creating a treeview Part 1. Designing it

Published on: February 07, 2014 Written by: Thokozani Mhlongo

Today we are going to be desigining a treeview using HTML, CSS, and jQuery. There are quite a few treeview plugins out there such as DynaTree. They are quite good too, but I found that they are prisoners to their own design. I find that they're not that easy to override the way they look (just like with most plugins).

The Markup

<ul class="treeview">
    <li data-node-state="collapsed"><span class="folder collapsed">Folder one</span>
        <ul>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder one</span>
                <ul>
                    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder one</span></li>
                    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder two</span></li>
                    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder three</span></li>
                    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder four</span></li>
                    <li><span>Item one</span></li>
                    <li><span>Item two</span></li>
                    <li><span>Item three</span></li>
                </ul>
            </li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder two</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder three</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder four</span></li>
            <li><span>Item one</span></li>
            <li><span>Item two</span></li>
            <li><span>Item three</span></li>
        </ul>
    </li>
    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder two</span>
        <ul>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder one</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder two</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder three</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder four</span></li>
            <li><span>Item one</span></li>
            <li><span>Item two</span></li>
            <li><span>Item three</span></li>
        </ul>
    </li>
    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder three</span>
        <ul>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder one</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder two</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder three</span></li>
            <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder four</span></li>
            <li><span>Item one</span></li>
            <li><span>Item two</span></li>
            <li><span>Item three</span></li>
        </ul>
    </li>
    <li class="folder" data-node-state="collapsed"><span class="folder collapsed">Folder four</span></li>
    <li><span>Item one</span></li>
    <li><span>Item two</span></li>
    <li><span>Item three</span></li>
</ul>

This markup produces the following:

As you can see just from the markup alone, nested ul elements produces a tree-like structure. The only thing special about the markup above are the data- attributes for the folder li tags that indicate the state of the folder whether its expanded or collapsed. By default, all folders will be collapsed. Now let us do the styling using CSS.

The CSS

body { 
    padding: 40px;
    background: #eee; 
    font-family: Arial; 
    font-size: 11pt; 
}

.treeview { 
    background: #fff; 
    padding: 16px; 
    border: 1px solid #aaa; 
    border-radius: 6px; 
}

.treeview ul { 
    display: none; /* Hide all child <ul> nodes */
    padding-left: 20px; 
}

.treeview li { 
    list-style: none; 
    padding: 4px 0px; 
    border-bottom: 1px dotted #ededed; 
}

.treeview span { 
    padding-left: 16px; 
    cursor: pointer; 
}

.treeview span:hover { color: #0080C0; }

.treeview span.folder { 
    background-image: url(tree-icons.png); 
    background-repeat: no-repeat; 
}

.treeview span.collapsed { background-position: 0px -86px; /* Show plus portion of the sprite image */ }

.treeview span.expanded { background-position: 0px -56px; /* Show minus portion of the sprite image */ }

This produces the following screenshot:

Here is the sprite image used in the treeview:

Now lets add the last part of the treeview. Just a bit of jQuery code to just toggle between expand and collapse.

$(document).ready(function() {
    $('span.folder').click(function() {
        var node = $(this).parent(); //Get parent
        var cssclass = $(node).attr('data-node-state');
        $(node).find('ul:first').slideToggle();
        if(cssclass === 'collapsed') { 
            $(node).attr('data-node-state' , 'expanded')
            $(this).removeClass('collapsed').addClass('expanded');
        } else {
            $(node).attr('data-node-state' , 'collapsed')
            $(this).removeClass('expanded').addClass('collapsed');
        }
    });
});

Comments