/*
 * Expanding/collapsing tree menu script
 * by Jamie Green
 * 
 * Based on Ben Boyle's expanding menu code, found at
 * <http://inspire.server101.com/js/xc/>
 */


/*
 * Constant values used to customize the menu display.
 */

// Nodes for expander/collapser controls. Use the DOM methods to create desired HTML blocks.
var selector_x = document.createElement( 'img' );
selector_x.setAttribute( 'src', 'images/tree_book_closed.gif' );
selector_x.setAttribute( 'width', '16' );
selector_x.setAttribute( 'height', '16' );
selector_x.setAttribute( 'border', '0' );
selector_x.setAttribute( 'alt', '[+]' );

var selector_c = document.createElement( 'img' );
selector_c.setAttribute( 'src', 'images/tree_book_open.gif' );
selector_c.setAttribute( 'width', '16' );
selector_c.setAttribute( 'height', '16' );
selector_c.setAttribute( 'border', '0' );
selector_c.setAttribute( 'alt', '[-]' );

var leaf_item = document.createElement( 'img' );
leaf_item.setAttribute( 'src', 'images/tree_page.gif' );
leaf_item.setAttribute( 'width', '16' );
leaf_item.setAttribute( 'height', '16' );
leaf_item.setAttribute( 'border', '0' );
leaf_item.setAttribute( 'alt', '[ ]' );

// Text to use in tooltips for expanded and collapsed menus.
// (I like mine without.)
var tooltip_x = "";
var tooltip_c = "";


/*
 * Style class definitions for linking menus to style sheets.
 */

// Suffixes to use for style of expanded and collapsed controls. To use these, create style sheets
// whose classes are named "<menuClass><suffix>". See tree_menu.css for example.
var suffix_x = "_x";
var suffix_c = "_c";
var suffix_leaf = "_leaf";

/*
 * Data for internal use.
 */

// Dictionary of "div" elements containing collapse and expand controls for each submenu. For each
// submenu, it keeps a "<submenuID><suffix_x>" and "<submenuID><suffix_c>" node containing anchors
// for switching the menus between collapsed and expanded states.
// Calculated as TreeMenuSetup calls TreeMenuMakeControl for each submenu.
var TreeControls = [];


/*
 * TreeMenuSetup
 * Called in "body" tag's OnLoad handler to set up each tree menu.
 * 
 *    menuID       ID attribute of the menu root
 * 
 * Optionally given extra arguments describing IDs of submenus to be expanded by default.
 */
function TreeMenuSetup( menuID ) {

	// Make sure the browser has adequate DOM support to do this.
	if( document.getElementById && document.createElement ) {
		
		// Get the base style class for the menu style.
		styleClass = document.getElementById( menuID ).className;
		
		// Get an array of all the "UL" elements in the menu.
		// This will get *all* of the submenus, regardless of hierarchy.
		var menuList = document.getElementById( menuID ).getElementsByTagName('ul');
		
		var thisMenuID, // ID of each submenu in the list
		thisControl, // Control to attach to the submenu
		thisParent, // Parent node used to attach the control
		i; // Iterator into the list of menu elements
		
		// Iterate through all the "UL" elements in the menu list.
		for ( i = 0; i < menuList.length; i++ )
			
			// Only turn ULs with ID attributes into menus.
			if ( thisMenuID = menuList[i].getAttribute('id') ) {
			
				// Set the class of this menu to the same as the main menu,
				// so it will be styled the same.
				menuList[i].className = styleClass;
				
				// Make nodes for each menu for its expanded and collapsed states.
				// Note that the default state for a menu is collapsed, so we
				// attach the "expand" control to the menu and set the display style.
				TreeMenuMakeControl( thisMenuID, styleClass, suffix_c );
				thisControl = TreeMenuMakeControl( thisMenuID, styleClass, suffix_x );
				menuList[i].style.display = 'none';
				
				// Attach the control to the menu's parent (li) node.
				thisParent = menuList[i].parentNode;
				thisParent.className = styleClass;
				thisParent.insertBefore( thisControl, thisParent.firstChild );
			}
		
		// Create a div to act as the "bullet" for leaf nodes.
		var theDiv = document.createElement( 'div' );
		theDiv.className = styleClass + suffix_leaf;
		theDiv.appendChild( leaf_item );
				
		// Get the list of LI elements so we can render leaf items.
		var itemList = document.getElementById( menuID ).getElementsByTagName('li');
		
		// Iterate through all the LI elements.
		for ( i = 0; i < itemList.length; i++ )
			
			// Only add leaf items to LIs which don't have submenus.
			if ( ! itemList[i].getElementsByTagName('ul').length ) {
				
				// Style this element as a leaf, and put the leaf symbol in it.
				itemList[i].className = styleClass + suffix_leaf;
				itemList[i].insertBefore( theDiv.cloneNode(true), itemList[i].firstChild );
			}

		// Expand the menus passed in the optional extra arguments.
		for ( i = 1; i < arguments.length; i++ )
			TreeMenuShow( arguments[i] );
	}
}


// Functions to show or hide menus. Called when the user clicks on a control.
function TreeMenuShow( theMenuID ) {
	TreeMenuSetControl( theMenuID, 'block', theMenuID+suffix_c, theMenuID+suffix_x );
}

function TreeMenuHide( theMenuID ) {
	TreeMenuSetControl( theMenuID, 'none', theMenuID+suffix_x, theMenuID+suffix_c );
}


// Replace the current control div to show or hide a menu.
// Called by the TreeMenuShow and TreeMenuHide functions to do the actual work.
function TreeMenuSetControl( theMenuID, displayStyle, newControl, oldControl ) {
	var theMenu = document.getElementById( theMenuID );
	theMenu.style.display = displayStyle;
	theMenu.parentNode.replaceChild( TreeControls[newControl], TreeControls[oldControl] );
	TreeControls[newControl].firstChild.focus();
}


// Make a +/- control for a submenu.
// Called by TreeMenuSetup when setting up the menu.
//   menuID       ID of the submenu we're making a control for
//   styleClass   Base menu style to be used to display the menu
//   theState     Whether to make an "expander" or "collapser" control.
function TreeMenuMakeControl( menuID, styleClass, theState ) {
     
     // Set the parts of the control to match its state.
	if( theState == suffix_x ) {
		theFunction = "TreeMenuShow";
		theSelector = selector_x;
		theToolTip = tooltip_x;
	}
	else {
		theFunction = "TreeMenuHide";
		theSelector = selector_c;
		theToolTip = tooltip_c;
	}
	
	// Make an anchor element to call the appropriate script when clicked.
	var theAnchor = document.createElement( 'a' );
	theAnchor.setAttribute( 'href', 'javascript:' + theFunction
	                                + '(\'' + menuID + '\');' );
	theAnchor.setAttribute( 'title', theToolTip );
	theAnchor.appendChild( theSelector.cloneNode(true) );

	// Make a div to hold the expanded/collapsed state info and the anchor.
	var theDiv = document.createElement( 'div' );
	theDiv.className = styleClass + theState;
	theDiv.appendChild( theAnchor );

	// Add this control div to the global dictionary.
	return TreeControls[ menuID + theState ] = theDiv;
}