dojo.require('dojo.fx');
/*
 * HOW IT WORKS:
 * 
 * We make the assumption that structure of the nested lists is:
 * <li> 
 * 	<a class="open|closed" />
 * 	<div id="collapsing_menu_???" style="display:block|none"> // id must start with "collapsing_menu_" & shown/hidden
 * 		<ul>
 * 			...more LIs
 * 		</ul>
 * 	</div>
 * </li>
 * 
 * It must all be contained within a div with the ID of "menu".
 * 
 * All div IDs must be unique.
 * 
 * Calling page instantiates JS class like this (After including Dojo in header):
 * 
 * oCollapsingMenu = new CollapsingMenu();
 * dojo.addOnLoad( function(){ oCollapsingMenu.init(); } );
 */
CollapsingMenu = function()
{
}

CollapsingMenu.prototype.init = function()
{
	this.addOnclicks(); 
	this.setTitleAttributes();
}

CollapsingMenu.prototype.addOnclicks = function()
{
	// find divs
	var divs = dojo.query( "#menu div[id^='collapsing_menu_']" ); // all divs with ID beginning "collapsing_menu_"
	
	// add onClick to preceding a tag
	dojo.forEach( 
		divs, 
		function( item )
		{
			var a_tag = dojo.query( '> a', item.parentNode )[0];
			dojo.connect( a_tag, 'onclick', this, 'doCollapse' );
			
			// console.log( a_tag );
		},
		this // scope
	)
}

CollapsingMenu.prototype.setTitleAttributes = function()
{
	dojo.query( 'li.closed > a' ).attr( 'title', 'Click to expand' );
	dojo.query( 'li.open > a' ).attr( 'title', 'Click to close' );
}

CollapsingMenu.prototype.doCollapse = function( click_event )
{
	// console.log( click_event );
	
	click_event.preventDefault();
	
	var id = dojo.attr( dojo.query( "> div[id^='collapsing_menu_']", click_event.target.parentNode )[0], 'id' );
	
	// get ancestors
	var open_items = this.getAncestorMap( id );
	
	// close open items not in map
	var divs = dojo.query( "#menu div[id^='collapsing_menu_']" ); // all divs with ID beginning "collapsing_menu_"
	dojo.forEach( 
		divs, 
		function( node )
		{
			if( dojo.indexOf( open_items, dojo.attr( node, 'id' ) ) == -1  &&
				dojo.hasClass( node.parentNode, 'open' ) )
			{
				this.closeContainerDiv( dojo.attr( node, 'id' ) );
			}
		},
		this // scope
	);
	
	// if open item clicked, close it
	if( dojo.hasClass( dojo.byId( id ).parentNode, 'open' ) )
	{
		this.closeContainerDiv( id );
		open_items = open_items.slice( 1 ); // remove this element's ID so it doesn't get opened again
	}
	
	// open those in map not already open
	dojo.forEach(
		open_items,
		function( id )
		{
			if( dojo.hasClass( dojo.byId( id ).parentNode, 'closed' ) )
			{
				this.openContainerDiv( id );
			}
		},
		this
	);
}

CollapsingMenu.prototype.getAncestorMap = function( id )
{
	// console.log( 'rebuilding ancestor map' );
	
	var map = [ id ];
	var node;
	while(true)
	{
		node = this.getFirstAncestorContainerDiv( id );
		if( node == null )
		{
			break;
		}
		else
		{
			id = dojo.attr( node, 'id' ); // prepare to loop upwards again from here
			// console.log( 'Appending id = ', id );
			map.push( id ); // append node
			// console.log( 'map now = ', map );
		}
	}
	
	//map = map.reverse(); // lowest-level items first
	
	// console.log( 'new map', map );
	
	return map;
}

CollapsingMenu.prototype.getFirstAncestorContainerDiv = function( id )
{
	var node = dojo.byId( id );
	
	// start looping upwards through DOM
	while(true)
	{
		if( node == null || node.parentNode == null )
		{
			// console.log( 'node is null - breaking' );
			node = null;
			break;
		}
		else
		{
			node = node.parentNode;
			
			// only nodes with IDs concern us
			if( dojo.attr( node, 'id' ) == null )
			{
				continue;
			}
			// reached #menu so stop
			else if( dojo.attr( node, 'id' ).match( /^menu$/i ) )
			{
				// console.log( '#menu reached. Stopping search.', node );
				node = null;
				break;
			}
			// this is a collapsing menu div so return it
			else if( node.nodeName.match( /^div$/i ) && dojo.attr( node, 'id' ).match( /^collapsing_menu_/i ) ) 
			{
				// console.log( 'found ancestor', node );
				break;
			}
			else
			{
				// console.log( 'searched', node );
			}
		}
	}
	
	// console.log( 'returning from getFirstAncestorContainerDiv', node);
	
	return node;
}

CollapsingMenu.prototype.closeContainerDiv = function( id )
{
	// console.log( 'closing', id );
	
	dojo.attr( dojo.query( "> a", dojo.byId( id ).parentNode )[0], 'title', 'Click to expand' );
	
	dojo.addClass( dojo.byId( id ).parentNode, 'closed' );
	dojo.removeClass( dojo.byId( id ).parentNode, 'open' );
	
	dojo.fx.wipeOut( {
		node: id,
        duration: 600
		} ).play();
}

CollapsingMenu.prototype.openContainerDiv = function( id )
{
	// console.log( 'opening', id );
	
	dojo.attr( dojo.query( "> a", dojo.byId( id ).parentNode )[0], 'title', 'Click to close' );
	
	dojo.addClass( dojo.byId( id ).parentNode, 'open' );
	dojo.removeClass( dojo.byId( id ).parentNode, 'closed' );
	
	dojo.fx.wipeIn( {
		node: id,
        duration: 600
		} ).play();
}