(function($){
	$.fn.dropDownMenu = function(f,g) {
		// デフォルトの設定
		var cfg = {
				sensitivity: 7,
				interval: 100,
				timeout: 0
			};
		// デフォルト以外の設定が行われていた場合はその設定で上書きする
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// マウスの座標取得
		// cX, cY = 現在のマウス座標（mousemoveイベントが発生したときに更新）
		// pX, pY = mouseoverイベントが発生した時と、intervalに設定されている時間が経過したときのマウス座標
		var cX, cY, pX, pY;
		// マウス座標を取得する為のメソッド
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// 現在のマウス座標と、マウスオーバーした時と指定時間ごとに取得したマウス座標を比較
		var compare = function(ev, ob) {
			ob.dropDownMenu_t = clearTimeout(ob.dropDownMenu_t);

			if( ( Math.abs(pX - cX) + Math.abs(pY - cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove", track);
				// マウスアウトが発生した際にセットします
				ob.dropDownMenu_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// マウスオーバーまたは、指定時間が来るまで、マウスの座標を代入します
				pX = cX;
				pY = cY;
				// 明示的に、タイムアウトイベントを設定します
				ob.dropDownMenu_t = setTimeout( function(){ compare(ev, ob);}, cfg.interval );
			}
		};


		// マウスアウトイベント時に、遅延する為のメソッド
		var delay = function(ev, ob) {
			ob.dropDownMenu_t = clearTimeout(ob.dropDownMenu_t);
			ob.dropDownMenu_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// マウスオーバーした時に実行されるメソッド
		var handleHover = function(e) {
			// 次のツリーにjQuery.hoverを設定します
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;

			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }

			if( p == this ) { return false; }

			var ev = jQuery.extend({}, e);
			var ob = this;

			if( ob.dropDownMenu_t ) { ob.dropDownMenu_t = clearTimeout(ob.dropDownMenu_t); }

			if( e.type == "mouseover" ) {
				pX = ev.pageX;
				pY = ev.pageY;
				$(ob).bind("mousemove", track);

				if( ob.dropDownMenu_s != 1 ) { ob.dropDownMenu_t = setTimeout( function(){ compare(ev, ob); }, cfg.interval); }
			} else {
				$(ob).unbind("mousemove", track);
				if( ob.dropDownMenu_s == 1 ) { ob.dropDownMenu_t = setTimeout( function(){ delay(ev, ob); }, cfg.timeout ); }
			}
		};
		// イベントリスナーの設定
		return this.mouseover(handleHover).mouseout(handleHover);
	};
})(jQuery);
