★ wanayoo — archive 1999 http://developer.netscape.com/docs/technote/dynhtml/collapse/index.htmlNouvelle recherche | Portail wanayoo


Click Here!

JavaScript DHTML Collapsible Lists
Organize Content Easily
By Michael Bostock
Netscape Production Engineer


If you're managing a site with a lot of content, you undoubtedly have some sort of scheme to organize that information. Futhermore, you've probably organized it into a hierarchical list. This way, users don't have to look at all of your pages to find the one page they want. On the other hand, to get to that one page, your users probably have to travel through several levels of the hierarchy tree. So while the tree organizes content, it puts more distance between the page your users want and the root. How does one fix this? Collapsible lists.

Collapsible lists have been available for a long time, but now DHTML allows for the creation of more functional and more adaptable lists. Pre-DHTML, collapsible lists (such as those by Danny Goodman) had to live in their own frame and use cookies to store the state of the list. Not so with these lists! The JavaScript DHTML Collapsible List library lets you create lists with the functionality you need for a real solution. Plus, these lists can be stylized to fit even the most far-out Web sites.


CONTENTS


SOME EXAMPLES


HOW TO USE THE LIBRARY

To use the library, you first have to include it. Start by downloading the library to your local hard drive. Right-click on list.js and select "Save Link As...." Do the same thing with true.gif and false.gif. These two images are the arrows which show up next to sublists. Next, you'll probably want to add a function that is called when the page loads. This way, the list appears when the page loads. (Of course, if you want to, you can load the list at a later time.) The top of your HTML document should look something like this:

<HEAD>
<SCRIPT LANGUAGE="JavaScript1.2" SRC="/old?u=http%3A%2F%2Fdeveloper.netscape.com%2Fdocs%2Ftechnote%2Fdynhtml%2Fcollapse%2Flist.js&y=1999"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
function init() {

}
</SCRIPT>
</HEAD>
<BODY ONLOAD="init();">

The "ONLOAD" attribute in the <BODY> tag will call the init() function when the page loads. You then have to write some code inside init() to actually create the list. Start by creating a new List object:

var width = 350, height = 22;
myList = new List(true, width, height, "#CCCCCC");

The first argument is a boolean that specifies whether the list is initially visible. The second argument specifies the width, the third the height (both in pixels). The fourth argument is the background color of the list. If you don't specify a background color, the list will be transparent.

Next we add items:

myList.addItem("This is an item!");

The argument to addItem() is a string. This string can be plain text (as above) or a string of HTML. You can include a link, an image, practically anything. Items will appear in the list in the order they are added from the top down.

Sublists

Of course, creating a list with only one level isn't collapsible. To make a collapsible list, we need multiple levels. This means that we need to create sublists. These are the lists that show up when we expand the list, and they hide when we collapse the list. To make a sublist, first create a new List object:

subList = new List(false, width, height, "#CCCCCC");
subList.addItem("This is a sub item!");

Now we simply add that to the main list.

myList.addList(subList, "Some sub-items:");

Now a new item will appear on the root level (part of myList) with an arrow next to it. Click on the arrow, and the subList will show up. By specifying which sublists are initially visible (the first argument to the List object constructor), you determine how the list looks when it initially loads. When you're adding sublists, you can create as many levels as you want (within reason). Adding new sublists to existing sublists using the same method as described above. (Create a new List object, add a couple items to it, and then call addList() from the list you want to contain the sublist.)

When you're done adding items and sublists, you have to build the list:

myList.build(100,20);

Here "100" refers to the x coordinate of the list, and "20" to the y coordinate. Note that you only have to build the outermost (parent) list. So, no matter how many sublists you have, you should only call build() once on the outermost list.

Tip

When building your list, make sure that the window is big enough to fit the list with every sublist completely expanded. If it won't fit on the screen, you can add HTML spacers into the BODY of your document so that the user can scroll down. An easy way to do this is to add an empty <DIV> tag, like so:

<STYLE TYPE="text/css">
#spacer { position: absolute; height: 800; }
</STYLE>
</HEAD>
<BODY ONLOAD="init();">
<DIV ID="spacer"></DIV>


CROSS-BROWSER LISTS

Internet Explorer cannot make layers dynamically. Therefore, you have to make the layers manually. To do this, go to the builder page. This will automatically make the HTML code you need to get your list working. You need to specify how many items total are in your list. Then, paste the generated code into your HTML document, and voilà! - cross-browser lists. Note: If you're putting your list inside a parent layer, make sure that the <DIV> tags created by the builder are also put inside that parent layer.


ADDITIONAL FUNCTIONALITY

There's quite a range of additional functionality built-in to the List object that lets you create lists in a wide range of styles. You've seen already that you can specify background colors for lists. This means that each sublist can have a different color, allowing you to visually differentiate content in your list. In fact, you have control over the background colors of every individual element in the list. To specify a unique color for an individual list item, use an additional argument in the addList() or addItem() functions. For example,

myList.addItem("I am yellow!", "#FFFF00");

would create an item that is yellow, regardless of the color of the parent list. (The color of the parent list was specified in the List object constructor.)

If you wanted to apply a text styling to the list as a whole, you can use the setFont() function. For example:

myList.setFont("<FONT COLOR='white' SIZE=-1>","</FONT>");

This would make every item in the list white and one size smaller. You could put the HTML styling into the addItem() or addList() text, but this lets you apply fonts over the list as a whole.

To further differentiate content, you can also specify varying widths and heights of your sublists in the List object constructor. For example, suppose you wanted a list of people with their pictures. The outer list could just have their names and have a height of 22 pixels. The sublist which contained the pictures could have a height of 70 to show the pictures.

You can also specify a parent layer to contain the list. This way, you could have control over the list as a whole. For example, if the parent layer was draggable, the list would be draggable. There are lots of possibilities. In the DevEdge Online example, the parent layer was made "drifting" so that when the user scrolls, the list would move. Specify a parent layer using the parLayer attribute:

myList.parLayer = document.layers.container;

You can also specify the amount of indentation for the list. Do this using the setIndent() function:

myList.setIndent(20);

If you specify an indent of 0, all items will be on the same level, though there will still be space reserved for the arrow on the left side. To eliminate this space, you can use an indent of -1. Here is an example showing the difference between different indents. You should specify the indent for each sublist, as indentation is not inherited from the parent list. To get the style you want, it's best to just play around with it for a while.

Finally, there is also event-level control. If you specify the "onexpand" attribute of the List object with a function, that function will be called when the list is expanded. Inside the function that is called (which you must define), "this" will refer to the list that was expanded. The function will also be passed the id of the list that was expanded. Each list has a unique ID, starting at 0 and going up by one with each new List object. Here's an example of how to use this feature: first, set the attribute:

myList.onexpand = colorize;

Now define the colorize() function:

function colorize(id) {
  if(this.bgColor != "red") {
    this.bgColor = "red";
    this.needsUpdate = true;
  }
}

Note that you have to set the "needsUpdate" attribute to true if you want the list to actually be updated. This is so that the expand process isn't slowed down at all if you don't want to update. You can do a great deal of things inside the colorize() function. You can change the height of the list, or even add new items or sublists! (If you add new items or sublists, or if you change the height, you'll also want to set the "needsRewrite" attribute to true as well.) This feature was designed to give you added styling and functionality, but it's up to you to be creative in how to use it. Feel free to experiment! (Here's an example I came up with.)

Note for techies: The function associated with onexpand will be called before the list is actually expanded so that changes you make (e.g., bgColor) will show up when the list is expanded. If you want to gather information about the list after it has been exanded (for example, the new height), you should use the "postexpand" property.

In my example, I also took advantage of the fact that you can access a sublist's parent through the "parent" attribute, that the "id" attribute of the list reflects its ID, and that you can access all the lists on a page through the "document.lists" array.


ADDITIONAL INFORMATION

These utilities require DHTML and so they only work on 4.0+ browsers.

To speed the initial loading time of the lists, sublists are only loaded as they become visible. Thus, no matter how many nested lists you add to the main list, the initial loading time stays the same. Sublists that were not initially visible are loaded when the user opens them for the first time.

When you add items to the list, you are not merely passing text - you are passing a string of HTML. Consquently, you can pass in hyperlinks, images, or whatever you desire. For example l.addItem("<A HREF='/old?u=http%3A%2F%2Fdeveloper.netscape.com%2Fdocs%2Ftechnote%2Fdynhtml%2Fcollapse%2Findex.html&y=1999'>Main Page</A>") will add an item which is a link to the "Main Page."

In Navigator 4.0, JavaScript positioned content loses shaped when the window is resized. To fix this problem, first download the library called resize.js by right-clicking on the link and choosing "Save Target As...". Next, add the following line of code to your document:

<SCRIPT SRC="/old?u=http%3A%2F%2Fdeveloper.netscape.com%2Fdocs%2Ftechnote%2Fdynhtml%2Fcollapse%2FJavaScript1.2&y=1999" SRC="/old?u=http%3A%2F%2Fdeveloper.netscape.com%2Fdocs%2Ftechnote%2Fdynhtml%2Fcollapse%2Fresize.js&y=1999"></SCRIPT>

This will reload the positioned content automatically.


REFERENCES


ABOUT THE AUTHOR

Michael Bostock is a class of 2000 student at Princeton University in New Jersey. He is a Computer Science major in the Engineering school. Over the summer, when he's not interning with Netscape Communications Corporation, he spends his time wondering about the weather in Oak Ridge, TN.



For the latest technical information on Sun-Netscape Alliance products, go to: http://developer.iplanet.com

For more Internet development resources, try Netscape TechSearch.


Copyright © 1999 Netscape Communications Corporation.
This site powered by: Netscape Enterprise Server and Netscape Compass Server.