/************************************************************************************/
/* テーブルの行（tbody）の上下入替を行うためのスクリプトです                        */
/*                                                                                  */
/* 上下ボタンで移動させる事と、マウスドラッグでの移動が可能です。                   */
/* 指定カラム(標準はSEQ)の値を入替時保持する事が可能です。                          */
/* このスクリプトはロードするだけでtbodyMovableのクラスを持つエリア(DIV等)に        */
/* mousedown,mousemove,mouseupのイベントをセットします。                            */
/* 該当タグのseqclm属性値が存在する場合はシーケンスカラム名とします。               */
/* シーケンスは指定カラムの先頭名称で判断するので注意して下さい。初期値SEQです。    */
/* 　例：SEQの指定でSEQUENCEカラムが判定されてしまう。                              */
/* seqclm属性はカンマ区切りで複数指定可能です。                                     */
/* 又、adjustSeq属性で指定したカラム（seqclmで指定されている必要あり）は、          */
/* 上に動かした時は上の値から-1された値を、下に動かした時は下の値に+1した値を       */
/* セットするような動作になります。これは１つのみ指定可能で初期値NULLです。         */
/* 複数のtableの移動を同期させる場合には同様にsyncro属性でクラスを指定します。      */
/* シンクロクラスはtableか、table直上の要素のクラスのみ指定可能です。               */
/* (tbodyMovableが複数ある場合は先頭の属性値がセットされます)                       */
/* マウスでドラッグできないTOBODYはclassをnoDrag属性でカンマ区切りで指定します。    */
/* 同様に入替対象でない(入替範囲限定など)場合はnoMove属性カンマ区切りです。         */
/*                                                                                  */
/*                                                                                  */
/*                                                                                  */
/* 例：                                                                             */
/*  <div class="tbodyMovable" seqclm="SEQUENCE,DAY" syncro="sync"                   */
/*              noMove="disMovable" noDrag="disDragable" adjustSeq="SEQUENCE">      */
/*     <table id="viewTalbe>....                                                    */
/*  </div>                                                                          */
/*                                                                                  */
/* -----                                                                            */
/* ファンクションの手動呼び出し                                                     */
/* コマンドを与える事で動作が変化します。                                           */
/* (1)onClickで移動させる場合 (オブジェクトには通常thisを指定)                      */
/* オブジェクトが所属するtbody行を１つ下と入れ替える：ogTbodyMovable(OBJECT,'DOWN') */
/* オブジェクトが所属するtbody行を１つ上と入れ替える：ogTbodyMovable(OBJECT,'UP')   */
/*                                                                                  */
/* (2)行のドラッグで移動させる場合（通常はtable外側のDIVに指定する）                */
/* onMouseDown用：ogTbodyMovable(this,'DRAGON',event)                               */
/* onMouseMove用：ogTbodyMovable(this,'DRAG',event)                                 */
/* onmouseUp用  ：ogTbodyMovable(this,'DRAGOFF',event)                              */
/*                                                                                  */
/* (3)シーケンスカラムのカラム名変更(カンマ区切り、カラム名の先頭で判断します）     */
/*	ogTbodyMovable('カラム名称１,カラム名称２','SEQCLM');                           */
/*                                                                                  */
/* (4)シーケンスカラムのうち、上下で-1,+1するカラムを１つ指定                       */
/*	ogTbodyMovable('カラム名称','ADJUST');                                          */
/*                                                                                  */
/* (5)シンクロClassの変更(シンクロさせるテーブルor直上要素のClassをカンマ区切り)    */
/*	ogTbodyMovable('対象Class1,対象Class2','SYNCRO');                               */
/*                                                                                  */
/* (6)ドラッグさせたくないTBODY指定(TBODYのClassをカンマ区切り。ボタン移動は対象外) */
/*	ogTbodyMovable('対象Class1,対象Class2','NODRAG');                               */
/*                                                                                  */
/* (7)入替対象外Classの変更（TBODYのClassをカンマ区切り）                           */
/*	ogTbodyMovable('対象Class1,対象Class2','NOMOVE');                               */
/*                                                                                  */
/* @og.rev 5.6.3.0 (2013/04/01) Takahashi Masakazu 新規追加                         */
/* Revision: $Id$                                                                   */
/************************************************************************************/

var ogTbodyMovable = (function(){
	var SeqClm = new Array('SEQ'); // シーケンスカラム
	var syncClass = '';	// シンクロクラス配列（動かしたVIEWと同じように動かす）
	var disDragable = ''; // ドラッグできないクラス配列
	var disMovable = ''; // 入替対象にならないクラス配列
	var adjustSeq = ''; // シーケンス1:上はマイナス、下はプラスにするカラム。SeqClm対象の必要あり。1つのみ指定可
	
	dragObj = new Object();
	dragObj.dragFlag = false;
	dragObj.offsetX = dragObj.offsetY = 0;
	dragObj.mouseX = dragObj.mouseY = 0;
	dragObj.height = dragObj.width = 0;
	dragObj.target = null;
	
	// HTML5に対応したDnDを取り入れる場合は
	// tableDnDのようなプラグインを利用する。
	
	// 上のtbody要素との入れ替え
	// _thisElm:移動元tbody内に配置された要素(通常this)
	function tbodyUp( _thisElm ,sync ){
		if(_thisElm.tagName.toUpperCase()=='TBODY'){
			var tbodyElm = _thisElm;
		}
		else{
			var tbodyElm = $(_thisElm).parents('tbody').get(0);
		}
		var tbleElm = $(tbodyElm).closest('table');
		var prevTbody = $(tbodyElm).prev('tbody');
		
		// tbodyにdisMovableにクラスが含まれているなら移動対象外
		for (i in disMovable) {
			if( $(prevTbody).hasClass(disMovable[i]) ){ return ; }
		}

		
		// シンクロ
		if( !sync && syncClass ){
			var rownumber =  $(tbleElm).children('tbody').index(tbodyElm);
			for (i in syncClass) {
			    	$('.'+syncClass[i]).each( function(){
			    		var _tgt = this;
			    		if( this.tagName.toUpperCase() != 'TABLE' ){
			    			_tgt = $(this).children('table').get(0);
			    		}
			    		if( $(_tgt) != $(tbleElm) ){
			    			tbodyUp($(_tgt).children('tbody').get(rownumber),true);}
			    		}
			    	 );
			}
		}
		
		// 入れ替え
		if ( prevTbody.length == 1 ){
			for( i in SeqClm){
				if ( $(tbodyElm).find('input[name^='+SeqClm[i]+']').length > 0
						&& $(prevTbody).find('input[name^='+SeqClm[i]+']').length > 0
					){
					var thisSeq = $(tbodyElm).find('input[name^='+SeqClm[i]+']').get(0);
					var prevSeq = $(prevTbody).find('input[name^='+SeqClm[i]+']').get(0);
					var thisSeqVal = thisSeq.value;
					var prevSeqVal = prevSeq.value;
					if( adjustSeq != null && SeqClm[i] == adjustSeq && Number(prevSeqVal) != NaN ){
						thisSeq.value = Number(prevSeqVal) - 1;
					}
					else{
						thisSeq.value = prevSeqVal;
						prevSeq.value = thisSeqVal;
					}
				}
			}
			$(tbodyElm).after( prevTbody );
			return true;
		}
		return false;
	};
	
	// 下のtbody要素との入れ替え
	// _thisElm:移動元tbody内に配置された要素(通常this)
	function tbodyDown( _thisElm, sync){
		if(_thisElm.tagName.toUpperCase()=='TBODY'){
			var tbodyElm = _thisElm;
		}
		else{
			var tbodyElm = $(_thisElm).parents('tbody').get(0);
		}
		var tbleElm = $(tbodyElm).closest('table');
		var nextTbody = $(tbodyElm).next('tbody');
		
		// tbodyにdisMovableにクラスが含まれているなら移動対象外
		for (i in disMovable) {
			if( $(nextTbody).hasClass(disMovable[i]) ){ return ; }
		}
		
		// シンクロ
		if( !sync && syncClass ){
			var rownumber =  $(tbleElm).children('tbody').index(tbodyElm);
			for (i in syncClass) {
			    	$('.'+syncClass[i]).each( function(){
			    		var _tgt = this;
			    		if( this.tagName.toUpperCase() != 'TABLE' ){
			    			_tgt = $(this).children('table').get(0);
			    		}
			    		if( $(_tgt) != $(tbleElm) ){
			    			tbodyDown($(_tgt).children('tbody').get(rownumber),true);}
			    		}
			    	 );
			}
		}

		// 入れ替え
		if ( nextTbody.length == 1 ){
			for( i in SeqClm){
				if ( $(tbodyElm).find('input[name^='+SeqClm[i]+']').length > 0
					 &&  $(nextTbody).find('input[name^='+SeqClm[i]+']').length > 0
					){
					var thisSeq = $(tbodyElm).find('input[name^='+SeqClm[i]+']').get(0);
					var nextSeq = $(nextTbody).find('input[name^='+SeqClm[i]+']').get(0);
					var thisSeqVal = thisSeq.value;
					var nextSeqVal = nextSeq.value;
					if( adjustSeq != null && SeqClm[i] == adjustSeq && Number(nextSeqVal) != NaN ){
						thisSeq.value = Number(nextSeqVal) + 1;
					}
					else{
						thisSeq.value = nextSeqVal;
						nextSeq.value = thisSeqVal;
					}
				}
			}
			$(tbodyElm).before(  nextTbody );
			return true;
		}
		return false;
	};
	
	// ドラッグ開始処理(マウス押下げ時の動作)
	function dragStart(_obj,_evt) {
		var evnt = ( _evt ) ? _evt : ( ( window.event ) ? window.event : null );
		var _tar = (evnt.target || evnt.srcElement);
		var _target = $(_tar).parents('tbody').get(0);
		
		if(_target ){
			// tbodyにdisDragableにクラスが含まれているなら除外
			for (i in disDragable) {
				if( $(_target).hasClass(disDragable[i]) ){ return true; }
			}
			if (document.all){
				mouseX = event.x;
				mouseY = event.y;
			}
			else{
				mouseX = _evt.pageX;
				mouseY = _evt.pageY;
			}
			dragObj.dragFlag = true;
			dragObj.target = _target;
			dragObj.height = _target.offsetHeight
			dragObj.width = _target.offsetWidth;
			dragObj.offsetX = mouseX - $(_target).offset().left;
			dragObj.offsetY = mouseY - $(_target).offset().top;
			dragObj.mouseY = mouseY;
			dragObj.mouseX = mouseX;
		}
		document.body.style.cursor = 'move';
		return false;
	}
	
	// ドラッグ終了処理(マウスを離した時の動作)
	function dragEnd(){
		dragObj.dragFlag = false;
		dragObj.offsetX = dragObj.offsetX = 0;
		dragObj.mouseX = dragObj.mouseY = 0;
		dragObj.height = dragObj.width = 0;
		dragObj.target = null;
		document.body.style.cursor = 'auto';
	}
	
	// ドラッグ中の処理
	function dragProc(_evt){
		var mouseX,mouseY;
		if (document.all){
			//mouseX = event.x;
			mouseY = event.y;
		}
		else{
			//mouseX = _evt.pageX;
			mouseY = _evt.pageY;
		}
		
		if (!dragObj.dragFlag) return;

		
		// 縦移動量を見て、該当オブジェクトの外に出たら上下移動させる
		if( dragObj.mouseY - mouseY > dragObj.offsetY ){
			if( tbodyUp(dragObj.target) ){
				dragObj.offsetX = mouseX - $(dragObj.target).offset().left;
				dragObj.offsetY = mouseY - $(dragObj.target).offset().top;
				dragObj.mouseY = mouseY;
			}
		}
		else if( mouseY - dragObj.mouseY > dragObj.height - dragObj.offsetY ){
			if( tbodyDown(dragObj.target) ){
				dragObj.offsetX = mouseX - $(dragObj.target).offset().left;
				dragObj.offsetY = mouseY - $(dragObj.target).offset().top;
				dragObj.mouseY = mouseY;
			}
		}
		return false;
	}
	
	// 実際に呼び出す場合は引数でコントロールする
	return function(_obj, _action, _event){
		switch( _action ){
			case 'UP':
				tbodyUp(_obj);
				break;
			case 'DOWN':
				tbodyDown(_obj);
				break;
			case 'DRAGON':
				dragStart(_obj,_event);
				break;
			case 'DRAGOFF':
				dragEnd();
				break;
			case 'DRAG':
				dragProc(_event);
				break;
			case 'SEQCLM':
				SeqClm = _obj.split(",");
				break;
			case 'SYNCRO':
				syncClass = _obj.split(",");
				break;
			case 'NODRAG':
				disDragable = _obj.split(",");
				break;
			case 'NOMOVE':
				disMovable = _obj.split(",");
				break;
			case 'ADJUST':
				adjustSeq = _obj;
			default: return;
		}
	};
})();
 
// 自動起動
$(function(){
	// 設定値は先頭のtbodyMovableのseqclmに限定する
	if( $('.tbodyMovable').length > 0 ) { 
		var sc = $('.tbodyMovable').get(0).getAttribute('seqclm');
		var sync =  $('.tbodyMovable').get(0).getAttribute('syncro');
		var nodrag =  $('.tbodyMovable').get(0).getAttribute('noDrag');
		var nomove =  $('.tbodyMovable').get(0).getAttribute('noMove');
		var adjustSeq = $('.tbodyMovable').get(0).getAttribute('adjustSeq');
		if( sc ){ ogTbodyMovable(sc,'SEQCLM'); }
		if( sync ){ ogTbodyMovable(sync,'SYNCRO'); }
		if( nodrag ){ ogTbodyMovable(nodrag,'NODRAG'); }
		if( nomove ){ ogTbodyMovable(nomove,'NOMOVE'); }
		if( adjustSeq ){ ogTbodyMovable(adjustSeq,'ADJUST'); }
	}
//	setEvent( ".tbodyMovable", "mousedown", function(){ ogTbodyMovable(this,'DRAGON',event); } );
//	setEvent( ".tbodyMovable", "mousemove", function(){ ogTbodyMovable(this,'DRAG',event); } );
//	setEvent( ".tbodyMovable", "mouseup", function(){ ogTbodyMovable(this,'DRAGOFF',event); } );
	$(".tbodyMovable").bind("mousedown", function(e){ ogTbodyMovable(this,'DRAGON', e||window.event); } );
	$(".tbodyMovable").bind("mousemove", function(e){ ogTbodyMovable(this,'DRAG',e||window.event); } );
	$(".tbodyMovable").bind("mouseup", function(e){ ogTbodyMovable(this,'DRAGOFF',e||window.event); } );
});