﻿//フローティングをセットする
var setFollow;
var getFixedBoxPos;
var followEventVectorDown;


$(document).ready(function() {

// IE 7.0 以上 または モダンブラウザー
var modernBrowser = typeof document.body.style.maxHeight != "undefined";
//フローティングのアニメーション回数
var followCount = 0;
//フローティングのアニメーションリトライ数
var followCountReTry = 0;
//上Fixed用
var topFixedAnimationEnd = false;	//2回アニメーションをさせない為に使用
var topFixedAnimationEnd2 = false;	//2回アニメーションをさせない為に使用
//下Relative用
var bottomRelativeAnimationEnd = false ; //2回アニメーションさせない為に使用
var bottomRelativeAnimationEnd2 = false; //2回アニメーションさせない為に使用
//下Fixed用
var bottomFixedAnimationEnd = false;	//2回アニメーションさせない為に使用
var stopF; //2回ストップさせない為に使用
//1イベント前の値
var beforeBoxTop;
var beforeScrollTop;
//Fixed時のオフセット値
var fixedOffsetTop;
//アニメーションのスピード
var animationSpeed = 120; //仮　動きを分かりやすくするために10倍にしている
//アニメーション開始遅延時間
var delayTime;
var delayTimerId;
var DELAT_TIME_FIXED = 0;
var DELAT_TIME_IE6 = 100;
//スクロールの移動量
var scrollVector;
//アニメーションフラグ true:アニメーションする false:アニメーションしない
var animationFlag;


//ウィンドウボックスモデル
var windowBox = {
	top:0,
	height:0,
	setValuse: function () {
		windowBox.top = $(window).scrollTop();
		windowBox.height = $(window).height();
	}
}


//フローティングエリアボックスモデル
var areaBox = {
	areaName:"",//フローティングエリアの名前(例：#movable)
	top:0,
	bottom:0,
	height:0,
	setValue: function () {
		areaBox.top = $(areaBox.areaName).offset().top;
		areaBox.bottom = $(areaBox.areaName).offset().top + $(areaBox.areaName).outerHeight({margin: true});
		areaBox.height = $(areaBox.areaName).outerHeight({margin: true});
	}
}


//フローティングボックスモデル
var followBox = {
	name:"",//フローティングボックスの名前(例：#cart)
	top:0,
	bottom:0,
	height:0,
	setValue: function () {
		followBox.top = $(followBox.name).offset().top;
		followBox.bottom = $(followBox.name).offset().top + $(followBox.name).outerHeight({margin: true});
		followBox.height = $(followBox.name).outerHeight({margin: true});
		//fixedの時は値の取得方法を変える
		if ($(followBox.name).css("position") == "fixed") {
			followBox.top = windowBox.top + fixedOffsetTop;
			followBox.bottom = windowBox.top + fixedOffsetTop + $(followBox.name).outerHeight({margin: true});
		}
	}
}


//リミットモデル
var LimitModel = {
	areaTopLimit:0,		//エリア上限
	areaBottomLimit:0,	//エリア下限
  boxTopLimit:0,	//ボックス上限
	boxBottomLimit:0,	//ボックス下限
	setLimitValue: function () {
		LimitModel.areaTopLimit =  windowBox.top <= areaBox.top;
		LimitModel.areaBottomLimit = windowBox.height <= followBox.height && windowBox.top + windowBox.height >= areaBox.bottom
			|| windowBox.height > followBox.height && windowBox.top > areaBox.bottom - followBox.height;
		LimitModel.boxTopLimit = windowBox.top <=  followBox.top;
		LimitModel.boxBottomLimit = (windowBox.top + windowBox.height) >= followBox.bottom;
	}
}


//フローティングをセットする
setFollow = function(arg1, arg2) {
	followBox.name = arg1;
	areaBox.areaName = arg2;
	topFixedAnimationEnd = false;
	topFixedAnimationEnd2 = false;
	bottomRelativeAnimationEnd = false;
	bottomRelativeAnimationEnd2 = false;
	bottomFixedAnimationEnd = false;
	stopF = false;
	//イベントハンドラを設定
	setEvent();
	//初回呼び出し
	followEvent(false);

}


//フラグをリセットしてフローティングイベントを実行する
function resetFollowEvent(animationF) {
	topFixedAnimationEnd = false;
	topFixedAnimationEnd2 = false;
	bottomRelativeAnimationEnd = false;
	bottomRelativeAnimationEnd2 = false;
	bottomFixedAnimationEnd = false;
	stopF = false;
	followEvent(animationF);
}


//fixedを使用する独自のフローティングメソッド
function followEvent(animationF) {

	//値をリフレッシュする
	setValues(animationF);

	if (windowBox.top - beforeScrollTop != 0) {

		scrollVector = $(window).scrollTop() - beforeScrollTop;		//スクロール移動量

		//アニメーションキューを削除する
		$(followBox.name).queue( [ ] );

		//アニメーション開始遅延処理
		if(delayTime > 0) {

			if (delayTimerId) {
				clearTimeout(delayTimerId)
			}

			delayTimerId = setTimeout(function() {followEventEx()}, delayTime);

		}
		//アニメーション開始遅延処理を行わない
		else {
			followEventEx()
		}

	}

	resizeAreaBox();

}

followEventVectorDown = function() {
	scrollVector = 1;

	//値をリフレッシュする
	setValues(true);

	//アニメーションキューを削除する
	$(followBox.name).queue( [ ] );
	followEventEx()
}


function setValues(animationF) {
	windowBox.setValuse();
	areaBox.setValue();
	followBox.setValue();
	LimitModel.setLimitValue();
	animationFlag = animationF;
}


function followEventEx() {

	//ボックスがウィンドウに納まっている
	if ( windowBox.height > followBox.height) {

		//上Fixed(上フローティング)
		if (!LimitModel.areaTopLimit && !LimitModel.areaBottomLimit) {
			topFixed(false, animationFlag, scrollVector);
		}
		else {
			//上Relative(エリア上限)
			if (LimitModel.areaTopLimit) {
				topRelative(false, animationFlag, scrollVector);
			}
			//下Relative(エリア下限)
			if (LimitModel.areaBottomLimit) {
				bottomRelative(false, animationFlag, scrollVector);
			}
		}

	}
	//ウィンドウに収まらない
	else {

		//上方向に移動
		if (scrollVector < 0) {
			//上Fixed(上フローティング)
			if (!LimitModel.areaTopLimit) {
				//上 fixed(フローティング上)
				if (LimitModel.boxTopLimit) {
					topFixed(true, animationFlag, scrollVector);
				}
				//relative(その場に止る)
				else {
					stopRelative(animationFlag, scrollVector);
				}
			}
			//上Relative(エリア上限)
			else {
				topRelative(true, animationFlag, scrollVector);
			}
		}

		//下方向に移動
		else if (scrollVector > 0) {
			//下fixed(フローティング下)
			if (!LimitModel.areaBottomLimit) {
				//下 fixed(ボックス下限)
				if (LimitModel.boxBottomLimit) {
					bottomFixed(animationFlag, scrollVector);
				}
				//その場に止まる
				else {
					stopRelative(animationFlag, scrollVector);
				}
			}
			//下Relative(エリア下限)
			else {
				bottomRelative(true, animationFlag, scrollVector);
			}

		}
	}

	beforeBoxTop = followBox.top;
	beforeScrollTop = windowBox.top;

}


//上 fixed(フローティング上)
function topFixed(sizeOver, animationF, scrollVector) {

	if (!sizeOver){

		if (!topFixedAnimationEnd) {

			topFixedAnimation(animationF, scrollVector);
			bottomRelativeAnimationEnd = false;

		}
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			topFixedAnimationEnd = true;
	  }
	} else {

		if (!topFixedAnimationEnd2) {
			topFixedAnimation(animationF, scrollVector);
			bottomFixedAnimationEnd = false;
			bottomRelativeAnimationEnd2 = false;

		}
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			topFixedAnimationEnd2 = true;
		}
	}

}


//上 fixed(フローティング上) アニメーション
function topFixedAnimation(animationF, scrollVector) {
	if (animationF) {
		$(followBox.name).animate({
		top: (windowBox.top - areaBox.top) + "px"
		},
		{
			duration: animationSpeed ,
			complete: function () {
				// IE 7.0 以上 または モダンブラウザー
				if (modernBrowser) {
					fixedOffsetTop = 0;
					$(followBox.name).css("position", "fixed");
					$(followBox.name).css("top", fixedOffsetTop);
				}
				stopF = false;
			}
		});
	} else {
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			fixedOffsetTop = 0;
			$(followBox.name).css("position", "fixed");
			$(followBox.name).css("top", fixedOffsetTop);
		}
		stopF = false;
	}
}


//下Fixed
function bottomFixed(animationF, scrollVector) {
	//Relative(FollowBoxの下限) → 下Fixed
	if (!bottomFixedAnimationEnd) {
		if (animationF) {
			setValues(animationF);
			$(followBox.name).animate({
			top: ((windowBox.top + windowBox.height) -  (followBox.height + areaBox.top)) + "px"
			},
			{
				duration: animationSpeed ,
				complete: function () {
				  beforeBoxTop = followBox.top;
					// IE 7.0 以上 または モダンブラウザー
					if (modernBrowser) {
						fixedOffsetTop = (windowBox.height - followBox.height);
						$(followBox.name).css("position", "fixed");
						$(followBox.name).css("top", fixedOffsetTop + "px");
					}
					stopF = false;
				}
			});
		} else {
			$(followBox.name).css("position", "relative");
			$(followBox.name).css("top", (areaBox.height - followBox.height) + "px");
		}
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			bottomFixedAnimationEnd = true;
		}
	}

}


//上Relative(エリア上限)
function topRelative(sizeOver, animationF, scrollVector) {
  //アニメーションキューを削除する
	$(followBox.name).stop();

	$(followBox.name).css("position", "relative");
	$(followBox.name).css("top", 0);

	if (!sizeOver) {
		topFixedAnimationEnd = false;
		bottomRelativeAnimationEnd = false;
	} else {
		topFixedAnimationEnd2 = false;
		bottomRelativeAnimationEnd2 = false;
	}

}


//下Relative(エリア下限)
function bottomRelative(sizeOver, animationF, scrollVector) {

	if (!sizeOver) {
		if (!bottomRelativeAnimationEnd) {
			$(followBox.name).css("position", "relative");
			$(followBox.name).css("top", (windowBox.top - areaBox.top) + "px");
			bottomRelativeAnimation(animationF, scrollVector);
		}
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			bottomRelativeAnimationEnd = true;
		}
		topFixedAnimationEnd = false;
	} else {
		if (!bottomRelativeAnimationEnd) {
			$(followBox.name).css("position", "relative");
			$(followBox.name).css("top", (areaBox.height - followBox.height) + "px");
			bottomRelativeAnimation(animationF, scrollVector);
		}
		// IE 7.0 以上 または モダンブラウザー
		if (modernBrowser) {
			bottomRelativeAnimationEnd2 = true;
		}
		topFixedAnimationEnd2 = false;
	}

}


//下Relative(エリア下限)アニメーション
function bottomRelativeAnimation(animationF, scrollVector) {

	if (animationF) {
		setValues(animationF);
		$(followBox.name).animate({
		top: (areaBox.height - followBox.height) + "px"
		},
		{
			duration: animationSpeed ,
			complete: function () {
				beforeBoxTop = followBox.top;

				$(followBox.name).css("position", "relative");
				$(followBox.name).css("top", (areaBox.height - followBox.height) + "px");
			}
		});
	} else {
		$(followBox.name).css("position", "relative");
		$(followBox.name).css("top", (areaBox.height - followBox.height) + "px");
	}

}


//その場に止る処理
function stopRelative(animationF, scrollVector) {

	if (!stopF) {
		$(followBox.name).css("position", "relative");
		$(followBox.name).css("top", (followBox.top - areaBox.top) + "px");

		if (animationF) {
			$(followBox.name).animate({
			top: (beforeBoxTop - areaBox.top) + "px"
			},
			{
				duration: animationSpeed ,
				complete: function () {
					beforeBoxTop = followBox.top;

					stopF = true;
				}
			});
		} else {
			$(followBox.name).css("top", (beforeBoxTop - areaBox.top) + "px");
			stopF = true;
		}
	}
	topFixedAnimationEnd = false;
	topFixedAnimationEnd2 = false;
	bottomRelativeAnimationEnd = false;
	bottomRelativeAnimationEnd2 = false;
	bottomFixedAnimationEnd = false;

}


//イベントハンドラを設定する
function setEvent() {
	$(window).scroll(function(){
		followEvent(true);
	});
}

//エリア高さをボックス高さが超えた場合、エリア高さをボックス高さにする。
function resizeAreaBox() {
	if ($(areaBox.areaName).outerHeight({margin: true}) < $(followBox.name).outerHeight({margin: true})) {
		 $(areaBox.areaName).css("height", $(followBox.name).outerHeight({margin: true}))
	}
}

//フローティングボックスの位置を返す
getFixedBoxPos = function() {
	var top;
	top = $(followBox.name).offset().top;

	//fixedの時は値の取得方法を変える
	if ($(followBox.name).css("position") == "fixed") {
		top = windowBox.top + fixedOffsetTop;
	}

	return {y:top};
}

if(modernBrowser) {
	delayTime = DELAT_TIME_FIXED;
} else {
	delayTime = DELAT_TIME_IE6;
}


});

