JavaScript Collapsible Lists

JavaScript and DHTML can be used to make collapsible and expandable HTML lists that degrade cleanly (that is, are still usable for visitors who don’t have JavaScript-enabled web browsers). You can see an example in the JavaScript Collapsible Lists Demonstration.

The code

Add the code shown below to the head section of the document. You will need to change the values of CLOSED_IMAGE and OPEN_IMAGE to the names of the image files you want to use as toggle images in the collapsible lists (visitors click on the closed image when the sublists are closed to expand them, and the open image when sublists are open to collapse them).

<script type="text/javascript">

/* CLOSED_IMAGE - the image to be displayed when the sublists are closed
 * OPEN_IMAGE   - the image to be displayed when the sublists are opened
 */
CLOSED_IMAGE='plus.png';
OPEN_IMAGE='minus.png';

/* makeCollapsible - makes a list have collapsible sublists
 * 
 * listElement - the element representing the list to make collapsible
 */
function makeCollapsible(listElement){

  // removed list item bullets and the sapce they occupy
  listElement.style.listStyle='none';
  listElement.style.marginLeft='0';
  listElement.style.paddingLeft='0';

  // loop over all child elements of the list
  var child=listElement.firstChild;
  while (child!=null){

    // only process li elements (and not text elements)
    if (child.nodeType==1){

      // build a list of child ol and ul elements and hide them
      var list=new Array();
      var grandchild=child.firstChild;
      while (grandchild!=null){
        if (grandchild.tagName=='OL' || grandchild.tagName=='UL'){
          grandchild.style.display='none';
          list.push(grandchild);
        }
        grandchild=grandchild.nextSibling;
      }

      // add toggle buttons
      var node=document.createElement('img');
      node.setAttribute('src',CLOSED_IMAGE);
      node.setAttribute('class','collapsibleClosed');
      node.onclick=createToggleFunction(node,list);
      child.insertBefore(node,child.firstChild);

    }

    child=child.nextSibling;
  }

}

/* createToggleFunction - returns a function that toggles the sublist display
 * 
 * toggleElement  - the element representing the toggle gadget
 * sublistElement - an array of elements representing the sublists that should
 *                  be opened or closed when the toggle gadget is clicked
 */
function createToggleFunction(toggleElement,sublistElements){

  return function(){

    // toggle status of toggle gadget
    if (toggleElement.getAttribute('class')=='collapsibleClosed'){
      toggleElement.setAttribute('class','collapsibleOpen');
      toggleElement.setAttribute('src',OPEN_IMAGE);
    }else{
      toggleElement.setAttribute('class','collapsibleClosed');
      toggleElement.setAttribute('src',CLOSED_IMAGE);
    }

    // toggle display of sublists
    for (var i=0;i<sublistElements.length;i++){
      sublistElements[i].style.display=
          (sublistElements[i].style.display=='block')?'none':'block';
    }

  }

}

</script>

Next you need to set an id attribute on the list that you want to have collapsible sublists. Then just add a call to the makeCollapsible function in the body element’s onLoad attribute value. For example:

<body onLoad="makeCollapsible(document.getElementById('computers'));">
  <ul id="computers">
    <li>
      Apple
      <ul>
        <li>Apple II</li>
        <li>Macintosh</li>
        <li>PowerMac</li>
        <li>iMac</li>
      </ul>
    </li>
    <li>
      Commodore
      <ul>
        <li>PET</li>
        <li>VIC-20</li>
        <li>Commodore 64</li>
        <li>Amiga</li>
      </ul>
    </li>
  </ul>
</body>

Note that the ol and ul elements to be made collapsible must be within the li elements of their parent list.

Achieving cross-browser support for JavaScript

Writing JavaScript that works with a range of browsers is not easy, as their implementations of the standard (ECMA-262) differ. The O’Reilly book JavaScript the Definitive Guide details which JavaScript features are supported by different browsers’ implementations, and is very helpful in writing code that works in a range of web browsers.

This article was last edited on 15th March 2008. The author can be contacted using the form below.
Back to home page
Bookmark with: