September 10, 2004

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></a></h2>
<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 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.)

Links:
Collapsable / expandable menu items arranged alphabetically - a combo PHP javascript script from Maddy in the forums


Has this tutorial been helpful? Please consider linking to Learning Movable Type at http://learningmovabletype.com/ . Thanks!

Posted by Elise Bauer on September 10, 2004 to HTML and Javascript
Comments(25) | Email to a friend | Printer-friendly version


Trackback

If you would like to send a trackback
please use the following URL: http://learningmovabletype.com/cgi-bin/mt32/mt-tb.cgi/331

» SubCats and Contents from Movalog
Following on from Elise's Expandable List Menus tutorial, this is a way to incorporate Sub Category relationships in your Table of Contents or other similar pages.......[read more]

Tracked: September 14, 2004 07:47 AM

Comments

Nice work, but it doesn't seem to work in Firefox 0.9, the submenu displays then closes back up. Is it IE-centric?

Hi Kevin, I've got it working in Mac Safari, Mac IE 5.5, and Mac FireFox 0.9.3. Do you have the latest version of Firefox?

Kevin, I'll bet you've got the Tabbrowser Extension running on firefox. If so, try disabling it, closing firefox, and then launching it again. Tabbrowser Extension made my life better in all kinds of ways, but I stopped using it because it breaks a lot of javascripts. For what it's worth, I'm using firefox 0.9.3 on XPSP2 and not having any problems with the expanding menus.

Works fine in FireFox 1.0 Preview Release for me under Windows XP SP 2 without Tabbrowser.

TBE is evil it causes loads of things to malfunction. This is an interesting script and i had thought of implementing it when I made my table of contents for Movalog - then decided against it. Reason ? Well if you rely on this javascript you assume people have that enabled etc. I'd rather people could just browse through the list without having to do any extra clicking.

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.

Lance your right. TBE is installed. I'll disable it and report back.

Bingo, TBE disabled and all is well now. Sorry Elise, false alarm regarding the 0.92 version of Firefox.

Thanks Lance for pointing me to the TBE problem.

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!

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

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

ex//
Entertainment

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

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!

This code doesn't produce valid xhtml, but it works beautifully. Any suggestions?

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.

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. :)

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

I really would like to use this script but do you know of a way for me to just display the 5 most recent entries in the category list that drops down?

If you do not know, I will play around with it and see what I can come up with.

I'm using this script on my WordPress blog to parse a feed of my del.icio.us bookmarks. It's working well but I'm getting a single bullet point at the top of the page from the li class=treenode part.

Any suggestions for how to remove it?

I'm using the script at http://blog.zoctagon.net/my-bookmarks/

Hi Kevin,
I have the same problem going on with my Table of Contents page. There must be some why to deal with this using divs and CSS, but I don't have the time to figure it out. If you or anyone else does figure it out, please let me know!

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.

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.


Post a comment

(Before posting a comment please see the Comments and Trackbacks Policy. Do you need help troubleshooting your weblog? Please post questions and requests for support at the MT Support Forums. Thanks!)




Remember Me?

(you may use HTML tags for style)

Email to a friend

Email this article to:


Your email address:


Message (optional):