var $scroll = function(obj){
	return document.getElementById(obj);
};

var addEvent = function(elm, evType, fn, useCapture) {
	if (elm.addEventListener) {
		elm.addEventListener(evType, fn, useCapture);
		return true;
	}
	else if (elm.attachEvent) {
		var r = elm.attachEvent('on' + evType, fn);
		return r;
	}
	else {
		elm['on' + evType] = fn;
	}
}


// scrollBy だと、終了条件の設定が難しい。また、現在のスクロール位置の影響を受ける
// 正の移動で、スクロール限界に引っかかると無限ループ
// onClick等でキャンセル


var scroll = {
	leap: function(idname){
		var start = this.getScrollPos();
		var obj = $scroll(idname);
		var goal = this.getElementPos(obj);
		
		var moveY = goal.y - start.y;
		var moveX = goal.x - start.x;

		var direction = new Object;
		direction.x = moveX > 0 ? 'plus' : 'minus'
		direction.y = moveY > 0 ? 'plus' : 'minus'

		var maxScroll = this.getMaxScroll();
		goal.x = goal.x > maxScroll.x ? maxScroll.x : goal.x;
		goal.y = goal.y > maxScroll.y ? maxScroll.y : goal.y;

		this.land(goal,direction);
		this.cancel();
	},

	land: function(goal,direction){
		var pos = this.getScrollPos();
		var arrive = new Object;
		arrive.x = direction.x == 'plus'
			? Math.floor(pos.x + ((goal.x - pos.x) / 5)) + 1
			: arrive.x = Math.max(Math.floor(pos.x - (pos.x / 6)),goal.x);
		arrive.y = direction.y == 'plus'
			? Math.floor(pos.y + ((goal.y - pos.y) / 5)) + 1
			: arrive.y = Math.max(Math.floor(pos.y - (pos.y / 6)),goal.y)

		scrollTo(arrive.x,arrive.y);

		if(direction.y == 'plus' && direction.x == 'plus') {
			if(arrive.y < goal.y || arrive.x < goal.x){
				this.timerID = setTimeout( function(){ scroll.land(goal,direction) },10);
			}
		}
		else if(direction.y == 'plus' && direction.x == 'minus') {
			if(arrive.y < goal.y || arrive.x != goal.x){
				this.timerID = setTimeout( function(){ scroll.land(goal,direction) },10);
			}
		}
		else if(direction.y == 'minus' && direction.x == 'plus') {
			if(arrive.y != goal.y || arrive.x < goal.x){
				this.timerID = setTimeout( function(){ scroll.land(goal,direction) },10);
			}
		}
		else if(direction.y == 'minus' && direction.x == 'minus') {
			if(arrive.y != goal.y || arrive.x != goal.x){
				this.timerID = setTimeout( function(){ scroll.land(goal,direction) },10);
			}
		}
		else {
			console.log('error!');
		}

//console.log(direction);
//console.log(arrive,goal);
//console.log(pos.y);
	},

	cancel: function(){
		addEvent(document,'mousedown',function(){clearTimeout(scroll.timerID)},false);
		addEvent(document,'keydown',function(){clearTimeout(scroll.timerID)},false);
		addEvent(document,'mousewheel',function(){clearTimeout(scroll.timerID)},false);
		addEvent(document,'DOMMouseScroll',function(){clearTimeout(scroll.timerID)},false);
	},

	getMaxScroll: function(){
		var scrSize = this.getScreenSize();
		var docSize = this.getDocSize();

		var maxScroll = new Object;
		maxScroll.x = docSize.x - scrSize.x;
		maxScroll.y = docSize.y - scrSize.y;
		
		return maxScroll;
	},

	getElementPos: function(elem){
		var obj = new Object();
		obj.x = elem.offsetLeft;
		obj.y = elem.offsetTop;

		while(elem.offsetParent) {
			elem = elem.offsetParent;
			obj.x += elem.offsetLeft;
			obj.y += elem.offsetTop;
		}
		return obj;
	},

	getScrollPos: function(){
		var pos = new Object();
		pos.x = document.documentElement.scrollLeft || document.body.scrollLeft;
		pos.y = document.documentElement.scrollTop || document.body.scrollTop;
		return pos;
	},

	getDocSize: function(){
		var doc = new Object;
		doc.x = document.documentElement.scrollWidth || document.body.scrollWidth;
		doc.y = document.documentElement.scrollHeight || document.body.scrollHeight;
		return doc;
	},

	getScreenSize: function() {
		var isOpera = (navigator.userAgent.toLowerCase().indexOf('opera')+1?1:0);
		var isSafari = (navigator.appVersion.toLowerCase().indexOf('safari')+1?1:0);
		var obj = new Object();
		if (!isSafari && !isOpera) {
			obj.x = document.documentElement.clientWidth || document.body.clientWidth || document.body.scrollWidth;
			obj.y = document.documentElement.clientHeight || document.body.clientHeight || document.body.scrollHeight;
		} else {
			obj.x = window.innerWidth;
			obj.y = window.innerHeight;
		}
		obj.mx = parseInt((obj.x)/2);
		obj.my = parseInt((obj.y)/2);
		return obj;
	},

	hop: function(d){
		var direction = d == 'up' ? 'minus' : 'plus';
		var pos = this.getScrollPos();
		var scr = this.getScreenSize();
		
		var goal = new Object;
		goal.x = pos.x;
		goal.y = direction == 'plus' ? pos.y + scr.y : pos.y - scr.y;

		var maxScroll = this.getMaxScroll();
		goal.x = pos.x;
		goal.y = goal.y > maxScroll.y ? maxScroll.y : goal.y;

		this.land(goal,direction);
		this.cancel();
	}
}
