/* *
 * Tree View
 * Deo 2010.03.12
 * */
var treeview = (function() {
	var // Default add this class to span
		controlClass = 'treeview_control',
		
		// Default add this class to drop menu
		dropClass = 'treeview_dropmenu';
	
	// Init Function
	function init( settings ) {
		// Default Config
		var config = {
			// Rrequired
			id 		: '',
			
			// Open image or text
			open	: '+',
			
			// Close image or text
			close	: '-',
			
			// The controler seat
			seat	: 'front',
			
			// Close all or open all
			allClosed	: true,
			
			openClass	: 'open',
			closeClass	: 'close',
			
			// Add class to A
			linkClass	: 'treeview_link',
			
			// Add class to LI
			menuClass	: 'treeview_menu',
			
			domOpened	: '',
			
			// Callback
			// 	1. 'drop': Current drop menu
			// 	2. 'link': Link of current drop menu
			// 	3. 'menu': Previous parent node of current click element 
			// 	4. 'mapArray {'open': null, 'close': null}': Click information
			clickAfter	: function() {}
		};
		jPack.extend( config, settings );
		
		// Load the function if the object exist
		if ( $( config.id ) ) mainFunc( config );
	}
	
	// Each the DOM
	function mainFunc( config ) {
		// Default drop settings
		var dropList = $( config.id ).getElementsByTagName('ul');
		
		for( var i = 0; i < dropList.length; i ++ ) {
			var drop = dropList[ i ];
		
			// Init the drop click information
			if ( !drop._click ) { 
				drop._click = { 
					// Open Num
					open: 0, 
					
					// Close Num
					close: 0 
				}; 
			}
			
			// Default all close
			if ( config.allClosed )
				drop._closed = true;
				
			// Default all open
			else
				drop._closed = false;
			
			// Set the control
			setControl( drop, config );
		}
		// End drop settings
		
		var links = $( config.id ).getElementsByTagName('a');
		for( var i = 0; i < links.length; i ++ ) {
			var classArr = links[ i ].className.split(/\s+/);
			
			// Open Event
			checkClassName( classArr, config.openClass, function(){ 
				toOpen( links[ i ], config ); 
			});
			
			// Close Event
			checkClassName( classArr, config.closeClass, function(){ 
				toClose( links[ i ], config ); 
			});
		}
	}
	
	// Add control icon
	function setControl( drop, config ) {
		var olink = drop.parentNode.getElementsByTagName('a')[ 0 ],
		
			// Link parent - 'LI'
			menu = olink.parentNode;
		
		var control = document.createElement('span');
			
			// Bind the event to img
			control.onclick = function(){ clickEvent( this, config ); }
			
		// Add control in front of the link
		if ( config.seat == 'front' ) {
			olink.parentNode.insertBefore( control, olink );
		}
		
		// Add control in end of the link	
		if ( config.seat == 'end' ) {
			jPack.insertAfter( control, olink );
		}
		
		// Add class style
		jPack.classEvent( menu ).add( config.menuClass );
		jPack.classEvent( olink ).add( config.linkClass );
		jPack.classEvent( control ).add( controlClass );
		
		// Default set drop and control
		if ( drop._closed )
			hideFunc( control, drop, true, config );
		else 
			showFunc( control, drop, true, config );
		
		// Bind link event
		bindLinkEvent( olink, config );
	}
	
	// Bind link event if the href is not html url
	function bindLinkEvent( olink, config ) {
		var isBreakHref = jPack.breakHref( olink );
		
		if ( isBreakHref ) {
			olink.href = 'javascript:void(0);';
			olink.onclick = function(){ clickEvent( this.parentNode, config ); }
		}
	}
	
	// Check open or close
	function checkClassName( arr, curClass, func ) {
		for (var i = 0; i < arr.length; i ++)
			if ( arr[ i ] == curClass ) 
				func();
	}
	
	// Open the drop and reset control
	function toOpen( olink, config ) {
		var cur = olink;
		
		while( cur.id != config.id ) {
			// Get current link' parent
			if ( cur != undefined && cur.nodeName.toUpperCase() == 'LI' ) {
				var control = getControlBox( cur, true ), drop = cur.getElementsByTagName('ul')[ 0 ];
				
				if ( drop != undefined ) {
					showFunc( control, drop, false, config );
					
					drop._click.open ++;
				}
			}
			
			cur = cur.parentNode;
		}
	}
	
	// Close the drop
	function toClose( olink, config ) {
		var dropList = olink.parentNode.getElementsByTagName('ul');
		
		for( var i = 0; i < dropList.length; i ++ ) {
			var control = getControlBox( dropList[ i ].parentNode );
			
			hideFunc( control, dropList[ i ], false, config );
		}
	}
	
	// Control img events
	function clickEvent( obj, config ) {
		var olink = obj.nodeName.toUpperCase() == 'SPAN'?
				obj.parentNode.getElementsByTagName('a')[ 0 ]:
				obj.getElementsByTagName('a')[ 0 ],
		
			drop = olink.parentNode.getElementsByTagName('ul')[ 0 ];
		
		// Show drop menu
		if ( drop._closed ) {
			showFunc( olink, drop, false, config );
			
			drop._click.open ++;
		}
		
		// Close drop menu
		else {
			hideFunc( olink, drop, false, config );
		
			drop._click.close ++;
		}
		
		// Back information function
		config.clickAfter( 
			// Current drop menu
			drop, 
			
			// Link of current drop menu
			olink, 
			
			// Previous parent node of current click element 
			olink.parentNode, 
			
			// Click information
			// 1. open num
			// 2. close num
			drop._click
		);
	}
	
	// To show drop 
	function showFunc( control, drop, isFirst, config ) {
		setButton( control, config.close, isFirst );
		
		jPack.classEvent( control ).add( config.domOpened );
		
		drop.style.display = 'block';
		drop._closed = false;
	}
	
	// To hide drop
	function hideFunc( control, drop, isFirst, config ) {
		setButton( control, config.open, isFirst );
		
		jPack.classEvent( control ).remove( config.domOpened );
		
		drop.style.display = 'none';
		drop._closed = true;
	}
	
	// Check controler is img or text
	function setButton( control, curObj, isFirst ) {
		// Get the control box
		var cb = getControlBox( control );
		
		if ( /.?\.(jpg|gif|bmp|png)/.test( curObj ) ) {
			
			// Creat new image
			if ( isFirst == true ) 
				cb.innerHTML = '<img src="'+ curObj +'" alt="" />';
				
			// Update the image src
			else
				cb.getElementsByTagName('img')[ 0 ].src = curObj;
		} 
		
		// Just the text
		else {
			cb.innerHTML = curObj;
		}
	}
	
	function getControlBox( elem, defOpen ) {
		var elem = (defOpen === true? elem: elem.parentNode);
		var spanlist = elem.getElementsByTagName('span'), classArr = [];
		
		for ( var i = 0; i < spanlist.length; i ++ ) {
			var classArr = spanlist[ i ].className.split(/\s+/);
			
			// Check class name
			for ( var j = 0; j < classArr.length; j ++ )
				if ( classArr[ j ] == controlClass)
					return spanlist[ i ];
		}
	}
	
	function $( id ) { return document.getElementById( id ); }
	
	return {
		init: function( settings ) {
			init( settings );
		}
	};
})();
