window.scroll = {
	ScrollPanel:jsfw.Class({
		__constructor:function(el,o){
			this.o = $h.extend({
				keyEvent:true,  
				step:50	
			},o);
			this.dom = $(el);
			this.content = $.create('div',{className:'ScrollPanel'});
			while(this.dom.childNodes[0])
			{
				this.content.appendChild(this.dom.childNodes[0]);
			}
			this.dom.appendChild(this.content);
			this.dom.style.overflow = 'hidden';
			this.dom.style.position = 'relative';
			this.vScroll = new scroll.VerticalScroll(this);
			this.vScroll.addEvent('onscroll',$d(this,this.onVerticalScroll));
			if(!jsfw.browser.mozilla)
				jsfw.event.add(this.dom,'onmousewheel',$d(this,this.mouseWheel));
			else
				this.dom.addEventListener('DOMMouseScroll', $d(this,this.mouseWheel), false);
			jsfw.event.add(window,'onresize',$d(this,this.resize));
			if(this.o.keyEvent) jsfw.event.add(document,'onkeydown',$d(this,this.keydown));
		},
		getDom:function(){return this.dom;},
		onVerticalScroll:function(s,p)
		{
			this.content.style.top = (this.dom.clientHeight-this.content.clientHeight)*p+'px';
			this.callEvent(['onscroll','onvscroll'],[p]);
		},
		mouseWheel:function(s,e)
		{
			if((e.wheelDelta || -e.detail)>0) this.vScroll.up();
			else this.vScroll.down();
			return false;
		},
		resize:function()
		{
			this.vScroll.scrollInvalidate();
			this.vScroll.scrollHelperInvalidate();
		},
		keydown:function(s,e)
		{
			switch(e.keyCode)
			{
				case 38:this.vScroll.up();
				break;
				case 40:this.vScroll.down();
				break;
				case 36:this.vScroll.setScroll(0);
				break;
				case 35:this.vScroll.setScroll(1);
				break;
				case 32:
					if(e.shiftKey)
					{
						this.vScroll.up(this.vScroll.k);
						break;
					}
				case 34:
					this.vScroll.down(this.vScroll.k);
				break;
				case 33:this.vScroll.up(this.vScroll.k);
				break;
				default: return true;
			}
			
			return false;
		}
	},jsfw.Object), 
	VerticalScroll:jsfw.Class({
		__constructor:function(panel,o){
			this.panel = panel;
			this.o = $h.extend({
				step:50
			},o);
			
			this.dom = $.create('div',{className:'VerticalScroll',onmousedown:$d(this,this.clickScrol)},panel.getDom());
			this.helper = $.create('div',{className:'scrollHelper'},this.dom);
			this.bUp = $.create('div',{className:'button up',onclick:$d(this,function(){this.up();return false;}),onmousedown:$d(this,this.startAutoScroll,['up'])},this.dom);
			this.bScroll = $.create('div',{className:'scroll',onmousedown:$d(this,this.startMoveScroll)},this.dom);
			this.bDown = $.create('div',{className:'button down',onclick:$d(this,function(){this.down();return false;}),onmousedown:$d(this,this.startAutoScroll,['down'])},this.dom);
			
			this.dMoveScroll = $d(this,this.moveScroll);
			this.dStopMoveScroll = $d(this,this.stopMoveScroll);
			this.scrollInvalidate();
			this.scrollHelperInvalidate();
			this.setScroll(0);
		},
		getDom:function(){return this.dom;},
		scrollInvalidate:function()
		{
			this.dom.style.display='';
			this.k = (this.dom.clientHeight-this.bUp.clientHeight-this.bDown.clientHeight-1)/this.panel.content.clientHeight;
			this.step = this.o.step/this.dom.clientHeight;
			if(this.k>1) this.dom.style.display='none';
			var h = this.panel.dom.clientHeight*this.k;
			this.bScroll.style.height = h+'px';
		},
		scrollHelperInvalidate:function()
		{
			$.empty(this.helper);
			var con = this.panel.content;
			var k = this.k;
			var img_p=false;
			for(var i=0,len=con.childNodes.length;i<len;i++)
			{
				var el = con.childNodes[i];
				var type=false;
				var height = ((el.offsetHeight*k-1)||1)+'px';
				var tag = el.tagName && el.tagName.toLowerCase();
				switch(tag)
				{
					case 'a':
						var img = el.getElementsByTagName('img');
						if(img.length==0) break;
						el = img[0];
					case 'img': 
						if((img_p =$.getCss(el,'float'))!='none') break;
						type='img';
					break;
					case 'p': case 'ul':case 'ol':case 'dl':
						if(img_p=='left') type='img_paragraph';
						else if(img_p=='right') type='paragraph_img';
						else type='paragraph';
						img_p = false;
					break;
					case 'h1':case 'h2':case 'h3':case 'h4':case 'h5':case 'h6':case 'h7': type='head '+tag;
						height=undefined;
					break;
					case 'table':type='table';
					break;
				}
				if(type) $.create('div',{className:type,title:(el.textContent || el.innerText).substr(0,200),style:{height:height,top:(el.offsetTop*k+1)+'px'}},this.helper);
			}
		},
		setScroll:function(p)
		{
			if(p<0) p=0;
			if(p>1) p=1;
			this.bScroll.style.top = this.bUp.clientHeight+(this.dom.clientHeight-this.bUp.clientHeight-this.bDown.clientHeight - this.bScroll.clientHeight)*p+'px';
			this.callEvent('onscroll',[p]);
			
		},
		getScroll:function()
		{
			return (this.bScroll.offsetTop - this.bUp.clientHeight)/(this.dom.clientHeight-this.bUp.clientHeight-this.bDown.clientHeight - this.bScroll.clientHeight);
		},
		up:function(step)
		{
			this.setScroll(this.getScroll()-(step||this.step));
		},
		down:function(step)
		{
			this.setScroll(this.getScroll()+(step||this.step));
		},
		startMoveScroll:function(s,e)
		{
			this.p0 = e.clientY;
			this.oldTop = this.bScroll.offsetTop;
			this.dragScroll = true;
			jsfw.event.add(document.body,'onmousemove',this.dMoveScroll);
			jsfw.event.add(document.body,'onmouseup',this.dStopMoveScroll);
			jsfw.event.add(document.body,'onmouseout',this.dStopMoveScroll);
			return false;
		},
		stopMoveScroll:function(s,e)
		{
			if(e.type=='mouseout')
			{
				var p = e.relatedTarget;
				while ( p && p != s ) try { p = p.parentNode; } catch(e) { p = s; };
				if ( p == s ) return false;
			}
			jsfw.event.remove(document.body,'onmousemove',this.dMoveScroll);
			jsfw.event.remove(document.body,'onmouseup',this.dStopMoveScroll);
			jsfw.event.remove(document.body,'onmouseout',this.dStopMoveScroll);
			this.dragScroll = false;
			return false;
		},
		moveScroll:function(s,e)
		{
			var d = this.p0-e.clientY;
			this.oldTop = this.oldTop-d;
			this.bScroll.style.top = this.oldTop+'px';
			this.p0 = e.clientY;
			this.setScroll(this.getScroll());
			return false;
		},
		clickScrol:function(s,e)
		{
			if(!this.dragScroll)
			{
				var p = jsFW.element.offset(s);
				var layer = {x:e.clientX - p.left,y:e.clientY-p.top};
				var s = (layer.y - this.bUp.clientHeight)/(this.dom.clientHeight-this.bUp.clientHeight-this.bDown.clientHeight);
				if(s>=0 && s<=1) this.setScroll(s);
				return false;
			}
		},
		startAutoScroll:function(s,e,type)
		{
			var delayScroll;
			var delay = setTimeout($d(this,function()
			{
				var _this=this;
				(function(){
					_this[type]();
					delayScroll = setTimeout(arguments.callee,200);
				})();
			}),500);
			jsfw.event.one(document.body,'onmouseup',function()
			{
				if(delay) clearTimeout(delay);
				if(delayScroll) clearTimeout(delayScroll);
				return false;
			});
			return false;
		}
	},jsfw.Object)
};