/* version: 0.0.1 
 * author : Sen Li
 * date   : 2012/05/10
 * 機能   : ガント図の描画
 */

/*
 * 変数を隠蔽するため、クロージャー化します。
 */
var adjustGantTable = (function(){

// 属性変数
var gantZoom;							// ガントズーム
var gantStartDate;						// ガントの描画開始日付(時間)
var gantEndDate;						// 
var daySpan;
var skipHoliday;						// 休日を飛ばすか
var arrCalender;						// カレンダー配列
var verticalShift = "true";				// ガントバー要素の縦方向でずらす
var margeRows	  = "false";			// 複数行のマージ、条件：前の行のデータと一致する時
var fixedCols	  = 0;					// 列固定、固定列の数

// 全域変数
var hoursPreDay;						// 一日の描画時間数
var gantStartTime;						// 始業時間
var gantEndTime;						// 終業時間
// ガントバー移動用の変数
var hilightBar = null;
var startX;
var oriLeft;
var oriWidth;
var cnBunkatu  = 3;
var startInputObj = null;
var endInputObj = null;
// Mouse Action
var cnMNone    = 0;
var cnMLeft    = 1;
var cnMMiddle  = 2;
var cnMRight   = 3;
var nLeftRightLimit = 2;		// sayu no tukamishiro no saishou-chi
var nMAction;

// システム定数
var SYS_BAR_HEIGHT		 	= 20;		// ガントバー要素の高さ
var SYS_MIN_HEIGHT_SHIFT 	= 50;		// ガントバー要素の縦方向でずらす場合の行高さ
var SYS_MIN_HEIGHT_NO_SHIFT = 30;		// ガントバー要素の縦方向でずらさない場合の行高さ
var SYS_MARKER_OFFSET_H	 	= 3;		// マーカーとバーの縦方向の相対位置
var SYS_CELLPADDING			= 0;		// 
var SYS_NUMBER_CELLS		= 3;		// viewTableの番号列の数

//リストオブジェクト
function List(){
	this.head    = null; 
	this.end     = null; 
	this.current = null;
	this.size    = 0;
} 

//リストにノードを追加する
List.prototype.add = function( inObj ){ 
	var node = { obj:inObj ,next:null }; 
	if( this.head ){ 
		this.end.next = node; 
		this.end	  = node; 
	}
	else{ 
		this.head    = node; 
		this.end     = node; 
		this.current = node; 
	} 
	this.size++;
} 

//リストから次のノードを取得する
List.prototype.next = function(){ 
	var node = null;
	if( this.current ){ 
		node		 = this.current.obj; 
		this.current = this.current.next;
	}
	return node; 
} 

//リストから次のノードが存在するかを確認する
List.prototype.hasnext = function(){ 
	if( this.current != null ) return true; 
	return false; 
}

// Arrayコピー用のメソッドを追加する。
Array.prototype.clone = function(){
    return Array.apply(null,this)
}
// Arrayに要素の存在チェックするためのメソッドを追加する。
Array.prototype.contains = function( value ){
	for(var i = 0; i < this.length; i++){
		if(this[i] === value){
			return true;
		}
	}
	return false;
};
// ２つの日付の差分を計算する
function compareDate( inDate1, inDate2) {
	if( inDate1 == null || inDate2 == null ){return 0;}
	if( inDate1.length != 8 || inDate2.length != 8 ){return 0;}
	var year1  = inDate1.substring( 0 ,4 );
	var month1 = inDate1.substring( 4 ,6 );
	var day1   = inDate1.substring( 6 );
	var year2  = inDate2.substring( 0 ,4 );
	var month2 = inDate2.substring( 4 ,6 );
	var day2   = inDate2.substring( 6 );
    var dt1 = new Date(year1, month1 - 1, day1);
    var dt2 = new Date(year2, month2 - 1, day2);
    var diff = dt1 - dt2;
    var diffDay = diff / 86400000;		// 1日の86400000ミリ秒数
    return diffDay;
}
//n日後、n日前の日付を求める
function addDays( inDate ,inDays ) {
	var year  = inDate.substring( 0 ,4 );
	var month = inDate.substring( 4 ,6 );
	var day   = inDate.substring( 6 );
	var rtnDate = new Date( year, month - 1, day );
	var baseSec = rtnDate.getTime();
	var addSec  = inDays * 86400000;	// 1日の86400000ミリ秒数
	var targetSec = baseSec + addSec;
	rtnDate.setTime( targetSec );
	return rtnDate.getFullYear() + ( "00" + ( rtnDate.getMonth() + 1 ) ).slice( -2 ) + ("00" + rtnDate.getDate()).slice( -2 );
}

// 日付の入力欄への反映
function performDateChange( nMyMAction, movedSpan ){
	startInputObj = document.getElementsByName( hilightBar.startInput )[0];
	switch ( hilightBar.type ){
		case "0" :
			startInputObj.value = addDays( hilightBar.startDT ,movedSpan ) 
			break;
		case "1" :
			endInputObj   = document.getElementsByName( hilightBar.endInput )[0];
			switch ( nMAction ){
				case cnMLeft :
					startInputObj.value = addDays( hilightBar.startDT ,movedSpan ) 
					break;
				case cnMRight:
					endInputObj.value = addDays( hilightBar.endDT ,movedSpan ) 
					break;
				case cnMMiddle:
					startInputObj.value = addDays( hilightBar.startDT ,movedSpan ) 
					endInputObj.value = addDays( hilightBar.endDT ,movedSpan ) 
					break;
				default:
			}
			break;
		default:
	}
}
// 行のチェックをonにする
function setRowChecked(oMyForm, sName, bValue)
{
	var nIndexUp;
	var aInputs=document.getElementsByName(sName);
	if(null != aInputs)
	{
		for(nIndexUp = 0; nIndexUp < aInputs.length;  nIndexUp++ )
		{
			var oSetObj  = aInputs[nIndexUp];
			if(("INPUT" == oSetObj.tagName )
			&& (( "checkbox" == oSetObj.type ) || ( "radio" == oSetObj.type )))
			{
				oSetObj.checked = ((undefined == bValue) ? true : bValue);
			}
		}
	}
}

// ガントバーのドラグドロップ処理
function fnMouseDown( event ){
	hilightBar = event.srcElement;

	if( null != hilightBar )
	{
		var nMyWidth = hilightBar.offsetWidth;

		nLeftRightLimit = Math.min( Math.max( nMyWidth / cnBunkatu, 2 ) ,20 );

		switch ( hilightBar.type ){
			// マイルストーン
			case "0" :
				nMAction = cnMMiddle;
				hilightBar.style.cursor = "move";
				break;
			// バー
			case "1" :
				if( event.offsetX <= nLeftRightLimit ){
					nMAction = cnMLeft;
					hilightBar.style.cursor = "E-resize";
				}
				else if( event.offsetX > ( nMyWidth - nLeftRightLimit )){
					nMAction = cnMRight;
					hilightBar.style.cursor = "E-resize";
				}
				else
				{
					nMAction = cnMMiddle;
					hilightBar.style.cursor = "move";
				}
				break;
			default:
		}

		hilightBar.setCapture();
		startX   = event.screenX;
		oriLeft  = hilightBar.parentNode.offsetLeft;
		oriWidth = hilightBar.width;
	}

}
// ガントバーのドラグドロップ処理
function fnMouseUp( event ){
	if( null != hilightBar )
	{
		hilightBar.style.cursor = "auto";
		hilightBar.releaseCapture();

		if( startInputObj ){
			hilightBar.startDT = startInputObj.value;
		}
		if( endInputObj ){
			hilightBar.endDT   = endInputObj.value;
		}

		nMAction      = cnMNone;
		// 行の選択をonにする
		if(hilightBar.chboxid && ( "" != hilightBar.chboxid)) {
			setRowChecked(null, hilightBar.chboxid);
		}

	}

}

// ガントバーのドラグドロップ処理
function fnMouseMove( event ){
	if(( 1 == event.button ) && ( hilightBar != null )){
		var moveDist = event.screenX - startX;

		switch ( hilightBar.type ){
			// マイルストーン
			case "0" :
				moveDist = Math.ceil( moveDist / hilightBar.pixelPreSpan ) * hilightBar.pixelPreSpan;
				switch( nMAction ){
					// 中間
					case cnMMiddle:
						hilightBar.parentNode.style.left = parseInt( oriLeft ) + moveDist;
						break;
					default:
				}
				break;
			// バー
			case "1" :
				switch ( nMAction ){
				case cnMLeft :
					moveDist = Math.floor( moveDist / hilightBar.pixelPreSpan ) * hilightBar.pixelPreSpan;
					hilightBar.parentNode.style.left  = parseInt( oriLeft ) + moveDist ;
					hilightBar.width = oriWidth - moveDist;
					break;
				case cnMRight:
					moveDist = Math.ceil( moveDist / hilightBar.pixelPreSpan ) * hilightBar.pixelPreSpan;
					hilightBar.width = oriWidth + moveDist;
					break;
				case cnMMiddle:
					moveDist = Math.ceil( moveDist / hilightBar.pixelPreSpan ) * hilightBar.pixelPreSpan;
					hilightBar.parentNode.style.left = parseInt( oriLeft ) + moveDist;
					break;
				default:
			}
			break;
			default:
		}
		// Change the date
		performDateChange( nMAction, moveDist / hilightBar.pixelPreSpan );
	}
}
/*
    ZOOM  ラベル        日数ピクセル変換率          ヘッダ上      ヘッダ下    1文字(CSS)
  ==================================================================================
     0 : １週間 日数 * 12 * 4     48   48px =  1日  [02/   ]      [23(EE)]       8px
     1 : ２週間 日数 * 12 * 2     24   24px =  1日  [02/]         [23 ]          8px
     2 : １ヶ月 日数 * 12         12   12px =  1日  [2]           [3]           12px
     3 : ２ヶ月 日数 * 12 / 1.5    8   56px =  7日  [2004/  ]     [02/03  ]      8px
     4 : ３ヶ月 日数 * 12 / 3      4   56px = 14日  [2004/  ]     [02/03  ]      8px
     5 : ４ヶ月 日数 * 12 / 4      3   90px = 30日  [2004/     ]  [02/03     ]   9px
     6 : ６ヶ月 日数 * 12 / 6      2   60px = 30日  [2004/ ]      [02/03 ]      10px
     7 : １年   日数 * 12 / 12     1   90px = 90日  [2004/     ]  [02/03     ]   9px
     8 : ２年   日数 * 12 / 24    0.5  90px =180日  [2004/     ]  [02/03     ]   9px
     9 : ３年   日数 * 12 / 36    0.33 60px =180日  [2004/ ]      [02/03 ]      10px
    10 : 週単位 日数 * 12 / 3.5   3.43 24px =  7日  [19W]         [12 ]          8px
    20 : 1時間  時間 * 12 * 4       48 48px = 1時間 [02日]        [07h ]        12px
    21 : 1時間2 時間 * 12 * 2       24 24px = 1時間 [02]          [07]          12px
    22 : 2時間  時間 * 12 * 4 /  2  24 48px = 2時間 [02日]        [07h ]        12px
    23 : 2時間2 時間 * 12 * 2 /  2  12 24px = 2時間 [02]          [07]          12px
    24 : 4時間  時間 * 12 * 4 /  4  12 48px = 4時間 [02日]        [07h ]        12px
    25 : 4時間2 時間 * 12 * 2 /  4   6 24px = 4時間 [02]          [07]          12px
    26 : 6時間  時間 * 12 * 4 /  6   8 48px = 6時間 [02日]        [07h ]        12px
    27 : 6時間2 時間 * 12 * 2 /  6   4 24px = 6時間 [02]          [07]          12px
    28 : 8時間  時間 * 12 * 4 /  8   6 48px = 8時間 [02日]        [07h ]        12px
    29 : 8時間2 時間 * 12 * 2 /  8   3 24px = 8時間 [02]          [07]          12px
    30 :12時間  時間 * 12 * 4 / 12   4 48px =12時間 [02日]        [07h ]        12px
    31 :12時間2 時間 * 12 * 2 / 12   2 24px =12時間 [02]          [07]          12px 
*/
function showGantBar( gantTd ,listGantBar ,lineHeight ){
	if( gantTd == null || listGantBar == null ){ return false; }
	// ガントセル幅
	var unitPixel = {"0" : 48 ,"1" : 24 ,"2" : 12 ,"3" : 56 ,"4" : 56 ,"5" : 90 ,"6" : 60 ,"7" : 90 ,"8" : 90 ,"9" : 60 ,"10": 24 ,"20": 48 ,"21": 24 ,"22": 48 ,"23": 24 ,"24": 48 ,"25": 24 ,"26": 48 ,"27": 24 ,"28": 48 ,"29": 24 ,"30": 48 ,"31": 24 };
	// ガントセル毎の日数・時間数
	var unitSpan  = {"0" : 1  ,"1" : 1  ,"2" : 1  ,"3" : 7  ,"4" : 14 ,"5" : 30 ,"6" : 30 ,"7" : 90 ,"8" :180 ,"9" :180 ,"10":  7 ,"20":  1 ,"21":  1 ,"22":  2 ,"23":  2 ,"24":  4 ,"25":  4 ,"26":  6 ,"27":  6 ,"28":  8 ,"29":  8 ,"30": 12 ,"31": 12 };
	// 一日または一時間当たりのピクセル数
	var pixelPreSpan = unitPixel[gantZoom] / unitSpan[gantZoom] ;

	//
	iDiv 	      		= document.createElement("div");
	gantTd.appendChild( iDiv );
	iDiv.style.position = "relative";
	iDiv.style.height   = lineHeight - 2;
	iDiv.style.width    = "100%";
	iDiv.style.fontSize	="0";
	// バー間の上下位置をずらす
	var hPosShift = 10;
	// ガント要素のトップ位置
	var iGantPos_Top = ( lineHeight - SYS_BAR_HEIGHT ) / 2 -10;
	
	// ガント要素毎に描画する。
	while ( listGantBar.hasnext() ){
		var gantBarObj = listGantBar.next();
		//
		var iGantDiv   = document.createElement("div");
		iGantDiv.style.position = "absolute";
		iGantDiv.style.top =iGantPos_Top;
		// 
		switch( gantBarObj.type ){
			// ガントマーカー
			case "0":
				// 開始終了日付(YYYYMMDD)
				var startDate  = gantBarObj.start.substring( 0 ,8 );
				// 開始終了時間(HH24MM)
				var startTime  = gantBarObj.start.substring( 8 );
				// ガントバーはカレンダー範囲外は描画不能
				if( startDate > gantEndDate ){
					startDate = gantEndDate;
				}
				// 開始日はガント開始日より小さい場合、ガント開始日から描画する
				if( startDate < gantStartDate ){
					startDate = gantStartDate;
				}
				// 開始時間
				if( startTime < gantStartTime ){
					startTime = gantStartTime;
				}
				if( startTime > gantEndTime ){
					startTime = gantEndTime;
				}

				var diffDayS   = compareDate( startDate ,gantStartDate );
				//描画開始、終了位置の計算
				var startPos;
				if( parseInt( gantZoom ,10 ) <= 10 ){
					startPos   = diffDayS * pixelPreSpan;
				}
				else{
					// 休日を飛ばす場合	
					var countHoliday = 0;
					if( skipHoliday == "true" ){
						// 
						countHoliday = 0;
						for( var i = 0 ; i < diffDayS ;i++ ){
							if( arrCalender[i] > 0 ){ countHoliday++; }
						}
						diffDayS -= countHoliday;
					}
					// 描画開始位置 = 日付差分(開始日) + 時間差分(開始時間)
					startPos   = diffDayS * Math.ceil( hoursPreDay / unitSpan[gantZoom] ) * unitPixel[gantZoom] +
								 ( parseInt( startTime.substring( 0 ,2 ) ,10 ) - parseInt( gantStartTime.substring( 0 ,2 ) ,10 ) + 
								 ( parseInt( startTime.substring( 2    ) ,10 ) - parseInt( gantStartTime.substring( 2    ) ,10 )) / 60 ) * pixelPreSpan;
				}
				iGantDiv.style.left= startPos;

				var iCenter    = document.createElement("img");
				iCenter.src    = gantBarObj.src;
				// ツールチップの表示
				iCenter.alt = startDate.substring( 0 ,4 ) + "/" + startDate.substring( 4 ,6 ) + "/" + startDate.substring( 6 ,8 ) 
								+ " " + startTime.substring( 0 ,2 ) + ":" + startTime.substring( 2 ,4 )
							  ;
				// ガントバーの移動対応
				if( gantBarObj.startInput ){
					// 値連動用のパラメータ
					iCenter.type         = gantBarObj.type;
					iCenter.startDT      = gantBarObj.start;
					iCenter.startInput   = gantBarObj.startInput;
					iCenter.pixelPreSpan = pixelPreSpan;
					iCenter.chboxid      = gantBarObj.chboxid;
					iCenter.attachEvent( "onmousedown"  , function(){ fnMouseDown( event );} );
					iCenter.attachEvent( "onmousemove"  , function(){ fnMouseMove( event );} );
					iCenter.attachEvent( "onmouseup"    , function(){ fnMouseUp(   event );} );
				}

				// 
				iGantDiv.appendChild( iCenter );
				//
				iGantDiv.style.top = iGantPos_Top * 1 + SYS_MARKER_OFFSET_H;
				break;
			// ガントバー
			case "1":
				// バーを縦方向でずらして描画
				if( verticalShift == "true" ){
					hPosShift = hPosShift == -10 ? 10 : -10;
				}
				else{
					hPosShift = 0;
				}
				iGantPos_Top = ( lineHeight - SYS_BAR_HEIGHT ) / 2 + hPosShift;
				iGantDiv.style.top = iGantPos_Top;

				// 開始終了日付(YYYYMMDD)
				var startDate  = gantBarObj.start.substring( 0 ,8 );
				var endDate    = gantBarObj.end.substring( 0 ,8 );
				// 開始終了時間(HH24MM)
				var startTime  = gantBarObj.start.substring( 8 );
				var endTime    = gantBarObj.end.substring( 8 );
				// 開始日と終了日逆転は描画不能
				if( startDate > endDate ){
					break;
				}
				// ガントバーはカレンダー範囲外は描画不能
				if( startDate > gantEndDate || endDate < gantStartDate ){
					break;
				}
				// 終了時間は開始時間より小さい場合、終了日は次の日で計算する。（夜勤の場合）
				if( endTime < startTime ){
					endDate = addDays( endDate ,1 );
				}
				// 開始日はガント開始日より小さい場合、ガント開始日から描画する
				if( startDate < gantStartDate ){
					startDate = gantStartDate;
				}
				// 終了日はガント終了日より多きい場合、ガント終了日まで描画する
				if( endDate > gantEndDate ){
					endDate = gantEndDate;
				}
				// 開始時間
				if( startTime < gantStartTime ){
					startTime = gantStartTime;
				}
				if( startTime > gantEndTime ){
					startTime = gantEndTime;
				}
				// 終了時間
				if( endTime > gantEndTime ){
					endTime = gantEndTime;
				}
				if( endTime < gantStartTime ){
					endTime = gantStartTime;
				}

				var diffDayS   = compareDate( startDate ,gantStartDate );
				var diffDayE   = compareDate( endDate   ,gantStartDate );
				//描画開始、終了位置の計算
				var startPos;
		        var endPos  ;
				if( parseInt( gantZoom ,10 ) <= 10 ){
					startPos   = diffDayS * pixelPreSpan;
					endPos     = diffDayE * pixelPreSpan;
				}
				else{
					// 休日を飛ばす場合	
					var countHoliday = 0;
					if( skipHoliday == "true" ){
						// 
						countHoliday = 0;
						for( var i = 0 ; i < diffDayS ;i++ ){
							if( arrCalender[i] > 0 ){ countHoliday++; }
						}
						diffDayS -= countHoliday;
						// 
						countHoliday = 0;
						for( var i = 0 ; i < diffDayE ;i++ ){
							if( arrCalender[i] > 0 ){ countHoliday++; }
						}
						diffDayE -= countHoliday;
					}
					// 描画開始位置 = 日付差分(開始日) + 時間差分(開始時間)
					startPos   = diffDayS * Math.ceil( hoursPreDay / unitSpan[gantZoom] ) * unitPixel[gantZoom] +
								 ( parseInt( startTime.substring( 0 ,2 ) ,10 ) - parseInt( gantStartTime.substring( 0 ,2 ) ,10 ) + 
								 ( parseInt( startTime.substring( 2    ) ,10 ) - parseInt( gantStartTime.substring( 2    ) ,10 )) / 60 ) * pixelPreSpan;
					// 描画終了位置 = 日付差分(終了日) + 時間差分(終了時間)
					endPos     = diffDayE * Math.ceil( hoursPreDay / unitSpan[gantZoom] ) * unitPixel[gantZoom]+
								 ( parseInt( endTime.substring( 0 ,2 ) ,10 ) - parseInt( gantStartTime.substring( 0 ,2 ) ,10 ) + 
								 ( parseInt( endTime.substring( 2    ) ,10 ) - parseInt( gantStartTime.substring( 2    ) ,10 )) / 60 ) * pixelPreSpan;
				}
				iGantDiv.style.left= startPos;

				var iCenter    = document.createElement("img");
				//ガント図の元画像
				switch( gantBarObj.color ){
					case "blue":
						iCenter.src    = "../image/W_Blue.png";
						break;
					case "lightblue":
						iCenter.src    = "../image/W_LightBlue.png";
						break;
					case "green":
						iCenter.src    = "../image/W_Green.png";
						break;
					case "lightgreen":
						iCenter.src    = "../image/W_LightGreen.png";
						break;
					case "red":
						iCenter.src    = "../image/W_Red.png";
						break;
					case "pink":
						iCenter.src    = "../image/W_Pink.png";
						break;
					case "orange":
						iCenter.src    = "../image/W_Orange.png";
						break;
					case "brown":
						iCenter.src    = "../image/W_Brown.png";
						break;
					case "purple":
						iCenter.src    = "../image/W_Purple.png";
						break;
					case "black":
						iCenter.src    = "../image/W_Black.png";
						break;
					default:
						iCenter.src    = "../image/W_Blue.png";
						break;
				}
				iCenter.width  = endPos - startPos;
				iCenter.height = SYS_BAR_HEIGHT;
				// ツールチップの表示
				iCenter.alt = startDate.substring( 0 ,4 ) + "/" + startDate.substring( 4 ,6 ) + "/" + startDate.substring( 6 ,8 ) 
								+ " " + startTime.substring( 0 ,2 ) + ":" + startTime.substring( 2 ,4 ) + "-" + 
							  endDate.substring( 0 ,4 )   + "/" + endDate.substring( 4 ,6 )   + "/" + endDate.substring( 6 ,8 )
								+ " " + endTime.substring( 0 ,2 ) + ":" + endTime.substring( 2 ,4 )
							  ;
				// 
				iGantDiv.appendChild( iCenter );
				// ガントバーの移動対応
				if( gantBarObj.startInput != null || gantBarObj.endInput != null ){
					// 値連動用のパラメータ
					iCenter.type         = gantBarObj.type;
					iCenter.startDT      = gantBarObj.start;
					iCenter.endDT        = gantBarObj.end;
					iCenter.startInput   = gantBarObj.startInput;
					iCenter.endInput     = gantBarObj.endInput;
					iCenter.pixelPreSpan = pixelPreSpan;
					iCenter.chboxid      = gantBarObj.chboxid;
					iCenter.attachEvent( "onmousedown"  , function(){ fnMouseDown( event );} );
					iCenter.attachEvent( "onmousemove"  , function(){ fnMouseMove( event );} );
					iCenter.attachEvent( "onmouseup"    , function(){ fnMouseUp(   event );} );
				}

				// 改行
				var iBr    = document.createElement("br");
				iGantDiv.appendChild( iBr );
		}
		// 注釈
		iGantDiv.style.fontSize	="12";
		// 注釈をガント要素の下方に表示させる
		iGantDiv.appendChild( document.createTextNode( gantBarObj.msg ));

		// 
		iDiv.appendChild( iGantDiv );
	}
}

// メイン処理（画面から呼び出す）
function adjustGant(){

// チューニング用
//var t1=new Date();

	// viewTableのオブジェクトの取得
	var viewTableObj = document.getElementById( "viewTable" );
	// viewTableが存在しなければ終了
	if( viewTableObj == null ){ return false; } 

	// ganttHeaderオブジェクトの取得
	var gantHeaderObj = document.getElementById( "ganttHeaderData" );
	// gantHeaderObjが存在しなければ終了
	if( gantHeaderObj == null ){ return false; }

	// iGantオブジェクト取得
	var iGantObjs = document.getElementsByTagName( "iGant" );
	// iGantObjsが存在しなければ終了
	if( iGantObjs == null || iGantObjs.length == 0 ){ return false; }

	// 休憩時間の網掛けを非表示（高さ調整前）
	$(".breaktime").hide();
	// カレンダーの文字列
	var strCalender   = gantHeaderObj.calDB;
	// 描画可能なズーム
	var gantZooms = ["0","1","2","3","4","5","6","7","8","9","10","20","21","22","23","24","25","26","27","28","29","30","31"];
	// 属性値の取得
	// ガントズーム
	gantZoom      = gantHeaderObj.zoom;
	// ガントの描画開始日付(時間)
	gantStartDate = gantHeaderObj.startDate;
	gantEndDate   = gantHeaderObj.endDate;
	// 一日の描画時間数(0700-2000)
	daySpan		  = gantHeaderObj.daySpan;
	// 休日を飛ばすか
	skipHoliday   = gantHeaderObj.skipHoliday;

	// 複数行のマージ
	margeRows 	  = iGantObjs[0].margeRows;
	// 固定列
	fixedCols 	  = iGantObjs[0].fixedCols;
	// viewTableに番号列が表示されるか
	viewNumberType	  = iGantObjs[0].viewNumberType;

	// 必須属性のチェック、設定していなければ終了
	if( gantZoom == null || gantStartDate == null || gantEndDate == null || daySpan == null ){ return false; }
	// gantZoomのチェック
	if( !gantZooms.contains( gantZoom ) ){ return false; }

	// 始業時間(0700-xxxx)
	gantStartTime	  = daySpan.split("-")[0];
	// 終業時間(xxxx-2000)
	gantEndTime	  	  = daySpan.split("-")[1];
	// 終業時間が大きい場合、始業時間と終業時間ともに同日の時間で計算する
	if( gantEndTime > gantStartTime ){
		hoursPreDay = parseInt( gantEndTime.substring( 0 ,2 ) ,10 ) - parseInt( gantStartTime.substring( 0 ,2 ) ,10 ) + 
					( parseInt( gantEndTime.substring( 2    ) ,10 ) - parseInt( gantStartTime.substring( 2    ) ,10 )) / 60;
	}
	// 始業時間が大きい場合、始業時間は終業時間の次の日の時間として計算する(夜勤)
	else{
		hoursPreDay = 24 + 
					  parseInt( gantStartTime.substring( 0 ,2 ) ,10 ) - parseInt( gantEndTime.substring( 0 ,2 ) ,10 ) + 
					( parseInt( gantStartTime.substring( 2    ) ,10 ) - parseInt( gantEndTime.substring( 2    ) ,10 )) / 60;
	}
	// カレンダー解析（パス）
	if( skipHoliday == "true" ){
		var calenderDays = strCalender.length;
		arrCalender = new Array( calenderDays );
		for( i = 0 ;i < calenderDays ;i++ ){
			arrCalender[i] = strCalender.substr( i ,1 );
		}
	}

	// viewTableよりデータノードを作成する。
	// theadオブジェクトの取得（一つしかない）
	var headerObjs   = viewTableObj.all.tags("THEAD");
	// theadにタイトルの物理的な行数
	var tHeadLines   = headerObjs[0].all.tags("TR").length;
	//
	var bodyHeight = 0;
	
	// tbodyオブジェクトの取得（業務データの一行分）
	var tBodyObjs   = viewTableObj.all.tags("TBODY");
	var countTBody = tBodyObjs.length;
	// tbodyに業務データの物理的な行数
	var countLines = tBodyObjs[0].all.tags("TR").length;
	// tbody毎のセル数
	var countCells = tBodyObjs[0].all.tags("TD").length;
	// 業務データ行(tBody)の高さ
	var lineHeight = tBodyObjs[0].offsetHeight;
	// ２段組でガントバーを上下シフトして表示させる
	if( verticalShift == "true" ){
		if( lineHeight < SYS_MIN_HEIGHT_SHIFT    ){ lineHeight = SYS_MIN_HEIGHT_SHIFT; }
	}
	else{
		if( lineHeight < SYS_MIN_HEIGHT_NO_SHIFT ){ lineHeight = SYS_MIN_HEIGHT_NO_SHIFT; }
	}

	// ガント要素のリスト
	// 描画の行単位でキャッシュする、行マージする場合はマージ後の行となる
	var listGantBar = new List();
	// 前後行のデータ
	var cellValPre  = new Array( countCells );
	var cellValNext = new Array( countCells );
	// 前後行の比較結果（0:同様(マージできる) 1:同様じゃない(マージできない)）
	var fgDiff      = 0;
	var gantTd		= null;
	// tBodyの数分ループ（業務データの一行(tBody)ずつ描画させる）
	for( var i = 0; i < countTBody; i++ ){
		// ガント要素のリスト
		// 業務データの行単位(tBody)のガント要素をキャッシュする。行マージする場合はマージ前の行となる
		var swapGantBar = new List();
		// 業務データの行(tBody)毎のセル
		var lineTdObjs = tBodyObjs[i].all.tags("TD");
		// ガント要素の親TD
		var swapGantTd = null;

		for( var j = 0; j < countCells; j++ ){
			// 前方の行番号など、比較対象外
			if( j < SYS_NUMBER_CELLS && viewNumberType !='delete' ){
				cellValNext[j] = "";
			}
			// ガント要素、比較対象外
			else if( lineTdObjs[j].firstChild && lineTdObjs[j].firstChild.tagName == "IGANTBAR" ){
				var childObjs = lineTdObjs[j].childNodes;
				// 
				for( var k = 0; k < childObjs.length; k++ ){
					swapGantBar.add( childObjs[k] );
				}
				cellValNext[j] = "";
				swapGantTd = lineTdObjs[j];
			}
			else{
				cellValNext[j] = lineTdObjs[j].innerHTML;
			}
		}
		// 前行の初期値
		if( i == 0 ){
			cellValPre = cellValNext.clone();

			gantTd     = swapGantTd;
			// ガント要素を描画リストに追加
			while ( swapGantBar.hasnext() ){
				listGantBar.add( swapGantBar.next() );
			}
		}
		else{
			// 行のマージを行う場合
			if( margeRows == "true" ){
				// 前後行データの比較
				fgDiff = 0;
				for( var j = 0; j < countCells; j++ ){
					if( cellValPre[j] != cellValNext[j] ){
						cellValPre = cellValNext.clone();
						// 不一致あり
						fgDiff = 1;
						break;
					}
				}
			}
			// 行のマージを行わない場合
			else{
				fgDiff = 1;
			}
			// 
			if( fgDiff == 1 ){
				// ガント要素の出力
				bodyHeight += lineHeight + 2;
				// ガント要素の描画
				showGantBar( gantTd ,listGantBar ,lineHeight );
				// リスト削除
				listGantBar.head = null;
				listGantBar.size = 0;

				// 
				gantTd = swapGantTd;
				// ガント要素を描画リストに追加
				while ( swapGantBar.hasnext() ){
					listGantBar.add( swapGantBar.next() );
				}
			}
			// マージされるため、行要素の削除
			else{
				// ガント要素を描画リストに追加
				while ( swapGantBar.hasnext() ){
					listGantBar.add( swapGantBar.next() );
				}
				tBodyObjs[i].parentNode.removeChild( tBodyObjs[i] );
				i--;
				countTBody--;

			}
		}
	}
	// 最後一行の出力
	bodyHeight += lineHeight + 2;
	// ガント要素の描画
	showGantBar( gantTd ,listGantBar ,lineHeight );
	// リスト削除
	listGantBar.head = null;
	listGantBar.size = 0;
	//
	var headSpanObjs = headerObjs[0].all.tags("SPAN");
	var countBreakTimeSpan = 0;
	for( var i = 0; i < headSpanObjs.length; i++ ){
		if( headSpanObjs[i].className == "breaktime" ) countBreakTimeSpan++;
	}

	// breakTimeの調整
	var spanObjs = viewTableObj.all.tags("SPAN");
	var indexBreakTimeSpan = 0;
	if( spanObjs != null ){
		for( var i = 0 ;i < spanObjs.length ;i++  ){
			if( spanObjs[i].className == "breaktime" ){
				indexBreakTimeSpan++;
				if( indexBreakTimeSpan <= countBreakTimeSpan ){
					spanObjs[i].style.height = bodyHeight;
				}
				else{
					spanObjs[i].style.height = 0;
				}
			}
		}
	}

	//固定列数が設定される場合、テーブルの２分割処理を行う。
	if( fixedCols > 0 ){
		// 二分割の処理を行う。
		makeSuperTable( "viewTable" ,fixedCols );
	
	}
	// 休憩時間の網掛けを表示させる（高さ調整済）
	$(".breaktime").show();

// チューニング用
//var t2=(new Date())-t1;
//$("body").append("実行時間："+t2+"ms");

};

/* version: 0.0.1 
 * author : Sen Li
 * date   : 2012/05/10
 * 機能   : テーブルの左右2分割処理
 */

// セルの位置情報( 行 ,列 )
function cellNode( inRow ,inCol ){ 
	this.row   = inRow;
	this.col   = inCol;
}
// テーブル２分割処理
function makeSuperTable( viewTableId, fixedCols ) {
	// 初期化
	var scrollBarWidth  = 10;
	var scrollBarHeight = 20;
	// 左側の固定列数（初期値：0）
	fixedCols = parseInt( fixedCols || "0" );
	// 各列の幅
	colWidths = [];
	
	// 各枠のDIV要素作成
	ourterDiv = document.createElement( "DIV" );

	// ヘッダーの固定部
	fixedHeaderDiv  = ourterDiv.cloneNode( false );

	// ヘッダーのスクロール部分のベース枠
	scrollHeaderBaseDiv = ourterDiv.cloneNode( false );

	// ヘッダーのスクロール部分の枠
	scrollHeaderDiv = ourterDiv.cloneNode( false );

	// ボディの左固定部分のベース枠
	fixBodyBaseDiv = ourterDiv.cloneNode( false );

	// ボディの左固定部分の枠
	fixBodyDiv = ourterDiv.cloneNode( false );

	// ボディの右スクロール部分の枠
	scrollBodyDiv = ourterDiv.cloneNode( false );

	// ボディの右スクロール部分のテーブル
	scrollBodyTable = document.getElementById( viewTableId );
	// viewTableが存在しなければ終了
	if( scrollBodyTable == null ){ return false; }
	// 元のテーブルの縦横幅の取得
	var tableWidth  = scrollBodyTable.offsetWidth;
	var tableHeight = scrollBodyTable.offsetHeight;

	var sHeaderHeight;
	var tHead = scrollBodyTable.tHead;

	if( tHead ){
		sHeaderHeight = tHead.offsetHeight;
	}
	else{
		sHeaderHeight = scrollBodyTable.tBody[0].offsetHeight;
	}

	if( scrollBodyTable == null || fixedCols <= 0 ){ return true; }

	// スタイルの設定
	// -----------------------------------------------------
	// 外枠のスタイル
	ourterDiv.id		= "ourterDiv";
	// ヘッダーの固定部
	fixedHeaderDiv.id 	= "fixedHeaderDiv";
	// ヘッダーのスクロール部分のベース枠
	scrollHeaderBaseDiv.id = "scrollHeaderBaseDiv";
	// ヘッダーのスクロール部分の枠
	scrollHeaderDiv.id	   = "scrollHeaderDiv";
	// ボディの左固定部分のベース枠
	fixBodyBaseDiv.id	   = "fixBodyBaseDiv";
	// ボディの左固定部分の枠
	fixBodyDiv.id		   = "fixBodyDiv";
	// ボディの右スクロール部分の枠
	scrollBodyDiv.id	   = "scrollBodyDiv";

	// -----------------------------------------------------
	// カラムスタイル
	colGroupStyle    = document.createElement("COLGROUP");

	// IE幅
	var windowWidth  = getClientWidth();
	// テーブルのトップ位置
	var tableTop= scrollBodyTable.offsetTop;

	// IEの高さ
	var windowHeight = getClientHeight();
	// 
	// テーブルの実レイアウトによりCOLGROUPを作成するため、既存のCOLGROUPを削除する。
	for( i = scrollBodyTable.getElementsByTagName( "COLGROUP" ).length-1 ;i >= 0 ;i-- ){
		scrollBodyTable.removeChild( scrollBodyTable.getElementsByTagName( "COLGROUP" )[i] );
	}
	// 
	sParent 		 = scrollBodyTable.parentNode;
	sParentHeight 	 = sParent.offsetHeight;
	sParentWidth 	 = sParent.offsetWidth;
	
	// スワップ変数
	var alpha, beta, i, j;
	// ヘッダーのスクロール部分のテーブル作成
	scrollHeaderTable = scrollBodyTable.cloneNode( false );
	// ヘッダーのスクロール部分のテーブルのスタイル設定
	scrollHeaderTable.id ="scrollHeaderTable" ;

	// 元のテーブルにtHeadが存在すれば、そのtHeadをコピーする。
	if( tHead ) {
		alpha = tHead;
		// ヘッダーのスクロール部分のテーブル作成
		scrollHeaderTable.appendChild( alpha.cloneNode( true ));
	} else {
		alpha = scrollBodyTable.tBodies[0];
		scrollHeaderTable.appendChild( alpha.cloneNode( true ));
	}

	// ヘッダーのスクロール部分のテーブルをDIVに入れる。
	scrollHeaderDiv.appendChild( scrollHeaderTable );
	
	fixedHeaderTable = scrollHeaderTable.cloneNode( true );
	// スタイル設定
	fixedHeaderTable.id = "fixedHeaderTable";

	fixedHeaderDiv.appendChild(fixedHeaderTable);
	// ボディの左固定部のテーブル

	fixedBodyTable = scrollBodyTable.cloneNode( true );
	// ボディの左固定部のテーブルのスタイル
	fixedBodyTable.id = "fixedBodyTable";
	fixBodyDiv.appendChild( fixedBodyTable );
	
	// カラムスタイルの設定
	var tBodyRows       = scrollBodyTable.tBodies[0].rows;
	var tBodyRowsLength = tBodyRows.length;
	var maxCellRow      = 0;
	var countRowCells   = 0;

	// クリティカルパスの作成準備
	var cellColSpan     = 0;
	var cellRowSpan     = 0;
	var countSingleCol  = 0;
	var colLength       = tBodyRows[0].cells.length;
	for( i = 0; i < colLength; i++ ){
		countSingleCol += tBodyRows[0].cells[i].colSpan;
	}
	// 
	var cellGridMap     = new Array( tBodyRowsLength );

	// 行毎のセル番号のキャッシュ
	var colIndex = new Array( tBodyRowsLength );
	for( rowId = 0; rowId < tBodyRowsLength; rowId++ ){
		cellGridMap[rowId] = new Array( countSingleCol );
		colIndex[rowId]=0;
	}
	// cellGridMapの作成
	for( rowId = 0; rowId < tBodyRowsLength; rowId++ ){
		colLength    = tBodyRows[rowId].cells.length;
		for( colId = 0; colId < colLength; colId++ ){
			cellRowSpan = tBodyRows[rowId].cells[colId].rowSpan;
			cellColSpan = tBodyRows[rowId].cells[colId].colSpan;
			for( j = 0 ;j < cellColSpan ;j++ ){
				for( i = 0 ;i < cellRowSpan ;i++ ){
					// 空セルを探す。
					for( m =0 ;m < countSingleCol; m++ ){
						if( cellGridMap[rowId + i][ colIndex[rowId]] != null ) colIndex[rowId]++;
					}
					// セル情報のキャッシュ
					cellGridMap[rowId + i][ colIndex[rowId] ] = new cellNode( rowId ,colId );
				}
				colIndex[rowId]++;
			}

		}
	}
//	cellGridMapの出力（debug用）
//	for(i=0 ;i<tBodyRowsLength ;i++){
//		for(j=0 ;j<countSingleCol ;j++){
//			alert("(" + cellGridMap[i][j].row + "," + cellGridMap[i][j].col + ")");
//		}
//	}

	// クリティカルパスの作成
	var keyCells = [];
	var index    = 0;
	for( j = 0 ;j < countSingleCol ;j++ ){
		for( i = 0 ;i < tBodyRowsLength ;i++ ){
			cellColSpan = tBodyRows[ cellGridMap[i][j].row ].cells[ cellGridMap[i][j].col ].colSpan;
			if( cellColSpan == 1 ){
				keyCells[index] = new cellNode( cellGridMap[i][j].row ,cellGridMap[i][j].col );
				index++
				break;
			}
		}
	}

	// クリティカルパスにより、各列の幅を取得する。
	for( i=0; i < countSingleCol; i++){
		colWidths[i] = tBodyRows[ keyCells[i].row ].cells[ keyCells[i].col ].offsetWidth;
	}

	// colspanによる幅の誤差計算
	var fixedDivDiff = 0;
	var totalDiff    = 0;
	index = 0;
	// 誤差計算
	for( i = 0 ; i < countSingleCol ;i++ ){
		if( colWidths[i] > SYS_CELLPADDING ){
			colWidths[i] -= SYS_CELLPADDING;
		}
		else{
			if( i < fixedCols ){
				fixedDivDiff += SYS_CELLPADDING * 1;
			}
			totalDiff        += SYS_CELLPADDING * 1;
		}
		i += tHead.rows[0].cells[index++].colSpan - 1 ;
	}

	// 誤差を加味する。
	var fixedHeaderDivWidth = tBodyRows[ keyCells[fixedCols].row ].cells[ keyCells[fixedCols].col ].offsetLeft + fixedDivDiff;

	// カラムスタイルを一致させる
	for( i = 0, j = colWidths.length; i < j; i++ ){
		colGroupStyle.appendChild( document.createElement( "COL" ));
		colGroupStyle.lastChild.setAttribute( "width", colWidths[i] );
	}

	// ボディ部のスクロールテーブル
	scrollBodyTable.insertBefore(    colGroupStyle.cloneNode( true ), scrollBodyTable.firstChild   );
	// ヘッダー部のスクロールテーブル
	scrollHeaderTable.insertBefore(  colGroupStyle.cloneNode( true ), scrollHeaderTable.firstChild );
	// ボディの固定部分
	fixedBodyTable.insertBefore(     colGroupStyle.cloneNode( true ), fixedBodyTable.firstChild    );
	// ヘッダーの固定部分
	fixedHeaderTable.insertBefore(   colGroupStyle.cloneNode( true ), fixedHeaderTable.firstChild  );
	
	// 画面に外枠(ourterDiv)の出力
	sParent.insertBefore( ourterDiv, scrollBodyTable );

	// ヘッダーの固定部を外枠(ourterDiv)に入れる
	ourterDiv.appendChild( fixedHeaderDiv );
	// 
	scrollHeaderBaseDiv.appendChild( scrollHeaderDiv );
	// ヘッダーのスクロール部を外枠(ourterDiv)に入れる
	ourterDiv.appendChild( scrollHeaderBaseDiv );

	// ボディの固定部を外枠(ourterDiv)に入れる
	ourterDiv.appendChild( fixBodyBaseDiv );

	fixBodyBaseDiv.appendChild( fixBodyDiv );
	// ボディのスクロール部を外枠(ourterDiv)に入れる
	ourterDiv.appendChild( scrollBodyDiv );

	scrollBodyDiv.appendChild( scrollBodyTable );

	// 左固定部の幅を設定する。
	fixedHeaderDiv.style.width = fixedHeaderDivWidth + "px";
	
	// テーブルのスタイル設定
	var scrollBodyDivStyles, scrollBodyTableStyles;

	scrollBodyTableStyles = "margin-top: " + ( sHeaderHeight * -1 ) + "px;";
	scrollBodyDivStyles   = "margin-top: " +   sHeaderHeight + "px;";

	// テーブル幅のトータル誤差を加味する。
	tableWidth = tableWidth + totalDiff;
	var ourterDivWidth = ( tableWidth  + scrollBarWidth  ) > windowWidth             ? windowWidth             : ( tableWidth  + scrollBarWidth ) ;
	var ourterDivHeight= ( tableHeight + scrollBarHeight ) > windowHeight - tableTop ? windowHeight - tableTop : ( tableHeight + scrollBarHeight) ;

	ourterDiv.style.width  = ourterDivWidth ;
	ourterDiv.style.height = ourterDivHeight;

	scrollBodyDivStyles += "height: " + (ourterDivHeight - sHeaderHeight) + "px;";

	// ボディのスクロール部のテーブルのスタイル
	scrollBodyTableStyles += "margin-left: " + (fixedHeaderDivWidth * -1) + "px;";
	scrollBodyTableStyles += "table-layout: fixed;";

	// ボディのスクロール部の枠のスタイル
	scrollBodyDivStyles += "margin-left: " + fixedHeaderDivWidth + "px;";
	scrollBodyDivStyles += "width: " + ( ourterDivWidth - fixedHeaderDivWidth ) + "px;";

	scrollBodyDiv.style.cssText   = scrollBodyDivStyles;
	scrollBodyTable.style.cssText = scrollBodyTableStyles;

	// スクロールのイベント処理
	scrollBodyDiv.onscroll = function () {
		// scrollHeaderDivをscrollBodyDivのスクロール（横方向）と連動させる。
		scrollHeaderDiv.style.right = scrollBodyDiv.scrollLeft + "px";
		// fixBodyDivをscrollBodyDivのスクロール（縦方向）と連動させる。
		fixBodyDiv.style.top = (scrollBodyDiv.scrollTop * -1) + "px";
	};
	return true;
};

// メイン処理（画面から呼び出す）
function adjustTable(){
// チューニング用
//var t1=new Date();
	// iTable
	var iTable = document.getElementsByTagName( "iTable" );
	// iTableが存在しなければ終了
	if( iTable == null || iTable.length == 0 ){ return false; }
	// 
	fixedCols = parseInt( iTable[0].fixedCols || "0" );
	
	// 二分割の処理を行う。
	makeSuperTable( "viewTable" ,fixedCols );
	
	// チューニング用
//var t2=(new Date())-t1;
//$("body").append("実行時間："+t2+"ms");
};

// 実際に呼び出す場合は引数でコントロールする
return function(_mode){
	if(_mode == 'adjustTable'){
		adjustTable();
	}
	else if(_mode == 'adjustGant'){
		adjustGant();
	}
};
})();

// クロージャー外からのCall用
function adjustTable(){
	adjustGantTable('adjustTable');
};

function adjustGant(){
	adjustGantTable('adjustGant');
};
