var ScrollBox = function(o, p){
	var o = o ? o : {}, p = p ? p : {};
	this.o = {
		'box'		: o.box		? document.getElementById(o.box)		: null,
		'list'		: o.list	? document.getElementById(o.list)		: null,
		'handle1'	: o.handle1 ? document.getElementById(o.handle1)	: null,
		'handle2'	: o.handle2 ? document.getElementById(o.handle2)	: null
	}
	for(var key in this.o){ if(!this.o[key]){ return; } }
	this.p = {
		'box_width'		: p.box_width	? p.box_width	: 200,
		'box_height'	: p.box_height	? p.box_height	: 200,
		'item_width'	: p.item_width	? p.item_width	: 'auto',
		'item_height'	: p.item_height ? p.item_height : 'auto',
		'item_margin' 	: p.item_margin ? p.item_margin : 0,
		'move_offset'	: p.move_offset ? p.move_offset : 5,
		'move_mode' 	: p.move_mode	? p.move_mode	: 'fb',
		'move_type'		: p.move_type	? p.move_type	: 'smarty',
		'move_every'	: p.move_every	? p.move_every	: 1
	}
	this.width_visual = this.p.box_width;
	this.height_visual = this.p.box_height;
	this.width_actual = 0;
	this.height_actual = 0;
	this.timer = null;
	this.widthreset = false;
	this.heightreset = false;
	this.rolling = false;
	this.items = [];
	this.direction = '';
	this.from = 0;
	this.to = 0;
	this.current = 0;
	
	this.build();
	return this;
}
ScrollBox.prototype = {
	
	item: function(index, o){
		return {
			'index' : index,
			'ele': o
		}	
	},
	
	roll: function(direction, num){
		//alert(direction + ":" + this.canRoll(direction))
		if(this.canRoll(direction)){
			this.rolling  = true;
			var distance = 0;
			var box = this.o.box;
			var list = this.o.list;
			var mode = this.getRollMode();
			var every = num ? num :  this.p.move_every;
			var length = this.items.length;
			var margin = this.p.item_margin;

			switch(direction){
				case 'f': //前
					this.to = (this.from + every > length - 1 ) ? (length - 1) : (this.from + every);
					for(var i=this.from; i<this.to; i++){
						distance += (this.items[i].ele.offsetWidth + margin);
					}
					this.from = (this.from + every > length - 1 ) ?  this.to - every : this.to;
					
				break;
				
				case 'b': //后
					this.to = (this.from - every < 0) ? 0 : (this.from - every);
					for(var i=this.to; i<this.from; i++){
						distance += (this.items[i].ele.offsetWidth + margin);
					}
					this.from = (this.from - every < 0 ) ?  0 : this.to;
				break;				
				
				case 'd': //下
					this.to = (this.from + every > length - 1 ) ? (length - 1) : (this.from + every);
					for(var i=this.from; i<this.to; i++){
						distance += (this.items[i].ele.offsetHeight + margin);
					}
					this.from = (this.from + every > length - 1 ) ?  this.to - every : this.to;
				break;				
				
				case 'u': //上
					this.to = (this.from - every < 0) ? 0 : (this.from - every);
					for(var i=this.to; i<this.from; i++){
						distance += (this.items[i].ele.offsetHeight + margin);
					}
					this.from = (this.from - every < 0 ) ?  0 : this.to;
				break;
			}
			
			//alert('from' + this.from + '; to: ' + this.to + '; distance:' + distance)

			//if(this.from != this.to){
				this.direction = direction;
				var offset = this.p.move_offset; if(offset < 1){offset = 1;}
				var _this = this;
				var step = 0;
				var count = 0;
				this.timer = setInterval(function(){ 
											if(_this.p.move_type == 'smarty'){ step += offset; }
											else{ step += distance; }
											count += step;
											if(count > distance){ //清除溢出
												var flow = count - distance;
												step -= flow;
											}
											switch(direction){
												case 'u':
													box.scrollTop -= step;
												break;
												case 'd':
													box.scrollTop += step;
												break;
												case 'b':
													box.scrollLeft -= step;
												break;
												case 'f':
													box.scrollLeft += step;
												break;
											}
											if(count >= distance ) { _this.stopRoll(); }
										}, 25);
			//}
		}
	},
	
	rollToView: function(index){

		if(!typeof(index) == 'undefined'){ return; }
		var index = Math.abs(parseInt(index, 10));
		if(index > this.items.length - 1){ index = this.items.length - 1; }
		var num = index - this.from;
		
		if(num == 0){ return; }
		else{
			var mode = this.getRollMode();
			var direction = '';
			if(num > 0){ if(mode == 'ud'){ direction='d'; } else{ direction='f'; } }	
			else{ if(mode == 'ud'){ direction='u'; } else{ direction='b'; } }	
			num = Math.abs(num);
			//alert('roll(\'' + direction + '\',' + num +')' + 'from:' + this.from + ',to' + index);
			this.roll(direction, num);
			
		}
		
	},
	
	checkRoll: function(){
		var handle1 = this.o.handle1;
		var handle2 = this.o.handle2;
		var mode = this.getRollMode();
		if(mode == 'ud'){
			if(this.canRoll('u')){ handle1.style.visibility = 'visible'; }else{ handle1.style.visibility = 'hidden'; }
			if(this.canRoll('d')){ handle2.style.visibility = 'visible'; }else{ handle2.style.visibility = 'hidden'; }
		}
		else if(mode == 'fb'){	
			if(this.canRoll('b')){ handle1.style.visibility = 'visible'; }else{ handle1.style.visibility = 'hidden'; }
			if(this.canRoll('f')){ handle2.style.visibility = 'visible'; }else{ handle2.style.visibility = 'hidden'; }
		}
	},
	
	canRoll: function(direction){
		if(this.rolling || this.timer){ return false; }
		var box = this.o.box;
		var margin = this.p.item_margin; 
		switch(direction){
			case 'u':
				if(box.scrollTop <= 0){
					return false;	
				}
			break;	
			case 'd':
				if(box.scrollTop + this.height_visual >= this.height_actual){
					return false;	
				}
			break;	
			case 'b':
				if(box.scrollLeft <= 0){
					return false;	
				}
			break;	
			case 'f':
				if(box.scrollLeft + this.width_visual >= this.width_actual){
					return false;	
				}
			break;	
		}
		return true;
	},
	
	getRollMode: function(){
		return this.p.move_mode;
	},
	
	stopRoll: function(direction){
		clearInterval(this.timer);
		this.timer = null;
		this.rolling = false;
		//this.from = this.to;
		
		this.checkRoll();
	},
	
	update: function(){
		
	},
	
	bind: function(){
		var _this = this;
		var mode = this.getRollMode();		
		var box = this.o.box;
		var list = this.o.list;
		var every = this.p.item_every;		
		var handle1 = this.o.handle1;
		var handle2 = this.o.handle2;
		//handle事件
		if(mode == 'ud'){
			handle1.onclick = function(){ _this.roll('u') };
			handle2.onclick = function(){ _this.roll('d') };
		}
		else if(mode = 'fb'){
			handle1.onclick = function(){ _this.roll('b') };
			handle2.onclick = function(){ _this.roll('f') };
		}
		handle1.style.cursor = 'pointer';
		handle2.style.cursor = 'pointer';
		
		function cancleBubble(e){ 
			if(e.preventDefault) {    
				e.preventDefault();
				e.stopPropagation();
			}else {    
				e.cancelBubble = true;    
				e.returnValue = false;    
			} 
		}
		
		box.onmouseover = function(){ this.focus(); }
		box.onmouseout = function(){ this.blur(); }
		
		//滚轮支持
		box.onmousewheel = function(e){
			var e = e || event;	
			cancleBubble(e);
			if(e.wheelDelta/120 > 0){ if(mode == 'ud') { _this.roll('u', every); } else if(mode == 'fb') { _this.roll('b', every); } } 
			else{ if(mode == 'ud') { _this.roll('d', every); } else if(mode == 'fb') { _this.roll('f', every); } }
		}
		if(!document.all){
		box.addEventListener('DOMMouseScroll', 
							function(e){
								var e = e || event;
								cancleBubble(e);
								if(e.detail/120 > 0){ if(mode == 'ud') { _this.roll('d', every); } else if(mode == 'fb') { _this.roll('f', every); } } 
								else{ if(mode == 'ud') { _this.roll('u', every); } else if(mode == 'fb') { _this.roll('b', every); } }
							},
							false);
		}
		
		//键盘支持
		box.onkeydown = function(e){
			var e = e || event;	
			cancleBubble(e);
			var code = e.keyCode ? e.keyCode : e.which;			
			if(code == 38){ if(mode == 'ud') { _this.roll('u', every); } }
			if(code == 40){ if(mode == 'ud') { _this.roll('d', every); } }
			if(code == 37){ if(mode == 'fb') { _this.roll('b', every); } }
			if(code == 39){ if(mode == 'fb') { _this.roll('f', every); } }
			if(code == 9){				
				if(e.shiftKey){
					if(mode == 'ud'){ _this.roll('u', 1); }
					if(mode == 'fb'){ _this.roll('b', 1); }
				}else{
					if(mode == 'ud'){ _this.roll('d', 1); }
					if(mode == 'fb'){ _this.roll('f', 1); }
				}
			}
			return false;
		}
	},
	
	build: function(){
		var list = this.o.list, 
			box = this.o.box,
			items = this.o.list.childNodes;
			mode = this.getRollMode(),
			margin = this.p.item_margin;
		for(var i=0, len=items.length; i<len; i++){
			var item = items[i];
			if(item.nodeType == 1){ this.items.push(new this.item(i, item)); } //true elment
		}
		//reset element
		while(list.hasChildNodes()){
			list.firstChild.parentNode.removeChild(list.firstChild);
		}
		if(!document.all){
			box.tabIndex = 0;
			box.style.outline = 'none';
		}
		box.style.width		= this.p.box_width + 'px'; 
		box.style.height	= this.p.box_height + 'px';
		box.style.overflow	= 'hidden';		
		list.style.width	= this.p.box_width + 'px';
		list.style.height	= this.p.box_height + 'px';

		var w = 0, h = 0;
		for(var i=0, len=this.items.length; i<len; i++){
			var item = this.items[i];
			list.appendChild(item.ele);
			if(mode == 'fb'){
				if(document.all){
					item.ele.style.styleFloat = 'left';
				}else{
					item.ele.style.cssFloat = 'left';	
				}
			}
			var item_width  = (this.p.item_width == 'auto') ? item.ele.offsetWidth : this.p.item_width;
			var item_height = (this.p.item_height == 'auto') ? item.ele.offsetHeight : this.p.item_height;
			item.ele.style.width = item_width + 'px';
			item.ele.style.height = item_height + 'px';
			item.ele.style.overflow = 'hidden';			
			if(mode == 'fb'){
				if(i != len -1){
					w += (item_width + margin);
					item.ele.style.marginRight = margin + 'px';
				}else{
					w += item_width;
					item.ele.style.marginRight = 0 + 'px';
				}
			}
			else if(mode == 'ud'){
				if(i != len -1){
					h += (item_height + margin);
					item.ele.style.marginBottom = margin + 'px';
				}else{
					h += item_height;
					item.ele.style.marginBottom = 0 + 'px';
				}
			}	
		}
		if (mode == 'fb'){ list.style.width = w + 'px'; }
		else if(mode == 'ud'){ list.style.height = h + 'px'; }
		
		this.width_actual	= list.scrollWidth;
		this.height_actual	= list.scrollHeight;
		/*if(document.all){ 
			var s = 'MSIE', i= -1, u = navigator.userAgent;
			if((i = u.indexOf(s)) >= 0){
				var v = parseFloat(u.substr(i + s.length));
				if(v == 6){this.width_actual -= margin;}
			}
		}*/
		this.bind();
		this.checkRoll();
	}
}

