/********************************************************************************

	スクローラーセッター
		作成者	Masashi Kikkawa

	【説明】
		ページ内リンクのa要素及びarea要素のclass属性に「scroller」を入れると
		クリック時に該当位置までスムーズスクロールする。

	【更新履歴】
		2007.10.12 v.1.06
			v.1.03の改良で、MacIEで動作しなくなっていたバグを修正。
			area要素に対応。
		2007.08.21 v.1.05
			DOCTYPEによっては現在のスクロール量が正確に取得できないバグを修正。
		2007.08.04 v.1.04
			ブラウザ、OS判定を追加。
		2007.08.03 v.1.03
			ブラウザの戻るボタン対策のバグを修正。
			ソースを全面書き直し。
		2007.07.31 v.1.02
			ブラウザの戻るボタンでスクロール前の位置に戻れるように改良。
			横方向のスクロールを廃止。
		2007.07.30 v.1.01
			終点位置を-20pxに修正。
		2007.07.27 v.1.00
			公開。

********************************************************************************/




//_______________________________________________________________________________
//	スクローラー
var	eoScroller	=	new class_eoScroller();
function	class_eoScroller()
{
	this.objOnload	=	window.onload;	//	既存のonloadイベント

	//	定数
	this.vSCROLL_SMOOTH	=	20;	//	スクロールの滑らかさ
	this.vSCROLL_STEP	=	15;	//	スクロールステップ数

	//	変数
	this.vNowX	=	0;	//	スクロール前のX座標
	this.vNowY	=	0;	//	スクロール前のY座標
	this.vTgtY	=	0;	//	スクロール後のY座標
	this.vTgtID	=	'';	//	スクロール先ID
	this.vCnt	=	0;	//	スクロールカウント

	this.objHistory	=	'';	//	ブラウザの戻るボタン対策オブジェクト

	//___________________________________________________________________________
	//	スクローラ初期化
	this.Init	=	function()
	{
		var	vHistory;
		var	aAncList	=	new Array();
		var	aAreaList	=	new Array();
		var	aAncStock	=	new Array();

		//	既存のonLoadイベントを実行
		if( this.objOnload != null )	this.objOnload();

		//	動作環境判定
		if(
			( eoEnv.vOS == 'Mac' && eoEnv.vBrowser == 'IE' )	//	Mac+IE
			|| ( eoEnv.vBrowser == 'NS' )						//	NS
		)
		{
			return;
		}

		//	ブラウザの戻るボタン対策（divを追加）
		vHistory				=	document.createElement( 'div' );
		vHistory.id				=	'eoHistory';
		vHistory.style.position	=	'absolute';
		vHistory.style.top		=	'0px';
		document.body.appendChild( vHistory );
		this.objHistory			=	document.getElementById( 'eoHistory' );

		//	<a>の一覧を取得して検索
		aAncList	=	document.getElementsByTagName( 'a' );
		for( var i=0; i<aAncList.length; i++ )
		{
			//	クラス名判定
			if( aAncList[i].className == 'scroller' )
			{
				aAncStock[aAncStock.length]	=	aAncList[i];
			}
		}

		//	<area>の一覧を取得して検索
		aAreaList	=	document.getElementsByTagName( 'area' );
		for( var i=0; i<aAreaList.length; i++ )
		{
			//	クラス名判定
			if( aAreaList[i].className == 'scroller' )
			{
				aAncStock[aAncStock.length]	=	aAreaList[i];
			}
		}

		//	イベントセット
		for( var i=0; i<aAncStock.length; i++ )
		{
			var	vHref	=	aAncStock[i].getAttribute( 'href' );
			if( vHref )
			{
				//	#以前の余分なパスを消去
				vHref	=	vHref.replace( /.*#/, '#' );

				//	ページ内リンク判定
				if( vHref.charAt('0') == '#' )
				{
					//	イベント設定
					aAncStock[i].onclick	=	function()
					{
						eoScroller.Set( this );
						return false;
					}
				}
			}
		}
	};

	//___________________________________________________________________________
	//	スクロールセット
	this.Set	=	function( vObj )
	{
		var	objTgt;
		var	vNextAnc;

		//	移動先IDの取得
		this.vTgtID	=	vObj.hash.substring( 1 );

		//	移動先オブジェクトの取得
		objTgt	=	document.getElementById( this.vTgtID );

		//	現在の座標を取得
		this.vNowX	=	this._GetScrollX( window );
		this.vNowY	=	this._GetScrollY( window );

		//	目的の座標を取得
		this.vTgtY	=	this._GetTargetScrollY( window, objTgt );

		//	カウント初期化
		this.vCnt	=	0;

		//	実行
		this.Do();

		//	ブラウザの戻るボタン対策
		vNextAnc	=	this.vTgtID + ( new Date() * 1 );
		this.objHistory.style.top	=	this.vNowY + 'px';
		this.objHistory.id			=	vNextAnc;
		document.location.hash		=	vNextAnc;
	};

	//___________________________________________________________________________
	//	スクロール実行（再帰）
	this.Do	=	function()
	{
		var	vY	=	this._Easing( this.vNowY, this.vTgtY, this.vCnt/this.vSCROLL_STEP , 100, 4 );

		//	カウントアップ
		this.vCnt	+=	1;

		//	スクロール
		if( this.vCnt < this.vSCROLL_STEP )
		{
			scrollTo( this.vNowX, vY );
			setTimeout( "eoScroller.Do()", 20 );
		}
		else
		{
			scrollTo( this.vNowX, this.vTgtY );
		}
	};

	//___________________________________________________________________________
	//	現在のスクロールX値を取得
	this._GetScrollX	=	function( objWin )
	{
		return	document.body.scrollLeft || document.documentElement.scrollLeft;
	};
	//___________________________________________________________________________
	//	現在のスクロールY値を取得
	this._GetScrollY	=	function( objWin )
	{
		return	document.body.scrollTop || document.documentElement.scrollTop;
	};
	//___________________________________________________________________________
	//	対象のスクロールY値を取得
	this._GetTargetScrollY	=	function( objWin, objTgt )
	{
		var	vY, vMaxY;
		var	objTmp;

		//	目的の座標を取得
		objTmp	=	objTgt;
		vY	=	objTmp.offsetTop;
		while( objTmp.offsetParent )
		{
			objTmp	=	objTmp.offsetParent;
			vY		+=	objTmp.offsetTop;
		}

		//	スクロール量の最大値を取得
		if( objWin.innerHeight )
		{	//	Safari用
			vMaxY	=	objWin.document.body.offsetHeight - objWin.innerHeight;
		}
		else if( document.documentElement && document.documentElement.clientHeight )
		{	//	Mozilla用
			vMaxY	=	objWin.document.body.offsetHeight - objWin.document.documentElement.clientHeight;
		}

		//	位置補正
		vY	=	( vY >= 20 )?	vY-20:	vY;

		//	スクロールしきらない場合は目的座標を修正
		if( vMaxY && vY > vMaxY )
		{
			vY	=	vMaxY + objTgt.offsetHeight;
		}

		return	vY;
	};

	//___________________________________________________________________________
	//	イージング
	//		vSttVal		開始値
	//		vEndVal		終了値
	//		vCnt		カウント（0〜1）
	//		vEasing		イージング値（-100〜100）
	//		vEasingLv	イージングレベル（1以上の実数）
	this._Easing	=	function( vSttVal, vEndVal, vCnt, vEasing, vEasingLv )
	{
		var vN;

		if( vEasing <= 0 )
		{
			vN = ( 1-vEasingLv ) / 100 * vEasing + 1;
			return vSttVal + ( vEndVal - vSttVal ) * Math.pow( vCnt, vN );
		}
		else
		{
			vN = ( vEasingLv - 1 ) / 100 * vEasing + 1;
			return vEndVal - ( vEndVal - vSttVal ) * Math.pow( 1 - vCnt, vN );
		}
	};
}




//_______________________________________________________________________________
//	環境
if( typeof( eoEnv ) == 'undefined' )
{
	function	class_eoEnv()
	{
		this.vBrowser	=	'';
		this.vOS		=	'';

		//_________________________________________________________________________
		//	環境初期化
		this.Init	= function()
		{
			var	vUA	=	navigator.userAgent;

			//	ブラウザ判定
			if( vUA.indexOf( 'MSIE' ) != -1 )			this.vBrowser	=	'IE';
			else if( vUA.indexOf( 'Firefox' ) != -1 )	this.vBrowser	=	'FF';
			else if( vUA.indexOf( 'Netscape' ) != -1 )	this.vBrowser	=	'NS';
			else if( vUA.indexOf( 'Opera' ) != -1 )		this.vBrowser	=	'OP';
			else if( vUA.indexOf( 'Safari' ) != -1 )	this.vBrowser	=	'SA';
			else										this.vBrowser	=	vUA;

			//	OS判定
			if( vUA.indexOf( 'Win' ) != -1 )		this.vOS	=	'Win';
			else if( vUA.indexOf( 'Mac' ) != -1 )	this.vOS	=	'Mac';
			else									this.vOS	=	vUA;
		};
	}

	//	環境初期化実行
	var	eoEnv	=	new class_eoEnv();
	eoEnv.Init();
}




//_______________________________________________________________________________
//	window.onloadにセット
window.onload	=	function()
{
	//	スクローラー初期化
	eoScroller.Init();
}





