// Tip
/******************************************************
 * Drop for JQuery
 * By Mudoo 2011-11
 
 * Demo:
 * 通过class绑定下拉对象，支持JQuery选择规则

 	<a href="###" class="Drop[#testDrop]">测试下拉</a>
	<div id="testDrop">测试下拉内容</div>
	
	$("a[class*='Drop[']").Drop({
		object : null,				// 全局下拉对象，未通过class绑定对象时生效
		mode : 'o',					// 触发事件，o=mouseover, c=click，默认o
		position : 'b',				// 显示位置，t,top=上方，r,right=右侧，b,bottom=下方，l,left=左侧，默认b
		effect : 'slide',			// 显示效果，fade=渐显渐隐，slide=下拉，为空关闭，默认slide
		space : 0,					// 间隔空隙，默认0
		relative : false,			// 是否相对定位，在父容器使用position:relative的情况下使用，默认false
		keep : true,				// 鼠标悬停在下拉内容上时，是否保持显示，默认true
		show : function(e, d) {},	// 内容显示前执行函数，传入参数（e=当前触发元素，d=当前下拉元素），返回false则不显示，默认null
		hide : function(e, d) {}	// 内容隐藏后执行函数，传入参数（e=当前触发元素，d=当前下拉元素），默认null
	});
 ******************************************************/
(function($){
	$.fn.Drop = function(o) {
		var $set = $.extend({}, {object: null, mode: 'o', position: 'b', effect: 'slide', space: 0, relative: false, keep: true, show: null, hide: null}, o || {});
		if(!!$set.object) $set.object=$($set.object);
		switch($set.mode) {
			case 'c' :
				$set.mode = 'click';
				break;
			case 'o' :
				$set.mode = 'mouseover';
				break;
		};
		
		$(this).each(function(i) {
			var
			$self = $(this),
			$selector = $(this).attr('class').replace(/.*Drop\[(.*)\].*/, "$1"),
			$obj = !$selector ? $set.object : $($selector),
			$time = null,
			$displayed = false;
			
			if(!$obj) return true;
			$obj.hide();
			
			$self.bind($set.mode, function() {
				show();
			}).bind('mouseout', function() {
				hide();
			});
			
			if($set.keep) {
				$obj.bind('mouseenter', function() {
					clearTimeout($time);
				}).bind('mouseleave', function() {
					hide(true);
				});
			}
			
			function show() {
				if(!!$set.show) {
					try{
						if($set.show($self, $obj)==false) return;
					}catch(e){}
				}
				
				var $pos = $set.relative ? $self.position() : $self.offset(),
				$oSize = {'width': $self.outerWidth(), 'height': $self.outerHeight()},
				$cSize = {'width': $obj.outerWidth(), 'height': $obj.outerHeight()},
				$dSize = {'width': $(document).width(), 'height': $(document).height()};
				
				//alert($pos.top +' _ '+ $pos.left);
				switch($set.position) {
					case 't': case 'top' :		// 上
						$pos.top = $pos.top-$cSize.height-$set.space;
						break;
					case 'r': case 'right' :	// 右
						$pos.left = $pos.left+$self.width()+$set.space;
						break;
					case 'b': case 'bottom' :	// 下
						$pos.top = $pos.top+$self.height()+$set.space;
						break;
					case 'l': case 'left' :		// 左
						$pos.left = $pos.left-$cSize.width-$set.space;
						break;
				};
				//alert($pos.top +' _ '+ $pos.left);
				
				if(!$set.relative) {
					$pos = {
						top : $pos.top>0 ? ($pos.top+$cSize.height>$dSize.height ? $dSize.height-$cSize.height : $pos.top) : 0,
						left : $pos.left>0 ? ($pos.left+$cSize.width>$dSize.width ? $dSize.width-$cSize.width : $pos.left) : 0
					};
				}
				
				$obj.css('top', $pos.top).css('left', $pos.left);
				display('show');
			}
			
			function hide(n) {
				if(!n && $set.keep) {
					$time = setTimeout(function(){hide(true);}, 100);
					return false;
				}
				display('hide');
				
				if(!!$set.hide) {
					try{
						$set.hide($self, $obj);
					}catch(e){}
				}
			}
			
			function display(t) {
				if(t=='hide' && !$displayed) return;
				if($set.effect!='') {
					var $ef = '';
					if($set.effect=='slide') $ef = $set.effect + t.replace('show','Down').replace('hide', 'Up');
					if($set.effect=='fade') $ef = $set.effect + t.replace('show','In').replace('hide', 'Out');
					if($ef!='') {
						$obj.stop(true, true)[$ef]('fast');
					}else{
						t=='show' ? $obj.show() : $obj.hide();
					}
				}else{
					t=='show' ? $obj.show() : $obj.hide();
				}
				$displayed=(t=='show');
			}
		});
	};
})(jQuery);

