Explorer Tree


Explorer Tree is a bit of DHTML that implements a Windows Explorer-like tree from simple unordered list markup. People without Javascript, or with Javascript disabled, get a regular unordered list. With Javascript, the list becomes a tree with branches that can be collapsed or expanded to hide and reveal sub-lists (tree branches).

For a long time I'd been looking at the rather long and boring list of pages on my Site Map and thinking that they needed a bit of improving.

The sort of thing I wanted was primarily a collapsible tree, so that you didn't have to see the entire site, but only the parts you were interested in. There was also a secondary goal of being able to show the page you had come from (if applicable) to give visitors some better feedback of where they were in my site.

I found aqLists, in particular the "aqtree3clickable" set of files. However, there were several things I didn't like about it:

In the course of resolving these issues, I ended up completely rewriting the aqList code. I also added many new features and tried to make it more customisation friendly.

Required Files

Creative Commons License
This work is licensed under a Creative Commons License.



Add the following code into the <head> of your page (modified as appropriate for the correct file locations on your site):

<link rel="stylesheet" type="text/css" href="explorertree.css"> <script type="text/javascript" src="events.js"></script> <script type="text/javascript" src="cssutil.js"></script> <script type="text/javascript" src="explorertree.js"></script>

Then add class="explorertree" to your <ul> tag(s). For example:

<ul class="explorertree"> <li>Google<ul> <li><a href="http://www.google.com/">Web</a><ul> <li><a href="http://www.google.com/advanced_search">Advanced Search</a></li> <li><a href="http://www.google.com/preferences">Preferences</a></li> <li><a href="http://www.google.com/language_tools">Language Tools</a></li> </ul></li> <li><a href="http://images.google.com/">Images</a><ul> <li><a href="http://images.google.com/advanced_image_search">Advanced Search</a></li> <li><a href="http://images.google.com/preferences">Preferences</a></li> <li><a href="http://images.google.com/help/faq_images.html">Help</a></li> </ul></li> <li><a href="http://groups.google.com/">Groups</a><ul> <li><a href="http://groups.google.com/advanced_group_search">Advanced Search</a></li> <li><a href="http://groups.google.com/preferences">Preferences</a></li> <li><a href="http://groups.google.com/googlegroups/help.html">Help</a></li> </ul></li> <li><a href="http://news.google.com/">News</a><ul> <li><a href="http://news.google.com/intl/en_us/about_google_news.html">About</a></li> </ul></li> <li><a href="http://froogle.google.com/">Froogle</a><ul> <li><a href="http://froogle.google.com/froogle_advanced_search">Advanced Search</a></li> <li><a href="http://www.google.com/preferences">Preferences</a></li> <li><a href="http://froogle.google.com/froogle/about.html">Help</a></li> </ul></li> </ul></li> </ul>

Will be rendered as:

The initialisation code will automatically fully collapse the tree. If you don't want a branch to start out collapsed, simply add class="explorertree-open" to the relevant <li>s. If you don't want a sublist to collapse at all, add class="explorertree-bullet".

You can also freely mix-and-match classes, for example: class="explorertree-open fancyclass". The name "fancyclass" will be preserved by the script.

Different Bullet Images

If you create a set of custom bullet images, they must all be the same width and height. You should also set the explorerTreeBulletWidth property for your tree (see below). The next list is the same list as above, but uses triangle bullet images:

All I needed to do was set the id of the list to "triangles", then override some styles and set the bullet width value by adding the following into the <head> of the page:

<style type="text/css"> ul#triangles ul { padding-left: 15px; } ul#triangles li { list-style-image: url(tri-none.png); } ul#triangles li.explorertree-open { list-style-image: url(tri-down.png); } ul#triangles li.explorertree-closed { list-style-image: url(tri-right.png); } /* The next two are optional extras */ ul#triangles li.web { list-style-image: url(/images/externalweb.png); } ul#triangles li.news { list-style-image: url(/images/news.png); } </style> <script type="text/javascript"> explorerTreeBulletWidth.triangles=20; </script>

I've also added some different bullet images for the web and news list items. A class="web" or class="news" was added to the list item tags.

NOTE: The bullet width was set to 20, not 15, to cater to some Internet Explorer bugs. See below.

More Examples

Here are some pages that demonstrate more advanced techniques. Some of these require CSS support that is currently only available in Mozilla/Firefox:

Scripting API



If you dynamically modify your document structure to add a new explorer tree list, or add or remove list items and/or sub-lists from an existing explorer tree, then calling this function will have the script update all the explorer trees on the page. If any list items no longer have sub-lists, it ensures that any "open" or "closed" styles are changed to "bullet". If there are sub-lists without any explorer tree styles, they are set to "closed".


As for explorerTreeRefreshAll above, except only the explorer tree with the specified id is refreshed.


Collapses all collapsible branches of the specified explorer tree.


Expands all expandable branches of the specified explorer tree.

element explorerTreeOpenTo(id, href, scroll, expand)

Searches the specified explorer tree for the list item which contains an anchor (<a> tag) with an href corresponding to the specified href.

If such a list item is found, the tree is opened to reveal that list item. If scroll is true, the document is scrolled to center the list item on the viewport. If expand is true the list item is expanded (if possible).

Returns the HTMLElement of the found list item, or null if no list item was found.

Global Variables


This controls whether or not the script will automatically collapse explorer tree branches that are unrelated to the branch being opened by the user. Intended to work around an Internet Explorer issue (see below). Avoid using if possible, as the effect can be a bit disconcerting.

Set by using a property name the same as the tree id. For example: explorerTreeAutoCollapse.sitemap=true;. Use explorerTreeAutoCollapse['default'] to set the default value.


If you want to use different bullet images, set this to the pixel width of your bullet images. All your bullet images must be the same width and height.

Set by using a property name the same as the tree id. For example: explorerTreeBulletWidth.sitemap=20;. Use explorerTreeBulletWidth['default'] to set the default value.

Note: An issue with Internet Explorer is described below.

Known Issues

Internet Explorer

Internet Explorer adds some extra unwanted space between the inside edge of the list items and the bullet images. If you use explorerTreeBulletWidth, you may need to use values a bit larger than you might expect. You'll need to experiment for the best 'feel'.

Internet Explorer also has some severe bugs when setting dimensions on list items, and on elements enclosing lists. This applies to all lists, not just Explorer Tree.

Setting a width on list items themselves tends to introduce very severe bugs, including things like missing list markers! I've also seen instances where the numbers on ordered lists didn't increment. The only solution I'm aware of is to never set the width/height of a list item.

Another critical problem is one where events stop triggering on list bullets. This totally breaks Explorer Tree. It tends to occur when setting a width/height on the list tag (<ul> or <ol>). The easiest workaround I've found (that seems to work) is to enclose the list in a <div> styled with the same width/height. I've also heard it happens when the enclosing <div> is floated. The solution I found for that was to float the top <ul> the same.

Opera (7+, fixed in 9) and Firefox (0.8+, fixed in 1.5)

These browsers have trouble using images for list item bullets. Firefox is OK as soon as the images are in the cache. Opera simply has trouble when the images are required by dynamically setting list item class names.

The workaround for these browsers is to load the bullet images elsewhere on the same page as the explorer tree(s). The following code is suggested:

<img src="explorertree-plus.png" width="0" height="0" alt=""> <img src="explorertree-minus.png" width="0" height="0" alt=""> <img src="explorertree-bullet.png" width="0" height="0" alt="">


Tested using version 3.2.2 (Knoppix 3.4).

Explorer Tree works with Konqueror, except that bug 57913 prevents onload registration. I've added a work around to the events.js support file.


The "You Were There" Indication on my Site Map

This was quite simple. I added id="sitemap" to the top-level <ul> tag, then added the following code (which should all go on one line) to open the tree to the item with the href matching document.referrer, and if such a list item was found, giving it an id of "current":

<script type="text/javascript">addEvent(window, 'load', new Function( "var li = explorerTreeOpenTo('sitemap', document.referrer, true, true); if (li) li.setAttribute('id', 'current');"), false);</script>

To show up the found list item, I added the following to my style sheet:

/* Highlight the referring page in the sitemap */ ul#sitemap li#current>a { font-weight: bolder; font-size: larger; }

The use of the child selector (>) means it doesn't work in Internet Explorer, however, there's no other easy way to highlight just the current link, without also highlighting all the links below it. If Microsoft can't be bothered implementing a spec dating from May 1998, I can't be bothered writing a bunch of Javascript working around it. I'll leave it as an exercise for the reader...

"Fully Expand Tree" Link

The intention for this is to allow people with limited mobility to fully expand the tree so they have less fiddling about opening individual branches. The code is simple:

<button type="button" onclick="explorerTreeExpand('sitemap')">Fully expand tree</button>

Using Background Images

Some people find using background images instead of list-style-image gives them better cross-browser results. The problem with that is if your visitors surf with images turned off - there would be no list indicators at all! In my opinion, that is a serious usability issue. The call is yours, of course. My script does not dictate any particular styling at all - that was one of the main design goals. Just replace my default stylesheet with your own. As an example, here is the default Explorer Tree list style done using background images:

ul.explorertree li { list-style-type: none; background-repeat: no-repeat; background-position: 2px 1px; } ul.explorertree, ul.explorertree ul, ul.explorertree li { margin: 0; padding: 0; } ul.explorertree li { padding-left: 20px; } /* sublist indentation */ /* Set the bullet images */ ul.explorertree li { background-image: url(/images/explorertree-bullet.png); } ul.explorertree li.explorertree-open { background-image: url(/images/explorertree-minus.png); } ul.explorertree li.explorertree-closed { background-image: url(/images/explorertree-plus.png); } /* Actually show and hide sublists */ ul.explorertree li.explorertree-open ul { display: block; } ul.explorertree li.explorertree-closed ul { display: none; }

Version History

Explorer Tree Version History
  • Fixed event handling to prevent default browser actions instead of stopping bubbling/propagation.
  • Added support for Dean Edwards IE7 script.
  • Modified events.js to work around Konqueror bug.
  • Added a degree of Konqueror support (changes to explorertree.js and cssutil.js).
  • Made nodeName comparisons case-insensitive.
  • Removed onclick coordinate checks.
  • Changed the two global variables. No longer simple variables, they're now objects with properties. This change breaks any existing usage, but they weren't needed to be used by default. The script is now a lot more flexible.
  • Fixed the Gecko text selection issue.
  • Replaced element.onclick code with calls to addEvent().
  • Removed line-height property from style sheet. I'd put it in there because it fixed glitches with IE6. Today, removing it has fixed the problem! I'm confused.
  • Added fallback list-style-type properties to the style sheet.
  • Initial version. Inspired by the aqLists implementation by Stuart Langridge.