/*
 * 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拡張 #                        */
/*--------------------------------------*/


/* よく使うの
 *************************************************/
var _SRC = 'src',
    _WIDTH = 'width',
    _HEIGHT = 'height';



/* クラス
 *************************************************/
$.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].join(''));
			});
		});
		
		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 = 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].join('');
		},
		
		time : function(sep){
			sep = sep || '';
			return [this.h, sep, this.m, sep, this.s].join('');
		},
		
		now : function(sep){
			sep = sep || '';
			return [this.date(sep), sep, this.time(sep)].join('');
		}
	}
});


/*** $.preload ***
 **************************************************/
$.preload = function(path){
	if(!(path instanceof Array)){
		var img = new Image();
		img.src = path;
		return img;
	}
	
	var load = arguments.callee, ret = [];
	$.each(path, function(i, v){
		ret.push(load(v));
	});
	return ret;
};


/*** $.popup ***
 ポップアップ
 **************************************************/
$.popup = function(file, name, options){
	options = $.extend({
		location : 'no',
		menubar : 'no',
		status : 'no',
		toolbar : 'no'
	}, options);
	
	//スクロールバー処理
	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;
		}
	}
	
	var optArr = [], _EQ = '=';
	$.each(options, function(i, v){
		optArr.push([i, v].join(_EQ))
	});
	optStr = optArr.join(',');
	
	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, ';'].join('')).match(['; ', name, '=([^;]*)?;'].join(''));
		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)].join(''),
			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, ']'].join('')).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 = {}, _AND = '&', _EQ = '=';
	$.each(args.split(_AND), function(i, v){
		var pair = v.split(_EQ);
		ret[pair[0].toString()] = 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());
				});
				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].join(''));
};


/*** $.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" chimg="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: 'chimg',
		prefixAttr: 'prefix',
		postfixAttr: 'postfix',
		rolloverAttr: 'rollover',
		autoActive: false,
		acceptNotLink: false
	},options);
	var exclude = options.exclude,
	    autoActive = options.autoActive,
	    acceptNotLink = options.acceptNotLink;
	
	var img_tags = 'img, input:image',
	    link_tags = 'a, area, input:image';
	
	var $this = this;
	
	return $this
		.each(function(){
			var $elms = $(this);
			
			
			//リンク以外を許可しない場合
			if(!acceptNotLink){
				$elms = $elms.is(link_tags) ?
				        	$elms.filter(link_tags) :
				        	$elms.parents(link_tags).length ?
				        		$elms :
				        		$elms.find(link_tags);
			}
			
			if(!$elms.length) return true; //continue
			
			$elms
				.each(function(){
					var $elm = $(this);
					
					//操作対象
					var target = $elm.attr(options.targetAttr);
					var $target = target ? $('#' + target) : $elm;
					$target = ($target.is(img_tags) ? $target : $target.find(img_tags)).eq(0);
					if(!$target.length) return true; //continue
					
					var src = $target.attr(_SRC);
					if(!src) return true; //continue
					
					//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 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.stripe({
	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.stripe = 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);
