This is version . It is not the current version, and thus it cannot be edited.
[Back to current version]   [Restore this version]

Turn ordinary lists into collapsable trees by enclosing them inside a tag. When clicking a list item bullet, you can expand or collapse nested list items.
I use it for the LeftMenu and long hierarchical trees of text. This feature is javascript driven.
--DF, Jun 2004

Usage#

Enclose the collapsable list in a tag.

%%collapse
* Europe
** France
*** Paris
*** Nice
** Belgium
*** Brussel
*** Peulis
* Australia
%%

Here is the result:

  • Europe
    • France
      • Paris
      • Nice
    • Belgium
      • Brussel
      • Peulis
  • Australia

How does it work#

After loading a page, a set of javascript routines are triggered when they encounter the <div class="collapse"> element. All nested lists get additional css styles and expand/collapse bullets are inserted.

The collapse status of a list (which part of the list hierarchy is visisble or hidden) is stored in a cookie. So it can be remembered in case you would visit some other pages in between.

What you need to do:

  • put some javascript to parse the collable list when loading the page [1]
  • put some .css code in template/<YourWikiTemplate>/jspwiki.css [2]

[#1] Collapse Javascript support routines


// Convert blocks with %%collapse to dynamic collapsable lists
// Remember collapse status in a coockie
//
var clpsCookie    = null;
var previousLI    = null;

function Cookie(name)
{
  this.name   = name;
  this.pos    = clpsCookie.length;
  this.cookie = "";
  this.index  = 0;
    
  var re = new RegExp( "clps" + name + "=([-+e]*)\." );
  if ( re.exec(document.cookie) )  this.cookie = RegExp.$1; 
  
  this.isNew = ( this.cookie.length == 0) ;
}


function putCOOKIE(name,value) 
{
  document.cookie = "clps" + name + "=" + value + "." ;
}


function toggleLI(id)
{
  var re = /clps(\d+)\.(\d+)/;          if (!re.exec(id)) return; 
  var cookie = clpsCookie[RegExp.$1];   if (!cookie) return;

  var i = RegExp.$2 ;
  var s = cookie.cookie ;
  var c = s.charAt(i-1) ;

  c = hideLI(id, c) ;
  cookie.cookie = s.substring(0,i-1) + c + s.substring(i,s.length) ;
  putCOOKIE(cookie.name, cookie.cookie);
}


function hideLI (id,  hide)
{
  var nodeUL = document.getElementById(id);     if (!nodeUL)  return;
  var nodeA  = document.getElementById("a"+id); if (!nodeA)   return;

  if (hide == '+') 
  { 
    nodeUL.style.display = "none"; 
    nodeA.setAttribute ("title", "Click to expand");
    return ('-');
  } 
  if (hide == '-') 
  { 
    nodeUL.style.display = "";
    nodeA.setAttribute ("title", "Click to collapse");
    return('+');
  } 
}


// validateCollapse is called after loading the page
// look for a DIV with a %%collapse marker
function validateCollapse()
{
  if (!document.createElement) return;

  clpsCookie = new Array();

  var re = /\?page=(\w+)/ ;
  var pageName = "";
  if (re.exec(document.location))  pageName = RegExp.$1;
  
  validateCollapsePage( "jspwiki_leftmenu",       "LeftMenu",       0);   
  validateCollapsePage( "jspwiki_leftmenufooter", "LeftMenuFooter", 1);   
  validateCollapsePage( "jspwiki_pagecontent",    pageName,         2);   
}


function validateCollapsePage(pageId, pageName, cookieIndex)
{
  if (pageName == "") return;

  var page = document.getElementById(pageId);   
  if (!page) return; 

  clpsCookie[cookieIndex] = new Cookie(pageName);

  // find a <div class="collapse"> element
  var divArr = page.getElementsByTagName("div");
  if (! divArr) return; 

  for (i=0; i<divArr.length; i++) 
  {
    if ( divArr[i].className == "collapse" )
    {
      //alert("collapse found in " + pageId);
      previousLI =  null;
      validateCollapseNode(divArr[i], clpsCookie[cookieIndex]);   
    } 
  }  
}


function validateCollapseNode(node, cookie)
{
  if ( (node.nodeName == "UL") || (node.nodeName == "OL") )
  {
    var hide = validateLI('ULOL',cookie);
    var id   = "clps" + cookie.pos + "." + cookie.index;

    if (previousLI)
    {
      var nodeAnchor = document.createElement("a"); 
      nodeAnchor.setAttribute ("id", "a"+id); 
      nodeAnchor.setAttribute ("href", "javascript:toggleLI('" + id +  "')" );
      nodeAnchor.className = "clpsBullet";
      nodeAnchor.innerHTML = "&raquo;" ;

      previousLI.className = "clpsLI";

      if (previousLI.hasChildNodes) 
            { previousLI.insertBefore(nodeAnchor, previousLI.childNodes[0]); }
      else  { previousLI.appendChild(nodeAnchor);                            }

      node.setAttribute ("id", id); 
      if (hide == '-')  hideLI(id,'+'); 
  
      previousLI = null;
    }
  }

  if ( node.nodeName == "LI")  previousLI = node;
  
  if (node.hasChildNodes) 
  {
    for (var i=0; i<node.childNodes.length; i++) 
    { 
      validateCollapseNode(node.childNodes[i],cookie);
    }
  }

  if ( (node.nodeName == "UL") || (node.nodeName == "OL"))  // closure of UL OL
  {
    var endULOL = validateLI('eULOL',cookie);
    previousLI = null;
  }

}


// validate LI from page against LI from cookie
// - return expanded '+' or collapsed '-' state for UL and OL
function validateLI(node,cookie)
{
  cookie.index++;
  if (! cookie.isNew)
  {
    var t = cookie.cookie.charAt(cookie.index-1);
    if (node == 'ULOL'  && t == '+') return('+');
    if (node == 'ULOL'  && t == '-') return('-');
    if (node == 'eULOL' && t == 'e') return('e');  
   
    //alert('mismatch between cookie and doc ul|ol -- continue as if new cookie:');
    cookie.cookie=cookie.cookie.substring(0,cookie.index-1);
    cookie.isNew=true;
  }

  // new cookies
  if (node == 'ULOL')  { cookie.cookie+='+'; return('+'); } ;
  if (node == 'eULOL') { cookie.cookie+='e'; return('e'); } ;
  
}

In the default jspwiki template, the window onload function is defined in search_highlight.js,
You'll need to extend it with a call to the validateCollapse function.

function runOnLoad 
{
  googleSearchHighlight();
  validateCollapse();
}
window.onload = runOnLoad;

[#2] TOC Stylesheet: add this to template/<YourWikiTemplate>/jspwiki.css


/* collapsable list items - see jspwiki.js */   
/* turn off automatic bullets              */
/* div.collapse                            */
/* ul                                      */
/*  li                                     */
/*  li.clpsLI a.clpsBullet                 */
/*  ul                                     */
/*    li                                   */
/*                                         */

ul
   { margin-left  :  0;
     margin-top   :  0px; /* ie */
     margin-bottom:  0px; /* ie */
     padding-left :  1.5em;
   }

.collapse ul ,
.collapse ol 
   { list-style:  disc;
   }
     
/* collapsable li bullets in front of sub-ul or sub-ol */
li.clpsLI
   { list-style:  none;
     position  :  relative;
   }

a.clpsBullet
   { position       :  absolute;
     left           :  -1em;  /* relative to the containing LI */     
     text-decoration:  none;
     font-weight    :  bold;
   }

/* ie mac5 hack \*/
li.clpsLI a.clpsBullet
   { left:  -1.5em;
   }

a.clpsBullet:hover
   { background:  #FF9933;
     color     :  white;
   }

Example#

Back to BrushedTemplate

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
jpg
brushed-collapse.jpg 5.8 kB 1 24-Oct-2005 23:00 DirkFrederickx
jpg
vanilla-collapse.jpg 17.4 kB 1 24-Oct-2005 23:00 DirkFrederickx
jpg
vanilla-collapsed.jpg 11.2 kB 1 24-Oct-2005 23:00 DirkFrederickx
« This particular version was published on 15-Jun-2004 00:05 by DirkFrederickx.