
/**
 ** 200 Collapsable list items 
 **
 ** See also David Lindquist <first name><at><last name><dot><net>
 ** See: http://www.gazingus.org/html/DOM-Scripted_Lists_Revisited.html
 **
 **/
var Collapsable = new Object();

Collapsable.tmpcookie    = null;
Collapsable.cookies      = [] ;
Collapsable.cookieNames  = [] ;

Collapsable.ClassName    = "collapse";
Collapsable.ClassNameBox = "collapsebox";
Collapsable.ClassNameBody= "collapsebody";
Collapsable.OpenTip      = "Click to collapse";
Collapsable.CloseTip     = "Click to expand";
Collapsable.CollapseID   = "clps"; //prefix for unique IDs of inserted DOM nodes
Collapsable.MarkerOpen   = "O";    //cookie state chars 
Collapsable.MarkerClose  = "C"; 
Collapsable.CookiePrefix = "JSPWikiCollapse";
Collapsable.bullet           = document.createElement("div"); // template bullet node
Collapsable.bullet.className = "collapseBullet";
Collapsable.bullet.innerHTML = "";


Collapsable.onPageLoad = function()
{
  this.initialise( "favorites",   this.CookiePrefix + "Favorites" );
  this.initialise( "pagecontent", this.CookiePrefix + Wiki.getPageName() );
 }


Collapsable.initialise = function( domID, cookieName )
{
  var page  = document.getElementById( domID );  if( !page ) return;
  this.tmpcookie = document.getCookie( cookieName );
  this.cookies.push( "" ) ; //initialise new empty collapse cookie
  this.cookieNames.push( cookieName );

  var nodes;
  nodes = getElementsByClassName( page, this.ClassName ); 
  if( nodes ) 
  { 
    for( var i=0; i < nodes.length; i++)  this.collapseNode( nodes[i] );
  }
  nodes = getElementsByClassName( page, this.ClassNameBox );
  if( nodes ) 
  { 
    for( var i=0; i < nodes.length; i++)  this.collapseBox( nodes[i] );
  }  
}

Collapsable.REboxtitle = new RegExp ( "h2|h3|h4" );
Collapsable.collapseBox = function( node )
{
  var title = node.firstChild; 
  while( (title != null) && (!this.REboxtitle.test( title.nodeName.toLowerCase() )) )
  {
    title = title.nextSibling;
  }
  if( !title ) return;  
  if( !title.nextSibling ) return;
  
  var body = document.createElement( "div" );
  body.className = this.ClassNameBody;
  while( title.nextSibling ) body.appendChild( title.nextSibling );
  node.appendChild( body );    

  var bullet  = this.bullet.cloneNode(true);
  this.initBullet( bullet, body, this.MarkerOpen );
  title.appendChild( bullet );
}


// Modifies the list such that sublists canbe hidden and shown by clicking the listitem bullet
// The listitem bullet is a node inserted into the DOM tree as the first child of the 
// listitem containing the sublist.
Collapsable.collapseNode = function( node )
{
  var items = node.getElementsByTagName("li");
  for( i=0; i < items.length; i++ )
  {
    var nodeLI = items[i];
    var nodeXL = ( nodeLI.getElementsByTagName("ul")[0] || 
                   nodeLI.getElementsByTagName("ol")[0] ); 

    //dont insert bullet when LI is "empty" -- iow it has no text or no non ulol tags inside
    //eg. * a listitem
    //    *** a nested list item - intermediate level is empty
    var emptyLI = true;
    for( var n = nodeLI.firstChild; n ; n = n.nextSibling )
    {
      if((n.nodeType == 3 ) && ( n.nodeValue.trim() == "" ) ) continue; //keep searching
      if((n.nodeName == "UL") || (n.nodeName == "OL")) break; //seems like an empty li 
      emptyLI = false; 
      break;
    }
    if( emptyLI ) continue; //do not insert a bullet

    var bullet  = this.bullet.cloneNode(true);
    
    if( nodeXL )
    {
      var defaultState = (nodeXL.nodeName == "UL") ? this.MarkerOpen : this.MarkerClose ;
      this.initBullet( bullet, nodeXL, defaultState );
    }
    nodeLI.insertBefore( bullet, nodeLI.firstChild ); 
  }
}


// initialise bullet according to parser settings
Collapsable.initBullet = function( bullet, body, defaultState )
{
  var collapseState = this.parseCookie( defaultState ); 
  bullet.onclick = this.toggleBullet;
  bullet.id = this.CollapseID + "." + (this.cookies.length-1) + 
                                "." + (this.cookies[this.cookies.length-1].length-1);
  this.setOpenOrClose( bullet, ( collapseState == this.MarkerOpen ), body );
}

// modify dom-node according to the setToOpen flag
Collapsable.setOpenOrClose = function( bullet, setToOpen, body )
{
  bullet.innerHTML   = (setToOpen) ? ""      : "" ;
  bullet.className   = (setToOpen) ? "collapseOpen" : "collapseClose" ;
  bullet.title       = (setToOpen) ? this.OpenTip   : this.CloseTip ;
  body.style.display = (setToOpen) ? "block"        : "none" ;
}
 
 
// parse cookie 
// this.tmpcookie  contains cookie being validated agains the document
// this.cookies.last contains actual cookie being constructed
//    this cookie is stored in the cookies[] 
//    and only persisted when the user opens/closes something
// returns collapseState MarkerOpen, MarkerClose
Collapsable.parseCookie = function( token )
{
  var currentcookie = this.cookies[this.cookies.length-1];
  var cookieToken = token; //default value

  if( (this.tmpcookie) && (this.tmpcookie.length > currentcookie.length) )
  {
    cookieToken = this.tmpcookie.charAt( currentcookie.length );
    if(  ( (token == this.MarkerOpen) && (cookieToken == this.MarkerClose) ) 
      || ( (token == this.MarkerClose) && (cookieToken == this.MarkerOpen) ) ) //##fixed
        token = cookieToken ; 
    if( token != cookieToken )  //mismatch between tmpcookie and expected token
        this.tmpcookie = null;
  }   
  this.cookies[this.cookies.length - 1] += token; //append and save currentcookie

  return( token );    
}


// toggle bullet and update corresponding cookie
// format of ID of bullet = "collapse.<cookies-index>.<cookie-charAt>"
Collapsable.toggleBullet = function( )
{
  var ctx = Collapsable; //avoid confusion with this == clicked bullet

  var idARR  = this.id.split(".");  if( idARR.length != 3 ) return;
  var cookie = ctx.cookies[idARR[1]]; // index in cookies array

  var body;
  if( ctx.REboxtitle.test( this.parentNode.nodeName.toLowerCase() ) )
  {
    body = this.parentNode.nextSibling;
  } 
  else
  {
    body = ( this.parentNode.getElementsByTagName("ul")[0] || 
             this.parentNode.getElementsByTagName("ol")[0] ); 
  }
  if( !body ) return;

  ctx.setOpenOrClose( this, (body.style.display == "none"), body );
  
  var i = parseInt(idARR[2]); // position inside cookie
  var c = ( cookie.charAt(i) == ctx.MarkerOpen ) ? ctx.MarkerClose : ctx.MarkerOpen; 
  cookie = cookie.substring(0,i) + c + cookie.substring(i+1) ;

  document.setCookie( ctx.cookieNames[idARR[1]], cookie );
  ctx.cookies[idARR[1]] = cookie;

  return false;  
}

/*
 *  Chooses a suitable stylesheet based on browser.
 *
 * issue a document.write statement with the link to the browser specific stylesheet
 * should always be execute from direct javascript during page-load
 */
Wiki.loadBrowserSpecificCSS  = function ( baseurl, templatePath, pagename )
{
    var Op  = (navigator.appName == ("Opera")) ? true : false;
	var NS  = (navigator.userAgent.indexOf("Navigator")== -1) ? false : true;
	var Mac = (navigator.userAgent.indexOf("Safari") == -1) ? false : true;
	var IE6 = (navigator.userAgent.substr(25, 10).indexOf("MSIE 6") == -1) ? false :true;
	var IE7 = (navigator.userAgent.substr(25, 10).indexOf("MSIE 7") == -1) ? false :true;
	var sheet = "";

    if( NS )
    {
        sheet = "jspwiki_ns.css";
    }
        else if( Mac )
    {
        sheet = "jspwiki_mac.css";
    }
	else if( Op )
    {
        sheet = "jspwiki_opera.css";
    }
    	else if( IE6 )
    {
        sheet = "jspwiki_ie.css";
    }
    	else if( IE7 )
    {
        sheet = "jspwiki_ie7.css";
    }
	
    
    if( sheet != "" )
    {
        sheet = baseurl+"templates/" +templatePath + "/" + sheet;
        document.write("<link rel=\"stylesheet\" href=\""+sheet+"\" />");
	

    }

 

    this.BaseURL = baseurl;
    this.BasePath = this.BaseURL.slice( this.BaseURL.indexOf( location.host )
                                      + location.host.length, -1 );
    this.PageName = pagename;

}
