/*
 * Drop Menu
 * Author: Deo 2009.11.27
 */
var dropmenu = DropMenu = function (eid, stylesheet) {
	if ( !window.DropMenu ) return new DropMenu();
	DropMenu.prototype.Initialize(eid, stylesheet); 
}
// For theme package
// Element's Class
DropMenu.classes = {
	menu		: 'dropMenu_ui-menu',
	mainSubMenu	: 'dropMenu_ui-main_menu',// Main Menu
	subSubMenu	: 'dropMenu_ui-subsub_menu',// Sub Level Menu
	sub			: 'dropMenu_ui-sub',// Sub List
	subSub		: 'dropMenu_ui-subsub',// Sub... List
	cur			: 'dropMenu_ui-current_link'// Current Link
};
DropMenu.prototype = {
	Initialize: function(eid, stylesheet) {
		var oMenu = document.getElementById( eid );
		if ( oMenu ) { this.classEvent(oMenu, DropMenu.classes.menu, 'add'); this.MainMenu( oMenu ); }
		else { alert('Not Found Element.'); }
	},
	MainMenu: function( oMenu ) {
		var _this = this, oMainList = oMenu.getElementsByTagName('a'), menuArr = [];
		var map = {};
		for (var i = 0; i < oMainList.length; i ++) {
			var oMain = oMainList[i];
			
			// Get the sub menu of main menu
			this.EachSubMenu(oMain, function( sub ){
				map[ i ] = sub;
				_this.classEvent(oMain, DropMenu.classes.mainSubMenu, 'add');
				
				_this.MainMenuEvent(oMain, sub); 
			});
		}
		
		// JS to check sub level
		for (var key in map) {
			var sub = map[ key ];
			this.wrap(sub, 'div');
			this.classEvent(sub, DropMenu.classes.sub, 'add');
			
			var subLevel = this.GetElemLevel(sub, oMenu);
			this.SubSub(oMainList[ key ], sub, subLevel);
		}
	},
	MainMenuEvent: function(oMain, sub) {
		var _this = this, _handle = null, _timer = 100;
		clearTimeout( _handle );
		this.addEvent(oMain, 'mouseover', function(){
			clearTimeout( _handle );
			_this.SubEvent(sub, 'show');
		});
	
		this.addEvent(oMain, 'mouseout', function(){
			_this.addEvent(sub, 'mouseover', function(){ 
				clearTimeout( _handle );
				_this.classEvent(oMain, DropMenu.classes.cur, 'add'); 
			});
			_this.addEvent(sub, 'mouseout', function(){ 
				clearTimeout( _handle ); 
				_Handle();
			});
			_Handle();
		});
		
		function _Handle() {
			_handle = setTimeout(function(){ 
				_this.classEvent(oMain, DropMenu.classes.cur, 'remove'); 
				_this.SubEvent( sub ); 
			}, _timer);
		}
	},
	SubEvent: function(sub, status) {
		if (status == 'show') { this.show( sub ); } 
		else { this.hide( sub ); }
	},
	EachSubMenu: function(elem, func) {
		var nodes = elem.parentNode.childNodes;
		for (var i = 0; i < nodes.length; i ++) {
			var node = nodes[i];
			if (node.nodeType == 1 && node.nodeName.toUpperCase() != 'A') {
				func( node );
			}
		}
	},
	SubSub: function(mainMenu, sub, level) {
		if (level > 1) { 
			this.classEvent(mainMenu, DropMenu.classes.subSubMenu, 'add'); 
			this.classEvent(sub, DropMenu.classes.subSub, 'add'); 
		}
	},
	// Find the Elem's level in parent element
	// Compared with the className
	GetElemLevel: function(elem, parent){
		var chkElem = elem, i = 0;
		while (elem != parent) {
			if (chkElem.className == elem.className) { i ++; }
			elem = elem.parentNode;
		}
		return i;
	},
	// Base Function
	// Wrap a element to elem
	wrap: function(elem, wrapTagName) {
		if (typeof elem == 'string'){
			var elem = document.getElementById( elem );
		} else {
			var oWrap = document.createElement( wrapTagName );
			elem.parentNode.appendChild( oWrap );
			oWrap.appendChild( elem );
		}
	},
	// Bind Event
	addEvent: function( obj, type, fn ) {
		if ( obj.attachEvent ) {
			obj['e'+type+fn] = fn;
			obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
			obj.attachEvent( 'on'+type, obj[type+fn] );
		} else {
			obj.addEventListener( type, fn, false );
		}
	},
	// Add ClassName or Remove
	classEvent: function(elem, className, type) {
		var arr = [], map = {}, isClass = false, 
			hasClass = elem.className.split(" ");
		for (var i = 0; i < hasClass.length; i ++) {
			if (hasClass[i] != className) { map[ hasClass[i] ] = hasClass[i]; }
			else { isClass = true; }
			arr.push( hasClass[i] );
		}
		if (type == 'add' && !isClass) 	{ arr.push( className ); }
		if (type == 'remove') 			{ arr = []; for (var key in map) { arr.push( key ); } }
		elem.className = arr.join(" ").replace(/^\s*|\s*$/g,'');
	},
	show: function( o ) {
		if (typeof o == 'string') { 
			$( o ).style.display = 'block';
			
			if ( !$( o )._showed ) {
				$( o )._showed = false;
				$( o )._height = o.offsetHeight;
			}
			this.effect( $( o ) );// Add by DEO 2010.03.11
		}
		if (typeof o == 'object') { 
			o.style.display = 'block';
			
			if ( !o._showed ) {
				o._showed = false;
				o._height = o.offsetHeight;
			}
			this.effect( o );// Add by DEO 2010.03.11
		}
	},
	hide: function( o ) {
		if (typeof o == 'string') { $( o ).style.display = 'none'; }
		if (typeof o == 'object') { o.style.display = 'none'; }
	},
	
	// Add by DEO 2010.03.11
	effect: function( obj ) {
		obj._showed = true;
		
		var _this = this;
		
		moving(0, obj._height, 30, function( s ){
			if ( s != false ) {
				var op = s / obj._height;
				obj.style.height = s + 'px';
				_this.css(obj, {'height': s + 'px', 'opacity': op});
			}
		});
		
		function moving ( start, end, time, func ) {
			var _this = this;
			var t = 0, s = start, c = end, d = time;
			
			_doing();
			function _doing() {
				clearTimeout( _doing._t );
				if ( t < d ) {
					t ++;
					
					var step = Math.ceil( tween( t, s, c, d) );
					
					if ( func && typeof func == 'function' ) func( step );
					
					_doing._t = setTimeout( _doing, 0 );
				} else {
					if ( func && typeof func == 'function' ) func( false );
				}
			}
		}
		
		function tween( t, b, c, d ) {
			return c*((t=t/d-1)*t*t*t*t + 1) + b;
		}
	},
	
	css: function(obj, options) {
		var arr = [];
		if (typeof obj == 'object' && options && typeof options == 'object') {
			if ( obj.length != undefined ) arr = obj;
			else arr.push( obj );
			
			for ( var i = 0; i < arr.length; i ++ ) {				
				for( var name in options ){
					var nameCase = name.replace(/\-(\w)/g, function($2, $1){
						return $1.toUpperCase();
					});
					
					arr[ i ].style[nameCase] = options[name];
					if( document.all && name == 'opacity' )
						arr[ i ].style.filter = 'alpha(opacity='+options["opacity"]*100+')';
				}
			}
		}
	}
	// End Add by DEO 2010.03.11
};
