/*
 * Copyright (C) 2008 Daichi Tachihata 
 *
 */
(function($){ //jQueryを$で


/*@cc_on //IEもにょもにょ
eval((function(props) {
  var code = [];
  for (var i = 0, l = props.length;i<l;i++){
    var prop = props[i];
    window['_'+prop]=window[prop];
    code.push(prop+'=_'+prop)
  }
  return 'var '+code.join(',');
})('document self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' ')));
@*/




/*--------------------------------------*/
/*# jQuery拡張 #                        */
/*--------------------------------------*/


/* クラス
 *************************************************/
$.Class = {
	//クラス定義
	/* 使い方
	var newclass = $.Class.define({
		name: クラス名,
		extend: 親クラス,
		construct: function(arg){
			this.p = arg;
		},
		methods: {
			m1 : function(){},
			m2 : function(){}
		},
		statics: {
			s1 : function(){},
			s2 : function(){}
		},
		borrows: メソッドを借用したいクラスかクラスの配列,
		provides: 同じメソッドがあるか検証したいクラスかクラスの配列
	});
	*/
	define : function(data){
		var classname = data.name;
		var superclass = data.extend || Object;
		var constructor = data.construct || function(){};
		var methods = data.methods || {};
		var statics = data.statics || {};
		var borrows = !data.borrows ?
		              	[] :
		              	data.borrows instanceof Array ?
		              		data.borrows :
		              		[data.borrows];
		var provides = !data.provides ?
		              	[] :
		              	data.provides instanceof Array ?
		              		data.provides :
		              		[data.provides];
		
		
		var _TYPE_FUNCTION = "function",
		    _P_NAME_CONSTRUCTOR = "constructor",
		    _P_NAME_SUPERCLASS = "superclass";
		
		var proto = new superclass();
		
		for(var p in proto){
			if(proto.hasOwnProperty(p)) delete proto[p];
		}
		
		$.each(borrows, function(i, v){
			$.each(v.prototype, function(ii, vv){
				if(typeof vv != _TYPE_FUNCTION) return true;//continue
				proto[ii] = vv;
			});
		});
		
		for(var p in methods) proto[p] = methods[p];
		
		proto.constructor = constructor;
		proto.superclass = superclass;
		
		if(classname) proto.classname = classname;
		
		$.each(provides, function(i, v){
			$.each(v.prototype, function(ii, vv){
				if(typeof vv != _TYPE_FUNCTION) return true;//continue
				if(ii == _P_NAME_CONSTRUCTOR || ii == _P_NAME_SUPERCLASS) return true;//continue
				if(ii in proto &&
				   typeof proto[ii] == _TYPE_FUNCTION &&
				   proto[ii].length == vv.length) return true;//continue
				
				throw new Error("Class"+ classname +"does not provide method "+ v.classname +"."+ ii);
			});
		});
		
		constructor.prototype = proto;
		
		for(var p in statics) constructor[p] = statics[p];
		
		return constructor;
	}
};


/*** $.URI ***
 *************************************************/
$.URI = $.Class.define({
	name: '$.URI',
	construct: function(url){
		this.originalPath = url;
		this.absolutePath = this.getAbsolutePath(url);
	},
	methods: {
		//絶対パスを取得
		getAbsolutePath : function(path){
			var img = new Image();
			img.src = path;
			path = img.src;
			img.src = '#';
			return path;
		},
		
		//同じ文書にリンクしているかどうか
		isSelfLink : (this.absolutePath == location.href)
	}
});


/*** $.Date ***
 日付関連
 **************************************************/
$.Date = $.Class.define({
	name: '$.Date',
	extend: Date,
	construct: function(d){
		var d = this.d = d ? new Date(d) : new Date();
		
		var yy = d.getFullYear() || d.getYear();
		var mm = d.getMonth() + 1;
		var dd = d.getDate();
		this.yy = yy > 1900 ? yy : yy + 1900;
		this.mm = mm < 10 ? mm = "0" + mm : mm;
		this.dd = dd <10 ? dd = "0" + dd : dd;
		
		var h = d.getHours();
		var m = d.getMinutes();
		var s = d.getSeconds();
		this.h = h < 10 ? h = "0" + h : h;
		this.m = m <10 ? m = "0" + m : m;
		this.s = s < 10 ? s = "0" + s : s;
	},
	methods: {
		date : function(sep){
			sep = sep || "";
			return this.yy + sep + this.mm + sep + this.dd;
		},
		
		time : function(sep){
			sep = sep || "";
			return this.h + sep + this.m + sep + this.s;
		},
		
		now : function(sep){
			sep = sep || "";
			return this.date(sep) + sep + this.time(sep);
		},
		
		day : function(en){
			var dow = ['日', '月', '火', '水', '木', '金', '土'];
			var dow_en = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
			return (en ? dow_en : dow)[this.d.getUTCDay()];
		}
		
	}
});


/*** $.preload ***
 **************************************************/
$.preload = function(path){
	if(!path instanceof Array)
		(new Image()).src = path; return;
	
	var load = arguments.callee;
	$.each(path, function(i, v){
		load(v);
	});
};


/*** $.popup ***
 ポップアップ
 **************************************************/
$.popup = function(file, name, options){
	options = $.extend({
		location : "no",
		menubar : "no",
		status : "no",
		toolbar : "no"
	}, options);
	
	var optStr = "", _EQ = "=", _COMMA = ",", _SCROLLBARS = "scrollbars", _YES = "yes";
	if("scrollbars" in options && 
	   (options["scrollbars"] == "yes" ||
	    options["scrollbars"] == "1")){
		if("width" in options){
			var width = options["width"] - 0;
			options["width"] = width + 15;
		}
		if("height" in options){
			var height = options["height"] - 0;
			options["height"] = height + 20;
		}
	}
	$.each(options, function(i, v){
		optStr += i + _EQ + v + _COMMA;
	});
	optStr = optStr.substring(0, optStr.length - 1);
	
	return void window.open(file, name, optStr);
};


/*** $.cookie ***
 $.cookie("hoge", "fuga")でset
 $.cookie("hoge")でget
 **************************************************/
$.cookie = function(name, value, options){
	if(arguments.length == 0){ //getAll：return {～}
		var pairs = document.cookie.split("; ");
		var ret = {};
		$.each(pairs, function(i, v){
			var pair = v.split("=");
			ret[pair[0]] = pair[1];
		});
		return ret;
	}
	else if(arguments.length == 1){ //get
		var match = ('; ' + document.cookie + ';').match('; ' + name + '=([^;]*)?;');
		return match ? decodeURIComponent(match[1]) : '';
	}else{ //set
		options = $.extend({
			expires: (function(){
				var d = new Date;
				d.setTime(d.getTime() + 24*60*60*1000 * 365);
				return d;
			})(),
			path: "",
			domain: "",
			secure: ""
		}, options);
		var expires = '; expires=' + options.expires.toGMTString(),
		    path = options.path ? '; path=' + (options.path) : '',
		    domain = options.domain ? '; domain=' + (options.domain) : '',
		    secure = options.secure ? '; secure' : '';
		
		document.cookie = [
			encodeURIComponent(name) + "=" + encodeURIComponent(value),
			expires,
			path,
			domain,
			secure
		].join('');
	}
};


/*** $.dump ***
 jqueryオブジェクトの中身をダンプ
 **************************************************/
$.dump = function($obj) {
	var dumphtml = [];
	if(jQuery.browser.msie) {
		for(var i = 0, l = $obj.length; i < l; i++) {
			dumphtml.push('[' + i + '] ');
			dumphtml.push($obj[i].outerHTML.replace(/^[\r\n\t]+/, ''));
			dumphtml.push("\n");
		}
	} else {
		for(var i = 0, l = $obj.length; i < l; i++) {
			dumphtml.push('[' + i + '] '
				+ '<' + $obj[i].nodeName.toLowerCase());
			for(var j = 0, l2 = $obj[i].attributes.length; j < l2; j++) {
				dumphtml.push(' ' + $obj[i].attributes[j].nodeName + '="' 
					+ $obj[i].attributes[j].nodeValue + '"');
			}
			dumphtml.push('>' + $obj[i].innerHTML);
			dumphtml.push('<\/' + $obj[i].nodeName.toLowerCase() + '>');
			dumphtml.push("\n");
		}
	}
	alert(dumphtml.join(''));
};


/*** $.srcArg ***
 scriptタグのsrcから引数取得
 *************************************************/
$.srcArg = function(scriptName, name){
	var src = $("script[src*=" +scriptName+ "]").attr("src");
	
	if(!src) return false;
	
	src = src.split("?");
	var args = src[1];
	src = src[0];
	
	if(!args || !src.match(new RegExp(scriptName.replace(".", "\.") + "$"))) return false;
	
	if(args.indexOf("=") == -1) return args;
	
	var ret = {};
	$.each(args.split("&"), function(i, v){
		var pair = v.split("=");
		ret[pair[0] + ""] = pair[1];
	});
	return name ? ret[name] : ret;
};


/*** $.tblSerialize ***
 table内容をシリアライズ
 *************************************************/
$.tblSerialize = function(table){
	$table = (table instanceof jQuery ? table : $(table)).eq(0);
	
	if(!$table.is("table")) throw '$.tblSerialize(): argument is not "table".';
	
	table = {
		thead: $table.find("thead"),
		tbody: $table.find("tbody"),
		tfoot: $table.find("tfoot")
	};
	
	var ret = {};
	$.each(table, function(i, $v){
		if($v.length > 0){
			ret[i] = [];
			$v.find("tr").each(function(){
				//*
				var tr = [];
				$(this).find("th, td").each(function(){
					tr.push($(this).text());
				});
				/*/
				var tr = $.makeArray($(this).find("th, td"));
				//*/
				ret[i].push(tr);
			});
		}
	});
	return ret;
};


/*** $.srcReplace ***
 srcを置換。
 afterSrc = $.srcReplace(src, prefix, postfix);
 *************************************************/
$.srcReplace = function(src, prefix, postfix){
	if(prefix == undefined) prefix = '';
	if(postfix == undefined) postfix = '';
	
	var ftype = src.substring(src.lastIndexOf('.'));
	var imgName = src.replace(ftype, '');
	if(src.lastIndexOf('/') != -1)
		imgName = imgName.substring(src.lastIndexOf('/') + 1);
	return src.replace(imgName, prefix + imgName + postfix);
};


/*** $.bench ***
 ベンチ
 *************************************************/
$.bench = function(func, count){
	if(!$.isFunction(func)) return;
	count = count || 1;
	
	return function(){
		var start = new Date();
		for(var i = 0; i < count; i++){
			func.apply(null, arguments);
		}
		return (new Date()) - start;
	}
	
};


/*** $.repeat ***
 strを指定回数繰り返す
 *************************************************/
$.repeat = function(str, num, start){
	var i = start || 0, buf = "";
	var isF = $.isFunction(str);
	for(; i < num; i++) buf += isF ? str(i) : str;
	return buf;
}


/*** $.pageSize ***
 ブラウザの表示領域の大きさ
 *************************************************/
$.pageSize = function(){
	var xScroll, yScroll;
	if(window.innerHeight && window.scrollMaxY){
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	}else if(document.body.scrollHeight > document.body.offsetHeight){
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	}else{
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;
	if(self.innerHeight) {
		if(document.documentElement.clientWidth){
			windowWidth = document.documentElement.clientWidth; 
		} else {
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	}else if(document.documentElement && document.documentElement.clientHeight){
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	}else if(document.body){
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}
	
	var pageWidth = xScroll < windowWidth ? xScroll : windowWidth;
	var pageHeight = yScroll < windowHeight ? windowHeight : yScroll;
	
	return [pageWidth,pageHeight,windowWidth,windowHeight];
}


/*** $.scrollPos ***
 スクロール位置の取得
 *************************************************/
$.scrollPos = function(){
	return {
		top: document.documentElement.scrollTop || document.body.scrollTop,
		left: document.documentElement.scrollLeft || document.body.scrollLeft
	};
};


/*--------------------------------------*/
/*# jQueryプラグイン #                  */
/*--------------------------------------*/


/*** ロールオーバー ＆ 対象画像切替 ***
■設定
$obj.chimg({
	exclude: "active",
	prefix: "",
	postfix: "_o",
	targetAttr: "target",
	prefixAttr: "prefix",
	postfixAttr: "postfix",
	rolloverAttr: "rollover",
	autoActive: false,
	acceptNotLink: false
});

■解説
[対象Object]自身、または[対象Object]内にあるリンク(含:input:image)のマウスオーバー時に
if(「[設定:targetAttr]="****"」属性が指定されていたら){
	その指定されたID「****」の画像が、
}else{
	そのリンク内にある画像が
}
if(「[設定:rolloverAttr]="****"」属性が指定されていたら){
	その指定された画像「****」に
}else{
	if(「[設定:prefixAttr]="****"」属性か「[設定:postfixAttr]="****"」属性が指定されていたら){
		その指定されたprefixやpostfixが付与された形の画像に
		（例:foo.gif→****foo****.gif）
	}else{
		「[設定:prefix]画像名[設定:postfix].拡張子」に
		（例：foo.gif→foo_o.gif）
	}
}
切り替わる。
もちろんリンクからのマウスアウトで元の画像に戻る。
リンクでは無い画像や、class="[設定:exclude]"を付与された画像ではマウスオーバー時の切替しない。


[設定:autoActive]がtrueの場合、class="[設定:exclude]"が指定されている画像が
ページロード時にマウスオーバー後の画像になるようにする。


[設定:acceptNotLink]がtrueの場合、リンクの有無は関係なく画像のマウスオーバーが設定される。


■例1 (デフォ設定)
<div class="chimg">
	<a href=""><img src="foo.gif"></a>　←反応する
	<a href=""><img src="bar.gif"></a>　←反応する
	<a href=""><img src="foobar.gif" class="active"></a>　←反応しない
	<a href="" class="active"><img src="baz.gif"></a>　←反応しない
	<img src="foo2.gif">　←反応しない
</div>

■例2 (デフォ設定)
<a href="" class="chimg"><img src="hoge.jpg"></a>　←中の画像が切り替わる

<a href="" class="chimg" target="fuga"><img src="xxx.jpg"><a>
<img src="yyy.jpg" id="fuga">
↑リンクマウスオーバー時、ID:fugaの画像（yyy.jpg）が切り替わる。

<input type="image" src="zzz.jpg" class="chimg">　←これ自身が切り替わる

 *************************************************/
$.fn.chimg = function(options){
	
	options = $.extend({
		exclude: "active",
		prefix: "",
		postfix: "_o",
		targetAttr: "target",
		prefixAttr: "prefix",
		postfixAttr: "postfix",
		rolloverAttr: "rollover",
		autoActive: false,
		acceptNotLink: false
	},options);
	var exclude = options.exclude,
	    autoActive = options.autoActive,
	    acceptNotLink = options.acceptNotLink;
	
	var $this = this;
	
	return $this
		.each(function(){
			var $elms = $(this);
			
			//リンク以外を許可するか
			if(acceptNotLink){
				var tags = "img, input:image";
				$elms = $elms.is(tags) ? $elms.filter(tags) : $elms.find(tags);
			}else{
				var tags = "a, area, input:image";
				$elms = $elms.is(tags) ?
				        	$elms.filter(tags) :
				        	$elms.parents(tags).length ?
				        		$elms :
				        		$elms.find(tags);
			}
			
			if(!$elms.length) return true; //continue
			
			$elms
				.each(function(){
					var $elm = $(this);
					
					//操作対象
					var target = $elm.attr(options.targetAttr);
					var $target = target ? $("#" + target) : $elm;
					var tags = "img, input:image";
					$target = ($target.is(tags) ? $target : $target.find(tags)).eq(0);
					
					//prefix,postfix設定
					var prefix =  $elm.attr(options.prefixAttr);
					var postfix =  $elm.attr(options.postfixAttr);
					prefix = prefix ? prefix : options.prefix;
					postfix = postfix ? postfix : options.postfix;
					
					var src = $target.attr("src");
					if(!src) return true; //continue
					
					//マウスオーバーイメージのパス
					var osrc = $elm.attr(options.rolloverAttr);
					if(!osrc) osrc = $.srcReplace(src, prefix, postfix);
					$.preload(osrc);
					
					//除外設定
					var isExclude = !!($target.is("." + exclude) || $target.parents("." + exclude).length);
					
					//autoActive
					if(autoActive && isExclude){
						var asrc = typeof autoActive == 'string' ? $.srcReplace(src, prefix, autoActive) : osrc;
						$target.attr("src", asrc);
					}
					
					//動作部
					var action = function(chsrc){
						if(!isExclude)
							$target.attr("src", chsrc);
					};
					
					//イベント
					$elm.hover(function(){
						action(osrc);
					}, function(){
						action(src);
					});
					
				});
			
		});
};


/*** テーブル(やリスト等)交互色 ***
■設定
$obj.alternate({
	evenClass: "even",
	oddClass: "odd",
	onlyTbody: true,
	childOnly: false,
	rowTag: false
});

■解説
[対象Object]内のtrやliタグなんかに交互に
class="[設定:oddClass]"とclass="[設定:evenClass]"を付与する。
cssで色をつければ交互色に。


table要素で使われる場合に、[設定:onlyTbody]がtrueの場合、theadやtfoot内の
trをカウントしない。


[設定:childOnly]がtrueの場合、子要素のみに適用される。(孫以下スルー)


[設定:rowTag]が指定されている場合、その指定したobjectに交互に
class付与される。（タグ(例:"div")でもクラスでも(例:".hoge")OKっす）


■例（こんなかんじになるよ、と）
<table class="coloredRow">
	<tr class="even">　←追加されたクラス
		<th></th><td></td>
	</tr>
	<tr class="odd">　←追加されたクラス
		<th></th><td></td>
	</tr>
	<tr class="even">　←追加されたクラス
		<th></th><td></td>
	</tr>
</table>

 *************************************************/
$.fn.alternate = function(options){
	
	options = $.extend({
		evenClass: "even",
		oddClass: "odd",
		onlyTbody: true,
		childOnly: false,
		rowTag: false
	},options);
	var evenClass = options.evenClass,
	    oddClass = options.oddClass,
	    childOnly = options.childOnly ? "> ": "",
	    rowTag = options.rowTag;
	
	var $this = this;
	
	return $this
		.each(function(){
			$elm = $(this);
			
			rowTag = rowTag ||
			         $elm.is("table") ?
			         	"tr" :
			         	$elm.is("ul, ol") ?
			         		"li" :
			         		$elm.is("dl") ?
			         			"dt, dd" : false ;
			
			if(!rowTag) return true; //continue
			
			if($elm.is("table"))
				$elm = options.onlyTbody ? $elm.find("> tbody") : $elm;
			
			//イベント
			$elm.find(childOnly + "*")
				.filter(rowTag)
					.removeClass(oddClass)
					.removeClass(evenClass)
					.filter(":odd").addClass(oddClass)
					.end()
					.filter(":even").addClass(evenClass);
			
		});
};


/*** tblSort ***
■設定
$obj.tblSort({
	type: "arrow", //"arrow"か"link"
	caseSensitive : false, //大文字小文字の区別
	arrowColor: "#9999cc",
	arrowActiveColor: "#0000ff",
	ignoreColLabel: "", //無視するカラムのラベル（theadのセルの中身）
	theadColText: "列"
}, callback);

■解説
$obj.tblSort({
	type: "arrow", //"arrow"か"link"
	caseSensitive : false, //大文字小文字の区別
	arrowColor: "#9999cc",
	arrowActiveColor: "#0000ff",
	ignoreColLabel: "", //無視するカラムのラベル（theadのセルの中身）
	theadColText: "列"
}, callback);

テーブル並び替えできるようになる。
見た目は[設定:type]で変更。「arrow」と「link」の2種類。

callbackは並び替え動作完了時に何かしたいことがあれば書いとく。
（交互色とかここでもっかいやった方がいいかも。）
ちなみにcallbackは[対象Object]のメソッドとして実行されるのでthisは[対象Object]になる。
あと、オプション省略して引数がcallbackだけでも可。

 *************************************************/
$.fn.tblSort = function(options ,callback){
	
	//引数処理
	if(arguments.length < 2){
		if($.isFunction(options)) callback = options, options = {};
	}
	options = $.extend({
		type: "arrow", //"arrow"か"link"
		caseSensitive : false, //大文字小文字の区別
		arrowColor: "#9999cc",
		arrowActiveColor: "#0000ff",
		ignoreColLabel: "", //無視するカラムのラベル（theadのセルの中身）
		theadColText: "列"
	},options);
	var arrowColor = options.arrowColor,
	    arrowActiveColor = options.arrowActiveColor;
	
	var _cellInner = "tblSort-thead-cell-inner",
	    _arrowClass = "tblSort-arrow",
	    _activeArrowClass= "tblSort-arrow-active";
	
	var $this = this;
	
	return $this
		.each(function(i){
			var $table = $(this);
			
			//テーブル以外ならスルー
			if(!$table.is("table")) return true; //continue
			
			var $thead = $table.find("> thead"),
			    $tbody = $table.find("> tbody"),
			    $tfoot = $table.find("> tfoot");
			
			//theadが無ければ追加
			if($thead.length == 0){
				$thead = $('<thead><tr></tr></thead>');
				$tbody.find("> tr:first").find("> th, > td").each(function(colNo){
					$thead.find("> tr").append('<th>' + options.theadColText + (colNo + 1) + '</th>');
				});
				$table.prepend($thead);
			}
			
			//theadにコントロール追加
			$thead.find("> th, > td")
				.each(function(j){
					var $elm = $(this);
					
					if($elm.text() == options.ignoreColLabel) return true; //continue
					
					switch(options.type){
						//type "link"
						case "link":
							$elm
								.wrapInner('<a href="javascript:;"></a>')
								.children()
									.after('<strong class="' + _arrowClass + '"></strong>')
									.next()
										.css({
											"margin-left": "2px",
											"color": arrowColor,
											"font-weight": "bold"
										})
									.end()
									.toggle(function(){
										action.call($(this), j, "ascend");
										$(this).next().text("↑");
									}, function(){
										action.call($(this), j, "descend");
										$(this).next().text("↓");
									});
							break;
						//type "arrow"
						case "arrow":
						default:
							var _top = ($elm.height() - 18) / 2 + "px";
							var _right = $.browser.msie ? $elm.css("padding-right") : 0 + "px";
							$elm
								.wrapInner('<div class="' + _cellInner + '">')
								.children()
									.css("position", "relative")
									.append('<div class="' + _arrowClass + 's">' +
									        	'<div class="' + _arrowClass + ' ' + _arrowClass + '-ascend">▲</div>' +
									        	'<div class="' + _arrowClass + ' ' + _arrowClass + '-descend">▼</div>' +
									        '</div>')
									.find("> ." + _arrowClass + "s")
										.css({
											"position": "absolute",
											"top": _top,
											"right": _right,
											"color": arrowColor,
											"font-size": "9px",
											"line-height": "1",
											"cursor": "pointer"
										})
										.find("> ." + _arrowClass)
											.hover(function(){
												$(this).css("color", arrowActiveColor);
											}, function(){
												if(!$(this).is("." + _activeArrowClass))
													$(this).css("color", arrowColor);
											})
											.click(function(){
												if($(this).is("." + _arrowClass + "-ascend")){
													action.call($(this), j, "ascend");
												}else{
													action.call($(this), j, "descend");
												}
											});
							break;
					}
					
					//動作部
					var action = function(colNo, mode){
						$tbody = $table.find("tbody");
						var $tr = $tbody.find("> tr");
						var trArr = $.makeArray($tr);
						
						trArr.sort(function(tr1, tr2){
							var $tr1 = $(tr1),
							    $tr2 = $(tr2);
							
							var cell1 = $tr1.find("> th, > td").eq(colNo).text(),
							    cell2 = $tr2.find("> th, > td").eq(colNo).text();
							
							//大文字小文字を区別する場合
							if(options.caseSensitive){
								cell1 = cell1.toLowerCase();
								cell2 = cell2.toLowerCase();
							}
							
							return cell1 == cell2 ? 0 : cell1 > cell2 ? 1 : -1;
						})
						
						//逆
						if(mode == "descend") trArr.reverse();
						
						$tbody.empty().append($(trArr));
						
						//色変更
						$chColor = $(this).is("." + _arrowClass) ? $(this) : $(this).siblings("." + _arrowClass);
						$thead.find("." + _arrowClass)
							.removeClass(_activeArrowClass)
							.css("color", arrowColor);
						$chColor
							.css("color", arrowActiveColor)
							.addClass(_activeArrowClass);
						
						if(callback) callback.call($table[0]);
					};
					
				})
		});
};


/*** tblHover ***
■設定
$obj.tblHover({
		type: "cross", //"cross" or "row" or "col" or "cell"
		hoverClass: "hover",
		onlyTbody: true,
		ignoreTh: true,
		clickMark: true
});

■解説
テーブルのセルにマウスオーバーでマーカーとしてクラス：[設定:hoverClass]を追加。

[設定:type]は
	"cross" : 行、列両方にマーカー
	"row"   : 行だけにマーカー
	"col"   : 列だけにマーカー
	"cell"  : 対象セルだけマーカー

[設定:clickMark]がtrueならクリックでマーカー固定。

[設定:onlyTbody]がtrueならtbody内だけで、theadとかtfoot無視。

[設定:ignoreTh]がtrueならthは無視。

 *************************************************/
$.fn.tblHover = function(options ,callback){
	
	options = $.extend({
		type: "cross", //"col" or "row" or "cell" or "cross"
		hoverClass: "hover",
		onlyTbody: true,
		ignoreTh: true,
		clickMark: true
	},options);
	
	var $this = this;
	var cellTag = options.ignoreTh ? "> td" : "> th, > td";
	var clicked = false,
	    colored = false,
	    hover = true;
	
	return $this
		.each(function(i){
			var $table = $(this);
			
			//テーブル以外ならスルー
			if(!$table.is("table")) return true; //continue
			
			var $thead = $table.find("> thead"),
			    $tbody = $table.find("> tbody"),
			    $tfoot = $table.find("> tfoot");
			
			if(options.onlyTbody) $table = $tbody;
			
			var $trs = $table.find("tr");
			
			$trs
				.each(function(i){
					$tr = $(this);
					
					$tr.find(cellTag)
						.each(function(j){
							var $cell = $(this);
							
							$cell
								.hover(function(){
									if(hover)
										action.call(this, [i, j], 0);
								}, function(){
									if(hover)
										action.call(this, [i, j], 1);
								});
							
							if(options.clickMark)
								$cell
									.click(function(){
										if(!clicked){
											clicked = [i, j];
											hover = false;
										}else{
											if(clicked[0] == i && clicked[1] == j){
												//action.call(this, [i, j], 1);
												clicked = false;
												hover = true;
											}else{
												action.call(this, [colored[0], colored[1]], 1);
												action.call(this, [i, j], 0);
												clicked = [i, j];
											}
										}
									});
							
							
							//動作部
							var action = function(addr, remove){
								var method = remove ? "removeClass" : "addClass";
								var row = addr[0],
								    col = addr[1];
								
								var $target = $(this);
								switch(options.type){
									case "cell":
										if(remove) $target = $trs.eq(row).find(cellTag).eq(col);
										break;
									case "row":
										$target = $trs.eq(row).find(cellTag);
										break;
									case "col":
										$target = $trs.map(function(){
											return $(this).find(cellTag)[col];
										});
										break;
									case "cross":
									default:
										$target = $trs.map(function(k){
											var $tgCell = $(this).find(cellTag);
											return row == k ? $tgCell.get() : $tgCell[col];
										});
										break;
								}
								colored = [row, col];
								$target[method](options.hoverClass);
							};
						});
					
				});
		});
};


/*** floating ***
 ■解説
 スクロールにぬるぬるついてくるやつ。
 *************************************************/
$.fn.floating = function(options){
	
	options = $.extend({
		wait: 100,
		minDuration: 100,
		check: 1000
	}, options);
	
	return this.each(function(){
		var $this = $(this);
		
		//safariはfixedでお茶濁し
		if($.browser.safari){
			$this.css("position", "fixed");
			return true; //continue
		}
		
		var boxTop = function(){return $this.offset().top};
		var startTop = boxTop();
		
		var timer, checkTimer;
		var scrollTop, nowTop, targetTop, duration;
		var d = document, w = window;
		
		var getPosTop = function(){
			scrollTop = d.body.scrollTop || d.documentElement.scrollTop;
			nowTop = boxTop();
			targetTop = scrollTop + startTop;
			duration = Math.max(options.minDuration, Math.abs(targetTop - nowTop));
		};
		
		var scrollAnimation = function(){
			$this
				.animate({
					top: targetTop + "px"
				}, duration, function(){
					timer = 0;
				});
		};
		
		$(w)
			.scroll(function(){
				if(timer) return;
				timer = w.setTimeout(function(){
					getPosTop();
					scrollAnimation();
				}, options.wait);
			});
		
		//定期的にチェック checkが0ならスルー
		if(options.check)
			checkTimer = w.setInterval(function(){
				if(timer) return;
				getPosTop();
				if(nowTop == targetTop) return;
				scrollAnimation();
			}, options.check);
		
	});
};



/*** If ***
■解説
exprが真ならtrue_cbで偽ならfalse_cb。
exprがfunctionなら、thisの中からexprで評価して真のものにtrue_cb、偽のものにfalse_cb
 *************************************************/
$.fn.If = function(expr, true_cb, false_cb){
	var $this = this;
	true_cb = $.isFunction(true_cb) ? true_cb : false;
	false_cb = $.isFunction(false_cb) ? false_cb : false;
	
	if($.isFunction(expr)){
		var $true_obj = $.grep($this, expr);
		var $false_obj = $.grep($this, expr, 1);
		true_cb && $true_obj.length && $true_obj.each(true_cb);
		false_cb && $false_obj.length && $false_obj.each(false_cb);
	}else{
		expr ? true_cb && $this.each(true_cb) : false_cb && $this.each(false_cb);
	}
	
	return $this;
};



/*** pageInit ***
■解説
$obj.pageInit({
	hogehoge : fugafuga
}, callback);

$("body")がhogehogeな時に$(fugafuga)を対象にcallback(hogehoge, fugafuga)する。
ちなみにcallbackは[対象Object]のメソッドとして実行されるのでthisは[対象Object]になる。

■例
$obj.pageInit({
	".foo" : "#id1",
	".bar" : "#id2"
}, function(test, target){
	$(this).addClass("baz");
});

 *************************************************/
$.fn.pageInit = function(mapping, callback, options){
	
	options = $.extend({
		testObject: "body"
	}, options);
	
	var $this = this;
	var $body = $(options.testObject);
	
	if(callback && typeof callback == "string")
		callback = $.isFunction(eval(callback)) && eval(callback);
	if(!mapping || !callback || !$.isFunction(callback)) return $this;
	
	$.each(mapping, function(cond, selector){
		if($body.is(cond)){
			//selectorが配列だったら2個目以降を引数に追加するよ
			if(selector instanceof Array){
				var addArgs = selector;
				var selector = addArgs.shift();
			}
			
			var $target = selector ? $this.find(selector) : $this;
			
			var args = [cond, selector];
			if(addArgs) args = args.concat(addArgs);
			$target.each(callback, args);
		}
	});
	
	return $this
};



})(jQuery);
