/********************************************************************************

	スクローラーセッター
		作成者	Masashi Kikkawa

	【説明】
		ページ内リンクのa要素及びarea要素のclass属性に「scroller」を入れると
		クリック時に該当位置までスムーズスクロールする。

	【更新履歴】
		2008.07.03 v.1.08
			v1.07の改良で、MacIEで動作しなくなっていたバグを修正。
		2008.05.15 v.1.07
			複数のクラス指定に対応。
		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( /(^|\s)scroller(\s|$)/.test( aAncList[i].className ) )
			{
				aAncStock[aAncStock.length]	=	aAncList[i];
			}
		}

		//	<area>の一覧を取得して検索
		aAreaList	=	document.getElementsByTagName( 'area' );
		for( var i=0; i<aAreaList.length; i++ )
		{
			//	クラス名判定
			if( /(^|\s)scroller(\s|$)/.test( aAreaList[i].className ) )
			{
				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();
}





