« Photo Sharing | Main | Keeping an Entry at the Top »

Expandable List Menus

If you have a lot of content - entries, categories, sidebar information - sooner or later things may begin to look a little cluttered on your weblog. One way to address this is to make some of your lists expandable and collapsible, as I have done with LMT's Table of Contents. There are probably many different ways to do this. I have found one method, based on Javascript, that is simple to implement and appears to work fine, from Bleeding Ego.


1. Upload listmenu.js to your server.

Copy the following script into a new file with a texteditor. Save the script as "listmenu.js". Upload the script to a location within the public directory of your server using an FTP program. (You can also find a copy of this script at Bleeding Ego.)

/*
Expandable Listmenu Script
Author : Daniel Nolan
http://www.bleedingego.co.uk/webdev.php
*/

function initMenus() {
if (!document.getElementsByTagName) return;

var aMenus = document.getElementsByTagName("LI");
for (var i = 0; i < aMenus.length; i++) {
var mclass = aMenus[i].className;
if (mclass.indexOf("treenode") > -1) {
var submenu = aMenus[i].childNodes;
for (var j = 0; j < submenu.length; j++) {
if (submenu[j].tagName == "A") {

submenu[j].onclick = function() {
var node = this.nextSibling;

while (1) {
if (node != null) {
if (node.tagName == "UL") {
var d = (node.style.display == "none")
node.style.display = (d) ? "block" : "none";
this.className = (d) ? "treeopen" : "treeclosed";
return false;
}
node = node.nextSibling;
} else {
return false;
}
}
return false;
}

submenu[j].className = (mclass.indexOf("open") > -1) ? "treeopen" : "treeclosed";
}

if (submenu[j].tagName == "UL")
submenu[j].style.display = (mclass.indexOf("open") > -1) ? "block" : "none";
}
}
}
}

window.onload = initMenus;


2. Add a script reference line to the header of your index or archive template.

In the header section of the templates in which you want the expandable list menu to be used, add the following line:

<script src="http://www.your_web_site.com/path/to/listmenu.js" type="text/javascript"></script>

Replace the "http://www.your_web_site.com/path/to/" with the actual path on your server to the listmenu.js that you uploaded to your server in step one above.

3. Insert your list into your template or document using the following structure:

<ul class="treemenu">
<li class="treenode">
<a href="">Top Level Item</a>
<ul>
<li><a href="">List Item</a></li>
<li><a href="">List Item</a></li>
<li><a href="">List Item</a></li>
<li><a href="">List Item</a></li>
</ul>
</li>
</ul>


Note in particular the lack of a symbol between quotation marks in <a href="">

For example, here is a snippet of code that I use on my Table of Contents template:


<ul class="treemenu">
<li class="treenode">
<a href=""><h2>Beginner Tips</h2></a>
<ul>
<MTEntries category="Beginner Tips" sort_by="title" sort_order="ascend">
<a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a><br />

</MTEntries>
</ul>

<a href=""><h2>Categories</h2></a>
<ul>
<MTEntries category="Categories" sort_by="title" sort_order="ascend">
<a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a><br />
</MTEntries>
</ul>
</li>
</ul>

This code requires that you specify each category and give it a name. I've done this with my Table of Contents so that I could list out the contents in the specific order I wanted. If you want to simplify this process and list out your TOC in the ascending order of your categories, try the following code (suggested by Arvind from Movalog):

<ul class="treemenu">
<MTCategories>
<li class="treenode">
<a href=""><h2><MTCategoryLabel></h2></a>
<ul>

<MTEntries><li><a href="<MTEntryPermalink>"><MTEntryTitle>
</a></li></MTEntries>
</ul>

</MTCategories>
</li>

</ul>

4. Add ListMenu stylesheet elements to your stylesheet.

You can style your list by adding some style elements to your stylesheet. See listmenu.css for an example of some css elements to add to your stylesheet from Bleeding Ego. Here are the style elements I've added to the stylesheet for the Table of Contents in LMT:

.treemenu {
margin : 0px 20px;
padding : 10px;
list-style : none;
}

.treemenu h2
color: #004090;
font-family: 'Trebuchet MS', Verdana, sans-serif;
font-size: small;
text-align: left;
font-weight: bold;
margin-top: 5px;
margin-bottom: 5px;
}

.treemenu UL {
list-style : none;
}

.treemenu LI {
display : inline;
}

.treemenu A {
text-decoration: underline;
}

The best place to add these style elements is at the very bottom of your stylesheet.

(Note the only real problem I encountered with this script was in Safari. The Table of Contents index template still had RSS header information in the header. For some weird reason these lines interfered with the Safari browser when the script was loading for the first time, with the result being a lot of odd text added to the page. Removing the RSS, Atom, and RSD link rel lines from the TOC template resolved the problem.)

Comments (18)

elise:

If the user's browser does not support Javascript, the menu should show up as all expanded. In case this doesn't happen, I've included a link to a section of the Index page (Master archive list) that has the entries sorted out by category. I find it much easier to look at the section titles without having to scroll forever through every entry title.

You can improve the code you use on your Table of Contents page..rather than manually listing out each h2 and then the entries underneath it try out this

<ul class="treemenu">
<MTCategories>
<li class="treenode">
<a href=""><h2><MTCategoryLabel></h2></a>
<ul>
<MTEntries><li><a href="<MTEntryPermalink>"><MTEntryTitle></a></li></MTEntries>
</ul>
</li>
</MTCategories>
</ul>

it should produce the same code, just one block of it now rather than x (number of categories) blocks!

frostdoll [TypeKey Profile Page]:

I just want to let you know that the last code posted by Arvind misses a tag

<a href=""><h2><MTCategoryLabel></h2> </a>

Otherwise the script doesn't work.

Note from Elise: Missing closing A tag added into Arvind's code in his comment. Thanks for the catch. ~Elise

Sithicus:

Has anybody gotten this this same script or something simliar to work with so it goes one more level deep.

ex//
Entertainment

kumaran [TypeKey Profile Page]:

In the code snippet provided by Arvind, the following two lines need to be swapped in their order:

<li class="treenode">
<MTCategories>

Otherwise, only the first category has a list-item marker. The corresponding two lines closing these tags also need to be swapped.

Note from Elise: I swapped these as recommended in Arvind's code text in his comment. Thanks for the suggestion. ~Elise

Olivier Severyns:

When I click on an entry in an expanded category, the menu collapses back on the new page : is it normal ? I wish the menu for the current category would stay expanded while viewing the entry. Any suggestion ?
Thanks for this very helpful site !

Elise - I use both MT and TypePad Pro (which is similar to MT in tags and such), and I want to say that your site is incredibly helpful.

I just implemented the technique above on my TypePad sites on the categories to save space, but also in a couple of other areas. I put some Bloglines script in there to hide my burgeoning blogroll and I've used it in my comments section.

I had long wanted to have comments more accessible to readers. This was the solution. I created the list just as above, but inserted the comment tag and put it at the bottom of my entries section. There may be an easier way, but this worked for me.

Thanks very much!

Thank you for a great web site! I added this to a site I am helping a friend with and I somehow it does not work with the archives. Also, does anyone know how to make this work for a list of subcategories? So categories --> subcat --> list of articles?
Thanks a bunch...and btw - the site I am working on is www.blogbridge.com/index2...an open source project.

sk:

I just want to have a sub-category collapsible, i.e sub-sub-category menu items expand/collapse. I do not want to list entries at all in the collapsible menu. Would anyone know the code for that?

Thanks and thanks elise for a wonderful site.

I found a website called, Quirks Mode and he's got a script that enables you to add a deeper level to the collapsible menu. Visit his website at www.quirksmode.org and navigate to:

Javascript > DHTML > Navigation:display

Might require some understanding of JScript to be implemented though.

Cheers. :)

paul:

I have created a collapsing nav menu using CSS, this is my first time trying such a task and was wondering how I can keep the nav menu open when I proceed to the linked page. I read your comments above and cannot seem to apply them to my code.
Here is my code, any suggestions on how to do this would be greatly appreciated!

style type="text/css" media="screen"

body {
margin: 0;
padding: 0;
background color: #d1daec;
font-family: helvetica;
font-size: 0.6em;
font-weight: bold;
}
#dl, dt, dd, ul, li {
margin: 0;
padding: 0;
list-style-type: none;
white-space: normal;
}
#menu {
position: static; /* Menu position that can be changed at will */
top: 105;
left: 2;
}
#menu {
width: 12em;
}
#menu dt {
cursor: pointer;
margin: 0;

line-height: 15px;
text-align: left;
font-weight: bold;
border: #d1daec;
background: #d1daec;
}
#menu dd {
border: #d1daec;
}
#menu li {
text-align: left;
background: #ffffff;
}
#menu li a, #menu dt a {
color: #d1daec;
text-decoration: none;
display: block;
border: 0 none;
height: 100%;
}
#menu dt a:hover {
background: #ffffff;
}
#menu li a:hover {
background: #d1daec;
}

/style

script type="text/javascript"

window.onload=show;
function show(id) {
var d = document.getElementById(id);
for (var i = 1; i

Perry:

I can't get Arvinds solution to work in MT 3.2
Is it not possible to do this in the alpha-part of the MT-site? In the left sidebar?

Has anyone done anything to get subcategories working in this manner?

Implementing Arvind's suggestion, above, I've got all of my categories and subcategories in one big list...clicking on any of them gives me a list of the entries in them.

What I thought should happen would be that you'd click on a category, and then get a list of any entries for just that category, and then the list of subcategories. Clicking on the subcategories would then give you the entries for the subcategories and then more subcategories (if you're nesting that far).

i.e.

*Parties
*Visits
*Misc

Click Parties

*Parties
*Birthday
*Holiday
Dad's Retirement (this would be an entry under "Parties, but not under the subcategories)
*Visits
*Misc

Click on Birthday
*Parties
*Birthday
Dad
Mom
Son
*Holiday
Dad's Retirement
*Visits
*Misc

Etc.

Has any work been done in this area?

Thanks.

Chris:

Why doesn't this code work? It's driving nuts. The script is properly linked on the page but this code still doesn't work.

<div class="category-menu">
<ul class="treemenu">
<li class="treenode">
<MTTopLevelCategories>
<a href=""><MTCategoryLabel></a>
<ul>
<MTSubCategories>
<li>
<MTIfNonZero tag="MTCategoryCount">
<a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
<MTElse>
<$MTCategoryLabel$>
</MTElse>
</MTIfNonZero>
</li>
</MTSubCategories>
</ul>
</MTTopLevelCategories>
</li>
</ul>
</div>

Thanks for any help.

Hi all,

I am completely winging it when I implement code like this. It's all trial and error. Sorry I can't be of more help. You might consult someone who knows something about javascript and CSS.

Regarding the stray bullet point, I finally figured that out. Needed to add this in the CSS:

.treemenu LI {
display : inline;
}

This code still works fine for me with MT3.3 by the way.

Jim:

FYI - I had problems getting this to work. After much hair-pulling, I tracked it down to the example above:

(3rd example under Step #3)

<a href=""><h2><MTCategoryLabel></a></h2>

Note the "</a>" is nested inside the closing "</h2>" - it needs to be outside for the script to work. Like so:

<a href=""><h2><MTCategoryLabel></h2></a>

At least, that fixed my problem.

Is there some way this method could work with monthly archives?

Hi Jim,
Oh, I hate little bugs like that. Thanks for the catch.

Hi Joanna,
I don't know of any method. I don't recommend monthly archives (too much rebuilding) and wouldn't recommend using something like this with them.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)