var _scrollmenuDefault = {
	// 各初期値設定(''の中の数値を変更)
	// 移動幅
	movePx: '10',
	
	// スクロールが遅くなり始める位置
	slowPt: '40',
	
	// スクロールの速度(小さいほど速い)
	scrlSp: '15',
	
	// メニューが隠れ始めるまでのしきい値(小さいほど速い)
	hideSp: '100'
};



// 以下は変更不可
var _scrollmenuOn  = new Object();
var _scrollmenuOff = new Object();

function initMenu(elem, drc){
	var parent = elem.parentNode;
	
	if(parent.getElementsByTagName('ul')[0]){
		var getRandom = function(max){
			var char = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
			var s = 0;
			var e = char.length;
			var t = e - s;
			
			var id = new String();
			for(var i=0; i<max; i++){
				id += new String(char.charAt(Math.floor(Math.random() * (t + 1)) + s));
			}
			return id;
		};
		
		var sub = parent.getElementsByTagName('ul')[0];
		
		var subStyle = sub.currentStyle || document.defaultView.getComputedStyle(sub, null);
		var _position = sub.style.position || subStyle.position;
		var _display = sub.style.display || subStyle.display;
		
		if(!_position || _position=='relative') sub.style.position = 'absolute';
		if(_display=='none'){
			sub.style.top = '-9999px';
			sub.style.left = '-9999px';
			sub.style.display = 'block';
		}
		
		var id = getRandom(12);
		
		var _x, _y;
		switch(drc){
			case 'up':
				_x = parent.offsetLeft;
				_y = eval('-' + sub.offsetHeight);
			break;
			
			case 'down':
				_x = parent.offsetLeft;
				_y = parent.offsetTop + parent.offsetHeight;
			break;
			
			case 'left':
				_x = parent.offsetLeft - sub.offsetWidth;
				_y = parent.offsetTop;
			break;
			
			case 'right':
			default:
				_x = parent.offsetWidth;
				_y = parent.offsetTop;
			break;
		}
		
		addEvent(elem, 'mouseover', sub_view, sub, id, drc, _x, _y);
		addEvent(elem, 'mouseout', sub_view, sub, id, drc);
		addEvent(sub, 'mouseover', sub_view, sub, id, drc, _x, _y);
		addEvent(sub, 'mouseout', sub_view, sub, id, drc);
	}
}

function sub_view(){
	var setPosition = function(elem, top, left){
		if(arguments.length<2){
			top = '-9999';
			left = '-9999';
		}
		elem.style.top = top + 'px';
		elem.style.left = left + 'px';
	};
	
	var elemConf = function(elem, id, drc, top, left){
		this.elem = elem;
		this.drc = drc;
		this.posi_x = left;
		this.posi_y = top;
		this.id = id;
		
		switch(drc){
			case 'up':
				this._x = left;
				if(this.elem.offsetTop=='-9999'){
					this._y = 0;
					this.rect = 0;
				}
				else{
					this._y = this.elem.offsetTop;
					if(this.elem.style.clip.match(/\d+px/, 'i')) this.rect = this.elem.style.clip.match(/(\d+)px/, 'i')[1];
					else this.rect = 0;
					this.rect = eval(this.rect);
				}
			break;
			
			case 'down':
				this._x = left;
				if(this.elem.offsetTop=='-9999'){
					this._y = Math.round(top - this.elem.offsetHeight);
					this.rect = this.elem.offsetHeight;
				}
				else{
					this._y = this.elem.offsetTop;
					if(this.elem.style.clip.match(/\d+px/, 'i')) this.rect = this.elem.style.clip.match(/(\d+)px/, 'i')[1];
					else this.rect = this.elem.offsetHeight;
					this.rect = eval(this.rect);
				}
			break;
			
			case 'left':
				if(this.elem.offsetLeft=='-9999'){
					this._x = 0;
					this.rect = 0;
				}
				else{
					this._x = this.elem.offsetLeft;
					if(this.elem.style.clip.match(/\d+px/, 'i')) this.rect = this.elem.style.clip.match(/(\d+)px/, 'i')[1];
					else this.rect = 0;
					this.rect = eval(this.rect);
				}
				this._y = top;
			break;
			
			case 'right':
			default:
				if(this.elem.offsetLeft=='-9999'){
					this._x = Math.round(left - this.elem.offsetWidth);
					this.rect = this.elem.offsetWidth;
				}
				else{
					this._x = this.elem.offsetLeft;
					if(this.elem.style.clip.match(/\d+px/, 'i')) this.rect = this.elem.style.clip.match(/(\d+)px/, 'i')[1];
					else this.rect = this.elem.offsetWidth;
					this.rect = eval(this.rect);
				}
				this._y = top;
			break;
		}
		
		this.movePx = eval(_scrollmenuDefault.movePx);
		this.slowPt = eval(_scrollmenuDefault.slowPt);
	};
	
	elemConf.prototype.viewElem = function(){
		var exeRoop = function(args){
			if(typeof(_scrollmenuOn[args.id])!='undefined') clearTimeout(_scrollmenuOn[args.id]);
			
			var setRoop = null;
			var diff = 0;
			
			switch(args.drc){
				case 'up':
					diff = args.posi_y - args._y;
					if(diff>=eval('-' + args.slowPt)){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._y -= args.movePx;
					if(args._y<args.posi_y) args._y = args.posi_y;
					args.rect += args.movePx;
					if(args.rect>args.elem.offsetHeight) args.rect = args.elem.offsetHeight;
					args.elem.style.clip = 'rect(auto, auto, ' + args.rect + 'px, auto)';
					if(diff<-1) setRoop = true;
				break;
				
				case 'down':
					diff = args.posi_y - args._y;
					if(diff<=args.slowPt){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._y += args.movePx;
					if(args._y>args.posi_y) args._y = args.posi_y;
					args.rect -= args.movePx;
					if(args.rect<0) args.rect = 0;
					args.elem.style.clip = 'rect(' + args.rect + 'px, auto, auto, auto)';
					if(diff>1) setRoop = true;
				break;
				
				case 'left':
					diff = args.posi_x - args._x;
					if(diff>=eval('-' + args.slowPt)){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._x -= args.movePx;
					if(args._x<args.posi_x) args._x = args.posi_x;
					args.rect += args.movePx;
					if(args.rect>args.elem.offsetWidth) args.rect = args.elem.offsetWidth;
					args.elem.style.clip = 'rect(auto, ' + args.rect + 'px, auto, auto)';
					if(diff<-1) setRoop = true;
				break;
				
				case 'right':
				default:
					diff = args.posi_x - args._x;
					if(diff<=args.slowPt){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._x += args.movePx;
					if(args._x>args.posi_x) args._x = args.posi_x;
					args.rect -= args.movePx;
					if(args.rect<0) args.rect = 0;
					args.elem.style.clip = 'rect(auto, auto, auto, ' + args.rect + 'px)';
					if(diff>1) setRoop = true;
				break;
			}
			
			setPosition(args.elem, args._y, args._x);
			if(setRoop) _scrollmenuOn[args.id] = setTimeout(function(){ exeRoop(args); }, eval(_scrollmenuDefault.scrlSp));
		};
		
		exeRoop(this);
	};
	
	elemConf.prototype.hideElem = function(){
		var exeRoop = function(args){
			if(typeof(_scrollmenuOff[args.id])!='undefined') clearTimeout(_scrollmenuOff[args.id]);
			
			var setRoop = null;
			var diff = 0;
			
			switch(args.drc){
				case 'up':
					diff = args._y - args.posi_y;
					if(diff>=eval('-' + args.slowPt)){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._y += args.movePx;
					if(args._y>args.posi_y) args._y = args.posi_y;
					args.rect -= args.movePx;
					if(args.rect<0) args.rect = 0;
					args.elem.style.clip = 'rect(auto, auto, ' + args.rect + 'px, auto)';
					if(diff<-1) setRoop = true;
					else args._x = args._y = '-9999';
				break;
				
				case 'down':
					diff = args._y - args.posi_y;
					if(diff<=args.slowPt){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._y -= args.movePx;
					if(args._y<args.posi_y) args._y = args.posi_y;
					args.rect += args.movePx;
					if(args.rect>args.elem.offsetHeight) args.rect = args.elem.offsetHeight;
					args.elem.style.clip = 'rect(' + args.rect + 'px, auto, auto, auto)';
					if(diff>1) setRoop = true;
					else args._x = args._y = '-9999';
				break;
				
				case 'left':
					diff = args._x - args.posi_x;
					if(diff>=eval('-' + args.slowPt)){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._x += args.movePx;
					if(args._x>args.posi_x) args._x = args.posi_x;
					args.rect -= args.movePx;
					if(args.rect<0) args.rect = 0;
					args.elem.style.clip = 'rect(auto, ' + args.rect + 'px, auto, auto)';
					if(diff<-1) setRoop = true;
					else args._x = args._y = '-9999';
				break;
				
				case 'right':
				default:
					diff = args._x - args.posi_x;
					if(diff<=args.slowPt){
						args.slowPt = Math.ceil(args.slowPt / 2);
						args.movePx = Math.ceil(args.movePx / 2);
					}
					args._x -= args.movePx;
					if(args._x<args.posi_x) args._x = args.posi_x;
					args.rect += args.movePx;
					if(args.rect>args.elem.offsetWidth) args.rect = args.elem.offsetWidth;
					args.elem.style.clip = 'rect(auto, auto, auto, ' + args.rect + 'px)';
					if(diff>1) setRoop = true;
					else args._x = args._y = '-9999';
				break;
			}
			
			setPosition(args.elem, args._y, args._x);
			if(setRoop) _scrollmenuOff[args.id] = setTimeout(function(){ exeRoop(args); }, eval(_scrollmenuDefault.scrlSp));
		};
		
		exeRoop(this);
	};
	
	var elem = arguments[0];
	var id   = arguments[1];
	var drc  = arguments[2];
	var leng = arguments.length;
	
	if(leng<3){
		return false;
	}
	else if(leng==3){
		if(typeof(_scrollmenuOn[id])!='undefined') clearTimeout(_scrollmenuOn[id]);
		
		var parent = elem.parentNode;
		var top, left;
		switch(drc){
			case 'up':
				top = 0;
				left = parent.offsetLeft;
			break;
			
			case 'down':
				top = Math.round(parent.offsetHeight - elem.offsetHeight);
				left = parent.offsetLeft;
			break;
			
			case 'left':
				top = parent.offsetTop;
				left = 0;
			break;
			
			case 'right':
			default:
				top = parent.offsetTop;
				left = Math.round(parent.offsetWidth - elem.offsetWidth);
			break;
			
		}
		
		if((drc=='up' && elem.offsetTop<top) ||
		   (drc=='down' && elem.offsetTop>top) ||
		   (drc=='left' && elem.offsetLeft<left) ||
		   (drc=='right' && elem.offsetLeft>left)){
			var menu = new elemConf(elem, id, drc, top, left);
			_scrollmenuOff[id] = setTimeout(function(){ menu.hideElem() }, eval(_scrollmenuDefault.hideSp));
		}
	}
	else if(leng==5){
		if(typeof(_scrollmenuOff[id])!='undefined') clearTimeout(_scrollmenuOff[id]);
		
		var top  = arguments[4];
		var left = arguments[3];
		
		if((drc=='up' && (elem.offsetTop>top || elem.offsetTop<0)) ||
		   (drc=='down' && elem.offsetTop<top) ||
		   (drc=='left' && (elem.offsetLeft>left || elem.offsetLeft<0)) ||
		   (drc=='right' && elem.offsetLeft<left)){
			var menu = new elemConf(elem, id, drc, top, left);
			menu.viewElem();
		}
	}
	
	return false;
}

