// JavaScript Document

// **********************************************************
// this is a simple class that we will be using to create a menu system based off unordered lists
function menuItem ( elementId, oneSubmenu, detachSubmenu )
	{
	// this is a method that is called to hide / show the sub-menu that is associated with this object
	this.toggle = function ( closure )
		{
		// if the function is called with a parameter then we return a closure for use in event handlers
		if( closure )
			{
			return (function() {thisObj.toggle();});		
			}
			
		// if the oneSubmenu option is set then we need to go through and hide all the other submenus
		if( this.oneSubmenu )
			{
			if( walden_vertical_menu_array[0] )
				{
				for( subMenu = 1; subMenu < walden_vertical_menu_array.length; subMenu++ )
					{
					if( subMenu == this.registrationNumber )
						{
						continue;	
						}
					walden_vertical_menu_array[subMenu]();
					}
				}
			}
			
		// tell the other menu objects that at least one subMenu is visible
		walden_vertical_menu_array[0] = true;
		
		// check to see if the jQuery object is available and if it is then we will use it's animation
		// effects for displaying and hiding the submenu
		if( typeof( jQuery ) == "function" )
			{
			if( this.shown )
				{
				jQuery( this.submenu ).fadeOut("slow");
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "false" );
				this.element.classname = this.oldclass;
				}
			else
				{
				jQuery( this.submenu ).fadeIn("slow");	
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "true" );
				this.element.classname = this.oldclass + " submenu_active";
				}	
			}
		// if jQuery is not available then we will fall back on instantly hiding or displaying the submenu
		// via manipulation of the submenu CSS properties
		else
			{
			if( this.shown )
				{
				this.submenu.style.display = "none";
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "false" );
				this.element.classname = this.oldclass;
				}
			else
				{
				this.submenu.style.display = "block";	
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "true" );
				this.element.classname = this.oldclass + " submenu_active";
				}
			}
		}
		
	// this method is simply called to hide this objects submenu
	this.hide = function ( closure )
		{
		// if the function is called with a parameter then we return a closure for use in event handlers
		if( closure )
			{
			return (function() {thisObj.hide();});		
			}
			
		if( typeof( jQuery ) == "function" )
			{
			if( this.shown )
				{
				jQuery( this.submenu ).fadeOut("slow");
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "false" );
				this.element.classname = this.oldclass;
				}
			}
		else
			{
			if( this.shown )
				{
				this.submenu.style.display = "none";
				this.shown = !this.shown;
				this.createCookie ( this.element.id, "false" );
				this.element.classname = this.oldclass;
				}
			}
		}
		
	// this method is designed to be assigned as an event handler to cancel event bubbling
	// this is used to stop the submenus from triggering their parents element's onclick event handlers
	// when they are clicked
	this.cancelBubble = function ( closure, e )
		{
		if( closure )
			{
			return (function(e) {thisObj.cancelBubble(false, e);});		
			}
		if (!e) var e = window.event;
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();		
		}
		
	// some functions to get and set cookie values
	// first a function to create the cookies
	this.createCookie = function (name,value,days) 
		{
		if (days) 
			{
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
			}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
		}

	// then a function to read previously created cookies
	this.readCookie = function (name) 
		{
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) 
			{
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
			}
		return null;
		}
		
	// assign a static instance of THIS for use later in providing closures for event handlers
	var thisObj = this;
	// declare the variable that will hold the status of this objects menu
	this.shown = true;
	// if the oneSubmenu property was supplied then we need to assign it to an internal property so that 
	// the methods will have access to it
	this.oneSubmenu = oneSubmenu;
	// if the detachSubmenu property was supplied the we need to assign it to an internal property so that
	// the methods will have access to it
	this.detachSubmenu = detachSubmenu;

	
	// find the submenu that is attached to this object's LI element and assign it to a variable
	this.element = document.getElementById( elementId );
	if( typeof( this.element ) == "object" )
		{
		for( x = 0, no_children = this.element.childNodes.length; x < no_children; x++ )
			{
			if( this.element.childNodes[x].tagName && ( this.element.childNodes[x].tagName == "UL" ))
				{
				this.submenu = this.element.childNodes[x];
				}
			}
			
		// if detachSubmenu = true then we need to move the submenu so that it is a child of the element containing 
		// the menu rather than a child of the LI element
		if( this.detachSubmenu )
			{
			this.parent = this.element.parentNode.parentNode;
			var tempElement = "";
			tempElement = this.submenu;
			this.element.removeChild( this.submenu );
			this.parent.appendChild( tempElement );
			this.submenu = tempElement;
			this.submenu.className = "is_submenu";
			}
			
		// this next part deals with registering the object so that we can display only one submenu
		// at a time if we wish
	
		// first check to see if any objects of this type have already been registered
		if( typeof(walden_vertical_menu_array) != "undefined" )
			{
			// and if so then we need to register this object's toggle() method
			this.registrationNumber = walden_vertical_menu_array.length;
			walden_vertical_menu_array[ walden_vertical_menu_array.length ] = this.hide( true );
			}
		else
			{
			// if no objects have been registered yet then we need to create the registration array and register this
			// object with it
			walden_vertical_menu_array = new Array();
			walden_vertical_menu_array[0] = false;
			walden_vertical_menu_array[1] = this.hide( true );
			this.registrationNumber = 1;
			}
			
		// make note of the class attribute of the the element containing the submenu
		this.oldclass = this.element.classname;
		// assign the necessary event handlers to the parent menu element	
		this.element.onclick = this.toggle( true );
		// and also to the child submenu
		this.submenu.onclick = this.cancelBubble( true );
		
		// check whether a cookie has been set for this menu item
		this.cookie = this.readCookie ( this.element.id );
		// if not then create a cookie that says that the menu item is close
		if( this.cookie == null )
			{
			this.shown = false;
			this.submenu.style.display = "none";
			this.createCookie ( this.element.id, "false" );
			}
		// if there is a cookie for the menuItem then restore the menuItem to it's previous state
		else
			{
			if( this.cookie == "false" )
				{
				this.shown = false;
				this.submenu.style.display = "none";	
				}
			else
				{
				walden_vertical_menu_array[0] = true;
				this.element.classname = this.oldclass + " submenu_active";
				}
			}
		}
		
	
	}
	
// **********************************************************
// this function hides all open submenus
function hideAll ()
	{
	if( walden_vertical_menu_array[0] )
		{
		for( subMenu = 1; subMenu < walden_vertical_menu_array.length; subMenu++ )
			{
			walden_vertical_menu_array[subMenu]();
			}
		}	
	}
	
	
// **********************************************************
function waldenMenuInit () 
	{
	// first grab any list items that have been marked with the class has_submenu
	menuItems = jQuery(".has_submenu");
	menuArray = new Array();
	for( var x = 0, menuLength = menuItems.length; x < menuLength; x++ )
		{
		menuArray[x] = new menuItem( menuItems[x].id, true, true);
		}
	// now grab any menu items marked with the class no_submenu. When clicked on these need to hide all the other submenus
	noSubmenus = jQuery( ".no_submenu" );
	for( var x = 0 , submenuLength = noSubmenus.length; x < submenuLength; x++ )
		{
		noSubmenus[x].onclick = hideAll;
		}
	
	
	}


// initialize the menu system
jQuery(document).ready( waldenMenuInit );


